Blame view

arch/x86/kernel/apic/probe_32.c 6.49 KB
9b0c50288   Paolo Ciarrocchi   x86: coding style...
1
  /*
7b3872531   Ingo Molnar   x86: remove subar...
2
3
   * Default generic APIC driver. This handles up to 8 CPUs.
   *
9b0c50288   Paolo Ciarrocchi   x86: coding style...
4
5
6
   * Copyright 2003 Andi Kleen, SuSE Labs.
   * Subject to the GNU Public License, v.2
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   * Generic x86 APIC driver probe layer.
9b0c50288   Paolo Ciarrocchi   x86: coding style...
8
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
  #include <linux/threads.h>
  #include <linux/cpumask.h>
7d01d32d3   Ingo Molnar   x86, apic: fix bu...
11
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/ctype.h>
  #include <linux/init.h>
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
16
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
  #include <asm/fixmap.h>
  #include <asm/mpspec.h>
  #include <asm/apicdef.h>
7b6aa335c   Ingo Molnar   x86, apic: remove...
20
  #include <asm/apic.h>
54ac14a8e   Yinghai Lu   x86: fix wakeup_c...
21
  #include <asm/setup.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22

7b3872531   Ingo Molnar   x86: remove subar...
23
  #include <linux/smp.h>
7b3872531   Ingo Molnar   x86: remove subar...
24
  #include <asm/ipi.h>
6bda2c8b3   Ingo Molnar   x86: remove subar...
25
26
  #include <linux/interrupt.h>
  #include <asm/acpi.h>
6bda2c8b3   Ingo Molnar   x86: remove subar...
27
  #include <asm/e820.h>
6bda2c8b3   Ingo Molnar   x86: remove subar...
28

6bda2c8b3   Ingo Molnar   x86: remove subar...
29
30
31
32
33
34
35
  #ifdef CONFIG_HOTPLUG_CPU
  #define DEFAULT_SEND_IPI	(1)
  #else
  #define DEFAULT_SEND_IPI	(0)
  #endif
  
  int no_broadcast = DEFAULT_SEND_IPI;
9be1b56a3   Ingo Molnar   x86, apic: separa...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  static __init int no_ipi_broadcast(char *str)
  {
  	get_option(&str, &no_broadcast);
  	pr_info("Using %s mode
  ",
  		no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
  	return 1;
  }
  __setup("no_ipi_broadcast=", no_ipi_broadcast);
  
  static int __init print_ipi_mode(void)
  {
  	pr_info("Using IPI %s mode
  ",
  		no_broadcast ? "No-Shortcut" : "Shortcut");
  	return 0;
  }
  late_initcall(print_ipi_mode);
6bda2c8b3   Ingo Molnar   x86: remove subar...
54

3f6f67988   Tejun Heo   x86: Implement th...
55
56
57
58
  static int default_x86_32_early_logical_apicid(int cpu)
  {
  	return 1 << cpu;
  }
681ee44d4   Suresh Siddha   x86, apic: Don't ...
59
  static void setup_apic_flat_routing(void)
28aa29eeb   Ingo Molnar   remove: genapic p...
60
61
62
63
64
65
66
67
  {
  #ifdef CONFIG_X86_IO_APIC
  	printk(KERN_INFO
  		"Enabling APIC mode:  Flat.  Using %d I/O APICs
  ",
  		nr_ioapics);
  #endif
  }
7b3872531   Ingo Molnar   x86: remove subar...
68
69
70
71
72
73
74
75
76
77
78
  static void default_vector_allocation_domain(int cpu, struct cpumask *retmask)
  {
  	/*
  	 * 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.
  	 */
5c6cb5e2b   Rusty Russell   cpumask: remove c...
79
80
  	cpumask_clear(retmask);
  	cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
7b3872531   Ingo Molnar   x86: remove subar...
81
82
83
84
85
86
87
  }
  
  /* should be called last. */
  static int probe_default(void)
  {
  	return 1;
  }
1a8880a14   Suresh Siddha   x86, apic: Make a...
88
  static struct apic apic_default = {
7b3872531   Ingo Molnar   x86: remove subar...
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  
  	.name				= "default",
  	.probe				= probe_default,
  	.acpi_madt_oem_check		= NULL,
  	.apic_id_registered		= default_apic_id_registered,
  
  	.irq_delivery_mode		= dest_LowestPrio,
  	/* logical delivery broadcast to all CPUs: */
  	.irq_dest_mode			= 1,
  
  	.target_cpus			= default_target_cpus,
  	.disable_esr			= 0,
  	.dest_logical			= APIC_DEST_LOGICAL,
  	.check_apicid_used		= default_check_apicid_used,
  	.check_apicid_present		= default_check_apicid_present,
  
  	.vector_allocation_domain	= default_vector_allocation_domain,
  	.init_apic_ldr			= default_init_apic_ldr,
  
  	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
681ee44d4   Suresh Siddha   x86, apic: Don't ...
109
  	.setup_apic_routing		= setup_apic_flat_routing,
7b3872531   Ingo Molnar   x86: remove subar...
110
  	.multi_timer_check		= NULL,
7b3872531   Ingo Molnar   x86: remove subar...
111
  	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
7abc07531   Cyrill Gorcunov   x86: apic: Do not...
112
  	.apicid_to_cpu_present		= physid_set_mask_of_physid,
7b3872531   Ingo Molnar   x86: remove subar...
113
114
115
116
117
118
119
120
121
122
123
124
  	.setup_portio_remap		= NULL,
  	.check_phys_apicid_present	= default_check_phys_apicid_present,
  	.enable_apic_mode		= NULL,
  	.phys_pkg_id			= default_phys_pkg_id,
  	.mps_oem_check			= NULL,
  
  	.get_apic_id			= default_get_apic_id,
  	.set_apic_id			= NULL,
  	.apic_id_mask			= 0x0F << 24,
  
  	.cpu_mask_to_apicid		= default_cpu_mask_to_apicid,
  	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and,
43f39890d   Yinghai Lu   x86: seperate def...
125
126
  	.send_IPI_mask			= default_send_IPI_mask_logical,
  	.send_IPI_mask_allbutself	= default_send_IPI_mask_allbutself_logical,
7b3872531   Ingo Molnar   x86: remove subar...
127
128
  	.send_IPI_allbutself		= default_send_IPI_allbutself,
  	.send_IPI_all			= default_send_IPI_all,
6b64ee02d   Ingo Molnar   x86, apic, 32-bit...
129
  	.send_IPI_self			= default_send_IPI_self,
7b3872531   Ingo Molnar   x86: remove subar...
130

7b3872531   Ingo Molnar   x86: remove subar...
131
132
133
134
135
136
  	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
  	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
  
  	.wait_for_init_deassert		= default_wait_for_init_deassert,
  
  	.smp_callin_clear_local_apic	= NULL,
7b3872531   Ingo Molnar   x86: remove subar...
137
  	.inquire_remote_apic		= default_inquire_remote_apic,
c1eeb2de4   Yinghai Lu   x86: fold apic_op...
138
139
140
141
142
143
144
  
  	.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,
acb8bc09c   Tejun Heo   x86: Add apic->x8...
145

3f6f67988   Tejun Heo   x86: Implement th...
146
  	.x86_32_early_logical_apicid	= default_x86_32_early_logical_apicid,
7b3872531   Ingo Molnar   x86: remove subar...
147
  };
107e0e0cd   Suresh Siddha   x86, apic: Introd...
148
  apic_driver(apic_default);
be163a159   Ingo Molnar   x86, apic: rename...
149
  struct apic *apic = &apic_default;
7d01d32d3   Ingo Molnar   x86, apic: fix bu...
150
  EXPORT_SYMBOL_GPL(apic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
152
153
154
  static int cmdline_apic __initdata;
  static int __init parse_apic(char *arg)
  {
8b37e8806   Suresh Siddha   x86, apic: Use .a...
155
  	struct apic **drv;
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
156
157
158
  
  	if (!arg)
  		return -EINVAL;
8b37e8806   Suresh Siddha   x86, apic: Use .a...
159
160
161
  	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
  		if (!strcmp((*drv)->name, arg)) {
  			apic = *drv;
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
162
163
164
165
  			cmdline_apic = 1;
  			return 0;
  		}
  	}
9a8cb626a   Andi Kleen   [PATCH] i386: Avo...
166
167
168
  
  	/* Parsed again by __setup for debug/verbose */
  	return 0;
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
169
170
  }
  early_param("apic", parse_apic);
911a62d42   Venkatesh Pallipadi   [PATCH] x86: suto...
171

69c252ffc   Suresh Siddha   x86, apic: Clean ...
172
  void __init default_setup_apic_routing(void)
911a62d42   Venkatesh Pallipadi   [PATCH] x86: suto...
173
  {
69c252ffc   Suresh Siddha   x86, apic: Clean ...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  	int version = apic_version[boot_cpu_physical_apicid];
  
  	if (num_possible_cpus() > 8) {
  		switch (boot_cpu_data.x86_vendor) {
  		case X86_VENDOR_INTEL:
  			if (!APIC_XAPIC(version)) {
  				def_to_bigsmp = 0;
  				break;
  			}
  			/* If P4 and above fall through */
  		case X86_VENDOR_AMD:
  			def_to_bigsmp = 1;
  		}
  	}
b20d70b70   Yinghai Lu   x86: make generic...
188
  #ifdef CONFIG_X86_BIGSMP
911a62d42   Venkatesh Pallipadi   [PATCH] x86: suto...
189
  	/*
69c252ffc   Suresh Siddha   x86, apic: Clean ...
190
  	 * This is used to switch to bigsmp mode when
911a62d42   Venkatesh Pallipadi   [PATCH] x86: suto...
191
  	 * - There is no apic= option specified by the user
27b46d766   Simon Arlott   spelling fixes: a...
192
  	 * - generic_apic_probe() has chosen apic_default as the sub_arch
911a62d42   Venkatesh Pallipadi   [PATCH] x86: suto...
193
194
  	 * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
  	 */
838312be4   Jan Beulich   apic, i386/bigsmp...
195
196
  	if (!cmdline_apic && apic == &apic_default)
  		generic_bigsmp_probe();
d49c42884   Yinghai Lu   x86: make generic...
197
  #endif
69c252ffc   Suresh Siddha   x86, apic: Clean ...
198
199
200
  
  	if (apic->setup_apic_routing)
  		apic->setup_apic_routing();
911a62d42   Venkatesh Pallipadi   [PATCH] x86: suto...
201
  }
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
202
  void __init generic_apic_probe(void)
9b0c50288   Paolo Ciarrocchi   x86: coding style...
203
  {
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
204
  	if (!cmdline_apic) {
8b37e8806   Suresh Siddha   x86, apic: Use .a...
205
206
207
208
209
  		struct apic **drv;
  
  		for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
  			if ((*drv)->probe()) {
  				apic = *drv;
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
210
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
  			}
  		}
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
213
  		/* Not visible without early console */
8b37e8806   Suresh Siddha   x86, apic: Use .a...
214
  		if (drv == __apicdrivers_end)
1a3f239dd   Rusty Russell   [PATCH] i386: Rep...
215
  			panic("Didn't find an APIC driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  	}
c8d46cf06   Ingo Molnar   x86: rename 'gena...
217
218
  	printk(KERN_INFO "Using APIC driver %s
  ", apic->name);
9b0c50288   Paolo Ciarrocchi   x86: coding style...
219
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  
  /* These functions can switch the APIC even after the initial ->probe() */
9c7642470   Ingo Molnar   x86: consolidate ...
222
223
  int __init
  generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
9b0c50288   Paolo Ciarrocchi   x86: coding style...
224
  {
8b37e8806   Suresh Siddha   x86, apic: Use .a...
225
  	struct apic **drv;
5f836405e   Ingo Molnar   x86, smp: clean u...
226

8b37e8806   Suresh Siddha   x86, apic: Use .a...
227
228
  	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
  		if (!((*drv)->mps_oem_check))
5f836405e   Ingo Molnar   x86, smp: clean u...
229
  			continue;
8b37e8806   Suresh Siddha   x86, apic: Use .a...
230
  		if (!(*drv)->mps_oem_check(mpc, oem, productid))
5f836405e   Ingo Molnar   x86, smp: clean u...
231
232
233
  			continue;
  
  		if (!cmdline_apic) {
8b37e8806   Suresh Siddha   x86, apic: Use .a...
234
  			apic = *drv;
5f836405e   Ingo Molnar   x86, smp: clean u...
235
236
237
  			printk(KERN_INFO "Switched to APIC driver `%s'.
  ",
  			       apic->name);
9b0c50288   Paolo Ciarrocchi   x86: coding style...
238
  		}
5f836405e   Ingo Molnar   x86, smp: clean u...
239
  		return 1;
9b0c50288   Paolo Ciarrocchi   x86: coding style...
240
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  	return 0;
9b0c50288   Paolo Ciarrocchi   x86: coding style...
242
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

306db03b0   Ingo Molnar   x86: clean up api...
244
  int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  {
8b37e8806   Suresh Siddha   x86, apic: Use .a...
246
  	struct apic **drv;
306db03b0   Ingo Molnar   x86: clean up api...
247

8b37e8806   Suresh Siddha   x86, apic: Use .a...
248
249
  	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
  		if (!(*drv)->acpi_madt_oem_check)
306db03b0   Ingo Molnar   x86: clean up api...
250
  			continue;
8b37e8806   Suresh Siddha   x86, apic: Use .a...
251
  		if (!(*drv)->acpi_madt_oem_check(oem_id, oem_table_id))
306db03b0   Ingo Molnar   x86: clean up api...
252
253
254
  			continue;
  
  		if (!cmdline_apic) {
8b37e8806   Suresh Siddha   x86, apic: Use .a...
255
  			apic = *drv;
306db03b0   Ingo Molnar   x86: clean up api...
256
257
258
  			printk(KERN_INFO "Switched to APIC driver `%s'.
  ",
  			       apic->name);
9b0c50288   Paolo Ciarrocchi   x86: coding style...
259
  		}
306db03b0   Ingo Molnar   x86: clean up api...
260
  		return 1;
9b0c50288   Paolo Ciarrocchi   x86: coding style...
261
262
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  }