鸿蒙轻内核A核源码分析系列五 虚实映射(7)虚实映射Flag属性

news2024/9/25 7:19:30

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 轻内核A核源码分析系列一 数据结构-双向循环链表
  • 轻内核A核源码分析系列二 数据结构-位图操作
  • 轻内核A核源码分析系列三 物理内存(1)
  • 轻内核A核源码分析系列三 物理内存(2)
  • 轻内核A核源码分析系列四(1)虚拟内存进程空间编号
  • 轻内核A核源码分析系列四(2) 虚拟内存
  • 轻内核A核源码分析系列四(3) 虚拟内存
  • 轻内核A核源码分析系列五 虚实映射(1)基础概念
  • 轻内核A核源码分析系列五 虚实映射(2)虚实映射初始化
  • 轻内核A核源码分析系列五 虚实映射(3)虚拟物理内存映射
  • 轻内核A核源码分析系列五 虚实映射(5)虚实映射解除
  • 轻内核A核源码分析系列五 虚实映射(6)虚拟映射修改转移
  • 轻内核A核源码分析系列五 虚实映射(7)虚实映射Flag属性
  • 轻内核A核源码分析系列六 MMU协处理器(1)
  • 轻内核A核源码分析系列六 MMU协处理器(2)
  • 轻内核A核源码分析系列七 进程管理 (1)
  • 轻内核A核源码分析系列七 进程管理 (2)
  • 轻内核A核源码分析系列七 进程管理 (3)
  • 持续更新中……

在学习函数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_READMAP_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;
        }
    }

小结

本文介绍了MMU虚实映射的基本概念,运行机制,分析了映射初始化、映射查询、映射虚拟内存和物理内存,解除虚实映射,更改映射属性,重新映射等常用接口的代码。

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2121539.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如果 Android 手机出现数据丢失,如何在Android上恢复丢失的数据

当您的 Android 手机发生数据丢失时&#xff0c;您可能需要检索丢失的文件。为了帮助您完成此过程&#xff0c;以下是执行 Android 数据恢复的一些有效方法&#xff1a; 如何在Android上检索数据 如果您的 Android 手机出现数据丢失&#xff0c;您可能需要检索丢失的文件。为了…

Python批量发邮件:如何批量发个性化邮件?

Python批量发邮件的实用技巧&#xff1f;如何利用Python发邮件&#xff1f; 无论是营销推广、客户关怀&#xff0c;还是内部通知&#xff0c;个性化邮件都能显著提升沟通效果。那么&#xff0c;Python批量发邮件如何实现个性化呢&#xff1f;本文将详细介绍如何使用Python批量…

ESP32 UDP 05

1.在上一文章基础上修改&#xff0c;文章网址 ESP32-Ethernet-04-CSDN博客 2.基本代码 /* Ethernet Basic ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware…

再见Java 8,请掌握最新LTS

简介 在Java开发中&#xff0c;Java 8曾经是无可争议的主流&#xff0c;凭借其稳定性和广泛的社区支持&#xff0c;陪伴了无数开发者走过多年辉煌时刻。然而&#xff0c;随着时间的推移&#xff0c;技术不断革新&#xff0c;企业和开发者们逐渐把目光投向了更新的LTS&#xff0…

LLM时代的transformer参数量、计算量、激活值的分析

导读&#xff1a;本文可以看作是对分析transformer模型的参数量、计算量、中间激活、KV cache的详细说明 定性分析 GPU上都存了哪些东西 首先我们来从全局整体的角度看一看&#xff0c;在训练阶段GPU显存上都有哪些内容&#xff1a; Model States&#xff1a;模型训练过程中…

使用 nuxi upgrade 升级现有nuxt项目版本

title: 使用 nuxi upgrade 升级现有nuxt项目版本 date: 2024/9/10 updated: 2024/9/10 author: cmdragon excerpt: 摘要:本文介绍了如何使用nuxi upgrade命令升级Nuxt 3项目,包括打开终端、运行升级命令、使用选项、测试项目等步骤,以及升级前的注意事项,如备份代码、检…

shader 案例学习笔记之绘制圆

环境搭建&#xff1a;参考glsl vscode环境搭建 先上代码 #ifdef GL_ES precision mediump float; #endifuniform vec2 u_resolution;void main(){vec2 st gl_FragCoord.xy/u_resolution.xy;st - 0.5;st.x * u_resolution.x/u_resolution.y;float r length(st);float d ste…

【面试分享】面试题——网络题目_网络面试题

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 一、题目 1、网关、网桥、路由器、中继器作用、实现以及对应的osi层? 2、MAC地址是什么? 3、webSocket是什么? 4、常见的协议有哪些&#xff1f; 5、什么…

交换机vlan配置实现

交换机配置 1. 配置交换机速度 进入交换机相应端口。 speed数值&#xff1a; 单位为Mbits;可选10&#xff0c;100&#xff0c;auto duplex参数&#xff1a;参数可选full全双工,half半双工,auto自适应 配置交换机管理IP地址&#xff1a; 在全局模式下&#xff1a; interf…

Qt使用UDP进行单波通信

Qt使用UDP进行单波通信 我们一般学习完基础的一些编程之后就会开始接触网络编程&#xff0c;我们熟悉的网络编程一般会涉及到两个协议一个时TCP&#xff0c;一个是UDP。TCP一般是point to point&#xff0c;UDP一般有单播和广播两种方式&#xff0c;那么我们今天就来学习一下单…

ECRS软件作业分析:提升工厂生产效率的钥匙

在竞争日益激烈的现代工业环境中&#xff0c;如何提升生产效率、降低资源消耗、增加产品价值&#xff0c;成为了每一家制造企业必须面对的重要课题。作业分析&#xff0c;作为一种科学的管理工具&#xff0c;正逐步成为企业优化生产流程、提升竞争力的关键手段。本文旨在深入探…

Unity SRP 可编程渲染管线的基本用法

可编程渲染管线使用教程 SRP 可以处理Canvas为Screen Space - Overlay的渲染 安装插件 首先进入package manager&#xff0c;下载Core RP Lib组件 创建渲染管线 编写渲染管线逻辑脚本 新建脚本取名为MPipeLine&#xff0c;该脚本用于实现渲染管线的处理逻辑 using Unity…

Python计算机视觉 第7章-图像搜索

Python计算机视觉 第7章-图像搜索 7.1 基于内容的图像检索 在大型图像数据库上&#xff0c;CBIR&#xff08;Content-Based Image Retrieval&#xff0c;基于内容的图像检索&#xff09;技术用于检索在视觉上具相似性的图像。这样返回的图像可以是颜色相似、纹理相似、图像中…

优秀一点点

在职场中&#xff0c;想要获得晋升&#xff0c;重要的是比其他同事优秀一点点。这就好比百米短跑比赛&#xff0c;第一名比第二名可能之快了0.01秒&#xff0c;这个0.01秒&#xff0c;和跑一百米所花的10秒钟比起来&#xff0c;可能只有千分之一。也就是说&#xff0c;第一名比…

麦汁煮沸工艺

麦汁煮沸是啤酒酿造中至关重要的工艺环节之一&#xff0c;直接影响啤酒的风味。今天&#xff0c;天泰邀您一起深入探讨这一关键的酿造技术。 煮沸麦汁 在煮沸麦汁时&#xff0c;时间和温度控制至关重要。通常&#xff0c;麦汁煮沸持续 40 到 50 分钟&#xff0c;具体时间取决于…

OpenAI Embeddings API: How embeddings work?

题意&#xff1a;OpenAI 嵌入 API&#xff1a;嵌入是如何工作的&#xff1f; 问题背景&#xff1a; There are quite a few tutorials on embeddings in OpenAI. I cant understand how they work. 在OpenAI中有很多关于嵌入的教程&#xff0c;但我无法理解它们是如何工作的。…

轻松实现游戏串流,内网穿透

一、部署Gemini Gemini使用教程 二、部署Moonlight 过程大概说一下&#xff0c;网上有太多太多moonlight的东西了 需要运行游戏的机器上安装GFE&#xff08;GeForce Experience&#xff09;&#xff0c;登录并开启GAMESTREAM&#xff08;游戏串流&#xff09;功能 注&…

什么是 Flash Attention

Flash Attention 是 由 Tri Dao 和 Dan Fu 等人在2022年的论文 FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 中 提出的&#xff0c; 论文可以从 https://arxiv.org/abs/2205.14135 页面下载&#xff0c;点击 View PDF 就可以下载。 下面我…

Php数组函数中的那些什么sort排序函数是不是很乱? 可以这样看。以及php搜索给定的值在数组中最后一次出现的位置的实现思考

一、Php数组函数中的那些什么sort排序函数是不是很乱? 可以这样看 PHP的数组函数真不少&#xff0c;甚至对一个程序员来说&#xff0c;在其整个程序生涯中有些方法他永远也不会用上。不过每一个方法都有其价值、或者在出现的时候有其价值。所以偶尔有空时还是可以去看看。在这…

并发编程:线程池(下)

一、线程池常用的阻塞队列有哪些&#xff1f; 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数&#xff0c;如果达到的话&#xff0c;新任务就会被存放在队列中。 不同的线程池会选用不同的阻塞队列&#xff0c;我们可以结合内置线程池来分析。 容量为 Integer…