Skip to content

Commit a638b04

Browse files
sm-scpalmer-dabbelt
authored andcommitted
riscv: prevent pt_regs corruption for secondary idle threads
Top of the kernel thread stack should be reserved for pt_regs. However this is not the case for the idle threads of the secondary boot harts. Their stacks overlap with their pt_regs, so both may get corrupted. Similar issue has been fixed for the primary hart, see c7cdd96 ("riscv: prevent stack corruption by reserving task_pt_regs(p) early"). However that fix was not propagated to the secondary harts. The problem has been noticed in some CPU hotplug tests with V enabled. The function smp_callin stored several registers on stack, corrupting top of pt_regs structure including status field. As a result, kernel attempted to save or restore inexistent V context. Fixes: 9a2451f ("RISC-V: Avoid using per cpu array for ordered booting") Fixes: 2875fe0 ("RISC-V: Add cpu_ops and modify default booting method") Signed-off-by: Sergey Matyukevich <[email protected]> Reviewed-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 1613e60 commit a638b04

File tree

2 files changed

+2
-3
lines changed

2 files changed

+2
-3
lines changed

arch/riscv/kernel/cpu_ops_sbi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle)
7272
/* Make sure tidle is updated */
7373
smp_mb();
7474
bdata->task_ptr = tidle;
75-
bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE;
75+
bdata->stack_ptr = task_pt_regs(tidle);
7676
/* Make sure boot data is updated */
7777
smp_mb();
7878
hsm_data = __pa(bdata);

arch/riscv/kernel/cpu_ops_spinwait.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ static void cpu_update_secondary_bootdata(unsigned int cpuid,
3434

3535
/* Make sure tidle is updated */
3636
smp_mb();
37-
WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid],
38-
task_stack_page(tidle) + THREAD_SIZE);
37+
WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], task_pt_regs(tidle));
3938
WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle);
4039
}
4140

0 commit comments

Comments
 (0)