penglaispmp--enclave_mm关于region管理的逻辑

enclave_mm.c 基于PMP(Physical Memory Protection,物理内存保护)伙伴系统(Buddy System) 的内存区域(region)管理逻辑,主要用于安全监控器(SM,Security Monitor)中对enclave(安全区)内存的隔离、分配和释放。核心逻辑围绕“内存区域的初始化、分配、释放”以及“PMP权限控制”展开,以下是详细分析:

一、核心数据结构

内存区域管理依赖以下关键数据结构,用于跟踪内存状态和PMP配置:

  1. mm_regions 数组
    类型:struct mm_region_t mm_regions[N_PMP_REGIONS]
    作用:存储所有可用的内存区域信息,每个元素对应一个由PMP保护的物理内存块。
    关键成员:

    • valid:标记区域是否有效(已初始化)。
    • paddr/size:区域的物理起始地址和大小(必须是2的幂,且不小于一页)。
    • mm_list_head:指向伙伴系统的链表头,用于管理该区域内的空闲内存块(基于伙伴系统)。
  2. pmp_bitmap 位图
    类型:unsigned long pmp_bitmap
    作用:跟踪PMP寄存器的使用状态,每一位对应一个PMP索引(如bit 0对应PMP 0,bit 1对应PMP 1),置位表示该PMP已被占用。

  3. 伙伴系统相关结构

    • struct mm_list_head_t:伙伴系统中相同“阶(order)”的内存块链表头,用于快速查找可用块。
      • order:内存块的阶(大小为2^order字节)。
      • prev_list_head/next_list_head:链表指针,连接不同阶的链表头。
      • mm_list:指向当前阶的空闲内存块链表。
    • struct mm_list_t:单个内存块的元数据。
      • order:块的阶。
      • prev_mm/next_mm:链表指针,连接同阶的其他空闲块。

二、核心流程分析

1. 内存区域初始化(mm_init

作用:将一块物理内存初始化为受PMP保护的enclave内存区域,并初始化伙伴系统用于后续分配。
流程:

  • 参数检查:验证内存大小是否为2的幂、地址是否按大小对齐、不小于一页(check_mem_size)。
  • 冲突检查:确保新区域不与安全监控器(SM)内存或现有区域重叠(check_mem_overlap)。
  • PMP分配:通过pmp_bitmap找到空闲的PMP索引,标记为占用,并配置PMP寄存器(set_pmp_and_sync),初始权限为“无访问权限(PMP_NO_PERM)”,防止未授权访问。
  • 伙伴系统初始化:在区域起始地址创建伙伴系统的根节点(mm_list_headmm_list),将整个区域作为一个大内存块加入伙伴系统。
2. 内存分配(mm_alloc

作用:从已初始化的区域中分配一块满足大小要求的内存(基于伙伴系统)。
流程:

  • 计算阶数:根据请求大小计算所需的“阶(order)”(如8KB对应order=3,因为2^3=8)。
  • 遍历区域:对每个已初始化的区域,尝试从其伙伴系统中分配一块不小于所需阶的内存块(alloc_one_region)。
  • 块拆分:若找到的块阶数大于所需阶,将其拆分为 smaller 块(每次拆分阶数减1),剩余部分插回伙伴系统(insert_mm_region)。
  • 返回地址:返回分配的物理地址,并清零内存(sbi_memset)。
3. 内存释放(mm_free

作用:将内存块归还给伙伴系统,并尝试合并相邻块以减少碎片(伙伴系统核心特性)。
流程:

  • 参数检查:验证释放的内存大小是否为2的幂、地址对齐。
  • 查找区域:确定释放的内存属于哪个已初始化的区域。
  • 插入伙伴系统:将内存块插入对应阶的链表,并尝试合并相邻的同阶块(merge_regions),合并后阶数加1,直到无法合并或达到区域最大阶。
4. PMP权限管理

为了在enclave初始化、运行等阶段灵活控制内存访问权限,提供了以下函数:

  • grant_kernel_access:临时允许内核访问enclave内存(如初始化enclave或配置页表),通过PMP 0配置权限为“读写执行(PMP_R|W|X)”。
  • retrieve_kernel_access:撤销内核对enclave内存的访问权限(目前未实现,仅返回0)。
  • grant_enclave_access:允许enclave访问自身内存,配置PMP和SPMP(Supervisor PMP)权限为“读写执行”(目前部分实现)。
  • retrieve_enclave_access:撤销enclave对内存的访问权限(目前部分实现)。

三、核心逻辑总结

  1. 基于PMP的内存隔离:通过PMP寄存器将enclave内存与其他区域隔离,初始权限为“无访问”,仅在需要时(如内核初始化enclave)临时开放权限。
  2. 伙伴系统的内存管理:采用伙伴系统实现高效的内存分配与释放,支持块的拆分与合并,减少碎片。
  3. 线程安全:通过自旋锁(pmp_bitmap_lock)保证多线程环境下对pmp_bitmap和伙伴系统链表的操作原子性。

四、关键细节与限制

  • 区域数量限制:最多支持N_PMP_REGIONS个区域(由PMP寄存器数量决定)。
  • 大小限制:内存块大小必须是2的幂,且不小于一页(RISCV_PGSIZE)。
  • PMP配置:目前部分PMP操作被注释(#if 0),可能处于开发阶段,实际权限控制需依赖完整实现。

整体而言,这段代码是安全监控器中enclave内存管理的核心,通过PMP实现硬件级隔离,通过伙伴系统实现高效的内存分配,为enclave提供安全且灵活的内存环境。

五、系统内核 飞地虚拟地址映射逻辑 penglai-enclave-page

这段代码实现了基于页表的内存管理系统,主要用于安全监控器(Security Monitor)中管理enclave(安全区)的内存映射。核心逻辑围绕“页表遍历”、“虚拟地址到物理地址映射”以及“内存分配释放”展开,以下是详细分析:

5.1、核心数据结构与设计思想
  1. 内存页管理

    • 使用链表(struct list_head free_mem)管理空闲页,每个节点为struct free_mem_t,包含虚拟地址vaddr
    • 通过init_free_mem初始化链表,将连续物理内存按页分割并加入链表。
  2. 页表结构

    • 基于RISC-V架构的多级页表(RISCV_PT_LEVEL级,通常为3级)。
    • 每个页表项(PTE)包含物理页号(PPN)和权限位(如PTE_V表示有效)。
  3. 地址转换

    • va2ppn:虚拟地址→物理页号(右移页大小位数)。
    • pte2pa:页表项→物理地址(提取PPN并左移页大小位数)。
5.2、关键函数与流程分析
5.2.1. 页表操作核心函数
static pt_entry_t * walk_enclave_pt(struct list_head* free_mem, 
                                   pt_entry_t* enclave_root_pt, 
                                   vaddr_t vaddr, bool create);
  • 作用:遍历页表,查找或创建虚拟地址对应的页表项。
  • 流程
    1. 从根页表(enclave_root_pt)开始,逐级解析虚拟地址中的索引。
    2. 若中间页表项不存在且create=true,则分配新页表页(create_ptd_page)。
    3. 返回最终页表项的指针。
  • 应用:为内存映射和分配提供底层支持。
5.2.2. 内存分配与映射
vaddr_t enclave_alloc_page(enclave_mem_t* enclave_mem, vaddr_t vaddr, unsigned long flags);
vaddr_t map_va2pa(enclave_mem_t* enclave_mem, vaddr_t vaddr, paddr_t paddr, unsigned long flags);
  • enclave_alloc_page
    • 分配一个空闲页(从free_mem链表获取),并将其映射到指定虚拟地址vaddr
    • 设置页表项权限(flags),如读写执行权限。
  • map_va2pa
    • 将物理地址paddr映射到虚拟地址vaddr,用于已有物理内存的映射(如设备内存)。
    • 同样设置页表项权限。
5.2.3. 初始化与销毁
void enclave_mem_int(enclave_mem_t* enclave_mem, vaddr_t vaddr, int size, paddr_t paddr);
int enclave_mem_destroy(enclave_mem_t * enclave_mem);
  • enclave_mem_int
    • 初始化enclave内存管理器:
      1. vaddr开始的size字节内存按页分割,加入free_mem链表。
      2. 分配根页表,并设置enclave_root_pt
      3. 预留两个特殊页(注释中提到用于动态分配记录)。
  • enclave_mem_destroy
    • 清理空闲页链表,但未完全实现(注释中标记为FIXME)。
    • 需补充释放页表内存和enclave占用的物理页。
5.3、核心逻辑总结
  1. 空闲页管理

    • 使用链表实现简单的页分配器,支持初始化、分配和回收。
    • 适用于enclave内部的小内存块分配(如栈、堆)。
  2. 页表操作

    • 实现多级页表的递归遍历和动态创建。
    • 通过walk_enclave_pt实现“按需创建”页表,节省内存。
  3. 映射策略

    • enclave_alloc_page:分配新页并映射,用于动态内存(如堆)。
    • map_va2pa:将已有物理内存映射到虚拟地址,用于静态内存(如代码段、设备内存)。
5.4、关键细节与限制
  1. 权限控制

    • 通过flags参数设置页表项权限(如PTE_RPTE_WPTE_X)。
    • 需配合硬件PMP/SPMP进一步隔离enclave与外部内存。
  2. 性能优化

    • 页表遍历涉及多次内存访问,可通过TLB(Translation Lookaside Buffer)缓存加速。
  3. 未完成的功能

    • enclave_mem_destroy未完全实现页表回收,可能导致内存泄漏。
    • 预留的两个特殊页(用于动态分配记录)未实现具体逻辑。
5.5、安全考量
  1. 地址验证

    • 代码未显式检查vaddr是否在enclave合法范围内,需上层调用者保证。
    • 若传入非法地址,可能导致页表污染或越界访问。
  2. 权限隔离

    • 页表权限与PMP/SPMP需协同工作,确保enclave内存不被外部非法访问。
    • 例如,enclave代码段应设置为“只读+可执行”,数据段为“读写”。
5.6、总结

这段代码实现了一个轻量级的enclave内存管理系统,核心是基于多级页表的虚拟内存映射和简单的空闲页链表分配器。它为enclave提供了内存隔离的基础,但需与硬件保护机制(如PMP)结合,才能实现完整的安全隔离。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值