Skip to content

Commit 9a2451f

Browse files
atishp04palmer-dabbelt
authored andcommitted
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 <[email protected]> Signed-off-by: Atish Patra <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 3938d5a commit 9a2451f

File tree

4 files changed

+58
-15
lines changed

4 files changed

+58
-15
lines changed

arch/riscv/include/asm/cpu_ops_sbi.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (c) 2021 by Rivos Inc.
4+
*/
5+
#ifndef __ASM_CPU_OPS_SBI_H
6+
#define __ASM_CPU_OPS_SBI_H
7+
8+
#ifndef __ASSEMBLY__
9+
#include <linux/init.h>
10+
#include <linux/sched.h>
11+
#include <linux/threads.h>
12+
13+
/**
14+
* struct sbi_hart_boot_data - Hart specific boot used during booting and
15+
* cpu hotplug.
16+
* @task_ptr: A pointer to the hart specific tp
17+
* @stack_ptr: A pointer to the hart specific sp
18+
*/
19+
struct sbi_hart_boot_data {
20+
void *task_ptr;
21+
void *stack_ptr;
22+
};
23+
#endif
24+
25+
#endif /* ifndef __ASM_CPU_OPS_SBI_H */

arch/riscv/kernel/asm-offsets.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <asm/kvm_host.h>
1313
#include <asm/thread_info.h>
1414
#include <asm/ptrace.h>
15+
#include <asm/cpu_ops_sbi.h>
1516

1617
void asm_offsets(void);
1718

@@ -468,4 +469,6 @@ void asm_offsets(void)
468469
DEFINE(PT_SIZE_ON_STACK, ALIGN(sizeof(struct pt_regs), STACK_ALIGN));
469470

470471
OFFSET(KERNEL_MAP_VIRT_ADDR, kernel_mapping, virt_addr);
472+
OFFSET(SBI_HART_BOOT_TASK_PTR_OFFSET, sbi_hart_boot_data, task_ptr);
473+
OFFSET(SBI_HART_BOOT_STACK_PTR_OFFSET, sbi_hart_boot_data, stack_ptr);
471474
}

arch/riscv/kernel/cpu_ops_sbi.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,22 @@
77

88
#include <linux/init.h>
99
#include <linux/mm.h>
10+
#include <linux/sched/task_stack.h>
1011
#include <asm/cpu_ops.h>
12+
#include <asm/cpu_ops_sbi.h>
1113
#include <asm/sbi.h>
1214
#include <asm/smp.h>
1315

1416
extern char secondary_start_sbi[];
1517
const struct cpu_operations cpu_ops_sbi;
1618

19+
/*
20+
* Ordered booting via HSM brings one cpu at a time. However, cpu hotplug can
21+
* be invoked from multiple threads in parallel. Define a per cpu data
22+
* to handle that.
23+
*/
24+
DEFINE_PER_CPU(struct sbi_hart_boot_data, boot_data);
25+
1726
static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr,
1827
unsigned long priv)
1928
{
@@ -55,14 +64,19 @@ static int sbi_hsm_hart_get_status(unsigned long hartid)
5564

5665
static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle)
5766
{
58-
int rc;
5967
unsigned long boot_addr = __pa_symbol(secondary_start_sbi);
6068
int hartid = cpuid_to_hartid_map(cpuid);
61-
62-
cpu_update_secondary_bootdata(cpuid, tidle);
63-
rc = sbi_hsm_hart_start(hartid, boot_addr, 0);
64-
65-
return rc;
69+
unsigned long hsm_data;
70+
struct sbi_hart_boot_data *bdata = &per_cpu(boot_data, cpuid);
71+
72+
/* Make sure tidle is updated */
73+
smp_mb();
74+
bdata->task_ptr = tidle;
75+
bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE;
76+
/* Make sure boot data is updated */
77+
smp_mb();
78+
hsm_data = __pa(bdata);
79+
return sbi_hsm_hart_start(hartid, boot_addr, hsm_data);
6680
}
6781

6882
static int sbi_cpu_prepare(unsigned int cpuid)

arch/riscv/kernel/head.S

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <asm/page.h>
1212
#include <asm/pgtable.h>
1313
#include <asm/csr.h>
14+
#include <asm/cpu_ops_sbi.h>
1415
#include <asm/hwcap.h>
1516
#include <asm/image.h>
1617
#include "efi-header.S"
@@ -168,15 +169,15 @@ secondary_start_sbi:
168169
la a3, .Lsecondary_park
169170
csrw CSR_TVEC, a3
170171

171-
slli a3, a0, LGREG
172-
la a4, __cpu_up_stack_pointer
173-
XIP_FIXUP_OFFSET a4
174-
la a5, __cpu_up_task_pointer
175-
XIP_FIXUP_OFFSET a5
176-
add a4, a3, a4
177-
add a5, a3, a5
178-
REG_L sp, (a4)
179-
REG_L tp, (a5)
172+
/* a0 contains the hartid & a1 contains boot data */
173+
li a2, SBI_HART_BOOT_TASK_PTR_OFFSET
174+
XIP_FIXUP_OFFSET a2
175+
add a2, a2, a1
176+
REG_L tp, (a2)
177+
li a3, SBI_HART_BOOT_STACK_PTR_OFFSET
178+
XIP_FIXUP_OFFSET a3
179+
add a3, a3, a1
180+
REG_L sp, (a3)
180181

181182
.Lsecondary_start_common:
182183

0 commit comments

Comments
 (0)