Skip to content

Commit

Permalink
[platform][halt] refactor the default halt/reboot/shutdown logic
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
travisg committed Aug 10, 2024
1 parent 6fd2626 commit e03d419
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 172 deletions.
4 changes: 2 additions & 2 deletions platform/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 23 additions & 9 deletions platform/include/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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. */
Expand All @@ -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

3 changes: 2 additions & 1 deletion platform/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 13 additions & 31 deletions platform/jh7110/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
}

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;
}

arch_disable_ints();
for (;;)
arch_idle();
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) {
Expand Down
9 changes: 0 additions & 9 deletions platform/pc/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

93 changes: 80 additions & 13 deletions platform/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions platform/qemu-virt-arm/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
14 changes: 2 additions & 12 deletions platform/qemu-virt-arm/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
33 changes: 0 additions & 33 deletions platform/qemu-virt-m68k/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
#else
#include <kernel/novm.h>
#endif
#if WITH_LIB_CONSOLE
#include <lib/console.h>
#endif

#include "platform_p.h"

Expand Down Expand Up @@ -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
Loading

0 comments on commit e03d419

Please sign in to comment.