CPU0
从 u-boot 的 theKernel 到 linux的 start_kernel中的 stext -> start_kernel
cpu 寄存器的初始化
sp寄存器
cpsr
Supervisor Mode
irq disabled
fiq disabled
little endian
cp15 寄存器 的初始化
cache
dcache
icache
write buffer
mmu
page table
domain access
CPU1 …
cpu 寄存器的初始化
sp寄存器 // 值来自于 cpu0的设定值 secondary_data.stack
cpsr
Supervisor Mode
irq disabled
fiq disabled
little endian
cp15 寄存器 的初始化
cache
dcache
icache
write buffer
mmu
page table // 值来自于 cpu0的设置值 secondary_data.pgdir
domain access // 值来自于 cpu0的设置值 secondary_data.pgdir
流程
cpu0:smp_init
idle_threads_init
for_each_possible_cpu idle_init
fork_idle
copy_process
bringup_nonboot_cpus
cpu_up
_cpu_up
// cpu1跑起来的时候会设置自己cpu1,参数就是下面的值
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
secondary_data.pgdir = virt_to_phys(idmap_pgd);
secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
smp_ops.smp_boot_secondary(cpu, idle); / 即 psci_boot_secondary
psci_ops.cpu_on // 对应 0.1 版本的 psci为 psci_0_1_cpu_on
psci_0_1_cpu_on
__psci_cpu_on
invoke_psci_fn // 调用什么 取决于 set_conduit 的设定值
__invoke_psci_fn_smc
arm_smccc_smc
__arm_smccc_smc
SMCCC SMCCC_SMC
__SMC
0xE1600070 | (((imm4) & 0xF) << 0),
0xF7F08000 | (((imm4) & 0xF) << 16)
cpu1:secondary_startup
// 设置为 svc mode
// irq off
// fiq off
safe_svcmode_maskall r9
// 将 __secondary_switched 放到 r13
mov_l r12, __secondary_switched
mov r13, r12
// 跳转到 arch/arm/mm/proc-v6.S 中的 __v6_setup ,并返回
ldr r12, [r10, #PROCINFO_INITFUNC]
add r12, r12, r10
ret r12
// 跳转到 __enable_mmu
__enable_mmu
// 用 secondary_data.pgdir 设置 page table pointer
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
b __turn_mmu_on
__turn_mmu_on
// 跳转到 __secondary_switched
mov r3, r13
ret r3
__secondary_switched
// 用 secondary_data.stack 的值 设置 sp
ldr_l r7, secondary_data + 12
mov sp, r7
// 跳转到 secondary_start_kernel
b secondary_start_kernel
上一篇:OK6410A 开发板 (八) 23 linux-5.11 OK6410A start_kernel 功能角度 第二阶段
下一篇:OK6410A 开发板 (八) 21 linux-5.11 OK6410A schedule 的 __switch_to 部分
推荐阅读最新更新时间:2024-11-07 14:24