区域权限检查正确
PMP(Physical Memory Protection)是RISC-V特权架构的安全机制,允许M模式定义最多16(或64)个内存区域,每个区域有独立的读/写/执行权限。PMP主要用于隔离不可信的S/U模式代码,是嵌入式安全和可信执行的基础。
| PMP区域 | 模式 | 权限 | 锁定 | 用途 |
|---|---|---|---|---|
| 0x00000000-0x00000FFF | NAPOT | R-X | L=1 | Boot ROM |
| 0x00001000-0x00001FFF | NAPOT | RW- | L=0 | 设备寄存器 |
| 0x80000000-0x80FFFFFF | NAPOT | RWX | L=0 | 主内存 |
| 0x00000000-0xFFFFFFFF | 默认 | --- | — | 其余区域禁止 |
PMP在物理地址上工作,不需要MMU。这使得PMP适用于没有虚拟内存的嵌入式系统(RV32I MCU)。对于有MMU的系统,PMP在虚拟地址翻译之后检查,作为最后一道安全防线。
// 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
| 机制 | 粒度 | 需要MMU | 防M模式 |
|---|---|---|---|
| PMP | 4字节-4GB | 否 | 是(L位) |
| 虚拟内存 | 4KB | 是 | 否 |
| TrustZone | 2区域 | 否 | 是 |
| MPU | 8-16区域 | 否 | 否 |
PMP是唯一既能防M模式又不需要MMU的机制。这使得RISC-V在嵌入式安全领域有独特优势——可以在没有MMU的简单核心上实现安全隔离。
掌握本课内容需要结合理论学习和动手实践:
| 工具 | 用途 | 安装 |
|---|---|---|
| Verilator 5.020 | Verilog编译仿真 | 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 |
本课程推荐以下开发工具链:
| 工具 | 用途 | 安装命令 |
|---|---|---|
| Verilator | Verilog编译/仿真 | 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 |
| Spike | ISA模拟器 | 从源码编译 |
# 编译本课Verilog代码
cd verilog/
iverilog -o tb_test *.v
vvp tb_test
# Verilator lint检查
verilator --lint-only -Wno-BLKLOOPINIT *.v
# 应无Error输出
完成基础实验后,尝试以下进阶挑战:
$display打印关键状态变化$dumpfile/$dumpvars生成VCD波形本课是第27课,在整体课程中承上启下。每一课都构建在前一课的基础上,建议按顺序学习。