__pa_symbol 的定义
其作用是在内核物理内存的线性映射还没建立的时候,用来根据虚拟地址计算物理地址。
定义如下
#define __pa_symbol(x) __phys_addr_symbol(RELOC_HIDE((unsigned long)(x), 0))
#define __phys_addr_symbol(x) __pa_symbol_nodebug(x)
#define __pa_symbol_nodebug(x) __kimg_to_phys((phys_addr_t)(x))
#define __kimg_to_phys(addr) ((addr) - kimage_voffset)
__pa_symbol(x)最终等价于 x - kimage_voffset
其中 kimage_voffset 就是内核虚拟地址和物理地址直接的偏移量。
kimage_voffset 的计算过程
如下:
/*/home/zqxl/work/qemu_work/kernel/linux-5.4.220/arch/arm64/kernel/head.S*/
ldr_l x4, kimage_vaddr // Save the offset between
sub x4, x4, x0 // the kernel virtual and
str_l x4, kimage_voffset, x5 // physical mappings
str_l 的含义如下,作用就是把x4 的值保存到变量kimage_voffset。x5 是临时使用,用来保存kimage_voffset 这个变量所在的页的地址。
str_l 分析
str_l 的定义如下
/*arch/arm64/include/asm/assembler.h*/
230 /*
231 * @src: source register (32 or 64 bit wide)
232 * @sym: name of the symbol
233 * @tmp: mandatory 64-bit scratch register to calculate the address
234 * while <src> needs to be preserved.
235 */
236 .macro str_l, src, sym, tmp
237 adrp \tmp, \sym
238 str \src, [\tmp, :lo12:\sym]
239 .endm
将str_l x4, kimage_voffset, x5
展开如下
adrp x5, kimage_voffset
str x4, [x5, :lo12:kimage_voffset]
其中,adrp 将 kimage_voffset 所在的页的地址保存进了x5。:lo12:kimage_voffset
看起来是取了 &kimage_voffset 的低12bit,也就是kimage_voffset 在其所在页中的偏移地址。
adrp 的作用参考:adrp指令