* [PATCH 0/2] Coldboot wait improvements
@ 2024-03-19 14:59 Anup Patel
2024-03-19 14:59 ` [PATCH 1/2] lib: sbi: Simplify wait_for_coldboot() implementation Anup Patel
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Anup Patel @ 2024-03-19 14:59 UTC (permalink / raw)
To: opensbi
These are some of the simplifications/improvements which were found
upon trying QEMU virt machine with large number of HARTs.
These patches can also be found in the coldboot_wait_simplify_v1
branch at https://github.com/avpatel/opensbi.git
Anup Patel (2):
lib: sbi: Simplify wait_for_coldboot() implementation
lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path
include/sbi/riscv_barrier.h | 6 ++-
lib/sbi/sbi_init.c | 81 ++++++-------------------------------
2 files changed, 17 insertions(+), 70 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] lib: sbi: Simplify wait_for_coldboot() implementation
2024-03-19 14:59 [PATCH 0/2] Coldboot wait improvements Anup Patel
@ 2024-03-19 14:59 ` Anup Patel
2024-03-19 14:59 ` [PATCH 2/2] lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path Anup Patel
2024-04-05 12:26 ` [PATCH 0/2] Coldboot wait improvements Anup Patel
2 siblings, 0 replies; 4+ messages in thread
From: Anup Patel @ 2024-03-19 14:59 UTC (permalink / raw)
To: opensbi
On QEMU virt machine with large number of HARTs, some of the HARTs
randomly fail to come out of wait_for_coldboot() due to one of the
following race-conditions:
1) Failing HARTs are not able to acquire the coldboot_lock and
update the coldboot_hartmask in wait_for_coldboot() before
the coldboot HART acquires the coldboot_lock and sends IPI
in wake_coldboot_harts() hence the failing HARTs never
receive IPI from the coldboot HART.
2) Failing HARTs acquire the coldbood_lock and update the
coldboot_hartmask before coldboot HART does sbi_scratch_init()
so the sbi_hartmask_set_hartid() does not update the
coldboot_hartmask on the failing HARTs hence they never
receive IPI from the coldboot HART.
To address this, use a simple busy-loop in wait_for_coldboot() for
polling on coldboot_done flag.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi/riscv_barrier.h | 6 +++-
lib/sbi/sbi_init.c | 70 ++-----------------------------------
2 files changed, 8 insertions(+), 68 deletions(-)
diff --git a/include/sbi/riscv_barrier.h b/include/sbi/riscv_barrier.h
index 1fba8b8..3d4a038 100644
--- a/include/sbi/riscv_barrier.h
+++ b/include/sbi/riscv_barrier.h
@@ -40,7 +40,11 @@
#define smp_wmb() RISCV_FENCE(w,w)
/* CPU relax for busy loop */
-#define cpu_relax() asm volatile ("" : : : "memory")
+#define cpu_relax() \
+do { \
+ unsigned long __t; \
+ __asm__ __volatile__ ("div %0, %0, zero" : "=r" (__t)); \
+} while (0)
/* clang-format on */
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 796cccc..b3f3e38 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -10,7 +10,6 @@
#include <sbi/riscv_asm.h>
#include <sbi/riscv_atomic.h>
#include <sbi/riscv_barrier.h>
-#include <sbi/riscv_locks.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_cppc.h>
#include <sbi/sbi_domain.h>
@@ -190,82 +189,19 @@ static void sbi_boot_print_hart(struct sbi_scratch *scratch, u32 hartid)
sbi_hart_delegation_dump(scratch, "Boot HART ", " ");
}
-static spinlock_t coldboot_lock = SPIN_LOCK_INITIALIZER;
-static struct sbi_hartmask coldboot_wait_hmask = { 0 };
-
static unsigned long coldboot_done;
static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
{
- unsigned long saved_mie, cmip;
-
- if (__smp_load_acquire(&coldboot_done))
- return;
-
- /* Save MIE CSR */
- saved_mie = csr_read(CSR_MIE);
-
- /* Set MSIE and MEIE bits to receive IPI */
- csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
-
- /* Acquire coldboot lock */
- spin_lock(&coldboot_lock);
-
- /* Mark current HART as waiting */
- sbi_hartmask_set_hartid(hartid, &coldboot_wait_hmask);
-
- /* Release coldboot lock */
- spin_unlock(&coldboot_lock);
-
- /* Wait for coldboot to finish using WFI */
- while (!__smp_load_acquire(&coldboot_done)) {
- do {
- wfi();
- cmip = csr_read(CSR_MIP);
- } while (!(cmip & (MIP_MSIP | MIP_MEIP)));
- }
-
- /* Acquire coldboot lock */
- spin_lock(&coldboot_lock);
-
- /* Unmark current HART as waiting */
- sbi_hartmask_clear_hartid(hartid, &coldboot_wait_hmask);
-
- /* Release coldboot lock */
- spin_unlock(&coldboot_lock);
-
- /* Restore MIE CSR */
- csr_write(CSR_MIE, saved_mie);
-
- /*
- * The wait for coldboot is common for both warm startup and
- * warm resume path so clearing IPI here would result in losing
- * an IPI in warm resume path.
- *
- * Also, the sbi_platform_ipi_init() called from sbi_ipi_init()
- * will automatically clear IPI for current HART.
- */
+ /* Wait for coldboot to finish */
+ while (!__smp_load_acquire(&coldboot_done))
+ cpu_relax();
}
static void wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid)
{
- u32 i, hartindex = sbi_hartid_to_hartindex(hartid);
-
/* Mark coldboot done */
__smp_store_release(&coldboot_done, 1);
-
- /* Acquire coldboot lock */
- spin_lock(&coldboot_lock);
-
- /* Send an IPI to all HARTs waiting for coldboot */
- sbi_hartmask_for_each_hartindex(i, &coldboot_wait_hmask) {
- if (i == hartindex)
- continue;
- sbi_ipi_raw_send(i);
- }
-
- /* Release coldboot lock */
- spin_unlock(&coldboot_lock);
}
static unsigned long entry_count_offset;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path
2024-03-19 14:59 [PATCH 0/2] Coldboot wait improvements Anup Patel
2024-03-19 14:59 ` [PATCH 1/2] lib: sbi: Simplify wait_for_coldboot() implementation Anup Patel
@ 2024-03-19 14:59 ` Anup Patel
2024-04-05 12:26 ` [PATCH 0/2] Coldboot wait improvements Anup Patel
2 siblings, 0 replies; 4+ messages in thread
From: Anup Patel @ 2024-03-19 14:59 UTC (permalink / raw)
To: opensbi
Currently, all non-coldboot HARTs busy spin in wait_for_coldboot()
until the entire coldboot init sequence is completed.
This means:
1) On QEMU, all non-coldboot HARTs will eat host CPU time and
also slow down the coldboot HART until the entire coldboot
init sequence is completed.
2) On real HW, all non-coldboot HARTs will consume more CPU
power until the entire coldboot init sequence is completed.
To address this, wake up all non-coldboot HARTs as early as
possible in the coldboot init sequence.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
lib/sbi/sbi_init.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index b3f3e38..8fdc8de 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -243,6 +243,14 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
if (rc)
sbi_hart_hang();
+ /*
+ * All non-coldboot HARTs do HSM initialization (i.e. enter HSM state
+ * machine) at the start of the warmboot path so it is wasteful to
+ * have these HARTs busy spin in wait_for_coldboot() until coldboot
+ * path is completed.
+ */
+ wake_coldboot_harts(scratch, hartid);
+
rc = sbi_platform_early_init(plat, true);
if (rc)
sbi_hart_hang();
@@ -348,8 +356,6 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
sbi_hart_hang();
}
- wake_coldboot_harts(scratch, hartid);
-
count = sbi_scratch_offset_ptr(scratch, init_count_offset);
(*count)++;
@@ -369,6 +375,7 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
count = sbi_scratch_offset_ptr(scratch, entry_count_offset);
(*count)++;
+ /* Note: This has to be first thing in warmboot init sequence */
rc = sbi_hsm_init(scratch, hartid, false);
if (rc)
sbi_hart_hang();
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 0/2] Coldboot wait improvements
2024-03-19 14:59 [PATCH 0/2] Coldboot wait improvements Anup Patel
2024-03-19 14:59 ` [PATCH 1/2] lib: sbi: Simplify wait_for_coldboot() implementation Anup Patel
2024-03-19 14:59 ` [PATCH 2/2] lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path Anup Patel
@ 2024-04-05 12:26 ` Anup Patel
2 siblings, 0 replies; 4+ messages in thread
From: Anup Patel @ 2024-04-05 12:26 UTC (permalink / raw)
To: opensbi
On Tue, Mar 19, 2024 at 8:29?PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> These are some of the simplifications/improvements which were found
> upon trying QEMU virt machine with large number of HARTs.
>
> These patches can also be found in the coldboot_wait_simplify_v1
> branch at https://github.com/avpatel/opensbi.git
>
> Anup Patel (2):
> lib: sbi: Simplify wait_for_coldboot() implementation
> lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path
Applied this series to the riscv/opensbi repo.
Regards,
Anup
>
> include/sbi/riscv_barrier.h | 6 ++-
> lib/sbi/sbi_init.c | 81 ++++++-------------------------------
> 2 files changed, 17 insertions(+), 70 deletions(-)
>
> --
> 2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-04-05 12:26 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-19 14:59 [PATCH 0/2] Coldboot wait improvements Anup Patel
2024-03-19 14:59 ` [PATCH 1/2] lib: sbi: Simplify wait_for_coldboot() implementation Anup Patel
2024-03-19 14:59 ` [PATCH 2/2] lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path Anup Patel
2024-04-05 12:26 ` [PATCH 0/2] Coldboot wait improvements Anup Patel
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.