RISC-V: Avoid using per cpu array for ordered booting
Currently both order booting and spinwait approach uses a per cpu array to update stack & task pointer. This approach will not work for the following cases. 1. If NR_CPUs are configured to be less than highest hart id. 2. A platform has sparse hartid. This issue can be fixed for ordered booting as the booting cpu brings up one cpu at a time using SBI HSM extension which has opaque parameter that is unused until now. Introduce a common secondary boot data structure that can store the stack and task pointer. Secondary harts will use this data while booting up to setup the sp & tp. 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:
parent
3938d5a2f9
commit
9a2451f186
4 changed files with 57 additions and 14 deletions
25
arch/riscv/include/asm/cpu_ops_sbi.h
Normal file
25
arch/riscv/include/asm/cpu_ops_sbi.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 by Rivos Inc.
|
||||||
|
*/
|
||||||
|
#ifndef __ASM_CPU_OPS_SBI_H
|
||||||
|
#define __ASM_CPU_OPS_SBI_H
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/threads.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sbi_hart_boot_data - Hart specific boot used during booting and
|
||||||
|
* cpu hotplug.
|
||||||
|
* @task_ptr: A pointer to the hart specific tp
|
||||||
|
* @stack_ptr: A pointer to the hart specific sp
|
||||||
|
*/
|
||||||
|
struct sbi_hart_boot_data {
|
||||||
|
void *task_ptr;
|
||||||
|
void *stack_ptr;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ifndef __ASM_CPU_OPS_SBI_H */
|
|
@ -12,6 +12,7 @@
|
||||||
#include <asm/kvm_host.h>
|
#include <asm/kvm_host.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
#include <asm/cpu_ops_sbi.h>
|
||||||
|
|
||||||
void asm_offsets(void);
|
void asm_offsets(void);
|
||||||
|
|
||||||
|
@ -468,4 +469,6 @@ void asm_offsets(void)
|
||||||
DEFINE(PT_SIZE_ON_STACK, ALIGN(sizeof(struct pt_regs), STACK_ALIGN));
|
DEFINE(PT_SIZE_ON_STACK, ALIGN(sizeof(struct pt_regs), STACK_ALIGN));
|
||||||
|
|
||||||
OFFSET(KERNEL_MAP_VIRT_ADDR, kernel_mapping, virt_addr);
|
OFFSET(KERNEL_MAP_VIRT_ADDR, kernel_mapping, virt_addr);
|
||||||
|
OFFSET(SBI_HART_BOOT_TASK_PTR_OFFSET, sbi_hart_boot_data, task_ptr);
|
||||||
|
OFFSET(SBI_HART_BOOT_STACK_PTR_OFFSET, sbi_hart_boot_data, stack_ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,22 @@
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
#include <linux/sched/task_stack.h>
|
||||||
#include <asm/cpu_ops.h>
|
#include <asm/cpu_ops.h>
|
||||||
|
#include <asm/cpu_ops_sbi.h>
|
||||||
#include <asm/sbi.h>
|
#include <asm/sbi.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
|
||||||
extern char secondary_start_sbi[];
|
extern char secondary_start_sbi[];
|
||||||
const struct cpu_operations cpu_ops_sbi;
|
const struct cpu_operations cpu_ops_sbi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ordered booting via HSM brings one cpu at a time. However, cpu hotplug can
|
||||||
|
* be invoked from multiple threads in parallel. Define a per cpu data
|
||||||
|
* to handle that.
|
||||||
|
*/
|
||||||
|
DEFINE_PER_CPU(struct sbi_hart_boot_data, boot_data);
|
||||||
|
|
||||||
static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr,
|
static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr,
|
||||||
unsigned long priv)
|
unsigned long priv)
|
||||||
{
|
{
|
||||||
|
@ -55,14 +64,19 @@ static int sbi_hsm_hart_get_status(unsigned long hartid)
|
||||||
|
|
||||||
static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle)
|
static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
unsigned long boot_addr = __pa_symbol(secondary_start_sbi);
|
unsigned long boot_addr = __pa_symbol(secondary_start_sbi);
|
||||||
int hartid = cpuid_to_hartid_map(cpuid);
|
int hartid = cpuid_to_hartid_map(cpuid);
|
||||||
|
unsigned long hsm_data;
|
||||||
|
struct sbi_hart_boot_data *bdata = &per_cpu(boot_data, cpuid);
|
||||||
|
|
||||||
cpu_update_secondary_bootdata(cpuid, tidle);
|
/* Make sure tidle is updated */
|
||||||
rc = sbi_hsm_hart_start(hartid, boot_addr, 0);
|
smp_mb();
|
||||||
|
bdata->task_ptr = tidle;
|
||||||
return rc;
|
bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE;
|
||||||
|
/* Make sure boot data is updated */
|
||||||
|
smp_mb();
|
||||||
|
hsm_data = __pa(bdata);
|
||||||
|
return sbi_hsm_hart_start(hartid, boot_addr, hsm_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sbi_cpu_prepare(unsigned int cpuid)
|
static int sbi_cpu_prepare(unsigned int cpuid)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/csr.h>
|
#include <asm/csr.h>
|
||||||
|
#include <asm/cpu_ops_sbi.h>
|
||||||
#include <asm/hwcap.h>
|
#include <asm/hwcap.h>
|
||||||
#include <asm/image.h>
|
#include <asm/image.h>
|
||||||
#include "efi-header.S"
|
#include "efi-header.S"
|
||||||
|
@ -168,15 +169,15 @@ secondary_start_sbi:
|
||||||
la a3, .Lsecondary_park
|
la a3, .Lsecondary_park
|
||||||
csrw CSR_TVEC, a3
|
csrw CSR_TVEC, a3
|
||||||
|
|
||||||
slli a3, a0, LGREG
|
/* a0 contains the hartid & a1 contains boot data */
|
||||||
la a4, __cpu_up_stack_pointer
|
li a2, SBI_HART_BOOT_TASK_PTR_OFFSET
|
||||||
XIP_FIXUP_OFFSET a4
|
XIP_FIXUP_OFFSET a2
|
||||||
la a5, __cpu_up_task_pointer
|
add a2, a2, a1
|
||||||
XIP_FIXUP_OFFSET a5
|
REG_L tp, (a2)
|
||||||
add a4, a3, a4
|
li a3, SBI_HART_BOOT_STACK_PTR_OFFSET
|
||||||
add a5, a3, a5
|
XIP_FIXUP_OFFSET a3
|
||||||
REG_L sp, (a4)
|
add a3, a3, a1
|
||||||
REG_L tp, (a5)
|
REG_L sp, (a3)
|
||||||
|
|
||||||
.Lsecondary_start_common:
|
.Lsecondary_start_common:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue