1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 2f1a0c4aaSCatalin Marinas/* 3f1a0c4aaSCatalin Marinas * Cache maintenance 4f1a0c4aaSCatalin Marinas * 5f1a0c4aaSCatalin Marinas * Copyright (C) 2001 Deep Blue Solutions Ltd. 6f1a0c4aaSCatalin Marinas * Copyright (C) 2012 ARM Ltd. 7f1a0c4aaSCatalin Marinas */ 8f1a0c4aaSCatalin Marinas 9a2d25a53SVladimir Murzin#include <linux/errno.h> 10f1a0c4aaSCatalin Marinas#include <linux/linkage.h> 11f1a0c4aaSCatalin Marinas#include <linux/init.h> 12f1a0c4aaSCatalin Marinas#include <asm/assembler.h> 13301bcfacSAndre Przywara#include <asm/cpufeature.h> 148d883b23SMarc Zyngier#include <asm/alternative.h> 15b4b8664dSAl Viro#include <asm/asm-uaccess.h> 16f1a0c4aaSCatalin Marinas 17f1a0c4aaSCatalin Marinas/* 18fade9c2cSFuad Tabba * caches_clean_inval_pou_macro(start,end) [fixup] 19116b7f55SFuad Tabba * 20116b7f55SFuad Tabba * Ensure that the I and D caches are coherent within specified region. 21116b7f55SFuad Tabba * This is typically used when code has been written to a memory region, 22116b7f55SFuad Tabba * and will be executed. 23116b7f55SFuad Tabba * 24116b7f55SFuad Tabba * - start - virtual start address of region 25116b7f55SFuad Tabba * - end - virtual end address of region 26116b7f55SFuad Tabba * - fixup - optional label to branch to on user fault 27116b7f55SFuad Tabba */ 28fade9c2cSFuad Tabba.macro caches_clean_inval_pou_macro, fixup 29116b7f55SFuad Tabbaalternative_if ARM64_HAS_CACHE_IDC 30116b7f55SFuad Tabba dsb ishst 31116b7f55SFuad Tabba b .Ldc_skip_\@ 32116b7f55SFuad Tabbaalternative_else_nop_endif 33116b7f55SFuad Tabba mov x2, x0 34163d3f80SFuad Tabba mov x3, x1 35116b7f55SFuad Tabba dcache_by_line_op cvau, ish, x2, x3, x4, x5, \fixup 36116b7f55SFuad Tabba.Ldc_skip_\@: 37116b7f55SFuad Tabbaalternative_if ARM64_HAS_CACHE_DIC 38116b7f55SFuad Tabba isb 39116b7f55SFuad Tabba b .Lic_skip_\@ 40116b7f55SFuad Tabbaalternative_else_nop_endif 41116b7f55SFuad Tabba invalidate_icache_by_line x0, x1, x2, x3, \fixup 42116b7f55SFuad Tabba.Lic_skip_\@: 43116b7f55SFuad Tabba.endm 44116b7f55SFuad Tabba 45116b7f55SFuad Tabba/* 46fade9c2cSFuad Tabba * caches_clean_inval_pou(start,end) 47f1a0c4aaSCatalin Marinas * 48f1a0c4aaSCatalin Marinas * Ensure that the I and D caches are coherent within specified region. 49f1a0c4aaSCatalin Marinas * This is typically used when code has been written to a memory region, 50f1a0c4aaSCatalin Marinas * and will be executed. 51f1a0c4aaSCatalin Marinas * 52f1a0c4aaSCatalin Marinas * - start - virtual start address of region 53f1a0c4aaSCatalin Marinas * - end - virtual end address of region 54f1a0c4aaSCatalin Marinas */ 55fade9c2cSFuad TabbaSYM_FUNC_START(caches_clean_inval_pou) 56fade9c2cSFuad Tabba caches_clean_inval_pou_macro 57116b7f55SFuad Tabba ret 58fade9c2cSFuad TabbaSYM_FUNC_END(caches_clean_inval_pou) 59*61786170SArd BiesheuvelSYM_FUNC_ALIAS(__pi_caches_clean_inval_pou, caches_clean_inval_pou) 60f1a0c4aaSCatalin Marinas 61f1a0c4aaSCatalin Marinas/* 62fade9c2cSFuad Tabba * caches_clean_inval_user_pou(start,end) 63f1a0c4aaSCatalin Marinas * 64f1a0c4aaSCatalin Marinas * Ensure that the I and D caches are coherent within specified region. 65f1a0c4aaSCatalin Marinas * This is typically used when code has been written to a memory region, 66f1a0c4aaSCatalin Marinas * and will be executed. 67f1a0c4aaSCatalin Marinas * 68f1a0c4aaSCatalin Marinas * - start - virtual start address of region 69f1a0c4aaSCatalin Marinas * - end - virtual end address of region 70f1a0c4aaSCatalin Marinas */ 71fade9c2cSFuad TabbaSYM_FUNC_START(caches_clean_inval_user_pou) 72448fadc8SChristoffer Dall uaccess_ttbr0_enable x2, x3, x4 73f1a0c4aaSCatalin Marinas 74fade9c2cSFuad Tabba caches_clean_inval_pou_macro 2f 75116b7f55SFuad Tabba mov x0, xzr 7639bc88e5SCatalin Marinas1: 770482b505SChristoffer Dall uaccess_ttbr0_disable x1, x2 78a2d25a53SVladimir Murzin ret 79116b7f55SFuad Tabba2: 80a2d25a53SVladimir Murzin mov x0, #-EFAULT 8139bc88e5SCatalin Marinas b 1b 82fade9c2cSFuad TabbaSYM_FUNC_END(caches_clean_inval_user_pou) 83f1a0c4aaSCatalin Marinas 84f1a0c4aaSCatalin Marinas/* 85fade9c2cSFuad Tabba * icache_inval_pou(start,end) 864fee9473SMarc Zyngier * 874fee9473SMarc Zyngier * Ensure that the I cache is invalid within specified region. 884fee9473SMarc Zyngier * 894fee9473SMarc Zyngier * - start - virtual start address of region 904fee9473SMarc Zyngier * - end - virtual end address of region 914fee9473SMarc Zyngier */ 92fade9c2cSFuad TabbaSYM_FUNC_START(icache_inval_pou) 936ae4b6e0SShanker Donthinenialternative_if ARM64_HAS_CACHE_DIC 946ae4b6e0SShanker Donthineni isb 956ae4b6e0SShanker Donthineni ret 966ae4b6e0SShanker Donthinenialternative_else_nop_endif 976ae4b6e0SShanker Donthineni 987908072dSFuad Tabba invalidate_icache_by_line x0, x1, x2, x3 994fee9473SMarc Zyngier ret 100fade9c2cSFuad TabbaSYM_FUNC_END(icache_inval_pou) 1014fee9473SMarc Zyngier 1024fee9473SMarc Zyngier/* 103fade9c2cSFuad Tabba * dcache_clean_inval_poc(start, end) 104f1a0c4aaSCatalin Marinas * 105814b1860SFuad Tabba * Ensure that any D-cache lines for the interval [start, end) 1060a28714cSAshok Kumar * are cleaned and invalidated to the PoC. 107f1a0c4aaSCatalin Marinas * 108814b1860SFuad Tabba * - start - virtual start address of region 109814b1860SFuad Tabba * - end - virtual end address of region 110f1a0c4aaSCatalin Marinas */ 1110f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_clean_inval_poc) 1120a28714cSAshok Kumar dcache_by_line_op civac, sy, x0, x1, x2, x3 113f1a0c4aaSCatalin Marinas ret 1140f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_clean_inval_poc) 1150f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_clean_inval_poc, __pi_dcache_clean_inval_poc) 1167363590dSCatalin Marinas 1177363590dSCatalin Marinas/* 118fade9c2cSFuad Tabba * dcache_clean_pou(start, end) 1190a28714cSAshok Kumar * 120406d7d4eSFuad Tabba * Ensure that any D-cache lines for the interval [start, end) 1210a28714cSAshok Kumar * are cleaned to the PoU. 1220a28714cSAshok Kumar * 123406d7d4eSFuad Tabba * - start - virtual start address of region 124406d7d4eSFuad Tabba * - end - virtual end address of region 1250a28714cSAshok Kumar */ 126fade9c2cSFuad TabbaSYM_FUNC_START(dcache_clean_pou) 1276ae4b6e0SShanker Donthinenialternative_if ARM64_HAS_CACHE_IDC 1286ae4b6e0SShanker Donthineni dsb ishst 1296ae4b6e0SShanker Donthineni ret 1306ae4b6e0SShanker Donthinenialternative_else_nop_endif 1310a28714cSAshok Kumar dcache_by_line_op cvau, ish, x0, x1, x2, x3 1320a28714cSAshok Kumar ret 133fade9c2cSFuad TabbaSYM_FUNC_END(dcache_clean_pou) 1340a28714cSAshok Kumar 1350a28714cSAshok Kumar/* 136fade9c2cSFuad Tabba * dcache_inval_poc(start, end) 137d46befefSRobin Murphy * 138e3974adbSFuad Tabba * Ensure that any D-cache lines for the interval [start, end) 139d46befefSRobin Murphy * are invalidated. Any partial lines at the ends of the interval are 140d46befefSRobin Murphy * also cleaned to PoC to prevent data loss. 141d46befefSRobin Murphy * 142e3974adbSFuad Tabba * - start - kernel start address of region 143e3974adbSFuad Tabba * - end - kernel end address of region 144d46befefSRobin Murphy */ 1450f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_inval_poc) 1467363590dSCatalin Marinas dcache_line_size x2, x3 1477363590dSCatalin Marinas sub x3, x2, #1 148ebf81a93SCatalin Marinas tst x1, x3 // end cache line aligned? 1497363590dSCatalin Marinas bic x1, x1, x3 150ebf81a93SCatalin Marinas b.eq 1f 151ebf81a93SCatalin Marinas dc civac, x1 // clean & invalidate D / U line 152ebf81a93SCatalin Marinas1: tst x0, x3 // start cache line aligned? 153ebf81a93SCatalin Marinas bic x0, x0, x3 154ebf81a93SCatalin Marinas b.eq 2f 155ebf81a93SCatalin Marinas dc civac, x0 // clean & invalidate D / U line 156ebf81a93SCatalin Marinas b 3f 157ebf81a93SCatalin Marinas2: dc ivac, x0 // invalidate D / U line 158ebf81a93SCatalin Marinas3: add x0, x0, x2 1597363590dSCatalin Marinas cmp x0, x1 160ebf81a93SCatalin Marinas b.lo 2b 1617363590dSCatalin Marinas dsb sy 1627363590dSCatalin Marinas ret 1630f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_inval_poc) 1640f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_inval_poc, __pi_dcache_inval_poc) 1657363590dSCatalin Marinas 1667363590dSCatalin Marinas/* 167fade9c2cSFuad Tabba * dcache_clean_poc(start, end) 168d34fdb70SKwangwoo Lee * 1691f42faf1SFuad Tabba * Ensure that any D-cache lines for the interval [start, end) 170d34fdb70SKwangwoo Lee * are cleaned to the PoC. 171d34fdb70SKwangwoo Lee * 1721f42faf1SFuad Tabba * - start - virtual start address of region 1731f42faf1SFuad Tabba * - end - virtual end address of region 1747363590dSCatalin Marinas */ 1750f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_clean_poc) 176d34fdb70SKwangwoo Lee dcache_by_line_op cvac, sy, x0, x1, x2, x3 1777363590dSCatalin Marinas ret 1780f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_clean_poc) 1790f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_clean_poc, __pi_dcache_clean_poc) 180d34fdb70SKwangwoo Lee 181d34fdb70SKwangwoo Lee/* 182fade9c2cSFuad Tabba * dcache_clean_pop(start, end) 183d50e071fSRobin Murphy * 184f749448eSFuad Tabba * Ensure that any D-cache lines for the interval [start, end) 185d50e071fSRobin Murphy * are cleaned to the PoP. 186d50e071fSRobin Murphy * 187f749448eSFuad Tabba * - start - virtual start address of region 188f749448eSFuad Tabba * - end - virtual end address of region 189d50e071fSRobin Murphy */ 1900f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_clean_pop) 19133309ecdSWill Deacon alternative_if_not ARM64_HAS_DCPOP 192fade9c2cSFuad Tabba b dcache_clean_poc 19333309ecdSWill Deacon alternative_else_nop_endif 194d50e071fSRobin Murphy dcache_by_line_op cvap, sy, x0, x1, x2, x3 195d50e071fSRobin Murphy ret 1960f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_clean_pop) 1970f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_clean_pop, __pi_dcache_clean_pop) 198