1. 程式人生 > 其它 >linux aarch64 __inval_dcache_area(kaddr, size)

linux aarch64 __inval_dcache_area(kaddr, size)

__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;
   }

}