美文网首页
Linux arm64 启动过程简析

Linux arm64 启动过程简析

作者: jackniu_ae28 | 来源:发表于2020-03-26 16:01 被阅读0次

1. arch/arm64/kernel/head.S 开始分析

_head:
    /*
     * The following callee saved general purpose registers are used on the
     * primary lowlevel boot path:
     *
     *  Register   Scope                      Purpose
     *  x21        stext() .. start_kernel()  FDT pointer passed at boot in x0
     *  x23        stext() .. start_kernel()  physical misalignment/KASLR offset
     *  x28        __create_page_tables()     callee preserved temp register
     *  x19/x20    __primary_switch()         callee preserved temp registers
     */
ENTRY(stext)
    bl  preserve_boot_args                                 #A 存储  bootloader 传递过来的参数
    bl  el2_setup                                        // Drop to EL1, w0=cpu_boot_mode
    adrp    x23, __PHYS_OFFSET
    and x23, x23, MIN_KIMG_ALIGN - 1       // KASLR offset, defaults to 0
    bl  set_cpu_boot_mode_flag                   //B
    bl  __create_page_tables                         //C
    /*
     * The following calls CPU setup code, see arch/arm64/mm/proc.S for
     * details.
     * On return, the CPU will be ready for the MMU to be turned on and
     * the TCR will have been set.
     */
    bl  __cpu_setup         //D initialise processor
    b   __primary_switch            //E
ENDPROC(stext)

程序通过下面调用对处理器基本初始化和存储boot传递过来的dtb指针mov x21, x0存储到x21中,最后调用__primary_switch进入下面代码部分使用 str_l x21, __fdt_pointer, x5dtb指针存储到__fdt_pointer 里面,在用C代码去使用。


2.调用过程

bl preserve_boot_args
|
mov x21, x0 // x21=FDT

bl set_cpu_boot_mode_flag

bl __create_page_tables

bl __cpu_setup

b __primary_switch
| bl __enable_mmu
| bl __relocate_kernel
|
|__primary_switched
|
| str_l x21, __fdt_pointer, x5 // Save FDT pointer(保存dtb文件)
|
b start_kernel //启动内核


__primary_switch:
#ifdef CONFIG_RANDOMIZE_BASE
    mov x19, x0             // preserve new SCTLR_EL1 value
    mrs x20, sctlr_el1          // preserve old SCTLR_EL1 value
#endif

    bl  __enable_mmu
#ifdef CONFIG_RELOCATABLE
    bl  __relocate_kernel
#ifdef CONFIG_RANDOMIZE_BASE
    ldr x8, =__primary_switched
    adrp    x0, __PHYS_OFFSET
    blr x8

    /*
     * If we return here, we have a KASLR displacement in x23 which we need
     * to take into account by discarding the current kernel mapping and
     * creating a new one.
     */
    pre_disable_mmu_workaround
    msr sctlr_el1, x20          // disable the MMU
    isb
    bl  __create_page_tables        // recreate kernel mapping

    tlbi    vmalle1             // Remove any stale TLB entries
    dsb nsh

    msr sctlr_el1, x19          // re-enable the MMU
    isb
    ic  iallu               // flush instructions fetched
    dsb nsh             // via old mapping
    isb

    bl  __relocate_kernel
#endif
#endif
    ldr x8, =__primary_switched
    adrp    x0, __PHYS_OFFSET
    br  x8
ENDPROC(__primary_switch)
/*
 * The following fragment of code is executed with the MMU enabled.
 *
 *   x0 = __PHYS_OFFSET
 */
__primary_switched:
    adrp    x4, init_thread_union
    add sp, x4, #THREAD_SIZE
    adr_l   x5, init_task
    msr sp_el0, x5          // Save thread_info

    adr_l   x8, vectors         // load VBAR_EL1 with virtual
    msr vbar_el1, x8            // vector table address
    isb

    stp xzr, x30, [sp, #-16]!
    mov x29, sp

    str_l   x21, __fdt_pointer, x5      // Save FDT pointer

    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

    // Clear BSS
    adr_l   x0, __bss_start
    mov x1, xzr
    adr_l   x2, __bss_stop
    sub x2, x2, x0
    bl  __pi_memset
    dsb ishst               // Make zero page visible to PTW

#ifdef CONFIG_KASAN
    bl  kasan_early_init
#endif
#ifdef CONFIG_RANDOMIZE_BASE
    tst x23, ~(MIN_KIMG_ALIGN - 1)  // already running randomized?
    b.ne    0f
    mov x0, x21             // pass FDT address in x0
    bl  kaslr_early_init        // parse FDT for KASLR options
    cbz x0, 0f              // KASLR disabled? just proceed
    orr x23, x23, x0            // record KASLR offset
    ldp x29, x30, [sp], #16     // we must enable KASLR, return
    ret                 // to __primary_switch()
0:
#endif
    add sp, sp, #16
    mov x29, #0
    mov x30, #0
    b   start_kernel
ENDPROC(__primary_switched)

/*
 * Preserve the arguments passed by the bootloader in x0 .. x3
 */
preserve_boot_args:
    mov x21, x0             // x21=FDT

    adr_l   x0, boot_args           // record the contents of
    stp x21, x1, [x0]           // x0 .. x3 at kernel entry
    stp x2, x3, [x0, #16]

    dmb sy              // needed before dc ivac with
                        // MMU off

    mov x1, #0x20           // 4 x 8 bytes
    b   __inval_dcache_area     // tail call
ENDPROC(preserve_boot_args)

3.__fdt_pointer 地址时哪里呢?

答:0x83000000 开机后输入 printenv打印环境参数如下

fdt_addr=0x83000000
loadaddr=0x80280000
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}

loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}

使用md - memory display命令显示这个内存的信息

image.png
使用hexdump -C 查看源文件如下,确实一样的文件。
image.png

内核查看


image.png

内核源文件查看


image.png

4.代码里面打印证明地址信息

arch/arm64/kernel/setup.c 查看里面添加打印信息查看__fdt_pointer 地址时0x83000000
在这个地址开始有dtb文件,扫描这个地址就行了。

static void __init setup_machine_fdt(phys_addr_t dt_phys)//
{
   void *dt_virt = fixmap_remap_fdt(dt_phys);
   const char *name;

   if (!dt_virt || !early_init_dt_scan(dt_virt)) {
       pr_crit("\n"
           "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n"
           "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n"
           "\nPlease check your bootloader.",
           &dt_phys, dt_virt);

       while (true)
           cpu_relax();
   }

   name = of_flat_dt_get_machine_name();
   if (!name)
       return;

   pr_info("Machine model: %s\n", name);
   pr_info("%s,%d: dt_phys:%x  dt_virt:%x \n",__func__,__LINE__,dt_phys,dt_virt);
   dump_stack_set_arch_desc("%s (DT)", name);
}

image.png

相关文章

网友评论

      本文标题:Linux arm64 启动过程简析

      本文链接:https://www.haomeiwen.com/subject/jsjcuhtx.html