日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CPU場(chǎng)景下的TLB相關(guān)細(xì)節(jié)

Linux閱碼場(chǎng) ? 來(lái)源:Linuxer ? 作者:Linuxer ? 2020-12-26 09:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、前言

進(jìn)程切換是一個(gè)復(fù)雜的過(guò)程,本文不準(zhǔn)備詳細(xì)描述整個(gè)進(jìn)程切換的方方面面,而是關(guān)注進(jìn)程切換中一個(gè)小小的知識(shí)點(diǎn):TLB的處理。為了能夠講清楚這個(gè)問(wèn)題,我們?cè)诘诙旅枋鲈趩?a target="_blank">CPU場(chǎng)景下一些和TLB相關(guān)的細(xì)節(jié),第三章推進(jìn)到多核場(chǎng)景,至此,理論部分結(jié)束。在第二章和第三章,我們從基本的邏輯角度出發(fā),并不拘泥于特定的CPU和特定的OS,這里需要大家對(duì)基本的TLB的組織原理有所了解,具體可以參考本站的《TLB操作》一文。再好的邏輯也需要體現(xiàn)在HW block和SW block的設(shè)計(jì)中,在第四章,我們給出了linux4.4.6內(nèi)核在ARM64平臺(tái)上的TLB代碼處理細(xì)節(jié)(在描述tlb lazy mode的時(shí)候引入部分x86架構(gòu)的代碼),希望能通過(guò)具體的代碼和實(shí)際的CPU硬件行為加深大家對(duì)原理的理解。

二、單核場(chǎng)景的工作原理

1、block diagram

我們先看看在單核場(chǎng)景下,和進(jìn)程切換相關(guān)的邏輯block示意圖:

4148eccc-4422-11eb-8b86-12bb97331649.jpg

CPU上運(yùn)行了若干的用戶空間的進(jìn)程和內(nèi)核線程,為了加快性能,CPU中往往設(shè)計(jì)了TLB和Cache這樣的HW block。Cache為了更快的訪問(wèn)main memory中的數(shù)據(jù)和指令,而TLB是為了更快的進(jìn)行地址翻譯而將部分的頁(yè)表內(nèi)容緩存到了Translation lookasid buffer中,避免了從main memory訪問(wèn)頁(yè)表的過(guò)程。

假如不做任何的處理,那么在進(jìn)程A切換到進(jìn)程B的時(shí)候,TLB和Cache中同時(shí)存在了A和B進(jìn)程的數(shù)據(jù)。對(duì)于kernel space其實(shí)無(wú)所謂,因?yàn)樗械倪M(jìn)程都是共享的,但是對(duì)于A和B進(jìn)程,它們各種有自己的獨(dú)立的用戶地址空間,也就是說(shuō),同樣的一個(gè)虛擬地址X,在A的地址空間中可以被翻譯成Pa,而在B地址空間中會(huì)被翻譯成Pb,如果在地址翻譯過(guò)程中,TLB中同時(shí)存在A和B進(jìn)程的數(shù)據(jù),那么舊的A地址空間的緩存項(xiàng)會(huì)影響B(tài)進(jìn)程地址空間的翻譯,因此,在進(jìn)程切換的時(shí)候,需要有tlb的操作,以便清除舊進(jìn)程的影響,具體怎樣做呢?我們下面一一討論。

2、絕對(duì)沒(méi)有問(wèn)題,但是性能不佳的方案

當(dāng)系統(tǒng)發(fā)生進(jìn)程切換,從進(jìn)程A切換到進(jìn)程B,從而導(dǎo)致地址空間也從A切換到B,這時(shí)候,我們可以認(rèn)為在A進(jìn)程執(zhí)行過(guò)程中,所有TLB和Cache的數(shù)據(jù)都是for A進(jìn)程的,一旦切換到B,整個(gè)地址空間都不一樣了,因此需要全部flush掉(注意:我這里使用了linux內(nèi)核的術(shù)語(yǔ),flush就是意味著將TLB或者cache中的條目設(shè)置為無(wú)效,對(duì)于一個(gè)ARM平臺(tái)上的嵌入式工程師,一般我們會(huì)更習(xí)慣使用invalidate這個(gè)術(shù)語(yǔ),不管怎樣,在本文中,flush等于invalidate)。

這種方案當(dāng)然沒(méi)有問(wèn)題,當(dāng)進(jìn)程B被切入執(zhí)行的時(shí)候,其面對(duì)的CPU是一個(gè)干干凈凈,從頭開(kāi)始的硬件環(huán)境,TLB和Cache中不會(huì)有任何的殘留的A進(jìn)程的數(shù)據(jù)來(lái)影響當(dāng)前B進(jìn)程的執(zhí)行。當(dāng)然,稍微有一點(diǎn)遺憾的就是在B進(jìn)程開(kāi)始執(zhí)行的時(shí)候,TLB和Cache都是冰冷的(空空如也),因此,B進(jìn)程剛開(kāi)始執(zhí)行的時(shí)候,TLB miss和Cache miss都非常嚴(yán)重,從而導(dǎo)致了性能的下降。

3、如何提高TLB的性能?

對(duì)一個(gè)模塊的優(yōu)化往往需要對(duì)該模塊的特性進(jìn)行更細(xì)致的分析、歸類,上一節(jié),我們采用進(jìn)程地址空間這樣的術(shù)語(yǔ),其實(shí)它可以被進(jìn)一步細(xì)分為內(nèi)核地址空間和用戶地址空間。對(duì)于所有的進(jìn)程(包括內(nèi)核線程),內(nèi)核地址空間是一樣的,因此對(duì)于這部分地址翻譯,無(wú)論進(jìn)程如何切換,內(nèi)核地址空間轉(zhuǎn)換到物理地址的關(guān)系是永遠(yuǎn)不變的,其實(shí)在進(jìn)程A切換到B的時(shí)候,不需要flush掉,因?yàn)锽進(jìn)程也可以繼續(xù)使用這部分的TLB內(nèi)容(上圖中,橘色的block)。對(duì)于用戶地址空間,各個(gè)進(jìn)程都有自己獨(dú)立的地址空間,在進(jìn)程A切換到B的時(shí)候,TLB中的和A進(jìn)程相關(guān)的entry(上圖中,青色的block)對(duì)于B是完全沒(méi)有任何意義的,需要flush掉。

在這樣的思路指導(dǎo)下,我們其實(shí)需要區(qū)分global和local(其實(shí)就是process-specific的意思)這兩種類型的地址翻譯,因此,在頁(yè)表描述符中往往有一個(gè)bit來(lái)標(biāo)識(shí)該地址翻譯是global還是local的,同樣的,在TLB中,這個(gè)標(biāo)識(shí)global還是local的flag也會(huì)被緩存起來(lái)。有了這樣的設(shè)計(jì)之后,我們可以根據(jù)不同的場(chǎng)景而flush all或者只是flush local tlb entry。

4、特殊情況的考量

我們考慮下面的場(chǎng)景:進(jìn)程A切換到內(nèi)核線程K之后,其實(shí)地址空間根本沒(méi)有必要切換,線程K能訪問(wèn)的就是內(nèi)核空間的那些地址,而這些地址也是和進(jìn)程A共享的。既然沒(méi)有切換地址空間,那么也就不需要flush 那些進(jìn)程特定的tlb entry了,當(dāng)從K切換會(huì)A進(jìn)程后,那么所有TLB的數(shù)據(jù)都是有效的,從大大降低了tlb miss。此外,對(duì)于多線程環(huán)境,切換可能發(fā)生在一個(gè)進(jìn)程中的兩個(gè)線程,這時(shí)候,線程在同樣的地址空間,也根本不需要flush tlb。

4、進(jìn)一步提升TLB的性能

還有可能進(jìn)一步提升TLB的性能嗎?有沒(méi)有可能根本不flush TLB?

當(dāng)然可以,不過(guò)這需要我們?cè)谠O(shè)計(jì)TLB block的時(shí)候需要識(shí)別process specific的tlb entry,也就是說(shuō),TLB block需要感知到各個(gè)進(jìn)程的地址空間。為了完成這樣的設(shè)計(jì),我們需要標(biāo)識(shí)不同的address space,這里有一個(gè)術(shù)語(yǔ)叫做ASID(address space ID)。原來(lái)TLB查找是通過(guò)虛擬地址VA來(lái)判斷是否TLB hit。有了ASID的支持后,TLB hit的判斷標(biāo)準(zhǔn)修改為(虛擬地址+ASID),ASID是每一個(gè)進(jìn)程分配一個(gè),標(biāo)識(shí)自己的進(jìn)程地址空間。TLB block如何知道一個(gè)tlb entry的ASID呢?一般會(huì)來(lái)自CPU的系統(tǒng)寄存器(對(duì)于ARM64平臺(tái),它來(lái)自TTBRx_EL1寄存器),這樣在TLB block在緩存(VA-PA-Global flag)的同時(shí),也就把當(dāng)前的ASID緩存在了對(duì)應(yīng)的TLB entry中,這樣一個(gè)TLB entry中包括了(VA-PA-Global flag-ASID)。

有了ASID的支持后,A進(jìn)程切換到B進(jìn)程再也不需要flush tlb了,因?yàn)锳進(jìn)程執(zhí)行時(shí)候緩存在TLB中的殘留A地址空間相關(guān)的entry不會(huì)影響到B進(jìn)程,雖然A和B可能有相同的VA,但是ASID保證了硬件可以區(qū)分A和B進(jìn)程地址空間。

三、多核的TLB操作

1、block diagram

完成單核場(chǎng)景下的分析之后,我們一起來(lái)看看多核的情況。進(jìn)程切換相關(guān)的TLB邏輯block示意圖如下:

417bb3c8-4422-11eb-8b86-12bb97331649.jpg

在多核系統(tǒng)中,進(jìn)程切換的時(shí)候,TLB的操作要復(fù)雜一些,主要原因有兩點(diǎn):其一是各個(gè)cpu core有各自的TLB,因此TLB的操作可以分成兩類,一類是flush all,即將所有cpu core上的tlb flush掉,還有一類操作是flush local tlb,即僅僅flush本cpu core的tlb。另外一個(gè)原因是進(jìn)程可以調(diào)度到任何一個(gè)cpu core上執(zhí)行(當(dāng)然具體和cpu affinity的設(shè)定相關(guān)),從而導(dǎo)致task處處留情(在各個(gè)cpu上留有殘余的tlb entry)。

2、TLB操作的基本思考

根據(jù)上一節(jié)的描述,我們了解到地址翻譯有g(shù)lobal(各個(gè)進(jìn)程共享)和local(進(jìn)程特定的)的概念,因而tlb entry也有g(shù)lobal和local的區(qū)分。如果不區(qū)分這兩個(gè)概念,那么進(jìn)程切換的時(shí)候,直接flush該cpu上的所有殘余。這樣,當(dāng)進(jìn)程A切出的時(shí)候,留給下一個(gè)進(jìn)程B一個(gè)清爽的tlb,而當(dāng)進(jìn)程A在其他cpu上再次調(diào)度的時(shí)候,它面臨的也是一個(gè)全空的TLB(其他cpu的tlb不會(huì)影響)。當(dāng)然,如果區(qū)分global 和local,那么tlb操作也基本類似,只不過(guò)進(jìn)程切換的時(shí)候,不是flush該cpu上的所有tlb entry,而是flush所有的tlb local entry就OK了。

對(duì)local tlb entry還可以進(jìn)一步細(xì)分,那就是了ASID(address space ID)或者PCID(process context ID)的概念了(global tlb entry不區(qū)分ASID)。如果支持ASID(或者PCID)的話,tlb操作變得簡(jiǎn)單一些,或者說(shuō)我們沒(méi)有必要執(zhí)行tlb操作了,因?yàn)樵赥LB搜索的時(shí)候已經(jīng)可以區(qū)分各個(gè)task上下文了,這樣,各個(gè)cpu中殘留的tlb不會(huì)影響其他任務(wù)的執(zhí)行。在單核系統(tǒng)中,這樣的操作可以獲取很好的性能。比如A---B--->A這樣的場(chǎng)景中,如果TLB足夠大,可以容納2個(gè)task的tlb entry(現(xiàn)代cpu一般也可以做到這一點(diǎn)),那么A再次切回的時(shí)候,TLB是hot的,大大提升了性能。

不過(guò),對(duì)于多核系統(tǒng),這種情況有一點(diǎn)點(diǎn)的麻煩,其實(shí)也就是傳說(shuō)中的TLB shootdown帶來(lái)的性能問(wèn)題。在多核系統(tǒng)中,如果cpu支持PCID并且在進(jìn)程切換的時(shí)候不flush tlb,那么系統(tǒng)中各個(gè)cpu中的tlb entry則保留各種task的tlb entry,當(dāng)在某個(gè)cpu上,一個(gè)進(jìn)程被銷毀,或者修改了自己的頁(yè)表(也就是修改了VA PA映射關(guān)系)的時(shí)候,我們必須將該task的相關(guān)tlb entry從系統(tǒng)中清除出去。這時(shí)候,你不僅僅需要flush本cpu上對(duì)應(yīng)的TLB entry,還需要shootdown其他cpu上的和該task相關(guān)的tlb殘余。而這個(gè)動(dòng)作一般是通過(guò)IPI實(shí)現(xiàn)(例如X86),從而引入了開(kāi)銷。此外PCID的分配和管理也會(huì)帶來(lái)額外的開(kāi)銷,因此,OS是否支持PCID(或者ASID)是由各個(gè)arch代碼自己決定(對(duì)于linux而言,x86不支持,而ARM平臺(tái)是支持的)。

四、進(jìn)程切換中的tlb操作代碼分析

1、tlb lazy mode

在context_switch中有這樣的一段代碼:

if (!mm) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);

這段代碼的意思就是如果要切入的next task是一個(gè)內(nèi)核線程(next->mm == NULL )的話,那么可以通過(guò)enter_lazy_tlb函數(shù)標(biāo)記本cpu上的next task進(jìn)入lazy TLB mode。由于ARM64平臺(tái)上的enter_lazy_tlb函數(shù)是空函數(shù),因此我們采用X86來(lái)描述lazy TLB mode。

當(dāng)然,我們需要一些準(zhǔn)備工作,畢竟對(duì)于熟悉ARM平臺(tái)的嵌入式工程師而言,x86多少有點(diǎn)陌生。

到目前,我們還都是從邏輯角度來(lái)描述TLB操作,但是在實(shí)際中,進(jìn)程切換中的tlb操作是HW完成還是SW完成呢?不同的處理器思路是不一樣的(具體原因未知),有的處理器是HW完成,例如X86,在加載cr3寄存器進(jìn)行地址空間切換的時(shí)候,hw會(huì)自動(dòng)操作tlb。而有的處理是需要軟件參與完成tlb操作,例如ARM系列的處理器,在切換TTBR寄存器的時(shí)候,HW沒(méi)有tlb動(dòng)作,需要SW完成tlb操作。因此,x86平臺(tái)上,在進(jìn)程切換的時(shí)候,軟件不需要顯示的調(diào)用tlb flush函數(shù),在switch_mm函數(shù)中會(huì)用next task中的mm->pgd加載CR3寄存器,這時(shí)候load cr3的動(dòng)作會(huì)導(dǎo)致本cpu中的local tlb entry被全部flush掉。

在x86支持PCID(X86術(shù)語(yǔ),相當(dāng)與ARM的ASID)的情況下會(huì)怎樣呢?也會(huì)在load cr3的時(shí)候flush掉所有的本地CPU上的 local tlb entry嗎?其實(shí)在linux中,由于TLB shootdown,普通的linux并不支持PCID(KVM中會(huì)使用,但是不在本文考慮范圍內(nèi)),因此,對(duì)于x86的進(jìn)程地址空間切換,它就是會(huì)有flush local tlb entry這樣的side effect。

另外有一點(diǎn)是ARM64和x86不同的地方:ARM64支持在一個(gè)cpu core執(zhí)行tlb flush的指令,例如tlbi vmalle1is,將inner shareablity domain中的所有cpu core的tlb全部flush掉。而x86不能,如果想要flush掉系統(tǒng)中多有cpu core的tlb,只能是通過(guò)IPI通知到其他cpu進(jìn)行處理。

好的,至此,所有預(yù)備知識(shí)都已經(jīng)ready了,我們進(jìn)入tlb lazy mode這個(gè)主題。雖然進(jìn)程切換伴隨tlb flush操作,但是某些場(chǎng)景亦可避免。在下面的場(chǎng)景,我們可以不flush tlb(我們?nèi)匀徊捎肁--->B task的場(chǎng)景來(lái)描述):

(1)如果要切入的next task B是內(nèi)核線程,那么我們也暫時(shí)不需要flush TLB,因?yàn)閮?nèi)核線程不會(huì)訪問(wèn)usersapce,而那些進(jìn)程A殘留的TLB entry也不會(huì)影響內(nèi)核線程的執(zhí)行,畢竟B沒(méi)有自己的用戶地址空間,而且和A共享內(nèi)核地址空間。

(2)如果A和B在一個(gè)地址空間中(一個(gè)進(jìn)程中的兩個(gè)線程),那么我們也暫時(shí)不需要flush TLB。

除了進(jìn)程切換,還有其他的TLB flush場(chǎng)景。我們先看一個(gè)通用的TLB flush場(chǎng)景,如下圖所示:

419d21a2-4422-11eb-8b86-12bb97331649.jpg

一個(gè)4核系統(tǒng)中,A0 A1和A2 task屬于同一個(gè)進(jìn)程地址空間,CPU_0和CPU_2上分別運(yùn)行了A0和A2 task,CPU_1有點(diǎn)特殊,它正在運(yùn)行一個(gè)內(nèi)核線程,但是該內(nèi)核線程正在借用A1 task的地址空間,CPU_3上運(yùn)行不相關(guān)的B task。

當(dāng)A0 task修改了自己的地址翻譯,那么它不能只是flush CPU_0的tlb,還需要通知到CPU_1和CPU_2,因?yàn)檫@兩個(gè)CPU上當(dāng)前active的地址空間和CPU_0是一樣的。由于A1 task的修改,CPU_1和CPU_2上的這些緩存的TLB entry已經(jīng)失效了,需要flush。同理,可以推廣到更多的CPU上,也就是說(shuō),在某個(gè)CPUx上運(yùn)行的task修改了地址映射關(guān)系,那么tlb flush需要傳遞到所有相關(guān)的CPU中(當(dāng)前的mm等于CPUx的current mm)。在多核系統(tǒng)中,這樣的通過(guò)IPI來(lái)傳遞TLB flush的消息會(huì)隨著cpu core的增加而增加,有沒(méi)有辦法減少那些沒(méi)有必要的TLB flush呢?當(dāng)然有,也就是上圖中的A1 task場(chǎng)景,這也就是傳說(shuō)中的lazy tlb mode。

我先回頭看看代碼。在代碼中,如果next task是內(nèi)核線程,我們并不會(huì)執(zhí)行switch_mm(該函數(shù)會(huì)引起tlb flush的動(dòng)作),而是調(diào)用enter_lazy_tlb進(jìn)入lazy tlb mode。在x86架構(gòu)下,代碼如下:

static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
#ifdef CONFIG_SMP
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
#endif
}

在x86架構(gòu)下,進(jìn)入lazy tlb mode也就是在該cpu的cpu_tlbstate變量中設(shè)定TLBSTATE_LAZY的狀態(tài)就OK了。因此,進(jìn)入lazy mode的時(shí)候,也就不需要調(diào)用switch_mm來(lái)切換進(jìn)程地址空間,也就不會(huì)執(zhí)行flush tlb這樣毫無(wú)意義的動(dòng)作了。enter_lazy_tlb并不操作硬件,只要記錄該cpu的軟件狀態(tài)就OK了。

切換之后,內(nèi)核線程進(jìn)入執(zhí)行狀態(tài),CPU_1的TLB殘留進(jìn)程A的entry,這對(duì)于內(nèi)核線程的執(zhí)行沒(méi)有影響,但是當(dāng)其他CPU發(fā)送IPI要求flush TLB的時(shí)候呢?按理說(shuō)應(yīng)該立刻flush tlb,但是在lazy tlb mode下,我們可以不執(zhí)行flush tlb操作。這樣問(wèn)題來(lái)了:什么時(shí)候flush掉殘留的A進(jìn)程的tlb entry呢?答案是在下一次進(jìn)程切換中。因?yàn)橐坏﹥?nèi)核線程被schedule out,并且切入一個(gè)新的進(jìn)程C,那么在switch_mm,切入到C進(jìn)程地址空間的時(shí)候,所有之前的殘留都會(huì)被清除掉(因?yàn)橛衛(wèi)oad cr3的動(dòng)作)。因此,在執(zhí)行內(nèi)核線程的時(shí)候,我們可以推遲tlb invalidate的請(qǐng)求。也就是說(shuō),當(dāng)收到ipi中斷要求進(jìn)行該mm的tlb invalidate的動(dòng)作的時(shí)候,我們暫時(shí)沒(méi)有必要執(zhí)行了,只需要記錄狀態(tài)就OK了。

2、ARM64中如何管理ASID?

和x86不同的是:ARM64支持了ASID(類似x86的PCID),難道ARM64解決了TLB Shootdown的問(wèn)題?其實(shí)我也在思考這個(gè)問(wèn)題,但是還沒(méi)有想明白。很顯然,在ARM64中,我們不需要通過(guò)IPI來(lái)進(jìn)行所有cpu core的TLB flush動(dòng)作,ARM64在指令集層面支持shareable domain中所有PEs上的TLB flush動(dòng)作,也許是這樣的指令讓TLB flush的開(kāi)銷也沒(méi)有那么大,那么就可以選擇支持ASID,在進(jìn)程切換的時(shí)候不需要進(jìn)行任何的TLB操作,同時(shí),由于不需要IPI來(lái)傳遞TLB flush,那么也就沒(méi)有特別的處理lazy tlb mode了。

既然linux中,ARM64選擇支持ASID,那么它就要直面ASID的分配和管理問(wèn)題了。硬件支持的ASID有一定限制,它的編址空間是8個(gè)或者16個(gè)bit,最大256或者65535個(gè)ID。當(dāng)ASID溢出之后如何處理呢?這就需要一些軟件的控制來(lái)協(xié)調(diào)處理。我們用硬件支持上限為256個(gè)ASID的情景來(lái)描述這個(gè)基本的思路:當(dāng)系統(tǒng)中各個(gè)cpu的TLB中的asid合起來(lái)不大于256個(gè)的時(shí)候,系統(tǒng)正常運(yùn)行,一旦超過(guò)256的上限后,我們將全部TLB flush掉,并重新分配ASID,每達(dá)到256上限,都需要flush tlb并重新分配HW ASID。具體分配ASID代碼如下:

static u64 new_context(struct mm_struct *mm, unsigned int cpu)
{
static u32 cur_idx = 1;
u64 asid = atomic64_read(&mm->context.id);
u64 generation = atomic64_read(&asid_generation);

if (asid != 0) {-------------------------(1)
u64 newasid = generation | (asid & ~ASID_MASK);
if (check_update_reserved_asid(asid, newasid))
return newasid;
asid &= ~ASID_MASK;
if (!__test_and_set_bit(asid, asid_map))
return newasid;
}


asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx);---(2)
if (asid != NUM_USER_ASIDS)
goto set_asid;

generation = atomic64_add_return_relaxed(ASID_FIRST_VERSION,----(3)
&asid_generation);
flush_context(cpu);

asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); ------(4)

set_asid:
__set_bit(asid, asid_map);
cur_idx = asid;
return asid | generation;
}

(1)在創(chuàng)建新的進(jìn)程的時(shí)候會(huì)分配一個(gè)新的mm,其software asid(mm->context.id)初始化為0。如果asid不等于0那么說(shuō)明這個(gè)mm之前就已經(jīng)分配過(guò)software asid(generation+hw asid)了,那么new context不過(guò)就是將software asid中的舊的generation更新為當(dāng)前的generation而已。

(2)如果asid等于0,說(shuō)明我們的確是需要分配一個(gè)新的HW asid,這時(shí)候首先要找一個(gè)空閑的HW asid,如果能夠找到(jump to set_asid),那么直接返回software asid(當(dāng)前generation+新分配的hw asid)。

(3)如果找不到一個(gè)空閑的HW asid,說(shuō)明HW asid已經(jīng)用光了,這是只能提升generation了。這時(shí)候,多有cpu上的所有的old generation需要被flush掉,因?yàn)橄到y(tǒng)已經(jīng)準(zhǔn)備進(jìn)入new generation了。順便一提的是這里generation變量已經(jīng)被賦值為new generation了。

(4)在flush_context函數(shù)中,控制HW asid的asid_map已經(jīng)被全部清零了,因此,這里進(jìn)行的是new generation中HW asid的分配。

3、進(jìn)程切換過(guò)程中ARM64的tlb操作以及ASID的處理

代碼位于arch/arm64/mm/context.c中的check_and_switch_context:

void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
{
unsigned long flags;
u64 asid;

asid = atomic64_read(&mm->context.id); -------------(1)

if (!((asid ^ atomic64_read(&asid_generation)) >> asid_bits) ------(2)
&& atomic64_xchg_relaxed(&per_cpu(active_asids, cpu), asid))
goto switch_mm_fastpath;

raw_spin_lock_irqsave(&cpu_asid_lock, flags);
asid = atomic64_read(&mm->context.id);
if ((asid ^ atomic64_read(&asid_generation)) >> asid_bits) { ------(3)
asid = new_context(mm, cpu);
atomic64_set(&mm->context.id, asid);
}

if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) ------(4)
local_flush_tlb_all();

atomic64_set(&per_cpu(active_asids, cpu), asid);
raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);

switch_mm_fastpath:
cpu_switch_mm(mm->pgd, mm);
}

看到這些代碼的時(shí)候,你一定很抓狂:本來(lái)期望支持ASID的情況下,進(jìn)程切換不需要TLB flush的操作了嗎?怎么會(huì)有那么多代碼?呵呵~~實(shí)際上理想很美好,現(xiàn)實(shí)很骨干,代碼中嵌入太多管理asid的內(nèi)容了。

(1)現(xiàn)在準(zhǔn)備切入mm變量指向的地址空間,首先通過(guò)內(nèi)存描述符獲取該地址空間的ID(software asid)。需要說(shuō)明的是這個(gè)ID并不是HW asid,實(shí)際上mm->context.id是64個(gè)bit,其中低16 bit對(duì)應(yīng)HW 的ASID(ARM64支持8bit或者16bit的ASID,但是這里假設(shè)當(dāng)前系統(tǒng)的ASID是16bit)。其余的bit都是軟件擴(kuò)展的,我們稱之generation。

(2)arm64支持ASID的概念,理論上進(jìn)程切換不需要TLB的操作,不過(guò)由于HW asid的編址空間有限,因此我們擴(kuò)展了64 bit的software asid,其中一部分對(duì)應(yīng)HW asid,另外一部分被稱為asid generation。asid generation從ASID_FIRST_VERSION開(kāi)始,每當(dāng)HW asid溢出后,asid generation會(huì)累加。asid_bits就是硬件支持的ASID的bit數(shù)目,8或者16,通過(guò)ID_AA64MMFR0_EL1寄存器可以獲得該具體的bit數(shù)目。

當(dāng)要切入的mm的software asid仍然處于當(dāng)前這一批次(generation)的ASID的時(shí)候,切換中不需要任何的TLB操作,可以直接調(diào)用cpu_switch_mm進(jìn)行地址空間的切換,當(dāng)然,也會(huì)順便設(shè)定active_asids這個(gè)percpu變量。

(3)如果要切入的進(jìn)程和當(dāng)前的asid generation不一致,那么說(shuō)明該地址空間需要一個(gè)新的software asid了,更準(zhǔn)確的說(shuō)是需要推進(jìn)到new generation了。因此這里調(diào)用new_context分配一個(gè)新的context ID,并設(shè)定到mm->context.id中。

(4)各個(gè)cpu在切入新一代的asid空間的時(shí)候會(huì)調(diào)用local_flush_tlb_all將本地tlb flush掉。

原文標(biāo)題:郭?。?進(jìn)程切換分析之——TLB處理

文章出處:【微信公眾號(hào):Linuxer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11337

    瀏覽量

    226009

原文標(biāo)題:郭?。?進(jìn)程切換分析之——TLB處理

文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    遠(yuǎn)程協(xié)作新范式:工業(yè)場(chǎng)景的專家支持技術(shù)演進(jìn)

    遠(yuǎn)程協(xié)作新范式:工業(yè)場(chǎng)景的專家支持技術(shù)演進(jìn) 當(dāng)設(shè)備現(xiàn)場(chǎng)出現(xiàn)故障無(wú)法解決時(shí),如何快速獲取專家指導(dǎo)?這曾是困擾制造業(yè)、能源、工程機(jī)械等重資產(chǎn)行業(yè)的普遍難題。傳統(tǒng)模式,企業(yè)要么派遣專家長(zhǎng)途跋涉,要么
    發(fā)表于 04-30 09:54

    電流探頭在特殊測(cè)量場(chǎng)景的應(yīng)用技巧

    文章總結(jié):電流探頭在特殊測(cè)量場(chǎng)景中需關(guān)注帶寬、噪聲、恢復(fù)時(shí)間及熱管理,以確保測(cè)量準(zhǔn)確性和設(shè)備安全。
    的頭像 發(fā)表于 04-17 09:23 ?302次閱讀

    特殊應(yīng)用場(chǎng)景電流互感器的選型與工程實(shí)踐

    系統(tǒng)闡述電流互感器在特殊應(yīng)用場(chǎng)景的技術(shù)特點(diǎn)、選型要點(diǎn)和工程實(shí)踐,為相關(guān)領(lǐng)域的設(shè)計(jì)、建設(shè)和運(yùn)維提供技術(shù)參考。 二、直流系統(tǒng)電流測(cè)量應(yīng)用 2.1 直流系統(tǒng)特點(diǎn) 直流系統(tǒng)廣泛應(yīng)用于: 軌道交通 :地鐵、高鐵牽引供電 數(shù)據(jù)中心
    的頭像 發(fā)表于 01-29 14:05 ?411次閱讀

    PCB拼板三大細(xì)節(jié)要點(diǎn)

    ,但不少工程師在下單時(shí)容易忽略填寫【拼版款數(shù)】參數(shù),導(dǎo)致出現(xiàn)生產(chǎn)偏差。 錯(cuò)誤場(chǎng)景: 拼板包含多款不同單板(單PCS資料不一致),但下單時(shí)忽略填寫【拼版款數(shù)= X】,而廠商工程未能準(zhǔn)確發(fā)現(xiàn)多拼版意圖
    發(fā)表于 01-23 14:00

    工業(yè)電子EMC整改:工業(yè)場(chǎng)景90%工程師踩過(guò)的雷區(qū)

    工業(yè)電子EMC整改:工業(yè)場(chǎng)景90%工程師踩過(guò)的雷區(qū)|深圳南柯電子
    的頭像 發(fā)表于 12-16 10:07 ?477次閱讀

    如何確定特定應(yīng)用場(chǎng)景電能質(zhì)量在線監(jiān)測(cè)裝置的最佳校準(zhǔn)提醒周期?

    確定特定應(yīng)用場(chǎng)景電能質(zhì)量在線監(jiān)測(cè)裝置的最佳校準(zhǔn)提醒周期,核心邏輯是 “基準(zhǔn)周期 + 場(chǎng)景修正因子” 結(jié)合,兼顧精度要求、環(huán)境影響、運(yùn)維成本與行業(yè)標(biāo)準(zhǔn),最終實(shí)現(xiàn) “數(shù)據(jù)準(zhǔn)確 + 成本最優(yōu)” 的平衡
    的頭像 發(fā)表于 12-12 15:10 ?418次閱讀
    如何確定特定應(yīng)用<b class='flag-5'>場(chǎng)景</b><b class='flag-5'>下</b>電能質(zhì)量在線監(jiān)測(cè)裝置的最佳校準(zhǔn)提醒周期?

    場(chǎng)景向——CD7377CZ/CD7388場(chǎng)景適配全解析:通勤、改裝、商用各選對(duì)款

    不同用車場(chǎng)景對(duì)功放芯片的需求天差地別:日常通勤追求“省電+細(xì)膩”,專業(yè)改裝追求“功率+動(dòng)態(tài)”,商用車型追求“穩(wěn)定+抗造”。今天結(jié)合實(shí)測(cè),拆解華潤(rùn)微CD7377CZ與CD7388在不同場(chǎng)景的適配性
    發(fā)表于 12-11 11:04

    CPU的幾種復(fù)位方式適合哪些場(chǎng)景?

    1、上電復(fù)位 適用場(chǎng)景:系統(tǒng)首次上電或電源以外斷電后重新上電時(shí); 2、看門狗復(fù)位 適用場(chǎng)景:虛脫程序運(yùn)行異常,如陷入死循環(huán)或長(zhǎng)時(shí)間無(wú)響應(yīng)時(shí); 3、軟件復(fù)位 適用場(chǎng)景:軟件程序需重啟或重新初始化
    發(fā)表于 11-27 07:56

    哪些場(chǎng)景適合使用DMA?

    DMA(直接內(nèi)存訪問(wèn))控制器允許外設(shè)和內(nèi)存之間或內(nèi)存和內(nèi)存之間直接傳輸數(shù)據(jù),而無(wú)需CPU的參與。這可以大大減輕CPU的負(fù)擔(dān),讓CPU去處理其他任務(wù),從而提高系統(tǒng)效率。以下是一些常見(jiàn)的使用DMA的
    發(fā)表于 11-12 07:13

    TDD+FDD場(chǎng)景的濾波要求

    在TDD+FDD混合場(chǎng)景,濾波器的設(shè)計(jì)需兼顧兩種雙工模式的特點(diǎn),以滿足系統(tǒng)對(duì)信號(hào)隔離、抗干擾和性能穩(wěn)定性的要求。以下是關(guān)鍵的濾波要求:希望以上內(nèi)容對(duì)您有所幫助
    的頭像 發(fā)表于 11-05 17:33 ?816次閱讀
    TDD+FDD<b class='flag-5'>場(chǎng)景</b><b class='flag-5'>下</b>的濾波要求

    國(guó)產(chǎn)AI芯片真能扛住“算力內(nèi)卷”?海思昇騰的這波操作藏了多少細(xì)節(jié)?

    反而壓到了310W。更有意思的是它的異構(gòu)架構(gòu):NPU+CPU+DVPP的組合,居然能同時(shí)扛住訓(xùn)練和推理場(chǎng)景,之前做自動(dòng)駕駛算法時(shí),用它跑模型時(shí)延直接降了20%。 但疑惑也有:這種算力密度,散熱怎么解決?而且昇騰的生態(tài)適配速度能
    發(fā)表于 10-27 13:12

    無(wú)引導(dǎo)線的左轉(zhuǎn)場(chǎng)景,自動(dòng)駕駛?cè)绾我?guī)劃軌跡?

    場(chǎng)景,想要很好地處理好無(wú)引導(dǎo)線左轉(zhuǎn)是一個(gè)非常大的挑戰(zhàn)。但想要讓自動(dòng)駕駛汽車滿足所有的出行需求,這一場(chǎng)景必須解決,那在無(wú)引導(dǎo)線的左轉(zhuǎn)場(chǎng)景,
    的頭像 發(fā)表于 09-18 09:12 ?936次閱讀
    無(wú)引導(dǎo)線的左轉(zhuǎn)<b class='flag-5'>場(chǎng)景</b><b class='flag-5'>下</b>,自動(dòng)駕駛?cè)绾我?guī)劃軌跡?

    CPU 到 GPU,渲染技術(shù)如何重塑游戲、影視與設(shè)計(jì)?

    渲染技術(shù)是計(jì)算機(jī)圖形學(xué)的核心內(nèi)容之一,它是將三維場(chǎng)景轉(zhuǎn)換為二維圖像的過(guò)程。渲染技術(shù)一直在不斷演進(jìn),從最初的CPU渲染到后來(lái)的GPU渲染,性能和質(zhì)量都有了顯著提升。從CPU到GPU:技術(shù)特點(diǎn)和優(yōu)缺點(diǎn)
    的頭像 發(fā)表于 09-01 12:16 ?1164次閱讀
    從 <b class='flag-5'>CPU</b> 到 GPU,渲染技術(shù)如何重塑游戲、影視與設(shè)計(jì)?

    單核CPU網(wǎng)關(guān)和雙核CPU網(wǎng)關(guān)有什么區(qū)別

    單核CPU網(wǎng)關(guān)與雙核CPU網(wǎng)關(guān)的核心區(qū)別在于處理能力、多任務(wù)效率、性能表現(xiàn)及適用場(chǎng)景,雙核CPU網(wǎng)關(guān)在多任務(wù)處理、復(fù)雜計(jì)算和響應(yīng)速度上具有顯著優(yōu)勢(shì),而單核
    的頭像 發(fā)表于 07-05 14:37 ?1352次閱讀

    哪些場(chǎng)景使用FTP網(wǎng)線比較合適

    FTP屏蔽雙絞線(鋁箔總屏蔽雙絞線)在電磁干擾可控但需兼顧成本與性能的場(chǎng)景中具有顯著優(yōu)勢(shì),以下從技術(shù)特性與場(chǎng)景需求匹配角度,分析其適用場(chǎng)景及核心原因: 一、FTP的核心優(yōu)勢(shì)與適用場(chǎng)景
    的頭像 發(fā)表于 05-06 11:00 ?1001次閱讀
    宣化县| 绿春县| 台东市| 揭阳市| 德令哈市| 新源县| 修文县| 淮安市| 淮阳县| 河南省| 威宁| 峡江县| 珲春市| 潼南县| 页游| 黑龙江省| 驻马店市| 张掖市| 东方市| 江华| 辽源市| 洛阳市| 辉县市| 闽清县| 宜阳县| 荥阳市| 大悟县| 连州市| 越西县| 萝北县| 本溪市| 乐清市| 神池县| 河北省| 嘉黎县| 离岛区| 堆龙德庆县| 南阳市| 尼勒克县| 滨海县| 隆回县|