淘宝做网站费用,免费建站的手机app,win7和WordPress的关系,西安高风险调整MMU简介
MMU#xff08;内存管理单元#xff09;负责将软件使用的虚拟地址转换为内存系统中使用的物理地址。MMU包括两个模块#xff1a;TLB#xff08;Translation Lookaside Buffer#xff09;和TWU#xff08;Table Walk Unit#xff09;。TLB缓存最近使用的转换内存管理单元负责将软件使用的虚拟地址转换为内存系统中使用的物理地址。MMU包括两个模块TLBTranslation Lookaside Buffer和TWUTable Walk Unit。TLB缓存最近使用的转换类似cache将转换映射放入缓存提高映射效率而TWU从内存中读取转换表查表完成虚拟地址到物理地址的转换。
转换表位于内存中用于存储虚拟地址和物理地址之间的映射另外还包括物理内存位置的属性。这些转换表是由内存管理单元MMU访问。
软件分配的所有内存地址都是虚拟的。这些内存地址被传递到 MMUMMU 检查 TLB 中是否有最近使用的缓存转换。如果 MMU 没有找到最近缓存的转换TWU会从内存中读取相应的表条目如下所示 转换XLAT表库
代码结构
转换表库有两个版本V1和V2我们这里只关注V2的转换表库。
├── aarch64
│ ├── enable_mmu.S
│ └── xlat_tables_arch.c
├── ro_xlat_tables.mk
├── xlat_tables.mk
├── xlat_tables_context.c
├── xlat_tables_core.c
├── xlat_tables_private.h
└── xlat_tables_utils.c核心模块主要是xlat_tables_core.c文件提供转换上下文初始化和内存映射等功能上下文模块主要是xlat_tables_context.c文件提供添加映射区域等接口工具模块主要是xlat_tables_utils.c文件提供转换表状态打印内存属性查看等功能架构模块主要是xlat_tables_arch.c文件提供TLB无效创建MMU及计算物理地址空间大小等功能
映射区域
mmap regions是对要内存映射区域的抽象。
/** Structure for specifying a single region of memory.*/
typedef struct mmap_region {unsigned long long base_pa;uintptr_t base_va;size_t size;unsigned int attr;/* Desired granularity. See the MAP_REGION2() macro for more details. */size_t granularity;
} mmap_region_t;base_pa物理基地址base_va虚拟基地址size大小attr属性granularity映射粒度
为了不直接使用结构体struct mmap_region使用宏MAP_REGION和MAP_REGION_PLAT定义映射区域。
/** Default granularity size for an mmap_region_t.* Useful when no specific granularity is required.** By default, choose the biggest possible block size allowed by the* architectural state and granule size in order to minimize the number of page* tables required for the mapping.*/
#define REGION_DEFAULT_GRANULARITY XLAT_BLOCK_SIZE(MIN_LVL_BLOCK_DESC)/* Helper macro to define an mmap_region_t. */
#define MAP_REGION(_pa, _va, _sz, _attr) \MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, REGION_DEFAULT_GRANULARITY)/* Helper macro to define an mmap_region_t with an identity mapping. */
#define MAP_REGION_FLAT(_adr, _sz, _attr) \MAP_REGION(_adr, _adr, _sz, _attr)可以看出最终展开到宏MAP_REGION_FULL_SPEC定义如下。
/** Helper macro to define an mmap_region_t. This macro allows to specify all* the fields of the structure but its parameter list is not guaranteed to* remain stable as we add members to mmap_region_t.*/
#define MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) \{ \.base_pa (_pa), \.base_va (_va), \.size (_sz), \.attr (_attr), \.granularity (_gr), \}内存属性
内存属性包括内存类型、访问权限、执行权限以及缓存性与共享性等。
/** Memory mapping attributes*//** Memory types supported.* These are organised so that, going down the list, the memory types are* getting weaker; conversely going up the list the memory types are getting* stronger.*/
#define MT_DEVICE U(0)
#define MT_NON_CACHEABLE U(1)
#define MT_MEMORY U(2)
/* Values up to 7 are reserved to add new memory types in the future */#define MT_RO (U(0) MT_PERM_SHIFT)
#define MT_RW (U(1) MT_PERM_SHIFT)#define MT_SECURE (U(0) MT_PAS_SHIFT)
#define MT_NS (U(1) MT_PAS_SHIFT)
#define MT_ROOT (U(2) MT_PAS_SHIFT)
#define MT_REALM (U(3) MT_PAS_SHIFT)/** Access permissions for instruction execution are only relevant for normal* read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially* overridden) otherwise:* - Device memory is always marked as execute-never.* - Read-write normal memory is always marked as execute-never.*/
#define MT_EXECUTE (U(0) MT_EXECUTE_SHIFT)
#define MT_EXECUTE_NEVER (U(1) MT_EXECUTE_SHIFT)/** When mapping a region at EL0 or EL1, this attribute will be used to determine* if a User mapping (EL0) will be created or a Privileged mapping (EL1).*/
#define MT_USER (U(1) MT_USER_SHIFT)
#define MT_PRIVILEGED (U(0) MT_USER_SHIFT)/** Shareability defines the visibility of any cache changes to* all masters belonging to a shareable domain.** MT_SHAREABILITY_ISH: For inner shareable domain* MT_SHAREABILITY_OSH: For outer shareable domain* MT_SHAREABILITY_NSH: For non shareable domain*/
#define MT_SHAREABILITY_ISH (U(1) MT_SHAREABILITY_SHIFT)
#define MT_SHAREABILITY_OSH (U(2) MT_SHAREABILITY_SHIFT)
#define MT_SHAREABILITY_NSH (U(3) MT_SHAREABILITY_SHIFT)/* Compound attributes for most common usages */
#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE)
#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
#define MT_RW_DATA (MT_MEMORY | MT_RW | MT_EXECUTE_NEVER)内存类型设备内存MT_DEVICE不带Cache普通内存MT_NON_CACHEABLE普通内存MT_MEMORY。访问权限只读RO读写RW。物理地址空间安全属性安全MT_SECURE非安全MT_NSROOTMT_ROOTREALMMT_REALM后面两种是Armv9新增的RME。指令执行权限可执行MT_EXECUTE不可执行MT_EXECUTE_NEVER。执行权限仅对普通只读内存有效即MT_MEMORY | MT_RO。设备内存和读写内存始终标记为不可执行即忽略执行权限。EL0/EL1虚拟地址空间有两个区域布局内核空间和应用空间下面定义了转换表选择用户空间映射MT_USER内核空间映射MT_PRIVILEGED。对于属于一个共享域中的Master定义了缓存共享性内部共享MT_SHAREABILITY_ISH外部共享MT_SHAREABILITY_OSH没有共享性MT_SHAREABILITY_NSH。最后结合上面定义了一些常用的属性代码MT_CODE只读数据MT_RO_DATA读写数据MT_RW_DATA。
另外还定义了EL3下的内存类型如果使能了RMEEL3的PAS物理地址空间属性是ROOT否则是SECURE。
/* Memory type for EL3 regions. With RME, EL3 is in ROOT PAS */
#if ENABLE_RME
#define EL3_PAS MT_ROOT
#else
#define EL3_PAS MT_SECURE
#endif /* ENABLE_RME */转换上下文
转换上下文存放了转换表的所有信息结构体定义如下
/* Struct that holds all information about the translation tables. */
struct xlat_ctx {/** Max allowed Virtual and Physical Addresses.*/unsigned long long pa_max_address;uintptr_t va_max_address;/** Array of all memory regions stored in order of ascending end address* and ascending size to simplify the code that allows overlapping* regions. The list is terminated by the first entry with size 0.* The max size of the list is stored in mmap_num. mmap points to an* array of mmap_num 1 elements, so that there is space for the final* null entry.*/struct mmap_region *mmap;int mmap_num;/** Array of finer-grain translation tables.* For example, if the initial lookup level is 1 then this array would* contain both level-2 and level-3 entries.*/uint64_t (*tables)[XLAT_TABLE_ENTRIES];int tables_num;
#if PLAT_RO_XLAT_TABLESbool readonly_tables;
#endif/** Keep track of how many regions are mapped in each table. The base* table cant be unmapped so it isnt needed to keep track of it.*/
#if PLAT_XLAT_TABLES_DYNAMICint *tables_mapped_regions;
#endif /* PLAT_XLAT_TABLES_DYNAMIC */int next_table;/** Base translation table. It doesnt need to have the same amount of* entries as the ones used for other levels.*/uint64_t *base_table;unsigned int base_table_entries;/** Max Physical and Virtual addresses currently in use by the* translation tables. These might get updated as we map/unmap memory* regions but they will never go beyond pa/va_max_address.*/unsigned long long max_pa;uintptr_t max_va;/* Level of the base translation table. */unsigned int base_level;/* Set to true when the translation tables are initialized. */bool initialized;/** Translation regime managed by this xlat_ctx_t. It should be one of* the EL*_REGIME defines.*/int xlat_regime;
};pa_max_address va_max_address允许的最大虚拟地址和物理地址。mmap mmap_num存放内存映射区域数组及数组大小按结束地址和大小升序排列。tables tables_num多级转换表项比如如果查询页表等级L1该数组存放L2页表项和L3页表项。base_table base_table_entries转换表基地址和表项数量。max_pa max_va当前转换表中最大的物理地址和虚拟地址。base_level基本转换表等级。initialized转换表是否初始化。xlat_regime转换机制包括EL1EL0EL1_EL0_REGIMEEL2EL2_REGIMEEL3EL3_REGIMEINVALIDEL_REGIME_INVALIDINVALID表示运行时决定。
对于启动阶段创建分配了一个默认转换上下文使用宏REGISTER_XLAT_CONTEXT定义。
REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \_virt_addr_space_size, _phy_addr_space_size) \REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \(_xlat_tables_count), \(_virt_addr_space_size), \(_phy_addr_space_size), \EL_REGIME_INVALID, \xlat_table, base_xlat_table)该宏需要提供如下参数
_ctx_name上下文名字_mmap_count需要分配的最大映射区域数_xlat_tables_count需要分配的次级页表数量_virt_addr_space_size虚拟地址空间大小_phy_addr_space_size物理地址空间大小
通用转换表API
每个API都有两种接口类型用于BL启动镜像的当前转换上下文用于给定的上下文以_ctx结尾。
初始化转换表
根据当前映射区域初始化转换表。在调用该API之后只允许添加动态内存区域。
/** Initialize translation tables from the current list of mmap regions. Calling* this function marks the transition point after which static regions can no* longer be added.*/
void init_xlat_tables(void);
void init_xlat_tables_ctx(xlat_ctx_t *ctx);init_xlat_tables最终也是调用init_xlat_tables_ctx函数只是先获取当前的运行异常等级配置使用哪个转换机制。
void __init init_xlat_tables(void)
{assert(tf_xlat_ctx.xlat_regime EL_REGIME_INVALID);unsigned int current_el xlat_arch_current_el();if (current_el 1U) {tf_xlat_ctx.xlat_regime EL1_EL0_REGIME;} else if (current_el 2U) {tf_xlat_ctx.xlat_regime EL2_REGIME;} else {assert(current_el 3U);tf_xlat_ctx.xlat_regime EL3_REGIME;}init_xlat_tables_ctx(tf_xlat_ctx);
}init_xlat_tables_ctx主要功能是将映射区域添加到转换表中定义如下关键函数为xlat_tables_map_region。
void __init init_xlat_tables_ctx(xlat_ctx_t *ctx)
{assert(ctx ! NULL);assert(!ctx-initialized);assert((ctx-xlat_regime EL3_REGIME) ||(ctx-xlat_regime EL2_REGIME) ||(ctx-xlat_regime EL1_EL0_REGIME));assert(!is_mmu_enabled_ctx(ctx));mmap_region_t *mm ctx-mmap;assert(ctx-va_max_address (xlat_get_min_virt_addr_space_size() - 1U));assert(ctx-va_max_address (MAX_VIRT_ADDR_SPACE_SIZE - 1U));assert(IS_POWER_OF_TWO(ctx-va_max_address 1U));xlat_mmap_print(mm);/* All tables must be zeroed before mapping any region. */for (unsigned int i 0U; i ctx-base_table_entries; i)ctx-base_table[i] INVALID_DESC;for (int j 0; j ctx-tables_num; j) {
#if PLAT_XLAT_TABLES_DYNAMICctx-tables_mapped_regions[j] 0;
#endiffor (unsigned int i 0U; i XLAT_TABLE_ENTRIES; i)ctx-tables[j][i] INVALID_DESC;}while (mm-size ! 0U) {uintptr_t end_va xlat_tables_map_region(ctx, mm, 0U,ctx-base_table, ctx-base_table_entries,ctx-base_level);
#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)xlat_clean_dcache_range((uintptr_t)ctx-base_table,ctx-base_table_entries * sizeof(uint64_t));
#endifif (end_va ! (mm-base_va mm-size - 1U)) {ERROR(Not enough memory to map region:\n VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x\n,mm-base_va, mm-base_pa, mm-size, mm-attr);panic();}mm;}assert(ctx-pa_max_address xlat_arch_get_max_supported_pa());assert(ctx-max_va ctx-va_max_address);assert(ctx-max_pa ctx-pa_max_address);ctx-initialized true;xlat_tables_print(ctx);
}添加映射区域
上面两个API是根据PA和VA添加映射区域下面两个是以数组形式进行添加映射区域。
/** Add a static region with defined base PA and base VA. This function can only* be used before initializing the translation tables. The region cannot be* removed afterwards.*/
void mmap_add_region(unsigned long long base_pa, uintptr_t base_va,size_t size, unsigned int attr);
void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);/** Add an array of static regions with defined base PA and base VA. This* function can only be used before initializing the translation tables. The* regions cannot be removed afterwards.*/
void mmap_add(const mmap_region_t *mm);
void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);在启动阶段定义了一个默认的转换上下文
/** Allocate and initialise the default translation context for the BL image* currently executing.*/
REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);mmap_add_region和mmap_add都是添加到这个默认的转换上下文中。
void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,unsigned int attr)
{mmap_region_t mm MAP_REGION(base_pa, base_va, size, attr);mmap_add_region_ctx(tf_xlat_ctx, mm);
}void mmap_add(const mmap_region_t *mm)
{mmap_add_ctx(tf_xlat_ctx, mm);
}上面最终都会调用mmap_add_region_ctx函数将定义的映射区域添加到转换上下文定义的数组中其是就是整合到一个映射区域数组中虚拟地址小和区域大小小的排在前面。
void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
{mmap_region_t *mm_cursor ctx-mmap, *mm_destination;const mmap_region_t *mm_end ctx-mmap ctx-mmap_num;const mmap_region_t *mm_last;unsigned long long end_pa mm-base_pa mm-size - 1U;uintptr_t end_va mm-base_va mm-size - 1U;int ret;/* Ignore empty regions */if (mm-size 0U)return;/* Static regions must be added before initializing the xlat tables. */assert(!ctx-initialized);ret mmap_add_region_check(ctx, mm);if (ret ! 0) {ERROR(mmap_add_region_check() failed. error %d\n, ret);assert(false);return;}/** Find correct place in mmap to insert new region.** 1 - Lower region VA end first.* 2 - Smaller region size first.** VA 0 0xFF** 1st |------|* 2nd |------------|* 3rd |------|* 4th |---|* 5th |---|* 6th |----------|* 7th |-------------------------------------|** This is required for overlapping regions only. It simplifies adding* regions with the loop in xlat_tables_init_internal because the outer* ones wont overwrite block or page descriptors of regions added* previously.** Overlapping is only allowed for static regions.*/while (((mm_cursor-base_va mm_cursor-size - 1U) end_va) (mm_cursor-size ! 0U)) {mm_cursor;}while (((mm_cursor-base_va mm_cursor-size - 1U) end_va) (mm_cursor-size ! 0U) (mm_cursor-size mm-size)) {mm_cursor;}/** Find the last entry marker in the mmap*/mm_last ctx-mmap;while ((mm_last-size ! 0U) (mm_last mm_end)) {mm_last;}/** Check if we have enough space in the memory mapping table.* This shouldnt happen as we have checked in mmap_add_region_check* that there is free space.*/assert(mm_last-size 0U);/* Make room for new region by moving other regions up by one place */mm_destination mm_cursor 1;(void)memmove(mm_destination, mm_cursor,(uintptr_t)mm_last - (uintptr_t)mm_cursor);/** Check we havent lost the empty sentinel from the end of the array.* This shouldnt happen as we have checked in mmap_add_region_check* that there is free space.*/assert(mm_end-size 0U);*mm_cursor *mm;if (end_pa ctx-max_pa)ctx-max_pa end_pa;if (end_va ctx-max_va)ctx-max_va end_va;
}启用MMU
启用MMU有两个函数setup_mmu_cfg和enable_mmu_direct_el*。定义了一个与MMU配置寄存器相对应的数组每个元素都是64位
/** MMU configuration register values for the active translation context. Used* from the MMU assembly helpers.*/
uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];setup_mmu_cfg是将转换上下文中信息存储到上面的配置寄存器数组中。
void setup_mmu_cfg(uint64_t *params, unsigned int flags,const uint64_t *base_table, unsigned long long max_pa,uintptr_t max_va, int xlat_regime)
{uint64_t mair, ttbr0, tcr;uintptr_t virtual_addr_space_size;/* Set attributes in the right indices of the MAIR. */mair MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);mair | MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX);mair | MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX);/** Limit the input address ranges and memory region sizes translated* using TTBR0 to the given virtual address space size.*/assert(max_va ((uint64_t)UINTPTR_MAX));virtual_addr_space_size (uintptr_t)max_va 1U;assert(virtual_addr_space_size xlat_get_min_virt_addr_space_size());assert(virtual_addr_space_size MAX_VIRT_ADDR_SPACE_SIZE);assert(IS_POWER_OF_TWO(virtual_addr_space_size));/** __builtin_ctzll(0) is undefined but here we are guaranteed that* virtual_addr_space_size is in the range [1,UINTPTR_MAX].*/int t0sz 64 - __builtin_ctzll(virtual_addr_space_size);tcr (uint64_t)t0sz TCR_T0SZ_SHIFT;/** Set the cacheability and shareability attributes for memory* associated with translation table walks.*/if ((flags XLAT_TABLE_NC) ! 0U) {/* Inner outer non-cacheable non-shareable. */tcr | TCR_SH_NON_SHAREABLE |TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC;} else {/* Inner outer WBWA shareable. */tcr | TCR_SH_INNER_SHAREABLE |TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA;}/** It is safer to restrict the max physical address accessible by the* hardware as much as possible.*/unsigned long long tcr_ps_bits tcr_physical_addr_size_bits(max_pa);if (xlat_regime EL1_EL0_REGIME) {/** TCR_EL1.EPD1: Disable translation table walk for addresses* that are translated using TTBR1_EL1.*/tcr | TCR_EPD1_BIT | (tcr_ps_bits TCR_EL1_IPS_SHIFT);} else if (xlat_regime EL2_REGIME) {tcr | TCR_EL2_RES1 | (tcr_ps_bits TCR_EL2_PS_SHIFT);} else {assert(xlat_regime EL3_REGIME);tcr | TCR_EL3_RES1 | (tcr_ps_bits TCR_EL3_PS_SHIFT);}/* Set TTBR bits as well */ttbr0 (uint64_t) base_table;if (is_armv8_2_ttcnp_present()) {/* Enable CnP bit so as to share page tables with all PEs. */ttbr0 | TTBR_CNP_BIT;}params[MMU_CFG_MAIR] mair;params[MMU_CFG_TCR] tcr;params[MMU_CFG_TTBR0] ttbr0;
}首先是设置内存属性到MAIR寄存器这里配置设备内存属性ATTR_DEVICE为Device_nGnRE即聚合、不重排和提前写应答普通内存属性为两种ATTR_NON_CACHEABLE即普通内存、高速缓存的回写策略为直写策略、内部无高速缓存ATTR_IWBWA_OWBWA_NTR即普通内存、内外均直写策略。
接着设置TCR_ELx寄存器TCR_ELx 寄存器中的 TnSZ 字段控制虚拟地址空间的大小其值为64 - 虚地址空间大小RGN字段控制共享性和缓存性PS/IPS控制PA或者IPA空间大小。
最后配置TTBR寄存器存放了页表的基地址这里使用了低位虚拟地址空间TTBR0。
enable_mmu_direct_elx是一段汇编实现将上面的数组配置到相应的MMU寄存器中然后使能MMU以enable_mmu_direct_el3为例实现如下。 func enable_mmu_direct_\()el\el
#if ENABLE_ASSERTIONS_mrs x1, sctlr, \eltst x1, #SCTLR_M_BITASM_ASSERT(eq)
#endif/* Invalidate all TLB entries */tlbi_invalidate_all \elmov x7, x0adrp x0, mmu_cfg_paramsadd x0, x0, :lo12:mmu_cfg_params/* MAIR */ldr x1, [x0, #(MMU_CFG_MAIR 3)]_msr mair, \el, x1/* TCR */ldr x2, [x0, #(MMU_CFG_TCR 3)]_msr tcr, \el, x2/* TTBR */ldr x3, [x0, #(MMU_CFG_TTBR0 3)]_msr ttbr0, \el, x3/** Ensure all translation table writes have drained into memory, the TLB* invalidation is complete, and translation register writes are* committed before enabling the MMU*/dsb ishisb/* Set and clear required fields of SCTLR */_mrs x4, sctlr, \elmov_imm x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BITorr x4, x4, x5/* Additionally, amend SCTLR fields based on flags */bic x5, x4, #SCTLR_C_BITtst x7, #DISABLE_DCACHEcsel x4, x5, x4, ne_msr sctlr, \el, x4isbretendfunc enable_mmu_direct_\()el\el示例
以ARM FVP平台BL1阶段为例并假设不支持RME。在arm_bl1_plat_arch_setup函数中会创建MMU页表并启用MMU。
void arm_bl1_plat_arch_setup(void)
{...const mmap_region_t bl_regions[] {MAP_BL1_TOTAL,MAP_BL1_RO,{0}};setup_page_tables(bl_regions, plat_arm_get_mmap());enable_mmu_el3(0);...
}内存映射区域
页表创建包括两种类型通用内存区域和特定平台内存区域。
通用内存区域
MAP_BL1_TOTAL定义了BL1可见的所有可信RAM空间属性为普通内存可读性安全。其宏展开如下
#define MAP_BL1_TOTAL MAP_REGION_FLAT( \bl1_tzram_layout.total_base, \bl1_tzram_layout.total_size, \MT_MEMORY | MT_RW | EL3_PAS)而MAP_BL1_RO定义了BL1的代码段内存属性为代码普通内存只读可执行安全。
#define MAP_BL1_RO MAP_REGION_FLAT( \BL_CODE_BASE, \BL1_CODE_END - BL_CODE_BASE, \MT_CODE | EL3_PAS)特定平台内存区域
对于不同的平台也需要创建平台相关的页表主要是外设并映射内存区域。FVP平台BL1阶段的plat_arm_get_mmap()定义为
/** Table of memory regions for various BL stages to map using the MMU.* This doesnt include Trusted SRAM as setup_page_tables() already takes care* of mapping it.*/
#ifdef IMAGE_BL1
const mmap_region_t plat_arm_mmap[] {ARM_MAP_SHARED_RAM,V2M_MAP_FLASH0_RO,V2M_MAP_IOFPGA,MAP_DEVICE0,
#if FVP_INTERCONNECT_DRIVER FVP_CCNMAP_DEVICE1,
#endif
#if TRUSTED_BOARD_BOOT/* To access the Root of Trust Public Key registers. */MAP_DEVICE2,/* Map DRAM to authenticate NS_BL2U image. */ARM_MAP_NS_DRAM1,
#endif{0}
};
#endif对于ARM_MAP_SHARED_RAM定义了共享内存区域属性为设备内存读写安全。其展开如下
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ARM_SHARED_RAM_BASE, \ARM_SHARED_RAM_SIZE, \MT_DEVICE | MT_RW | EL3_PAS)如果使能安全启动MAP_DEVICE2定义了访问设备根公钥寄存器内存区域属性为设备内存读写安全。其展开如下
#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \DEVICE2_SIZE, \MT_DEVICE | MT_RW | MT_SECURE)页表创建
setup_page_tables函数用于创建页表定义如下
/** Set up the page tables for the generic and platform-specific memory regions.* The size of the Trusted SRAM seen by the BL image must be specified as well* as an array specifying the generic memory regions which can be;* - Code section;* - Read-only data section;* - Init code section, if applicable* - Coherent memory region, if applicable.*/void __init setup_page_tables(const mmap_region_t *bl_regions,const mmap_region_t *plat_regions)
{/** Map the Trusted SRAM with appropriate memory attributes.* Subsequent mappings will adjust the attributes for specific regions.*/mmap_add(bl_regions);/* Now (re-)map the platform-specific memory regions */mmap_add(plat_regions);/* Create the page tables to reflect the above mappings */init_xlat_tables();
}分别将BL区域和平台自定义区域添加到转换表中然后创建页表添加映射关系。
启用MMU
由于BL1处于EL3等级调用enable_mmu_el3函数使能MMU。
void enable_mmu_el3(unsigned int flags)
{setup_mmu_cfg((uint64_t *)mmu_cfg_params, flags,tf_xlat_ctx.base_table, MAX_PHYS_ADDR,tf_xlat_ctx.va_max_address, EL3_REGIME);enable_mmu_direct_el3(flags);
}参考
万字长文带你搞定MMUTLBTWU
欢迎关注“安全有理”微信公众号。