__inval_dcache_area(kaddr, size)
让一段 kaddr 开始的,长度为 size 的 内存 数据 缓存失效
在 arch/arm64/mm/cache.S 中实现的这个函数。
1 /* 2 * __inval_dcache_area(kaddr, size) 3 * 4 * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) 5 * are invalidated. Any partial lines at the ends of the interval are 6 * also cleaned to PoC to prevent data loss. 7 * 8 * - kaddr - kernel address 9 * - size - size in question 10 */ 11 SYM_FUNC_START_LOCAL(__dma_inv_area) 12 SYM_FUNC_START_PI(__inval_dcache_area) 13 /* FALLTHROUGH */ 14 15 /* 16 * __dma_inv_area(start, size) 17 * - start - virtual start address of region 18 * - size - size in question 19 */ 20 add x1, x1, x0 21 dcache_line_size x2, x3 22 sub x3, x2, #1 23 tst x1, x3 // end cache line aligned? 24 bic x1, x1, x3 25 b.eq 1f 26 dc civac, x1 // clean & invalidate D / U line 27 1: tst x0, x3 // start cache line aligned? 28 bic x0, x0, x3 29 b.eq 2f 30 dc civac, x0 // clean & invalidate D / U line 31 b 3f 32 2: dc ivac, x0 // invalidate D / U line 33 3: add x0, x0, x2 34 cmp x0, x1 35 b.lo 2b 36 dsb sy 37 ret 38 SYM_FUNC_END_PI(__inval_dcache_area) 39 SYM_FUNC_END(__dma_inv_area)
1、 dcache_line_size 是获取 data cache line size。 参考 https://www.cnblogs.com/zhangzhiwei122/p/15970511.html
2、dc civac <Xn> 是 让 Xn 指向 地址 的 缓存 无效。
使用下面的伪代码 表示 操作过程。
void __inval_dcache_area(kaddr, size) { x1_end_addr = kaddr + size; x2_cache_line_size = dcache_line_size(); // 处理末尾地址 if(x1_end_addr & ( x2_cache_line_size - 1 )){ dc_civac( x1_end_addr) } // 向下对齐 x1_end_addr = x1_end_addr & ~( x2_cache_line_size - 1 ) // bic bit clean x1_end_addr. // 处理起始地址 if(x0_kaddr & ( x2_cache_line_size - 1 ) ){ dc_civac( x0_kaddr ) } // 向下对齐 x0_kaddr = x0_kaddr & ~( x2_cache_line_size - 1 ) // bic bit clean x0_kaddr. // 下一个 cache line size 整数倍 的地址 x0_kaddr += x2_cache_line_size; while ( x0_kaddr < x1_end_addr){ dc_civac( x0_kaddr ); x0_kaddr += x2_cache_line_size; } }