aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/probe_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/probe_32.c')
-rw-r--r--arch/x86/kernel/probe_32.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/arch/x86/kernel/probe_32.c b/arch/x86/kernel/probe_32.c
new file mode 100644
index 000000000000..a6fba6914167
--- /dev/null
+++ b/arch/x86/kernel/probe_32.c
@@ -0,0 +1,248 @@
1/*
2 * Default generic APIC driver. This handles up to 8 CPUs.
3 *
4 * Copyright 2003 Andi Kleen, SuSE Labs.
5 * Subject to the GNU Public License, v.2
6 *
7 * Generic x86 APIC driver probe layer.
8 */
9#include <linux/threads.h>
10#include <linux/cpumask.h>
11#include <linux/string.h>
12#include <linux/kernel.h>
13#include <linux/ctype.h>
14#include <linux/init.h>
15#include <linux/errno.h>
16#include <asm/fixmap.h>
17#include <asm/mpspec.h>
18#include <asm/apicdef.h>
19#include <asm/genapic.h>
20#include <asm/setup.h>
21
22#include <linux/threads.h>
23#include <linux/cpumask.h>
24#include <asm/mpspec.h>
25#include <asm/genapic.h>
26#include <asm/fixmap.h>
27#include <asm/apicdef.h>
28#include <linux/kernel.h>
29#include <linux/string.h>
30#include <linux/smp.h>
31#include <linux/init.h>
32#include <asm/genapic.h>
33#include <asm/ipi.h>
34
35static void default_vector_allocation_domain(int cpu, struct cpumask *retmask)
36{
37 /*
38 * Careful. Some cpus do not strictly honor the set of cpus
39 * specified in the interrupt destination when using lowest
40 * priority interrupt delivery mode.
41 *
42 * In particular there was a hyperthreading cpu observed to
43 * deliver interrupts to the wrong hyperthread when only one
44 * hyperthread was specified in the interrupt desitination.
45 */
46 *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } };
47}
48
49/* should be called last. */
50static int probe_default(void)
51{
52 return 1;
53}
54
55struct genapic apic_default = {
56
57 .name = "default",
58 .probe = probe_default,
59 .acpi_madt_oem_check = NULL,
60 .apic_id_registered = default_apic_id_registered,
61
62 .irq_delivery_mode = dest_LowestPrio,
63 /* logical delivery broadcast to all CPUs: */
64 .irq_dest_mode = 1,
65
66 .target_cpus = default_target_cpus,
67 .disable_esr = 0,
68 .dest_logical = APIC_DEST_LOGICAL,
69 .check_apicid_used = default_check_apicid_used,
70 .check_apicid_present = default_check_apicid_present,
71
72 .vector_allocation_domain = default_vector_allocation_domain,
73 .init_apic_ldr = default_init_apic_ldr,
74
75 .ioapic_phys_id_map = default_ioapic_phys_id_map,
76 .setup_apic_routing = default_setup_apic_routing,
77 .multi_timer_check = NULL,
78 .apicid_to_node = default_apicid_to_node,
79 .cpu_to_logical_apicid = default_cpu_to_logical_apicid,
80 .cpu_present_to_apicid = default_cpu_present_to_apicid,
81 .apicid_to_cpu_present = default_apicid_to_cpu_present,
82 .setup_portio_remap = NULL,
83 .check_phys_apicid_present = default_check_phys_apicid_present,
84 .enable_apic_mode = NULL,
85 .phys_pkg_id = default_phys_pkg_id,
86 .mps_oem_check = NULL,
87
88 .get_apic_id = default_get_apic_id,
89 .set_apic_id = NULL,
90 .apic_id_mask = 0x0F << 24,
91
92 .cpu_mask_to_apicid = default_cpu_mask_to_apicid,
93 .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
94
95 .send_IPI_mask = default_send_IPI_mask,
96 .send_IPI_mask_allbutself = NULL,
97 .send_IPI_allbutself = default_send_IPI_allbutself,
98 .send_IPI_all = default_send_IPI_all,
99 .send_IPI_self = NULL,
100
101 .wakeup_cpu = NULL,
102 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
103 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
104
105 .wait_for_init_deassert = default_wait_for_init_deassert,
106
107 .smp_callin_clear_local_apic = NULL,
108 .store_NMI_vector = NULL,
109 .inquire_remote_apic = default_inquire_remote_apic,
110};
111
112extern struct genapic apic_numaq;
113extern struct genapic apic_summit;
114extern struct genapic apic_bigsmp;
115extern struct genapic apic_es7000;
116extern struct genapic apic_default;
117
118struct genapic *apic = &apic_default;
119
120static struct genapic *apic_probe[] __initdata = {
121#ifdef CONFIG_X86_NUMAQ
122 &apic_numaq,
123#endif
124#ifdef CONFIG_X86_SUMMIT
125 &apic_summit,
126#endif
127#ifdef CONFIG_X86_BIGSMP
128 &apic_bigsmp,
129#endif
130#ifdef CONFIG_X86_ES7000
131 &apic_es7000,
132#endif
133 &apic_default, /* must be last */
134 NULL,
135};
136
137static int cmdline_apic __initdata;
138static int __init parse_apic(char *arg)
139{
140 int i;
141
142 if (!arg)
143 return -EINVAL;
144
145 for (i = 0; apic_probe[i]; i++) {
146 if (!strcmp(apic_probe[i]->name, arg)) {
147 apic = apic_probe[i];
148 cmdline_apic = 1;
149 return 0;
150 }
151 }
152
153 if (x86_quirks->update_genapic)
154 x86_quirks->update_genapic();
155
156 /* Parsed again by __setup for debug/verbose */
157 return 0;
158}
159early_param("apic", parse_apic);
160
161void __init generic_bigsmp_probe(void)
162{
163#ifdef CONFIG_X86_BIGSMP
164 /*
165 * This routine is used to switch to bigsmp mode when
166 * - There is no apic= option specified by the user
167 * - generic_apic_probe() has chosen apic_default as the sub_arch
168 * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
169 */
170
171 if (!cmdline_apic && apic == &apic_default) {
172 if (apic_bigsmp.probe()) {
173 apic = &apic_bigsmp;
174 if (x86_quirks->update_genapic)
175 x86_quirks->update_genapic();
176 printk(KERN_INFO "Overriding APIC driver with %s\n",
177 apic->name);
178 }
179 }
180#endif
181}
182
183void __init generic_apic_probe(void)
184{
185 if (!cmdline_apic) {
186 int i;
187 for (i = 0; apic_probe[i]; i++) {
188 if (apic_probe[i]->probe()) {
189 apic = apic_probe[i];
190 break;
191 }
192 }
193 /* Not visible without early console */
194 if (!apic_probe[i])
195 panic("Didn't find an APIC driver");
196
197 if (x86_quirks->update_genapic)
198 x86_quirks->update_genapic();
199 }
200 printk(KERN_INFO "Using APIC driver %s\n", apic->name);
201}
202
203/* These functions can switch the APIC even after the initial ->probe() */
204
205int __init
206generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
207{
208 int i;
209
210 for (i = 0; apic_probe[i]; ++i) {
211 if (!apic_probe[i]->mps_oem_check)
212 continue;
213 if (!apic_probe[i]->mps_oem_check(mpc, oem, productid))
214 continue;
215
216 if (!cmdline_apic) {
217 apic = apic_probe[i];
218 if (x86_quirks->update_genapic)
219 x86_quirks->update_genapic();
220 printk(KERN_INFO "Switched to APIC driver `%s'.\n",
221 apic->name);
222 }
223 return 1;
224 }
225 return 0;
226}
227
228int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
229{
230 int i;
231
232 for (i = 0; apic_probe[i]; ++i) {
233 if (!apic_probe[i]->acpi_madt_oem_check)
234 continue;
235 if (!apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id))
236 continue;
237
238 if (!cmdline_apic) {
239 apic = apic_probe[i];
240 if (x86_quirks->update_genapic)
241 x86_quirks->update_genapic();
242 printk(KERN_INFO "Switched to APIC driver `%s'.\n",
243 apic->name);
244 }
245 return 1;
246 }
247 return 0;
248}