diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 15:11:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 15:11:41 -0500 |
commit | 7fe67a1180db49d41a3f764c379a08f8e31580ec (patch) | |
tree | 41a6f78958d5a6e63791a889daaa1a9633150a49 /arch/x86 | |
parent | fab5669d556200c4dd119af705bff14085845d1e (diff) | |
parent | da6139e49c7cb0f4251265cb5243b8d220adb48d (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull leftover x86 fixes from Ingo Molnar:
"Two leftover fixes that did not make it into v3.13"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86: Add check for number of available vectors before CPU down
x86, cpu, amd: Add workaround for family 16h, erratum 793
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/irq.h | 1 | ||||
-rw-r--r-- | arch/x86/include/uapi/asm/msr-index.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 70 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 6 |
5 files changed, 88 insertions, 0 deletions
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 0ea10f27d613..cb6cfcd034cf 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
@@ -25,6 +25,7 @@ extern void irq_ctx_init(int cpu); | |||
25 | 25 | ||
26 | #ifdef CONFIG_HOTPLUG_CPU | 26 | #ifdef CONFIG_HOTPLUG_CPU |
27 | #include <linux/cpumask.h> | 27 | #include <linux/cpumask.h> |
28 | extern int check_irq_vectors_for_cpu_disable(void); | ||
28 | extern void fixup_irqs(void); | 29 | extern void fixup_irqs(void); |
29 | extern void irq_force_complete_move(int); | 30 | extern void irq_force_complete_move(int); |
30 | #endif | 31 | #endif |
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index 37813b5ddc37..59cea185ad1d 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h | |||
@@ -184,6 +184,7 @@ | |||
184 | #define MSR_AMD64_PATCH_LOADER 0xc0010020 | 184 | #define MSR_AMD64_PATCH_LOADER 0xc0010020 |
185 | #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 | 185 | #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 |
186 | #define MSR_AMD64_OSVW_STATUS 0xc0010141 | 186 | #define MSR_AMD64_OSVW_STATUS 0xc0010141 |
187 | #define MSR_AMD64_LS_CFG 0xc0011020 | ||
187 | #define MSR_AMD64_DC_CFG 0xc0011022 | 188 | #define MSR_AMD64_DC_CFG 0xc0011022 |
188 | #define MSR_AMD64_BU_CFG2 0xc001102a | 189 | #define MSR_AMD64_BU_CFG2 0xc001102a |
189 | #define MSR_AMD64_IBSFETCHCTL 0xc0011030 | 190 | #define MSR_AMD64_IBSFETCHCTL 0xc0011030 |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 525712c7ffa2..d3153e281d72 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -507,6 +507,16 @@ static void early_init_amd(struct cpuinfo_x86 *c) | |||
507 | set_cpu_cap(c, X86_FEATURE_EXTD_APICID); | 507 | set_cpu_cap(c, X86_FEATURE_EXTD_APICID); |
508 | } | 508 | } |
509 | #endif | 509 | #endif |
510 | |||
511 | /* F16h erratum 793, CVE-2013-6885 */ | ||
512 | if (c->x86 == 0x16 && c->x86_model <= 0xf) { | ||
513 | u64 val; | ||
514 | |||
515 | rdmsrl(MSR_AMD64_LS_CFG, val); | ||
516 | if (!(val & BIT(15))) | ||
517 | wrmsrl(MSR_AMD64_LS_CFG, val | BIT(15)); | ||
518 | } | ||
519 | |||
510 | } | 520 | } |
511 | 521 | ||
512 | static const int amd_erratum_383[]; | 522 | static const int amd_erratum_383[]; |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 884d875c1434..dbb60878b744 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -266,6 +266,76 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs) | |||
266 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 266 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
267 | 267 | ||
268 | #ifdef CONFIG_HOTPLUG_CPU | 268 | #ifdef CONFIG_HOTPLUG_CPU |
269 | /* | ||
270 | * This cpu is going to be removed and its vectors migrated to the remaining | ||
271 | * online cpus. Check to see if there are enough vectors in the remaining cpus. | ||
272 | * This function is protected by stop_machine(). | ||
273 | */ | ||
274 | int check_irq_vectors_for_cpu_disable(void) | ||
275 | { | ||
276 | int irq, cpu; | ||
277 | unsigned int this_cpu, vector, this_count, count; | ||
278 | struct irq_desc *desc; | ||
279 | struct irq_data *data; | ||
280 | struct cpumask affinity_new, online_new; | ||
281 | |||
282 | this_cpu = smp_processor_id(); | ||
283 | cpumask_copy(&online_new, cpu_online_mask); | ||
284 | cpu_clear(this_cpu, online_new); | ||
285 | |||
286 | this_count = 0; | ||
287 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | ||
288 | irq = __this_cpu_read(vector_irq[vector]); | ||
289 | if (irq >= 0) { | ||
290 | desc = irq_to_desc(irq); | ||
291 | data = irq_desc_get_irq_data(desc); | ||
292 | cpumask_copy(&affinity_new, data->affinity); | ||
293 | cpu_clear(this_cpu, affinity_new); | ||
294 | |||
295 | /* Do not count inactive or per-cpu irqs. */ | ||
296 | if (!irq_has_action(irq) || irqd_is_per_cpu(data)) | ||
297 | continue; | ||
298 | |||
299 | /* | ||
300 | * A single irq may be mapped to multiple | ||
301 | * cpu's vector_irq[] (for example IOAPIC cluster | ||
302 | * mode). In this case we have two | ||
303 | * possibilities: | ||
304 | * | ||
305 | * 1) the resulting affinity mask is empty; that is | ||
306 | * this the down'd cpu is the last cpu in the irq's | ||
307 | * affinity mask, or | ||
308 | * | ||
309 | * 2) the resulting affinity mask is no longer | ||
310 | * a subset of the online cpus but the affinity | ||
311 | * mask is not zero; that is the down'd cpu is the | ||
312 | * last online cpu in a user set affinity mask. | ||
313 | */ | ||
314 | if (cpumask_empty(&affinity_new) || | ||
315 | !cpumask_subset(&affinity_new, &online_new)) | ||
316 | this_count++; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | count = 0; | ||
321 | for_each_online_cpu(cpu) { | ||
322 | if (cpu == this_cpu) | ||
323 | continue; | ||
324 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; | ||
325 | vector++) { | ||
326 | if (per_cpu(vector_irq, cpu)[vector] < 0) | ||
327 | count++; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | if (count < this_count) { | ||
332 | pr_warn("CPU %d disable failed: CPU has %u vectors assigned and there are only %u available.\n", | ||
333 | this_cpu, this_count, count); | ||
334 | return -ERANGE; | ||
335 | } | ||
336 | return 0; | ||
337 | } | ||
338 | |||
269 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ | 339 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ |
270 | void fixup_irqs(void) | 340 | void fixup_irqs(void) |
271 | { | 341 | { |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f5252c4eec8c..a32da804252e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -1312,6 +1312,12 @@ void cpu_disable_common(void) | |||
1312 | 1312 | ||
1313 | int native_cpu_disable(void) | 1313 | int native_cpu_disable(void) |
1314 | { | 1314 | { |
1315 | int ret; | ||
1316 | |||
1317 | ret = check_irq_vectors_for_cpu_disable(); | ||
1318 | if (ret) | ||
1319 | return ret; | ||
1320 | |||
1315 | clear_local_APIC(); | 1321 | clear_local_APIC(); |
1316 | 1322 | ||
1317 | cpu_disable_common(); | 1323 | cpu_disable_common(); |