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