ARM體系架構(gòu)——MMU

一、前言

嵌入式Linux 開發(fā)中,往往會(huì)聽到 MMU 這個(gè)詞,但大多數(shù)情況下并不會(huì)去了解它,因?yàn)椴僮飨到y(tǒng)已經(jīng)做好了關(guān)于 MMU 的一切操作,我們只需要在操作系統(tǒng)的框架下直接使用即可。但了解 MMU 有助于幫助我們理解操作系統(tǒng),理解進(jìn)程等,讓我們對(duì) 嵌入式Linux 的理解上升一個(gè)層次。本文將簡(jiǎn)單地講述一下關(guān)于 MMU 的基本信息。

注意:本文將按照ARMv7的二級(jí)頁(yè)表映射進(jìn)行講述

二、MMU

2.1 MMU基本信息

MMU 全稱為 Memory Management Unit,即 內(nèi)存管理單元。在 帶有MMU的嵌入式Linux 中,CPU 訪問(wèn)的地址都是 虛擬地址,而 MMU 負(fù)責(zé)將程序中 代碼或數(shù)據(jù)虛擬地址 翻譯為 物理地址,以便程序訪問(wèn)內(nèi)存。

在執(zhí)行操作時(shí),MMU 會(huì)自動(dòng)轉(zhuǎn)換 CPU發(fā)出的虛擬地址,無(wú)法人工進(jìn)行操作,只需要配置好 MMU 相關(guān)屬性即可。

虛擬地址 是在 編譯和鏈接 時(shí)定義的,可以簡(jiǎn)單地理解為 由鏈接器和鏈接器腳本 指定虛擬地址。
除了 翻譯虛擬地址,MMU 還可以配置 內(nèi)存區(qū)域 的各項(xiàng)配置,如內(nèi)存區(qū)域的訪問(wèn)權(quán)限,內(nèi)存區(qū)域是否使能cache等功能。
總結(jié) MMU 的功能,如下:

  • 翻譯虛擬地址
  • 配置內(nèi)存區(qū)域的相關(guān)屬性

2.2 MMU基本概念

看到 MMU 的相關(guān)文章時(shí),總會(huì)提及幾個(gè)概念如 頁(yè)頁(yè)框(頁(yè)幀),頁(yè)表頁(yè)表項(xiàng),TLB等等,下面我們逐個(gè)拆分來(lái)講述。

2.2.1 頁(yè)

MMU 管理 虛擬地址空間 時(shí),是按照 頁(yè) 為單位來(lái)進(jìn)行管理。在 ARMv7MMU ,頁(yè)大小 一共有 16M(Super Section)、1M(Section)64K(Large Page) 4K(Page)。頁(yè)大小 可以通過(guò) 協(xié)處理器CP15 進(jìn)行配置,越小的頁(yè)意味著內(nèi)存的顆粒度越小,內(nèi)存使用時(shí)的浪費(fèi)會(huì)越小,但也意味著使用的TLB行越多。越大的也內(nèi)存的顆粒度月大,內(nèi)存的使用浪費(fèi)也可能月大,但使用的TLB行越少。比如只需要申請(qǐng) 7K 大小的 物理內(nèi)存,如果使用 7K大小 的內(nèi)存,我們可以分配 2 個(gè) 4K頁(yè),如果分配 64K的大頁(yè),則浪費(fèi)的空間就比較大。

2.2.2 頁(yè)框

因?yàn)?虛擬地址空間 需要有所對(duì)應(yīng)的 物理地址,這樣才能在 虛擬地址 中存儲(chǔ)數(shù)據(jù)。所以 MMU 管理 物理地址空間 時(shí),按照 頁(yè)幀 為單位進(jìn)行管理。其大小分為 64K4K。一段 虛擬地址空間 有可能存在著多個(gè) 頁(yè),這些 頁(yè) 對(duì)應(yīng)著多個(gè) 頁(yè)幀。

按照筆者理解,頁(yè)頁(yè)幀不同地址空間下的關(guān)于內(nèi)存空間大小的概念

2.2.3 頁(yè)表及頁(yè)表項(xiàng)

MMU 在進(jìn)行 地址轉(zhuǎn)換 時(shí),需要一些信息,存放這些信息的就是 頁(yè)表。每個(gè) 頁(yè)表 的最小單位就是 頁(yè)表項(xiàng)
頁(yè)表 存儲(chǔ)在 物理地址空間 中,且一個(gè) 頁(yè)表項(xiàng) 對(duì)應(yīng)著一個(gè) 頁(yè)
切換頁(yè)表 時(shí),通過(guò)將 頁(yè)表的物理首地址 設(shè)置到 協(xié)處理器CP15 中的 TTBR寄存器(Translation Table Base Register)。此后 MMU 會(huì)通過(guò)該地址自動(dòng)去 物理地址空間 中找到對(duì)應(yīng)的 頁(yè)表,從而完成 虛擬地址到物理地址的映射

在不考慮 TLB多級(jí)頁(yè)表 的情況下,可以簡(jiǎn)單地如下圖所示:

頁(yè)表及頁(yè)表項(xiàng)

2.2.4 TLB

TLB 全程為 Translation Lookaside Buffer,即 旁路轉(zhuǎn)換緩沖。它是 MMU 的專屬 全相聯(lián)cache,用于臨時(shí)存放 虛擬地址到物理地址映射 所需要的信息。
下面按照步驟說(shuō)明 TLB 的作用:

  1. CPU 訪問(wèn) 虛擬地址MMU。
  2. MMU 根據(jù)規(guī)則(規(guī)則在下文講述)查看 虛擬地址 是否在 TLB 中。
  3. 如果在 TLB 中,則稱為 TLB命中。從 TLB 中直接獲取 物理地址 對(duì)內(nèi)存進(jìn)行訪問(wèn)
  4. 如果不在 TLB 中,則稱為 TLB失效。此時(shí) MMU 將進(jìn)行 translation table walking,即通過(guò) 訪問(wèn)頁(yè)表來(lái)獲取 物理地址。并將該 虛擬地址 的信息存入 TLB,以便下次使用。

值得注意的是:ARM架構(gòu)的TLB只存儲(chǔ)有效的頁(yè)表項(xiàng),對(duì)于無(wú)效的頁(yè)表項(xiàng)TLB并不會(huì)存儲(chǔ)

TLB 由許多 TLB行 組成,如下圖所示:

TLB

TLB行3個(gè) 部分組成,分別為 標(biāo)簽、ASID描述符

  • 標(biāo)簽:該部分由 虛擬地址的一部分bit 組成,MMU 通過(guò)將 虛擬地址的一部分bitTLB 的所有標(biāo)簽對(duì)比進(jìn)行搜索。
  • ASID:全稱為 Address Space ID,一般用于 多進(jìn)程系統(tǒng),下文會(huì)詳細(xì)講述。
  • 描述符:由 2個(gè) 部分組成,分別為 物理地址(一部分bit)內(nèi)存區(qū)域?qū)傩?/strong> 組成??梢岳斫鉃?cache 中的數(shù)據(jù)。

一般情況下,切換 進(jìn)程 時(shí)會(huì)切換 頁(yè)表,因?yàn)殡S著進(jìn)程的切換, 虛擬地址物理地址 的映射已經(jīng)改變。此時(shí)需要 清理TLB(即無(wú)效化TLB中的數(shù)據(jù)) 來(lái)保持 TLB一致性清理TLB 一般通過(guò) 協(xié)處理器CP15 來(lái)完成,在 Linux內(nèi)核 中,有 flush_tlb_all()flush_tlb_range() 函數(shù)來(lái)完成該工作。

2.3 MMU組成

如下圖所示:

MMU組成

MMU 的工作流程可以總結(jié)為下面 2 種情況:

  • 訪問(wèn) 虛擬地址 時(shí),MMU 通過(guò)查找 TLB 來(lái)找出對(duì)應(yīng)的 頁(yè)幀,從而訪問(wèn) 物理地址,如圖中的 頁(yè)1頁(yè)2頁(yè)3。
  • 如果 MMUTLB 中沒(méi)找到對(duì)應(yīng)的 TLB行 時(shí),將進(jìn)行 traslation table working。即從 物理地址空間頁(yè)表中 找出對(duì)應(yīng)的 頁(yè)表項(xiàng),并根據(jù) 頁(yè)表項(xiàng) 找到對(duì)應(yīng)的 物理地址。并將該 頁(yè)表項(xiàng) 更新到 TLB 中,以備下次使用。

2.4 MMU工作過(guò)程

ARMv7 下的 MMU 具有 2級(jí)頁(yè)表,分為 1級(jí)頁(yè)表2級(jí)頁(yè)表。

2.4.1 1級(jí)頁(yè)表

1級(jí)頁(yè)表 也稱 主頁(yè)表段頁(yè)表,下面簡(jiǎn)稱 L1頁(yè)表。它將 4GB 的地址空間劃分為 4096 個(gè) 1MB 大小的 ,每個(gè)段的地址為 32bit。所以 1級(jí)頁(yè)表 擁有 4096 個(gè) 32bit頁(yè)表項(xiàng)

2.4.1.1 一級(jí)頁(yè)表項(xiàng)

L1頁(yè)表 使用了 短描述符頁(yè)表(Short-descriptor translation table),其 頁(yè)表項(xiàng) 具有以下特征:

  • 32bit 的頁(yè)描述符
  • 具有 2級(jí) 以上的 頁(yè)表
  • 支持 32bit物理地址
  • 支持 4種 內(nèi)存大?。?
    • 16MB/1M,稱為
    • 64KB/4KB,稱為 頁(yè)

在前面說(shuō)了 TTBR寄存器 是存放 頁(yè)表物理地址 的寄存器,需要注意的是:存放在TTBR寄存器的地址需要16KB對(duì)齊

一級(jí)頁(yè)表項(xiàng) 一共有 4種 格式,如下圖所示:

一級(jí)頁(yè)表項(xiàng)格式

每種格式都由 物理地址部分+屬性部分 組成,可以直接在圖中看出 物理地址部分 的示意,這里不多贅述。各種格式的含義如下:

  1. 1MB段轉(zhuǎn)換頁(yè)表項(xiàng)(Section) ,映射到 1MB 的物理地址范圍。其 物理地址部分 即為所需要映射的 物理基地址
  2. 物理地址部分 指向 2級(jí)頁(yè)表物理基地址。
  3. 16MB段(SuperSection) 轉(zhuǎn)換頁(yè)表項(xiàng),是一種特殊的 1MB段轉(zhuǎn)換頁(yè)表項(xiàng)。其 物理地址部分 即為所需要映射的 物理基地址。
  4. 無(wú)效頁(yè)表項(xiàng),當(dāng)訪問(wèn)該頁(yè)表項(xiàng)時(shí),將觸發(fā) 指令取指異常取數(shù)據(jù)異常

下面簡(jiǎn)單說(shuō)下各個(gè)字段的含義:

  • Ignored:忽略
  • Level 2 Descriptor Base Address二級(jí)頁(yè)表物理基地址
  • Section Base Address1MB段基地址
  • Supersection Base Address16MB段基地址
  • SBZ:全稱 should be zero,無(wú)效屬性字段
  • AP:全稱 Access Permissions,內(nèi)存區(qū)域訪問(wèn)權(quán)限
  • Domain:用于權(quán)限控制,下文講述。
  • TEX:全稱 Type extension,設(shè)置內(nèi)存區(qū)域類型
  • B:全稱 Bufferable,是否設(shè)置 寫緩沖
  • C:全稱 Cacheable,是否設(shè)置 cache
  • nG:全稱 non-Global。如果 頁(yè)表項(xiàng)的nGbit 被設(shè)置,那么該 頁(yè)表項(xiàng) 對(duì)應(yīng)的 內(nèi)存區(qū)域 將只能被 特定的進(jìn)程 使用。當(dāng)MMU 使用該 頁(yè)表項(xiàng) 進(jìn)行映射時(shí),也需要使用到 ASID。
  • S:全稱 Shareable,共享設(shè)置項(xiàng)。
  • bit[18]:該 bit 決定 段頁(yè)表項(xiàng)1MB頁(yè)表項(xiàng) 還是 16MB頁(yè)表項(xiàng)。
  • bit[1:0]:這 2個(gè)bit 決定頁(yè)表項(xiàng)的類型,如下:
    • 00無(wú)效頁(yè)表項(xiàng)
    • 01轉(zhuǎn)換表頁(yè)表項(xiàng)
    • 10段頁(yè)表項(xiàng)

2.4.1.2 一級(jí)頁(yè)轉(zhuǎn)換

1MB段 舉例,假設(shè) L1頁(yè)表 的物理地址為 0x12300000,現(xiàn)在有一個(gè)虛擬地址 0x00100000。其轉(zhuǎn)換過(guò)程如圖所示:

查表過(guò)程

轉(zhuǎn)換過(guò)程

  1. 查表過(guò)程:將 虛擬地址高12bit,即0x001 乘以 4 得到 0x0040x004 即為 該虛擬地址所在段的頁(yè)表項(xiàng)在頁(yè)表中的偏移,所以 該虛擬地址對(duì)應(yīng)的頁(yè)表項(xiàng)的物理地址為0x12300000+0x004=0x12300004。
  2. 根據(jù)查到的 頁(yè)表項(xiàng),將 頁(yè)表項(xiàng)高12bit虛擬地址低30bit 結(jié)合,即為 該虛擬地址在該1MB段內(nèi)的物理地址

值得注意的是:例子中,高12位一共是4096個(gè)頁(yè)表項(xiàng),那么4096x4一共是16384字節(jié)的大小,因?yàn)槊總€(gè)頁(yè)表項(xiàng)是32位。所以4096個(gè)頁(yè)表項(xiàng)需要16K大小的內(nèi)存來(lái)存儲(chǔ)頁(yè)表。也是因?yàn)槿绱?,每個(gè)虛擬地址的高12bit都需要乘以4.

下圖為例子的完整轉(zhuǎn)換過(guò)程,其余類型的 頁(yè)表項(xiàng) 轉(zhuǎn)換過(guò)程類似、

L1轉(zhuǎn)換完整過(guò)程

2.4.2 二級(jí)頁(yè)表

2級(jí)頁(yè)表 一共有 256 個(gè) 4字節(jié)大小頁(yè)表項(xiàng),總共占據(jù) 1KB大小 的內(nèi)存空間。L2頁(yè)表 的大部分內(nèi)容與 L1頁(yè)表 類似,相同部分下文將不再贅述

2.4.2 二級(jí)頁(yè)表項(xiàng)

二級(jí)頁(yè)表項(xiàng) 一共有 3種 格式,如下圖所示:

二級(jí)頁(yè)表項(xiàng)

每種格式與 L1頁(yè)表項(xiàng) 一樣由 物理地址部分+屬性部分 組成,可以直接在圖中看出 物理地址部分 的示意,格式如下:

2級(jí)頁(yè)表項(xiàng) 具有以下特征:

  1. 粗頁(yè)表項(xiàng): 其 物理地址部分指向 64KB大小物理基地址。
  2. 細(xì)頁(yè)表項(xiàng): 其 物理地址部分指向 4KB大小物理基地址
  3. 無(wú)效頁(yè)表項(xiàng),當(dāng)訪問(wèn)該頁(yè)表項(xiàng)時(shí),將觸發(fā) 指令取指異常取數(shù)據(jù)異常

屬性字段 的含義請(qǐng)參考 1級(jí)頁(yè)表 章節(jié)。

2.4.2 二級(jí)頁(yè)表轉(zhuǎn)換

L2頁(yè)表 的轉(zhuǎn)換過(guò)程與 L1頁(yè)表 的轉(zhuǎn)換過(guò)程一脈相承。以 4KB 為例子,如下圖所示:

image.png

由上圖可以看出其轉(zhuǎn)換步驟如下:

  1. 通過(guò) 虛擬地址 找出 L1頁(yè)表項(xiàng) 并轉(zhuǎn)換為 L2頁(yè)表基地址。
  2. 根據(jù) L2頁(yè)表基地址 并集合 虛擬地址的[19:12]bit 找出 虛擬地址 對(duì)應(yīng)的 L2頁(yè)表項(xiàng)
  3. 虛擬地址[11:0]bitL2頁(yè)表項(xiàng)物理地址部分 結(jié)合得出具體的 物理地址

結(jié)合 L1頁(yè)表 的完整轉(zhuǎn)化過(guò)程如下圖所示:

image.png

2.5 MMU內(nèi)存屬性

2.5.1 內(nèi)存區(qū)域權(quán)限

每個(gè) 內(nèi)存區(qū)域 都有自己的權(quán)限,不符合訪問(wèn)權(quán)限的 內(nèi)存訪問(wèn) 都會(huì)引發(fā) 異常。如果是 數(shù)據(jù)訪問(wèn) 則引發(fā) 數(shù)據(jù)異常。如果是 指令訪問(wèn),且該指令在執(zhí)行前沒(méi)有被 flush,將引發(fā) 預(yù)取指異常。
引發(fā)的 異常原因 將會(huì)被設(shè)置在 CP15the fault address and fault status registers

內(nèi)存區(qū)域權(quán)限APAPXDomain(域) 共同控制,如下:

  • AP/APX:字段 APAPX 的不同組合將形成不同的 訪問(wèn)權(quán)限,如圖所示。按照筆者理解,
    Privileged 指的是 CPU 處于 svc 等狀態(tài),而 Unprivileged 則為 CPU 處于 user 狀態(tài)。
    訪問(wèn)權(quán)限組合表
  • Domain:這是一種 ARM架構(gòu) 不常用的 內(nèi)存全權(quán)限控制 方式。MMU 可以將所有 內(nèi)存區(qū)域 分配到 16個(gè)域 中,每一個(gè) 都有自己的 訪問(wèn)權(quán)限。被分配到 中的 內(nèi)存區(qū)域 必須遵循該 的訪問(wèn)權(quán)限??梢酝ㄟ^(guò)設(shè)置 頁(yè)表項(xiàng) 中的 Domain字段 來(lái)實(shí)現(xiàn) 的分配。
    CP15協(xié)處理器 中有一個(gè) DACR寄存器(Domain Access Control Register),該寄存器為 32bit,每個(gè) 訪問(wèn)權(quán)限2個(gè)bit 設(shè)置,一共設(shè)置 16個(gè)域。 的權(quán)限設(shè)置如下:
    • 不可訪問(wèn)(no-access):對(duì)該 內(nèi)存區(qū)域 進(jìn)行訪問(wèn)將引發(fā) 異常
    • 管理者(Manager mode):訪問(wèn)不受任何控制,不產(chǎn)生 異常
    • 用戶(Client mode):使用 頁(yè)表項(xiàng) 中的 AP/APX字段 進(jìn)行控制

需要注意的是:內(nèi)存區(qū)域控制以域控制為主,頁(yè)表項(xiàng)的AP/APX字段為次。ARMv7不建議使用域進(jìn)行控制,所以建議把DACR寄存器設(shè)置為用戶模式

2.5.2 內(nèi)存類型

ARM架構(gòu) 實(shí)現(xiàn)了 3種內(nèi)存類型,每種類型都是 互斥的,如下:

  • Strongly-ordered
  • Device
  • Normal

每種 類型 的細(xì)節(jié)如下圖所示:

image.png

需要注意的是,Device類型的Shareable內(nèi)存區(qū)域現(xiàn)在已經(jīng)被棄用

內(nèi)存區(qū)域類型 可以通過(guò) TEX字段、C字段B字段 來(lái)進(jìn)行設(shè)置,如下圖所示

image.png

值得注意的是:按照筆者理解,inner cache是L1 cache,而outer cache是指在L1cache下面的cache,比如L2cache

操作系統(tǒng)如何使用頁(yè)表

2.6 進(jìn)程與MMU

操作系統(tǒng) 會(huì)為 每個(gè)進(jìn)程 分配一個(gè) 頁(yè)表,該 頁(yè)表 使用 物理地址 存儲(chǔ)。當(dāng) 進(jìn)程 使用類似 malloc 等需要 映射代碼或數(shù)據(jù) 的操作時(shí),操作系統(tǒng) 會(huì)在隨后馬上 修改頁(yè)表 以加入新的 物理內(nèi)存。當(dāng)進(jìn)程完成退出時(shí),內(nèi)核會(huì)將相關(guān)的頁(yè)表項(xiàng)刪除掉,以便分配給新的進(jìn)程。

2.6.1 Address Space ID

在操作系統(tǒng)中, 多進(jìn)程 是一種常態(tài)。那么多進(jìn)程 的情況下,每次 切換進(jìn)程 都需要進(jìn)行 TLB清理。這樣會(huì)導(dǎo)致切換的效率變低。
為了解決問(wèn)題,TLB 引入了 ASID(Address Space ID) 。ASID 的范圍是 0-255。
ASID 由操作系統(tǒng)分配,當(dāng)前進(jìn)程的ASID值 被寫在 ASID寄存器(使用CP15 c3訪問(wèn))TLB 在更新 頁(yè)表項(xiàng) 時(shí)也會(huì)將 ASID 寫入 TLB。
如果設(shè)置了如果 當(dāng)前進(jìn)程的ASID,那么 MMU 在查找 TLB 時(shí), 只會(huì)查找 TLB 中具有 相同ASID值TLB行。且在切換進(jìn)程是,TLB 中被設(shè)置了 ASIDTLB行 不會(huì)被清理掉,當(dāng)下次切換回來(lái)的時(shí)候還在。所以ASID 的出現(xiàn)使得切換進(jìn)程時(shí)不需要清理 TLB 中的所有數(shù)據(jù),可以大大減少 切換開銷

具體可以看參考鏈接《多核MMU和ASID管理邏輯》

2.6.2 TTBR0和TTBR1

前面講了 TTBR寄存器 是用于存放 頁(yè)表基地址,在 ARmv7 中一共有 2個(gè) 這樣的寄存器,分別是 TTBR0TTBR1。
那么這里提出一個(gè)問(wèn)題:在進(jìn)行 Translation Table walking 的時(shí)候,選擇哪個(gè)TTBR寄存器,又如何選擇?
ARMv7 中,有一個(gè)寄存器為 TTBCR(TTB Control Register),即TTB控制寄存器。TTBCR寄存器 可以被設(shè)置為 0-7 這幾個(gè)值。
在進(jìn)行 地址映射 時(shí), MMU 會(huì)根據(jù) TTBCR寄存器 中的值查看 虛擬地址 是高位地址,根據(jù) 高位地址 選擇對(duì)應(yīng)的 TTBR寄存器。
舉個(gè)例子,假設(shè) TTBCR寄存器 被設(shè)置為 4,則 MMU 會(huì)檢查 虛擬地址高4bit,如果 高4bit 都為 0,則此時(shí)選擇 TTBR0

需要注意的是:TTBCR被設(shè)置為 0 時(shí),默認(rèn)選擇 TTBR0。

下面我們看看使用和不使用 TTBR1 帶來(lái)的影響。

  • 不使用:在 ARM32架構(gòu)的操作系統(tǒng)中,不使用 TTBR1寄存器。此時(shí),用戶空間內(nèi)核空間 共用一個(gè) 頁(yè)表。也就是說(shuō) 用戶空間內(nèi)核空間 都使用 TTBR0 來(lái)記錄 頁(yè)表地址,這樣可以避免一個(gè)問(wèn)題,就是進(jìn)行 用戶空間和內(nèi)核空間的切換時(shí),可以避免切換頁(yè)表帶來(lái)的性能損耗。但與此同時(shí)也帶來(lái)一個(gè)問(wèn)題,用戶空間每個(gè)進(jìn)程 都擁有 內(nèi)核頁(yè)表副本,當(dāng) 內(nèi)核空間頁(yè)表 修改時(shí),所有 進(jìn)程 都需要同步修改其 內(nèi)核頁(yè)表副本。造成一定的性能損失
  • 使用ARM64架構(gòu)的操作系統(tǒng)中虛擬地址空間 非常大。用戶空間內(nèi)核空間 都是 256T。用戶空間地址高位為0,內(nèi)核空間地址高位為1。這樣的特性滿足 TTBR1寄存器 的使用條件。根據(jù) 用戶空間地址內(nèi)核空間地址 的不同,選擇對(duì)應(yīng)的 TTBR寄存器。這樣就不需要為每個(gè) 進(jìn)程 維護(hù)一份 內(nèi)核頁(yè)表副本。

2.6.3 代碼實(shí)例

本小節(jié)簡(jiǎn)單地講述一下 Linux 進(jìn)行 MMU切換 時(shí)的代碼片段。以 ARMv7單核CPU 為例子。
根據(jù)筆者的理解,其調(diào)用圖譜如下:

->switch_mm
  ->check_and_switch_context
    ->cpu_switch_mm(processor.switch_mm)
      ->cpu_v7_switch_mm

筆者會(huì)將簡(jiǎn)單的說(shuō)明注釋在代碼中,不進(jìn)行另外的說(shuō)明。

/* arch/arm/include/asm/mmu_context.h */
static inline void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
      struct task_struct *tsk)
{
#ifdef CONFIG_MMU
    unsigned int cpu = smp_processor_id();

    /*
     * __sync_icache_dcache doesn't broadcast the I-cache invalidation,
     * so check for possible thread migration and invalidate the I-cache
     * if we're new to this CPU.
     */
    /* 這里應(yīng)該是說(shuō)進(jìn)程如果調(diào)度到新的CPU,則需要將該CPU的cache給清理掉 */
    if (cache_ops_need_broadcast() &&
        !cpumask_empty(mm_cpumask(next)) &&
        !cpumask_test_cpu(cpu, mm_cpumask(next)))
        __flush_icache_all();

    if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
        /* 如果調(diào)度的進(jìn)程不是本進(jìn)程,則執(zhí)行check_and_switch_context */
        check_and_switch_context(next, tsk);
        if (cache_is_vivt())
            cpumask_clear_cpu(cpu, mm_cpumask(prev));
    }
#endif
}

static inline void check_and_switch_context(struct mm_struct *mm,
                        struct task_struct *tsk)
{
    if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
        __check_vmalloc_seq(mm);

    if (irqs_disabled())
        /*
         * cpu_switch_mm() needs to flush the VIVT caches. To avoid
         * high interrupt latencies, defer the call and continue
         * running with the old mm. Since we only support UP systems
         * on non-ASID CPUs, the old mm will remain valid until the
         * finish_arch_post_lock_switch() call.
         */
        mm->context.switch_pending = 1;
    else
        /* 使用該函數(shù)進(jìn)行MMU切換頁(yè)表 */
        cpu_switch_mm(mm->pgd, mm);
}

/* arch/arm/include/asm/proc-fns.h */
/* 根據(jù)筆者找的代碼,cpu_switch_mm 應(yīng)該直接調(diào)用了processor.switch_mm */
#define cpu_do_switch_mm        processor.switch_mm
#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)

processor.switch_mm 是一個(gè) 回調(diào)函數(shù),根據(jù)筆者找到的資料,應(yīng)該是指向 ** arch/arm/mm** 目錄下的一些列 MMU 操作代碼。這里以 proc-v7-2level.S(即ARMv7 2級(jí)頁(yè)表) 進(jìn)行說(shuō)明

/* arch/arm/mm/proc-v7-2level.S */
/* 根據(jù)APCS,傳入的參數(shù)是存放在寄存器 r0和r1 */
ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
        mmid    r1, r1                          @ get mm->context.id
        ALT_SMP(orr     r0, r0, #TTB_FLAGS_SMP)
        ALT_UP(orr      r0, r0, #TTB_FLAGS_UP)
#ifdef CONFIG_PID_IN_CONTEXTIDR
        mrc     p15, 0, r2, c13, c0, 1          @ read current context ID
        lsr     r2, r2, #8                      @ extract the PID
        bfi     r1, r2, #8, #24                 @ insert into new context ID
#endif
#ifdef CONFIG_ARM_ERRATA_754322
        dsb
#endif
        mcr     p15, 0, r1, c13, c0, 1          @ set context ID
        isb
        /* 在這里,將r0所指向的頁(yè)表基地址設(shè)置到TTBR0中,完成頁(yè)表的切換 */
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
        isb
#endif
        bx      lr
ENDPROC(cpu_v7_switch_mm)

三、參考鏈接

《ARM Cortex-A Series Programmer’s Guide》
《Cortex-A7 MPCore Technical Reference Manual》
《多核MMU和ASID管理邏輯》
TLB的作用及工作過(guò)程
MMU和cache詳解(TLB機(jī)制)
inux-kernel – Linux內(nèi)核ARM轉(zhuǎn)換表庫(kù)(TTB0和TTB1)
ARM TTBR0,TTBR1寄存器與ARM32頁(yè)表復(fù)制
選擇使用TTBR0或TTBR1做為translation table base地址寄存器
TLB中ASID和nG bit的關(guān)系
ASID
Linux arm 進(jìn)程切換
ARM-LINUX的進(jìn)程切換

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文轉(zhuǎn)載自 https://juejin.im/post/59f8691b51882534af254317 參考:...
    xingdong閱讀 2,891評(píng)論 0 3
  • ## 一些小話 前段時(shí)間因?yàn)橐恍╇s七雜八的事情 被逼無(wú)奈 趕各種作業(yè) 再加上某個(gè)姓張的賤人 欺騙我說(shuō)計(jì)網(wǎng)...
    小師弟_831a閱讀 2,465評(píng)論 0 5
  • 前言 虛擬內(nèi)存算是操作系統(tǒng)中比較重要的一部分了,內(nèi)容也很多,早在看操作系統(tǒng)相關(guān)書籍的時(shí)候就有想要總結(jié)這一部分,但是...
    非專業(yè)程序員閱讀 1,457評(píng)論 0 5
  • 維基百科——虛擬內(nèi)存定義 虛擬內(nèi)存是計(jì)算機(jī)內(nèi)存管理的一種技術(shù)。它使得應(yīng)用程序認(rèn)為它擁有連續(xù)可用的內(nèi)存(一個(gè)連續(xù)完整...
    小胖學(xué)編程閱讀 906評(píng)論 0 8
  • 近日,一名自稱是中鐵十二局的員工在網(wǎng)絡(luò)發(fā)帖稱,由中鐵十二局成貴鐵路11標(biāo)項(xiàng)目經(jīng)理部修建的成貴高鐵鎮(zhèn)雄段存在安全質(zhì)量...
    KisenJ閱讀 362評(píng)論 0 1

友情鏈接更多精彩內(nèi)容