linux/kernel/reboot.c
<<
>>
Prefs
   1/*
   2 *  linux/kernel/reboot.c
   3 *
   4 *  Copyright (C) 2013  Linus Torvalds
   5 */
   6
   7#define pr_fmt(fmt)     "reboot: " fmt
   8
   9#include <linux/ctype.h>
  10#include <linux/export.h>
  11#include <linux/kexec.h>
  12#include <linux/kmod.h>
  13#include <linux/kmsg_dump.h>
  14#include <linux/reboot.h>
  15#include <linux/suspend.h>
  16#include <linux/syscalls.h>
  17#include <linux/syscore_ops.h>
  18#include <linux/uaccess.h>
  19
  20/*
  21 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
  22 */
  23
  24int C_A_D = 1;
  25struct pid *cad_pid;
  26EXPORT_SYMBOL(cad_pid);
  27
  28#if defined(CONFIG_ARM) || defined(CONFIG_UNICORE32)
  29#define DEFAULT_REBOOT_MODE             = REBOOT_HARD
  30#else
  31#define DEFAULT_REBOOT_MODE
  32#endif
  33enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;
  34
  35int reboot_default;
  36int reboot_cpu;
  37enum reboot_type reboot_type = BOOT_ACPI;
  38int reboot_force;
  39
  40/*
  41 * If set, this is used for preparing the system to power off.
  42 */
  43
  44void (*pm_power_off_prepare)(void);
  45
  46/**
  47 *      emergency_restart - reboot the system
  48 *
  49 *      Without shutting down any hardware or taking any locks
  50 *      reboot the system.  This is called when we know we are in
  51 *      trouble so this is our best effort to reboot.  This is
  52 *      safe to call in interrupt context.
  53 */
  54void emergency_restart(void)
  55{
  56        kmsg_dump(KMSG_DUMP_EMERG);
  57        machine_emergency_restart();
  58}
  59EXPORT_SYMBOL_GPL(emergency_restart);
  60
  61void kernel_restart_prepare(char *cmd)
  62{
  63        blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
  64        system_state = SYSTEM_RESTART;
  65        usermodehelper_disable();
  66        device_shutdown();
  67}
  68
  69/**
  70 *      register_reboot_notifier - Register function to be called at reboot time
  71 *      @nb: Info about notifier function to be called
  72 *
  73 *      Registers a function with the list of functions
  74 *      to be called at reboot time.
  75 *
  76 *      Currently always returns zero, as blocking_notifier_chain_register()
  77 *      always returns zero.
  78 */
  79int register_reboot_notifier(struct notifier_block *nb)
  80{
  81        return blocking_notifier_chain_register(&reboot_notifier_list, nb);
  82}
  83EXPORT_SYMBOL(register_reboot_notifier);
  84
  85/**
  86 *      unregister_reboot_notifier - Unregister previously registered reboot notifier
  87 *      @nb: Hook to be unregistered
  88 *
  89 *      Unregisters a previously registered reboot
  90 *      notifier function.
  91 *
  92 *      Returns zero on success, or %-ENOENT on failure.
  93 */
  94int unregister_reboot_notifier(struct notifier_block *nb)
  95{
  96        return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
  97}
  98EXPORT_SYMBOL(unregister_reboot_notifier);
  99
 100static void migrate_to_reboot_cpu(void)
 101{
 102        /* The boot cpu is always logical cpu 0 */
 103        int cpu = reboot_cpu;
 104
 105        cpu_hotplug_disable();
 106
 107        /* Make certain the cpu I'm about to reboot on is online */
 108        if (!cpu_online(cpu))
 109                cpu = cpumask_first(cpu_online_mask);
 110
 111        /* Prevent races with other tasks migrating this task */
 112        current->flags |= PF_NO_SETAFFINITY;
 113
 114        /* Make certain I only run on the appropriate processor */
 115        set_cpus_allowed_ptr(current, cpumask_of(cpu));
 116}
 117
 118/**
 119 *      kernel_restart - reboot the system
 120 *      @cmd: pointer to buffer containing command to execute for restart
 121 *              or %NULL
 122 *
 123 *      Shutdown everything and perform a clean reboot.
 124 *      This is not safe to call in interrupt context.
 125 */
 126void kernel_restart(char *cmd)
 127{
 128        kernel_restart_prepare(cmd);
 129        migrate_to_reboot_cpu();
 130        syscore_shutdown();
 131        if (!cmd)
 132                pr_emerg("Restarting system\n");
 133        else
 134                pr_emerg("Restarting system with command '%s'\n", cmd);
 135        kmsg_dump(KMSG_DUMP_RESTART);
 136        machine_restart(cmd);
 137}
 138EXPORT_SYMBOL_GPL(kernel_restart);
 139
 140static void kernel_shutdown_prepare(enum system_states state)
 141{
 142        blocking_notifier_call_chain(&reboot_notifier_list,
 143                (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
 144        system_state = state;
 145        usermodehelper_disable();
 146        device_shutdown();
 147}
 148/**
 149 *      kernel_halt - halt the system
 150 *
 151 *      Shutdown everything and perform a clean system halt.
 152 */
 153void kernel_halt(void)
 154{
 155        kernel_shutdown_prepare(SYSTEM_HALT);
 156        migrate_to_reboot_cpu();
 157        syscore_shutdown();
 158        pr_emerg("System halted\n");
 159        kmsg_dump(KMSG_DUMP_HALT);
 160        machine_halt();
 161}
 162EXPORT_SYMBOL_GPL(kernel_halt);
 163
 164/**
 165 *      kernel_power_off - power_off the system
 166 *
 167 *      Shutdown everything and perform a clean system power_off.
 168 */
 169void kernel_power_off(void)
 170{
 171        kernel_shutdown_prepare(SYSTEM_POWER_OFF);
 172        if (pm_power_off_prepare)
 173                pm_power_off_prepare();
 174        migrate_to_reboot_cpu();
 175        syscore_shutdown();
 176        pr_emerg("Power down\n");
 177        kmsg_dump(KMSG_DUMP_POWEROFF);
 178        machine_power_off();
 179}
 180EXPORT_SYMBOL_GPL(kernel_power_off);
 181
 182static DEFINE_MUTEX(reboot_mutex);
 183
 184/*
 185 * Reboot system call: for obvious reasons only root may call it,
 186 * and even root needs to set up some magic numbers in the registers
 187 * so that some mistake won't make this reboot the whole machine.
 188 * You can also set the meaning of the ctrl-alt-del-key here.
 189 *
 190 * reboot doesn't sync: do that yourself before calling this.
 191 */
 192SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
 193                void __user *, arg)
 194{
 195        struct pid_namespace *pid_ns = task_active_pid_ns(current);
 196        char buffer[256];
 197        int ret = 0;
 198
 199        /* We only trust the superuser with rebooting the system. */
 200        if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
 201                return -EPERM;
 202
 203        /* For safety, we require "magic" arguments. */
 204        if (magic1 != LINUX_REBOOT_MAGIC1 ||
 205                        (magic2 != LINUX_REBOOT_MAGIC2 &&
 206                        magic2 != LINUX_REBOOT_MAGIC2A &&
 207                        magic2 != LINUX_REBOOT_MAGIC2B &&
 208                        magic2 != LINUX_REBOOT_MAGIC2C))
 209                return -EINVAL;
 210
 211        /*
 212         * If pid namespaces are enabled and the current task is in a child
 213         * pid_namespace, the command is handled by reboot_pid_ns() which will
 214         * call do_exit().
 215         */
 216        ret = reboot_pid_ns(pid_ns, cmd);
 217        if (ret)
 218                return ret;
 219
 220        /* Instead of trying to make the power_off code look like
 221         * halt when pm_power_off is not set do it the easy way.
 222         */
 223        if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
 224                cmd = LINUX_REBOOT_CMD_HALT;
 225
 226        mutex_lock(&reboot_mutex);
 227        switch (cmd) {
 228        case LINUX_REBOOT_CMD_RESTART:
 229                kernel_restart(NULL);
 230                break;
 231
 232        case LINUX_REBOOT_CMD_CAD_ON:
 233                C_A_D = 1;
 234                break;
 235
 236        case LINUX_REBOOT_CMD_CAD_OFF:
 237                C_A_D = 0;
 238                break;
 239
 240        case LINUX_REBOOT_CMD_HALT:
 241                kernel_halt();
 242                do_exit(0);
 243                panic("cannot halt");
 244
 245        case LINUX_REBOOT_CMD_POWER_OFF:
 246                kernel_power_off();
 247                do_exit(0);
 248                break;
 249
 250        case LINUX_REBOOT_CMD_RESTART2:
 251                ret = strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1);
 252                if (ret < 0) {
 253                        ret = -EFAULT;
 254                        break;
 255                }
 256                buffer[sizeof(buffer) - 1] = '\0';
 257
 258                kernel_restart(buffer);
 259                break;
 260
 261#ifdef CONFIG_KEXEC
 262        case LINUX_REBOOT_CMD_KEXEC:
 263                ret = kernel_kexec();
 264                break;
 265#endif
 266
 267#ifdef CONFIG_HIBERNATION
 268        case LINUX_REBOOT_CMD_SW_SUSPEND:
 269                ret = hibernate();
 270                break;
 271#endif
 272
 273        default:
 274                ret = -EINVAL;
 275                break;
 276        }
 277        mutex_unlock(&reboot_mutex);
 278        return ret;
 279}
 280
 281static void deferred_cad(struct work_struct *dummy)
 282{
 283        kernel_restart(NULL);
 284}
 285
 286/*
 287 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
 288 * As it's called within an interrupt, it may NOT sync: the only choice
 289 * is whether to reboot at once, or just ignore the ctrl-alt-del.
 290 */
 291void ctrl_alt_del(void)
 292{
 293        static DECLARE_WORK(cad_work, deferred_cad);
 294
 295        if (C_A_D)
 296                schedule_work(&cad_work);
 297        else
 298                kill_cad_pid(SIGINT, 1);
 299}
 300
 301char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
 302
 303static int __orderly_poweroff(bool force)
 304{
 305        char **argv;
 306        static char *envp[] = {
 307                "HOME=/",
 308                "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
 309                NULL
 310        };
 311        int ret;
 312
 313        argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL);
 314        if (argv) {
 315                ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
 316                argv_free(argv);
 317        } else {
 318                ret = -ENOMEM;
 319        }
 320
 321        if (ret && force) {
 322                pr_warn("Failed to start orderly shutdown: forcing the issue\n");
 323                /*
 324                 * I guess this should try to kick off some daemon to sync and
 325                 * poweroff asap.  Or not even bother syncing if we're doing an
 326                 * emergency shutdown?
 327                 */
 328                emergency_sync();
 329                kernel_power_off();
 330        }
 331
 332        return ret;
 333}
 334
 335static bool poweroff_force;
 336
 337static void poweroff_work_func(struct work_struct *work)
 338{
 339        __orderly_poweroff(poweroff_force);
 340}
 341
 342static DECLARE_WORK(poweroff_work, poweroff_work_func);
 343
 344/**
 345 * orderly_poweroff - Trigger an orderly system poweroff
 346 * @force: force poweroff if command execution fails
 347 *
 348 * This may be called from any context to trigger a system shutdown.
 349 * If the orderly shutdown fails, it will force an immediate shutdown.
 350 */
 351int orderly_poweroff(bool force)
 352{
 353        if (force) /* do not override the pending "true" */
 354                poweroff_force = true;
 355        schedule_work(&poweroff_work);
 356        return 0;
 357}
 358EXPORT_SYMBOL_GPL(orderly_poweroff);
 359
 360static int __init reboot_setup(char *str)
 361{
 362        for (;;) {
 363                /*
 364                 * Having anything passed on the command line via
 365                 * reboot= will cause us to disable DMI checking
 366                 * below.
 367                 */
 368                reboot_default = 0;
 369
 370                switch (*str) {
 371                case 'w':
 372                        reboot_mode = REBOOT_WARM;
 373                        break;
 374
 375                case 'c':
 376                        reboot_mode = REBOOT_COLD;
 377                        break;
 378
 379                case 'h':
 380                        reboot_mode = REBOOT_HARD;
 381                        break;
 382
 383                case 's':
 384                        if (isdigit(*(str+1)))
 385                                reboot_cpu = simple_strtoul(str+1, NULL, 0);
 386                        else if (str[1] == 'm' && str[2] == 'p' &&
 387                                                        isdigit(*(str+3)))
 388                                reboot_cpu = simple_strtoul(str+3, NULL, 0);
 389                        else
 390                                reboot_mode = REBOOT_SOFT;
 391                        break;
 392
 393                case 'g':
 394                        reboot_mode = REBOOT_GPIO;
 395                        break;
 396
 397                case 'b':
 398                case 'a':
 399                case 'k':
 400                case 't':
 401                case 'e':
 402                case 'p':
 403                        reboot_type = *str;
 404                        break;
 405
 406                case 'f':
 407                        reboot_force = 1;
 408                        break;
 409                }
 410
 411                str = strchr(str, ',');
 412                if (str)
 413                        str++;
 414                else
 415                        break;
 416        }
 417        return 1;
 418}
 419__setup("reboot=", reboot_setup);
 420
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.