linux/drivers/xen/manage.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Handle extern requests for shutdown, reboot and sysrq
   4 */
   5
   6#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
   7
   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 only
  34           report a crash, not be instructed to crash!
  35           HALT is the same as POWEROFF, as far as we're concerned.  The tools use
  36           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_CALLBACKS
  62static 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        dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
 145
 146        if (err) {
 147                pr_err("failed to start xen_suspend: %d\n", err);
 148                si.cancelled = 1;
 149        }
 150
 151        xen_arch_resume();
 152
 153out_resume:
 154        if (!si.cancelled)
 155                xs_resume();
 156        else
 157                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 11
 170        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        default:
 183                break;
 184        }
 185        return NOTIFY_DONE;
 186}
 187static void do_poweroff(void)
 188{
 189        switch (system_state) {
 190        case SYSTEM_BOOTING:
 191        case SYSTEM_SCHEDULING:
 192                orderly_poweroff(true);
 193                break;
 194        case SYSTEM_RUNNING:
 195                orderly_poweroff(false);
 196                break;
 197        default:
 198                /* Don't do it when we are halting/rebooting. */
 199                pr_info("Ignoring Xen toolstack shutdown.\n");
 200                break;
 201        }
 202}
 203
 204static void do_reboot(void)
 205{
 206        shutting_down = SHUTDOWN_POWEROFF; /* ? */
 207        ctrl_alt_del();
 208}
 209
 210static struct shutdown_handler shutdown_handlers[] = {
 211        { "poweroff",   true,   do_poweroff },
 212        { "halt",       false,  do_poweroff },
 213        { "reboot",     true,   do_reboot   },
 214#ifdef CONFIG_HIBERNATE_CALLBACKS
 215        { "suspend",    true,   do_suspend  },
 216#endif
 217};
 218
 219static void shutdown_handler(struct xenbus_watch *watch,
 220                             const char *path, const char *token)
 221{
 222        char *str;
 223        struct xenbus_transaction xbt;
 224        int err;
 225        int idx;
 226
 227        if (shutting_down != SHUTDOWN_INVALID)
 228                return;
 229
 230 again:
 231        err = xenbus_transaction_start(&xbt);
 232        if (err)
 233                return;
 234
 235        str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
 236        /* Ignore read errors and empty reads. */
 237        if (XENBUS_IS_ERR_READ(str)) {
 238                xenbus_transaction_end(xbt, 1);
 239                return;
 240        }
 241
 242        for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
 243                if (strcmp(str, shutdown_handlers[idx].command) == 0)
 244                        break;
 245        }
 246
 247        /* Only acknowledge commands which we are prepared to handle. */
 248        if (idx < ARRAY_SIZE(shutdown_handlers))
 249                xenbus_write(xbt, "control", "shutdown", "");
 250
 251        err = xenbus_transaction_end(xbt, 0);
 252        if (err == -EAGAIN) {
 253                kfree(str);
 254                goto again;
 255        }
 256
 257        if (idx < ARRAY_SIZE(shutdown_handlers)) {
 258                shutdown_handlers[idx].cb();
 259        } else {
 260                pr_info("Ignoring shutdown request: %s\n", str);
 261                shutting_down = SHUTDOWN_INVALID;
 262        }
 263
 264        kfree(str);
 265}
 266
 267#ifdef CONFIG_MAGIC_SYSRQ
 268static void sysrq_handler(struct xenbus_watch *watch, const char *path,
 269                          const char *token)
 270{
 271        char sysrq_key = '\0';
 272        struct xenbus_transaction xbt;
 273        int err;
 274
 275 again:
 276        err = xenbus_transaction_start(&xbt);
 277        if (err)
 278                return;
 279        err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key);
 280        if (err < 0) {
 281                /*
 282                 * The Xenstore watch fires directly after registering it and
 283                 * after a suspend/resume cycle. So ENOENT is no error but
 284                 * might happen in those cases. ERANGE is observed when we get
 285                 * an empty value (''), this happens when we acknowledge the
 286                 * request by writing '\0' below.
 287                 */
 288                if (err != -ENOENT && err != -ERANGE)
 289                        pr_err("Error %d reading sysrq code in control/sysrq\n",
 290                               err);
 291                xenbus_transaction_end(xbt, 1);
 292                return;
 293        }
 294
 295        if (sysrq_key != '\0') {
 296                err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
 297                if (err) {
 298                        pr_err("%s: Error %d writing sysrq in control/sysrq\n",
 299                               __func__, err);
 300                        xenbus_transaction_end(xbt, 1);
 301                        return;
 302                }
 303        }
 304
 305        err = xenbus_transaction_end(xbt, 0);
 306        if (err == -EAGAIN)
 307                goto again;
 308
 309        if (sysrq_key != '\0')
 310                handle_sysrq(sysrq_key);
 311}
 312
 313static struct xenbus_watch sysrq_watch = {
 314        .node = "control/sysrq",
 315        .callback = sysrq_handler
 316};
 317#endif
 318
 319static struct xenbus_watch shutdown_watch = {
 320        .node = "control/shutdown",
 321        .callback = shutdown_handler
 322};
 323
 324static struct notifier_block xen_reboot_nb = {
 325        .notifier_call = poweroff_nb,
 326};
 327
 328static int setup_shutdown_watcher(void)
 329{
 330        int err;
 331        int idx;
 332#define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-"))
 333        char node[FEATURE_PATH_SIZE];
 334
 335        err = register_xenbus_watch(&shutdown_watch);
 336        if (err) {
 337                pr_err("Failed to set shutdown watcher\n");
 338                return err;
 339        }
 340
 341
 342#ifdef CONFIG_MAGIC_SYSRQ
 343        err = register_xenbus_watch(&sysrq_watch);
 344        if (err) {
 345                pr_err("Failed to set sysrq watcher\n");
 346                return err;
 347        }
 348#endif
 349
 350        for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
 351                if (!shutdown_handlers[idx].flag)
 352                        continue;
 353                snprintf(node, FEATURE_PATH_SIZE, "feature-%s",
 354                         shutdown_handlers[idx].command);
 355                err = xenbus_printf(XBT_NIL, "control", node, "%u", 1);
 356                if (err) {
 357                        pr_err("%s: Error %d writing %s\n", __func__,
 358                                err, node);
 359                        return err;
 360                }
 361        }
 362
 363        return 0;
 364}
 365
 366static int shutdown_event(struct notifier_block *notifier,
 367                          unsigned long event,
 368                          void *data)
 369{
 370        setup_shutdown_watcher();
 371        return NOTIFY_DONE;
 372}
 373
 374int xen_setup_shutdown_event(void)
 375{
 376        static struct notifier_block xenstore_notifier = {
 377                .notifier_call = shutdown_event
 378        };
 379
 380        if (!xen_domain())
 381                return -ENODEV;
 382        register_xenstore_notifier(&xenstore_notifier);
 383        register_reboot_notifier(&xen_reboot_nb);
 384
 385        return 0;
 386}
 387EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
 388
 389subsys_initcall(xen_setup_shutdown_event);
 390