AArch64 Linux 上的記憶體佈局¶
作者:Catalin Marinas <catalin.marinas@arm.com>
本文件描述了 AArch64 Linux 核心使用的虛擬記憶體佈局。該架構允許最多 4 級轉換表,頁面大小為 4KB,以及最多 3 級,頁面大小為 64KB。
AArch64 Linux 使用 3 級或 4 級轉換表,配置為 4KB 頁面,允許使用者和核心分別使用 39 位 (512GB) 或 48 位 (256TB) 虛擬地址。使用 64KB 頁面時,僅使用 2 級轉換表,允許 42 位 (4TB) 虛擬地址,但記憶體佈局相同。
ARMv8.2 增加了對大型虛擬地址空間的可選支援。 這僅在使用 64KB 頁面大小時可用,並擴充套件了第一級轉換中的描述符數量。
TTBRx 選擇由虛擬地址的第 55 位給出。 swapper_pg_dir 僅包含核心(全域性)對映,而使用者 pgd 僅包含使用者(非全域性)對映。 swapper_pg_dir 地址寫入 TTBR1,從不寫入 TTBR0。
當使用沒有虛擬化主機擴充套件的 KVM 時,hypervisor 會在 EL2 中以相對於線性對映的固定(且可能隨機)偏移量對映核心頁面。 有關更多詳細資訊,請參閱 kern_hyp_va 宏和 kvm_update_va_mask 函式。 當為特定 CPU 啟用 ARM64_SPECTRE_V3A 時,GICv2 等 MMIO 裝置會對映到 HYP idmap 頁面旁邊,向量也會對映到旁邊。
當使用帶有虛擬化主機擴充套件的 KVM 時,不會建立其他對映,因為主機核心直接在 EL2 中執行。
核心中的 52 位 VA 支援¶
如果存在 ARMv8.2-LVA 可選功能,並且我們正在使用 64KB 頁面大小執行,則可以為使用者空間和核心地址使用 52 位的地址空間。 但是,任何支援 52 位的核心二進位制檔案也必須能夠在早期啟動時回退到 48 位,如果硬體功能不存在。
這種回退機制需要核心 .text 位於較高的地址中,以便它們對 48/52 位 VA 不變。 由於 kasan 陰影是整個核心 VA 空間的一小部分,因此 kasan 陰影的末尾也必須位於核心 VA 空間的較高一半中,對於 48/52 位。(從 48 位切換到 52 位,kasan 陰影的末尾是不變的,並且依賴於 ~0UL,而起始地址將“增長”到較低的地址)。
為了最佳化 phys_to_virt 和 virt_to_phys,PAGE_OFFSET 保持恆定為 0xFFF0000000000000(對應於 52 位),這消除了額外變數讀取的需要。 physvirt 偏移量和 vmemmap 偏移量在早期啟動時計算,以啟用此邏輯。
由於單個二進位制檔案需要同時支援 48 位和 52 位 VA 空間,因此 VMEMMAP 的大小必須足夠大,以容納 52 位 VA,並且必須足夠大,以容納固定的 PAGE_OFFSET。
核心中的大多數程式碼都不需要考慮 VA_BITS,對於確實需要知道 VA 大小的程式碼,變數定義如下
VA_BITS 常量,最大 VA 空間大小
VA_BITS_MIN 常量,最小 VA 空間大小
vabits_actual 變數,實際 VA 空間大小
最大和最小大小對於確保緩衝區的大小足夠大,或者地址的位置足夠接近“最壞”情況可能很有用。
52 位使用者空間 VA¶
為了保持與依賴於 ARMv8.0 VA 空間最大大小 48 位的軟體的相容性,核心預設將從 48 位範圍返回虛擬地址給使用者空間。
軟體可以透過指定大於 48 位的 mmap 提示引數來“選擇加入”從 52 位空間接收 VA。
例如
maybe_high_address = mmap(~0UL, size, prot, flags,...);
也可以透過啟用以下核心配置選項來構建一個從 52 位空間返回地址的除錯核心
CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y
請注意,此選項僅用於除錯應用程式,不應在生產中使用。