詳解 ARM64 核心中對 52 位虛擬位址的支援

2021-10-19 11:17:14 字數 3451 閱讀 5155

當 64 位硬體變得可用之後,處理更大位址空間(大於 232 位元組)的需求變得顯而易見。現如今一些公司已經提供 64tib 或更大記憶體的伺服器,x86_64 架構和 arm64 架構現在允許定址的位址空間大於 248 位元組(可以使用預設的 48 位位址支援)。

x86_64 架構通過讓硬體和軟體啟用五級頁表以支援這些用例。它允許定址的位址空間等於 257 位元組(詳情見x86:在 4.12 核心中啟用 5 級頁表)。它突破了過去虛擬位址空間 128pib 和實體地址空間 4pib 的上限。

arm64 架構通過引入兩個新的體系結構 —— armv8.2 lva(更大的虛擬定址) 和 armv8.2 lpa(更大的實體地址定址) —— 拓展來實現相同的功能。這允許使用 4pib 的虛擬位址空間和 4pib 的實體地址空間(即分別為 252 位)。

隨著新的 arm64 cpu 中支援了 armv8.2 體系結構拓展,同時現在開源軟體也支援了這兩種新的硬體拓展。

從 linux 5.4 核心開始, arm64 架構中的 52 位(大)虛擬位址(va)和實體地址(pa)得到支援。儘管核心文件描述了這些特性和新的核心執行時對舊的 cpu(硬體層面不支援 52 位虛擬位址拓展)和新的 cpu(硬體層面支援 52 位虛擬位址拓展)的影響,但對普通使用者而言,理解這些並且如何 「選擇使用」 52 位的位址空間可能會很複雜。

1. 在增加了對這些功能的支援後,核心的記憶體布局如何「翻轉」到 arm64 架構

2. 對使用者態應用的影響,尤其是對提供除錯支援的程式(例如:kexec-tools、 makedumpfile 和 crash-utility)

3. 如何通過指定大於 48 位的 mmap 引數,使使用者態應用「選擇」從 52 位位址空間接受 va?

armv8.2 架構的 lva 和 lpa 拓展

armv8.2 架構提供兩種重要的拓展:大虛擬定址(lva)和大物理定址(lpa)。

當使用 64 kb 轉換粒度時,armv8.2-lva 為每個翻譯表基位址暫存器提供了乙個更大的 52 位虛擬位址空間。

在 armv8.2-lva 中允許:

當使用 64 kb 轉換粒度時,中間實體地址(ipa)和實體地址空間拓展為 52 位。

如果使用 64 kb 轉換粒度來實現對 52 位實體地址的支援,那麼一級塊將會覆蓋 4tb 的位址空間。

需要注意的是這些特性僅在 aarch64 架構中支援。

目前下列的 arm64 cortex-a 處理器支援 armv8.2 拓展:

arm64 的核心記憶體布局

伴隨著 armv8.2 拓展增加了對 lva 位址的支援(僅當以頁大小為 64 kb 執行時可用),在第一級轉換中,描述符的數量會增加。

頁面大小為 64 kb 和三個級別的(具有 52 位硬體支援)的 aarch64 架構下 linux 記憶體布局如下:

4 kb 頁面的轉換查詢表如下:>

64 kb 頁面的轉換查詢表如下:

核心對 52 位虛擬位址的支援

因為支援 lva 的較新的核心應該可以在舊的 cpu(硬體不支援 lva 拓展)和新的 cpu(硬體支援 lva 拓展)上都正常執行,因此採用的設計方法是使用單個二進位制檔案來支援 52 位(如果硬體不支援該特性,則必須在剛開始啟動時能回退到 48 位)。也就是說,為了滿足 52 位的虛擬位址以及固定大小的 page_offset,vmemmap 必須設定得足夠大。

va_bits         常量       *最大的* 虛擬位址空間大小

vabits_actual 變數 *實際的* 虛擬位址空間大小

翻轉核心記憶體布局保持乙個單一核心二進位制檔案的設計方法要求核心的 .text 位於高位位址中,因此它們對於 48/52 位虛擬位址是不變的。因為核心位址檢測器(kasan)區域僅佔整個核心虛擬位址空間的一小部分,因此對於 48 位或 52 位的虛擬位址空間,kasan 區域的末尾也必須在核心虛擬位址空間的上半部分。(從 48 位切換到 52 位,kasan 區域的末尾是不變的,且依賴於 ~0ul,而起始位址將「增長」到低位位址)

為了優化 phys_to_virt() 和 virt_to_phys(),頁偏移量將被保持在 0xfff0000000000000 (對應於 52 位),這消除了讀取額外變數的需求。在早期啟動時將會計算 physvirt 和 vmemmap 偏移量以啟用這個邏輯。

對用於除錯核心的使用者態程式的影響

有幾個使用者空間應用程式可以用於除錯正在執行的/活動中的核心或者分析系統崩潰時的 vmcore 轉儲(例如確定核心奔潰的根本原因):kexec-tools、makedumpfile 和 crash-utility。

當用它們來除錯 arm64 核心時,因為 arm64 核心記憶體對映被「翻轉」,因此也會對它們產生影響。這些應用程式還需要遍歷轉換表以確定與虛擬位址相應的實體地址(類似於核心中的完成方式)。

相應地,在將「翻轉」引入核心記憶體對映之後,由於上游破壞了使用者態應用程式,因此必須對其進行修改。

我已經提議了對三個受影響的使用者態應用程式的修復;有一些已經被上游接受,但其他仍在等待中:

提議 makedumpfile 上游的修復

提議 kexec-tools 上游的修復

已接受的 crash-utility 的修復

除非在使用者空間應用程式進行了這些修改,否則它們將仍然無法除錯執行/活動中的核心或分析系統崩潰時的 vmcore 轉儲。

52 位使用者態虛擬位址

為了保持與依賴 armv8.0 虛擬位址空間的最大為 48 位的使用者空間應用程式的相容性,在預設情況下核心會將虛擬位址從 48 位範圍返回給使用者空間。

.mmap_high_addr.c

----

maybe_high_address = mmap(~0ul, size, prot, flags,...);

config_expert=y && config_arm64_force_52bit=y
結論總結一下:

arm64入棧出棧 棧 ARM64

棧 棧 是一種具有特殊的訪問方式的儲存空間 後進先出,last in out firt,lifo sp和fp暫存器 sp暫存器在任意時刻會儲存我們棧頂的位址.fp暫存器也稱為x29暫存器屬於通用暫存器,但是在某些時刻我們利用它儲存棧底的位址 注意 arm64開始,取消32位的 ldm,stm,pus...

ARM64除錯環境

自從上一次zctf做了一道arm64的逆向題目後,我決定記錄下利用qemu搭建arm64的環境的過程,以後肯定會遇到更多arm平台下的reverse和pwn。我要模擬的是64位的arm環境,所以需要使用的是qemu system aarch64。在kali下,使用apt get install qe...

arm64 頁表對映

armv8最多支援48根位址,4級頁表,這樣最多支援user space和kernnel space 分別是256tb 其中user space佔據低端位址 kernel可以支援48 42 39 根位址 config arm64 va bits 39 is not set config arm64 ...