Skip to content

Commit 7fe67a1

Browse files
committed
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
2 parents fab5669 + da6139e commit 7fe67a1

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

arch/x86/include/asm/irq.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern void irq_ctx_init(int cpu);
2525

2626
#ifdef CONFIG_HOTPLUG_CPU
2727
#include <linux/cpumask.h>
28+
extern int check_irq_vectors_for_cpu_disable(void);
2829
extern void fixup_irqs(void);
2930
extern void irq_force_complete_move(int);
3031
#endif

arch/x86/include/uapi/asm/msr-index.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
#define MSR_AMD64_PATCH_LOADER 0xc0010020
185185
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
186186
#define MSR_AMD64_OSVW_STATUS 0xc0010141
187+
#define MSR_AMD64_LS_CFG 0xc0011020
187188
#define MSR_AMD64_DC_CFG 0xc0011022
188189
#define MSR_AMD64_BU_CFG2 0xc001102a
189190
#define MSR_AMD64_IBSFETCHCTL 0xc0011030

arch/x86/kernel/cpu/amd.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
507507
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
508508
}
509509
#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+
510520
}
511521

512522
static const int amd_erratum_383[];

arch/x86/kernel/irq.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,76 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs)
266266
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
267267

268268
#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+
269339
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
270340
void fixup_irqs(void)
271341
{

arch/x86/kernel/smpboot.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,12 @@ void cpu_disable_common(void)
13121312

13131313
int native_cpu_disable(void)
13141314
{
1315+
int ret;
1316+
1317+
ret = check_irq_vectors_for_cpu_disable();
1318+
if (ret)
1319+
return ret;
1320+
13151321
clear_local_APIC();
13161322

13171323
cpu_disable_common();

0 commit comments

Comments
 (0)