更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_arch_mmu.h 文件参考


https://blog.csdn.net/qq_38410730/article/details/81036768 更多...

浏览源代码.

结构体

struct  ArchMmu
 内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。 更多...
 

类型定义

typedef struct ArchMmu LosArchMmu
 内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。 更多...
 

函数

BOOL OsArchMmuInit (LosArchMmu *archMmu, VADDR_T *virtTtb)
 
STATUS_T LOS_ArchMmuQuery (const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
 LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。
本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限 更多...
 
STATUS_T LOS_ArchMmuUnmap (LosArchMmu *archMmu, VADDR_T vaddr, size_t count)
 LOS_ArchMmuUnmap 解除进程空间虚拟地址区间与物理地址区间的映射关系 更多...
 
STATUS_T LOS_ArchMmuMap (LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T paddr, size_t count, UINT32 flags)
 LOS_ArchMmuMap 映射进程空间虚拟地址区间与物理地址区间
所谓的map就是生成L1,L2页表项的过程 更多...
 
STATUS_T LOS_ArchMmuChangeProt (LosArchMmu *archMmu, VADDR_T vaddr, size_t count, UINT32 flags)
 LOS_ArchMmuChangeProt 修改进程空间虚拟地址区间的映射属性 改变内存段的访问权限,例如: 读/写/可执行/不可用 == 更多...
 
STATUS_T LOS_ArchMmuMove (LosArchMmu *archMmu, VADDR_T oldVaddr, VADDR_T newVaddr, size_t count, UINT32 flags)
 LOS_ArchMmuMove 将进程空间一个虚拟地址区间的映射关系转移至另一块未使用的虚拟地址区间重新做映射。 更多...
 
VOID LOS_ArchMmuContextSwitch (LosArchMmu *archMmu)
 LOS_ArchMmuContextSwitch 切换MMU上下文 更多...
 
STATUS_T LOS_ArchMmuDestroy (LosArchMmu *archMmu)
 LOS_ArchMmuDestroy 销毁MMU 和 initMmu 相呼应,释放页表页 更多...
 
VOID OsArchMmuInitPerCPU (VOID)
 
VADDR_TOsGFirstTableGet (VOID)
 

详细描述


https://blog.csdn.net/qq_38410730/article/details/81036768

    https://blog.csdn.net/kuangyufei/article/details/109032636
    https://blog.csdn.net/qq_38410730/article/details/81036768
    虚拟内存空间中的地址叫做“虚拟地址”;而实际物理内存空间中的地址叫做“实际物理地址”或“物理地址”。处理器
    运算器和应用程序设计人员看到的只是虚拟内存空间和虚拟地址,而处理器片外的地址总线看到的只是物理地址空间和物理地址。
    MMU是 MemoryManagementUnit 的缩写即,内存管理单元. 
    MMU 的作用:
    1. 将虚拟地址翻译成为物理地址,然后访问实际的物理地址
    2. 访问权限控制
    当处理器试图访问一个虚存页面时,首先到页表中去查询该页是否已映射到物理页框中,并记录在页表中。如果在,
    则MMU会把页码转换成页框码,并加上虚拟地址提供的页内偏移量形成物理地址后去访问物理内存;如果不在,
    则意味着该虚存页面还没有被载入内存,这时MMU就会通知操作系统:发生了一个页面访问错误(页面错误),
    接下来系统会启动所谓的“请页”机制,即调用相应的系统操作函数,判断该虚拟地址是否为有效地址。
    
    如果是有效的地址,就从虚拟内存中将该地址指向的页面读入到内存中的一个空闲页框中,并在页表中添加上
    相对应的表项,最后处理器将从发生页面错误的地方重新开始运行;如果是无效的地址,则表明进程在试图访问
    一个不存在的虚拟地址,此时操作系统将终止此次访问。
* 


版本
作者
weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
日期
2021-11-16

@history

在文件 los_arch_mmu.h 中定义.

类型定义说明

◆ LosArchMmu

typedef struct ArchMmu LosArchMmu

内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。

函数说明

◆ LOS_ArchMmuChangeProt()

STATUS_T LOS_ArchMmuChangeProt ( LosArchMmu archMmu,
VADDR_T  vaddr,
size_t  count,
UINT32  flags 
)

LOS_ArchMmuChangeProt 修改进程空间虚拟地址区间的映射属性 改变内存段的访问权限,例如: 读/写/可执行/不可用 ==

参数
archMmu
count
flags
vaddr
返回
参见

在文件 los_arch_mmu.c949 行定义.

950{
951 STATUS_T status;
952 PADDR_T paddr = 0;
953
954 if ((archMmu == NULL) || (vaddr == 0) || (count == 0)) {
955 VM_ERR("invalid args: archMmu %p, vaddr %p, count %d", archMmu, vaddr, count);
956 return LOS_NOK;
957 }
958
959 while (count > 0) {
960 count--;
961 status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);//1. 先查出物理地址
962 if (status != LOS_OK) {
963 vaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
964 continue;
965 }
966
967 status = LOS_ArchMmuUnmap(archMmu, vaddr, 1);//2. 取消原有映射
968 if (status < 0) {
969 VM_ERR("invalid args:aspace %p, vaddr %p, count %d", archMmu, vaddr, count);
970 return LOS_NOK;
971 }
972
973 status = LOS_ArchMmuMap(archMmu, vaddr, paddr, 1, flags);//3. 重新映射 虚实地址
974 if (status < 0) {
975 VM_ERR("invalid args:aspace %p, vaddr %p, count %d",
976 archMmu, vaddr, count);
977 return LOS_NOK;
978 }
979 vaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
980 }
981 return LOS_OK;
982}
status_t LOS_ArchMmuMap(LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T paddr, size_t count, UINT32 flags)
LOS_ArchMmuMap 映射进程空间虚拟地址区间与物理地址区间 所谓的map就是生成L1,L2页表项的过程
Definition: los_arch_mmu.c:891
STATUS_T LOS_ArchMmuUnmap(LosArchMmu *archMmu, VADDR_T vaddr, size_t count)
LOS_ArchMmuUnmap 解除进程空间虚拟地址区间与物理地址区间的映射关系
Definition: los_arch_mmu.c:619
STATUS_T LOS_ArchMmuQuery(const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。 本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限
Definition: los_arch_mmu.c:569
unsigned long PADDR_T
Definition: los_typedef.h:207
int STATUS_T
Definition: los_typedef.h:215
函数调用图:
这是这个函数的调用关系图:

◆ LOS_ArchMmuContextSwitch()

VOID LOS_ArchMmuContextSwitch ( LosArchMmu archMmu)

LOS_ArchMmuContextSwitch 切换MMU上下文

参数
archMmu
返回
参见

在文件 los_arch_mmu.c1044 行定义.

1045{
1046 UINT32 ttbr;//B4.1.153 TTBCR, Translation Table Base Control Register,
1047 UINT32 ttbcr = OsArmReadTtbcr();//读取TTB寄存器的状态值
1048 if (archMmu) {
1049 ttbr = MMU_TTBRx_FLAGS | (archMmu->physTtb);//提供进程的映射页表地址,切换MMU代表要换进程,同一进程的线程切换并不需要切MMU
1050 /* enable TTBR0 */
1051 ttbcr &= ~MMU_DESCRIPTOR_TTBCR_PD0;//使能TTBR0 B4.1.154 TTBR0, Translation Table Base Register 0
1052 } else {
1053 ttbr = 0;
1054 /* disable TTBR0 */
1055 ttbcr |= MMU_DESCRIPTOR_TTBCR_PD0;//禁用TTBR0
1056 }
1057
1058#ifdef LOSCFG_KERNEL_VM
1059 /* from armv7a arm B3.10.4, we should do synchronization changes of ASID and TTBR. */
1060 OsArmWriteContextidr(LOS_GetKVmSpace()->archMmu.asid);//这里先把asid切到内核空间的ID
1061 ISB; //指令必须同步 ,清楚流水线中未执行指令
1062#endif
1063 OsArmWriteTtbr0(ttbr);//通过r0寄存器将进程页面基址写入TTB
1064 ISB;
1065 OsArmWriteTtbcr(ttbcr);//写入TTB状态位
1066 ISB;
1067#ifdef LOSCFG_KERNEL_VM
1068 if (archMmu) {
1069 OsArmWriteContextidr(archMmu->asid);//通过R0寄存器写入进程标识符至C13寄存器
1070 ISB; // 可查看 鸿蒙内核源码分析(优雅的宏篇)
1071 }
1072#endif
1073}
STATIC INLINE VOID OsArmWriteTtbcr(UINT32 val)
Definition: arm.h:124
STATIC INLINE VOID OsArmWriteContextidr(UINT32 val)
Definition: arm.h:228
STATIC INLINE UINT32 OsArmReadTtbcr(VOID)
Definition: arm.h:117
STATIC INLINE VOID OsArmWriteTtbr0(UINT32 val)
Definition: arm.h:98
unsigned int UINT32
Definition: los_typedef.h:57
LosVmSpace * LOS_GetKVmSpace(VOID)
内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间
Definition: los_vm_map.c:130
UINT32 asid
Definition: los_arch_mmu.h:92
PADDR_T physTtb
Definition: los_arch_mmu.h:91
函数调用图:
这是这个函数的调用关系图:

◆ LOS_ArchMmuDestroy()

STATUS_T LOS_ArchMmuDestroy ( LosArchMmu archMmu)

LOS_ArchMmuDestroy 销毁MMU 和 initMmu 相呼应,释放页表页

参数
archMmu
返回
参见

在文件 los_arch_mmu.c1083 行定义.

1084{
1085#ifdef LOSCFG_KERNEL_VM
1086 LosVmPage *page = NULL;
1087 /* free all of the pages allocated in archMmu->ptList */
1088 while ((page = LOS_ListRemoveHeadType(&archMmu->ptList, LosVmPage, node)) != NULL) {
1089 LOS_PhysPageFree(page);//释放物理页
1090 }
1091
1092 OsArmWriteTlbiasidis(archMmu->asid);
1093 OsFreeAsid(archMmu->asid);//释放asid
1094#endif
1095 return LOS_OK;
1096}
STATIC INLINE VOID OsArmWriteTlbiasidis(UINT32 val)
记录由协处理器记录当前是哪个进程在跑
Definition: arm.h:514
VOID OsFreeAsid(UINT32 asid)
释放 asid
Definition: los_asid.c:96
VOID LOS_PhysPageFree(LosVmPage *page)
释放一个物理页框
Definition: los_vm_phys.c:546
LOS_DL_LIST ptList
Definition: los_arch_mmu.h:93
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
Definition: los_vm_page.h:53
函数调用图:
这是这个函数的调用关系图:

◆ LOS_ArchMmuMap()

STATUS_T LOS_ArchMmuMap ( LosArchMmu archMmu,
VADDR_T  vaddr,
PADDR_T  paddr,
size_t  count,
UINT32  flags 
)

LOS_ArchMmuMap 映射进程空间虚拟地址区间与物理地址区间
所谓的map就是生成L1,L2页表项的过程

参数
archMmu
count
flags
paddr
vaddr
返回
参见

在文件 los_arch_mmu.c891 行定义.

892{
893 PTE_T *l1Entry = NULL;
894 UINT32 saveCounts = 0;
895 INT32 mapped = 0;
896 INT32 tryTime = TRY_MAX_TIMES;
897 INT32 checkRst;
898 MmuMapInfo mmuMapInfo = {
899 .archMmu = archMmu,
900 .vaddr = &vaddr,
901 .paddr = &paddr,
902 .flags = &flags,
903 };
904
905 checkRst = OsMapParamCheck(flags, vaddr, paddr);//检查参数
906 if (checkRst < 0) {
907 return checkRst;
908 }
909
910 /* see what kind of mapping we can use */
911 while (count > 0) {
912 if (MMU_DESCRIPTOR_IS_L1_SIZE_ALIGNED(*mmuMapInfo.vaddr) &&
913 MMU_DESCRIPTOR_IS_L1_SIZE_ALIGNED(*mmuMapInfo.paddr) &&
914 count >= MMU_DESCRIPTOR_L2_NUMBERS_PER_L1) {
915 /* compute the arch flags for L1 sections cache, r ,w ,x, domain and type */
916 saveCounts = OsMapSection(&mmuMapInfo, &count);
917 } else {
918 /* have to use a L2 mapping, we only allocate 4KB for L1, support 0 ~ 1GB */
919 l1Entry = OsGetPte1Ptr(archMmu->virtTtb, *mmuMapInfo.vaddr);
920 if (OsIsPte1Invalid(*l1Entry)) {
921 saveCounts = OsMapL1PTE(&mmuMapInfo, l1Entry, &count);
922 } else if (OsIsPte1PageTable(*l1Entry)) {
923 saveCounts = OsMapL2PageContinous(&mmuMapInfo, l1Entry, &count);
924 } else {
925 LOS_Panic("%s %d, unimplemented tt_entry %x\n", __FUNCTION__, __LINE__, l1Entry);
926 }
927 }
928 mapped += saveCounts;
929 tryTime = (saveCounts == 0) ? (tryTime - 1) : tryTime;
930 if (tryTime == 0) {
931 return LOS_ERRNO_VM_TIMED_OUT;
932 }
933 }
934
935 return mapped;
936}
NORETURN VOID LOS_Panic(const CHAR *fmt,...)
Kernel panic function.
STATIC INT32 OsMapParamCheck(UINT32 flags, VADDR_T vaddr, PADDR_T paddr)
Definition: los_arch_mmu.c:204
STATIC UINT32 OsMapL2PageContinous(MmuMapInfo *mmuMapInfo, PTE_T *pte1, UINT32 *count)
Definition: los_arch_mmu.c:851
STATIC UINT32 OsMapSection(MmuMapInfo *mmuMapInfo, UINT32 *count)
OsMapSection section页表格式项映射
Definition: los_arch_mmu.c:666
STATIC UINT32 OsMapL1PTE(MmuMapInfo *mmuMapInfo, PTE_T *l1Entry, UINT32 *count)
Definition: los_arch_mmu.c:806
STATIC INLINE BOOL OsIsPte1PageTable(PTE_T pte1)
Definition: los_pte_ops.h:87
STATIC INLINE PTE_T * OsGetPte1Ptr(PTE_T *pte1BasePtr, vaddr_t va)
pte1BasePtr L1 转换页表基地址
Definition: los_pte_ops.h:77
STATIC INLINE BOOL OsIsPte1Invalid(PTE_T pte1)
Definition: los_pte_ops.h:92
signed int INT32
Definition: los_typedef.h:60
unsigned long PTE_T
Definition: los_typedef.h:213
VADDR_T * virtTtb
Definition: los_arch_mmu.h:90
LosArchMmu * archMmu
Definition: los_arch_mmu.c:90
VADDR_T * vaddr
Definition: los_arch_mmu.c:91
PADDR_T * paddr
Definition: los_arch_mmu.c:92
函数调用图:
这是这个函数的调用关系图:

◆ LOS_ArchMmuMove()

STATUS_T LOS_ArchMmuMove ( LosArchMmu archMmu,
VADDR_T  oldVaddr,
VADDR_T  newVaddr,
size_t  count,
UINT32  flags 
)

LOS_ArchMmuMove 将进程空间一个虚拟地址区间的映射关系转移至另一块未使用的虚拟地址区间重新做映射。

参数
archMmu
count
flags
newVaddr
oldVaddr
返回
参见

在文件 los_arch_mmu.c996 行定义.

997{
998 STATUS_T status;
999 PADDR_T paddr = 0;
1000
1001 if ((archMmu == NULL) || (oldVaddr == 0) || (newVaddr == 0) || (count == 0)) {
1002 VM_ERR("invalid args: archMmu %p, oldVaddr %p, newVaddr %p, count %d",
1003 archMmu, oldVaddr, newVaddr, count);
1004 return LOS_NOK;
1005 }
1006
1007 while (count > 0) {
1008 count--;
1009 status = LOS_ArchMmuQuery(archMmu, oldVaddr, &paddr, NULL);
1010 if (status != LOS_OK) {
1011 oldVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
1012 newVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
1013 continue;
1014 }
1015 // we need to clear the mapping here and remain the phy page.
1016 status = LOS_ArchMmuUnmap(archMmu, oldVaddr, 1);
1017 if (status < 0) {
1018 VM_ERR("invalid args: archMmu %p, vaddr %p, count %d",
1019 archMmu, oldVaddr, count);
1020 return LOS_NOK;
1021 }
1022
1023 status = LOS_ArchMmuMap(archMmu, newVaddr, paddr, 1, flags);
1024 if (status < 0) {
1025 VM_ERR("invalid args:archMmu %p, old_vaddr %p, new_addr %p, count %d",
1026 archMmu, oldVaddr, newVaddr, count);
1027 return LOS_NOK;
1028 }
1029 oldVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
1030 newVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
1031 }
1032
1033 return LOS_OK;
1034}
函数调用图:
这是这个函数的调用关系图:

◆ LOS_ArchMmuQuery()

STATUS_T LOS_ArchMmuQuery ( const LosArchMmu archMmu,
VADDR_T  vaddr,
PADDR_T paddr,
UINT32 flags 
)

LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。
本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限

参数
archMmu
flags
paddr
vaddr
返回
参见

在文件 los_arch_mmu.c569 行定义.

570{//archMmu->virtTtb:转换表基地址
571 PTE_T l1Entry = OsGetPte1(archMmu->virtTtb, vaddr);//获取PTE vaddr右移20位 得到L1描述子地址
572 PTE_T l2Entry;
573 PTE_T* l2Base = NULL;
574
575 if (OsIsPte1Invalid(l1Entry)) {//判断L1描述子地址是否有效
576 return LOS_ERRNO_VM_NOT_FOUND;//无效返回虚拟地址未查询到
577 } else if (OsIsPte1Section(l1Entry)) {// section页表项: l1Entry低二位是否为 10
578 if (paddr != NULL) {//物理地址 = 节基地址(section页表项的高12位) + 虚拟地址低20位
579 *paddr = MMU_DESCRIPTOR_L1_SECTION_ADDR(l1Entry) + (vaddr & (MMU_DESCRIPTOR_L1_SMALL_SIZE - 1));
580 }
581
582 if (flags != NULL) {
583 OsCvtSecAttsToFlags(l1Entry, flags);//获取虚拟内存的flag信息
584 }
585 } else if (OsIsPte1PageTable(l1Entry)) {//PAGE_TABLE页表项: l1Entry低二位是否为 01
586 l2Base = OsGetPte2BasePtr(l1Entry);//获取L2转换表基地址
587 if (l2Base == NULL) {
588 return LOS_ERRNO_VM_NOT_FOUND;
589 }
590 l2Entry = OsGetPte2(l2Base, vaddr);//获取L2描述子地址
591 if (OsIsPte2SmallPage(l2Entry) || OsIsPte2SmallPageXN(l2Entry)) {
592 if (paddr != NULL) {//物理地址 = 小页基地址(L2页表项的高20位) + 虚拟地址低12位
593 *paddr = MMU_DESCRIPTOR_L2_SMALL_PAGE_ADDR(l2Entry) + (vaddr & (MMU_DESCRIPTOR_L2_SMALL_SIZE - 1));
594 }
595
596 if (flags != NULL) {
597 OsCvtPte2AttsToFlags(l1Entry, l2Entry, flags);//获取虚拟内存的flag信息
598 }
599 } else if (OsIsPte2LargePage(l2Entry)) {//鸿蒙目前暂不支持64K大页,未来手机版应该会支持。
600 LOS_Panic("%s %d, large page unimplemented\n", __FUNCTION__, __LINE__);
601 } else {
602 return LOS_ERRNO_VM_NOT_FOUND;
603 }
604 }
605
606 return LOS_OK;
607}
STATIC VOID OsCvtSecAttsToFlags(PTE_T l1Entry, UINT32 *flags)
Definition: los_arch_mmu.c:437
STATIC INLINE PTE_T * OsGetPte2BasePtr(PTE_T pte1)
获取页表基地址
Definition: los_arch_mmu.c:180
STATIC VOID OsCvtPte2AttsToFlags(PTE_T l1Entry, PTE_T l2Entry, UINT32 *flags)
Definition: los_arch_mmu.c:221
STATIC INLINE PTE_T OsGetPte1(PTE_T *pte1BasePtr, vaddr_t va)
Definition: los_pte_ops.h:82
STATIC INLINE PTE_T OsGetPte2(PTE_T *pte2BasePtr, vaddr_t va)
Definition: los_pte_ops.h:112
STATIC INLINE BOOL OsIsPte2SmallPageXN(PTE_T pte2)
Definition: los_pte_ops.h:160
STATIC INLINE BOOL OsIsPte2LargePage(PTE_T pte2)
Definition: los_pte_ops.h:165
STATIC INLINE BOOL OsIsPte2SmallPage(PTE_T pte2)
Definition: los_pte_ops.h:155
STATIC INLINE BOOL OsIsPte1Section(PTE_T pte1)
Definition: los_pte_ops.h:97
函数调用图:
这是这个函数的调用关系图:

◆ LOS_ArchMmuUnmap()

STATUS_T LOS_ArchMmuUnmap ( LosArchMmu archMmu,
VADDR_T  vaddr,
size_t  count 
)

LOS_ArchMmuUnmap 解除进程空间虚拟地址区间与物理地址区间的映射关系

参数
archMmu
count
vaddr
返回
参见

在文件 los_arch_mmu.c619 行定义.

620{
621 PTE_T *l1Entry = NULL;
622 INT32 unmapped = 0;
623 UINT32 unmapCount = 0;
624 INT32 tryTime = TRY_MAX_TIMES;
625
626 while (count > 0) {
627 l1Entry = OsGetPte1Ptr(archMmu->virtTtb, vaddr);//获取L1表
628 if (OsIsPte1Invalid(*l1Entry)) {//L1表是否有效
629 unmapCount = OsUnmapL1Invalid(&vaddr, &count);//取消L1表内的映射
630 } else if (OsIsPte1Section(*l1Entry)) {
631 if (MMU_DESCRIPTOR_IS_L1_SIZE_ALIGNED(vaddr) && count >= MMU_DESCRIPTOR_L2_NUMBERS_PER_L1) {
632 unmapCount = OsUnmapSection(archMmu, l1Entry, &vaddr, &count);
633 } else {
634 LOS_Panic("%s %d, unimplemented\n", __FUNCTION__, __LINE__);
635 }
636 } else if (OsIsPte1PageTable(*l1Entry)) {
637 unmapCount = OsUnmapL2PTE(archMmu, l1Entry, vaddr, &count);//取消L2表的映射
638 OsTryUnmapL1PTE(archMmu, l1Entry, vaddr, OsGetPte2Index(vaddr) + unmapCount,
639 MMU_DESCRIPTOR_L2_NUMBERS_PER_L1);
640 vaddr += unmapCount << MMU_DESCRIPTOR_L2_SMALL_SHIFT;
641 } else {
642 LOS_Panic("%s %d, unimplemented\n", __FUNCTION__, __LINE__);
643 }
644 tryTime = (unmapCount == 0) ? (tryTime - 1) : tryTime;
645 if (tryTime == 0) {
646 return LOS_ERRNO_VM_FAULT;
647 }
648 unmapped += unmapCount;
649 }
651 return unmapped;
652}
STATIC VOID OsTryUnmapL1PTE(LosArchMmu *archMmu, PTE_T *l1Entry, vaddr_t vaddr, UINT32 scanIndex, UINT32 scanCount)
Definition: los_arch_mmu.c:292
STATIC UINT32 OsUnmapSection(LosArchMmu *archMmu, PTE_T *l1Entry, vaddr_t *vaddr, UINT32 *count)
Definition: los_arch_mmu.c:515
STATIC INLINE UINT32 OsUnmapL1Invalid(vaddr_t *vaddr, UINT32 *count)
解除L1表的映射关系
Definition: los_arch_mmu.c:192
STATIC UINT32 OsUnmapL2PTE(LosArchMmu *archMmu, PTE_T *pte1, vaddr_t vaddr, UINT32 *count)
Definition: los_arch_mmu.c:482
STATIC INLINE UINT32 OsGetPte2Index(vaddr_t va)
Definition: los_pte_ops.h:102
STATIC INLINE VOID OsArmInvalidateTlbBarrier(VOID)
Definition: los_tlb_v6.h:48
函数调用图:
这是这个函数的调用关系图:

◆ OsArchMmuInit()

BOOL OsArchMmuInit ( LosArchMmu archMmu,
VADDR_T virtTtb 
)

在文件 los_arch_mmu.c537 行定义.

538{
539#ifdef LOSCFG_KERNEL_VM
540 if (OsAllocAsid(&archMmu->asid) != LOS_OK) {//分配一个asid,ASID可用来唯一标识进程空间
541 VM_ERR("alloc arch mmu asid failed");//地址空间标识码(address-space identifier,ASID)为CP15协处理器 C13寄存器
542 return FALSE;
543 }
544#endif
545
546#ifndef LOSCFG_PAGE_TABLE_FINE_LOCK
547 LOS_SpinInit(&archMmu->lock);
548#endif
549 LOS_ListInit(&archMmu->ptList);//初始化页表,双循环进程所有物理页框 LOS_ListAdd(&processCB->vmSpace->archMmu.ptList, &(vmPage->node));
550 archMmu->virtTtb = virtTtb;//为L1页表在内存位置 section(".bss.prebss.translation_table") UINT8 g_firstPageTable[MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS]
551 archMmu->physTtb = (VADDR_T)(UINTPTR)virtTtb - KERNEL_ASPACE_BASE + SYS_MEM_BASE;// TTB寄存器是CP15协处理器的C2寄存器,存页表的基地址
552 //SYS_MEM_BASE = 0x80000000 KERNEL_ASPACE_BASE = 0x40000000 见于 ..\vendor\hi3516dv300\config\board\include\board.h
553 //archMmu->physTtb = (VADDR_T)(UINTPTR)virtTtb + 0x40000000;
554 return TRUE;
555}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
STATUS_T OsAllocAsid(UINT32 *asid)
Definition: los_asid.c:78
VOID LOS_SpinInit(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:37
unsigned long VADDR_T
Definition: los_typedef.h:208
unsigned long UINTPTR
Definition: los_typedef.h:68
SPIN_LOCK_S lock
Definition: los_arch_mmu.h:88
函数调用图:
这是这个函数的调用关系图:

◆ OsArchMmuInitPerCPU()

VOID OsArchMmuInitPerCPU ( VOID  )

在文件 los_arch_mmu.c1243 行定义.

1244{
1245 UINT32 n = __builtin_clz(KERNEL_ASPACE_BASE) + 1;
1246 UINT32 ttbcr = MMU_DESCRIPTOR_TTBCR_PD0 | n;
1247
1248 OsArmWriteTtbr1(OsArmReadTtbr0());//读取地址转换表基地址
1249 ISB;//指令同步隔离。最严格:它会清洗流水线,以保证所有它前面的指令都执行完毕之后,才执行它后面的指令。
1250 OsArmWriteTtbcr(ttbcr);
1251 ISB;
1252 OsArmWriteTtbr0(0);
1253 ISB;
1254}
STATIC INLINE UINT32 OsArmReadTtbr0(VOID)
Definition: arm.h:91
STATIC INLINE VOID OsArmWriteTtbr1(UINT32 val)
Definition: arm.h:111
函数调用图:
这是这个函数的调用关系图:

◆ OsGFirstTableGet()

VADDR_T * OsGFirstTableGet ( VOID  )

在文件 los_arch_mmu.c186 行定义.

187{
188 return (VADDR_T *)g_firstPageTable;
189}
这是这个函数的调用关系图: