本文以Cortex-A53處理器為例,通過(guò)訪問(wèn) 處理器中的 內(nèi)部存儲(chǔ)單元 (tag RAM和dirty RAM),來(lái)讀取cache line 中的MOESI信息。
Cortex-A53提供了一種通過(guò)讀取一些系統(tǒng)寄存器,來(lái)訪問(wèn)Cache 和 TLB使用的一些內(nèi)部存儲(chǔ)單元的機(jī)制。這個(gè)功能可以探查出當(dāng)緩存中的數(shù)據(jù)與主存中的數(shù)據(jù)不一致時(shí)存在的問(wèn)題。
此外,A64模式和A32模式的讀取方式不同:
當(dāng)處理器處于A64模式時(shí),先通過(guò)一些只寫(xiě)(write-only)寄存器來(lái)選擇具體的cache line和內(nèi)存地址,然后通過(guò)只讀寄存器來(lái)讀取具體的tag信息。下圖為相關(guān)寄存器以及相關(guān)操作指令,需要注意的是,這些操作只在EL3時(shí)可用,如果在其他模式下使用這些指令,將會(huì)進(jìn)入U(xiǎn)ndefined Instruction 異常。
當(dāng)處理器處于A32模式下時(shí),先通過(guò)一些只寫(xiě)(write-only)CP15寄存器來(lái)選擇具體的cache line和內(nèi)存地址,然后通過(guò)只讀CP15寄存器來(lái)讀取具體的tag信息。下圖為相關(guān)寄存器以及相關(guān)操作指令,需要注意的是,這些操作只在EL3時(shí)可用,如果在其他模式下使用這些CP15指令,將會(huì)進(jìn)入U(xiǎn)ndefined Instruction 異常。
接下來(lái),本文以Cortex-A53的Data cache為例,讀取其某個(gè)cache line的tag信息,其具體的步驟很簡(jiǎn)單,分為兩步:
- 寫(xiě)入Data Cache Tag Read Operation Register,寫(xiě)入的內(nèi)容為具體的Set和way信息,通過(guò)way index和set index來(lái)定位到想要讀取的cache line。
- 讀取相應(yīng)的 Data Register 0 和 Data Register 1寄存器,通過(guò)對(duì)Data Register寄存器里面的數(shù)據(jù)進(jìn)行解碼,來(lái)獲取tag 信息。其他信息,比如Data cache 的data信息,Instruction Cache的data或者tag信息,以及TLB的data信息,都可以用這種方式讀取得到。
Step1:將Set/way信息寫(xiě)入Data Cache Tag Read Operation Register
首先,我們需要從一個(gè)虛擬地址(VA)中解析出Set index信息。
下圖為Cortex-A57的4-way組相連的32KB大小的data cache結(jié)構(gòu),其cache line大小也為64 bytes,從圖中可知,一個(gè)VA可以被分成幾個(gè)部分:Tag,Set index,word index以及byte index。其中Set index = VA[13:6]。
在另一個(gè)實(shí)例中,32KB大小的4-way組相連data cache,cache line大小為32 bytes,其Set index = VA[12:5]:
Cortex-A53的Data cache為4-way 組相連結(jié)構(gòu)。假設(shè)其為32KB,一個(gè)cache line的大小為64 bytes,我們就可以求出該data cache中有 32 KB / 64 B / 4 = 2^7 = 128個(gè)set(組),也就是說(shuō)至少需要7個(gè)bit才能完整解析出具體的set index。如下圖所示,可以通過(guò)公式:
S = log2(Data cache size / 4).
來(lái)計(jì)算出Set index的范圍:Set index = VA[12:6]。
由于是4-way 組相連結(jié)構(gòu),cache line 可以存在與任意一個(gè)way中,所以我們的cache way可能為0,1,2,3中任意一個(gè)數(shù)字。
求得了set和way的index后,需要對(duì)其進(jìn)行編碼,然后寫(xiě)入到Data Cache Tag Read Operation Register寄存器中。其編碼規(guī)則如下圖所示,只需將Set和way的值寫(xiě)入對(duì)應(yīng)的bit中即可,其中Rd[5:3]為cahche double word數(shù)據(jù)的偏移量,由于本次示例是讀取tag信息,所以Rd[5:3]為0即可。
所以我們要寫(xiě)入Data Cache Tag Read Operation Register的Rd的值可以通過(guò)以下代碼獲?。?/p>
unsigned int get_Rd_data(int * VA, way_num)
{
unsigned int set_way_index = VA | 0x1FC0; //get way index, VA[12:6]
set_way_index |= way_num < 30; //way_num could be 0,1,2,3
return set_way_index;
}
Rd中除了Set和way信息,其他值均為0,0x1FC0為VA[12:6]全為1的情況:
然后我們使用CP15寄存器將Rd的值寫(xiě)入,假設(shè)Rd為R0:
MCR p15, 3, r0, c15, c2, 0 ; r0 = get_Rd_data(VA,way_num)
Step2:讀取Data Register 1和Data Register 0數(shù)據(jù)并解碼
將Set/way信息寫(xiě)入Data Cache Tag Read Operation Register 后,相當(dāng)于選擇了想要操作的cache line,接下來(lái)我們將讀取Data Register 1和Data Register 0的數(shù)據(jù)來(lái)獲取該cache line里的tag信息,除了tag信息外,我們還可以從Data Register 1和Data Register 0兩個(gè)寄存器中獲?。?/p>
- MOESI 狀態(tài)信息
- outer內(nèi)存屬性
- valid 信息
可獲得的信息具體見(jiàn)下圖:
需要注意的是,如果是想獲取MOESI狀態(tài)信息,則需要兩個(gè)寄存器配合使用,即讀取Data Register 0 [1:0]以及Data Register 1 [30:29] ,Data Register 0 [1:0]里的為來(lái)自Dirty RAM的部分狀態(tài)信息,Data Register 1 [30:29]里的為來(lái)自tag RAM的部分MOESI信息,
其具體的組合見(jiàn)下圖:
比如讀取到的Data Register 0 [1:0]為1,以及Data Register 1 [30:29]也為1,根據(jù)上圖的組合關(guān)系,可知當(dāng)前cache line的MOESI狀態(tài)為 SharedDirty(O)。
示例代碼如下:
; step 1: write set index and way num into Data Cache Tag Read Operation Register
MCR p15, 3, r0, c15, c2, 0 ; r0 = get_Rd_data(VA,way_num)
; step 2: read Data Register 1 and Data Register 0
MCR p15, 3, r1, c15, c0, 0 ;r1 = Data Register 0
MCR p15, 3, r2, c15, c0, 1 ;r2 = Data Register 1
評(píng)論