RISC-V: Use __cpu_up_stack/task_pointer only for spinwait method
The __cpu_up_stack/task_pointer array is only used for spinwait method now. The per cpu array based lookup is also fragile for platforms with discontiguous/sparse hartids. The spinwait method is only used for M-mode Linux or older firmwares without SBI HSM extension. For general Linux systems, ordered booting method is preferred anyways to support cpu hotplug and kexec. Make sure that __cpu_up_stack/task_pointer is only used for spinwait method. Take this opportunity to rename it to __cpu_spinwait_stack/task_pointer to emphasize the purpose as well. Reviewed-by: Anup Patel <anup@brainfault.org> Signed-off-by: Atish Patra <atishp@rivosinc.com> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Родитель
410bb20a69
Коммит
c78f94f35c
|
@ -40,7 +40,5 @@ struct cpu_operations {
|
|||
|
||||
extern const struct cpu_operations *cpu_ops[NR_CPUS];
|
||||
void __init cpu_set_ops(int cpu);
|
||||
void cpu_update_secondary_bootdata(unsigned int cpuid,
|
||||
struct task_struct *tidle);
|
||||
|
||||
#endif /* ifndef __ASM_CPU_OPS_H */
|
||||
|
|
|
@ -8,31 +8,15 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <asm/cpu_ops.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
|
||||
|
||||
void *__cpu_up_stack_pointer[NR_CPUS] __section(".data");
|
||||
void *__cpu_up_task_pointer[NR_CPUS] __section(".data");
|
||||
|
||||
extern const struct cpu_operations cpu_ops_sbi;
|
||||
extern const struct cpu_operations cpu_ops_spinwait;
|
||||
|
||||
void cpu_update_secondary_bootdata(unsigned int cpuid,
|
||||
struct task_struct *tidle)
|
||||
{
|
||||
int hartid = cpuid_to_hartid_map(cpuid);
|
||||
|
||||
/* Make sure tidle is updated */
|
||||
smp_mb();
|
||||
WRITE_ONCE(__cpu_up_stack_pointer[hartid],
|
||||
task_stack_page(tidle) + THREAD_SIZE);
|
||||
WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
|
||||
}
|
||||
|
||||
void __init cpu_set_ops(int cpuid)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_RISCV_SBI)
|
||||
|
|
|
@ -6,11 +6,36 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <asm/cpu_ops.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
const struct cpu_operations cpu_ops_spinwait;
|
||||
void *__cpu_spinwait_stack_pointer[NR_CPUS] __section(".data");
|
||||
void *__cpu_spinwait_task_pointer[NR_CPUS] __section(".data");
|
||||
|
||||
static void cpu_update_secondary_bootdata(unsigned int cpuid,
|
||||
struct task_struct *tidle)
|
||||
{
|
||||
int hartid = cpuid_to_hartid_map(cpuid);
|
||||
|
||||
/*
|
||||
* The hartid must be less than NR_CPUS to avoid out-of-bound access
|
||||
* errors for __cpu_spinwait_stack/task_pointer. That is not always possible
|
||||
* for platforms with discontiguous hartid numbering scheme. That's why
|
||||
* spinwait booting is not the recommended approach for any platforms
|
||||
* booting Linux in S-mode and can be disabled in the future.
|
||||
*/
|
||||
if (hartid == INVALID_HARTID || hartid >= NR_CPUS)
|
||||
return;
|
||||
|
||||
/* Make sure tidle is updated */
|
||||
smp_mb();
|
||||
WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid],
|
||||
task_stack_page(tidle) + THREAD_SIZE);
|
||||
WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle);
|
||||
}
|
||||
|
||||
static int spinwait_cpu_prepare(unsigned int cpuid)
|
||||
{
|
||||
|
@ -28,7 +53,7 @@ static int spinwait_cpu_start(unsigned int cpuid, struct task_struct *tidle)
|
|||
* selects the first cpu to boot the kernel and causes the remainder
|
||||
* of the cpus to spin in a loop waiting for their stack pointer to be
|
||||
* setup by that main cpu. Writing to bootdata
|
||||
* (i.e __cpu_up_stack_pointer) signals to the spinning cpus that they
|
||||
* (i.e __cpu_spinwait_stack_pointer) signals to the spinning cpus that they
|
||||
* can continue the boot process.
|
||||
*/
|
||||
cpu_update_secondary_bootdata(cpuid, tidle);
|
||||
|
|
|
@ -347,9 +347,9 @@ clear_bss_done:
|
|||
csrw CSR_TVEC, a3
|
||||
|
||||
slli a3, a0, LGREG
|
||||
la a1, __cpu_up_stack_pointer
|
||||
la a1, __cpu_spinwait_stack_pointer
|
||||
XIP_FIXUP_OFFSET a1
|
||||
la a2, __cpu_up_task_pointer
|
||||
la a2, __cpu_spinwait_task_pointer
|
||||
XIP_FIXUP_OFFSET a2
|
||||
add a1, a3, a1
|
||||
add a2, a3, a2
|
||||
|
|
|
@ -16,7 +16,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa);
|
|||
asmlinkage void __init __copy_data(void);
|
||||
#endif
|
||||
|
||||
extern void *__cpu_up_stack_pointer[];
|
||||
extern void *__cpu_up_task_pointer[];
|
||||
extern void *__cpu_spinwait_stack_pointer[];
|
||||
extern void *__cpu_spinwait_task_pointer[];
|
||||
|
||||
#endif /* __ASM_HEAD_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче