版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。
/*
* Flush the wholeD-cache.
* Corrupted registers: x0-x7, x9-x11
*/
ENTRY(__flush_dcache_all)
//保證之前的訪存指令的順序
dsb sy
//讀cache level id register
//取bits[26:24](Level of Coherency for the cache hierarchy.)
//需要遵循cache一緻性的cache層級(例如有3級cache,但2級需要做一緻性)
and x3, x0, #0x7000000 // extract loc from clidr
//邏輯右移23位,把bits[26:24]放到bits[2:0]
lsr x3, x3, #23 // left align loc bit field
//如果需要做cache一緻性的層級為0,則不需要flush,跳轉到finished标記處。
cbz x3, finished // if loc is 0, then no need toclean
//x10存放cache級,從level0 cache開始做flush
//以下三個循環loop3是set/way(x9),
//loop2是index(x7),loop1是cache level(x10)
mov x10, #0 // start clean at cache level 0
loop1:
//x10+2後右移一位正好等于1,再加上x10本身正好等于3
//每執行一次loop1,x2+3*執行次數,目的在于把x0(clidr_el1)右移3位,
//取下一個cache的ctype type fields字段,clidr_el1的格式見《ARMv8 ARM》
add x2, x10, x10, lsr #1 /
//x0邏輯右移x2位,給x1,提取cache類型放到x1中,x0中存放:clidr_el1
lsr x1, x0, x2
//掩掉高位,隻取目前cache類型
and x1, x1, #7
/* 判斷目前cache是什麼類型:
* 000 No cache.
* 001 Instruction cache only.
* 010 Data cache only.
* 011 Separate instruction and data caches.
* 100 Unified cache.
*/
//小于2說明data cache不存在或者隻有icache,
//跳轉skip執行,大于等于2繼續執行
cmp x1, #2
b.lt skip
* Save/disableand restore interrupts.
* .macro save_and_disable_irqs, olddaif
* mrs \olddaif,daif
* disable_irq
* .endm
//儲存daif到x9寄存器中,關閉中斷
save_and_disable_irqs x9 // make CSSELR and CCSIDR access atomic
//選擇目前cache級進行操作,csselr_el1寄存器bit[3:1]選擇要操作的cache級
//第一次執行時x10=0,選擇level 0級cache
//isb用于同步新的cssr和csidr寄存器
isb
//因為執行了“msr csselr_el1,x10”,是以要重新讀取ccsidr_el1
/*
* .macro restore_irqs, olddaif
* msrdaif, \olddaif
. * endm
*/
restore_irqs x9
//x1存儲ccsidr_el1内容,低三位是(Log2(Number of bytes in cache line)) – 4
//加4後x2=(Log2(Numberof bytes in cache line))
and x2, x1, #7 // extract the length of the cachelines
add x2, x2, #4 // add 4 (line length offset)
mov x4, #0x3ff
//邏輯右移3位,提取bits[12:3](Associativityof cache) – 1,
//x4存儲cache的way數
and x4, x4, x1, lsr #3 // find maximum number on the way size
//計算x4前面0的個數,存到x5
//提取bits[27:13]位:(Number of sets in cache) - 1
mov x7, #0x7fff
//x7中存儲cache中的set數
and x7, x7, x1, lsr #13 // extract max number of the index size
loop2:
//把x4值備份
mov x9, x4 // create working copy of max waysize
loop3:
//把需要操作哪個way存儲到x6
lsl x6, x9, x5
//确定操作哪一級的哪個way(x10指定操作哪一級cache)
orr x11, x10, x6 // factor way and cache number intox11
//确定操作哪個set
lsl x6, x7, x2
orr x11, x11, x6 // factor index number into x11
//x11中存儲了哪一級cache(10),哪一路cache(x9),哪個set(x7)
dc cisw, x11 // clean & invalidate by set/way
//way數-1
subs x9, x9, #1 // decrementthe way
b.ge loop3
subs x7, x7, #1 // decrementthe index
b.ge loop2
skip:
add x10, x10, #2 // increment cache number,
//為什麼加2不是1?見loop1标号處解釋
b.gt loop1
finished:
mov x10, #0 // swith back to cache level 0
msr csselr_el1, x10 // select current cache level incsselr
dsb sy
isb
ret
ENDPROC(__flush_dcache_all)
如果你對此有疑問,歡迎留言讨論。
【新浪微網誌】 張昺華--sky
【twitter】 @sky2030_
【facebook】 張昺華 zhangbinghua
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.