kernel启动流程-head.S的执行_1.概述

本文详细分析了ARM64架构下Linux内核5.10版本的启动流程,特别是head.S的执行细节。通过对vmlinux.lds链接脚本的解析,确定了入口点_text的地址为0xffff800010000000,此地址位于vmalloc区域。HEAD_TEXT段包含了早期初始化的代码,且由于加载地址与链接地址不一致,表明在MMU开启前需要执行位置无关码。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值