/* SPDX-License-Identifier: GPL-2.0-only */1/*2* Cache maintenance3*4* Copyright (C) 2001 Deep Blue Solutions Ltd.5* Copyright (C) 2012 ARM Ltd.6*/78#include <linux/errno.h>9#include <linux/linkage.h>10#include <linux/init.h>11#include <asm/assembler.h>12#include <asm/cpufeature.h>13#include <asm/alternative.h>14#include <asm/asm-uaccess.h>1516/*17* caches_clean_inval_pou_macro(start,end) [fixup]18*19* Ensure that the I and D caches are coherent within specified region.20* This is typically used when code has been written to a memory region,21* and will be executed.22*23* - start - virtual start address of region24* - end - virtual end address of region25* - fixup - optional label to branch to on user fault26*/27.macro caches_clean_inval_pou_macro, fixup28alternative_if ARM64_HAS_CACHE_IDC29dsb ishst30b .Ldc_skip_\@31alternative_else_nop_endif32mov x2, x033mov x3, x134dcache_by_line_op cvau, ish, x2, x3, x4, x5, \fixup35.Ldc_skip_\@:36alternative_if ARM64_HAS_CACHE_DIC37isb38b .Lic_skip_\@39alternative_else_nop_endif40invalidate_icache_by_line x0, x1, x2, x3, \fixup41.Lic_skip_\@:42.endm4344/*45* caches_clean_inval_pou(start,end)46*47* Ensure that the I and D caches are coherent within specified region.48* This is typically used when code has been written to a memory region,49* and will be executed.50*51* - start - virtual start address of region52* - end - virtual end address of region53*/54SYM_FUNC_START(caches_clean_inval_pou)55caches_clean_inval_pou_macro56ret57SYM_FUNC_END(caches_clean_inval_pou)58SYM_FUNC_ALIAS(__pi_caches_clean_inval_pou, caches_clean_inval_pou)5960/*61* caches_clean_inval_user_pou(start,end)62*63* Ensure that the I and D caches are coherent within specified region.64* This is typically used when code has been written to a memory region,65* and will be executed.66*67* - start - virtual start address of region68* - end - virtual end address of region69*/70SYM_FUNC_START(caches_clean_inval_user_pou)71uaccess_ttbr0_enable x2, x3, x47273caches_clean_inval_pou_macro 2f74mov x0, xzr751:76uaccess_ttbr0_disable x1, x277ret782:79mov x0, #-EFAULT80b 1b81SYM_FUNC_END(caches_clean_inval_user_pou)8283/*84* icache_inval_pou(start,end)85*86* Ensure that the I cache is invalid within specified region.87*88* - start - virtual start address of region89* - end - virtual end address of region90*/91SYM_FUNC_START(icache_inval_pou)92alternative_if ARM64_HAS_CACHE_DIC93isb94ret95alternative_else_nop_endif9697invalidate_icache_by_line x0, x1, x2, x398ret99SYM_FUNC_END(icache_inval_pou)100101/*102* dcache_clean_inval_poc(start, end)103*104* Ensure that any D-cache lines for the interval [start, end)105* are cleaned and invalidated to the PoC.106*107* - start - virtual start address of region108* - end - virtual end address of region109*/110SYM_FUNC_START(__pi_dcache_clean_inval_poc)111dcache_by_line_op civac, sy, x0, x1, x2, x3112ret113SYM_FUNC_END(__pi_dcache_clean_inval_poc)114SYM_FUNC_ALIAS(dcache_clean_inval_poc, __pi_dcache_clean_inval_poc)115116/*117* dcache_clean_pou(start, end)118*119* Ensure that any D-cache lines for the interval [start, end)120* are cleaned to the PoU.121*122* - start - virtual start address of region123* - end - virtual end address of region124*/125SYM_FUNC_START(dcache_clean_pou)126alternative_if ARM64_HAS_CACHE_IDC127dsb ishst128ret129alternative_else_nop_endif130dcache_by_line_op cvau, ish, x0, x1, x2, x3131ret132SYM_FUNC_END(dcache_clean_pou)133134/*135* dcache_inval_poc(start, end)136*137* Ensure that any D-cache lines for the interval [start, end)138* are invalidated. Any partial lines at the ends of the interval are139* also cleaned to PoC to prevent data loss.140*141* - start - kernel start address of region142* - end - kernel end address of region143*/144SYM_FUNC_START(__pi_dcache_inval_poc)145dcache_line_size x2, x3146sub x3, x2, #1147tst x1, x3 // end cache line aligned?148bic x1, x1, x3149b.eq 1f150dc civac, x1 // clean & invalidate D / U line1511: tst x0, x3 // start cache line aligned?152bic x0, x0, x3153b.eq 2f154dc civac, x0 // clean & invalidate D / U line155b 3f1562: dc ivac, x0 // invalidate D / U line1573: add x0, x0, x2158cmp x0, x1159b.lo 2b160dsb sy161ret162SYM_FUNC_END(__pi_dcache_inval_poc)163SYM_FUNC_ALIAS(dcache_inval_poc, __pi_dcache_inval_poc)164165/*166* dcache_clean_poc(start, end)167*168* Ensure that any D-cache lines for the interval [start, end)169* are cleaned to the PoC.170*171* - start - virtual start address of region172* - end - virtual end address of region173*/174SYM_FUNC_START(__pi_dcache_clean_poc)175dcache_by_line_op cvac, sy, x0, x1, x2, x3176ret177SYM_FUNC_END(__pi_dcache_clean_poc)178SYM_FUNC_ALIAS(dcache_clean_poc, __pi_dcache_clean_poc)179180/*181* dcache_clean_pop(start, end)182*183* Ensure that any D-cache lines for the interval [start, end)184* are cleaned to the PoP.185*186* - start - virtual start address of region187* - end - virtual end address of region188*/189SYM_FUNC_START(__pi_dcache_clean_pop)190alternative_if_not ARM64_HAS_DCPOP191b dcache_clean_poc192alternative_else_nop_endif193dcache_by_line_op cvap, sy, x0, x1, x2, x3194ret195SYM_FUNC_END(__pi_dcache_clean_pop)196SYM_FUNC_ALIAS(dcache_clean_pop, __pi_dcache_clean_pop)197198199