2、 虚拟映射初始化
在文件kernel/base/vm/los_vm_boot.c
中的系统内存初始化函数OsSysMemInit()
会调用虚实映射初始化函数OsInitMappingStartUp()
。该函数代码定义在文件arch/arm/arm/src/los_arch_mmu.c
,代码如下。⑴处函数使TLB失效,清理虚实映射缓存数据,涉及些cp15寄存器和汇编,后续再分析。⑵处函数切换到临时TTB。⑶处设置内核地址空间的映射。下面分别详细这些函数代码。
VOID OsInitMappingStartUp(VOID)
{
⑴ OsArmInvalidateTlbBarrier();
⑵ OsSwitchTmpTTB();
⑶ OsSetKSectionAttr(KERNEL_VMM_BASE, FALSE);
OsSetKSectionAttr(UNCACHED_VMM_BASE, TRUE);
OsKSectionNewAttrEnable();
}
2.1 函数OsSwitchTmpTTB
函数OsSwitchTmpTTB
申请16KiB的内存存放L1页表项数据,把页表项数据从g_firstPageTable
复制到申请的内存区域。⑴处获取内核地址空间。L1页表由4096个页表项组成,每个4 bytes,共需要16KiB大小。所以⑵处代码按16KiB对齐申请16KiB大小的内存区域存放L1页表项。⑶处设置内核虚拟内存地址空间的转换表基地址TTB。⑷处把g_firstPageTable
页表数据复制到内核地址空间的转换表区域。如果复制失败,则直接使用g_firstPageTable
。⑸处设置内核虚拟地址空间的TTB转换地址对应的物理内存地址,然后调用函数OsArmWriteTtbr0
写入MMU寄存器。
STATIC VOID OsSwitchTmpTTB(VOID)
{
PTE_T *tmpTtbase = NULL;
errno_t err;
⑴ LosVmSpace *kSpace = LOS_GetKVmSpace();
/* ttbr address should be 16KByte align */
⑵ tmpTtbase = LOS_MemAllocAlign(m_aucSysMem0, MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS,
MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS);
if (tmpTtbase == NULL) {
VM_ERR("memory alloc failed");
return;
}
⑶ kSpace->archMmu.virtTtb = tmpTtbase;
⑷ err = memcpy_s(kSpace->archMmu.virtTtb, MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS,
g_firstPageTable, MMU_DESCRIPT