This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / x86_64 / kernel / genapic-xen.c
1 /*
2  * Copyright 2004 James Cleverdon, IBM.
3  * Subject to the GNU Public License, v.2
4  *
5  * Generic APIC sub-arch probe layer.
6  *
7  * Hacked for x86-64 by James Cleverdon from i386 architecture code by
8  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
9  * James Cleverdon.
10  */
11 #include <linux/config.h>
12 #include <linux/threads.h>
13 #include <linux/cpumask.h>
14 #include <linux/string.h>
15 #include <linux/kernel.h>
16 #include <linux/ctype.h>
17 #include <linux/init.h>
18 #include <linux/module.h>
19
20 #include <asm/smp.h>
21 #include <asm/ipi.h>
22
23 #if defined(CONFIG_ACPI)
24 #include <acpi/acpi_bus.h>
25 #endif
26
27 /* which logical CPU number maps to which CPU (physical APIC ID) */
28 u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
29 EXPORT_SYMBOL(x86_cpu_to_apicid);
30 u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
31
32 extern struct genapic apic_cluster;
33 extern struct genapic apic_flat;
34 extern struct genapic apic_physflat;
35
36 #ifndef CONFIG_XEN
37 struct genapic *genapic = &apic_flat;
38 #else
39 extern struct genapic apic_xen;
40 struct genapic *genapic = &apic_xen;
41 #endif
42
43
44 /*
45  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
46  */
47 void __init clustered_apic_check(void)
48 {
49 #ifndef CONFIG_XEN
50         long i;
51         u8 clusters, max_cluster;
52         u8 id;
53         u8 cluster_cnt[NUM_APIC_CLUSTERS];
54         int max_apic = 0;
55
56 #if defined(CONFIG_ACPI)
57         /*
58          * Some x86_64 machines use physical APIC mode regardless of how many
59          * procs/clusters are present (x86_64 ES7000 is an example).
60          */
61         if (acpi_fadt.revision > FADT2_REVISION_ID)
62                 if (acpi_fadt.force_apic_physical_destination_mode) {
63                         genapic = &apic_cluster;
64                         goto print;
65                 }
66 #endif
67
68         memset(cluster_cnt, 0, sizeof(cluster_cnt));
69         for (i = 0; i < NR_CPUS; i++) {
70                 id = bios_cpu_apicid[i];
71                 if (id == BAD_APICID)
72                         continue;
73                 if (id > max_apic)
74                         max_apic = id;
75                 cluster_cnt[APIC_CLUSTERID(id)]++;
76         }
77
78         /* Don't use clustered mode on AMD platforms. */
79         if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
80                 genapic = &apic_physflat;
81 #ifndef CONFIG_HOTPLUG_CPU
82                 /* In the CPU hotplug case we cannot use broadcast mode
83                    because that opens a race when a CPU is removed.
84                    Stay at physflat mode in this case.
85                    It is bad to do this unconditionally though. Once
86                    we have ACPI platform support for CPU hotplug
87                    we should detect hotplug capablity from ACPI tables and
88                    only do this when really needed. -AK */
89                 if (max_apic <= 8)
90                         genapic = &apic_flat;
91 #endif
92                 goto print;
93         }
94
95         clusters = 0;
96         max_cluster = 0;
97
98         for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
99                 if (cluster_cnt[i] > 0) {
100                         ++clusters;
101                         if (cluster_cnt[i] > max_cluster)
102                                 max_cluster = cluster_cnt[i];
103                 }
104         }
105
106         /*
107          * If we have clusters <= 1 and CPUs <= 8 in cluster 0, then flat mode,
108          * else if max_cluster <= 4 and cluster_cnt[15] == 0, clustered logical
109          * else physical mode.
110          * (We don't use lowest priority delivery + HW APIC IRQ steering, so
111          * can ignore the clustered logical case and go straight to physical.)
112          */
113         if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) {
114 #ifdef CONFIG_HOTPLUG_CPU
115                 /* Don't use APIC shortcuts in CPU hotplug to avoid races */
116                 genapic = &apic_physflat;
117 #else
118                 genapic = &apic_flat;
119 #endif
120         } else
121                 genapic = &apic_cluster;
122
123 print:
124 #else
125         /* hardcode to xen apic functions */
126         genapic = &apic_xen;
127 #endif
128         printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
129 }
130
131 /* Same for both flat and clustered. */
132
133 #ifdef CONFIG_XEN
134 extern void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest);
135 #endif
136
137 void send_IPI_self(int vector)
138 {
139 #ifndef CONFIG_XEN
140         __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
141 #else
142         xen_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
143 #endif
144 }