diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 3cfd7b5fdb6be57a048e077dd6290d760b19525f..55113c1da6f9c32477b63334fdef44f498a79d79 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -17,7 +17,7 @@ obj-y := entry.o fpu.o traps.o process.o sys_sw64.o irq.o \ irq_sw64.o signal.o setup.o ptrace.o time.o \ systbls.o dup_print.o tc.o timer.o \ insn.o early_init.o topology.o cacheinfo.o \ - vdso.o vdso/ hmcall.o stacktrace.o idle.o + vdso.o vdso/ hmcall.o stacktrace.o idle.o reset.o obj-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 3c5b6f032c8bd5b8cb92aeda28bfe5b5cdf1a7b6..4ffa724897c3d0bfbdc36ba8cd9d5d57e76a1fae 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -15,70 +14,6 @@ #include "proto.h" -/* - * Power off function, if any - */ -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - -struct halt_info { - int mode; - char *restart_cmd; -}; - -static void common_shutdown_1(void *generic_ptr) -{ - struct halt_info *how = (struct halt_info *)generic_ptr; - int cpuid __maybe_unused = smp_processor_id(); - - /* No point in taking interrupts anymore. */ - local_irq_disable(); - -#ifdef CONFIG_SMP - /* Secondaries halt here. */ - if (cpuid != 0) { - set_cpu_present(cpuid, false); - set_cpu_possible(cpuid, false); - - if (is_in_guest()) { - hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); - while (1) - asm("nop"); - } else - asm("halt"); - } -#endif - if (sw64_platform->kill_arch) - sw64_platform->kill_arch(how->mode); -} - -static void common_shutdown(int mode, char *restart_cmd) -{ - struct halt_info args; - - args.mode = mode; - args.restart_cmd = restart_cmd; - on_each_cpu(common_shutdown_1, &args, 0); -} - -void machine_restart(char *restart_cmd) -{ - common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd); -} - - -void machine_halt(void) -{ - common_shutdown(LINUX_REBOOT_CMD_HALT, NULL); -} - - -void machine_power_off(void) -{ - common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL); -} - - /* * Re-start a thread when doing execve() */ diff --git a/arch/sw_64/kernel/reset.c b/arch/sw_64/kernel/reset.c new file mode 100644 index 0000000000000000000000000000000000000000..51ca362e9e63c792b4d4e3d0b5192927d9fe3d81 --- /dev/null +++ b/arch/sw_64/kernel/reset.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020-2022 Sunway Technology Corporation Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void default_halt(void) +{ + local_irq_disable(); + + pr_notice("\n\n** You can safely turn off the power now **\n\n"); + + while (true) + arch_cpu_idle(); +} + +static void default_poweroff(void) +{ + /* No point in taking interrupts anymore. */ + local_irq_disable(); +#ifdef CONFIG_EFI + efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); +#endif + while (true) + arch_cpu_idle(); +} + +static void default_restart(void) +{ + /* No point in taking interrupts anymore. */ + local_irq_disable(); + +#ifdef CONFIG_EFI + if (efi_capsule_pending(NULL)) + efi_reboot(REBOOT_WARM, NULL); + else + efi_reboot(REBOOT_COLD, NULL); +#endif + + while (true) + arch_cpu_idle(); +} + +void (*pm_restart)(void); + +void (*pm_power_off)(void); + +void (*pm_halt)(void); + +void machine_halt(void) +{ +#ifdef CONFIG_SMP + preempt_disable(); + smp_send_stop(); +#endif + pm_halt(); +} + +void machine_power_off(void) +{ +#ifdef CONFIG_SMP + preempt_disable(); + smp_send_stop(); +#endif + pm_power_off(); +} + +void machine_restart(char *command) +{ +#ifdef CONFIG_SMP + preempt_disable(); + smp_send_stop(); +#endif + do_kernel_restart(command); + pm_restart(); +} + +static int __init sw64_reboot_setup(void) +{ + pm_restart = default_restart; + pm_power_off = default_poweroff; + pm_halt = default_halt; + + return 0; +} +arch_initcall(sw64_reboot_setup);