linux/arch/x86/kernel/reboot.c
<<
>>
Prefs
   1#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   2
   3#include <linux/module.h>
   4#include <linux/reboot.h>
   5#include <linux/init.h>
   6#include <linux/pm.h>
   7#include <linux/efi.h>
   8#include <linux/dmi.h>
   9#include <linux/sched.h>
  10#include <linux/tboot.h>
  11#include <linux/delay.h>
  12#include <acpi/reboot.h>
  13#include <asm/io.h>
  14#include <asm/apic.h>
  15#include <asm/desc.h>
  16#include <asm/hpet.h>
  17#include <asm/pgtable.h>
  18#include <asm/proto.h>
  19#include <asm/reboot_fixups.h>
  20#include <asm/reboot.h>
  21#include <asm/pci_x86.h>
  22#include <asm/virtext.h>
  23#include <asm/cpu.h>
  24#include <asm/nmi.h>
  25#include <asm/smp.h>
  26
  27#include <linux/ctype.h>
  28#include <linux/mc146818rtc.h>
  29#include <asm/realmode.h>
  30#include <asm/x86_init.h>
  31
  32/*
  33 * Power off function, if any
  34 */
  35void (*pm_power_off)(void);
  36EXPORT_SYMBOL(pm_power_off);
  37
  38static const struct desc_ptr no_idt = {};
  39
  40/*
  41 * This is set if we need to go through the 'emergency' path.
  42 * When machine_emergency_restart() is called, we may be on
  43 * an inconsistent state and won't be able to do a clean cleanup
  44 */
  45static int reboot_emergency;
  46
  47/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
  48bool port_cf9_safe = false;
  49
  50/*
  51 * Reboot options and system auto-detection code provided by
  52 * Dell Inc. so their systems "just work". :-)
  53 */
  54
  55/*
  56 * Some machines require the "reboot=b" or "reboot=k"  commandline options,
  57 * this quirk makes that automatic.
  58 */
  59static int __init set_bios_reboot(const struct dmi_system_id *d)
  60{
  61        if (reboot_type != BOOT_BIOS) {
  62                reboot_type = BOOT_BIOS;
  63                pr_info("%s series board detected. Selecting %s-method for reboots.\n",
  64                        d->ident, "BIOS");
  65        }
  66        return 0;
  67}
  68
  69void __noreturn machine_real_restart(unsigned int type)
  70{
  71        local_irq_disable();
  72
  73        /*
  74         * Write zero to CMOS register number 0x0f, which the BIOS POST
  75         * routine will recognize as telling it to do a proper reboot.  (Well
  76         * that's what this book in front of me says -- it may only apply to
  77         * the Phoenix BIOS though, it's not clear).  At the same time,
  78         * disable NMIs by setting the top bit in the CMOS address register,
  79         * as we're about to do peculiar things to the CPU.  I'm not sure if
  80         * `outb_p' is needed instead of just `outb'.  Use it to be on the
  81         * safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
  82         */
  83        spin_lock(&rtc_lock);
  84        CMOS_WRITE(0x00, 0x8f);
  85        spin_unlock(&rtc_lock);
  86
  87        /*
  88         * Switch back to the initial page table.
  89         */
  90#ifdef CONFIG_X86_32
  91        load_cr3(initial_page_table);
  92#else
  93        write_cr3(real_mode_header->trampoline_pgd);
  94#endif
  95
  96        /* Jump to the identity-mapped low memory code */
  97#ifdef CONFIG_X86_32
  98        asm volatile("jmpl *%0" : :
  99                     "rm" (real_mode_header->machine_real_restart_asm),
 100                     "a" (type));
 101#else
 102        asm volatile("ljmpl *%0" : :
 103                     "m" (real_mode_header->machine_real_restart_asm),
 104                     "D" (type));
 105#endif
 106        unreachable();
 107}
 108#ifdef CONFIG_APM_MODULE
 109EXPORT_SYMBOL(machine_real_restart);
 110#endif
 111
 112/*
 113 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
 114 */
 115static int __init set_pci_reboot(const struct dmi_system_id *d)
 116{
 117        if (reboot_type != BOOT_CF9) {
 118                reboot_type = BOOT_CF9;
 119                pr_info("%s series board detected. Selecting %s-method for reboots.\n",
 120                        d->ident, "PCI");
 121        }
 122        return 0;
 123}
 124
 125static int __init set_kbd_reboot(const struct dmi_system_id *d)
 126{
 127        if (reboot_type != BOOT_KBD) {
 128                reboot_type = BOOT_KBD;
 129                pr_info("%s series board detected. Selecting %s-method for reboot.\n",
 130                        d->ident, "KBD");
 131        }
 132        return 0;
 133}
 134
 135/*
 136 * This is a single dmi_table handling all reboot quirks.
 137 */
 138static struct dmi_system_id __initdata reboot_dmi_table[] = {
 139
 140        /* Acer */
 141        {       /* Handle reboot issue on Acer Aspire one */
 142                .callback = set_kbd_reboot,
 143                .ident = "Acer Aspire One A110",
 144                .matches = {
 145                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 146                        DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
 147                },
 148        },
 149
 150        /* Apple */
 151        {       /* Handle problems with rebooting on Apple MacBook5 */
 152                .callback = set_pci_reboot,
 153                .ident = "Apple MacBook5",
 154                .matches = {
 155                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
 156                        DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
 157                },
 158        },
 159        {       /* Handle problems with rebooting on Apple MacBookPro5 */
 160                .callback = set_pci_reboot,
 161                .ident = "Apple MacBookPro5",
 162                .matches = {
 163                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
 164                        DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
 165                },
 166        },
 167        {       /* Handle problems with rebooting on Apple Macmini3,1 */
 168                .callback = set_pci_reboot,
 169                .ident = "Apple Macmini3,1",
 170                .matches = {
 171                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
 172                        DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"),
 173                },
 174        },
 175        {       /* Handle problems with rebooting on the iMac9,1. */
 176                .callback = set_pci_reboot,
 177                .ident = "Apple iMac9,1",
 178                .matches = {
 179                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
 180                        DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
 181                },
 182        },
 183
 184        /* ASUS */
 185        {       /* Handle problems with rebooting on ASUS P4S800 */
 186                .callback = set_bios_reboot,
 187                .ident = "ASUS P4S800",
 188                .matches = {
 189                        DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
 190                        DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
 191                },
 192        },
 193
 194        /* Dell */
 195        {       /* Handle problems with rebooting on Dell DXP061 */
 196                .callback = set_bios_reboot,
 197                .ident = "Dell DXP061",
 198                .matches = {
 199                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 200                        DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
 201                },
 202        },
 203        {       /* Handle problems with rebooting on Dell E520's */
 204                .callback = set_bios_reboot,
 205                .ident = "Dell E520",
 206                .matches = {
 207                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 208                        DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
 209                },
 210        },
 211        {       /* Handle problems with rebooting on the Latitude E5410. */
 212                .callback = set_pci_reboot,
 213                .ident = "Dell Latitude E5410",
 214                .matches = {
 215                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 216                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"),
 217                },
 218        },
 219        {       /* Handle problems with rebooting on the Latitude E5420. */
 220                .callback = set_pci_reboot,
 221                .ident = "Dell Latitude E5420",
 222                .matches = {
 223                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 224                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
 225                },
 226        },
 227        {       /* Handle problems with rebooting on the Latitude E6320. */
 228                .callback = set_pci_reboot,
 229                .ident = "Dell Latitude E6320",
 230                .matches = {
 231                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 232                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
 233                },
 234        },
 235        {       /* Handle problems with rebooting on the Latitude E6420. */
 236                .callback = set_pci_reboot,
 237                .ident = "Dell Latitude E6420",
 238                .matches = {
 239                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 240                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
 241                },
 242        },
 243        {       /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
 244                .callback = set_bios_reboot,
 245                .ident = "Dell OptiPlex 330",
 246                .matches = {
 247                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 248                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
 249                        DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
 250                },
 251        },
 252        {       /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
 253                .callback = set_bios_reboot,
 254                .ident = "Dell OptiPlex 360",
 255                .matches = {
 256                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 257                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
 258                        DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
 259                },
 260        },
 261        {       /* Handle problems with rebooting on Dell Optiplex 745's SFF */
 262                .callback = set_bios_reboot,
 263                .ident = "Dell OptiPlex 745",
 264                .matches = {
 265                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 266                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
 267                },
 268        },
 269        {       /* Handle problems with rebooting on Dell Optiplex 745's DFF */
 270                .callback = set_bios_reboot,
 271                .ident = "Dell OptiPlex 745",
 272                .matches = {
 273                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 274                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
 275                        DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
 276                },
 277        },
 278        {       /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
 279                .callback = set_bios_reboot,
 280                .ident = "Dell OptiPlex 745",
 281                .matches = {
 282                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 283                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
 284                        DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
 285                },
 286        },
 287        {       /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
 288                .callback = set_bios_reboot,
 289                .ident = "Dell OptiPlex 760",
 290                .matches = {
 291                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 292                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
 293                        DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
 294                },
 295        },
 296        {       /* Handle problems with rebooting on the OptiPlex 990. */
 297                .callback = set_pci_reboot,
 298                .ident = "Dell OptiPlex 990",
 299                .matches = {
 300                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 301                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
 302                },
 303        },
 304        {       /* Handle problems with rebooting on Dell 300's */
 305                .callback = set_bios_reboot,
 306                .ident = "Dell PowerEdge 300",
 307                .matches = {
 308                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 309                        DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
 310                },
 311        },
 312        {       /* Handle problems with rebooting on Dell 1300's */
 313                .callback = set_bios_reboot,
 314                .ident = "Dell PowerEdge 1300",
 315                .matches = {
 316                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 317                        DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
 318                },
 319        },
 320        {       /* Handle problems with rebooting on Dell 2400's */
 321                .callback = set_bios_reboot,
 322                .ident = "Dell PowerEdge 2400",
 323                .matches = {
 324                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 325                        DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
 326                },
 327        },
 328        {       /* Handle problems with rebooting on the Dell PowerEdge C6100. */
 329                .callback = set_pci_reboot,
 330                .ident = "Dell PowerEdge C6100",
 331                .matches = {
 332                        DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
 333                        DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
 334                },
 335        },
 336        {       /* Handle problems with rebooting on the Precision M6600. */
 337                .callback = set_pci_reboot,
 338                .ident = "Dell Precision M6600",
 339                .matches = {
 340                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 341                        DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
 342                },
 343        },
 344        {       /* Handle problems with rebooting on Dell T5400's */
 345                .callback = set_bios_reboot,
 346                .ident = "Dell Precision T5400",
 347                .matches = {
 348                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 349                        DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
 350                },
 351        },
 352        {       /* Handle problems with rebooting on Dell T7400's */
 353                .callback = set_bios_reboot,
 354                .ident = "Dell Precision T7400",
 355                .matches = {
 356                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 357                        DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
 358                },
 359        },
 360        {       /* Handle problems with rebooting on Dell XPS710 */
 361                .callback = set_bios_reboot,
 362                .ident = "Dell XPS710",
 363                .matches = {
 364                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 365                        DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
 366                },
 367        },
 368
 369        /* Hewlett-Packard */
 370        {       /* Handle problems with rebooting on HP laptops */
 371                .callback = set_bios_reboot,
 372                .ident = "HP Compaq Laptop",
 373                .matches = {
 374                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 375                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
 376                },
 377        },
 378
 379        /* Sony */
 380        {       /* Handle problems with rebooting on Sony VGN-Z540N */
 381                .callback = set_bios_reboot,
 382                .ident = "Sony VGN-Z540N",
 383                .matches = {
 384                        DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 385                        DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
 386                },
 387        },
 388
 389        { }
 390};
 391
 392static int __init reboot_init(void)
 393{
 394        /*
 395         * Only do the DMI check if reboot_type hasn't been overridden
 396         * on the command line
 397         */
 398        if (reboot_default)
 399                dmi_check_system(reboot_dmi_table);
 400        return 0;
 401}
 402core_initcall(reboot_init);
 403
 404static inline void kb_wait(void)
 405{
 406        int i;
 407
 408        for (i = 0; i < 0x10000; i++) {
 409                if ((inb(0x64) & 0x02) == 0)
 410                        break;
 411                udelay(2);
 412        }
 413}
 414
 415static void vmxoff_nmi(int cpu, struct pt_regs *regs)
 416{
 417        cpu_emergency_vmxoff();
 418}
 419
 420/* Use NMIs as IPIs to tell all CPUs to disable virtualization */
 421static void emergency_vmx_disable_all(void)
 422{
 423        /* Just make sure we won't change CPUs while doing this */
 424        local_irq_disable();
 425
 426        /*
 427         * We need to disable VMX on all CPUs before rebooting, otherwise
 428         * we risk hanging up the machine, because the CPU ignore INIT
 429         * signals when VMX is enabled.
 430         *
 431         * We can't take any locks and we may be on an inconsistent
 432         * state, so we use NMIs as IPIs to tell the other CPUs to disable
 433         * VMX and halt.
 434         *
 435         * For safety, we will avoid running the nmi_shootdown_cpus()
 436         * stuff unnecessarily, but we don't have a way to check
 437         * if other CPUs have VMX enabled. So we will call it only if the
 438         * CPU we are running on has VMX enabled.
 439         *
 440         * We will miss cases where VMX is not enabled on all CPUs. This
 441         * shouldn't do much harm because KVM always enable VMX on all
 442         * CPUs anyway. But we can miss it on the small window where KVM
 443         * is still enabling VMX.
 444         */
 445        if (cpu_has_vmx() && cpu_vmx_enabled()) {
 446                /* Disable VMX on this CPU. */
 447                cpu_vmxoff();
 448
 449                /* Halt and disable VMX on the other CPUs */
 450                nmi_shootdown_cpus(vmxoff_nmi);
 451
 452        }
 453}
 454
 455
 456void __attribute__((weak)) mach_reboot_fixups(void)
 457{
 458}
 459
 460/*
 461 * Windows compatible x86 hardware expects the following on reboot:
 462 *
 463 * 1) If the FADT has the ACPI reboot register flag set, try it
 464 * 2) If still alive, write to the keyboard controller
 465 * 3) If still alive, write to the ACPI reboot register again
 466 * 4) If still alive, write to the keyboard controller again
 467 *
 468 * If the machine is still alive at this stage, it gives up. We default to
 469 * following the same pattern, except that if we're still alive after (4) we'll
 470 * try to force a triple fault and then cycle between hitting the keyboard
 471 * controller and doing that
 472 */
 473static void native_machine_emergency_restart(void)
 474{
 475        int i;
 476        int attempt = 0;
 477        int orig_reboot_type = reboot_type;
 478        unsigned short mode;
 479
 480        if (reboot_emergency)
 481                emergency_vmx_disable_all();
 482
 483        tboot_shutdown(TB_SHUTDOWN_REBOOT);
 484
 485        /* Tell the BIOS if we want cold or warm reboot */
 486        mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0;
 487        *((unsigned short *)__va(0x472)) = mode;
 488
 489        for (;;) {
 490                /* Could also try the reset bit in the Hammer NB */
 491                switch (reboot_type) {
 492                case BOOT_KBD:
 493                        mach_reboot_fixups(); /* For board specific fixups */
 494
 495                        for (i = 0; i < 10; i++) {
 496                                kb_wait();
 497                                udelay(50);
 498                                outb(0xfe, 0x64); /* Pulse reset low */
 499                                udelay(50);
 500                        }
 501                        if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
 502                                attempt = 1;
 503                                reboot_type = BOOT_ACPI;
 504                        } else {
 505                                reboot_type = BOOT_TRIPLE;
 506                        }
 507                        break;
 508
 509                case BOOT_TRIPLE:
 510                        load_idt(&no_idt);
 511                        __asm__ __volatile__("int3");
 512
 513                        reboot_type = BOOT_KBD;
 514                        break;
 515
 516                case BOOT_BIOS:
 517                        machine_real_restart(MRR_BIOS);
 518
 519                        reboot_type = BOOT_KBD;
 520                        break;
 521
 522                case BOOT_ACPI:
 523                        acpi_reboot();
 524                        reboot_type = BOOT_KBD;
 525                        break;
 526
 527                case BOOT_EFI:
 528                        if (efi_enabled(EFI_RUNTIME_SERVICES))
 529                                efi.reset_system(reboot_mode == REBOOT_WARM ?
 530                                                 EFI_RESET_WARM :
 531                                                 EFI_RESET_COLD,
 532                                                 EFI_SUCCESS, 0, NULL);
 533                        reboot_type = BOOT_KBD;
 534                        break;
 535
 536                case BOOT_CF9:
 537                        port_cf9_safe = true;
 538                        /* Fall through */
 539
 540                case BOOT_CF9_COND:
 541                        if (port_cf9_safe) {
 542                                u8 reboot_code = reboot_mode == REBOOT_WARM ?
 543                                        0x06 : 0x0E;
 544                                u8 cf9 = inb(0xcf9) & ~reboot_code;
 545                                outb(cf9|2, 0xcf9); /* Request hard reset */
 546                                udelay(50);
 547                                /* Actually do the reset */
 548                                outb(cf9|reboot_code, 0xcf9);
 549                                udelay(50);
 550                        }
 551                        reboot_type = BOOT_KBD;
 552                        break;
 553                }
 554        }
 555}
 556
 557void native_machine_shutdown(void)
 558{
 559        /* Stop the cpus and apics */
 560#ifdef CONFIG_X86_IO_APIC
 561        /*
 562         * Disabling IO APIC before local APIC is a workaround for
 563         * erratum AVR31 in "Intel Atom Processor C2000 Product Family
 564         * Specification Update". In this situation, interrupts that target
 565         * a Logical Processor whose Local APIC is either in the process of
 566         * being hardware disabled or software disabled are neither delivered
 567         * nor discarded. When this erratum occurs, the processor may hang.
 568         *
 569         * Even without the erratum, it still makes sense to quiet IO APIC
 570         * before disabling Local APIC.
 571         */
 572        disable_IO_APIC();
 573#endif
 574
 575#ifdef CONFIG_SMP
 576        /*
 577         * Stop all of the others. Also disable the local irq to
 578         * not receive the per-cpu timer interrupt which may trigger
 579         * scheduler's load balance.
 580         */
 581        local_irq_disable();
 582        stop_other_cpus();
 583#endif
 584
 585        lapic_shutdown();
 586
 587#ifdef CONFIG_HPET_TIMER
 588        hpet_disable();
 589#endif
 590
 591#ifdef CONFIG_X86_64
 592        x86_platform.iommu_shutdown();
 593#endif
 594}
 595
 596static void __machine_emergency_restart(int emergency)
 597{
 598        reboot_emergency = emergency;
 599        machine_ops.emergency_restart();
 600}
 601
 602static void native_machine_restart(char *__unused)
 603{
 604        pr_notice("machine restart\n");
 605
 606        if (!reboot_force)
 607                machine_shutdown();
 608        __machine_emergency_restart(0);
 609}
 610
 611static void native_machine_halt(void)
 612{
 613        /* Stop other cpus and apics */
 614        machine_shutdown();
 615
 616        tboot_shutdown(TB_SHUTDOWN_HALT);
 617
 618        stop_this_cpu(NULL);
 619}
 620
 621static void native_machine_power_off(void)
 622{
 623        if (pm_power_off) {
 624                if (!reboot_force)
 625                        machine_shutdown();
 626                pm_power_off();
 627        }
 628        /* A fallback in case there is no PM info available */
 629        tboot_shutdown(TB_SHUTDOWN_HALT);
 630}
 631
 632struct machine_ops machine_ops = {
 633        .power_off = native_machine_power_off,
 634        .shutdown = native_machine_shutdown,
 635        .emergency_restart = native_machine_emergency_restart,
 636        .restart = native_machine_restart,
 637        .halt = native_machine_halt,
 638#ifdef CONFIG_KEXEC
 639        .crash_shutdown = native_machine_crash_shutdown,
 640#endif
 641};
 642
 643void machine_power_off(void)
 644{
 645        machine_ops.power_off();
 646}
 647
 648void machine_shutdown(void)
 649{
 650        machine_ops.shutdown();
 651}
 652
 653void machine_emergency_restart(void)
 654{
 655        __machine_emergency_restart(1);
 656}
 657
 658void machine_restart(char *cmd)
 659{
 660        machine_ops.restart(cmd);
 661}
 662
 663void machine_halt(void)
 664{
 665        machine_ops.halt();
 666}
 667
 668#ifdef CONFIG_KEXEC
 669void machine_crash_shutdown(struct pt_regs *regs)
 670{
 671        machine_ops.crash_shutdown(regs);
 672}
 673#endif
 674
 675
 676#if defined(CONFIG_SMP)
 677
 678/* This keeps a track of which one is crashing cpu. */
 679static int crashing_cpu;
 680static nmi_shootdown_cb shootdown_callback;
 681
 682static atomic_t waiting_for_crash_ipi;
 683
 684static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
 685{
 686        int cpu;
 687
 688        cpu = raw_smp_processor_id();
 689
 690        /*
 691         * Don't do anything if this handler is invoked on crashing cpu.
 692         * Otherwise, system will completely hang. Crashing cpu can get
 693         * an NMI if system was initially booted with nmi_watchdog parameter.
 694         */
 695        if (cpu == crashing_cpu)
 696                return NMI_HANDLED;
 697        local_irq_disable();
 698
 699        shootdown_callback(cpu, regs);
 700
 701        atomic_dec(&waiting_for_crash_ipi);
 702        /* Assume hlt works */
 703        halt();
 704        for (;;)
 705                cpu_relax();
 706
 707        return NMI_HANDLED;
 708}
 709
 710static void smp_send_nmi_allbutself(void)
 711{
 712        apic->send_IPI_allbutself(NMI_VECTOR);
 713}
 714
 715/*
 716 * Halt all other CPUs, calling the specified function on each of them
 717 *
 718 * This function can be used to halt all other CPUs on crash
 719 * or emergency reboot time. The function passed as parameter
 720 * will be called inside a NMI handler on all CPUs.
 721 */
 722void nmi_shootdown_cpus(nmi_shootdown_cb callback)
 723{
 724        unsigned long msecs;
 725        local_irq_disable();
 726
 727        /* Make a note of crashing cpu. Will be used in NMI callback. */
 728        crashing_cpu = safe_smp_processor_id();
 729
 730        shootdown_callback = callback;
 731
 732        atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
 733        /* Would it be better to replace the trap vector here? */
 734        if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
 735                                 NMI_FLAG_FIRST, "crash"))
 736                return;         /* Return what? */
 737        /*
 738         * Ensure the new callback function is set before sending
 739         * out the NMI
 740         */
 741        wmb();
 742
 743        smp_send_nmi_allbutself();
 744
 745        msecs = 1000; /* Wait at most a second for the other cpus to stop */
 746        while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
 747                mdelay(1);
 748                msecs--;
 749        }
 750
 751        /* Leave the nmi callback set */
 752}
 753#else /* !CONFIG_SMP */
 754void nmi_shootdown_cpus(nmi_shootdown_cb callback)
 755{
 756        /* No other CPUs to shoot down */
 757}
 758#endif
 759