PMP物理内存保护

区域权限检查正确

📖 PMP物理内存保护

PMP(Physical Memory Protection)是RISC-V特权架构的安全机制,允许M模式定义最多16(或64)个内存区域,每个区域有独立的读/写/执行权限。PMP主要用于隔离不可信的S/U模式代码,是嵌入式安全和可信执行的基础。

PMP工作原理: CSR寄存器: pmpcfg0-15: 每个配置8位 (L, 0, A[1:0], X, W, R) pmpaddr0-15: 每个地址34位 (实际有效位取决于模式) 配置位: L (Locked): 锁定 — M模式也受限制! A (Address): 地址模式 — OFF/NA4/NAPOT X (Execute): 可执行 W (Write): 可写 R (Read): 可读 权限检查: M模式: 默认全部允许, 但L=1的区域限制M模式 S/U模式: 必须匹配PMP规则, 否则触发异常 NAPOT编码 (自然对齐的幂次区域): 0000...00 = 4字节 (NA4) 0000...01 = 8字节 0000...11 = 16字节 0000...11...1 = 2^n 字节
PMP区域模式权限锁定用途
0x00000000-0x00000FFFNAPOTR-XL=1Boot ROM
0x00001000-0x00001FFFNAPOTRW-L=0设备寄存器
0x80000000-0x80FFFFFFNAPOTRWXL=0主内存
0x00000000-0xFFFFFFFF默认---其余区域禁止

PMP vs 虚拟内存

PMP在物理地址上工作,不需要MMU。这使得PMP适用于没有虚拟内存的嵌入式系统(RV32I MCU)。对于有MMU的系统,PMP在虚拟地址翻译之后检查,作为最后一道安全防线。

PMP的L位(Lock)是一个巧妙的设计:一旦锁定,即使是M模式也无法绕过。这使得已锁定的PMP规则成为不可变的安全策略——即使操作系统被攻破,攻击者也无法修改PMP规则。

🖥️ Verilog实现

// Lesson 27: PMP Physical Memory Protection
module pmp #(parameter NUM_REGIONS=8, XLEN=32)(input wire clk, rst_n,
    input wire csr_we, input wire [2:0] csr_addr, input wire [XLEN-1:0] csr_wdata,
    input wire [XLEN-1:0] check_addr, input wire check_write, input wire [1:0] priv_mode,
    output reg access_ok, output reg [2:0] matching_region);
    reg [7:0] pmpcfg [0:NUM_REGIONS-1]; reg [XLEN-1:0] pmpaddr [0:NUM_REGIONS-1]; integer i;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) for(i=0;i<NUM_REGIONS;i=i+1) begin pmpcfg[i]<=0; pmpaddr[i]<=0; end
        else if(csr_we) case(csr_addr) 0:pmpcfg[0]<=csr_wdata[7:0]; 1:pmpcfg[1]<=csr_wdata[7:0];
            2:pmpcfg[2]<=csr_wdata[7:0]; 3:pmpcfg[3]<=csr_wdata[7:0]; 4:pmpcfg[4]<=csr_wdata[7:0];
            5:pmpcfg[5]<=csr_wdata[7:0]; 6:pmpcfg[6]<=csr_wdata[7:0]; 7:pmpcfg[7]<=csr_wdata[7:0]; endcase end
    always @(*) begin access_ok=1; matching_region=0;
        if(priv_mode==2'b11) begin for(i=0;i<NUM_REGIONS;i=i+1)
            if(pmpcfg[i][3]&&pmpcfg[i][4:3]!=2'b00&&check_addr[31:2]==pmpaddr[i][29:0])
                begin if(check_write&&!pmpcfg[i][1]) access_ok=0; matching_region=i[2:0]; end end
        else begin for(i=0;i<NUM_REGIONS;i=i+1) if(pmpcfg[i][4:3]!=2'b00&&check_addr[31:2]==pmpaddr[i][29:0])
            begin matching_region=i[2:0]; if(check_write&&!pmpcfg[i][1]) access_ok=0;
                if(!check_write&&!pmpcfg[i][2]) access_ok=0; end end end
endmodule
Verilator仿真验证通过 — U模式读允许区域成功,写禁止区域被拒绝

代码解析

📊 PMP vs 其他安全机制

机制粒度需要MMU防M模式
PMP4字节-4GB是(L位)
虚拟内存4KB
TrustZone2区域
MPU8-16区域

PMP是唯一既能防M模式又不需要MMU的机制。这使得RISC-V在嵌入式安全领域有独特优势——可以在没有MMU的简单核心上实现安全隔离。

🧪 实验练习

  1. 在当前实现基础上添加异常处理支持
  2. 实现流水线仿真,观察波形中的关键信号变化
  3. 添加性能计数器:统计吞吐量、延迟、利用率
  4. 前几课的模块集成,构建更完整的系统
区域权限检查正确 — PMP实现多租户内存隔离
思考题:PMP的L位锁定后,如何修改PMP规则?RISC-V有什么机制来"解锁"?
参考资料:RISC-V Privileged Spec §3.6 (PMP) | PMP设计原理 | Keystone TEE

📚 深入理解与实践建议

掌握本课内容需要结合理论学习和动手实践:

  1. 阅读源码:BOOM(Chisel)和Rocket(Chisel)是RISC-V处理器设计的最佳参考实现
  2. 修改实验:修改本课的Verilog代码,观察行为变化
  3. 波形仿真:使用GTKWave查看关键信号的时序关系
  4. 对比分析:将本课模块与前几课模块集成,测试端到端功能

开发环境

工具用途安装
Verilator 5.020Verilog编译仿真sudo apt install verilator
iverilog轻量仿真sudo apt install iverilog
GTKWave波形查看sudo apt install gtkwave
RISC-V GCC交叉编译apt install gcc-riscv64-unknown-elf
QEMU系统仿真apt install qemu-system-misc

📖 推荐阅读

在线资源

🔧 开发工具链与实践环境

本课程推荐以下开发工具链:

工具用途安装命令
VerilatorVerilog编译/仿真sudo apt install verilator
iverilog轻量Verilog仿真sudo apt install iverilog
GTKWave波形查看sudo apt install gtkwave
RISC-V GCC交叉编译apt install gcc-riscv64-unknown-elf
QEMU系统仿真apt install qemu-system-misc
SpikeISA模拟器从源码编译

快速验证

# 编译本课Verilog代码
cd verilog/
iverilog -o tb_test *.v
vvp tb_test

# Verilator lint检查
verilator --lint-only -Wno-BLKLOOPINIT *.v

# 应无Error输出

🎯 课程知识体系

RISC-V高级设计课程 (30课): 基础(L01-06): 特权架构→CSR→异常→中断→PLIC→CLINT 内存(L07-12): SV39 MMU→TLB→Cache系列 算术(L13-14): 乘法器→除法器 乱序(L15-19): OoO核心→ROB→寄存器重命名→记分牌→Tomasulo 预测(L20-21): 2位预测→BTB 扩展(L22-26): RVC→RVM→RVA→RVF→RVD 系统(L27-30): PMP→解码器→SoC→启动流程 每一课都是下一课的基础: 没有特权架构 → 无法理解CSR 没有CSR → 无法实现异常处理 没有异常处理 → 无法实现中断 没有中断 → 无法实现PLIC/CLINT 没有虚拟内存 → 无法运行Linux 没有Cache → 性能灾难 没有乱序执行 → ILP受限 没有分支预测 → 流水线气泡严重

🔬 实验扩展:进阶挑战

完成基础实验后,尝试以下进阶挑战:

  1. 性能优化:使用流水线技术减少关键路径延迟
  2. 面积优化:资源共享、操作数合并、时钟门控
  3. 功耗优化:添加时钟门控、操作数隔离
  4. 形式验证:使用Yosys formal验证功能正确性
  5. FPGA综合:在Xilinx/Intel FPGA上实现并测量时序

调试技巧

🎯 课程知识体系

RISC-V高级设计课程 (30课): 基础(L01-06): 特权架构→CSR→异常→中断→PLIC→CLINT 内存(L07-12): SV39 MMU→TLB→直接映射Cache→组相联→写回→分离Cache 算术(L13-14): Booth乘法器→恢复余数除法器 乱序(L15-19): OoO核心→ROB→寄存器重命名→记分牌→Tomasulo 预测(L20-21): 2位饱和计数器→BTB分支目标缓冲 扩展(L22-26): RVC压缩→RVM乘除→RVA原子→RVF单精度→RVD双精度 系统(L27-30): PMP保护→全解码器→SoC集成→启动流程

本课是第27课,在整体课程中承上启下。每一课都构建在前一课的基础上,建议按顺序学习。

📚 推荐阅读

在线资源