Kernel启动流程源码解析 6 setup_arch

本文详细介绍了Linux内核在ARM64架构下的setup_arch函数,包括setup_processor、setup_machine_fdt、arm64_memblock_init等步骤,涉及处理器检测、设备树处理、内存管理、分页机制初始化等内容,揭示了内核启动过程的关键细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一 setup_arch

setup_arch顾名思义就是架构相关的初始化函数,这里选取arm64结构进行分析。

1.0 setup_arch

定义在arch/arm64/kernel/setup.c中
void __init setup_arch(char **cmdline_p)
{
    setup_processor(); // 检测处理器类型,并初始化处理器相关的底层变量

    setup_machine_fdt(__fdt_pointer); // 获取device tree信息,并设置一些device tree相关全局变量信息
    init_mm.start_code = (unsigned long) _text; // 记录kernel代码段的虚拟启始地址
    init_mm.end_code   = (unsigned long) _etext; // 记录kernel代码段的虚拟结束地址
    init_mm.end_data   = (unsigned long) _edata; // 记录kernel数据段的虚拟结束地址
    init_mm.brk       = (unsigned long) _end; // brk指向kernel全部段的虚拟结束地址

    *cmdline_p = boot_command_line; // 将boot_command_line的地址保存到start_kernel局部指针变量cmdline_p中

    parse_early_param(); // 解析需要'早期'处理的启动参数用

    arm64_memblock_init(); // 初始化memblock,用于引导阶段的内存管理

    paging_init(); // 初始化分页机制
    request_standard_resources(); // 申请内核代码段和数据段内存资源

    unflatten_device_tree(); // DTB转换成节点是device_node的树状结构

    psci_init(); // Power State Coordination Interface,和多核启动相关,暂时没有用到

    cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
    cpu_read_bootcpu_ops(); // 获取cpu0的enable method
#ifdef CONFIG_SMP
    smp_init_cpus(); // 获取除cpu0外的其他cpu信息,并将它们设为possible状态
    smp_build_mpidr_hash(); // 生成MPIDR(cpu id) hash
#endif

#ifdef CONFIG_VT // 虚拟终端
#if defined(CONFIG_VGA_CONSOLE)
    conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
    conswitchp = &dummy_con;
#endif
#endif
}



1.1 setup_processor

定义在arch/arm64/kernel/setup.c中
static void __init setup_processor(void)
{
    struct cpu_info *cpu_info;

    /*
     * locate processor in the list of supported processor
     * types.  The linker builds this table for us from the
     * entries in arch/arm/mm/proc.S
     */
    cpu_info = lookup_processor_type(read_cpuid_id());
    if (!cpu_info) {
        printk("CPU configuration botched (ID %08x), unable to continue.\n",
               read_cpuid_id());
        while (1);
    }

    cpu_name = cpu_info->cpu_name;

    printk("CPU: %s [%08x] revision %d\n",
           cpu_name, read_cpuid_id(), read_cpuid_id() & 15);

    sprintf(init_utsname()->machine, "aarch64");
    elf_hwcap = 0;
}

struct cpu_info cpu_table[] = {
    {
        .cpu_id_val = 0x000f0000,
        .cpu_id_mask    = 0x000f0000,
        .cpu_name   = "AArch64 Processor",
        .cpu_setup  = __cpu_setup,
    },
    { /* Empty */ },
};

1.2 setup_machine_fdt

定义在arch/arm64/kernel/setup.c中
static void __init setup_machine_fdt(phys_addr_t dt_phys)
{
    struct boot_param_header *devtree;
    unsigned long dt_root;

    /* Check we have a non-NULL DT pointer */
    if (!dt_phys) {
        early_print("\n"
            "Error: NULL or invalid device tree blob\n"
            "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
            "\nPlease check your bootloader.\n");

        while (true)
            cpu_relax();

    }

    devtree = phys_to_virt(dt_phys);

    /* Check device tree validity */
    if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {
        early_print("\n"
            "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"
            "Expected 0x%x, found 0x%x\n"
            "\nPlease check your bootloader.\n",
            dt_phys, devtree, OF_DT_HEADER,
            be32_to_cpu(devtree->magic));

        while (true)
            cpu_relax();
    }

    initial_boot_params = devtree; // 全局变量initial_boot_params保存dev
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值