init/main.c
start_kernel
- >boot_cpu_init //引導(dǎo)cpu初始化 設(shè)置引導(dǎo)cpu的位掩碼 online active present possible都為true
- >setup_arch // arch/arm64/kernel/setup.c
- > if (acpi_disabled) //不支持acpi
psci_dt_init(); //drivers/firmware/psci.c(psci主要文件) psci初始化 解析設(shè)備樹 尋找psci匹配的節(jié)點(diǎn)
else
psci_acpi_init(); //acpi中允許使用psci情況
- >rest_init
- >kernel_init
- >kernel_init_freeable
- >smp_prepare_cpus //準(zhǔn)備cpu 對于每個(gè)可能的cpu 1. cpu_ops[cpu]- >cpu_prepare(cpu) 2.set_cpu_present(cpu, true) cpu處于present狀態(tài)
- >do_pre_smp_initcalls //多核啟動(dòng)之前的調(diào)用initcall回調(diào)
- >smp_init //smp初始化 kernel/smp.c 會(huì)啟動(dòng)其他從處理器
我們主要關(guān)注兩個(gè)函數(shù):psci_dt_init和smp_init psci_dt_init是解析設(shè)備樹,設(shè)置操作函數(shù),smp_init用于啟動(dòng)從處理器。
- >psci_dt_init() //drivers/firmware/psci.c:
- >init_fn()
- >psci_0_1_init() //設(shè)備樹中compatible = "arm,psci"為例
- >get_set_conduit_method() //根據(jù)設(shè)備樹method屬性設(shè)置 invoke_psci_fn = __invoke_psci_fn_smc; (method="smc")
- > invoke_psci_fn = __invoke_psci_fn_smc
- > if (!of_property_read_u32(np, "cpu_on", &id)) {
651 psci_function_id[PSCI_FN_CPU_ON] = id;
652 psci_ops.cpu_on = psci_cpu_on; //設(shè)置psci操作的開核接口
653 }
- >psci_cpu_on()
- >invoke_psci_fn()
- >__invoke_psci_fn_smc()
- > arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res) //這個(gè)時(shí)候x0=function_id x1=arg0, x2=arg1, x3arg2,...
- >__arm_smccc_smc()
- >SMCCC smc //arch/arm64/kernel/smccc-call.S
- > 20 .macro SMCCC instr
21 .cfi_startproc
22 instr #0 //即是smc #0 陷入到el3
23 ldr x4, [sp]
24 stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
25 stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
26 ldr x4, [sp, #8]
27 cbz x4, 1f /* no quirk structure */
28 ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
29 cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6
30 b.ne 1f
31 str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
32 1: ret
33 .cfi_endproc
34 .endm
最終通過22行 陷入了el3中。(這是因?yàn)榘踩赃€需要到ATF中啟動(dòng))smp_init函數(shù)做從處理器啟動(dòng):
start_kernel
- >arch_call_rest_init
- >rest_init
- >kernel_init,
- >kernel_init_freeable
- >smp_prepare_cpus //arch/arm64/kernel/smp.c
- >smp_init //kernel/smp.c (這是從處理器啟動(dòng)的函數(shù))
- >cpu_up
- >do_cpu_up
- >_cpu_up
- >cpuhp_up_callbacks
- >cpuhp_invoke_callback
- >cpuhp_hp_states[CPUHP_BRINGUP_CPU]
- >bringup_cpu
- >__cpu_up //arch/arm64/kernel/smp.c
- >boot_secondary
- >cpu_ops[cpu]- >cpu_boot(cpu)
- >cpu_psci_ops.cpu_boot
- >cpu_psci_cpu_boot //arch/arm64/kernel/psci.c
46 static int cpu_psci_cpu_boot(unsigned int cpu)
47 {
48 int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa_symbol(secondary_entry));
49 if (err)
50 pr_err("failed to boot CPU%d (%d)n", cpu, err);
51
52 return err;
53 }
啟動(dòng)從處理的時(shí)候最終調(diào)用到psci的cpu操作集的cpu_psci_cpu_boot函數(shù) ,會(huì)調(diào)用上面的psci_cpu_on,最終調(diào)用smc,傳遞第一個(gè)參數(shù)為cpu的id標(biāo)識(shí)啟動(dòng)哪個(gè)cpu,第二個(gè)參數(shù)為從處理器啟動(dòng)后進(jìn)入內(nèi)核執(zhí)行的地址secondary_entry(這是個(gè)物理地址)。
所以綜上,最后smc調(diào)用時(shí)傳遞的參數(shù)為arm_smccc_smc(0xC4000003, cpuid, secondary_entry, arg2, 0, 0, 0, 0, &res)。這樣陷入el3之后,就可以啟動(dòng)對應(yīng)的從處理器, 最終從處理器回到內(nèi)核(el3->el1),執(zhí)行secondary_entry處指令 ,從處理器啟動(dòng)完成。
可以發(fā)現(xiàn)psci的方式啟動(dòng)從處理器的方式相當(dāng)復(fù)雜,這里面涉及到了el1到安全的el3的跳轉(zhuǎn),而且涉及到大量的函數(shù)回調(diào),很容易繞暈。
(其實(shí)為了安全,所以啟動(dòng)從核開核這個(gè)操作必須在EL3,開了以后,就可以會(huì)EL1,因?yàn)橐呀?jīng)在EL3給你了準(zhǔn)確安全的啟動(dòng)位置了。)
-
處理器
+關(guān)注
關(guān)注
68文章
19432瀏覽量
231284 -
cpu
+關(guān)注
關(guān)注
68文章
10908瀏覽量
213111 -
SMP
+關(guān)注
關(guān)注
0文章
76瀏覽量
19758 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
62999
發(fā)布評論請先 登錄
相關(guān)推薦
四核Vs八核移動(dòng)處理器 性能差異并不大
四核處理器和八核處理器的區(qū)別,這篇文章終于講明白了
求一種在多處理器系統(tǒng)中的Nios II軟核處理器的啟動(dòng)方案
探討一下ARM處理器中的CPSR寄存器
分析ARMv8處理器產(chǎn)生異常的原因以及異常返回時(shí)的動(dòng)作
多核處理器啟動(dòng)的基本原理是什么?如何實(shí)現(xiàn)呢
看看一個(gè)多核處理器系統(tǒng)是如何啟動(dòng)的
Banias處理器
Intel雙核處理器,Intel雙核處理器是什么意思
四核處理器簡介
![四<b class='flag-5'>核</b><b class='flag-5'>處理器</b>簡介](https://file1.elecfans.com//web2/M00/A6/22/wKgZomUMO-aAU797AAASfdO0gko297.jpg)
評論