日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
loongarch架構(gòu)介紹—(五)TLB維護(hù)

??想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):??

成都創(chuàng)新互聯(lián)公司總部坐落于成都市區(qū),致力網(wǎng)站建設(shè)服務(wù)有網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站維護(hù)、公眾號(hào)搭建、小程序設(shè)計(jì)、軟件開(kāi)發(fā)等為企業(yè)提供一整套的信息化建設(shè)解決方案。創(chuàng)造真正意義上的網(wǎng)站建設(shè),為互聯(lián)網(wǎng)品牌在互動(dòng)行銷(xiāo)領(lǐng)域創(chuàng)造價(jià)值而不懈努力!

?? 開(kāi)源基礎(chǔ)軟件社區(qū)??

??https://ost.51cto.com??

前言

上一篇文章中介紹了loongarch中TLB相關(guān)的異常處理,這一篇文章繼續(xù)介紹TLB相關(guān)的維護(hù)操作。

1、TLB硬件組織機(jī)構(gòu)

首先補(bǔ)充loongarch中TLB相關(guān)的硬件背景知識(shí)。

loongarch架構(gòu)中,TLB分為兩個(gè)部分:一個(gè)是所有表項(xiàng)的頁(yè)大小都相同的Singular-Page-Size TLB,簡(jiǎn)稱(chēng)STLB;一個(gè)是支持不同表項(xiàng)的頁(yè)大小可以不同的Multiple-Page-Size TLB,簡(jiǎn)稱(chēng)MTLB。在進(jìn)行虛實(shí)地址轉(zhuǎn)換時(shí),STLB和MTLB同時(shí)查找。同時(shí)軟件上需保證不會(huì)出現(xiàn)MTLB和STLB同時(shí)命中的情況。

STLB和MTLB的表項(xiàng)格式基本一致,區(qū)別僅在于MTLB每個(gè)表項(xiàng)中均包含了一個(gè)頁(yè)大小的信息,而STLB每個(gè)表項(xiàng)中無(wú)此信息。

回顧上一篇文章中介紹了的TLB表項(xiàng)格式:

其中PS(page size)域僅存在于MTLB。

2、虛擬內(nèi)存系統(tǒng)與硬件維護(hù)

虛擬地址空間的引入為程序提供了方便,但同時(shí)也帶來(lái)了其他問(wèn)題。

其中,有一種稱(chēng)為homonym的問(wèn)題,其指的是單個(gè)虛擬地址指向多個(gè)物理地址的情況。例如,在多個(gè)進(jìn)程中使用了相同的虛擬地址,但這些虛擬地址實(shí)際上指向了不同的物理地址。當(dāng)進(jìn)程切換、虛擬地址空間切換、頁(yè)表修改等情況時(shí),硬件上的緩存數(shù)據(jù)不一定會(huì)自動(dòng)進(jìn)行同步,此時(shí)就會(huì)有數(shù)據(jù)不一致的問(wèn)題。

因此,操作系統(tǒng)在軟件上需要手動(dòng)去維護(hù)相關(guān)的硬件數(shù)據(jù)一致性:

  • TLB維護(hù):TLB中緩存的頁(yè)表項(xiàng)就有可能因?yàn)檐浖蠈?duì)頁(yè)表的修改,出現(xiàn)數(shù)據(jù)不一致的問(wèn)題。操作系統(tǒng)需要進(jìn)行invalidate(或者稱(chēng)為flush)TLB的操作,將相應(yīng)的表項(xiàng)無(wú)效。
  • cache維護(hù):某些類(lèi)型的cache也可能會(huì)因頁(yè)表的修改,出現(xiàn)數(shù)據(jù)不一致的問(wèn)題。對(duì)于這些cache,操作系統(tǒng)同樣需要進(jìn)行clean或invalidate操作。

(1)TLB維護(hù)與ASID

在一些早期的架構(gòu)中,invalidate TLB操作實(shí)際上是將整個(gè)TLB中的數(shù)據(jù)無(wú)效,因?yàn)門(mén)LB因homonym問(wèn)題無(wú)法判斷其緩存的表項(xiàng)屬于哪個(gè)進(jìn)程。

但實(shí)際上,刷新整個(gè)TLB的數(shù)據(jù)是一件相當(dāng)浪費(fèi)性能的事,既會(huì)影響上下文切換時(shí)的速度,也會(huì)降低TLB加速的作用。因此,后來(lái)的架構(gòu)一般都會(huì)在TLB中加入其他標(biāo)識(shí)以識(shí)別不同的進(jìn)程或者虛擬地址空間,這樣TLB不需要每次切換上下文都進(jìn)行invalidate操作。

ASID(Address Space ID)就是這樣的標(biāo)識(shí)。loongarch中支持ASID,見(jiàn)上文中TLB表項(xiàng)圖,其中就有ASID域。每個(gè)TLB表項(xiàng)都有ASID,ASID由操作系統(tǒng)在軟件上進(jìn)行分配,一般一個(gè)虛擬地址空間有一個(gè)唯一的ASID,這樣就有效減少了TLB invalidate操作的次數(shù)。

loongarch中,CSR.ASID寄存器可以控制當(dāng)前TLB使用的ASID,如下圖:

同時(shí)loongarch中TLB相關(guān)維護(hù)指令也支持根據(jù)ASID,只無(wú)效部分ASID匹配的表項(xiàng)。見(jiàn)后文介紹。

(2)cache維護(hù)

相較于cache維護(hù),TLB相關(guān)的維護(hù)是本文著重介紹的內(nèi)容。主要是因?yàn)槟壳發(fā)oongarch中cache相關(guān)的資料較少。

一般來(lái)說(shuō),在上下文切換、頁(yè)表修改等情況時(shí),是否需要在軟件上對(duì)cache進(jìn)行維護(hù),與具體的架構(gòu)和cache類(lèi)型有關(guān)。以ARM架構(gòu)為例,其中VIVT類(lèi)型的cache在涉及頁(yè)表切換等操作時(shí)需要進(jìn)行維護(hù)。

3、TLB相關(guān)維護(hù)指令

  • tlbclr:tlbclr指令根據(jù)TLB相關(guān)CSR中的信息無(wú)效TLB中的內(nèi)容。
  • 當(dāng)CSR.TLBIDX.Index落在MTLB范圍內(nèi)時(shí),執(zhí)行tlbclr,將MTLB中所有G=0且ASID等于CSR.ASID.ASID的表項(xiàng)無(wú)效。其中G、ASID為表項(xiàng)中的域。
  • 當(dāng)CSR.TLBIDX.Index落在STLB范圍內(nèi)時(shí),執(zhí)行tlbclr,將STLB中CSR.TLBIDX.Index對(duì)應(yīng)的且G=0且ASID等于CSR.ASID.ASID的表項(xiàng)無(wú)效。
  • tlbflush:tlbflush指令同樣根據(jù)TLB相關(guān)CSR中的信息無(wú)效TLB中的內(nèi)容,但作用范圍較tlbclr指令更廣。
  • 當(dāng)CSR.TLBIDX.Index落在MTLB范圍內(nèi)時(shí),執(zhí)行tlbflush,將MTLB中所有的表項(xiàng)無(wú)效。
  • 當(dāng)CSR.TLBIDX.Index落在STLB范圍內(nèi)時(shí),執(zhí)行tlbflush,將STLB中CSR.TLBIDX.Index對(duì)應(yīng)的表項(xiàng)無(wú)效。
  • invtlb op, rj, rk:invtlb指令同樣用于無(wú)效TLB中的內(nèi)容,但相較于tlbclr和tlbflush指令更加靈活。
  • op表示操作類(lèi)型,下面是loongarch手冊(cè)中列出的op類(lèi)型:
  • op=0:清除所有表項(xiàng)。
  • op=1:清除所有表項(xiàng)。效果和op=0完全一致。
  • op=2:清除所有G=1的表項(xiàng)。
  • op=3:清除所有G=0的表項(xiàng)。
  • op=4:清除所有G=0,且ASID等于寄存器指定ASID的表項(xiàng)。
  • op=5:清除所有G=0,ASID等于寄存器指定ASID,且VA等于寄存器指定VA的表項(xiàng)。
  • op=6:清除所有G=1或ASID等于寄存器指定ASID,且VA等于寄存器指定VA的表項(xiàng)。
  • 通用寄存器rj中存放ASID信息。當(dāng)op對(duì)應(yīng)的操作不需要ASID時(shí),rj應(yīng)設(shè)置為r0。
  • 通用寄存器rk中存放VA虛擬地址信息。當(dāng)op對(duì)應(yīng)的操作不需要VA時(shí),rk應(yīng)設(shè)置為r0。

下面用linux中l(wèi)oongarch下TLB flush相關(guān)API對(duì)invtlb指令舉例說(shuō)明。

注:目前l(fā)oongarch手冊(cè)中的op操作類(lèi)型似乎不全。

// invtlb指令中的op
enum invtlb_ops {
/* Invalid all tlb */
INVTLB_ALL = 0x0,
/* Invalid current tlb */
INVTLB_CURRENT_ALL = 0x1,
/* Invalid all global=1 lines in current tlb */
INVTLB_CURRENT_GTRUE = 0x2,
/* Invalid all global=0 lines in current tlb */
INVTLB_CURRENT_GFALSE = 0x3,
/* Invalid global=0 and matched asid lines in current tlb */
INVTLB_GFALSE_AND_ASID = 0x4,
/* Invalid addr with global=0 and matched asid in current tlb */
INVTLB_ADDR_GFALSE_AND_ASID = 0x5,
/* Invalid addr with global=1 or matched asid in current tlb */
INVTLB_ADDR_GTRUE_OR_ASID = 0x6,
/* Invalid matched gid in guest tlb */
INVGTLB_GID = 0x9,
/* Invalid global=1, matched gid in guest tlb */
INVGTLB_GID_GTRUE = 0xa,
/* Invalid global=0, matched gid in guest tlb */
INVGTLB_GID_GFALSE = 0xb,
/* Invalid global=0, matched gid and asid in guest tlb */
INVGTLB_GID_GFALSE_ASID = 0xc,
/* Invalid global=0 , matched gid, asid and addr in guest tlb */
INVGTLB_GID_GFALSE_ASID_ADDR = 0xd,
/* Invalid global=1 , matched gid, asid and addr in guest tlb */
INVGTLB_GID_GTRUE_ASID_ADDR = 0xe,
/* Invalid all gid gva-->gpa guest tlb */
INVGTLB_ALLGID_GVA_TO_GPA = 0x10,
/* Invalid all gid gpa-->hpa tlb */
INVTLB_ALLGID_GPA_TO_HPA = 0x11,
/* Invalid all gid tlb, including gva-->gpa and gpa-->hpa */
INVTLB_ALLGID = 0x12,
/* Invalid matched gid gva-->gpa guest tlb */
INVGTLB_GID_GVA_TO_GPA = 0x13,
/* Invalid matched gid gpa-->hpa tlb */
INVTLB_GID_GPA_TO_HPA = 0x14,
/* Invalid matched gid tlb,including gva-->gpa and gpa-->hpa */
INVTLB_GID_ALL = 0x15,
/* Invalid matched gid and addr gpa-->hpa tlb */
INVTLB_GID_ADDR = 0x16,
};
/*
* invtlb op info addr
* (0x1 << 26) | (0x24 << 20) | (0x13 << 15) |
* (addr << 10) | (info << 5) | op
*/
// 基于機(jī)器碼封裝了invtlb op info addr格式的指令
static inline void invtlb(u32 op, u32 info, u64 addr)
{
__asm__ __volatile__(
"parse_r addr,%0\n\t"
"parse_r info,%1\n\t"
".word ((0x6498000) | (addr << 10) | (info << 5) | %2)\n\t"
:
: "r"(addr), "r"(info), "i"(op)
:
);
}
// invtlb op 0 0指令
static inline void invtlb_all(u32 op, u32 info, u64 addr)
{
__asm__ __volatile__(
".word ((0x6498000) | (0 << 10) | (0 << 5) | %0)\n\t"
:
: "i"(op)
:
);
}

4、上下文切換和TLB維護(hù)

本節(jié)結(jié)合linux中上下文切換部分代碼對(duì)TLB invalidate操作進(jìn)行分析。

以下為linux中context_switch上下文切換函數(shù)的流程:

context_switch(struct rq *rq, struct task_struct *prev,
| struct task_struct *next)
| // 更新時(shí)間片、最近進(jìn)隊(duì)時(shí)間等調(diào)度信息以及其他準(zhǔn)備工作
|-> prepare_task_switch(rq, prev, next);
|
| // 虛擬地址空間切換相關(guān)
|-> mm = next->mm;
| oldmm = prev->active_mm;
| if (!mm) {
| next->active_mm = oldmm;
| atomic_inc(&oldmm->mm_count); // 增加oldmm的引用計(jì)數(shù)
| // 其他架構(gòu)(x86)相關(guān),這里不關(guān)注
| enter_lazy_tlb(oldmm, next);
| } else
| // 切換到用戶(hù)進(jìn)程,需切換進(jìn)程虛擬空間
| switch_mm(oldmm, mm, next);
|
|-> ...
|
| // 切換任務(wù)上下文
|-> switch_to(prev, next, prev);
| // 切換后再次被調(diào)度時(shí)向下執(zhí)行
|
| // 用barrier機(jī)制同步,
| // 保證switch_to和finish_task_switch的執(zhí)行順序
|-> barrier();
| // 使用gcc內(nèi)聯(lián)匯編:::"memory"語(yǔ)法實(shí)現(xiàn),
| // 這樣編譯器不會(huì)優(yōu)化此語(yǔ)句前后的訪(fǎng)存順序
|-> #define barrier() __asm__ __volatile__("": : :"memory")
|
| // 再次被調(diào)度時(shí),進(jìn)行清理工作
|-> finish_task_switch(this_rq(), prev);

在進(jìn)行任務(wù)上下文切換函數(shù)switch_to之前,如果涉及進(jìn)程虛擬地址空間改變,則需要切換mmu上下文。上面switch_mm函數(shù)的作用就是切換mmu上下文。

loongarch架構(gòu)代碼中switch_mm及相關(guān)函數(shù)的分析如下:

switch_mm(struct mm_struct *prev, struct mm_struct *next,
| struct task_struct *tsk)
|-> switch_mm_irqs_off(prev, next, tsk);
|-> unsigned int cpu = smp_processor_id();
|
| /* Check if our ASID is of an older version and thus invalid */
| // 如果asid不同,則需重新分配
|-> if (!asid_valid(next, cpu))
| get_new_mmu_context(next, cpu);
|
| // 寫(xiě)入asid到寄存器CSR.ASID
|-> write_csr_asid(cpu_asid(cpu, next));
|
| // 切換頁(yè)表
|-> if (next != &init_mm)
| csr_writeq((unsigned long)next->pgd, LOONGARCH_CSR_PGDL);
| else
| csr_writeq((unsigned long)invalid_pg_dir, LOONGARCH_CSR_PGDL);
|
|-> ...

#define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
#define asid_cache(cpu) (cpu_data[cpu].asid_cache)
static inline int asid_valid(struct mm_struct *mm, unsigned int cpu)
{
// 如果mm中的asid和當(dāng)前asid_cache不同,則返回?zé)o效
if ((cpu_context(cpu, mm) ^ asid_cache(cpu)) & asid_version_mask(cpu))
return 0;

return 1;
}

static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
{
| // 循環(huán)遞增地分配新的asid,為舊的asid_cache + 1
|-> u64 asid = asid_cache(cpu);
| if (!((++asid) & cpu_asid_mask(&cpu_data[cpu])))
| // 當(dāng)asid溢出時(shí)開(kāi)始新的分配循環(huán),此時(shí)需刷新TLB中所有用戶(hù)部分
| local_flush_tlb_user(); /* start new asid cycle */
|
| // 將mm中asid和當(dāng)前asid_cache設(shè)為新分配的asid
|-> cpu_context(cpu, mm) = asid_cache(cpu) = asid;
}

其中,switch_mm函數(shù)主要完成兩個(gè)任務(wù):

  • 維護(hù)TLB:如前文所述,loongarch中上下文切換時(shí)需要維護(hù)TLB數(shù)據(jù)一致性。在上面的代碼中,是結(jié)合ASID進(jìn)行實(shí)現(xiàn):
  • 每次檢測(cè)ASID是否變化,如果變化則說(shuō)明虛擬地址空間需要進(jìn)行切換,CSR.ASID寄存器需要重新設(shè)置
  • 上面代碼實(shí)現(xiàn)中是通過(guò)循環(huán)遞增的方式分配新的ASID,當(dāng)ASID溢出時(shí)需要使用invalidate TLB操作來(lái)保證數(shù)據(jù)一致性
  • 切換頁(yè)表:不同的用戶(hù)虛擬地址空間有不同的頁(yè)表,需通過(guò)設(shè)置相關(guān)寄存器進(jìn)行切換。頁(yè)表相關(guān)的配置可參考前面的文章。

上面的asid_valid函數(shù)檢測(cè)ASID是否變化,get_new_mmu_context函數(shù)負(fù)責(zé)重新分配ASID和ASID溢出時(shí)調(diào)用local_flush_tlb_user函數(shù)進(jìn)行invalidate TLB操作。

local_flush_tlb_user函數(shù)分析如下:

local_flush_tlb_user(void)
| // 刷新所有g(shù)lobal=0的TLB表項(xiàng)
|-> invtlb_all(INVTLB_CURRENT_GFALSE, 0, 0);

另外,上面代碼中ASID管理部分可以進(jìn)一步改進(jìn),因?yàn)槊看螜z測(cè)到ASID變化后,mm結(jié)構(gòu)體被設(shè)置了一個(gè)新分配的ASID,這樣實(shí)際上未能利用mm結(jié)構(gòu)體中原來(lái)的ASID和TLB中對(duì)應(yīng)緩存數(shù)據(jù)。

總結(jié)

本文介紹了TLB維護(hù)操作和相關(guān)指令,并結(jié)合linux中代碼進(jìn)行了分析。這篇文章之后,本系列文章暫時(shí)告一段落。主要是目前l(fā)oongarch相關(guān)的資料有限,描述二進(jìn)制翻譯擴(kuò)展等擴(kuò)展內(nèi)容的loongarch手冊(cè)第二、三卷也還沒(méi)有出。

最后,在查詢(xún)loongarch資料(主要是基于龍芯手冊(cè)第一卷1.02和linux中l(wèi)oongarch部分源碼)的過(guò)程中也發(fā)現(xiàn)了一些不足點(diǎn)或者是不夠詳細(xì)的地方,這里一并列出:

  • 指令的介紹有信息遺漏:如第一篇文章中列出的一部分手冊(cè)上沒(méi)有,但在代碼中出現(xiàn)的move等指令;又如前文中的invtlb指令中的op操作類(lèi)型相比代碼中缺少一些
  • 內(nèi)存一致性模型,內(nèi)存訪(fǎng)存類(lèi)型的信息不夠詳細(xì):第二篇文章中提到了這點(diǎn),如手冊(cè)中出現(xiàn)的一致可緩存等術(shù)語(yǔ)沒(méi)有解釋
  • 中斷機(jī)制相關(guān)信息不夠詳細(xì)
  • cache相關(guān)信息不夠詳細(xì)

??想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):??

?? 開(kāi)源基礎(chǔ)軟件社區(qū)??

??https://ost.51cto.com??


本文標(biāo)題:loongarch架構(gòu)介紹—(五)TLB維護(hù)
URL地址:http://www.dlmjj.cn/article/coehoij.html