Merge branches 'x86/apic', 'x86/cleanups', 'x86/cpufeature', 'x86/crashdump', 'x86/debug', 'x86/defconfig', 'x86/detect-hyper', 'x86/doc', 'x86/dumpstack', 'x86/early-printk', 'x86/fpu', 'x86/idle', 'x86/io', 'x86/memory-corruption-check', 'x86/microcode', 'x86/mm', 'x86/mtrr', 'x86/nmi-watchdog', 'x86/pat2', 'x86/pci-ioapic-boot-irq-quirks', 'x86/ptrace', 'x86/quirks', 'x86/reboot', 'x86/setup-memory', 'x86/signal', 'x86/sparse-fixes', 'x86/time', 'x86/uv' and 'x86/xen' into x86/core
This commit is contained in:
parent
3d44cc3e01
1ccedb7cdb
34945ede31
d437797406
c415b3dce3
beeb4195cb
f269b07e86
4e42ebd57b
e1286f2c68
878719e831
fd28a5b58d
adf77bac05
8f2466f45f
93093d099e
bb5574608a
f34a10bd9f
b6fd6f2673
30604bb410
5b9a0e14eb
67bac792cd
7a9787e1eb
f4166c54bf
69b88afa8d
8daa19051e
3e1e9002aa
8403295e0f
4db646b1af
205516c12d
c8182f0016
ecbf29cdb3
commit
fa623d1b02
@@ -21,6 +21,9 @@
|
||||
# include <asm/iommu.h>
|
||||
#endif
|
||||
|
||||
#include <mach_ipi.h>
|
||||
|
||||
|
||||
/*
|
||||
* Power off function, if any
|
||||
*/
|
||||
@@ -36,7 +39,10 @@ int reboot_force;
|
||||
static int reboot_cpu = -1;
|
||||
#endif
|
||||
|
||||
/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old]
|
||||
/* 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]
|
||||
warm Don't set the cold reboot flag
|
||||
cold Set the cold reboot flag
|
||||
bios Reboot by jumping through the BIOS (only for X86_32)
|
||||
@@ -45,6 +51,7 @@ static int reboot_cpu = -1;
|
||||
kbd Use the keyboard controller. cold reset (default)
|
||||
acpi Use the RESET_REG in the FADT
|
||||
efi Use efi reset_system runtime service
|
||||
pci Use the so-called "PCI reset register", CF9
|
||||
force Avoid anything that could hang.
|
||||
*/
|
||||
static int __init reboot_setup(char *str)
|
||||
@@ -79,6 +86,7 @@ static int __init reboot_setup(char *str)
|
||||
case 'k':
|
||||
case 't':
|
||||
case 'e':
|
||||
case 'p':
|
||||
reboot_type = *str;
|
||||
break;
|
||||
|
||||
@@ -404,12 +412,27 @@ static void native_machine_emergency_restart(void)
|
||||
reboot_type = BOOT_KBD;
|
||||
break;
|
||||
|
||||
|
||||
case BOOT_EFI:
|
||||
if (efi_enabled)
|
||||
efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD,
|
||||
efi.reset_system(reboot_mode ?
|
||||
EFI_RESET_WARM :
|
||||
EFI_RESET_COLD,
|
||||
EFI_SUCCESS, 0, NULL);
|
||||
reboot_type = BOOT_KBD;
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
reboot_type = BOOT_KBD;
|
||||
break;
|
||||
}
|
||||
@@ -470,6 +493,11 @@ static void native_machine_restart(char *__unused)
|
||||
|
||||
static void native_machine_halt(void)
|
||||
{
|
||||
/* stop other cpus and apics */
|
||||
machine_shutdown();
|
||||
|
||||
/* stop this cpu */
|
||||
stop_this_cpu(NULL);
|
||||
}
|
||||
|
||||
static void native_machine_power_off(void)
|
||||
@@ -523,3 +551,95 @@ void machine_crash_shutdown(struct pt_regs *regs)
|
||||
machine_ops.crash_shutdown(regs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
cpumask_t mask = cpu_online_map;
|
||||
cpu_clear(safe_smp_processor_id(), mask);
|
||||
if (!cpus_empty(mask))
|
||||
send_IPI_mask(mask, 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
|
||||
|
Reference in New Issue
Block a user