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                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        ctrl_alt_del();
 209}
 210
 211static struct shutdown_handler shutdown_handlers[] = {
 212        { "poweroff",   true,   do_poweroff },
 213        { "halt",       false,  do_poweroff },
 214        { "reboot",     true,   do_reboot   },
 215#ifdef CONFIG_HIBERNATE_CALLBACKS
 216        { "suspend",    true,   do_suspend  },
 217#endif
 218};
 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_SYSRQ
 269static 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 and
 284                 * after a suspend/resume cycle. So ENOENT is no error but
 285                 * might happen in those cases. ERANGE is observed when we get
 286                 * an empty value (''), this happens when we acknowledge the
 287                 * 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_handler
 317};
 318#endif
 319
 320static struct xenbus_watch shutdown_watch = {
 321        .node = "control/shutdown",
 322        .callback = shutdown_handler
 323};
 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_SYSRQ
 344        err = register_xenbus_watch(&sysrq_watch);
 345        if (err) {
 346                pr_err("Failed to set sysrq watcher\n");
 347                return err;
 348        }
 349#endif
 350
 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_event
 379        };
 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