aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-03-31 14:58:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-03-31 14:58:45 -0400
commit6ed7705167dd056c61b1954fe1366fcddb5bda98 (patch)
treed58f35c83a831b1b15c6cac8f07af6fe9d27924e
parent3a88fe3b748b5bcf1c2c739ad63dab8364fd5b9b (diff)
parentea7bdc65bca8cf837a63e0ff7b75daed83222511 (diff)
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 apic changes from Ingo Molnar: "An xAPIC CPU hotplug race fix, plus cleanups and minor fixes" * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/apic: Plug racy xAPIC access of CPU hotplug code x86/apic: Always define nox2apic and define it as initdata x86/apic: Remove unused function prototypes x86/apic: Switch wait_for_init_deassert() to a bool flag x86/apic: Only use default_wait_for_init_deassert()
-rw-r--r--arch/x86/include/asm/apic.h14
-rw-r--r--arch/x86/kernel/apic/apic.c13
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c4
-rw-r--r--arch/x86/kernel/apic/apic_noop.c3
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c2
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c3
-rw-r--r--arch/x86/kernel/apic/es7000_32.c12
-rw-r--r--arch/x86/kernel/apic/numaq_32.c3
-rw-r--r--arch/x86/kernel/apic/probe_32.c3
-rw-r--r--arch/x86/kernel/apic/summit_32.c3
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c2
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c2
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c2
-rw-r--r--arch/x86/kernel/smpboot.c16
14 files changed, 36 insertions, 46 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1d2091a226bc..19b0ebafcd3e 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -93,9 +93,6 @@ static inline int is_vsmp_box(void)
93 return 0; 93 return 0;
94} 94}
95#endif 95#endif
96extern void xapic_wait_icr_idle(void);
97extern u32 safe_xapic_wait_icr_idle(void);
98extern void xapic_icr_write(u32, u32);
99extern int setup_profiling_timer(unsigned int); 96extern int setup_profiling_timer(unsigned int);
100 97
101static inline void native_apic_mem_write(u32 reg, u32 v) 98static inline void native_apic_mem_write(u32 reg, u32 v)
@@ -184,7 +181,6 @@ extern int x2apic_phys;
184extern int x2apic_preenabled; 181extern int x2apic_preenabled;
185extern void check_x2apic(void); 182extern void check_x2apic(void);
186extern void enable_x2apic(void); 183extern void enable_x2apic(void);
187extern void x2apic_icr_write(u32 low, u32 id);
188static inline int x2apic_enabled(void) 184static inline int x2apic_enabled(void)
189{ 185{
190 u64 msr; 186 u64 msr;
@@ -221,7 +217,6 @@ static inline void x2apic_force_phys(void)
221{ 217{
222} 218}
223 219
224#define nox2apic 0
225#define x2apic_preenabled 0 220#define x2apic_preenabled 0
226#define x2apic_supported() 0 221#define x2apic_supported() 0
227#endif 222#endif
@@ -351,7 +346,7 @@ struct apic {
351 int trampoline_phys_low; 346 int trampoline_phys_low;
352 int trampoline_phys_high; 347 int trampoline_phys_high;
353 348
354 void (*wait_for_init_deassert)(atomic_t *deassert); 349 bool wait_for_init_deassert;
355 void (*smp_callin_clear_local_apic)(void); 350 void (*smp_callin_clear_local_apic)(void);
356 void (*inquire_remote_apic)(int apicid); 351 void (*inquire_remote_apic)(int apicid);
357 352
@@ -517,13 +512,6 @@ extern int default_cpu_present_to_apicid(int mps_cpu);
517extern int default_check_phys_apicid_present(int phys_apicid); 512extern int default_check_phys_apicid_present(int phys_apicid);
518#endif 513#endif
519 514
520static inline void default_wait_for_init_deassert(atomic_t *deassert)
521{
522 while (!atomic_read(deassert))
523 cpu_relax();
524 return;
525}
526
527extern void generic_bigsmp_probe(void); 515extern void generic_bigsmp_probe(void);
528 516
529 517
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 7f26c9a70a9e..53e20531470e 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -133,6 +133,10 @@ static inline void imcr_apic_to_pic(void)
133 * +1=force-enable 133 * +1=force-enable
134 */ 134 */
135static int force_enable_local_apic __initdata; 135static int force_enable_local_apic __initdata;
136
137/* Control whether x2APIC mode is enabled or not */
138static bool nox2apic __initdata;
139
136/* 140/*
137 * APIC command line parameters 141 * APIC command line parameters
138 */ 142 */
@@ -162,8 +166,7 @@ int x2apic_mode;
162/* x2apic enabled before OS handover */ 166/* x2apic enabled before OS handover */
163int x2apic_preenabled; 167int x2apic_preenabled;
164static int x2apic_disabled; 168static int x2apic_disabled;
165static int nox2apic; 169static int __init setup_nox2apic(char *str)
166static __init int setup_nox2apic(char *str)
167{ 170{
168 if (x2apic_enabled()) { 171 if (x2apic_enabled()) {
169 int apicid = native_apic_msr_read(APIC_ID); 172 int apicid = native_apic_msr_read(APIC_ID);
@@ -178,7 +181,7 @@ static __init int setup_nox2apic(char *str)
178 } else 181 } else
179 setup_clear_cpu_cap(X86_FEATURE_X2APIC); 182 setup_clear_cpu_cap(X86_FEATURE_X2APIC);
180 183
181 nox2apic = 1; 184 nox2apic = true;
182 185
183 return 0; 186 return 0;
184} 187}
@@ -283,8 +286,12 @@ u32 native_safe_apic_wait_icr_idle(void)
283 286
284void native_apic_icr_write(u32 low, u32 id) 287void native_apic_icr_write(u32 low, u32 id)
285{ 288{
289 unsigned long flags;
290
291 local_irq_save(flags);
286 apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id)); 292 apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id));
287 apic_write(APIC_ICR, low); 293 apic_write(APIC_ICR, low);
294 local_irq_restore(flags);
288} 295}
289 296
290u64 native_apic_icr_read(void) 297u64 native_apic_icr_read(void)
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 2c621a6b901a..7c1b29479513 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -198,7 +198,7 @@ static struct apic apic_flat = {
198 198
199 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 199 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
200 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 200 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
201 .wait_for_init_deassert = NULL, 201 .wait_for_init_deassert = false,
202 .smp_callin_clear_local_apic = NULL, 202 .smp_callin_clear_local_apic = NULL,
203 .inquire_remote_apic = default_inquire_remote_apic, 203 .inquire_remote_apic = default_inquire_remote_apic,
204 204
@@ -314,7 +314,7 @@ static struct apic apic_physflat = {
314 314
315 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 315 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
316 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 316 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
317 .wait_for_init_deassert = NULL, 317 .wait_for_init_deassert = false,
318 .smp_callin_clear_local_apic = NULL, 318 .smp_callin_clear_local_apic = NULL,
319 .inquire_remote_apic = default_inquire_remote_apic, 319 .inquire_remote_apic = default_inquire_remote_apic,
320 320
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index 191ce75c0e54..8c7c98249c20 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -172,8 +172,7 @@ struct apic apic_noop = {
172 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 172 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
173 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 173 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
174 174
175 .wait_for_init_deassert = NULL, 175 .wait_for_init_deassert = false,
176
177 .smp_callin_clear_local_apic = NULL, 176 .smp_callin_clear_local_apic = NULL,
178 .inquire_remote_apic = NULL, 177 .inquire_remote_apic = NULL,
179 178
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index 3e67f9e3d7ef..a5b45df8bc88 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -248,7 +248,7 @@ static const struct apic apic_numachip __refconst = {
248 .wakeup_secondary_cpu = numachip_wakeup_secondary, 248 .wakeup_secondary_cpu = numachip_wakeup_secondary,
249 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 249 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
250 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 250 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
251 .wait_for_init_deassert = NULL, 251 .wait_for_init_deassert = false,
252 .smp_callin_clear_local_apic = NULL, 252 .smp_callin_clear_local_apic = NULL,
253 .inquire_remote_apic = NULL, /* REMRD not supported */ 253 .inquire_remote_apic = NULL, /* REMRD not supported */
254 254
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index d50e3640d5ae..e4840aa7a255 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -199,8 +199,7 @@ static struct apic apic_bigsmp = {
199 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 199 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
200 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 200 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
201 201
202 .wait_for_init_deassert = default_wait_for_init_deassert, 202 .wait_for_init_deassert = true,
203
204 .smp_callin_clear_local_apic = NULL, 203 .smp_callin_clear_local_apic = NULL,
205 .inquire_remote_apic = default_inquire_remote_apic, 204 .inquire_remote_apic = default_inquire_remote_apic,
206 205
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index c55224731b2d..6f8f8b348a39 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -394,12 +394,6 @@ static void es7000_enable_apic_mode(void)
394 WARN(1, "Command failed, status = %x\n", mip_status); 394 WARN(1, "Command failed, status = %x\n", mip_status);
395} 395}
396 396
397static void es7000_wait_for_init_deassert(atomic_t *deassert)
398{
399 while (!atomic_read(deassert))
400 cpu_relax();
401}
402
403static unsigned int es7000_get_apic_id(unsigned long x) 397static unsigned int es7000_get_apic_id(unsigned long x)
404{ 398{
405 return (x >> 24) & 0xFF; 399 return (x >> 24) & 0xFF;
@@ -658,8 +652,7 @@ static struct apic __refdata apic_es7000_cluster = {
658 .trampoline_phys_low = 0x467, 652 .trampoline_phys_low = 0x467,
659 .trampoline_phys_high = 0x469, 653 .trampoline_phys_high = 0x469,
660 654
661 .wait_for_init_deassert = NULL, 655 .wait_for_init_deassert = false,
662
663 /* Nothing to do for most platforms, since cleared by the INIT cycle: */ 656 /* Nothing to do for most platforms, since cleared by the INIT cycle: */
664 .smp_callin_clear_local_apic = NULL, 657 .smp_callin_clear_local_apic = NULL,
665 .inquire_remote_apic = default_inquire_remote_apic, 658 .inquire_remote_apic = default_inquire_remote_apic,
@@ -722,8 +715,7 @@ static struct apic __refdata apic_es7000 = {
722 .trampoline_phys_low = 0x467, 715 .trampoline_phys_low = 0x467,
723 .trampoline_phys_high = 0x469, 716 .trampoline_phys_high = 0x469,
724 717
725 .wait_for_init_deassert = es7000_wait_for_init_deassert, 718 .wait_for_init_deassert = true,
726
727 /* Nothing to do for most platforms, since cleared by the INIT cycle: */ 719 /* Nothing to do for most platforms, since cleared by the INIT cycle: */
728 .smp_callin_clear_local_apic = NULL, 720 .smp_callin_clear_local_apic = NULL,
729 .inquire_remote_apic = default_inquire_remote_apic, 721 .inquire_remote_apic = default_inquire_remote_apic,
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 1e42e8f305ee..030ea1c04f72 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -505,8 +505,7 @@ static struct apic __refdata apic_numaq = {
505 .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, 505 .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH,
506 506
507 /* We don't do anything here because we use NMI's to boot instead */ 507 /* We don't do anything here because we use NMI's to boot instead */
508 .wait_for_init_deassert = NULL, 508 .wait_for_init_deassert = false,
509
510 .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, 509 .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic,
511 .inquire_remote_apic = NULL, 510 .inquire_remote_apic = NULL,
512 511
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index eb35ef9ee63f..cceb352c968c 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -119,8 +119,7 @@ static struct apic apic_default = {
119 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 119 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
120 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 120 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
121 121
122 .wait_for_init_deassert = default_wait_for_init_deassert, 122 .wait_for_init_deassert = true,
123
124 .smp_callin_clear_local_apic = NULL, 123 .smp_callin_clear_local_apic = NULL,
125 .inquire_remote_apic = default_inquire_remote_apic, 124 .inquire_remote_apic = default_inquire_remote_apic,
126 125
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index 00146f9b0254..b656128611cd 100644
--- a/arch/x86/kernel/apic/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -532,8 +532,7 @@ static struct apic apic_summit = {
532 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 532 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
533 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 533 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
534 534
535 .wait_for_init_deassert = default_wait_for_init_deassert, 535 .wait_for_init_deassert = true,
536
537 .smp_callin_clear_local_apic = NULL, 536 .smp_callin_clear_local_apic = NULL,
538 .inquire_remote_apic = default_inquire_remote_apic, 537 .inquire_remote_apic = default_inquire_remote_apic,
539 538
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index cac85ee6913f..e66766bf1641 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -279,7 +279,7 @@ static struct apic apic_x2apic_cluster = {
279 279
280 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 280 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
281 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 281 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
282 .wait_for_init_deassert = NULL, 282 .wait_for_init_deassert = false,
283 .smp_callin_clear_local_apic = NULL, 283 .smp_callin_clear_local_apic = NULL,
284 .inquire_remote_apic = NULL, 284 .inquire_remote_apic = NULL,
285 285
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index de231e328cae..6d600ebf6c12 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -133,7 +133,7 @@ static struct apic apic_x2apic_phys = {
133 133
134 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 134 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
135 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 135 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
136 .wait_for_init_deassert = NULL, 136 .wait_for_init_deassert = false,
137 .smp_callin_clear_local_apic = NULL, 137 .smp_callin_clear_local_apic = NULL,
138 .inquire_remote_apic = NULL, 138 .inquire_remote_apic = NULL,
139 139
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index d263b1307de1..7834389ba5be 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -396,7 +396,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
396 .wakeup_secondary_cpu = uv_wakeup_secondary, 396 .wakeup_secondary_cpu = uv_wakeup_secondary,
397 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 397 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
398 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 398 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
399 .wait_for_init_deassert = NULL, 399 .wait_for_init_deassert = false,
400 .smp_callin_clear_local_apic = NULL, 400 .smp_callin_clear_local_apic = NULL,
401 .inquire_remote_apic = NULL, 401 .inquire_remote_apic = NULL,
402 402
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index a32da804252e..60179ec39d4c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -122,8 +122,9 @@ static void smp_callin(void)
122 * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI. 122 * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI.
123 */ 123 */
124 cpuid = smp_processor_id(); 124 cpuid = smp_processor_id();
125 if (apic->wait_for_init_deassert && cpuid != 0) 125 if (apic->wait_for_init_deassert && cpuid)
126 apic->wait_for_init_deassert(&init_deasserted); 126 while (!atomic_read(&init_deasserted))
127 cpu_relax();
127 128
128 /* 129 /*
129 * (This works even if the APIC is not enabled.) 130 * (This works even if the APIC is not enabled.)
@@ -701,11 +702,15 @@ wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid,
701 int id; 702 int id;
702 int boot_error; 703 int boot_error;
703 704
705 preempt_disable();
706
704 /* 707 /*
705 * Wake up AP by INIT, INIT, STARTUP sequence. 708 * Wake up AP by INIT, INIT, STARTUP sequence.
706 */ 709 */
707 if (cpu) 710 if (cpu) {
708 return wakeup_secondary_cpu_via_init(apicid, start_ip); 711 boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip);
712 goto out;
713 }
709 714
710 /* 715 /*
711 * Wake up BSP by nmi. 716 * Wake up BSP by nmi.
@@ -725,6 +730,9 @@ wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid,
725 boot_error = wakeup_secondary_cpu_via_nmi(id, start_ip); 730 boot_error = wakeup_secondary_cpu_via_nmi(id, start_ip);
726 } 731 }
727 732
733out:
734 preempt_enable();
735
728 return boot_error; 736 return boot_error;
729} 737}
730 738