文章目录

  • 1、armv8的页表定义
  • 2、rodata section指向内存的结构体
  • 3、内存的分类和注册
  • 3、内存的属性(type)
  • 4、页表的构建

1、armv8的页表定义

透过事务看本质,页表里都有什么? 如下图描述了页表中的一个entry信息,而我们软件做的工作,其实就是针对每一个页面的管理,去填充一个entry, 一个entry对应一个页面, entry中包含页面地址和内存的一些属性。把所有的entry放到一起,就构成了页表www

2、rodata section指向内存的结构体

rodata section的地址段

     *(.rodata .rodata.*)/** 8 to avoid unwanted padding between __start_ta_head_section* and the first structure in ta_head_section, in 64-bit* builds*/. = ALIGN(8);__start_ta_head_section = . ;KEEP(*(ta_head_section))__stop_ta_head_section = . ;. = ALIGN(8);__start_phys_mem_map_section = . ;KEEP(*(phys_mem_map_section))__end_phys_mem_map_section = . ;. = ALIGN(8);__start_phys_sdp_mem_section = . ;KEEP(*(phys_sdp_mem_section))__end_phys_sdp_mem_section = . ;. = ALIGN(8);__start_phys_nsec_ddr_section = . ;KEEP(*(phys_nsec_ddr_section))__end_phys_nsec_ddr_section = . ;. = ALIGN(8);__start_phys_ddr_overall_section = . ;KEEP(*(phys_ddr_overall_section))__end_phys_ddr_overall_section = . ;

可以看出在rodata中定义了如下section:

  • ta_head_section
  • phys_mem_map_section
  • phys_sdp_mem_section
  • phys_nsec_ddr_section
  • phys_ddr_overall_section

指向内存的结构体:

struct core_mmu_phys_mem {const char *name;enum teecore_memtypes type;__extension__ union {paddr_t addr;};__extension__ union {paddr_size_t size;};
};

注:在section段落中的,每一个core_mmu_phys_mem数据类型,都代表这一块region.

3、内存的分类和注册

在optee中注册内存的宏有:

  • register_phys_mem 将注册的内存地址添加到phys_mem_map_section段
  • register_sdp_mem 将注册的内存地址添加到phys_sdp_mem_section段, 注意:sdp 应该是 secure device peripheral的意思
  • register_dynamic_shm 将注册的内存地址添加到phys_nsec_ddr_section段
  • register_ddr 将注册的内存地址添加到phys_ddr_overall_section段

以为register_phys_mem为例,该宏就是在.rodata的__start_phys_mem_map_section的section段定义一个struct core_mmu_phys_mem结构体类型的数据中,指向注册的这块mem的物理地址.

#define __register_memory2(_name, _type, _addr, _size, _section, _id) \static const struct core_mmu_phys_mem __phys_mem_ ## _id \__used __section(_section) = \{ .name = _name, .type = _type, .addr = _addr, .size = _size }#define __register_memory2_ul(_name, _type, _addr, _size, _section, _id) \__register_memory2(_name, _type, _addr, _size, _section, _id)
#endif#define __register_memory1(name, type, addr, size, section, id) \__register_memory2(name, type, addr, size, #section, id)#define __register_memory1_ul(name, type, addr, size, section, id) \__register_memory2_ul(name, type, addr, size, #section, id)#define register_phys_mem(type, addr, size) \__register_memory1(#addr, (type), (addr), (size), \phys_mem_map_section, __COUNTER__)

在core/arch/arm/plat_xxx/main.c中,注册这些内存:
可以注册多块物理内存:

register_phys_mem(xxx0_TYPE, xxx0_PA_BASE, xxx_SIZE);
register_phys_mem(xxx1_TYPE, xxx1_PA_BASE, xxx1_SIZE);

可以注册多个IO设备:

register_sdp_mem(DRM_VPU1_BASE, DRM_VPU1_BASE);
register_sdp_mem(DRM_VPU2_BASE, DRM_VPU2_BASE);

3、内存的属性(type)

在注册内存的时候,其实就是将包含name、type、addr、size四个元素的结构体,填写到了section段落,而type对应的就是内存的属性,对应着teecore_memtypes类型:

在optee中,有如下十几种type

enum teecore_memtypes {MEM_AREA_END = 0,MEM_AREA_TEE_RAM,MEM_AREA_TEE_RAM_RX,MEM_AREA_TEE_RAM_RO,MEM_AREA_TEE_RAM_RW,MEM_AREA_TEE_COHERENT,MEM_AREA_TEE_ASAN,MEM_AREA_TA_RAM,MEM_AREA_NSEC_SHM,MEM_AREA_RAM_NSEC,MEM_AREA_RAM_SEC,MEM_AREA_IO_NSEC,MEM_AREA_IO_SEC,MEM_AREA_RES_VASPACE,MEM_AREA_SHM_VASPACE,MEM_AREA_TA_VASPACE,MEM_AREA_PAGER_VASPACE,MEM_AREA_SDP_MEM,MEM_AREA_DDR_OVERALL,MEM_AREA_MAXTYPE
};

4、页表的构建

在optee中,定义一个region的静态数组,CFG_MMAP_REGIONS=127, 可以存放127块region

static struct tee_mmap_regionstatic_memory_map[CFG_MMAP_REGIONS + 1];struct tee_mmap_region {unsigned int type; /* enum teecore_memtypes */unsigned int region_size;paddr_t pa;vaddr_t va;size_t size;uint32_t attr; /* TEE_MATTR_* above */
};

在构建页表之前,先调用init_mem_map函数,将内存中已注册了的region读取到static_memory_map这个静态数组中

init_mem_map(static_memory_map, ARRAY_SIZE(static_memory_map));

init_mem_map()函数原型

在init_mem_map读取section region到static_memory_map的过程中,还会调用core_mmu_type_to_attr函数,将注册时写入的内存属性(type)转换位memory attribute
这里返回的memory attribute是一个32bit的值,而armv8要求的是64bit的。

uint32_t core_mmu_type_to_attr(enum teecore_memtypes t)
{const uint32_t attr = TEE_MATTR_VALID_BLOCK;const uint32_t cached = TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT;const uint32_t noncache = TEE_MATTR_CACHE_NONCACHE <<TEE_MATTR_CACHE_SHIFT;switch (t) {case MEM_AREA_TEE_RAM:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | cached;case MEM_AREA_TEE_RAM_RX:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRX | cached;case MEM_AREA_TEE_RAM_RO:return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached;case MEM_AREA_TEE_RAM_RW:case MEM_AREA_TEE_ASAN:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached;case MEM_AREA_TEE_COHERENT:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | noncache;case MEM_AREA_TA_RAM:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached;case MEM_AREA_NSEC_SHM:return attr | TEE_MATTR_PRW | cached;case MEM_AREA_IO_NSEC:return attr | TEE_MATTR_PRW | noncache;case MEM_AREA_IO_SEC:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | noncache;case MEM_AREA_RAM_NSEC:return attr | TEE_MATTR_PRW | cached;case MEM_AREA_RAM_SEC:return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached;case MEM_AREA_RES_VASPACE:case MEM_AREA_SHM_VASPACE:return 0;case MEM_AREA_PAGER_VASPACE:return TEE_MATTR_SECURE;default:panic("invalid type");}
}

在创建页表的时候会将32位的内存属性,转换成64的内存属性之后,再填充到页表的entry中
core_init_mmu_tables()—>core_mmu_map_region()—>core_mmu_set_entry()—>core_mmu_set_entry_primitive()

void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx,paddr_t pa, uint32_t attr)
{uint64_t *tbl = table;uint64_t desc = mattr_to_desc(level, attr);tbl[idx] = desc | pa;
}static uint64_t mattr_to_desc(unsigned level, uint32_t attr)
{uint64_t desc;uint32_t a = attr;if (a & TEE_MATTR_HIDDEN_BLOCK)return INVALID_DESC | HIDDEN_DESC;if (a & TEE_MATTR_HIDDEN_DIRTY_BLOCK)return INVALID_DESC | HIDDEN_DIRTY_DESC;if (a & TEE_MATTR_TABLE)return TABLE_DESC;if (!(a & TEE_MATTR_VALID_BLOCK))return 0;if (a & (TEE_MATTR_PX | TEE_MATTR_PW))a |= TEE_MATTR_PR;if (a & (TEE_MATTR_UX | TEE_MATTR_UW))a |= TEE_MATTR_UR;if (a & TEE_MATTR_UR)a |= TEE_MATTR_PR;if (a & TEE_MATTR_UW)a |= TEE_MATTR_PW;if (level == 3)desc = L3_BLOCK_DESC;elsedesc = BLOCK_DESC;if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX)))desc |= UPPER_ATTRS(XN);if (!(a & TEE_MATTR_PX))desc |= UPPER_ATTRS(PXN);if (a & TEE_MATTR_UR)desc |= LOWER_ATTRS(AP_UNPRIV);if (!(a & TEE_MATTR_PW))desc |= LOWER_ATTRS(AP_RO);/* Keep in sync with core_mmu.c:core_mmu_mattr_is_ok */switch ((a >> TEE_MATTR_CACHE_SHIFT) & TEE_MATTR_CACHE_MASK) {case TEE_MATTR_CACHE_NONCACHE:desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);break;case TEE_MATTR_CACHE_CACHED:desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);break;default:/** "Can't happen" the attribute is supposed to be checked* with core_mmu_mattr_is_ok() before.*/panic();}if (a & (TEE_MATTR_UR | TEE_MATTR_PR))desc |= LOWER_ATTRS(ACCESS_FLAG);if (!(a & TEE_MATTR_GLOBAL))desc |= LOWER_ATTRS(NON_GLOBAL);desc |= a & TEE_MATTR_SECURE ? 0 : LOWER_ATTRS(NS);return desc;
}

下图是一个页表创建的过程:

optee内存管理和页表建立相关推荐

  1. Linux内存管理 (2)页表的映射过程

    专题:Linux内存管理专题 关键词:swapper_pd_dir.ARM PGD/PTE.Linux PGD/PTE.pgd_offset_k. Linux下的页表映射分为两种,一是Linux自身的 ...

  2. Linux内核机制总结内存管理之页表缓存(十九)

    文章目录 1 页表缓存 1.1 TLB表项格式 1.2 TLB管理 1.3 地址空间标识符 1.4 虚拟机标识符 重要:本系列文章内容摘自<Linux内核深度解析>基于ARM64架构的Li ...

  3. optee中MMU内存管理模型-页表的建立模型

    思考: 1.__identity_map_init_start 的干啥的,作用? ----看起来是给ALSR用的,暂且不研究 MMU页表的创建模型,在optee os系统中,有很多种类型的memory ...

  4. OPTEE的内存管理 :页表的创建过程

    关键词: optee.ATF.TF-A.Trustzone.optee3.14.MMU.VMSA.cache.TLB.arm.armv8.armv9.TEE.安全.内存管理.页表- 快速链接: .

  5. OPTEE的内存管理 : 将内存加入到页表去管理

    关键词: optee.ATF.TF-A.Trustzone.optee3.14.MMU.VMSA.cache.TLB.arm.armv8.armv9.TEE.安全.内存管理.页表- 快速链接: .

  6. Linux内核初始化阶段内存管理的几种阶段

    本系列旨在讲述从引导到完全建立内存管理体系过程中,内核对内存管理所经历的几种状态.阅读本系列前,建议先阅读memblock的相关文章. 一些讲在前面的话 在很久很久以前,linux内核还是支持直接从磁 ...

  7. 内存分段分页机制理解_深度干货 | 真棒! 20 张图揭开内存管理的迷雾,瞬间豁然开朗...

    openEA开源周刊 openEA开源社区的官方运营载体 这里每天给大家呈现有价值的开源资讯,欢迎您的来稿与推荐,点击上方蓝色字,加入我们吧! 摘要:本篇跟大家说说内存管理,内存管理还是比较重要的一个 ...

  8. 20 张图揭开内存管理的迷雾,瞬间豁然开朗

    每日英语,每天进步一点点 前言 之前有不少读者跟我反馈,能不能写图解操作系统? 既然那么多读者想看,我最近就在疯狂的复习操作系统的知识. 操作系统确实是比较难啃的一门课,至少我认为比计算机网络难太多了 ...

  9. 从内存管理原理,窥探OS内存管理机制

    摘要:本文将从最简单的内存管理原理说起,带大家一起窥探OS的内存管理机制,由此熟悉底层的内存管理机制,写出高效的应用程序. 本文分享自华为云社区<探索OS的内存管理原理>,作者:元闰子 . ...

最新文章

  1. c语言windows程序设计 - 第十天,C语言Windows程序设计 - 第十天 - 响应键盘事件...
  2. linux中用截取一些信息,Linux如何使用cut命令截取文件信息
  3. 多路隔离输出的车载辅助电源设计
  4. DDD - 如何理解Entity与VO
  5. JSP Problem(第一次创建Web Project报错)
  6. Android 屏幕常亮、低电量监听
  7. 安装Docker环境并下载TensorFlow镜像
  8. 最早会外语的人,是怎么回事
  9. 李开复:几年内电子商务上市潮会来临
  10. 洛谷 P4200 千山鸟飞绝平衡树
  11. 计算机教室英语手抄报,关于教室的英语手抄报,英语手抄报简单又清楚?
  12. 【总结】最好的CV学习小组,超200个课时+10个方向+30个项目,从理论到实践全部系统掌握...
  13. 楼宇自动化专用BACnet网关BL103
  14. codeforces 1177B
  15. [object HTMLDivElement] 创建dom报与 innerHTML appendChild使用
  16. 原创:谈谈计算机图像识别技术之身份证号码识别
  17. 30天自制操作系统_序
  18. js数组遍历相关方法
  19. 【3D detection】CT3D部分代码的理解
  20. android分享图片到qq,Android 如何实现本地图片直接分享到微信、来往、QQ等,直接分享...

热门文章

  1. ios 后台唤醒应用_手机应用后台不断唤醒,耗电大,荣耀手机只需简单几步就可以解决...
  2. 成功解决极其刁钻bug之TypeError: ‘<=‘ not supported between instances of ‘list‘ and ‘int‘
  3. AI:百度飞桨EasyDL多门视频课程,手把手教你如何定制高精度AI模型
  4. 成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
  5. WSL:WSL(Windows Subsystem for Linux)的简介、安装、使用方法之详细攻略
  6. CV:基于Keras利用CNN主流架构之mini_XCEPTION训练性别分类模型hdf5并保存到指定文件夹下
  7. 【Linux】一步一步学Linux——Unix发展史(02)
  8. 371. 两整数之和
  9. 实验三:xen环境下的第一个虚拟机的安装
  10. 2017-2018-1 20155330 《信息安全系统设计基础》第11周学习总结