Linux内核启动阶段虚实地址映射

本文介绍了Linux ARM64内核启动时如何处理虚实地址映射。在MMU开启前,确保所有指令为位置无关,通过创建页表将编译时指定的运行地址(虚拟地址)映射到实际物理地址。关键宏如KIMAGE_VADDR、TEXT_OFFSET等定义了内核地址空间布局。通过create_pgd_entry和create_block_map创建页表,为.idmap.text段和整个kernel image建立虚实地址转换。

前言

编译kernel的时候,会通过链接脚本指定编译出来的image的布局以及image的运行地址,这里说的运行地址,是从CPU的视角来说的,是一个虚拟地址。CPU执行代码的时候,要么是顺序执行,要么是跳转到其他地址去执行,跳转的话又分为相对跳转和绝对跳转,顺序执行和相对跳转实际上都是相对PC当前位置做一个偏移,这种指令是位置无关指令,而绝对跳转是明确指定跳转到某个地址去,是位置相关指令,位置相关指令要跳转到的地址,是基于上诉所说的运行地址的。

从位置相关指令和位置无关指令的定义可以知道,位置相关指令即使不放在运行地址处,也是可以执行的,但是位置相关指令,必须放在运行地址处,否则CPU是无法寻址到该指令的。ARM64默认指定的运行地址是:ffff000008080000,这是一个虚拟地址。那么问题来了,由于CPU刚跳转到kernel的时候,MMU是关闭的,CPU只能直接通过物理地址寻址,那么如何保证CPU每次寻址都能找到正确的数据呢,这个其实很简单,只要保证在MMU开启之前所有的指令都是位置无关指令就可以了,一方面所有的跳转指令必须是相对跳转,另一方面,所有的load和store指令必须操作物理地址。在打开MMU之前,需要为虚拟地址到物理地址转换创建页表,虚拟地址的来源就是编译时指定的运行地址,而物理地址的来源更加简单,因为此时CPU寻址用的都是物理地址,所以很容易找到kernel的物理地址,详情下面会介绍。

宏定义

CPU不可能一直执行位置无关指令,所以必须将kernel本身的虚拟地址(运行地址)映射到它实际所在的物理地址,这个通过为MMU创建页表来实现,一旦页表创建完成,并打开了MMU,CPU发出的虚拟地址,可以由MMU转换成实际的物理地址,这样CPU执行kernel代码将不再受限。
在分析代码之前,有几个宏定义需要搞清楚:

  • KIMAGE_VADDR

定义:arch/arm64/include/asm/memory.h
#define KIMAGE_VADDR (MODULES_END)

Kernel Image的起始虚拟地址。
对于ARM64来说,虚拟地址的寻址能力一般是48 bits,当然也支持其他的寻址能力,我们这里按48 bits来作说明。按48 bits的寻址能力,分配给内核的起始虚拟地址是0xffff000000000000,前面会留一部分另做他用,如给KASAN,MODULE模块使用,后面才分给kernel image。我们这里假设不支持KASAN,则给MODULE预留128M的空间,128M以后给kernel image使用,也就是说kernel image的起始地址是0xffff000008000000。

  • TEXT_OFFSET
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值