Commit a638b046 authored by Sergey Matyukevich's avatar Sergey Matyukevich Committed by Palmer Dabbelt

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 c7cdd96e
("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: 9a2451f1 ("RISC-V: Avoid using per cpu array for ordered booting")
Fixes: 2875fe05 ("RISC-V: Add cpu_ops and modify default booting method")
Signed-off-by: default avatarSergey Matyukevich <sergey.matyukevich@syntacore.com>
Reviewed-by: default avatarAlexandre Ghiti <alexghiti@rivosinc.com>
Link: https://lore.kernel.org/r/20240523084327.2013211-1-geomatsi@gmail.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 1613e604
...@@ -72,7 +72,7 @@ static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle) ...@@ -72,7 +72,7 @@ static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle)
/* Make sure tidle is updated */ /* Make sure tidle is updated */
smp_mb(); smp_mb();
bdata->task_ptr = tidle; bdata->task_ptr = tidle;
bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE; bdata->stack_ptr = task_pt_regs(tidle);
/* Make sure boot data is updated */ /* Make sure boot data is updated */
smp_mb(); smp_mb();
hsm_data = __pa(bdata); hsm_data = __pa(bdata);
......
...@@ -34,8 +34,7 @@ static void cpu_update_secondary_bootdata(unsigned int cpuid, ...@@ -34,8 +34,7 @@ static void cpu_update_secondary_bootdata(unsigned int cpuid,
/* Make sure tidle is updated */ /* Make sure tidle is updated */
smp_mb(); smp_mb();
WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], task_pt_regs(tidle));
task_stack_page(tidle) + THREAD_SIZE);
WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle); WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment