diff options
author | Richard Braun <rbraun@sceen.net> | 2017-07-01 18:32:18 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-07-01 18:53:46 +0200 |
commit | d6a18f61e0a53d9bd68cc927831423d7454410af (patch) | |
tree | 36c166e4ee41cf0329e77a26d6eba6a968bee64b | |
parent | 9b81ecb970b4929be2a210ed8539e297a73003f1 (diff) |
kern/shutdown: new module
-rw-r--r-- | Makefrag.am | 2 | ||||
-rw-r--r-- | arch/x86/machine/boot.c | 2 | ||||
-rw-r--r-- | kern/kernel.c | 2 | ||||
-rw-r--r-- | kern/shutdown.c | 111 | ||||
-rw-r--r-- | kern/shutdown.h | 39 |
5 files changed, 156 insertions, 0 deletions
diff --git a/Makefrag.am b/Makefrag.am index 886ec1f5..8a966b25 100644 --- a/Makefrag.am +++ b/Makefrag.am @@ -74,6 +74,8 @@ x15_SOURCES += \ kern/semaphore.c \ kern/semaphore.h \ kern/semaphore_i.h \ + kern/shutdown.c \ + kern/shutdown.h \ kern/sleepq.c \ kern/sleepq.h \ kern/spinlock.c \ diff --git a/arch/x86/machine/boot.c b/arch/x86/machine/boot.c index 7ce7b85d..571b04f6 100644 --- a/arch/x86/machine/boot.c +++ b/arch/x86/machine/boot.c @@ -58,6 +58,7 @@ #include <kern/macros.h> #include <kern/panic.h> #include <kern/percpu.h> +#include <kern/shutdown.h> #include <kern/sleepq.h> #include <kern/sref.h> #include <kern/syscnt.h> @@ -514,6 +515,7 @@ boot_main(void) vm_setup(); boot_save_data(); biosmem_free_usable(); + shutdown_setup(); intr_setup(); cpu_mp_probe(); atcons_setup(); diff --git a/kern/kernel.c b/kern/kernel.c index 9aa5c359..6c562f4d 100644 --- a/kern/kernel.c +++ b/kern/kernel.c @@ -22,6 +22,7 @@ #include <kern/log.h> #include <kern/percpu.h> #include <kern/shell.h> +#include <kern/shutdown.h> #include <kern/sleepq.h> #include <kern/sref.h> #include <kern/syscnt.h> @@ -55,6 +56,7 @@ kernel_main(void) llsync_setup(); sref_setup(); vm_page_log_info(); + shutdown_register_shell_cmds(); log_start(); #ifdef X15_RUN_TEST_MODULE diff --git a/kern/shutdown.c b/kern/shutdown.c new file mode 100644 index 00000000..11a51832 --- /dev/null +++ b/kern/shutdown.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +#include <kern/init.h> +#include <kern/plist.h> +#include <kern/shell.h> +#include <kern/shutdown.h> +#include <machine/cpu.h> + +static struct plist shutdown_ops_list; + +#ifdef X15_SHELL + +static void +shutdown_shell_halt(int argc, char **argv) +{ + (void)argc; + (void)argv; + + shutdown_halt(); +} + +static void +shutdown_shell_reboot(int argc, char **argv) +{ + (void)argc; + (void)argv; + + shutdown_reboot(); +} + +static struct shell_cmd shutdown_shell_cmds[] = { + SHELL_CMD_INITIALIZER("shutdown_halt", shutdown_shell_halt, + "shutdown_halt", + "halt the system"), + SHELL_CMD_INITIALIZER("shutdown_reboot", shutdown_shell_reboot, + "shutdown_reboot", + "reboot the system"), +}; + +#endif /* X15_SHELL */ + +void __init +shutdown_setup(void) +{ + plist_init(&shutdown_ops_list); +} + +void __init +shutdown_register_shell_cmds(void) +{ + SHELL_REGISTER_CMDS(shutdown_shell_cmds); +} + +void __init +shutdown_register(struct shutdown_ops *ops, unsigned int priority) +{ + plist_node_init(&ops->node, priority); + plist_add(&shutdown_ops_list, &ops->node); +} + +static void +shutdown_halt_other_cpus(void) +{ + cpu_intr_disable(); + cpu_halt_broadcast(); +} + +void +shutdown_halt(void) +{ + shutdown_halt_other_cpus(); + printf("shutdown: system halted\n"); + cpu_halt(); +} + +void +shutdown_reboot(void) +{ + struct shutdown_ops *ops; + + if (plist_empty(&shutdown_ops_list)) { + printf("shutdown: no reset operation available, halting\n"); + shutdown_halt(); + } + + shutdown_halt_other_cpus(); + printf("shutdown: rebooting...\n"); + + plist_for_each_entry_reverse(&shutdown_ops_list, ops, node) { + ops->reset(); + } + + cpu_halt(); +} diff --git a/kern/shutdown.h b/kern/shutdown.h new file mode 100644 index 00000000..f7bc1879 --- /dev/null +++ b/kern/shutdown.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _KERN_SHUTDOWN_H +#define _KERN_SHUTDOWN_H + +#include <stdnoreturn.h> + +#include <kern/plist.h> + +struct shutdown_ops { + struct plist_node node; + void (*reset)(void); +}; + +void shutdown_setup(void); + +void shutdown_register_shell_cmds(void); + +void shutdown_register(struct shutdown_ops *ops, unsigned int priority); + +noreturn void shutdown_halt(void); +noreturn void shutdown_reboot(void); + +#endif /* _KERN_SHUTDOWN_H */ |