[platform][halt] refactor the default halt/reboot/shutdown logic
Move common logic into a default routine in platform/power that other platforms can reuse to implement the general default shutdown logic. Add helper routines to print the cause. Refactor the platforms that had substantial halt logic to reuse the default implementation.
This commit is contained in:
@@ -6,9 +6,9 @@
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include <platform/debug.h>
|
||||
|
||||
#include <lk/compiler.h>
|
||||
#include <lk/debug.h>
|
||||
#include <lk/trace.h>
|
||||
|
||||
/* Default implementation of panic time getc/putc.
|
||||
* Just calls through to the underlying dputc/dgetc implementation
|
||||
|
||||
@@ -21,6 +21,8 @@ typedef enum {
|
||||
HALT_ACTION_SHUTDOWN, // Shutdown and power off.
|
||||
} platform_halt_action;
|
||||
|
||||
const char *platform_halt_action_string(platform_halt_action action);
|
||||
|
||||
typedef enum {
|
||||
HALT_REASON_UNKNOWN = 0,
|
||||
HALT_REASON_POR, // Cold-boot
|
||||
@@ -35,14 +37,7 @@ typedef enum {
|
||||
HALT_REASON_SW_UPDATE, // SW triggered reboot in order to begin firmware update
|
||||
} platform_halt_reason;
|
||||
|
||||
/* super early platform initialization, before almost everything */
|
||||
void platform_early_init(void);
|
||||
|
||||
/* later init, after the kernel has come up */
|
||||
void platform_init(void);
|
||||
|
||||
/* called by the arch init code to get the platform to set up any mmu mappings it may need */
|
||||
void platform_init_mmu_mappings(void);
|
||||
const char *platform_halt_reason_string(platform_halt_reason reason);
|
||||
|
||||
/* if the platform has knowledge of what caused the latest reboot, it can report
|
||||
* it to applications with this function. */
|
||||
@@ -62,11 +57,30 @@ platform_halt_reason platform_get_reboot_reason(void);
|
||||
* reason, and then halt execution by turning off interrupts and spinning
|
||||
* forever.
|
||||
*/
|
||||
void platform_halt(platform_halt_action suggested_action,
|
||||
__WEAK void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) __NO_RETURN;
|
||||
|
||||
/* Default implementation of the above routine, which platforms can call with
|
||||
* appropriate hooks to implement platform specific reboot and shutdown behavior.
|
||||
*/
|
||||
typedef void (*platform_reboot_hook)(void);
|
||||
typedef void (*platform_shutdown_hook)(void);
|
||||
void platform_halt_default(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason,
|
||||
platform_reboot_hook prh,
|
||||
platform_shutdown_hook psh) __NO_RETURN;
|
||||
|
||||
/* called during chain loading to make sure drivers and platform is put into a stopped state */
|
||||
void platform_quiesce(void);
|
||||
|
||||
/* super early platform initialization, before almost everything */
|
||||
void platform_early_init(void);
|
||||
|
||||
/* later init, after the kernel has come up */
|
||||
void platform_init(void);
|
||||
|
||||
/* called by the arch init code to get the platform to set up any mmu mappings it may need */
|
||||
void platform_init_mmu_mappings(void);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#include <platform.h>
|
||||
|
||||
#include <lk/err.h>
|
||||
#include <lk/debug.h>
|
||||
#include <platform.h>
|
||||
|
||||
/*
|
||||
* default implementations of these routines, if the platform code
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#include <lib/minip.h>
|
||||
#endif
|
||||
#include <kernel/vm.h>
|
||||
#if WITH_LIB_CONSOLE
|
||||
#include <lib/console.h>
|
||||
#endif
|
||||
|
||||
#include "platform_p.h"
|
||||
|
||||
@@ -82,35 +79,20 @@ void platform_init(void) {
|
||||
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
switch (suggested_action) {
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
|
||||
// try to use SBI as a cleaner way to stop
|
||||
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
|
||||
*power_reset_reg = 0x5555;
|
||||
break;
|
||||
case HALT_ACTION_REBOOT:
|
||||
dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
|
||||
sbi_system_reset(SBI_RESET_TYPE_WARM_REBOOT, SBI_RESET_REASON_NONE);
|
||||
*power_reset_reg = 0x7777;
|
||||
break;
|
||||
case HALT_ACTION_HALT:
|
||||
#if ENABLE_PANIC_SHELL
|
||||
if (reason == HALT_REASON_SW_PANIC) {
|
||||
dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason);
|
||||
arch_disable_ints();
|
||||
panic_shell_start();
|
||||
}
|
||||
#endif // ENABLE_PANIC_SHELL
|
||||
dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
|
||||
break;
|
||||
}
|
||||
static void reboot_(void) {
|
||||
sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE);
|
||||
*power_reset_reg = 0x7777;
|
||||
}
|
||||
|
||||
arch_disable_ints();
|
||||
for (;;)
|
||||
arch_idle();
|
||||
static void shutdown_(void) {
|
||||
// try to use sbi as a cleaner way to stop
|
||||
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
|
||||
*power_reset_reg = 0x5555;
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) {
|
||||
// Use the default halt implementation using sbi as the reset and shutdown implementation.
|
||||
platform_halt_default(suggested_action, reason, &reboot_, &shutdown_);
|
||||
}
|
||||
|
||||
status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) {
|
||||
|
||||
@@ -94,12 +94,3 @@ void platform_dputc(char c) {
|
||||
int platform_dgetc(char *c, bool wait) {
|
||||
return cbuf_read_char(&console_input_buf, c, wait);
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
for (;;) {
|
||||
x86_cli();
|
||||
x86_hlt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,32 +12,99 @@
|
||||
#include <platform.h>
|
||||
#include <platform/debug.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if WITH_LIB_CONSOLE
|
||||
#include <lib/console.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* default implementations of these routines, if the platform code
|
||||
* chooses not to implement.
|
||||
*/
|
||||
__WEAK void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
// Default implementation of the system halt and reset function. Platforms may use
|
||||
// this as a helper to implement the logic by passing in a few hooks to do the
|
||||
// actual shutdown or reboot.
|
||||
void platform_halt_default(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason,
|
||||
platform_reboot_hook prh,
|
||||
platform_shutdown_hook psh) {
|
||||
const char *reason_string = platform_halt_reason_string(reason);
|
||||
switch (suggested_action) {
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
if (psh) {
|
||||
dprintf(ALWAYS, "Shutting down, reason '%s'\n", reason_string);
|
||||
psh();
|
||||
}
|
||||
break;
|
||||
case HALT_ACTION_REBOOT:
|
||||
if (prh) {
|
||||
dprintf(ALWAYS, "Rebooting, reason '%s'\n", reason_string);
|
||||
prh();
|
||||
}
|
||||
break;
|
||||
case HALT_ACTION_HALT:
|
||||
#if ENABLE_PANIC_SHELL
|
||||
if (reason == HALT_REASON_SW_PANIC && suggested_action == HALT_ACTION_HALT) {
|
||||
dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason);
|
||||
arch_disable_ints();
|
||||
panic_shell_start();
|
||||
}
|
||||
if (reason == HALT_REASON_SW_PANIC) {
|
||||
dprintf(ALWAYS, "CRASH: starting debug shell, reason '%s'\n", reason_string);
|
||||
arch_disable_ints();
|
||||
panic_shell_start();
|
||||
}
|
||||
#endif // ENABLE_PANIC_SHELL
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
|
||||
dprintf(ALWAYS, "HALT: spinning forever, reason '%s'\n", reason_string);
|
||||
arch_disable_ints();
|
||||
for (;;)
|
||||
arch_idle();
|
||||
}
|
||||
|
||||
// Default implementation of platform halt, which simply start the debug shell or spins forever.
|
||||
__WEAK void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
platform_halt_default(suggested_action, reason, NULL, NULL);
|
||||
}
|
||||
|
||||
__WEAK platform_halt_reason platform_get_reboot_reason(void) {
|
||||
return HALT_REASON_UNKNOWN;
|
||||
}
|
||||
|
||||
const char *platform_halt_action_string(platform_halt_action action) {
|
||||
switch(action) {
|
||||
case HALT_ACTION_HALT:
|
||||
return "halt";
|
||||
case HALT_ACTION_REBOOT:
|
||||
return "reboot";
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
return "shutdown";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char *platform_halt_reason_string(platform_halt_reason reason) {
|
||||
switch(reason) {
|
||||
case HALT_REASON_UNKNOWN:
|
||||
return "unknown";
|
||||
case HALT_REASON_POR:
|
||||
return "power on reset";
|
||||
case HALT_REASON_HW_WATCHDOG:
|
||||
return "hardware watchdog";
|
||||
case HALT_REASON_LOWVOLTAGE:
|
||||
return "low voltage";
|
||||
case HALT_REASON_HIGHVOLTAGE:
|
||||
return "high voltage";
|
||||
case HALT_REASON_THERMAL:
|
||||
return "thermal";
|
||||
case HALT_REASON_OTHER_HW:
|
||||
return "other hardware";
|
||||
case HALT_REASON_SW_RESET:
|
||||
return "software reset";
|
||||
case HALT_REASON_SW_WATCHDOG:
|
||||
return "software watchdog";
|
||||
case HALT_REASON_SW_PANIC:
|
||||
return "software panic";
|
||||
case HALT_REASON_SW_UPDATE:
|
||||
return "software update";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static int cmd_reboot(int argc, const console_cmd_args *argv) {
|
||||
platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
|
||||
return 0;
|
||||
|
||||
@@ -30,8 +30,8 @@ void platform_dputc(char c) {
|
||||
|
||||
int platform_dgetc(char *c, bool wait) {
|
||||
int ret = uart_getc(DEBUG_UART, wait);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*c = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -194,16 +194,6 @@ status_t platform_compute_msi_values(unsigned int vector, unsigned int cpu, bool
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) {
|
||||
switch (suggested_action) {
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
case HALT_ACTION_HALT:
|
||||
psci_system_off();
|
||||
break;
|
||||
case HALT_ACTION_REBOOT:
|
||||
psci_system_reset();
|
||||
break;
|
||||
}
|
||||
dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
|
||||
arch_disable_ints();
|
||||
for (;;);
|
||||
// Use the default halt implementation using psci as the reset and shutdown implementation.
|
||||
platform_halt_default(suggested_action, reason, &psci_system_reset, &psci_system_off);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#else
|
||||
#include <kernel/novm.h>
|
||||
#endif
|
||||
#if WITH_LIB_CONSOLE
|
||||
#include <lib/console.h>
|
||||
#endif
|
||||
|
||||
#include "platform_p.h"
|
||||
|
||||
@@ -119,33 +116,3 @@ void platform_init(void) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
switch (suggested_action) {
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
|
||||
*power_reset_reg = 0x5555;
|
||||
break;
|
||||
case HALT_ACTION_REBOOT:
|
||||
dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
|
||||
*power_reset_reg = 0x7777;
|
||||
break;
|
||||
case HALT_ACTION_HALT:
|
||||
#if ENABLE_PANIC_SHELL
|
||||
if (reason == HALT_REASON_SW_PANIC) {
|
||||
dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason);
|
||||
arch_disable_ints();
|
||||
panic_shell_start();
|
||||
}
|
||||
#endif // ENABLE_PANIC_SHELL
|
||||
dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
|
||||
break;
|
||||
}
|
||||
|
||||
arch_disable_ints();
|
||||
for (;;)
|
||||
arch_idle();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
#else
|
||||
#include <kernel/novm.h>
|
||||
#endif
|
||||
#if WITH_LIB_CONSOLE
|
||||
#include <lib/console.h>
|
||||
#endif
|
||||
|
||||
#include "platform_p.h"
|
||||
|
||||
@@ -123,39 +120,24 @@ void platform_init(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
switch (suggested_action) {
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
|
||||
static void reboot_(void) {
|
||||
#if RISCV_S_MODE
|
||||
// try to use SBI as a cleaner way to stop
|
||||
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
|
||||
sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE);
|
||||
#endif
|
||||
*power_reset_reg = 0x5555;
|
||||
break;
|
||||
case HALT_ACTION_REBOOT:
|
||||
dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
|
||||
#if RISCV_S_MODE
|
||||
sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE);
|
||||
#endif
|
||||
*power_reset_reg = 0x7777;
|
||||
break;
|
||||
case HALT_ACTION_HALT:
|
||||
#if ENABLE_PANIC_SHELL
|
||||
if (reason == HALT_REASON_SW_PANIC) {
|
||||
dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason);
|
||||
arch_disable_ints();
|
||||
panic_shell_start();
|
||||
}
|
||||
#endif // ENABLE_PANIC_SHELL
|
||||
dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
|
||||
break;
|
||||
}
|
||||
*power_reset_reg = 0x7777;
|
||||
}
|
||||
|
||||
arch_disable_ints();
|
||||
for (;;)
|
||||
arch_idle();
|
||||
static void shutdown_(void) {
|
||||
#if RISCV_S_MODE
|
||||
// try to use sbi as a cleaner way to stop
|
||||
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
|
||||
#endif
|
||||
*power_reset_reg = 0x5555;
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) {
|
||||
// Use the default halt implementation using sbi as the reset and shutdown implementation.
|
||||
platform_halt_default(suggested_action, reason, &reboot_, &shutdown_);
|
||||
}
|
||||
|
||||
status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) {
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#include <lib/minip.h>
|
||||
#endif
|
||||
#include <kernel/vm.h>
|
||||
#if WITH_LIB_CONSOLE
|
||||
#include <lib/console.h>
|
||||
#endif
|
||||
|
||||
#include "platform_p.h"
|
||||
|
||||
@@ -68,33 +65,22 @@ void platform_init(void) {
|
||||
uart_init();
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action,
|
||||
platform_halt_reason reason) {
|
||||
switch (suggested_action) {
|
||||
case HALT_ACTION_SHUTDOWN:
|
||||
dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
|
||||
// try to use SBI as a cleaner way to stop
|
||||
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
|
||||
break;
|
||||
case HALT_ACTION_REBOOT:
|
||||
dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
|
||||
sbi_system_reset(SBI_RESET_TYPE_WARM_REBOOT, SBI_RESET_REASON_NONE);
|
||||
break;
|
||||
case HALT_ACTION_HALT:
|
||||
#if ENABLE_PANIC_SHELL
|
||||
if (reason == HALT_REASON_SW_PANIC) {
|
||||
dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason);
|
||||
arch_disable_ints();
|
||||
panic_shell_start();
|
||||
}
|
||||
#endif // ENABLE_PANIC_SHELL
|
||||
dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
|
||||
break;
|
||||
}
|
||||
static void reboot_(void) {
|
||||
#if RISCV_S_MODE
|
||||
sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
arch_disable_ints();
|
||||
for (;;)
|
||||
arch_idle();
|
||||
static void shutdown_(void) {
|
||||
#if RISCV_S_MODE
|
||||
// try to use sbi as a cleaner way to stop
|
||||
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) {
|
||||
// Use the default halt implementation using sbi as the reset and shutdown implementation.
|
||||
platform_halt_default(suggested_action, reason, &reboot_, &shutdown_);
|
||||
}
|
||||
|
||||
status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) {
|
||||
|
||||
Reference in New Issue
Block a user