aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAnup Patel <apatel@ventanamicro.com>2024-03-15 19:55:23 +0530
committerAnup Patel <anup@brainfault.org>2024-04-05 17:48:23 +0530
commitbeb0cd177f10a6bdafd73aac19059fecf6a07a91 (patch)
treeb54f4bd17bd293cb3e27c62ffdf3338571758937 /include
parentf5375bc15e9f3e577dfc24f9095a3e37246a3fa3 (diff)
downloadopensbi-beb0cd177f10a6bdafd73aac19059fecf6a07a91.zip
opensbi-beb0cd177f10a6bdafd73aac19059fecf6a07a91.tar.gz
opensbi-beb0cd177f10a6bdafd73aac19059fecf6a07a91.tar.bz2
lib: sbi: Simplify wait_for_coldboot() implementation
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>
Diffstat (limited to 'include')
-rw-r--r--include/sbi/riscv_barrier.h6
1 files changed, 5 insertions, 1 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 */