X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Fkernel%2Fgenapic-xen.c;fp=arch%2Fx86_64%2Fkernel%2Fgenapic-xen.c;h=1903a5c3e9c8aeebcedee57c9e1301bd5a023841;hb=1db395853d4f30d6120458bd279ede1f882a8525;hp=0000000000000000000000000000000000000000;hpb=34a75f0025b9cf803b6a88db032e6ad6950c9313;p=linux-2.6.git diff --git a/arch/x86_64/kernel/genapic-xen.c b/arch/x86_64/kernel/genapic-xen.c new file mode 100644 index 000000000..1903a5c3e --- /dev/null +++ b/arch/x86_64/kernel/genapic-xen.c @@ -0,0 +1,144 @@ +/* + * Copyright 2004 James Cleverdon, IBM. + * Subject to the GNU Public License, v.2 + * + * Generic APIC sub-arch probe layer. + * + * Hacked for x86-64 by James Cleverdon from i386 architecture code by + * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and + * James Cleverdon. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if defined(CONFIG_ACPI) +#include +#endif + +/* which logical CPU number maps to which CPU (physical APIC ID) */ +u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; +EXPORT_SYMBOL(x86_cpu_to_apicid); +u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; + +extern struct genapic apic_cluster; +extern struct genapic apic_flat; +extern struct genapic apic_physflat; + +#ifndef CONFIG_XEN +struct genapic *genapic = &apic_flat; +#else +extern struct genapic apic_xen; +struct genapic *genapic = &apic_xen; +#endif + + +/* + * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. + */ +void __init clustered_apic_check(void) +{ +#ifndef CONFIG_XEN + long i; + u8 clusters, max_cluster; + u8 id; + u8 cluster_cnt[NUM_APIC_CLUSTERS]; + int max_apic = 0; + +#if defined(CONFIG_ACPI) + /* + * Some x86_64 machines use physical APIC mode regardless of how many + * procs/clusters are present (x86_64 ES7000 is an example). + */ + if (acpi_fadt.revision > FADT2_REVISION_ID) + if (acpi_fadt.force_apic_physical_destination_mode) { + genapic = &apic_cluster; + goto print; + } +#endif + + memset(cluster_cnt, 0, sizeof(cluster_cnt)); + for (i = 0; i < NR_CPUS; i++) { + id = bios_cpu_apicid[i]; + if (id == BAD_APICID) + continue; + if (id > max_apic) + max_apic = id; + cluster_cnt[APIC_CLUSTERID(id)]++; + } + + /* Don't use clustered mode on AMD platforms. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { + genapic = &apic_physflat; +#ifndef CONFIG_HOTPLUG_CPU + /* In the CPU hotplug case we cannot use broadcast mode + because that opens a race when a CPU is removed. + Stay at physflat mode in this case. + It is bad to do this unconditionally though. Once + we have ACPI platform support for CPU hotplug + we should detect hotplug capablity from ACPI tables and + only do this when really needed. -AK */ + if (max_apic <= 8) + genapic = &apic_flat; +#endif + goto print; + } + + clusters = 0; + max_cluster = 0; + + for (i = 0; i < NUM_APIC_CLUSTERS; i++) { + if (cluster_cnt[i] > 0) { + ++clusters; + if (cluster_cnt[i] > max_cluster) + max_cluster = cluster_cnt[i]; + } + } + + /* + * If we have clusters <= 1 and CPUs <= 8 in cluster 0, then flat mode, + * else if max_cluster <= 4 and cluster_cnt[15] == 0, clustered logical + * else physical mode. + * (We don't use lowest priority delivery + HW APIC IRQ steering, so + * can ignore the clustered logical case and go straight to physical.) + */ + if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) { +#ifdef CONFIG_HOTPLUG_CPU + /* Don't use APIC shortcuts in CPU hotplug to avoid races */ + genapic = &apic_physflat; +#else + genapic = &apic_flat; +#endif + } else + genapic = &apic_cluster; + +print: +#else + /* hardcode to xen apic functions */ + genapic = &apic_xen; +#endif + printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); +} + +/* Same for both flat and clustered. */ + +#ifdef CONFIG_XEN +extern void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest); +#endif + +void send_IPI_self(int vector) +{ +#ifndef CONFIG_XEN + __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); +#else + xen_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); +#endif +}