Rocket-chip-PMP

pmp(Physical Memory Protection CSRs)的介绍可以看:
《The RISC-V Instruction Set Manual Volume II: Privileged Architecture》

重点内容在这里提一下:

  1. 32位CPU最多具有8个可配置的pmp,配置寄存器分别为pmp0cfg,pmp1cfg,pmp2cfg,pmp3cfg,pmp4cfg,pmp5cfg,pmp6cfg和pmp7cfg,它们都是8-bit的,而pmpcfg0管理着mp0cfg-mp3cfg,pmpcfg1管理着pmp4cfg-pmp7cfg,pmpcfg0和pmpcfg1是32-bit的。若CPU为64位,则最多可以具有16个可配置的pmp,pmp0cfg-pmp15cfg,同时多了pmpcfg2和pmpcfg3。在这里插入图片描述
  2. 32位的CPU,pmp的匹配地址为32-bit,是正常地址右移两位得出,64位的CPU为64-bit,也是正常地址右移两位得出。因为我没有配置虚拟内存,所以这里的正常地址就是实际的物理地址。在这里插入图片描述
  3. pmp?cfg为8-bit CSR寄存器,包含L,A,X,W,R位。L表示锁定位,A为2-bit的区域位,X为可执行权限,W为可写权限,R为可读权限。在这里插入图片描述
  4. 区域配置中包括4种形式,2b’00表示不使用,2’b01表示向上的全部范围,2’b10表示对齐的4字节范围,2’b11表示对齐的2^N字节范围,且要≥8字节。在这里插入图片描述
  5. L表示锁定位尤为重要。
    当L置1后,只有系统复位才能清除。
    当L置1后,对应的pmp?cfg和pmpaddr?都不能再配置,写入值被忽略。
    当pmp?cfg.A配置为TOR时,这里的pmp?cfg,pmpaddr?和pmp?cfg和pmpaddr?-1都不能配置了。(if pmpicfg.A is set to TOR, writes to pmpaddri-1 are ignored.)
    当L置1后,全部模式(M,S和U)都必须执行pmp?cfg的配置。
    当L为0时,只有(S和U)执行pmp?cfg的配置,M模式不执行,且能自由修改配置。
    注意:?表示pmp的编号,例如0-7。
    在这里插入图片描述
  6. pmp具有优先级,编号越低优先级越高,pmp0>pmp1>pmp2,当pmp0和pmp1设置的地址具有重叠部分,那么pmp0起效,pmp1不起效。
    在这里插入图片描述

测试代码如下。

#include "encoding.h"

#define U32 *(volatile unsigned int *)
#define DEBUG_SIG   0x70000000
#define DEBUG_VAL   0x70000004

//--------------------------------------------------------------------------
// handle_trap function

void handle_trap()
{
    asm volatile ("nop");
    U32(0x60003000) = 0x2021314;
    U32(DEBUG_SIG) = 0xFF;
    while(1);
}

//--------------------------------------------------------------------------
// pmp configuration function

void pmp_config()
{
    unsigned int i;

    U32(0x60000000) = read_csr(pmpcfg0);
    U32(0x60000004) = read_csr(pmpcfg1);
    U32(0x60000010) = read_csr(pmpaddr0);
    U32(0x60000014) = read_csr(pmpaddr1);
    U32(0x60000018) = read_csr(pmpaddr2);
    U32(0x6000001c) = read_csr(pmpaddr3);
    U32(0x60000020) = read_csr(pmpaddr4);
    U32(0x60000024) = read_csr(pmpaddr5);
    U32(0x60000028) = read_csr(pmpaddr6);
    U32(0x6000002c) = read_csr(pmpaddr7);

    //addr0 -> 0x6000_0000
    write_csr(pmpaddr0,0x60000000>>2);
    //addr1 -> 0x6000_1000
    write_csr(pmpaddr1,0x60001000>>2);
    //pmp1cfg: L=1 A=1(TOR) X-0 W-0 R-0
    write_csr(pmpcfg0 ,0x00008800);

    for ( i = 0; i < 100; i++ )
        U32(0x80001000+4*i) = i + 1;

    for ( i = 0; i < 100; i++ )
        U32(0x60001000+4*i) = i + 1;

    U32(0x60000000) = 0x10086;
}


//--------------------------------------------------------------------------
// Main

void main()
{
    pmp_config();
    while(1) {asm volatile ("wfi");}
}

代码功能:

  1. 读取pmp相关的CSR寄存器,并输出值0x6000_0000(mmio)的总线上。
  2. 配置pmp区域1,地址为0x6000_0000-0x6000_0FFF,不可读,不可写,不可执行。
  3. 往0x8000_1000-0x8000_118C区域写入数据,证明memory区域没有问题。
  4. 往0x6000_1000-0x6000_118C区域写入数据,证明配置区域外没有问题。
  5. 往0x6000_0000地址写0x10086。
  6. 第五步触发异常,函数调至handle_trap(),往0x6000_3000输出0x2021314,同时结束仿真。

仿真波形如下图。

  • 红色箭头:读取pmp相关的CSR寄存器,并输出值0x6000_0000(mmio)的总线上,共8次,pmpcfg0,pmpcfg1和pmpaddr0-pmpaddr7。
  • 蓝色箭头:往0x6000_1000-0x6000_118C区域写入数据,证明配置区域外没有问题。
  • 黄色箭头:往0x6000_0000地址写0x10086,触发异常,异常为7(Store/AMO access fault)。
  • 白色箭头:往0x6000_3000输出0x2021314,同时结束仿真。
    在这里插入图片描述
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值