penglai pmp 内存权限配置过程

sbi platform_init

int platform_init()
{
  struct pmp_config_t pmp_config;

  //Clear pmp1, this pmp is reserved for allowing kernel
  //to config page table for enclave in enclave's memory.
  //There is no need to broadcast to other hart as every
  //hart will execute this function.
  //clear_pmp(1);
  clear_pmp_and_sync(1);
  printm("[Penglai Monitor@%s] init platfrom and prepare PMP\n", __func__);
  //config the PMP 0 to protect security monitor
  pmp_config.paddr = (uintptr_t)SM_BASE;
  pmp_config.size = ALIGN_UP_POWER_OF_2((unsigned long)SM_SIZE);
  pmp_config.mode = PMP_A_NAPOT;
  pmp_config.perm = PMP_NO_PERM;
  set_pmp_and_sync(0, pmp_config);

  //config the last PMP to allow kernel to access memory
  pmp_config.paddr = 0;
  pmp_config.size = -1UL;
  pmp_config.mode = PMP_A_NAPOT;
  pmp_config.perm = PMP_R | PMP_W | PMP_X;
  //set_pmp(NPMP-1, pmp_config);
  set_pmp_and_sync(NPMP-1, pmp_config);

  printm("[Penglai Monitor@%s] setting initial PMP ready\n", __func__);
  return 0;
}

这段代码是一个平台初始化函数 platform_init,用于配置 RISC-V 架构下的物理内存保护(PMP)寄存器。PMP 寄存器用于控制对物理内存的访问权限,确保只有授权的访问才能进行。下面是逐步解释:

代码解析

  1. 定义PMP配置结构体

    struct pmp_config_t pmp_config;
    

    定义了一个 pmp_config 结构体变量,用于存储 PMP 配置信息,包括物理地址、大小、模式和权限。

  2. 清除 PMP1

    clear_pmp_and_sync(1);
    
    • 这行代码用于清除 PMP 寄存器 1 的配置。PMP1 被保留用于允许内核在飞地(enclave)内存中配置页表。
    • clear_pmp_and_sync 函数用于清除指定的 PMP 寄存器并同步状态。
  3. 打印初始化信息

    printm("[Penglai Monitor@%s] init platfrom and prepare PMP\n", __func__);
    

    打印一条信息,表示正在进行平台初始化并准备 PMP 配置。

  4. 配置 PMP0 以保护安全监控代码

    pmp_config.paddr = (uintptr_t)SM_BASE;
    pmp_config.size = ALIGN_UP_POWER_OF_2((unsigned long)SM_SIZE);
    pmp_config.mode = PMP_A_NAPOT;
    pmp_config.perm = PMP_NO_PERM;
    set_pmp_and_sync(0, pmp_config);
    
    • 配置 PMP0 寄存器以保护安全监控代码所在的内存区域。
    • SM_BASE 是安全监控代码的起始物理地址。
    • SM_SIZE 是安全监控代码的大小,ALIGN_UP_POWER_OF_2 用于将大小向上对齐到最接近的 2 的幂。
    • PMP_A_NAPOT 表示使用“Not a Power of Two”模式,允许配置非 2 的幂大小的内存区域。
    • PMP_NO_PERM 表示禁止对该内存区域的访问权限。
    • set_pmp_and_sync 函数用于设置指定的 PMP 寄存器并同步状态。
  5. 配置最后一个 PMP 寄存器以允许内核访问内存

    pmp_config.paddr = 0;
    pmp_config.size = -1UL;
    pmp_config.mode = PMP_A_NAPOT;
    pmp_config.perm = PMP_R | PMP_W | PMP_X;
    set_pmp_and_sync(NPMP - 1, pmp_config);
    
    • 配置最后一个 PMP 寄存器(索引为 NPMP - 1)以允许内核访问整个内存。
    • paddr 设置为 0,size 设置为 -1UL,表示覆盖整个物理内存地址空间。
    • PMP_R | PMP_W | PMP_X 表示允许对该内存区域的读、写和执行权限。
  6. 打印 PMP 配置完成信息

    printm("[Penglai Monitor@%s] setting initial PMP ready\n", __func__);
    

    打印一条信息,表示初始 PMP 配置已完成。

  7. 返回初始化结果

    return 0;
    

    返回 0 表示初始化成功。

代码逻辑

  • 初始化 PMP 寄存器

    • 首先清除 PMP1 的配置,以便内核可以在飞地内存中配置页表。
    • 配置 PMP0 寄存器以保护安全监控代码所在的内存区域,禁止对该区域的访问。
    • 配置最后一个 PMP 寄存器以允许内核访问整个物理内存。
  • 同步机制

    • 使用 clear_pmp_and_syncset_pmp_and_sync 函数确保在清除或设置 PMP 寄存器后,状态在所有哈特(hart)之间同步。

注意事项

  • PMP 寄存器配置

    • PMP 寄存器数量由 NPMP 宏定义,通常为 16 个寄存器。
    • 每个 PMP 寄存器配置了一个物理内存区域的访问权限。
  • 权限配置

    • PMP_NO_PERM 表示禁止访问。
    • PMP_R | PMP_W | PMP_X 表示允许读、写和执行权限。
  • 平台依赖

    • 该代码依赖于具体的 RISC-V 平台实现,其中 SM_BASESM_SIZE 是平台特定的宏,表示安全监控代码的基地址和大小。
  • 打印函数

    • printm 是一个平台特定的打印函数,用于输出调试信息。

这段代码主要完成了对 PMP 寄存器的初始化配置,以确保安全监控代码的内存区域受到保护,同时允许内核访问其他内存区域。

现在,我将整理思路并以正式的形式回复用户。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值