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 | |
| 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
| -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(); |
