391 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Handle extern requests for shutdown, reboot and sysrq4 */5 6#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt7 8#include <linux/kernel.h>9#include <linux/err.h>10#include <linux/slab.h>11#include <linux/reboot.h>12#include <linux/sysrq.h>13#include <linux/stop_machine.h>14#include <linux/freezer.h>15#include <linux/syscore_ops.h>16#include <linux/export.h>17 18#include <xen/xen.h>19#include <xen/xenbus.h>20#include <xen/grant_table.h>21#include <xen/events.h>22#include <xen/hvc-console.h>23#include <xen/page.h>24#include <xen/xen-ops.h>25 26#include <asm/xen/hypercall.h>27#include <asm/xen/hypervisor.h>28 29enum shutdown_state {30 SHUTDOWN_INVALID = -1,31 SHUTDOWN_POWEROFF = 0,32 SHUTDOWN_SUSPEND = 2,33 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only34 report a crash, not be instructed to crash!35 HALT is the same as POWEROFF, as far as we're concerned. The tools use36 the distinction when we return the reason code to them. */37 SHUTDOWN_HALT = 4,38};39 40/* Ignore multiple shutdown requests. */41static enum shutdown_state shutting_down = SHUTDOWN_INVALID;42 43struct suspend_info {44 int cancelled;45};46 47static RAW_NOTIFIER_HEAD(xen_resume_notifier);48 49void xen_resume_notifier_register(struct notifier_block *nb)50{51 raw_notifier_chain_register(&xen_resume_notifier, nb);52}53EXPORT_SYMBOL_GPL(xen_resume_notifier_register);54 55void xen_resume_notifier_unregister(struct notifier_block *nb)56{57 raw_notifier_chain_unregister(&xen_resume_notifier, nb);58}59EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);60 61#ifdef CONFIG_HIBERNATE_CALLBACKS62static int xen_suspend(void *data)63{64 struct suspend_info *si = data;65 int err;66 67 BUG_ON(!irqs_disabled());68 69 err = syscore_suspend();70 if (err) {71 pr_err("%s: system core suspend failed: %d\n", __func__, err);72 return err;73 }74 75 gnttab_suspend();76 xen_manage_runstate_time(-1);77 xen_arch_pre_suspend();78 79 si->cancelled = HYPERVISOR_suspend(xen_pv_domain()80 ? virt_to_gfn(xen_start_info)81 : 0);82 83 xen_arch_post_suspend(si->cancelled);84 xen_manage_runstate_time(si->cancelled ? 1 : 0);85 gnttab_resume();86 87 if (!si->cancelled) {88 xen_irq_resume();89 xen_timer_resume();90 }91 92 syscore_resume();93 94 return 0;95}96 97static void do_suspend(void)98{99 int err;100 struct suspend_info si;101 102 shutting_down = SHUTDOWN_SUSPEND;103 104 err = freeze_processes();105 if (err) {106 pr_err("%s: freeze processes failed %d\n", __func__, err);107 goto out;108 }109 110 err = freeze_kernel_threads();111 if (err) {112 pr_err("%s: freeze kernel threads failed %d\n", __func__, err);113 goto out_thaw;114 }115 116 err = dpm_suspend_start(PMSG_FREEZE);117 if (err) {118 pr_err("%s: dpm_suspend_start %d\n", __func__, err);119 goto out_thaw;120 }121 122 printk(KERN_DEBUG "suspending xenstore...\n");123 xs_suspend();124 125 err = dpm_suspend_end(PMSG_FREEZE);126 if (err) {127 pr_err("dpm_suspend_end failed: %d\n", err);128 si.cancelled = 0;129 goto out_resume;130 }131 132 xen_arch_suspend();133 134 si.cancelled = 1;135 136 err = stop_machine(xen_suspend, &si, cpumask_of(0));137 138 /* Resume console as early as possible. */139 if (!si.cancelled)140 xen_console_resume();141 142 raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);143 144 xen_arch_resume();145 146 dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);147 148 if (err) {149 pr_err("failed to start xen_suspend: %d\n", err);150 si.cancelled = 1;151 }152 153out_resume:154 if (!si.cancelled)155 xs_resume();156 else157 xs_suspend_cancel();158 159 dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);160 161out_thaw:162 thaw_processes();163out:164 shutting_down = SHUTDOWN_INVALID;165}166#endif /* CONFIG_HIBERNATE_CALLBACKS */167 168struct shutdown_handler {169#define SHUTDOWN_CMD_SIZE 11170 const char command[SHUTDOWN_CMD_SIZE];171 bool flag;172 void (*cb)(void);173};174 175static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)176{177 switch (code) {178 case SYS_DOWN:179 case SYS_HALT:180 case SYS_POWER_OFF:181 shutting_down = SHUTDOWN_POWEROFF;182 break;183 default:184 break;185 }186 return NOTIFY_DONE;187}188static void do_poweroff(void)189{190 switch (system_state) {191 case SYSTEM_BOOTING:192 case SYSTEM_SCHEDULING:193 orderly_poweroff(true);194 break;195 case SYSTEM_RUNNING:196 orderly_poweroff(false);197 break;198 default:199 /* Don't do it when we are halting/rebooting. */200 pr_info("Ignoring Xen toolstack shutdown.\n");201 break;202 }203}204 205static void do_reboot(void)206{207 shutting_down = SHUTDOWN_POWEROFF; /* ? */208 orderly_reboot();209}210 211static const struct shutdown_handler shutdown_handlers[] = {212 { "poweroff", true, do_poweroff },213 { "halt", false, do_poweroff },214 { "reboot", true, do_reboot },215#ifdef CONFIG_HIBERNATE_CALLBACKS216 { "suspend", true, do_suspend },217#endif218};219 220static void shutdown_handler(struct xenbus_watch *watch,221 const char *path, const char *token)222{223 char *str;224 struct xenbus_transaction xbt;225 int err;226 int idx;227 228 if (shutting_down != SHUTDOWN_INVALID)229 return;230 231 again:232 err = xenbus_transaction_start(&xbt);233 if (err)234 return;235 236 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);237 /* Ignore read errors and empty reads. */238 if (XENBUS_IS_ERR_READ(str)) {239 xenbus_transaction_end(xbt, 1);240 return;241 }242 243 for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {244 if (strcmp(str, shutdown_handlers[idx].command) == 0)245 break;246 }247 248 /* Only acknowledge commands which we are prepared to handle. */249 if (idx < ARRAY_SIZE(shutdown_handlers))250 xenbus_write(xbt, "control", "shutdown", "");251 252 err = xenbus_transaction_end(xbt, 0);253 if (err == -EAGAIN) {254 kfree(str);255 goto again;256 }257 258 if (idx < ARRAY_SIZE(shutdown_handlers)) {259 shutdown_handlers[idx].cb();260 } else {261 pr_info("Ignoring shutdown request: %s\n", str);262 shutting_down = SHUTDOWN_INVALID;263 }264 265 kfree(str);266}267 268#ifdef CONFIG_MAGIC_SYSRQ269static void sysrq_handler(struct xenbus_watch *watch, const char *path,270 const char *token)271{272 char sysrq_key = '\0';273 struct xenbus_transaction xbt;274 int err;275 276 again:277 err = xenbus_transaction_start(&xbt);278 if (err)279 return;280 err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key);281 if (err < 0) {282 /*283 * The Xenstore watch fires directly after registering it and284 * after a suspend/resume cycle. So ENOENT is no error but285 * might happen in those cases. ERANGE is observed when we get286 * an empty value (''), this happens when we acknowledge the287 * request by writing '\0' below.288 */289 if (err != -ENOENT && err != -ERANGE)290 pr_err("Error %d reading sysrq code in control/sysrq\n",291 err);292 xenbus_transaction_end(xbt, 1);293 return;294 }295 296 if (sysrq_key != '\0') {297 err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0');298 if (err) {299 pr_err("%s: Error %d writing sysrq in control/sysrq\n",300 __func__, err);301 xenbus_transaction_end(xbt, 1);302 return;303 }304 }305 306 err = xenbus_transaction_end(xbt, 0);307 if (err == -EAGAIN)308 goto again;309 310 if (sysrq_key != '\0')311 handle_sysrq(sysrq_key);312}313 314static struct xenbus_watch sysrq_watch = {315 .node = "control/sysrq",316 .callback = sysrq_handler317};318#endif319 320static struct xenbus_watch shutdown_watch = {321 .node = "control/shutdown",322 .callback = shutdown_handler323};324 325static struct notifier_block xen_reboot_nb = {326 .notifier_call = poweroff_nb,327};328 329static int setup_shutdown_watcher(void)330{331 int err;332 int idx;333#define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-"))334 char node[FEATURE_PATH_SIZE];335 336 err = register_xenbus_watch(&shutdown_watch);337 if (err) {338 pr_err("Failed to set shutdown watcher\n");339 return err;340 }341 342 343#ifdef CONFIG_MAGIC_SYSRQ344 err = register_xenbus_watch(&sysrq_watch);345 if (err) {346 pr_err("Failed to set sysrq watcher\n");347 return err;348 }349#endif350 351 for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {352 if (!shutdown_handlers[idx].flag)353 continue;354 snprintf(node, FEATURE_PATH_SIZE, "feature-%s",355 shutdown_handlers[idx].command);356 err = xenbus_printf(XBT_NIL, "control", node, "%u", 1);357 if (err) {358 pr_err("%s: Error %d writing %s\n", __func__,359 err, node);360 return err;361 }362 }363 364 return 0;365}366 367static int shutdown_event(struct notifier_block *notifier,368 unsigned long event,369 void *data)370{371 setup_shutdown_watcher();372 return NOTIFY_DONE;373}374 375int xen_setup_shutdown_event(void)376{377 static struct notifier_block xenstore_notifier = {378 .notifier_call = shutdown_event379 };380 381 if (!xen_domain())382 return -ENODEV;383 register_xenstore_notifier(&xenstore_notifier);384 register_reboot_notifier(&xen_reboot_nb);385 386 return 0;387}388EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);389 390subsys_initcall(xen_setup_shutdown_event);391