| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright 2004 James Cleverdon, IBM. | 
					
						
							|  |  |  |  * Subject to the GNU Public License, v.2 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  |  * Flat APIC subarch code. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Hacked for x86-64 by James Cleverdon from i386 architecture code by | 
					
						
							|  |  |  |  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and | 
					
						
							|  |  |  |  * James Cleverdon. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:21 +02:00
										 |  |  | #include <linux/errno.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/threads.h>
 | 
					
						
							|  |  |  | #include <linux/cpumask.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/ctype.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							| 
									
										
										
										
											2008-07-10 11:16:48 -07:00
										 |  |  | #include <linux/hardirq.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/smp.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-17 13:58:15 +01:00
										 |  |  | #include <asm/apic.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-16 23:02:14 -08:00
										 |  |  | #include <asm/ipi.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-21 22:08:21 -07:00
										 |  |  | #ifdef CONFIG_ACPI
 | 
					
						
							|  |  |  | #include <acpi/acpi_bus.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-12 11:44:08 +02:00
										 |  |  | static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 
					
						
							| 
									
										
										
										
											2008-07-21 22:08:21 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static const struct cpumask *flat_target_cpus(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	return cpu_online_mask; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static void flat_vector_allocation_domain(int cpu, struct cpumask *retmask) | 
					
						
							| 
									
										
										
										
											2006-10-08 07:47:55 -06:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* Careful. Some cpus do not strictly honor the set of cpus
 | 
					
						
							|  |  |  | 	 * specified in the interrupt destination when using lowest | 
					
						
							|  |  |  | 	 * priority interrupt delivery mode. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * In particular there was a hyperthreading cpu observed to | 
					
						
							|  |  |  | 	 * deliver interrupts to the wrong hyperthread when only one | 
					
						
							|  |  |  | 	 * hyperthread was specified in the interrupt desitination. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	cpumask_clear(retmask); | 
					
						
							|  |  |  | 	cpumask_bits(retmask)[0] = APIC_ALL_CPUS; | 
					
						
							| 
									
										
										
										
											2006-10-08 07:47:55 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Set up the logical destination ID. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Intel recommends to set DFR, LDR and TPR before enabling | 
					
						
							|  |  |  |  * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel | 
					
						
							|  |  |  |  * document number 292116).  So here it goes... | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void flat_init_apic_ldr(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long val; | 
					
						
							|  |  |  | 	unsigned long num, id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	num = smp_processor_id(); | 
					
						
							|  |  |  | 	id = 1UL << num; | 
					
						
							| 
									
										
										
										
											2005-09-12 18:49:23 +02:00
										 |  |  | 	apic_write(APIC_DFR, APIC_DFR_FLAT); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; | 
					
						
							|  |  |  | 	val |= SET_APIC_LOGICAL_ID(id); | 
					
						
							| 
									
										
										
										
											2005-09-12 18:49:23 +02:00
										 |  |  | 	apic_write(APIC_LDR, val); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | static inline void _flat_send_IPI_mask(unsigned long mask, int vector) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-26 10:52:33 +02:00
										 |  |  | 	local_irq_save(flags); | 
					
						
							| 
									
										
										
										
											2009-01-28 15:42:24 +01:00
										 |  |  | 	__default_send_IPI_dest_field(mask, vector, apic->dest_logical); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	local_irq_restore(flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector) | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	unsigned long mask = cpumask_bits(cpumask)[0]; | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_flat_send_IPI_mask(mask, vector); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 15:42:24 +01:00
										 |  |  | static void | 
					
						
							|  |  |  |  flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	unsigned long mask = cpumask_bits(cpumask)[0]; | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 	int cpu = smp_processor_id(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cpu < BITS_PER_LONG) | 
					
						
							|  |  |  | 		clear_bit(cpu, &mask); | 
					
						
							| 
									
										
										
										
											2009-01-28 15:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 	_flat_send_IPI_mask(mask, vector); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-25 14:55:03 -07:00
										 |  |  | static void flat_send_IPI_allbutself(int vector) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 	int cpu = smp_processor_id(); | 
					
						
							| 
									
										
										
										
											2006-06-26 13:59:56 +02:00
										 |  |  | #ifdef	CONFIG_HOTPLUG_CPU
 | 
					
						
							|  |  |  | 	int hotplug = 1; | 
					
						
							| 
									
										
										
										
											2005-09-09 13:01:52 -07:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2006-06-26 13:59:56 +02:00
										 |  |  | 	int hotplug = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (hotplug || vector == NMI_VECTOR) { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 		if (!cpumask_equal(cpu_online_mask, cpumask_of(cpu))) { | 
					
						
							|  |  |  | 			unsigned long mask = cpumask_bits(cpu_online_mask)[0]; | 
					
						
							| 
									
										
										
										
											2006-01-11 22:43:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 			if (cpu < BITS_PER_LONG) | 
					
						
							|  |  |  | 				clear_bit(cpu, &mask); | 
					
						
							| 
									
										
										
										
											2005-09-09 13:01:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 			_flat_send_IPI_mask(mask, vector); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-06-26 13:59:56 +02:00
										 |  |  | 	} else if (num_online_cpus() > 1) { | 
					
						
							| 
									
										
										
										
											2009-01-28 15:42:24 +01:00
										 |  |  | 		__default_send_IPI_shortcut(APIC_DEST_ALLBUT, | 
					
						
							|  |  |  | 					    vector, apic->dest_logical); | 
					
						
							| 
									
										
										
										
											2006-06-26 13:59:56 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-06-25 14:55:02 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void flat_send_IPI_all(int vector) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-28 15:42:24 +01:00
										 |  |  | 	if (vector == NMI_VECTOR) { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 		flat_send_IPI_mask(cpu_online_mask, vector); | 
					
						
							| 
									
										
										
										
											2009-01-28 15:42:24 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		__default_send_IPI_shortcut(APIC_DEST_ALLINC, | 
					
						
							|  |  |  | 					    vector, apic->dest_logical); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-06-25 14:55:02 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 14:08:38 +01:00
										 |  |  | static unsigned int flat_get_apic_id(unsigned long x) | 
					
						
							| 
									
										
										
										
											2008-07-12 01:01:20 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned int id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	id = (((x)>>24) & 0xFFu); | 
					
						
							| 
									
										
										
										
											2009-01-28 14:08:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-12 01:01:20 -07:00
										 |  |  | 	return id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned long set_apic_id(unsigned int id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	x = ((id & 0xFFu)<<24); | 
					
						
							|  |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-10 11:16:48 -07:00
										 |  |  | static unsigned int read_xapic_id(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int id; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 14:08:38 +01:00
										 |  |  | 	id = flat_get_apic_id(apic_read(APIC_ID)); | 
					
						
							| 
									
										
										
										
											2008-07-10 11:16:48 -07:00
										 |  |  | 	return id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static int flat_apic_id_registered(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-10 11:16:48 -07:00
										 |  |  | 	return physid_isset(read_xapic_id(), phys_cpu_present_map); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 13:31:22 +01:00
										 |  |  | static int flat_phys_pkg_id(int initial_apic_id, int index_msb) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-15 13:05:16 -07:00
										 |  |  | 	return initial_apic_id >> index_msb; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 16:28:46 +01:00
										 |  |  | struct apic apic_flat =  { | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.name				= "flat", | 
					
						
							|  |  |  | 	.probe				= NULL, | 
					
						
							|  |  |  | 	.acpi_madt_oem_check		= flat_acpi_madt_oem_check, | 
					
						
							|  |  |  | 	.apic_id_registered		= flat_apic_id_registered, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 04:02:31 +01:00
										 |  |  | 	.irq_delivery_mode		= dest_LowestPrio, | 
					
						
							| 
									
										
										
										
											2009-01-28 05:13:04 +01:00
										 |  |  | 	.irq_dest_mode			= 1, /* logical */ | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.target_cpus			= flat_target_cpus, | 
					
						
							| 
									
										
										
										
											2009-01-28 05:08:44 +01:00
										 |  |  | 	.disable_esr			= 0, | 
					
						
							| 
									
										
										
										
											2009-01-28 05:29:25 +01:00
										 |  |  | 	.dest_logical			= APIC_DEST_LOGICAL, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.check_apicid_used		= NULL, | 
					
						
							|  |  |  | 	.check_apicid_present		= NULL, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.vector_allocation_domain	= flat_vector_allocation_domain, | 
					
						
							|  |  |  | 	.init_apic_ldr			= flat_init_apic_ldr, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.ioapic_phys_id_map		= NULL, | 
					
						
							|  |  |  | 	.setup_apic_routing		= NULL, | 
					
						
							|  |  |  | 	.multi_timer_check		= NULL, | 
					
						
							|  |  |  | 	.apicid_to_node			= NULL, | 
					
						
							|  |  |  | 	.cpu_to_logical_apicid		= NULL, | 
					
						
							| 
									
										
										
										
											2009-01-28 06:50:47 +01:00
										 |  |  | 	.cpu_present_to_apicid		= default_cpu_present_to_apicid, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.apicid_to_cpu_present		= NULL, | 
					
						
							|  |  |  | 	.setup_portio_remap		= NULL, | 
					
						
							| 
									
										
										
										
											2009-01-28 12:43:18 +01:00
										 |  |  | 	.check_phys_apicid_present	= default_check_phys_apicid_present, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.enable_apic_mode		= NULL, | 
					
						
							| 
									
										
										
										
											2009-01-28 13:31:22 +01:00
										 |  |  | 	.phys_pkg_id			= flat_phys_pkg_id, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.mps_oem_check			= NULL, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 14:08:38 +01:00
										 |  |  | 	.get_apic_id			= flat_get_apic_id, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.set_apic_id			= set_apic_id, | 
					
						
							|  |  |  | 	.apic_id_mask			= 0xFFu << 24, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-24 14:16:30 -07:00
										 |  |  | 	.cpu_mask_to_apicid		= default_cpu_mask_to_apicid, | 
					
						
							|  |  |  | 	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.send_IPI_mask			= flat_send_IPI_mask, | 
					
						
							|  |  |  | 	.send_IPI_mask_allbutself	= flat_send_IPI_mask_allbutself, | 
					
						
							|  |  |  | 	.send_IPI_allbutself		= flat_send_IPI_allbutself, | 
					
						
							|  |  |  | 	.send_IPI_all			= flat_send_IPI_all, | 
					
						
							|  |  |  | 	.send_IPI_self			= apic_send_IPI_self, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 16:15:16 +01:00
										 |  |  | 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW, | 
					
						
							|  |  |  | 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.wait_for_init_deassert		= NULL, | 
					
						
							|  |  |  | 	.smp_callin_clear_local_apic	= NULL, | 
					
						
							| 
									
										
										
										
											2009-04-08 08:00:01 -07:00
										 |  |  | 	.inquire_remote_apic		= default_inquire_remote_apic, | 
					
						
							| 
									
										
										
										
											2009-02-16 23:02:14 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.read				= native_apic_mem_read, | 
					
						
							|  |  |  | 	.write				= native_apic_mem_write, | 
					
						
							|  |  |  | 	.icr_read			= native_apic_icr_read, | 
					
						
							|  |  |  | 	.icr_write			= native_apic_icr_write, | 
					
						
							|  |  |  | 	.wait_icr_idle			= native_apic_wait_icr_idle, | 
					
						
							|  |  |  | 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2009-11-20 14:20:05 +01:00
										 |  |  |  * Physflat mode is used when there are more than 8 CPUs on a system. | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  |  * We cannot use logical delivery in this case because the mask | 
					
						
							|  |  |  |  * overflows, so use physical mode. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-10-12 11:44:09 +02:00
										 |  |  | static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 
					
						
							| 
									
										
										
										
											2008-07-21 22:08:21 -07:00
										 |  |  | { | 
					
						
							|  |  |  | #ifdef CONFIG_ACPI
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Quirk: some x86_64 machines can only use physical APIC mode | 
					
						
							|  |  |  | 	 * regardless of how many processors are present (x86_64 ES7000 | 
					
						
							|  |  |  | 	 * is an example). | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2009-05-09 23:47:42 -07:00
										 |  |  | 	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && | 
					
						
							| 
									
										
										
										
											2008-09-04 20:57:11 +02:00
										 |  |  | 		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) { | 
					
						
							|  |  |  | 		printk(KERN_DEBUG "system APIC only can use physical flat"); | 
					
						
							| 
									
										
										
										
											2008-07-21 22:08:21 -07:00
										 |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2008-09-04 20:57:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-01-18 12:10:48 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) { | 
					
						
							|  |  |  | 		printk(KERN_DEBUG "IBM Summit detected, will use apic physical"); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-21 22:08:21 -07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static const struct cpumask *physflat_target_cpus(void) | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	return cpu_online_mask; | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask) | 
					
						
							| 
									
										
										
										
											2006-10-08 07:47:55 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	cpumask_clear(retmask); | 
					
						
							|  |  |  | 	cpumask_set_cpu(cpu, retmask); | 
					
						
							| 
									
										
										
										
											2006-10-08 07:47:55 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector) | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-29 19:31:49 -08:00
										 |  |  | 	default_send_IPI_mask_sequence_phys(cpumask, vector); | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask, | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | 					      int vector) | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-29 19:31:49 -08:00
										 |  |  | 	default_send_IPI_mask_allbutself_phys(cpumask, vector); | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-01-11 22:43:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:52 -08:00
										 |  |  | static void physflat_send_IPI_allbutself(int vector) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-29 19:31:49 -08:00
										 |  |  | 	default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void physflat_send_IPI_all(int vector) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	physflat_send_IPI_mask(cpu_online_mask, vector); | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | static unsigned int physflat_cpu_mask_to_apicid(const struct cpumask *cpumask) | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int cpu; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * We're using fixed IRQ delivery, can only return one phys APIC ID. | 
					
						
							|  |  |  | 	 * May as well be the first. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:59 -08:00
										 |  |  | 	cpu = cpumask_first(cpumask); | 
					
						
							| 
									
										
										
										
											2008-07-18 18:11:30 -07:00
										 |  |  | 	if ((unsigned)cpu < nr_cpu_ids) | 
					
						
							| 
									
										
										
										
											2007-10-19 20:35:03 +02:00
										 |  |  | 		return per_cpu(x86_cpu_to_apicid, cpu); | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		return BAD_APICID; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:55 -08:00
										 |  |  | static unsigned int | 
					
						
							|  |  |  | physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 
					
						
							|  |  |  | 				const struct cpumask *andmask) | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:54 -08:00
										 |  |  | { | 
					
						
							|  |  |  | 	int cpu; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * We're using fixed IRQ delivery, can only return one phys APIC ID. | 
					
						
							|  |  |  | 	 * May as well be the first. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2009-01-28 15:20:18 +01:00
										 |  |  | 	for_each_cpu_and(cpu, cpumask, andmask) { | 
					
						
							| 
									
										
										
										
											2008-12-17 15:21:39 -08:00
										 |  |  | 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-01-28 15:20:18 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-17 18:29:46 -08:00
										 |  |  | 	return per_cpu(x86_cpu_to_apicid, cpu); | 
					
						
							| 
									
										
										
										
											2008-12-16 17:33:54 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 16:28:46 +01:00
										 |  |  | struct apic apic_physflat =  { | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.name				= "physical flat", | 
					
						
							|  |  |  | 	.probe				= NULL, | 
					
						
							|  |  |  | 	.acpi_madt_oem_check		= physflat_acpi_madt_oem_check, | 
					
						
							|  |  |  | 	.apic_id_registered		= flat_apic_id_registered, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 04:02:31 +01:00
										 |  |  | 	.irq_delivery_mode		= dest_Fixed, | 
					
						
							| 
									
										
										
										
											2009-01-28 05:13:04 +01:00
										 |  |  | 	.irq_dest_mode			= 0, /* physical */ | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.target_cpus			= physflat_target_cpus, | 
					
						
							| 
									
										
										
										
											2009-01-28 05:08:44 +01:00
										 |  |  | 	.disable_esr			= 0, | 
					
						
							| 
									
										
										
										
											2009-01-28 05:29:25 +01:00
										 |  |  | 	.dest_logical			= 0, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.check_apicid_used		= NULL, | 
					
						
							|  |  |  | 	.check_apicid_present		= NULL, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.vector_allocation_domain	= physflat_vector_allocation_domain, | 
					
						
							|  |  |  | 	/* not needed, but shouldn't hurt: */ | 
					
						
							|  |  |  | 	.init_apic_ldr			= flat_init_apic_ldr, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.ioapic_phys_id_map		= NULL, | 
					
						
							|  |  |  | 	.setup_apic_routing		= NULL, | 
					
						
							|  |  |  | 	.multi_timer_check		= NULL, | 
					
						
							|  |  |  | 	.apicid_to_node			= NULL, | 
					
						
							|  |  |  | 	.cpu_to_logical_apicid		= NULL, | 
					
						
							| 
									
										
										
										
											2009-01-28 06:50:47 +01:00
										 |  |  | 	.cpu_present_to_apicid		= default_cpu_present_to_apicid, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.apicid_to_cpu_present		= NULL, | 
					
						
							|  |  |  | 	.setup_portio_remap		= NULL, | 
					
						
							| 
									
										
										
										
											2009-01-28 12:43:18 +01:00
										 |  |  | 	.check_phys_apicid_present	= default_check_phys_apicid_present, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.enable_apic_mode		= NULL, | 
					
						
							| 
									
										
										
										
											2009-01-28 13:31:22 +01:00
										 |  |  | 	.phys_pkg_id			= flat_phys_pkg_id, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.mps_oem_check			= NULL, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 14:08:38 +01:00
										 |  |  | 	.get_apic_id			= flat_get_apic_id, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.set_apic_id			= set_apic_id, | 
					
						
							| 
									
										
										
										
											2009-01-28 14:59:17 +01:00
										 |  |  | 	.apic_id_mask			= 0xFFu << 24, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.cpu_mask_to_apicid		= physflat_cpu_mask_to_apicid, | 
					
						
							|  |  |  | 	.cpu_mask_to_apicid_and		= physflat_cpu_mask_to_apicid_and, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.send_IPI_mask			= physflat_send_IPI_mask, | 
					
						
							|  |  |  | 	.send_IPI_mask_allbutself	= physflat_send_IPI_mask_allbutself, | 
					
						
							|  |  |  | 	.send_IPI_allbutself		= physflat_send_IPI_allbutself, | 
					
						
							|  |  |  | 	.send_IPI_all			= physflat_send_IPI_all, | 
					
						
							|  |  |  | 	.send_IPI_self			= apic_send_IPI_self, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 16:15:16 +01:00
										 |  |  | 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW, | 
					
						
							|  |  |  | 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH, | 
					
						
							| 
									
										
										
										
											2009-01-28 02:37:01 +01:00
										 |  |  | 	.wait_for_init_deassert		= NULL, | 
					
						
							|  |  |  | 	.smp_callin_clear_local_apic	= NULL, | 
					
						
							| 
									
										
										
										
											2009-04-08 08:00:01 -07:00
										 |  |  | 	.inquire_remote_apic		= default_inquire_remote_apic, | 
					
						
							| 
									
										
										
										
											2009-02-16 23:02:14 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.read				= native_apic_mem_read, | 
					
						
							|  |  |  | 	.write				= native_apic_mem_write, | 
					
						
							|  |  |  | 	.icr_read			= native_apic_icr_read, | 
					
						
							|  |  |  | 	.icr_write			= native_apic_icr_write, | 
					
						
							|  |  |  | 	.wait_icr_idle			= native_apic_wait_icr_idle, | 
					
						
							|  |  |  | 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle, | 
					
						
							| 
									
										
										
										
											2005-07-28 21:15:42 -07:00
										 |  |  | }; |