kernel版本:5.10
平台:arm64
1.前言
本专题主要基于《arm64_linux head.S的执行流程》系列文章,前者是基于3.18,本专题针对的是内核5.10。主要分析head.S的执行过程。了解启动过程中head.S都做了哪些主要的工作。
2.head.S的执行
.......
ENTRY(_text)
.......
SECTIONS
{
/*
* XXX: The linker does not define how output sections are
* assigned to input sections when there are multiple statements
* matching the same input section name. There is no documented
* order of matching.
*/
DISCARDS
/DISCARD/ : {
*(.interp .dynamic)
*(.dynsym .dynstr .hash .gnu.hash)
}
. = KIMAGE_VADDR;
.head.text : {
_text = .;
HEAD_TEXT
}
.text : { /* Real text segment */
_stext = .; /* Text and read-only data */
IRQENTRY_TEXT
SOFTIRQENTRY_TEXT
ENTRY_TEXT
TEXT_TEXT
SCHED_TEXT
CPUIDLE_TEXT
LOCK_TEXT
KPROBES_TEXT
HYPERVISOR_TEXT
IDMAP_TEXT
HIBERNATE_TEXT
TRAMP_TEXT
*(.fixup)
*(.gnu.warning)
. = ALIGN(16);
*(.got) /* Global offset table */
}
......
}
从链接脚本vmlinux.lds中可以看到,定义了入口点为_text,通过 . = KIMAGE_VADDR 定义了链接地址, 可知_text的地址为KIMAGE_VADDR , 我们看下KIMAGE_VADDR 的定义:
KIMAGE_VADDR
//arch/arm64/include/asm/memory.h
#define KIMAGE_VADDR (MODULES_END)
#define MODULES_END (MODULES_VADDR + MODULES_VSIZE)
#define MODULES_VADDR (BPF_JIT_REGION_END)
#define MODULES_VSIZE (SZ_128M)
#define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE)
#define BPF_JIT_REGION_START (KASAN_SHADOW_END)
#define BPF_JIT_REGION_SIZE (SZ_128M)
#define KASAN_THREAD_SHIFT 0
#define KASAN_SHADOW_END (_PAGE_END(VA_BITS_MIN))
#define VA_BITS_MIN (VA_BITS)
#define _PAGE_END(va) (-(UL(1) << ((va) - 1)))
此处由于没有开启KASAN, 因此:
KASAN_SHADOW_END = -(1UL << (48 - 1)) = ffff800000000000,
BPF_JIT_REGION_START =ffff800000000000
BPF_JIT_REGION_END=ffff800000000000+ SZ_128M=0xffff800008000000
MODULES_VADDR = 0xffff800008000000
MODULES_END = 0xffff800008000000 + SZ_128M = 0xffff800010000000
KIMAGE_VADDR = 0xffff800010000000*
因此KIMAGE_VADDR的地址也就是_text的地址为0xffff800010000000(通过vmlinux.lds也可以看到)
通过反汇编vmlinux也可以看到_text的地址为ffff800010000000:
1
2 vmlinux: file format elf64-littleaarch64
3
4
5 Disassembly of section .head.text:
6
7 ffff800010000000 <_text>:
8 ffff800010000000: 91005a4d add x13, x18, #0x16
9 ffff800010000004: 1444ffff b ffff800011140000 <__init_begin>
......
通过ktdump节点可以看到KIMAGE_VADDR(0xffff800010000000)所处的区域位于
vmalloc(0xffff800010000000-0xfffffdffbfff0000),由此可知kernel image位于vmalloc区域
/sys/kernel/debug # cat kernel_page_tables
0x0000000000000000-0xffff000000000000
0xffff000000000000-0xffff000000200000
0xffff000000200000-0xffff000001200000
0xffff000001200000-0xffff000001340000
0xffff000001340000-0xffff000002643000
0xffff000002643000-0xffff000002644000
0xffff000002644000-0xffff000040000000
0xffff000040000000-0xffff008000000000
0xffff008000000000-0xffff800000000000
---[ Linear Mapping end ]---
---[ BPF start ]---
0xffff800000000000-0xffff800008000000
---[ BPF end ]---
---[ Modules start ]---
0xffff800008000000-0xffff800010000000
---[ Modules end ]---
---[ vmalloc() area ]---
0xffff800010000000-0xfffffdffbfff0000
---[ vmalloc() end ]---
0xfffffdffbfff0000-0xfffffdffc0000000
0xfffffdffc0000000-0xfffffdfffe400000
0xfffffdfffe400000-0xfffffdfffe5f9000
---[ Fixmap start ]---
0xfffffdfffe5f9000-0xfffffdfffea00000
---[ Fixmap end ]---
0xfffffdfffea00000-0xfffffdfffec00000
---[ PCI I/O start ]---
0xfffffdfffec00000-0xfffffdffffc00000
---[ PCI I/O end ]---
0xfffffdffffc00000-0xfffffdffffe00000
---[ vmemmap start ]---
0xfffffdffffe00000-0x0000000000000000
HEAD_TEXT
#include/asm-generic/vmlinux.lds.h
/* Section used for early init (in .S files) */
#define HEAD_TEXT KEEP(*(.head.text))
HEAD_TEXT定义如上,它就是head.S的text段,而由前面分析_text是整个vmlinux镜像的入口地址(0xffff800010000000),也是head.S的入口地址,并且是一个虚拟地址,而实际加载地址位于物理内存的PHYS_OFFSET处,因此加载地址与链接地址不一致,注定了head.S中在开启mmu之前需要运行的是位置无关码
————————————————
版权声明:本文为CSDN博主「HZero.chen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jasonactions/article/details/111190923
本文详细分析了ARM64架构下Linux内核5.10版本的启动流程,特别是head.S的执行细节。通过对vmlinux.lds链接脚本的解析,确定了入口点_text的地址为0xffff800010000000,此地址位于vmalloc区域。HEAD_TEXT段包含了早期初始化的代码,且由于加载地址与链接地址不一致,表明在MMU开启前需要执行位置无关码。

1873

被折叠的 条评论
为什么被折叠?



