简单的成绩录入系统程序及分析以及思考
600
2022-05-30
鸿蒙轻内核A核源码分析系列五 虚实映射(4)
7、Flag标签属性
在学习函数LOS_ArchMmuMap()代码时,我们已经了解了虚拟内存如何映射到物理内存,在映射的时候,可以通过UINT 32 flags参数定一些标签属性信息。本节,我们具体了解下内存标签属性信息。先了解下MMU标签属性,然后看看映射内存区间时的映射虚实信息,最后了解下属性信息转换函数。
7.1 MMU标签属性
在映射的时候,对于内存页可以指定一些内存属性,比如权限、内存类型、缓存策略等等。更多信息参考ARM官网资料《ARM® Cortex™-A Series Version: 4.0 Programmer’s Guide》,我们只快速摘录些关键信息。L1页表项的格式如下图所示,其中Type extension (TEX), Shareable (S), Access Permission (AP, APX)、 Cacheable (C)、 Bufferable (B)位表示内存属性信息。在arch\arm\arm\include\los_mmu_descriptor_v6.h文件中定义了MMU L1页表内存属性相关的宏,如下。
/* TEX CB */ #define MMU_DESCRIPTOR_L1_TEX_SHIFT 12 /* type extension field shift */ #define MMU_DESCRIPTOR_L1_TEX(x) \ ((x) << MMU_DESCRIPTOR_L1_TEX_SHIFT) /* type extension */ #define MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED \ (MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_NON_CACHEABLE) #define MMU_DESCRIPTOR_L1_TYPE_NORMAL_NOCACHE \ (MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_NON_CACHEABLE) #define MMU_DESCRIPTOR_L1_TYPE_DEVICE_SHARED \ (MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_WRITE_BACK_ALLOCATE) #define MMU_DESCRIPTOR_L1_TYPE_DEVICE_NON_SHARED \ (MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_2) | MMU_DESCRIPTOR_NON_CACHEABLE) #define MMU_DESCRIPTOR_L1_TYPE_NORMAL_WRITE_BACK_ALLOCATE \ (MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE) #define MMU_DESCRIPTOR_L1_TEX_TYPE_MASK \ (MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_MASK) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE) #define MMU_DESCRIPTOR_L1_AP2_SHIFT 15 #define MMU_DESCRIPTOR_L1_AP2(x) ((x) << MMU_DESCRIPTOR_L1_AP2_SHIFT) #define MMU_DESCRIPTOR_L1_AP2_0 (MMU_DESCRIPTOR_L1_AP2(0)) #define MMU_DESCRIPTOR_L1_AP2_1 (MMU_DESCRIPTOR_L1_AP2(1)) #define MMU_DESCRIPTOR_L1_AP01_SHIFT 10 #define MMU_DESCRIPTOR_L1_AP01(x) ((x) << MMU_DESCRIPTOR_L1_AP01_SHIFT) #define MMU_DESCRIPTOR_L1_AP01_0 (MMU_DESCRIPTOR_L1_AP01(0)) #define MMU_DESCRIPTOR_L1_AP01_1 (MMU_DESCRIPTOR_L1_AP01(1)) #define MMU_DESCRIPTOR_L1_AP01_3 (MMU_DESCRIPTOR_L1_AP01(3)) #define MMU_DESCRIPTOR_L1_AP_P_NA_U_NA (MMU_DESCRIPTOR_L1_AP2_0 | MMU_DESCRIPTOR_L1_AP01_0) #define MMU_DESCRIPTOR_L1_AP_P_RW_U_RW (MMU_DESCRIPTOR_L1_AP2_0 | MMU_DESCRIPTOR_L1_AP01_3) #define MMU_DESCRIPTOR_L1_AP_P_RW_U_NA (MMU_DESCRIPTOR_L1_AP2_0 | MMU_DESCRIPTOR_L1_AP01_1) #define MMU_DESCRIPTOR_L1_AP_P_RO_U_RO (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_3) #define MMU_DESCRIPTOR_L1_AP_P_RO_U_NA (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_1) #define MMU_DESCRIPTOR_L1_AP_MASK (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_3)
L2页表项的格式如下图所示。在arch\arm\arm\include\los_mmu_descriptor_v6.h文件中定义了MMU L2页表内存属性相关的宏,如下。
#define MMU_DESCRIPTOR_L2_TEX_SHIFT 6 /* type extension field shift */ #define MMU_DESCRIPTOR_L2_TEX(x) \ ((x) << MMU_DESCRIPTOR_L2_TEX_SHIFT) /* type extension */ #define MMU_DESCRIPTOR_L2_TYPE_STRONGLY_ORDERED \ (MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_NON_CACHEABLE) #define MMU_DESCRIPTOR_L2_TYPE_NORMAL_NOCACHE \ (MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_NON_CACHEABLE) #define MMU_DESCRIPTOR_L2_TYPE_DEVICE_SHARED \ (MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_WRITE_BACK_ALLOCATE) #define MMU_DESCRIPTOR_L2_TYPE_DEVICE_NON_SHARED \ (MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_2) | MMU_DESCRIPTOR_NON_CACHEABLE) #define MMU_DESCRIPTOR_L2_TYPE_NORMAL_WRITE_BACK_ALLOCATE \ (MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE) #define MMU_DESCRIPTOR_L2_TEX_TYPE_MASK \ (MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_MASK) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE) #define MMU_DESCRIPTOR_L2_AP2_SHIFT 9 #define MMU_DESCRIPTOR_L2_AP2(x) ((x) << MMU_DESCRIPTOR_L2_AP2_SHIFT) #define MMU_DESCRIPTOR_L2_AP2_0 (MMU_DESCRIPTOR_L2_AP2(0)) #define MMU_DESCRIPTOR_L2_AP2_1 (MMU_DESCRIPTOR_L2_AP2(1)) #define MMU_DESCRIPTOR_L2_AP01_SHIFT 4 #define MMU_DESCRIPTOR_L2_AP01(x) ((x) << MMU_DESCRIPTOR_L2_AP01_SHIFT) #define MMU_DESCRIPTOR_L2_AP01_0 (MMU_DESCRIPTOR_L2_AP01(0)) #define MMU_DESCRIPTOR_L2_AP01_1 (MMU_DESCRIPTOR_L2_AP01(1)) #define MMU_DESCRIPTOR_L2_AP01_3 (MMU_DESCRIPTOR_L2_AP01(3)) #define MMU_DESCRIPTOR_L2_AP_P_NA_U_NA (MMU_DESCRIPTOR_L2_AP2_0 | MMU_DESCRIPTOR_L2_AP01_0) #define MMU_DESCRIPTOR_L2_AP_P_RW_U_RW (MMU_DESCRIPTOR_L2_AP2_0 | MMU_DESCRIPTOR_L2_AP01_3) #define MMU_DESCRIPTOR_L2_AP_P_RW_U_NA (MMU_DESCRIPTOR_L2_AP2_0 | MMU_DESCRIPTOR_L2_AP01_1) #define MMU_DESCRIPTOR_L2_AP_P_RO_U_RO (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_3) #define MMU_DESCRIPTOR_L2_AP_P_RO_U_NA (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_1) #define MMU_DESCRIPTOR_L2_AP_MASK (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_3)
7.2 映射地址区间标签属性
kernel\base\include\los_vm_map.h文件中定义地址区间映射标签属性信息。标签属性信息主要分为4类,如图所示。前2位用于标记释放缓存设备,2-5位用于标记权限信息,6-8位用于标记共享私有等信息,9-19位用于标记stack、heap、data、text、bss、vsdo、mmap、shm、fixed、fixed_noreplace等属性信息。20-23位暂未使用,高8位被共享内存SHM使用。
/* the high 8 bits(24~31) should reserved, shm will use it */ #define VM_MAP_REGION_FLAG_CACHED (0<<0) #define VM_MAP_REGION_FLAG_UNCACHED (1<<0) #define VM_MAP_REGION_FLAG_UNCACHED_DEVICE (2<<0) /* only exists on some arches, otherwise UNCACHED */ #define VM_MAP_REGION_FLAG_STRONGLY_ORDERED (3<<0) /* only exists on some arches, otherwise UNCACHED */ #define VM_MAP_REGION_FLAG_CACHE_MASK (3<<0) #define VM_MAP_REGION_FLAG_PERM_USER (1<<2) #define VM_MAP_REGION_FLAG_PERM_READ (1<<3) #define VM_MAP_REGION_FLAG_PERM_WRITE (1<<4) #define VM_MAP_REGION_FLAG_PERM_EXECUTE (1<<5) #define VM_MAP_REGION_FLAG_PROT_MASK (0xF<<2) #define VM_MAP_REGION_FLAG_NS (1<<6) /* NON-SECURE */ #define VM_MAP_REGION_FLAG_SHARED (1<<7) #define VM_MAP_REGION_FLAG_PRIVATE (1<<8) #define VM_MAP_REGION_FLAG_FLAG_MASK (3<<7) #define VM_MAP_REGION_FLAG_STACK (1<<9) #define VM_MAP_REGION_FLAG_HEAP (1<<10) #define VM_MAP_REGION_FLAG_DATA (1<<11) #define VM_MAP_REGION_FLAG_TEXT (1<<12) #define VM_MAP_REGION_FLAG_BSS (1<<13) #define VM_MAP_REGION_FLAG_VDSO (1<<14) #define VM_MAP_REGION_FLAG_MMAP (1<<15) #define VM_MAP_REGION_FLAG_SHM (1<<16) #define VM_MAP_REGION_FLAG_FIXED (1<<17) #define VM_MAP_REGION_FLAG_FIXED_NOREPLACE (1<<18) #define VM_MAP_REGION_FLAG_INVALID (1<<19) /* indicates that flags are not specified */
7.3 标签转换操作
7.3.1 OsCvtProtFlagsToRegionFlags函数
函数OsCvtProtFlagsToRegionFlags()把保护属性转换为虚拟内存区间标签属性,该函数在系统调用、共享内存等模块会使用。参数unsigned long prot中的保护标签属性如PROT_READ、MAP_SHARED等等,定义在文件third_party/musl/porting/liteos_a/kernel/include/sys/mman.h。
STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags) { UINT32 regionFlags = 0; regionFlags |= VM_MAP_REGION_FLAG_PERM_USER; regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0; regionFlags |= (prot & PROT_WRITE) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0; regionFlags |= (prot & PROT_EXEC) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_EXECUTE) : 0; regionFlags |= (flags & MAP_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0; regionFlags |= (flags & MAP_PRIVATE) ? VM_MAP_REGION_FLAG_PRIVATE : 0; regionFlags |= (flags & MAP_FIXED) ? VM_MAP_REGION_FLAG_FIXED : 0; regionFlags |= (flags & MAP_FIXED_NOREPLACE) ? VM_MAP_REGION_FLAG_FIXED_NOREPLACE : 0; return regionFlags; }
7.3.2 OsCvtSecFlagsToAttrs函数和OsCvtSecAttsToFlags函数
OsCvtSecFlagsToAttrs函数用于把内存区域映射标签属性转换为L1 Section类型页表项的MMU标签属性。该函数又分为2个函数,分别是⑴处的OsCvtSecCacheFlagsToMMUFlags()函数和⑵处的OsCvtSecAccessFlagsToMMUFlags()函数。OsCvtSecCacheFlagsToMMUFlags()函数主要判断内存映射区域的低2位缓存标签属性的转换。OsCvtSecAccessFlagsToMMUFlags()函数用于映射标签属性的2-4位访问权限部分的转换。代码比较简单不再赘述。
⑶处的函数OsCvtSecAttsToFlags()是上述函数OsCvtSecFlagsToAttrs的逆过程,用于把L1 Section类型页表项的MMU标签属性转换为内存区域映射标签属性。自行阅读代码,不再逐行分析。
⑴ STATIC UINT32 OsCvtSecCacheFlagsToMMUFlags(UINT32 flags) { UINT32 mmuFlags = 0; switch (flags & VM_MAP_REGION_FLAG_CACHE_MASK) { case VM_MAP_REGION_FLAG_CACHED: mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_NORMAL_WRITE_BACK_ALLOCATE; #ifdef LOSCFG_KERNEL_SMP mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_SHAREABLE; #endif break; case VM_MAP_REGION_FLAG_STRONGLY_ORDERED: mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED; break; case VM_MAP_REGION_FLAG_UNCACHED: mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_NORMAL_NOCACHE; break; case VM_MAP_REGION_FLAG_UNCACHED_DEVICE: mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_DEVICE_SHARED; break; default: return LOS_ERRNO_VM_INVALID_ARGS; } return mmuFlags; } ⑵ STATIC UINT32 OsCvtSecAccessFlagsToMMUFlags(UINT32 flags) { UINT32 mmuFlags = 0; switch (flags & (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE)) { case 0: mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_NA_U_NA; break; case VM_MAP_REGION_FLAG_PERM_READ: case VM_MAP_REGION_FLAG_PERM_USER: mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RO_U_NA; break; case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ: mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RO_U_RO; break; case VM_MAP_REGION_FLAG_PERM_WRITE: case VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE: mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RW_U_NA; break; case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE: case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE: mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RW_U_RW; break; default: break; } return mmuFlags; } /* convert user level mmu flags to L1 descriptors flags */ STATIC UINT32 OsCvtSecFlagsToAttrs(UINT32 flags) { UINT32 mmuFlags; mmuFlags = OsCvtSecCacheFlagsToMMUFlags(flags); if (mmuFlags == LOS_ERRNO_VM_INVALID_ARGS) { return mmuFlags; } mmuFlags |= MMU_DESCRIPTOR_L1_SMALL_DOMAIN_CLIENT; mmuFlags |= OsCvtSecAccessFlagsToMMUFlags(flags); if (!(flags & VM_MAP_REGION_FLAG_PERM_EXECUTE)) { mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_XN; } if (flags & VM_MAP_REGION_FLAG_NS) { mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_NON_SECURE; } if (flags & VM_MAP_REGION_FLAG_PERM_USER) { mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_NON_GLOBAL; } return mmuFlags; } ⑶ STATIC VOID OsCvtSecAttsToFlags(PTE_T l1Entry, UINT32 *flags) { *flags = 0; if (l1Entry & MMU_DESCRIPTOR_L1_SECTION_NON_SECURE) { *flags |= VM_MAP_REGION_FLAG_NS; } switch (l1Entry & MMU_DESCRIPTOR_L1_TEX_TYPE_MASK) { case MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED: *flags |= VM_MAP_REGION_FLAG_STRONGLY_ORDERED; break; case MMU_DESCRIPTOR_L1_TYPE_NORMAL_NOCACHE: *flags |= VM_MAP_REGION_FLAG_UNCACHED; break; case MMU_DESCRIPTOR_L1_TYPE_DEVICE_SHARED: case MMU_DESCRIPTOR_L1_TYPE_DEVICE_NON_SHARED: *flags |= VM_MAP_REGION_FLAG_UNCACHED_DEVICE; break; default: break; } *flags |= VM_MAP_REGION_FLAG_PERM_READ; switch (l1Entry & MMU_DESCRIPTOR_L1_AP_MASK) { case MMU_DESCRIPTOR_L1_AP_P_RO_U_NA: break; case MMU_DESCRIPTOR_L1_AP_P_RW_U_NA: *flags |= VM_MAP_REGION_FLAG_PERM_WRITE; break; case MMU_DESCRIPTOR_L1_AP_P_RO_U_RO: *flags |= VM_MAP_REGION_FLAG_PERM_USER; break; case MMU_DESCRIPTOR_L1_AP_P_RW_U_RW: *flags |= VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE; break; default: break; } if (!(l1Entry & MMU_DESCRIPTOR_L1_SECTION_XN)) { *flags |= VM_MAP_REGION_FLAG_PERM_EXECUTE; } }
7.3.3 OsCvtPte2FlagsToAttrs函数和OsCvtPte2AttsToFlags函数
和上一小节非常类似,上节是L1 Section类型页表项MMU属性和内存区域标签属性的相互转换,本节的2个函数是L2页表项MMU属性和内存区域标签属性的相互转换。函数OsCvtPte2FlagsToAttrs()把内存区域映射标签属性转换为L2页表项MMU属性,又分为2个函数,分别是⑴处的函数OsCvtPte2CacheFlagsToMMUFlags()和⑵处的OsCvtPte2AccessFlagsToMMUFlags()。OsCvtPte2CacheFlagsToMMUFlags()函数主要判断内存映射区域的低2位缓存标签属性的转换。OsCvtPte2AccessFlagsToMMUFlags()函数用于映射标签属性的2-4位访问权限部分的转换。代码比较简单不再赘述。
⑶处的函数OsCvtPte2AttsToFlags()是上述函数OsCvtPte2FlagsToAttrs的逆过程,用于把L2页表项的MMU标签属性转换为内存区域映射标签属性。自行阅读代码,不再逐行分析。
⑴ STATIC UINT32 OsCvtPte2CacheFlagsToMMUFlags(UINT32 flags) { UINT32 mmuFlags = 0; switch (flags & VM_MAP_REGION_FLAG_CACHE_MASK) { case VM_MAP_REGION_FLAG_CACHED: #ifdef LOSCFG_KERNEL_SMP mmuFlags |= MMU_DESCRIPTOR_L2_SHAREABLE; #endif mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_NORMAL_WRITE_BACK_ALLOCATE; break; case VM_MAP_REGION_FLAG_STRONGLY_ORDERED: mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_STRONGLY_ORDERED; break; case VM_MAP_REGION_FLAG_UNCACHED: mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_NORMAL_NOCACHE; break; case VM_MAP_REGION_FLAG_UNCACHED_DEVICE: mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_DEVICE_SHARED; break; default: return LOS_ERRNO_VM_INVALID_ARGS; } return mmuFlags; } ⑵ STATIC UINT32 OsCvtPte2AccessFlagsToMMUFlags(UINT32 flags) { UINT32 mmuFlags = 0; switch (flags & (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE)) { case 0: mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_NA_U_NA; break; case VM_MAP_REGION_FLAG_PERM_READ: case VM_MAP_REGION_FLAG_PERM_USER: mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RO_U_NA; break; case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ: mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RO_U_RO; break; case VM_MAP_REGION_FLAG_PERM_WRITE: case VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE: mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RW_U_NA; break; case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE: case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE: mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RW_U_RW; break; default: break; } return mmuFlags; } /* convert user level mmu flags to L2 descriptors flags */ STATIC UINT32 OsCvtPte2FlagsToAttrs(UINT32 flags) { UINT32 mmuFlags; mmuFlags = OsCvtPte2CacheFlagsToMMUFlags(flags); if (mmuFlags == LOS_ERRNO_VM_INVALID_ARGS) { return mmuFlags; } mmuFlags |= OsCvtPte2AccessFlagsToMMUFlags(flags); if (!(flags & VM_MAP_REGION_FLAG_PERM_EXECUTE)) { mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE_XN; } else { mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE; } if (flags & VM_MAP_REGION_FLAG_PERM_USER) { mmuFlags |= MMU_DESCRIPTOR_L2_NON_GLOBAL; } return mmuFlags; } ⑶ STATIC VOID OsCvtPte2AttsToFlags(PTE_T l1Entry, PTE_T l2Entry, UINT32 *flags) { *flags = 0; /* NS flag is only present on L1 entry */ if (l1Entry & MMU_DESCRIPTOR_L1_PAGETABLE_NON_SECURE) { *flags |= VM_MAP_REGION_FLAG_NS; } switch (l2Entry & MMU_DESCRIPTOR_L2_TEX_TYPE_MASK) { case MMU_DESCRIPTOR_L2_TYPE_STRONGLY_ORDERED: *flags |= VM_MAP_REGION_FLAG_STRONGLY_ORDERED; break; case MMU_DESCRIPTOR_L2_TYPE_NORMAL_NOCACHE: *flags |= VM_MAP_REGION_FLAG_UNCACHED; break; case MMU_DESCRIPTOR_L2_TYPE_DEVICE_SHARED: case MMU_DESCRIPTOR_L2_TYPE_DEVICE_NON_SHARED: *flags |= VM_MAP_REGION_FLAG_UNCACHED_DEVICE; break; default: break; } *flags |= VM_MAP_REGION_FLAG_PERM_READ; switch (l2Entry & MMU_DESCRIPTOR_L2_AP_MASK) { case MMU_DESCRIPTOR_L2_AP_P_RO_U_NA: break; case MMU_DESCRIPTOR_L2_AP_P_RW_U_NA: *flags |= VM_MAP_REGION_FLAG_PERM_WRITE; break; case MMU_DESCRIPTOR_L2_AP_P_RO_U_RO: *flags |= VM_MAP_REGION_FLAG_PERM_USER; break; case MMU_DESCRIPTOR_L2_AP_P_RW_U_RW: *flags |= VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE; break; default: break; } if ((l2Entry & MMU_DESCRIPTOR_L2_TYPE_MASK) != MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE_XN) { *flags |= VM_MAP_REGION_FLAG_PERM_EXECUTE; } }
IoT 虚拟化 轻量级操作系统 LiteOS
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。