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 寄存器用于控制对物理内存的访问权限,确保只有授权的访问才能进行。下面是逐步解释:
代码解析
-
定义PMP配置结构体:
struct pmp_config_t pmp_config;定义了一个
pmp_config结构体变量,用于存储 PMP 配置信息,包括物理地址、大小、模式和权限。 -
清除 PMP1:
clear_pmp_and_sync(1);- 这行代码用于清除 PMP 寄存器 1 的配置。PMP1 被保留用于允许内核在飞地(enclave)内存中配置页表。
clear_pmp_and_sync函数用于清除指定的 PMP 寄存器并同步状态。
-
打印初始化信息:
printm("[Penglai Monitor@%s] init platfrom and prepare PMP\n", __func__);打印一条信息,表示正在进行平台初始化并准备 PMP 配置。
-
配置 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 寄存器并同步状态。
-
配置最后一个 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表示允许对该内存区域的读、写和执行权限。
- 配置最后一个 PMP 寄存器(索引为
-
打印 PMP 配置完成信息:
printm("[Penglai Monitor@%s] setting initial PMP ready\n", __func__);打印一条信息,表示初始 PMP 配置已完成。
-
返回初始化结果:
return 0;返回 0 表示初始化成功。
代码逻辑
-
初始化 PMP 寄存器:
- 首先清除 PMP1 的配置,以便内核可以在飞地内存中配置页表。
- 配置 PMP0 寄存器以保护安全监控代码所在的内存区域,禁止对该区域的访问。
- 配置最后一个 PMP 寄存器以允许内核访问整个物理内存。
-
同步机制:
- 使用
clear_pmp_and_sync和set_pmp_and_sync函数确保在清除或设置 PMP 寄存器后,状态在所有哈特(hart)之间同步。
- 使用
注意事项
-
PMP 寄存器配置:
- PMP 寄存器数量由
NPMP宏定义,通常为 16 个寄存器。 - 每个 PMP 寄存器配置了一个物理内存区域的访问权限。
- PMP 寄存器数量由
-
权限配置:
PMP_NO_PERM表示禁止访问。PMP_R | PMP_W | PMP_X表示允许读、写和执行权限。
-
平台依赖:
- 该代码依赖于具体的 RISC-V 平台实现,其中
SM_BASE和SM_SIZE是平台特定的宏,表示安全监控代码的基地址和大小。
- 该代码依赖于具体的 RISC-V 平台实现,其中
-
打印函数:
printm是一个平台特定的打印函数,用于输出调试信息。
这段代码主要完成了对 PMP 寄存器的初始化配置,以确保安全监控代码的内存区域受到保护,同时允许内核访问其他内存区域。
现在,我将整理思路并以正式的形式回复用户。
190

被折叠的 条评论
为什么被折叠?



