Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1148040
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2020-10-05 23:39:21


asmlinkage __visible void __init start_kernel(void)
{
    char *command_line;
    setup_arch(&command_line);
    setup_command_line(command_line);
}

////////////////////////////////////////////////////////////////////


//这个setup_arch就是各个架构自己的设置函数,哪个参与了编译就调用哪个,arm架构应当是arch/arm/kernel/setup.c中的 setup_arch。void __init setup_arch(char **cmdline_p)
{
    const struct machine_desc *mdesc;

    setup_processor();
//
//setup_machine_fdt函数获取内核前期初始化所需的bootargs,cmd_line等系统引导参数   
//__atags_pointer是bootloader传递参数的物理地址 
     mdesc = setup_machine_fdt(__atags_pointer);
    if (!mdesc)
        mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);

    /* populate cmd_line too for later use, preserving boot_command_line */
    strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
//这是setup_arch的参数出参赋值
    *cmdline_p = cmd_line;

    parse_early_param();

//
//解析设备树
 
    unflatten_device_tree();

    arm_dt_init_cpu_maps();
    psci_init();

    if (!is_smp())
        hyp_mode_check();

    reserve_crashkernel();


    if (mdesc->init_early)
        mdesc->init_early();
}

////////////////////////////////////

/**
 * unflatten_device_tree - create tree of device_nodes from flat blob
 *
 * unflattens the device-tree passed by the firmware, creating the
 * tree of struct device_node. It also fills the "name" and "type"
 * pointers of the nodes so the normal device-tree walking functions
 * can be used.
 */
void __init unflatten_device_tree(void)
{
    __unflatten_device_tree(initial_boot_params, &of_root,
                early_init_dt_alloc_memory_arch);

    /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
    of_alias_scan(early_init_dt_alloc_memory_arch);
}

///////////////////////////////////////////////////

/*
 * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
 * and builds the cpu logical map array containing MPIDR values related to
 * logical cpus
 *
 * Updates the cpu possible mask with the number of parsed cpu nodes
 */
void __init arm_dt_init_cpu_maps(void)
{
    /*
     * Temp logical map is initialized with UINT_MAX values that are
     * considered invalid logical map entries since the logical map must
     * contain a list of MPIDR[23:0] values where MPIDR[31:24] must
     * read as 0.
     */
    struct device_node *cpu, *cpus;
    int found_method = 0;
    u32 i, j, cpuidx = 1;
    u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;

    u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID };
    bool bootcpu_valid = false;
    cpus = of_find_node_by_path("/cpus");

    if (!cpus)
        return;

    for_each_child_of_node(cpus, cpu) {
        u32 hwid;

        if (of_node_cmp(cpu->type, "cpu"))
            continue;

        pr_debug(" * %s...\n", cpu->full_name);
        /*
         * A device tree containing CPU nodes with missing "reg"
         * properties is considered invalid to build the
         * cpu_logical_map.
         */
        if (of_property_read_u32(cpu, "reg", &hwid)) {
            pr_debug(" * %s missing reg property\n",
                     cpu->full_name);
            return;
        }

        /*
         * 8 MSBs must be set to 0 in the DT since the reg property
         * defines the MPIDR[23:0].
         */
        if (hwid & ~MPIDR_HWID_BITMASK)
            return;

        /*
         * Duplicate MPIDRs are a recipe for disaster.
         * Scan all initialized entries and check for
         * duplicates. If any is found just bail out.
         * temp values were initialized to UINT_MAX
         * to avoid matching valid MPIDR[23:0] values.
         */
        for (j = 0; j < cpuidx; j++)
            if (WARN(tmp_map[j] == hwid, "Duplicate /cpu reg "
                             "properties in the DT\n"))
                return;

        /*
         * Build a stashed array of MPIDR values. Numbering scheme
         * requires that if detected the boot CPU must be assigned
         * logical id 0. Other CPUs get sequential indexes starting
         * from 1. If a CPU node with a reg property matching the
         * boot CPU MPIDR is detected, this is recorded so that the
         * logical map built from DT is validated and can be used
         * to override the map created in smp_setup_processor_id().
         */
        if (hwid == mpidr) {
            i = 0;
            bootcpu_valid = true;
        } else {
            i = cpuidx++;
        }

        if (WARN(cpuidx > nr_cpu_ids, "DT /cpu %u nodes greater than "
                           "max cores %u, capping them\n",
                           cpuidx, nr_cpu_ids)) {
            cpuidx = nr_cpu_ids;
            break;
        }

        tmp_map[i] = hwid;

        if (!found_method)
            found_method = set_smp_ops_by_method(cpu);
    }

    /*
     * Fallback to an enable-method in the cpus node if nothing found in
     * a cpu node.
     */
    if (!found_method)
        set_smp_ops_by_method(cpus);

    if (!bootcpu_valid) {
        pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n");
        return;
    }

    /*
     * Since the boot CPU node contains proper data, and all nodes have
     * a reg property, the DT CPU list can be considered valid and the
     * logical map created in smp_setup_processor_id() can be overridden
     */
    for (i = 0; i < cpuidx; i++) {
        set_cpu_possible(i, true);
        cpu_logical_map(i) = tmp_map[i];
        pr_debug("cpu logical map 0x%x\n", cpu_logical_map(i));
    }
}
///////////////////////////////////////////////////////////////

static const struct of_device_id psci_of_match[] __initconst = {
    { .compatible = "arm,psci", .data = psci_0_1_init},
    { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
    {},
};

int __init psci_init(void)
{
    struct device_node *np;
    const struct of_device_id *matched_np;
    psci_initcall_t init_fn;

    np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
    if (!np)
        return -ENODEV;

    init_fn = (psci_initcall_t)matched_np->data;
    return init_fn(np);
}


阅读(1312) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~