class="hide-preCode-box">

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;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

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;
        }
    }

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

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;
        }
    }
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

小结

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

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

系统架构分析:https://qr18.cn/CgxrRy

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/139653578","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/99123377"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!