From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 5/9] riscv: add support for multi-hart systems
Date: Tue, 5 Mar 2019 23:53:27 +0100 [thread overview]
Message-ID: <20190305225331.1353-6-lukas.auer@aisec.fraunhofer.de> (raw)
In-Reply-To: <20190305225331.1353-1-lukas.auer@aisec.fraunhofer.de>
On RISC-V, all harts boot independently. To be able to run on a
multi-hart system, U-Boot must be extended with the functionality to
manage all harts in the system. All harts entering U-Boot are registered
in the available_harts mask stored in global data. A hart lottery system
as used in the Linux kernel selects the hart U-Boot runs on. All other
harts are halted. U-Boot can delegate functions to them using
smp_call_function().
Every hart has a valid pointer to the global data structure and a 8KiB
stack by default. The stack size is set with CONFIG_STACK_SIZE_SHIFT.
Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
---
Changes in v2:
- Implement hart lottery to pick main hart to run U-Boot
- Remove CONFIG_MAIN_HART as it is not required anymore
- Register available harts in the available_harts mask
arch/riscv/Kconfig | 4 ++
arch/riscv/cpu/cpu.c | 9 ++-
arch/riscv/cpu/start.S | 134 ++++++++++++++++++++++++++++++++++-
arch/riscv/include/asm/csr.h | 1 +
arch/riscv/lib/asm-offsets.c | 1 +
5 files changed, 147 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 9da609b33b..3a4470daf3 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -144,4 +144,8 @@ config SBI_IPI
default y if RISCV_SMODE
depends on SMP
+config STACK_SIZE_SHIFT
+ int
+ default 13
+
endmenu
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index e662140427..c32de8a4c3 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -12,10 +12,17 @@
#include <dm/uclass-internal.h>
/*
- * prior_stage_fdt_address must be stored in the data section since it is used
+ * The variables here must be stored in the data section since they are used
* before the bss section is available.
*/
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
+u32 hart_lottery __attribute__((section(".data"))) = 0;
+
+/*
+ * The main hart running U-Boot has acquired available_harts_lock until it has
+ * finished initialization of global data.
+ */
+u32 available_harts_lock = 1;
static inline bool supports_extension(char ext)
{
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index a30f6f7194..79b753847c 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -13,6 +13,7 @@
#include <config.h>
#include <common.h>
#include <elf.h>
+#include <asm/csr.h>
#include <asm/encoding.h>
#include <generated/asm-offsets.h>
@@ -45,6 +46,23 @@ _start:
/* mask all interrupts */
csrw MODE_PREFIX(ie), zero
+#ifdef CONFIG_SMP
+ /* check if hart is within range */
+ /* s0: hart id */
+ li t0, CONFIG_NR_CPUS
+ bge s0, t0, hart_out_of_bounds_loop
+#endif
+
+#ifdef CONFIG_SMP
+ /* set xSIE bit to receive IPIs */
+#ifdef CONFIG_RISCV_MMODE
+ li t0, MIE_MSIE
+#else
+ li t0, SIE_SSIE
+#endif
+ csrs MODE_PREFIX(ie), t0
+#endif
+
/*
* Set stackpointer in internal/ex RAM to call board_init_f
*/
@@ -56,7 +74,30 @@ call_board_init_f:
call_board_init_f_0:
mv a0, sp
jal board_init_f_alloc_reserve
+
+ /*
+ * Set global data pointer here for all harts, uninitialized at this
+ * point.
+ */
+ mv gp, a0
+
+ /* setup stack */
+#ifdef CONFIG_SMP
+ /* s0: hart id */
+ slli t0, s0, CONFIG_STACK_SIZE_SHIFT
+ sub sp, a0, t0
+#else
mv sp, a0
+#endif
+
+ /*
+ * Pick hart to initialize global data and run U-Boot. The other harts
+ * wait for initialization to complete.
+ */
+ la t0, hart_lottery
+ li s2, 1
+ amoswap.w s2, t1, 0(t0)
+ bnez s2, wait_for_gd_init
la t0, prior_stage_fdt_address
SREG s1, 0(t0)
@@ -66,6 +107,33 @@ call_board_init_f_0:
/* save the boot hart id to global_data */
SREG s0, GD_BOOT_HART(gp)
+ la t0, available_harts_lock
+ fence rw, w
+ amoswap.w zero, zero, 0(t0)
+
+wait_for_gd_init:
+ la t0, available_harts_lock
+ li t1, 1
+1: amoswap.w t1, t1, 0(t0)
+ fence r, rw
+ bnez t1, 1b
+
+ /* register available harts in the available_harts mask */
+ li t1, 1
+ sll t1, t1, s0
+ LREG t2, GD_AVAILABLE_HARTS(gp)
+ or t2, t2, t1
+ SREG t2, GD_AVAILABLE_HARTS(gp)
+
+ fence rw, w
+ amoswap.w zero, zero, 0(t0)
+
+ /*
+ * Continue on hart lottery winner, others branch to
+ * secondary_hart_loop.
+ */
+ bnez s2, secondary_hart_loop
+
/* Enable cache */
jal icache_enable
jal dcache_enable
@@ -95,7 +163,14 @@ relocate_code:
*Set up the stack
*/
stack_setup:
+#ifdef CONFIG_SMP
+ /* s0: hart id */
+ slli t0, s0, CONFIG_STACK_SIZE_SHIFT
+ sub sp, s2, t0
+#else
mv sp, s2
+#endif
+
la t0, _start
sub t6, s4, t0 /* t6 <- relocation offset */
beq t0, s4, clear_bss /* skip relocation */
@@ -175,13 +250,30 @@ clear_bss:
add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
- beq t0, t1, call_board_init_r
+ beq t0, t1, relocate_secondary_harts
clbss_l:
SREG zero, 0(t0) /* clear loop... */
addi t0, t0, REGBYTES
bne t0, t1, clbss_l
+relocate_secondary_harts:
+#ifdef CONFIG_SMP
+ /* send relocation IPI */
+ la t0, secondary_hart_relocate
+ add a0, t0, t6
+
+ /* store relocation offset */
+ mv s5, t6
+
+ mv a1, s2
+ mv a2, s3
+ jal smp_call_function
+
+ /* restore relocation offset */
+ mv t6, s5
+#endif
+
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
@@ -202,3 +294,43 @@ call_board_init_r:
* jump to it ...
*/
jr t4 /* jump to board_init_r() */
+
+#ifdef CONFIG_SMP
+hart_out_of_bounds_loop:
+ /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
+ wfi
+ j hart_out_of_bounds_loop
+#endif
+
+#ifdef CONFIG_SMP
+/* SMP relocation entry */
+secondary_hart_relocate:
+ /* a1: new sp */
+ /* a2: new gd */
+ /* s0: hart id */
+
+ /* setup stack */
+ slli t0, s0, CONFIG_STACK_SIZE_SHIFT
+ sub sp, a1, t0
+
+ /* update global data pointer */
+ mv gp, a2
+#endif
+
+secondary_hart_loop:
+ wfi
+
+#ifdef CONFIG_SMP
+ csrr t0, MODE_PREFIX(ip)
+#ifdef CONFIG_RISCV_MMODE
+ andi t0, t0, MIE_MSIE
+#else
+ andi t0, t0, SIE_SSIE
+#endif
+ beqz t0, secondary_hart_loop
+
+ mv a0, s0
+ jal handle_ipi
+#endif
+
+ j secondary_hart_loop
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 86136f542c..644e6baa15 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -46,6 +46,7 @@
#endif
/* Interrupt Enable and Interrupt Pending flags */
+#define MIE_MSIE _AC(0x00000008, UL) /* Software Interrupt Enable */
#define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */
#define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */
diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c
index e0b71f5691..f998402bd1 100644
--- a/arch/riscv/lib/asm-offsets.c
+++ b/arch/riscv/lib/asm-offsets.c
@@ -14,6 +14,7 @@
int main(void)
{
DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart));
+ DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts));
return 0;
}
--
2.20.1
next prev parent reply other threads:[~2019-03-05 22:53 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-05 22:53 [U-Boot] [PATCH v2 0/9] SMP support for RISC-V Lukas Auer
2019-03-05 22:53 ` [U-Boot] [PATCH v2 1/9] riscv: add infrastructure for calling functions on other harts Lukas Auer
2019-03-06 3:55 ` Anup Patel
2019-03-07 3:20 ` Atish Patra
2019-03-10 14:41 ` Auer, Lukas
2019-03-10 13:01 ` Bin Meng
2019-03-05 22:53 ` [U-Boot] [PATCH v2 2/9] riscv: import the supervisor binary interface header file Lukas Auer
2019-03-07 3:21 ` Atish Patra
2019-03-05 22:53 ` [U-Boot] [PATCH v2 3/9] riscv: implement IPI platform functions using SBI Lukas Auer
2019-03-07 3:23 ` Atish Patra
2019-03-10 13:01 ` Bin Meng
2019-03-05 22:53 ` [U-Boot] [PATCH v2 4/9] riscv: delay initialization of caches and debug UART Lukas Auer
2019-03-05 22:53 ` Lukas Auer [this message]
2019-03-06 3:56 ` [U-Boot] [PATCH v2 5/9] riscv: add support for multi-hart systems Anup Patel
2019-03-10 13:01 ` Bin Meng
2019-03-10 13:46 ` Auer, Lukas
2019-03-05 22:53 ` [U-Boot] [PATCH v2 6/9] riscv: boot images passed to bootm on all harts Lukas Auer
2019-03-10 13:01 ` Bin Meng
2019-03-05 22:53 ` [U-Boot] [PATCH v2 7/9] riscv: do not rely on hart ID passed by previous boot stage Lukas Auer
2019-03-06 3:56 ` Anup Patel
2019-03-07 3:26 ` Atish Patra
2019-03-10 13:01 ` Bin Meng
[not found] ` <752D002CFF5D0F4FA35C0100F1D73F3FA40983DC@ATCPCS16.andestech.com>
2019-03-13 2:10 ` Rick Chen
2019-03-05 22:53 ` [U-Boot] [PATCH v2 8/9] riscv: fu540: enable SMP Lukas Auer
2019-03-10 13:01 ` Bin Meng
2019-03-05 22:53 ` [U-Boot] [PATCH v2 9/9] riscv: qemu: " Lukas Auer
2019-03-10 13:01 ` Bin Meng
2019-03-06 4:00 ` [U-Boot] [PATCH v2 0/9] SMP support for RISC-V Anup Patel
2019-03-06 9:22 ` Auer, Lukas
2019-03-06 10:07 ` Anup Patel
2019-03-06 10:56 ` Andreas Schwab
2019-03-06 11:24 ` Anup Patel
2019-03-06 11:47 ` Andreas Schwab
2019-03-06 11:49 ` Anup Patel
2019-03-06 12:01 ` Andreas Schwab
2019-03-06 12:15 ` Auer, Lukas
2019-03-06 12:32 ` Anup Patel
2019-03-06 23:50 ` Atish Patra
2019-03-07 4:47 ` Anup Patel
2019-03-07 9:20 ` Andreas Schwab
2019-03-08 3:37 ` Anup Patel
2019-03-11 9:17 ` Andreas Schwab
2019-03-11 11:56 ` Palmer Dabbelt
2019-03-11 16:10 ` Anup Patel
2019-03-06 12:17 ` Auer, Lukas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190305225331.1353-6-lukas.auer@aisec.fraunhofer.de \
--to=lukas.auer@aisec.fraunhofer.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.