Skip to content

Commit 7dd09bf

Browse files
committed
lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop
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: d844dea ("lib: sbi: Use hsm stop for hsm wait") Signed-off-by: Anup Patel <[email protected]> Reviewed-by: Nick Hu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
1 parent 6f8bcae commit 7dd09bf

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

include/sbi/sbi_init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ struct sbi_scratch;
1616

1717
void __noreturn sbi_init(struct sbi_scratch *scratch);
1818

19+
void sbi_revert_entry_count(struct sbi_scratch *scratch);
20+
1921
unsigned long sbi_entry_count(u32 hartindex);
2022

2123
unsigned long sbi_init_count(u32 hartindex);

lib/sbi/sbi_hsm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,10 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch)
176176
* If the hsm_dev is ready and it support the hotplug, we can
177177
* use the hsm stop for more power saving
178178
*/
179-
if (hsm_device_has_hart_hotplug())
179+
if (hsm_device_has_hart_hotplug()) {
180+
sbi_revert_entry_count(scratch);
180181
hsm_device_hart_stop();
182+
}
181183

182184
wfi();
183185
}

lib/sbi/sbi_init.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,19 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
579579
init_warmboot(scratch, hartid);
580580
}
581581

582+
void sbi_revert_entry_count(struct sbi_scratch *scratch)
583+
{
584+
unsigned long *entry_count, *init_count;
585+
586+
if (!entry_count_offset || !init_count_offset)
587+
sbi_hart_hang();
588+
589+
entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset);
590+
init_count = sbi_scratch_offset_ptr(scratch, init_count_offset);
591+
592+
*entry_count = *init_count;
593+
}
594+
582595
unsigned long sbi_entry_count(u32 hartindex)
583596
{
584597
struct sbi_scratch *scratch;

0 commit comments

Comments
 (0)