loongarch架構(gòu)介紹(四)TLB異常處理
??想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:??
前言
上一篇文章中介紹了loongarch架構(gòu)中的地址翻譯模式及其配置方法,涉及到虛擬內(nèi)存系統(tǒng)中頁表相關(guān)的管理。本文中則介紹TLB相關(guān)的異常處理,并結(jié)合代碼進(jìn)行分析。因?yàn)閘oongarch架構(gòu)中采用的是一種軟件管理TLB的方法,所以其處理流程和軟件所需要進(jìn)行的管理操作與很多常見的架構(gòu)不同。
1、TLB表項(xiàng)和頁表項(xiàng)
首先介紹TLB表項(xiàng)和頁表項(xiàng)的格式,作基本的了解。
(1)頁表項(xiàng)格式
下圖為loongarch中的頁表項(xiàng)格式:
下面為各位的說明:
- V:有效位。標(biāo)志頁表項(xiàng)是否有效。
- D:臟位。標(biāo)志頁內(nèi)容是否需要回寫。
- MAT:存儲(chǔ)訪問類型。見前面的文章。
- G:是否為全局頁。
- P:物理頁是否存在。
- W:是否可寫。
- H:是否為大頁。
- PA:物理地址高地址部分。
- NR:不可讀位。表示該頁不可讀。
- NX:不可執(zhí)行位。表示該頁不可執(zhí)行。
- PLV和RPLV:特權(quán)級(jí),當(dāng)RPLV=0,表示可以被任何特權(quán)級(jí)不低于PLV的程序訪問;當(dāng)RPLV=1,表示僅可以被特權(quán)級(jí)等于PLV的程序訪問
其中,大頁的頁表項(xiàng)和基本頁的頁表項(xiàng)在格式上的主要區(qū)別是H位和G位。并且基本頁的頁表項(xiàng)在末級(jí)頁表,而大頁的頁表項(xiàng)實(shí)際上是替代了原來的頁目錄項(xiàng)。
另外,對(duì)于基本頁的頁表項(xiàng),loongarch中每個(gè)頁表項(xiàng)存放了相鄰的一對(duì)奇偶相鄰頁表信息。如下圖:
(2)TLB表項(xiàng)格式
下圖為loongarch中的TLB表項(xiàng)格式:
其中,每個(gè)TLB表項(xiàng)分為兩個(gè)部分:第一行為比較部分,下面兩行為物理轉(zhuǎn)換部分。
TLB表項(xiàng)的比較部分包括:
- E:存在位,1比特。為1時(shí)表示存在。用于TLB查找時(shí)判斷。
- ASID:address space identifier,10比特。用于區(qū)分不同的進(jìn)程或虛擬地址空間,減少進(jìn)程上下文切換等操作時(shí)刷新TLB的性能損失。TLB查找時(shí)也需匹配ASID。具體見后面的文章。
- G:全局位,1比特。用于取消ASID的作用,標(biāo)識(shí)為全局的表項(xiàng)。
- PS:頁大小,6比特。用于支持不同的頁大小。如對(duì)于16KB的頁,PS=14。
- VPPN:虛雙頁號(hào),對(duì)應(yīng)一對(duì)頁表項(xiàng)信息。對(duì)于基本頁的頁表項(xiàng),loongarch中每個(gè)頁表項(xiàng)存放了相鄰的一對(duì)奇偶相鄰頁表信息,所以TLB表項(xiàng)中存放的虛頁號(hào)是系統(tǒng)中虛頁號(hào)/2的內(nèi)容,即虛頁號(hào)的最低位不需要放在TLB中。查找TLB時(shí)根據(jù)被查找虛頁號(hào)的最低位決定是選擇奇數(shù)號(hào)頁還是偶數(shù)號(hào)頁的物理轉(zhuǎn)換信息。
而對(duì)于大頁的頁表項(xiàng),硬件上會(huì)自動(dòng)將其拆分為兩個(gè)尺寸折半的頁表項(xiàng)存儲(chǔ)在TLB中。如對(duì)于32MB的大頁,TLB會(huì)存儲(chǔ)兩個(gè)16MB大小的表項(xiàng)。
因?yàn)門LB和頁表雙頁存儲(chǔ)的特性,每個(gè)TLB表項(xiàng)中有兩個(gè)物理轉(zhuǎn)換信息。物理轉(zhuǎn)換信息中PPN即物理頁號(hào),其他和上文中頁表中的對(duì)應(yīng)。
2、軟件管理TLB
類似于MIPS架構(gòu),loongarch中使用的是一種軟件管理TLB的方式。在大多數(shù)其他的架構(gòu)中,采用的都是通過硬件管理TLB的方式。軟件管理TLB帶來了更多的靈活性,但性能相對(duì)較差。
硬件管理TLB中,在忽略page fault的細(xì)節(jié)和cache的情況下,虛擬地址轉(zhuǎn)換到物理地址的過程如下圖:
其中,TLB miss后查找頁表的這個(gè)過程是由硬件自動(dòng)完成的,軟件只需處理后面產(chǎn)生的page fault。整個(gè)過程中最多產(chǎn)生一次page fault。
下圖則為軟件管理TLB方案中虛擬地址轉(zhuǎn)換到物理地址的過程:
具體解釋如下:
- TLB miss后會(huì)產(chǎn)生第一次TLB重填(TLB refill)異常,在TLB重填異常中需要軟件去遍歷頁表并填充TLB表項(xiàng),這里應(yīng)該是軟件管理TLB和硬件管理TLB最大的不同。
- 然后TLB重填異常處理中,如果填充的頁表項(xiàng)仍然無效,那么在返回后再次查詢TLB時(shí),會(huì)第二次產(chǎn)生其他的fault處理,以填充頁表項(xiàng)、或填充頁表項(xiàng)和TLB項(xiàng)。
- 如果第二次fault處理中沒有重填TLB表項(xiàng),那么在返回后再次查詢TLB時(shí),還會(huì)產(chǎn)生第三次TLB重填異常。
可以看到,TLB miss后查找頁表的這個(gè)過程需要軟件進(jìn)行處理,并且整個(gè)過程中最多能產(chǎn)生三次異常。
另外,硬件上會(huì)保證在TLB重填異常中不能再次產(chǎn)生TLB重填異常。
3、TLB相關(guān)異常
loongarch中TLB相關(guān)的異常有:
- TLB重填異常:TLB miss后產(chǎn)生該異常
- load操作頁無效異常:load操作的虛擬地址在TLB中找到了匹配項(xiàng),但該匹配項(xiàng)的V=0時(shí)觸發(fā)
- store操作頁無效異常:store操作的虛擬地址在TLB中找到了匹配項(xiàng),但該匹配項(xiàng)的V=0時(shí)觸發(fā)
- 取指操作頁無效異常:取指操作的虛擬地址在TLB中找到了匹配項(xiàng),但該匹配項(xiàng)的V=0時(shí)觸發(fā)
- 頁特權(quán)等級(jí)不合規(guī)異常:訪存操作的虛擬地址在TLB中找到了匹配項(xiàng)且V=1,但訪問的特權(quán)等級(jí)不合規(guī)時(shí)觸發(fā)。參考上文頁表項(xiàng)中的PLV和RPLV域。
- 頁修改異常:store操作的虛擬地址在TLB中找到了匹配項(xiàng)且V=1且特權(quán)合規(guī),但該匹配項(xiàng)的D=0時(shí)觸發(fā)
- 頁不可讀異常:load操作的虛擬地址在TLB中找到了匹配項(xiàng)且V=1且特權(quán)合規(guī),但該匹配項(xiàng)的NR=1時(shí)觸發(fā)
- 頁不可執(zhí)行異常:取指操作的虛擬地址在TLB中找到了匹配項(xiàng)且V=1且特權(quán)合規(guī),但該匹配項(xiàng)的NX=1時(shí)觸發(fā)
其中,TLB重填異常時(shí)需遍歷頁表進(jìn)行重填工作。TLB重填異常于一般的異常不同,其擁有獨(dú)立的異常入口、獨(dú)立的用于維護(hù)現(xiàn)場的控制狀態(tài)寄存器和一套獨(dú)立的TLB訪問接口控制寄存器,并且因此TLB重填異??梢栽谄渌惓L幚磉^程中被觸發(fā)。而當(dāng)進(jìn)入TLB重填異常時(shí),硬件會(huì)自動(dòng)設(shè)置CSR.CRMD.DA=1和CSR.CRMD.PG=0,即進(jìn)入直接地址翻譯模式,從而避免在TLB重填異常中不能再次產(chǎn)生TLB重填異常。
而如load操作頁無效異常等異常,則需要完成類似于page fault的工作。
4、相關(guān)指令
在介紹TLB相關(guān)異常的處理之前,先對(duì)loongarch中相關(guān)的指令進(jìn)行介紹。
(1)TLB異常處理相關(guān)指令
- tlbsrch:查詢TLB對(duì)應(yīng)index。該指令使用CSR.ASID和CSR.TLBEHI中的信息查詢TLB,如果命中則將其對(duì)應(yīng)index寫入CSR.TLBIDX.Index,否則將CSR.TLBIDX.NE置為1。index可用于tlbwr等指令,指示操作的TLB索引。
- tlbrd:讀取index對(duì)應(yīng)TLB表項(xiàng)。將CSR.TLBIDX.Index作為索引,讀取TLB中的指定項(xiàng)。如果該TLB項(xiàng)有效,則將該TLB項(xiàng)的頁表項(xiàng)信息寫入到CSR.TLBEHI、CSR.TLBELO0、CSR.TLBELO1和CSR.TLBINX.PS這些相關(guān)寄存器,并將CSR.TLBIND.NE置0;如果無效,則將CSR.TLBIND.NE置1。
- tlbwr:寫入index對(duì)應(yīng)TLB表項(xiàng)。將CSR.TLBIDX.Index作為索引,把CSR.TLBEHI、CSR.TLBELO0、CSR.TLBELO1和CSR.TLBINX.PS這些相關(guān)寄存器中的頁表項(xiàng)信息寫入TLB中的指定項(xiàng)。其中,如果CSR.TLBIND.NE置為1,寫入的是一個(gè)無效TLB項(xiàng)。
- tlbfill:類似于tlbwr指令,不同的是tlbfill寫入TLB位置由硬件隨機(jī)決定。
具體案例可見后文相關(guān)代碼分析。
(2)頁表遍歷相關(guān)指令
- lddir rd, rj, level:訪問頁目錄項(xiàng)。
- level表示訪問頁表的級(jí)別。參考上一篇文章中的頁表分級(jí)。level為1-4分別對(duì)應(yīng)CSR.PWCL中的PT、Dir1、Dir2、Dir3。
- 如果通用寄存器rj中第6位是0,則rj表示第level級(jí)頁表的基址。此時(shí)lddir指令會(huì)根據(jù)當(dāng)前處理的TLB重填地址訪問level級(jí)頁表,取回對(duì)應(yīng)level-1級(jí)頁表的基址到rd中。
- 如果通用寄存器rj中第6位是1,則rj為一個(gè)大頁的頁表項(xiàng)。此時(shí)lddir指令會(huì)直接將rj寫入到rd中。
- ldpte rj, req:訪問頁表項(xiàng)。
- seq表示訪問的是奇數(shù)頁還是偶數(shù)頁。訪問偶數(shù)頁時(shí)結(jié)果將寫入CSR.TLBRELO0,訪問奇數(shù)頁時(shí)結(jié)果將寫入CSR.TLBRELO1。
- 如果通用寄存器rj中第6位是0,則rj表示末級(jí)頁表的基址。此時(shí)ldpte指令會(huì)根據(jù)當(dāng)前處理的TLB重填地址訪問末級(jí)頁表,取回對(duì)應(yīng)頁表項(xiàng)到CSR.TLBRELO0或CSR.TLBRELO1中。
- 如果通用寄存器rj中第6位是1,則rj為一個(gè)大頁的頁表項(xiàng)。此時(shí)lddir指令會(huì)直接將rj轉(zhuǎn)換為最終的頁表項(xiàng)格式寫入到CSR.TLBRELO0或CSR.TLBRELO1中。
具體案例可見后文相關(guān)代碼分析。
5、TLB相關(guān)異常處理
下面結(jié)合linux源碼對(duì)TLB相關(guān)異常處理進(jìn)行分析。
linux中TLB相關(guān)異常和相關(guān)處理函數(shù)的對(duì)應(yīng)關(guān)系如下:
- TLB重填異常:handle_tlb_refill
- load/取指操作頁無效異常:handle_tlb_load
- store操作頁無效異常:handle_tlb_store
- 頁修改異常:handle_tlb_modify
- 頁不可讀/不可寫/特權(quán)不合規(guī)異常:handle_tlb_protect
這里分析handle_tlb_refill、handle_tlb_load和handle_tlb_protect函數(shù)。其中handle_tlb_store和handle_tlb_modify實(shí)際上流程與handle_tlb_load基本一致,只是更新頁表項(xiàng)時(shí)更新的位不同。
(1)TLB重填異常
TLB重填異常(handle_tlb_refill)觸發(fā)前后硬件中的處理與一般異常存在差異,主要是TLB重填異常相關(guān)有獨(dú)立的一套寄存器。但都會(huì)有相應(yīng)保存和恢復(fù)現(xiàn)場、跳轉(zhuǎn)和返回操作。值得注意的是,TLB重填異常中出錯(cuò)的地址保存在CSR.TLBRBADV寄存器,而一般異常出錯(cuò)的地址保存在CSR.BADV寄存器。
TLB重填異常的軟件處理過程如下:
- 保存現(xiàn)場
- 根據(jù)CSR.TLBRBADV中記錄的缺失虛擬地址,和CSR.PGD中pgd基址,遍歷發(fā)生TLB重填異常的進(jìn)程的多級(jí)頁表,從內(nèi)存中取回頁表項(xiàng)信息并填入CSR.TLBELO0和CSR.TLBELO1寄存器的相應(yīng)域中
- 根據(jù)填入的CSR.TLBELO0和CSR.TLBELO1寄存器信息,最終用tlbfill指令將頁表項(xiàng)填入TLB
- 恢復(fù)并返回
代碼分析如下:
(2)load/取指操作頁無效異常
load/取指操作頁無效異常觸發(fā)前后硬件中的處理與一般異常相同。
handle_tlb_load處理的過程如下:
- 保存現(xiàn)場
- 根據(jù)CSR.BADV中記錄的缺失虛擬地址,和CSR.PGD中pgd基址,遍歷發(fā)生異常的進(jìn)程的多級(jí)頁表,從內(nèi)存中取回頁表項(xiàng)(或大頁)信息
- 判斷該頁表項(xiàng)是否存在,如果不存在則會(huì)跳轉(zhuǎn)執(zhí)行缺頁處理函數(shù)
- 如果存在則將頁表項(xiàng)置為有效并填入TLB。最后恢復(fù)并返回
代碼分析如下:
(3)頁不可讀/不可寫/特權(quán)不合規(guī)異常
頁不可讀/不可寫/特權(quán)不合規(guī)異常觸發(fā)前后硬件中的處理與一般異常相同。
handle_tlb_protect處理的過程實(shí)際上就是調(diào)用缺頁處理函數(shù),來填入頁表。
代碼分析如下:
總結(jié)
本文介紹了loongarch架構(gòu)中軟件管理TLB的機(jī)制、TLB重填異常和其他TLB相關(guān)的異常,以及相應(yīng)的異常處理和代碼分析。
軟件管理TLB機(jī)制、處理TLB相關(guān)異常,算是loongarch架構(gòu)中TLB相關(guān)軟件維護(hù)中較為特別的地方。下一篇文章將繼續(xù)介紹loongarch中其他的TLB維護(hù)和相關(guān)指令。