5a6 > #include 14a16,18 > #include > #include > #include 17d20 < # include 30c33 < static long no_idt[3]; --- > static const struct desc_ptr no_idt = {}; 39c42,51 < /* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] --- > /* This is set if we need to go through the 'emergency' path. > * When machine_emergency_restart() is called, we may be on > * an inconsistent state and won't be able to do a clean cleanup > */ > static int reboot_emergency; > > /* This is set by the PCI code if either type 1 or type 2 PCI is detected */ > bool port_cf9_safe = false; > > /* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] 47a60 > pci Use the so-called "PCI reset register", CF9 81a95 > case 'p': 171a186,203 > { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ > .callback = set_bios_reboot, > .ident = "Dell OptiPlex 330", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"), > DMI_MATCH(DMI_BOARD_NAME, "0KP561"), > }, > }, > { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */ > .callback = set_bios_reboot, > .ident = "Dell OptiPlex 360", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"), > DMI_MATCH(DMI_BOARD_NAME, "0T656F"), > }, > }, 179a212,219 > { /* Handle problems with rebooting on Dell T5400's */ > .callback = set_bios_reboot, > .ident = "Dell Precision T5400", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"), > }, > }, 187a228,259 > { /* Handle problems with rebooting on Dell XPS710 */ > .callback = set_bios_reboot, > .ident = "Dell XPS710", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"), > }, > }, > { /* Handle problems with rebooting on Dell DXP061 */ > .callback = set_bios_reboot, > .ident = "Dell DXP061", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"), > }, > }, > { /* Handle problems with rebooting on Sony VGN-Z540N */ > .callback = set_bios_reboot, > .ident = "Sony VGN-Z540N", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), > DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"), > }, > }, > { /* Handle problems with rebooting on CompuLab SBC-FITPC2 */ > .callback = set_bios_reboot, > .ident = "CompuLab SBC-FITPC2", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"), > DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"), > }, > }, 204c276 < static unsigned long long --- > static const unsigned long long 208,209c280,281 < 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ < 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ --- > 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ > 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ 212c284 < static struct desc_ptr --- > static const struct desc_ptr 234c306 < static unsigned char real_mode_switch [] = --- > static const unsigned char real_mode_switch [] = 248c320 < static unsigned char jump_to_bios [] = --- > static const unsigned char jump_to_bios [] = 258c330 < void machine_real_restart(unsigned char *code, int length) --- > void machine_real_restart(const unsigned char *code, int length) 334a407,446 > /* > * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot > */ > static int __init set_pci_reboot(const struct dmi_system_id *d) > { > if (reboot_type != BOOT_CF9) { > reboot_type = BOOT_CF9; > printk(KERN_INFO "%s series board detected. " > "Selecting PCI-method for reboots.\n", d->ident); > } > return 0; > } > > static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { > { /* Handle problems with rebooting on Apple MacBook5 */ > .callback = set_pci_reboot, > .ident = "Apple MacBook5", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"), > }, > }, > { /* Handle problems with rebooting on Apple MacBookPro5 */ > .callback = set_pci_reboot, > .ident = "Apple MacBookPro5", > .matches = { > DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), > DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"), > }, > }, > { } > }; > > static int __init pci_reboot_init(void) > { > dmi_check_system(pci_reboot_dmi_table); > return 0; > } > core_initcall(pci_reboot_init); > 345a458,499 > static void vmxoff_nmi(int cpu, struct die_args *args) > { > cpu_emergency_vmxoff(); > } > > /* Use NMIs as IPIs to tell all CPUs to disable virtualization > */ > static void emergency_vmx_disable_all(void) > { > /* Just make sure we won't change CPUs while doing this */ > local_irq_disable(); > > /* We need to disable VMX on all CPUs before rebooting, otherwise > * we risk hanging up the machine, because the CPU ignore INIT > * signals when VMX is enabled. > * > * We can't take any locks and we may be on an inconsistent > * state, so we use NMIs as IPIs to tell the other CPUs to disable > * VMX and halt. > * > * For safety, we will avoid running the nmi_shootdown_cpus() > * stuff unnecessarily, but we don't have a way to check > * if other CPUs have VMX enabled. So we will call it only if the > * CPU we are running on has VMX enabled. > * > * We will miss cases where VMX is not enabled on all CPUs. This > * shouldn't do much harm because KVM always enable VMX on all > * CPUs anyway. But we can miss it on the small window where KVM > * is still enabling VMX. > */ > if (cpu_has_vmx() && cpu_vmx_enabled()) { > /* Disable VMX on this CPU. > */ > cpu_vmxoff(); > > /* Halt and disable VMX on the other CPUs */ > nmi_shootdown_cpus(vmxoff_nmi); > > } > } > > 353a508,510 > if (reboot_emergency) > emergency_vmx_disable_all(); > 371c528 < load_idt((const struct desc_ptr *)&no_idt); --- > load_idt(&no_idt); 390d546 < 393c549,551 < efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, --- > efi.reset_system(reboot_mode ? > EFI_RESET_WARM : > EFI_RESET_COLD, 394a553,554 > reboot_type = BOOT_KBD; > break; 395a556,567 > case BOOT_CF9: > port_cf9_safe = true; > /* fall through */ > > case BOOT_CF9_COND: > if (port_cf9_safe) { > u8 cf9 = inb(0xcf9) & ~6; > outb(cf9|2, 0xcf9); /* Request hard reset */ > udelay(50); > outb(cf9|6, 0xcf9); /* Actually do the reset */ > udelay(50); > } 406d577 < int reboot_cpu_id; 409c580 < reboot_cpu_id = 0; --- > int reboot_cpu_id = 0; 413c584 < if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) && --- > if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && 423c594 < set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id)); --- > set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id)); 445a617,622 > static void __machine_emergency_restart(int emergency) > { > reboot_emergency = emergency; > machine_ops.emergency_restart(); > } > 452c629 < machine_emergency_restart(); --- > __machine_emergency_restart(0); 456a634,638 > /* stop other cpus and apics */ > machine_shutdown(); > > /* stop this cpu */ > stop_this_cpu(NULL); 491c673 < machine_ops.emergency_restart(); --- > __machine_emergency_restart(1); 509a692,780 > > > #if defined(CONFIG_SMP) > > /* This keeps a track of which one is crashing cpu. */ > static int crashing_cpu; > static nmi_shootdown_cb shootdown_callback; > > static atomic_t waiting_for_crash_ipi; > > static int crash_nmi_callback(struct notifier_block *self, > unsigned long val, void *data) > { > int cpu; > > if (val != DIE_NMI_IPI) > return NOTIFY_OK; > > cpu = raw_smp_processor_id(); > > /* Don't do anything if this handler is invoked on crashing cpu. > * Otherwise, system will completely hang. Crashing cpu can get > * an NMI if system was initially booted with nmi_watchdog parameter. > */ > if (cpu == crashing_cpu) > return NOTIFY_STOP; > local_irq_disable(); > > shootdown_callback(cpu, (struct die_args *)data); > > atomic_dec(&waiting_for_crash_ipi); > /* Assume hlt works */ > halt(); > for (;;) > cpu_relax(); > > return 1; > } > > static void smp_send_nmi_allbutself(void) > { > apic->send_IPI_allbutself(NMI_VECTOR); > } > > static struct notifier_block crash_nmi_nb = { > .notifier_call = crash_nmi_callback, > }; > > /* Halt all other CPUs, calling the specified function on each of them > * > * This function can be used to halt all other CPUs on crash > * or emergency reboot time. The function passed as parameter > * will be called inside a NMI handler on all CPUs. > */ > void nmi_shootdown_cpus(nmi_shootdown_cb callback) > { > unsigned long msecs; > local_irq_disable(); > > /* Make a note of crashing cpu. Will be used in NMI callback.*/ > crashing_cpu = safe_smp_processor_id(); > > shootdown_callback = callback; > > atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); > /* Would it be better to replace the trap vector here? */ > if (register_die_notifier(&crash_nmi_nb)) > return; /* return what? */ > /* Ensure the new callback function is set before sending > * out the NMI > */ > wmb(); > > smp_send_nmi_allbutself(); > > msecs = 1000; /* Wait at most a second for the other cpus to stop */ > while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { > mdelay(1); > msecs--; > } > > /* Leave the nmi callback set */ > } > #else /* !CONFIG_SMP */ > void nmi_shootdown_cpus(nmi_shootdown_cb callback) > { > /* No other CPUs to shoot down */ > } > #endif