1 PMA
PMA(Physical Memory Attributes),物理內存屬性,顧名思義就是用來設置物理內存屬性的,但這里說“設置”,并不合理,因為一般情況下各存儲的屬性,在芯片設計時就固定了,不可動態修改。
1.1 屬性定義??
PMA定義了物理內存區域的以下靜態屬性:
-
緩存行為??(Cacheable/Non-Cacheable):決定數據是否可被緩存。
-
原子操作支持??(Atomics):是否允許使用LR/SC指令進行原子操作。
-
可執行權限??(Execute Permission):是否允許執行指令。
例如,外設寄存器通常配置為Non-Cacheable且禁止執行,避免緩存干擾硬件交互;主內存(如RAM)則多設為Cacheable以提升性能。
另外,一般PMA屬性在芯片設計時固化,??無法通過軟件動態修改??,需通過硬件邏輯直接實現。這種設計保證了關鍵內存區域(如外設)行為的確定性,避免運行時誤操作。
1.2 SiFive U74 PMA
下圖是SiFive U74的內存映射和PMA
前面說PMA一般情況下不可修改,實際上芯來科技的設計內核架構提供了一組mattri[i]_base
、mattri[i]_mask
('i’指編號),可以讓軟件來修改PMA,但這里也有規則,有優先級順序,即只能從低優先級修改成高優先級屬性(感興趣可以自行查找芯來RISC-V ISA spec)
2 PMP
2.1 簡介
PMP(Physical Memory Protection)物理內存保護。
RISC-V特權模式及切換 , 有介紹過RISC-V的特權模式,如何限制各特權的訪問權限呢,實現安全隔離呢?這里就需要PMP來提供了。
PMP可以提供安全處理和故障隔離功能,對現代處理器來說是非常重要的。PMP 機制適用于所有特權模式為 S 或 U 的指令和數據訪問,通過在 M 態下修改每個 hart 對應的控制寄存器,可以指定每個物理內存區域的讀、寫和執行等訪問權限。此外,PMP 機制也可用于 S 態中的頁表訪問。違反 PMP 機制的訪存將被處理器捕獲并觸發異常
-
核心功能:
- 負責隔離S/U模式下的內存訪問,可通過RISC-V可信固件在M-mode下動態配置S/U模式下程序的讀、寫和執行權限。
- 用于保護安全外設IO,可以通過約束控制設備控制器MMIO地址空間的訪問權限來實現。
- 對于安全域共同訪問的共享內存,可以通過將該共享內存分配給不同安全域來實現。
- 當HART進行安全域切換時,RISC-V可信固件通過PMP為目標安全域分配可訪問的系統資源,這可以通過在M-mode下操作PMP配置表和地址表進行管理。
-
物理內存保護機制:
- 通過配置寄存器pmpcfg和地址寄存器pmpaddr,來定義內存區域訪問權限
- 一個配置寄存器和一個地址寄存器組成一個PMP表項(entry),每一個entry對應一段物理地址的范圍和權限(R/W/X),一般硬件對表項數量有要求,通常為8或者16,最大64
2.2 配置規則
- pmpcfg寄存器
pmpcfg<x>
寄存器用于指定 PMP 表項的權限配置寄存器,每個pmpcfg<x>
寄存器可以管理四個PMP 表項目
每個表項的權限配置寄存器 pmp<x>cfg
中各控制位域:
域 | 位 | 描述 |
---|---|---|
R | 0 | 控制數據可讀權限: - 1:地址區間可讀 - 0:地址區間不可讀 |
W | 1 | 控制數據可寫權限: - 1:地址區間可寫 - 0:地址區間不可寫 |
X | 2 | 控制代碼可執行權限: - 1:地址區間可執行 - 0:地址區間不可執行 |
A | 4:3 | 控制地址區間模式(詳見下表) |
Reserved | 6:5 | 未使用域(固定為0) |
L | 7 | 控制PMP表項鎖定: - 1:鎖定表項 - 0:不鎖定表項 |
每個表項的權限配置寄存器 pmp<x>cfg
中的“A”比特域(第 4~3 位)用于控制該表項的地
址區間模式,其編碼和模式的含義:
A | 名稱 | 描述 |
---|---|---|
0 | OFF | 空模式,即:沒有配置此表項 |
1 | TOR | 緊鄰下一邊界 即區域 X 的結束地址緊鄰下一區域的基地址寄存器 pmpaddrX 的值 舉例:pmpcfg0設置為TOR,則受保護為[pmpaddr0,pmpaddr1] |
2 | NA4 | 4 個字節大小的區域(地址對齊) |
3 | NAPOT | 2 的冪次方大小的區域(區域大小起碼大于等于 8 個字節,并且地址對齊) |
其中:
-
NA4:Naturally Aligned 4-byte
-
NAPOT:Naturally Aligned Power-of-Two
-
L域中L=1表示PMP entry會被鎖定,意味著此時寫PMP寄存器和地址寄存器會被忽略。
- pmpaddr
保護地址至少四字節對齊,所以在RV32的cfgaddr里寫保護地址的[33:2]
保護機制如下:
- 1、pmpcfg.A=2(NA4模式)
定義保護一個4字節對齊的連續地址,若此時pmpaddr0 = 0x20000
,則保護0x20000-0x20003
。一般用來包含單個寄存器或者單字數據。
- 2、pmpcfg.A=3(NAPOT模式)
定義保護一個2的冪次方對齊的連續區域,具體由pmpaddr0的低位連續1的個數決定。
如下圖所示:
將pmpaddr的值轉換成二進制,從低位開始統計連續1的數量(計為n
)。則保護區域大小為2^(n+3)
字節。
示例:pmpaddr的值為yyyy…y01111,則保護區域大小為:2^(4+3) = 128byte
。假如此時pmpaddr0 = 0x2000F
,
則保護0x20000-0x2007F
。
優先級及原子性說明:
-
1、優先級機制
PMP 條目間采用靜態優先級,當區間重疊時,編號小的條目優先級更高。匹配到訪問中任何字節的最低編號的 PMP 條目決定本次訪問是成功還是失敗。 -
2、原子性
匹配的 PMP 條目必須包含訪問的所有字節,否則無論 L、R、W 和 X 位的值是什么,訪問都將失敗。例如,如果一個 PMP 條目被配置為匹配 4 字節區域 0xC–0xF,且為最高優先級條目,那么對區域 0x8–0xF 的 8 字節訪問將失敗。
RV64說明:
另外上面的配置是針對RV32,對于RV64,每個pmpcfg<x>
寄存器,包含8個entry
,所以只需要 8 個 CSR 寄存器即可實現與RV32的相同功能。為了與 RV32 保持一致,并降低軟件支持成本,RV64 中的 CSR 寄存器編號均為偶數,即 pmpcfg0,pmpcfg2,...,pmpcfg14
,奇數編號的寄存器是非法的
pmpaddr
,bit[63:54]
固定為0,bit[53:0]
用于存儲地址信息,保護機制同RV32,類比即可,不再舉例說明。
NOTE:
- WARL(Write Any Read Legal)
2.3 配置code
OpenSBI(opensbi/lib/sbi/sbi_hart.c)
int sbi_hart_pmp_configure(struct sbi_scratch *scratch)
{int rc;unsigned int pmp_bits, pmp_log2gran;// 獲取當前硬件線程(hart)支持的PMP區域數量unsigned int pmp_count = sbi_hart_pmp_count(scratch);unsigned long pmp_addr_max;// 如果硬件不支持PMP,則直接返回0(無需配置)if (!pmp_count)return 0;// 獲取PMP的粒度(對齊單位),以2的對數值表示(如4表示16字節對齊)pmp_log2gran = sbi_hart_pmp_log2gran(scratch);// 計算PMP地址寄存器的有效位數(規范定義為實際位數減1)pmp_bits = sbi_hart_pmp_addrbits(scratch) - 1;// 計算PMP支持的最大物理地址:(2^(pmp_bits+1) - 1pmp_addr_max = (1UL << pmp_bits) | ((1UL << pmp_bits) - 1);// 根據是否支持SMEPMP擴展選擇不同的配置函數if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMEPMP))// 使用增強型PMP(SMEPMP)配置rc = sbi_hart_smepmp_configure(scratch, pmp_count,pmp_log2gran, pmp_addr_max);else// 使用傳統PMP配置rc = sbi_hart_oldpmp_configure(scratch, pmp_count,pmp_log2gran, pmp_addr_max);/** 特權規范v1.12第3.7.節要求:* 1. 內存訪問可能被預取執行,地址翻譯可能被緩存* 2. CPU熱插拔/非保持性掛起會丟失PMP狀態* 3. 需要刷新緩存以保證PMP配置立即生效*/// 檢查是否支持監管模式(S-mode)if (misa_extension('S')) {// 刷新當前硬件線程的TLB和地址翻譯緩存__asm__ __volatile__("sfence.vma");// 如果支持Hypervisor擴展(H-mode)if (misa_extension('H'))// 額外刷新所有Guest模式的地址翻譯緩存__sbi_hfence_gvma_all();}// 返回PMP配置結果(0=成功,非0=錯誤)return rc;
}
此函數是 RISC-V 安全引導流程(如 OpenSBI)的核心部分,負責:
- 初始化物理內存保護(PMP)機制。
- 根據硬件特性選擇傳統或增強型配置。
- 確保 PMP 生效后內存訪問的安全性。
3 PMA與PMP的協同規則
在RISC-V架構中,PMA(物理內存屬性)和PMP(物理內存保護)是兩種不同的機制,它們共同作用于物理內存訪問的控制。PMA定義了內存區域的固有屬性(如是否可緩存、是否可執行等),而PMP則提供了基于特權模式的訪問控制(如用戶模式是否可以讀寫某區域)。二者通過靜態屬性與動態權限疊加進行內存訪問保護,下面簡單介紹下協同工作的規則
3.1 協同規則
- PMP的權限約束需基于PMA的屬性定義
PMP(物理內存保護)的訪問控制規則僅在 PMA(物理內存屬性)允許的權限范圍內有效。例如,若 PMA 將某內存區域標記為 不可執行(Non-Executable),即使 PMP 配置為允許執行(Execute),對該區域的執行訪問仍會觸發異常。這是因為 PMA 是更底層的硬件保護機制,決定了內存的物理屬性(如可執行性、緩存策略),而 PMP 只能在此基礎上疊加權限限制。
- 外設寄存器的聯合保護機制
對于設備內存(如外設寄存器),PMA 通過設置 不可緩存(Non-Cacheable)屬性確保直接訪問硬件寄存器,而 PMP 則進一步通過權限配置(如僅允許 M-mode 讀寫)防止用戶程序(U-mode/S-mode)誤操作硬件。這種 PMA 屬性定義與 PMP 權限控制的協同設計,既能保障硬件訪問的可靠性,又能防止越權訪問引發的安全風險。
3.2 典型協同流程
上圖簡單總結了下,PMA與PMP的協同工作時的流程,內存訪問時,
- 1、進行地址轉換(虛擬地址到物理地址)
- 2、執行PMA檢查(驗證物理內存固有屬性,如可執行性/可寫性)
- 3、若失敗則立即觸發異常;
- 4、通過PMA后進入PMP檢查(驗證基于特權模式的軟件權限,如讀/寫/執行控制),若失敗同樣觸發異常;
- 5、只有同時通過PMA和PMP雙重檢查,才允許執行最終的內存訪問。
這種分層機制確保了硬件屬性與軟件權限的協同驗證,為系統提供基礎安全隔離和可靠性保障。
所以我們在在配置時,需確保PMP規則與PMA屬性一致,以避免意外行為。
3.3 ePMP(Enhanced Physical Memory Protection)
ePMP 是 RISC-V 架構中 PMP 的增強版本,通過 Smepmp 擴展實現。它在傳統 PMP 基礎上增加了關鍵安全特性,特別針對機器模式(M-mode)提供了更嚴格的內存保護機制。
關于ePMP后續再做具體補充說明,感興趣可以閱讀RISC-V來學習。
參考:
SiFive U74 手冊
The RISC-V Instruction Set Manual (Volume II: Privileged Architecture)