鸿蒙轻内核A核源码分析系列五 虚实映射(4)虚实映射查询 原创 精华
鸿蒙轻内核A核源码分析系列五 虚实映射
【#本文正在参与优质创作者激励#】
4、虚实映射查询函数LOS_ArchMmuQuery
给定一个虚拟内存地址,可以查询其映射到的物理内存地址,还可以查询映射标签属性信息,函数LOS_ArchMmuQuery
负责完成这些信息的查询。
4.1 函数LOS_ArchMmuQuery
函数LOS_ArchMmuQuery
用于获取进程空间虚拟地址对应的物理地址以及映射标签属性,其中输入参数为虚拟内存地址vaddr
,输出参数为物理内存地址*paddr
和标签属性*flags
。⑴处获取虚拟地址对应的页表项。⑵处如果虚拟地址对应的页表项描述符类型无效,返回错误码。⑶处如果页表项描述符类型为L1页表Section类型映射,则执行⑷获取映射的物理地址,其中MMU_DESCRIPTOR_L1_SECTION_ADDR(l1Entry)
为L1页表项的高12位,(vaddr & (MMU_DESCRIPTOR_L1_SMALL_SIZE - 1))
为虚拟地址的低20位,即页内偏移值。可以和上文了解到的知识相对应,物理内存地址的计算方式为页表项的高12位加上虚拟内存地址的低20位,如下图所示。⑸处获取映射的标签属性,把MMU标签转换为内存区域标签。
如果虚拟地址对应的页表项描述符类型为页表Page Table,则执行⑹调用内联函数OsGetPte2BasePtr()
计算L2页表项基地址,计算方法为:取L1页表项的高22位,低10位置0,得到L2页表项物理内存基地址,然后转化为L2页表项虚拟内存基地址。⑺处计算虚拟地址对应的L2页表项数值,从上文可知,L2页表项的指针地址在页表项基地址加上虚拟内存地址的12-19位上的索引值,取该地址的数据即为L2页表项数据。如果L2页表项描述符类型为小页,则执行⑻计算物理内存地址,其中MMU_DESCRIPTOR_L2_SMALL_PAGE_ADDR(l2Entry)
为L2页表项的高20位;vaddr & (MMU_DESCRIPTOR_L2_SMALL_SIZE - 1)
为虚拟地址的低12位,如下图所示。然后计算相应的标签值。⑼处表示当前轻内核还不支持大页类型。
STATUS_T LOS_ArchMmuQuery(const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
{
⑴ PTE_T l1Entry = OsGetPte1(archMmu->virtTtb, vaddr);
PTE_T l2Entry;
PTE_T* l2Base = NULL;
⑵ if (OsIsPte1Invalid(l1Entry)) {
return LOS_ERRNO_VM_NOT_FOUND;
⑶ } else if (OsIsPte1Section(l1Entry)) {
if (paddr != NULL) {
⑷ *paddr = MMU_DESCRIPTOR_L1_SECTION_ADDR(l1Entry) + (vaddr & (MMU_DESCRIPTOR_L1_SMALL_SIZE - 1));
}
if (flags != NULL) {
⑸ OsCvtSecAttsToFlags(l1Entry, flags);
}
} else if (OsIsPte1PageTable(l1Entry)) {
⑹ l2Base = OsGetPte2BasePtr(l1Entry);
if (l2Base == NULL) {
return LOS_ERRNO_VM_NOT_FOUND;
}
⑺ l2Entry = OsGetPte2(l2Base, vaddr);
if (OsIsPte2SmallPage(l2Entry) || OsIsPte2SmallPageXN(l2Entry)) {
if (paddr != NULL) {
⑻ *paddr = MMU_DESCRIPTOR_L2_SMALL_PAGE_ADDR(l2Entry) + (vaddr & (MMU_DESCRIPTOR_L2_SMALL_SIZE - 1));
}
if (flags != NULL) {
OsCvtPte2AttsToFlags(l1Entry, l2Entry, flags);
}
⑼ } else if (OsIsPte2LargePage(l2Entry)) {
LOS_Panic("%s %d, large page unimplemented\n", __FUNCTION__, __LINE__);
} else {
return LOS_ERRNO_VM_NOT_FOUND;
}
}
return LOS_OK;
}
【#本文正在参与优质创作者激励#】
文中此处描述错误。 % MMU_DESCRIPTOR_L1_SMALL_SIZE 表示取后20位,>> MMU_DESCRIPTOR_L2_SMALL_SHIFT然后右移12位。所以L2页表项的索引值保存在虚拟地址的第12-19位上,而不是高20位。