From 15ed1e74526d85f94c2cda338c572e36e249c803 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Fri, 3 Jan 2020 11:17:44 +0530 Subject: lib: improve system reboot and shutdown implementation We improve sbi_system_reboot() an sbi_system_shutdown() by: 1. Calling halt IPI to all harts (except current HART) before calling platform reboot/shutdown hook. 2. Calling sbi_exit() instead of sbi_hang() in-case platform reboot/shutdown hook failed. Signed-off-by: Anup Patel Reviewed-by: Atish Patra --- lib/sbi/sbi_system.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'lib/sbi/sbi_system.c') diff --git a/lib/sbi/sbi_system.c b/lib/sbi/sbi_system.c index 9ea3c21..d189a89 100644 --- a/lib/sbi/sbi_system.c +++ b/lib/sbi/sbi_system.c @@ -12,6 +12,7 @@ #include #include #include +#include int sbi_system_early_init(struct sbi_scratch *scratch, bool cold_boot) { @@ -33,24 +34,34 @@ void sbi_system_final_exit(struct sbi_scratch *scratch) sbi_platform_final_exit(sbi_platform_ptr(scratch)); } -void __attribute__((noreturn)) -sbi_system_reboot(struct sbi_scratch *scratch, u32 type) - +void __noreturn sbi_system_reboot(struct sbi_scratch *scratch, u32 type) { + u32 current_hartid_mask = 1UL << sbi_current_hartid(); + + /* Send HALT IPI to every hart other than the current hart */ + sbi_ipi_send_many(scratch, + sbi_hart_available_mask() & ~current_hartid_mask, + 0, SBI_IPI_EVENT_HALT, NULL); + + /* Platform specific reooot */ sbi_platform_system_reboot(sbi_platform_ptr(scratch), type); - sbi_hart_hang(); + + /* If platform specific reboot did not work then do sbi_exit() */ + sbi_exit(scratch); } -void __attribute__((noreturn)) -sbi_system_shutdown(struct sbi_scratch *scratch, u32 type) +void __noreturn sbi_system_shutdown(struct sbi_scratch *scratch, u32 type) { - /* First try the platform-specific method */ - sbi_platform_system_shutdown(sbi_platform_ptr(scratch), type); + u32 current_hartid_mask = 1UL << sbi_current_hartid(); + + /* Send HALT IPI to every hart other than the current hart */ + sbi_ipi_send_many(scratch, + sbi_hart_available_mask() & ~current_hartid_mask, + 0, SBI_IPI_EVENT_HALT, NULL); - /* If that fails (or is not implemented) send an IPI on every - * hart to hang and then hang the current hart */ - sbi_ipi_send_many(scratch, sbi_hart_available_mask(), 0, - SBI_IPI_EVENT_HALT, NULL); + /* Platform specific shutdown */ + sbi_platform_system_shutdown(sbi_platform_ptr(scratch), type); - sbi_hart_hang(); + /* If platform specific shutdown did not work then do sbi_exit() */ + sbi_exit(scratch); } -- cgit v1.2.3