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 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 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);} 12-28 12:20