* [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop
@ 2025-05-27 12:48 Anup Patel
2025-05-28 10:26 ` Nick Hu
2025-06-16 4:18 ` Anup Patel
0 siblings, 2 replies; 6+ messages in thread
From: Anup Patel @ 2025-05-27 12:48 UTC (permalink / raw)
To: Atish Patra; +Cc: Andrew Jones, Anup Patel, Nick Hu, opensbi, Anup Patel
Using hsm stop in hsm wait loop causes secondary harts to be stuck
forever in OpenSBI on RISC-V platforms where HSM hart hotplug is
available and all harts come-up at the same time during system
power-on.
For example, lets say we have two harts A and B on a RISC-V platform
with HSM hart hotplug which come-up at the same time during system
power-on. The hart A enters OpenSBI before hart B hence it becomes
the primary (or cold-boot) hart whereas hart B becomes the secondary
(or warm-boot) hart. The hart A follows the OpenSBI cold-boot path
and registers hsm device before hart B enters OpenSBI. The hart B
eventually enters OpenSBI and follows the OpenSBI warm-boot path
so it will increment it's own entry_count before entering hsm wait
loop where it sees hsm device and stops itself. Later as part of
the Linux boot-up sequence, hart A issues SBI HSM start call to
bring-up hart B but OpenSBI sees entry_count != init_count for
hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is
not called for hart B resulting in hart B stuck forever in OpenSBI.
To fix the above issue, revert entry_count before doing hsm stop
in hsm wait loop.
Fixes: d844deadec94 ("lib: sbi: Use hsm stop for hsm wait")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi/sbi_init.h | 2 ++
lib/sbi/sbi_hsm.c | 4 +++-
lib/sbi/sbi_init.c | 13 +++++++++++++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h
index c9013ea4..ad068674 100644
--- a/include/sbi/sbi_init.h
+++ b/include/sbi/sbi_init.h
@@ -16,6 +16,8 @@ struct sbi_scratch;
void __noreturn sbi_init(struct sbi_scratch *scratch);
+void sbi_revert_entry_count(struct sbi_scratch *scratch);
+
unsigned long sbi_entry_count(u32 hartindex);
unsigned long sbi_init_count(u32 hartindex);
diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index e8128a39..557ab131 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch)
* If the hsm_dev is ready and it support the hotplug, we can
* use the hsm stop for more power saving
*/
- if (hsm_device_has_hart_hotplug())
+ if (hsm_device_has_hart_hotplug()) {
+ sbi_revert_entry_count(scratch);
hsm_device_hart_stop();
+ }
wfi();
}
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 62c32682..84a63748 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
init_warmboot(scratch, hartid);
}
+void sbi_revert_entry_count(struct sbi_scratch *scratch)
+{
+ unsigned long *entry_count, *init_count;
+
+ if (!entry_count_offset || !init_count_offset)
+ sbi_hart_hang();
+
+ entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset);
+ init_count = sbi_scratch_offset_ptr(scratch, init_count_offset);
+
+ *entry_count = *init_count;
+}
+
unsigned long sbi_entry_count(u32 hartindex)
{
struct sbi_scratch *scratch;
--
2.43.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop 2025-05-27 12:48 [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop Anup Patel @ 2025-05-28 10:26 ` Nick Hu 2025-05-28 12:14 ` Anup Patel 2025-06-16 4:18 ` Anup Patel 1 sibling, 1 reply; 6+ messages in thread From: Nick Hu @ 2025-05-28 10:26 UTC (permalink / raw) To: Anup Patel; +Cc: Atish Patra, Andrew Jones, Anup Patel, opensbi On Tue, May 27, 2025 at 8:48 PM Anup Patel <apatel@ventanamicro.com> wrote: > > Using hsm stop in hsm wait loop causes secondary harts to be stuck > forever in OpenSBI on RISC-V platforms where HSM hart hotplug is > available and all harts come-up at the same time during system > power-on. > > For example, lets say we have two harts A and B on a RISC-V platform > with HSM hart hotplug which come-up at the same time during system > power-on. The hart A enters OpenSBI before hart B hence it becomes > the primary (or cold-boot) hart whereas hart B becomes the secondary > (or warm-boot) hart. The hart A follows the OpenSBI cold-boot path > and registers hsm device before hart B enters OpenSBI. The hart B > eventually enters OpenSBI and follows the OpenSBI warm-boot path > so it will increment it's own entry_count before entering hsm wait > loop where it sees hsm device and stops itself. Later as part of > the Linux boot-up sequence, hart A issues SBI HSM start call to > bring-up hart B but OpenSBI sees entry_count != init_count for > hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is > not called for hart B resulting in hart B stuck forever in OpenSBI. > > To fix the above issue, revert entry_count before doing hsm stop > in hsm wait loop. > > Fixes: d844deadec94 ("lib: sbi: Use hsm stop for hsm wait") > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > --- > include/sbi/sbi_init.h | 2 ++ > lib/sbi/sbi_hsm.c | 4 +++- > lib/sbi/sbi_init.c | 13 +++++++++++++ > 3 files changed, 18 insertions(+), 1 deletion(-) > > diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h > index c9013ea4..ad068674 100644 > --- a/include/sbi/sbi_init.h > +++ b/include/sbi/sbi_init.h > @@ -16,6 +16,8 @@ struct sbi_scratch; > > void __noreturn sbi_init(struct sbi_scratch *scratch); > > +void sbi_revert_entry_count(struct sbi_scratch *scratch); > + > unsigned long sbi_entry_count(u32 hartindex); > > unsigned long sbi_init_count(u32 hartindex); > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c > index e8128a39..557ab131 100644 > --- a/lib/sbi/sbi_hsm.c > +++ b/lib/sbi/sbi_hsm.c > @@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch) > * If the hsm_dev is ready and it support the hotplug, we can > * use the hsm stop for more power saving > */ > - if (hsm_device_has_hart_hotplug()) > + if (hsm_device_has_hart_hotplug()) { > + sbi_revert_entry_count(scratch); > hsm_device_hart_stop(); Hi Anup, Thanks for addressing the bug =) However, there may still be an issue in the following scenario: If the HSM state of core B is SBI_HSM_STATE_START_PENDING at this point, it won't enter the warm boot path. As a result, the `init_count` will end up being `entry_count` + 1 after the warm init path. Would it make sense to increment `entry_count` after the `sbi_hsm_init()` call instead? > + } > > wfi(); > } > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c > index 62c32682..84a63748 100644 > --- a/lib/sbi/sbi_init.c > +++ b/lib/sbi/sbi_init.c > @@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch) > init_warmboot(scratch, hartid); > } > > +void sbi_revert_entry_count(struct sbi_scratch *scratch) > +{ > + unsigned long *entry_count, *init_count; > + > + if (!entry_count_offset || !init_count_offset) > + sbi_hart_hang(); > + > + entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset); > + init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); > + > + *entry_count = *init_count; > +} > + > unsigned long sbi_entry_count(u32 hartindex) > { > struct sbi_scratch *scratch; > -- > 2.43.0 > Best Regards, Nick -- opensbi mailing list opensbi@lists.infradead.org http://lists.infradead.org/mailman/listinfo/opensbi ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop 2025-05-28 10:26 ` Nick Hu @ 2025-05-28 12:14 ` Anup Patel 2025-05-28 14:34 ` Nick Hu 0 siblings, 1 reply; 6+ messages in thread From: Anup Patel @ 2025-05-28 12:14 UTC (permalink / raw) To: Nick Hu; +Cc: Atish Patra, Andrew Jones, Anup Patel, opensbi On Wed, May 28, 2025 at 3:56 PM Nick Hu <nick.hu@sifive.com> wrote: > > On Tue, May 27, 2025 at 8:48 PM Anup Patel <apatel@ventanamicro.com> wrote: > > > > Using hsm stop in hsm wait loop causes secondary harts to be stuck > > forever in OpenSBI on RISC-V platforms where HSM hart hotplug is > > available and all harts come-up at the same time during system > > power-on. > > > > For example, lets say we have two harts A and B on a RISC-V platform > > with HSM hart hotplug which come-up at the same time during system > > power-on. The hart A enters OpenSBI before hart B hence it becomes > > the primary (or cold-boot) hart whereas hart B becomes the secondary > > (or warm-boot) hart. The hart A follows the OpenSBI cold-boot path > > and registers hsm device before hart B enters OpenSBI. The hart B > > eventually enters OpenSBI and follows the OpenSBI warm-boot path > > so it will increment it's own entry_count before entering hsm wait > > loop where it sees hsm device and stops itself. Later as part of > > the Linux boot-up sequence, hart A issues SBI HSM start call to > > bring-up hart B but OpenSBI sees entry_count != init_count for > > hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is > > not called for hart B resulting in hart B stuck forever in OpenSBI. > > > > To fix the above issue, revert entry_count before doing hsm stop > > in hsm wait loop. > > > > Fixes: d844deadec94 ("lib: sbi: Use hsm stop for hsm wait") > > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > > --- > > include/sbi/sbi_init.h | 2 ++ > > lib/sbi/sbi_hsm.c | 4 +++- > > lib/sbi/sbi_init.c | 13 +++++++++++++ > > 3 files changed, 18 insertions(+), 1 deletion(-) > > > > diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h > > index c9013ea4..ad068674 100644 > > --- a/include/sbi/sbi_init.h > > +++ b/include/sbi/sbi_init.h > > @@ -16,6 +16,8 @@ struct sbi_scratch; > > > > void __noreturn sbi_init(struct sbi_scratch *scratch); > > > > +void sbi_revert_entry_count(struct sbi_scratch *scratch); > > + > > unsigned long sbi_entry_count(u32 hartindex); > > > > unsigned long sbi_init_count(u32 hartindex); > > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c > > index e8128a39..557ab131 100644 > > --- a/lib/sbi/sbi_hsm.c > > +++ b/lib/sbi/sbi_hsm.c > > @@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch) > > * If the hsm_dev is ready and it support the hotplug, we can > > * use the hsm stop for more power saving > > */ > > - if (hsm_device_has_hart_hotplug()) > > + if (hsm_device_has_hart_hotplug()) { > > + sbi_revert_entry_count(scratch); > > hsm_device_hart_stop(); > > Hi Anup, > Thanks for addressing the bug =) > > However, there may still be an issue in the following scenario: > If the HSM state of core B is SBI_HSM_STATE_START_PENDING at this > point, it won't enter the warm boot path. As a result, the > `init_count` will end up being `entry_count` + 1 after the warm init > path. > > Would it make sense to increment `entry_count` after the > `sbi_hsm_init()` call instead? This is not a bug rather expected behaviour. When the hart B is in SBI_HSM_STATE_START_PENDING state then it means some other hart A has issued HSM hart start and has also provided entry details. The hart B increments entry_count upon entry into OpenSBI and increments init_count after initialization is done. Regards, Anup > > > + } > > > > wfi(); > > } > > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c > > index 62c32682..84a63748 100644 > > --- a/lib/sbi/sbi_init.c > > +++ b/lib/sbi/sbi_init.c > > @@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch) > > init_warmboot(scratch, hartid); > > } > > > > +void sbi_revert_entry_count(struct sbi_scratch *scratch) > > +{ > > + unsigned long *entry_count, *init_count; > > + > > + if (!entry_count_offset || !init_count_offset) > > + sbi_hart_hang(); > > + > > + entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset); > > + init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); > > + > > + *entry_count = *init_count; > > +} > > + > > unsigned long sbi_entry_count(u32 hartindex) > > { > > struct sbi_scratch *scratch; > > -- > > 2.43.0 > > > > Best Regards, > Nick -- opensbi mailing list opensbi@lists.infradead.org http://lists.infradead.org/mailman/listinfo/opensbi ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop 2025-05-28 12:14 ` Anup Patel @ 2025-05-28 14:34 ` Nick Hu 2025-05-30 7:05 ` Nick Hu 0 siblings, 1 reply; 6+ messages in thread From: Nick Hu @ 2025-05-28 14:34 UTC (permalink / raw) To: Anup Patel; +Cc: Atish Patra, Andrew Jones, Anup Patel, opensbi On Wed, May 28, 2025 at 8:14 PM Anup Patel <apatel@ventanamicro.com> wrote: > > On Wed, May 28, 2025 at 3:56 PM Nick Hu <nick.hu@sifive.com> wrote: > > > > On Tue, May 27, 2025 at 8:48 PM Anup Patel <apatel@ventanamicro.com> wrote: > > > > > > Using hsm stop in hsm wait loop causes secondary harts to be stuck > > > forever in OpenSBI on RISC-V platforms where HSM hart hotplug is > > > available and all harts come-up at the same time during system > > > power-on. > > > > > > For example, lets say we have two harts A and B on a RISC-V platform > > > with HSM hart hotplug which come-up at the same time during system > > > power-on. The hart A enters OpenSBI before hart B hence it becomes > > > the primary (or cold-boot) hart whereas hart B becomes the secondary > > > (or warm-boot) hart. The hart A follows the OpenSBI cold-boot path > > > and registers hsm device before hart B enters OpenSBI. The hart B > > > eventually enters OpenSBI and follows the OpenSBI warm-boot path > > > so it will increment it's own entry_count before entering hsm wait > > > loop where it sees hsm device and stops itself. Later as part of > > > the Linux boot-up sequence, hart A issues SBI HSM start call to > > > bring-up hart B but OpenSBI sees entry_count != init_count for > > > hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is > > > not called for hart B resulting in hart B stuck forever in OpenSBI. > > > > > > To fix the above issue, revert entry_count before doing hsm stop > > > in hsm wait loop. > > > > > > Fixes: d844deadec94 ("lib: sbi: Use hsm stop for hsm wait") > > > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > > > --- > > > include/sbi/sbi_init.h | 2 ++ > > > lib/sbi/sbi_hsm.c | 4 +++- > > > lib/sbi/sbi_init.c | 13 +++++++++++++ > > > 3 files changed, 18 insertions(+), 1 deletion(-) > > > > > > diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h > > > index c9013ea4..ad068674 100644 > > > --- a/include/sbi/sbi_init.h > > > +++ b/include/sbi/sbi_init.h > > > @@ -16,6 +16,8 @@ struct sbi_scratch; > > > > > > void __noreturn sbi_init(struct sbi_scratch *scratch); > > > > > > +void sbi_revert_entry_count(struct sbi_scratch *scratch); > > > + > > > unsigned long sbi_entry_count(u32 hartindex); > > > > > > unsigned long sbi_init_count(u32 hartindex); > > > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c > > > index e8128a39..557ab131 100644 > > > --- a/lib/sbi/sbi_hsm.c > > > +++ b/lib/sbi/sbi_hsm.c > > > @@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch) > > > * If the hsm_dev is ready and it support the hotplug, we can > > > * use the hsm stop for more power saving > > > */ > > > - if (hsm_device_has_hart_hotplug()) > > > + if (hsm_device_has_hart_hotplug()) { > > > + sbi_revert_entry_count(scratch); > > > hsm_device_hart_stop(); > > > > Hi Anup, > > Thanks for addressing the bug =) > > > > However, there may still be an issue in the following scenario: > > If the HSM state of core B is SBI_HSM_STATE_START_PENDING at this > > point, it won't enter the warm boot path. As a result, the > > `init_count` will end up being `entry_count` + 1 after the warm init > > path. > > > > Would it make sense to increment `entry_count` after the > > `sbi_hsm_init()` call instead? > > This is not a bug rather expected behaviour. > > When the hart B is in SBI_HSM_STATE_START_PENDING state > then it means some other hart A has issued HSM hart start and > has also provided entry details. The hart B increments entry_count > upon entry into OpenSBI and increments init_count after initialization > is done. > I'm not sure if I understand it correctly. In the above case, the `init_count` != `entry_count` for hart B after the initialization is done. If the hart B enters the `hsm_dev->hart_stop()` via the SBI_EXT_HSM_HART_STOP path, Doesn't that mean the hart A won’t be able to call `hsm_dev->hart_start()` for the hart B? The `hsm_dev->hart_stop()` function may transition the hart into a platform-specific low-power state that requires `hsm_dev->hart_start()` to wake it up. Best Regards, Nick > Regards, > Anup > > > > > > + } > > > > > > wfi(); > > > } > > > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c > > > index 62c32682..84a63748 100644 > > > --- a/lib/sbi/sbi_init.c > > > +++ b/lib/sbi/sbi_init.c > > > @@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch) > > > init_warmboot(scratch, hartid); > > > } > > > > > > +void sbi_revert_entry_count(struct sbi_scratch *scratch) > > > +{ > > > + unsigned long *entry_count, *init_count; > > > + > > > + if (!entry_count_offset || !init_count_offset) > > > + sbi_hart_hang(); > > > + > > > + entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset); > > > + init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); > > > + > > > + *entry_count = *init_count; > > > +} > > > + > > > unsigned long sbi_entry_count(u32 hartindex) > > > { > > > struct sbi_scratch *scratch; > > > -- > > > 2.43.0 > > > > > > > Best Regards, > > Nick -- opensbi mailing list opensbi@lists.infradead.org http://lists.infradead.org/mailman/listinfo/opensbi ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop 2025-05-28 14:34 ` Nick Hu @ 2025-05-30 7:05 ` Nick Hu 0 siblings, 0 replies; 6+ messages in thread From: Nick Hu @ 2025-05-30 7:05 UTC (permalink / raw) To: Anup Patel; +Cc: Atish Patra, Andrew Jones, Anup Patel, opensbi On Wed, May 28, 2025 at 10:34 PM Nick Hu <nick.hu@sifive.com> wrote: > > On Wed, May 28, 2025 at 8:14 PM Anup Patel <apatel@ventanamicro.com> wrote: > > > > On Wed, May 28, 2025 at 3:56 PM Nick Hu <nick.hu@sifive.com> wrote: > > > > > > On Tue, May 27, 2025 at 8:48 PM Anup Patel <apatel@ventanamicro.com> wrote: > > > > > > > > Using hsm stop in hsm wait loop causes secondary harts to be stuck > > > > forever in OpenSBI on RISC-V platforms where HSM hart hotplug is > > > > available and all harts come-up at the same time during system > > > > power-on. > > > > > > > > For example, lets say we have two harts A and B on a RISC-V platform > > > > with HSM hart hotplug which come-up at the same time during system > > > > power-on. The hart A enters OpenSBI before hart B hence it becomes > > > > the primary (or cold-boot) hart whereas hart B becomes the secondary > > > > (or warm-boot) hart. The hart A follows the OpenSBI cold-boot path > > > > and registers hsm device before hart B enters OpenSBI. The hart B > > > > eventually enters OpenSBI and follows the OpenSBI warm-boot path > > > > so it will increment it's own entry_count before entering hsm wait > > > > loop where it sees hsm device and stops itself. Later as part of > > > > the Linux boot-up sequence, hart A issues SBI HSM start call to > > > > bring-up hart B but OpenSBI sees entry_count != init_count for > > > > hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is > > > > not called for hart B resulting in hart B stuck forever in OpenSBI. > > > > > > > > To fix the above issue, revert entry_count before doing hsm stop > > > > in hsm wait loop. > > > > > > > > Fixes: d844deadec94 ("lib: sbi: Use hsm stop for hsm wait") > > > > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > > > > --- > > > > include/sbi/sbi_init.h | 2 ++ > > > > lib/sbi/sbi_hsm.c | 4 +++- > > > > lib/sbi/sbi_init.c | 13 +++++++++++++ > > > > 3 files changed, 18 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h > > > > index c9013ea4..ad068674 100644 > > > > --- a/include/sbi/sbi_init.h > > > > +++ b/include/sbi/sbi_init.h > > > > @@ -16,6 +16,8 @@ struct sbi_scratch; > > > > > > > > void __noreturn sbi_init(struct sbi_scratch *scratch); > > > > > > > > +void sbi_revert_entry_count(struct sbi_scratch *scratch); > > > > + > > > > unsigned long sbi_entry_count(u32 hartindex); > > > > > > > > unsigned long sbi_init_count(u32 hartindex); > > > > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c > > > > index e8128a39..557ab131 100644 > > > > --- a/lib/sbi/sbi_hsm.c > > > > +++ b/lib/sbi/sbi_hsm.c > > > > @@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch) > > > > * If the hsm_dev is ready and it support the hotplug, we can > > > > * use the hsm stop for more power saving > > > > */ > > > > - if (hsm_device_has_hart_hotplug()) > > > > + if (hsm_device_has_hart_hotplug()) { > > > > + sbi_revert_entry_count(scratch); > > > > hsm_device_hart_stop(); > > > > > > Hi Anup, > > > Thanks for addressing the bug =) > > > > > > However, there may still be an issue in the following scenario: > > > If the HSM state of core B is SBI_HSM_STATE_START_PENDING at this > > > point, it won't enter the warm boot path. As a result, the > > > `init_count` will end up being `entry_count` + 1 after the warm init > > > path. > > > > > > Would it make sense to increment `entry_count` after the > > > `sbi_hsm_init()` call instead? > > > > This is not a bug rather expected behaviour. > > > > When the hart B is in SBI_HSM_STATE_START_PENDING state > > then it means some other hart A has issued HSM hart start and > > has also provided entry details. The hart B increments entry_count > > upon entry into OpenSBI and increments init_count after initialization > > is done. > > > I'm not sure if I understand it correctly. > In the above case, the `init_count` != `entry_count` for hart B after > the initialization is done. > If the hart B enters the `hsm_dev->hart_stop()` via the > SBI_EXT_HSM_HART_STOP path, Doesn't that mean the hart A won’t be able > to call `hsm_dev->hart_start()` for the hart B? > The `hsm_dev->hart_stop()` function may transition the hart into a > platform-specific low-power state that requires > `hsm_dev->hart_start()` to wake it up. > Oh, I see. I had mistaken `hsm_device_hart_stop()` for `sbi_hsm_hart_stop()`. Since hsm_device_hart_stop() doesn't check the HSM state, hart B will proceed to hsm_dev->hart_stop() and, upon waking up, will enter the warm boot path. As a result, `init_count` will match `entry_count` after hart B completes initialization. Apologies for the confusion. The fix looks good to me. Reviewed-by: Nick Hu <nick.hu@sifive.com> > Best Regards, > Nick > > > Regards, > > Anup > > > > > > > > > + } > > > > > > > > wfi(); > > > > } > > > > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c > > > > index 62c32682..84a63748 100644 > > > > --- a/lib/sbi/sbi_init.c > > > > +++ b/lib/sbi/sbi_init.c > > > > @@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch) > > > > init_warmboot(scratch, hartid); > > > > } > > > > > > > > +void sbi_revert_entry_count(struct sbi_scratch *scratch) > > > > +{ > > > > + unsigned long *entry_count, *init_count; > > > > + > > > > + if (!entry_count_offset || !init_count_offset) > > > > + sbi_hart_hang(); > > > > + > > > > + entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset); > > > > + init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); > > > > + > > > > + *entry_count = *init_count; > > > > +} > > > > + > > > > unsigned long sbi_entry_count(u32 hartindex) > > > > { > > > > struct sbi_scratch *scratch; > > > > -- > > > > 2.43.0 > > > > > > > > > > Best Regards, > > > Nick -- opensbi mailing list opensbi@lists.infradead.org http://lists.infradead.org/mailman/listinfo/opensbi ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop 2025-05-27 12:48 [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop Anup Patel 2025-05-28 10:26 ` Nick Hu @ 2025-06-16 4:18 ` Anup Patel 1 sibling, 0 replies; 6+ messages in thread From: Anup Patel @ 2025-06-16 4:18 UTC (permalink / raw) To: Anup Patel; +Cc: Atish Patra, Andrew Jones, Nick Hu, opensbi On Tue, May 27, 2025 at 6:18 PM Anup Patel <apatel@ventanamicro.com> wrote: > > Using hsm stop in hsm wait loop causes secondary harts to be stuck > forever in OpenSBI on RISC-V platforms where HSM hart hotplug is > available and all harts come-up at the same time during system > power-on. > > For example, lets say we have two harts A and B on a RISC-V platform > with HSM hart hotplug which come-up at the same time during system > power-on. The hart A enters OpenSBI before hart B hence it becomes > the primary (or cold-boot) hart whereas hart B becomes the secondary > (or warm-boot) hart. The hart A follows the OpenSBI cold-boot path > and registers hsm device before hart B enters OpenSBI. The hart B > eventually enters OpenSBI and follows the OpenSBI warm-boot path > so it will increment it's own entry_count before entering hsm wait > loop where it sees hsm device and stops itself. Later as part of > the Linux boot-up sequence, hart A issues SBI HSM start call to > bring-up hart B but OpenSBI sees entry_count != init_count for > hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is > not called for hart B resulting in hart B stuck forever in OpenSBI. > > To fix the above issue, revert entry_count before doing hsm stop > in hsm wait loop. > > Fixes: d844deadec94 ("lib: sbi: Use hsm stop for hsm wait") > Signed-off-by: Anup Patel <apatel@ventanamicro.com> Applied this patch to the riscv/opensbi repo. Thanks, Anup > --- > include/sbi/sbi_init.h | 2 ++ > lib/sbi/sbi_hsm.c | 4 +++- > lib/sbi/sbi_init.c | 13 +++++++++++++ > 3 files changed, 18 insertions(+), 1 deletion(-) > > diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h > index c9013ea4..ad068674 100644 > --- a/include/sbi/sbi_init.h > +++ b/include/sbi/sbi_init.h > @@ -16,6 +16,8 @@ struct sbi_scratch; > > void __noreturn sbi_init(struct sbi_scratch *scratch); > > +void sbi_revert_entry_count(struct sbi_scratch *scratch); > + > unsigned long sbi_entry_count(u32 hartindex); > > unsigned long sbi_init_count(u32 hartindex); > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c > index e8128a39..557ab131 100644 > --- a/lib/sbi/sbi_hsm.c > +++ b/lib/sbi/sbi_hsm.c > @@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch) > * If the hsm_dev is ready and it support the hotplug, we can > * use the hsm stop for more power saving > */ > - if (hsm_device_has_hart_hotplug()) > + if (hsm_device_has_hart_hotplug()) { > + sbi_revert_entry_count(scratch); > hsm_device_hart_stop(); > + } > > wfi(); > } > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c > index 62c32682..84a63748 100644 > --- a/lib/sbi/sbi_init.c > +++ b/lib/sbi/sbi_init.c > @@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch) > init_warmboot(scratch, hartid); > } > > +void sbi_revert_entry_count(struct sbi_scratch *scratch) > +{ > + unsigned long *entry_count, *init_count; > + > + if (!entry_count_offset || !init_count_offset) > + sbi_hart_hang(); > + > + entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset); > + init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); > + > + *entry_count = *init_count; > +} > + > unsigned long sbi_entry_count(u32 hartindex) > { > struct sbi_scratch *scratch; > -- > 2.43.0 > -- opensbi mailing list opensbi@lists.infradead.org http://lists.infradead.org/mailman/listinfo/opensbi ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-06-16 4:18 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-27 12:48 [PATCH] lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop Anup Patel 2025-05-28 10:26 ` Nick Hu 2025-05-28 12:14 ` Anup Patel 2025-05-28 14:34 ` Nick Hu 2025-05-30 7:05 ` Nick Hu 2025-06-16 4:18 ` Anup Patel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox