]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
riscv: prevent pt_regs corruption for secondary idle threads
authorSergey Matyukevich <sergey.matyukevich@syntacore.com>
Thu, 23 May 2024 08:43:23 +0000 (11:43 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Jun 2024 09:03:59 +0000 (11:03 +0200)
[ Upstream commit a638b0461b58aa3205cd9d5f14d6f703d795b4af ]

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 c7cdd96eca28
("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: 9a2451f18663 ("RISC-V: Avoid using per cpu array for ordered booting")
Fixes: 2875fe056156 ("RISC-V: Add cpu_ops and modify default booting method")
Signed-off-by: Sergey Matyukevich <sergey.matyukevich@syntacore.com>
Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Link: https://lore.kernel.org/r/20240523084327.2013211-1-geomatsi@gmail.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/riscv/kernel/cpu_ops_sbi.c
arch/riscv/kernel/cpu_ops_spinwait.c

index efa0f0816634c40772005bfe564cda4411957a81..93cbc38d18057177846ca9686c45455385126bac 100644 (file)
@@ -72,7 +72,7 @@ static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle)
        /* Make sure tidle is updated */
        smp_mb();
        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 */
        smp_mb();
        hsm_data = __pa(bdata);
index d98d19226b5f5175aca387cf22558bad9df1f2c5..691e0c5366d2bd0b9812fcebe2366d5da3cd2423 100644 (file)
@@ -34,8 +34,7 @@ static void cpu_update_secondary_bootdata(unsigned int cpuid,
 
        /* Make sure tidle is updated */
        smp_mb();
-       WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid],
-                  task_stack_page(tidle) + THREAD_SIZE);
+       WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], task_pt_regs(tidle));
        WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle);
 }