Unverified Commit 9a2451f1 authored by Atish Patra's avatar Atish Patra Committed by Palmer Dabbelt
Browse files

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: default avatarAnup Patel <anup@brainfault.org>
Signed-off-by: default avatarAtish Patra <atishp@rivosinc.com>
Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 3938d5a2
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
/* 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 */
+3 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <asm/kvm_host.h>
#include <asm/thread_info.h>
#include <asm/ptrace.h>
#include <asm/cpu_ops_sbi.h>

void asm_offsets(void);

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

	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);
}
+20 −6
Original line number Diff line number Diff line
@@ -7,13 +7,22 @@

#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched/task_stack.h>
#include <asm/cpu_ops.h>
#include <asm/cpu_ops_sbi.h>
#include <asm/sbi.h>
#include <asm/smp.h>

extern char secondary_start_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,
			      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)
{
	int rc;
	unsigned long boot_addr = __pa_symbol(secondary_start_sbi);
	int hartid = cpuid_to_hartid_map(cpuid);

	cpu_update_secondary_bootdata(cpuid, tidle);
	rc = sbi_hsm_hart_start(hartid, boot_addr, 0);

	return rc;
	unsigned long hsm_data;
	struct sbi_hart_boot_data *bdata = &per_cpu(boot_data, cpuid);

	/* Make sure tidle is updated */
	smp_mb();
	bdata->task_ptr = tidle;
	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)
+10 −9
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/csr.h>
#include <asm/cpu_ops_sbi.h>
#include <asm/hwcap.h>
#include <asm/image.h>
#include "efi-header.S"
@@ -168,15 +169,15 @@ secondary_start_sbi:
	la a3, .Lsecondary_park
	csrw CSR_TVEC, a3

	slli a3, a0, LGREG
	la a4, __cpu_up_stack_pointer
	XIP_FIXUP_OFFSET a4
	la a5, __cpu_up_task_pointer
	XIP_FIXUP_OFFSET a5
	add a4, a3, a4
	add a5, a3, a5
	REG_L sp, (a4)
	REG_L tp, (a5)
	/* a0 contains the hartid & a1 contains boot data */
	li a2, SBI_HART_BOOT_TASK_PTR_OFFSET
	XIP_FIXUP_OFFSET a2
	add a2, a2, a1
	REG_L tp, (a2)
	li a3, SBI_HART_BOOT_STACK_PTR_OFFSET
	XIP_FIXUP_OFFSET a3
	add a3, a3, a1
	REG_L sp, (a3)

.Lsecondary_start_common: