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
This commit is contained in:
commit
7fe67a1180
|
@ -25,6 +25,7 @@ extern void irq_ctx_init(int cpu);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
|
extern int check_irq_vectors_for_cpu_disable(void);
|
||||||
extern void fixup_irqs(void);
|
extern void fixup_irqs(void);
|
||||||
extern void irq_force_complete_move(int);
|
extern void irq_force_complete_move(int);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -184,6 +184,7 @@
|
||||||
#define MSR_AMD64_PATCH_LOADER 0xc0010020
|
#define MSR_AMD64_PATCH_LOADER 0xc0010020
|
||||||
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
|
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
|
||||||
#define MSR_AMD64_OSVW_STATUS 0xc0010141
|
#define MSR_AMD64_OSVW_STATUS 0xc0010141
|
||||||
|
#define MSR_AMD64_LS_CFG 0xc0011020
|
||||||
#define MSR_AMD64_DC_CFG 0xc0011022
|
#define MSR_AMD64_DC_CFG 0xc0011022
|
||||||
#define MSR_AMD64_BU_CFG2 0xc001102a
|
#define MSR_AMD64_BU_CFG2 0xc001102a
|
||||||
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
|
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
|
||||||
|
|
|
@ -507,6 +507,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
|
||||||
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
|
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* F16h erratum 793, CVE-2013-6885 */
|
||||||
|
if (c->x86 == 0x16 && c->x86_model <= 0xf) {
|
||||||
|
u64 val;
|
||||||
|
|
||||||
|
rdmsrl(MSR_AMD64_LS_CFG, val);
|
||||||
|
if (!(val & BIT(15)))
|
||||||
|
wrmsrl(MSR_AMD64_LS_CFG, val | BIT(15));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int amd_erratum_383[];
|
static const int amd_erratum_383[];
|
||||||
|
|
|
@ -266,6 +266,76 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs)
|
||||||
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
|
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
/*
|
||||||
|
* This cpu is going to be removed and its vectors migrated to the remaining
|
||||||
|
* online cpus. Check to see if there are enough vectors in the remaining cpus.
|
||||||
|
* This function is protected by stop_machine().
|
||||||
|
*/
|
||||||
|
int check_irq_vectors_for_cpu_disable(void)
|
||||||
|
{
|
||||||
|
int irq, cpu;
|
||||||
|
unsigned int this_cpu, vector, this_count, count;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
struct irq_data *data;
|
||||||
|
struct cpumask affinity_new, online_new;
|
||||||
|
|
||||||
|
this_cpu = smp_processor_id();
|
||||||
|
cpumask_copy(&online_new, cpu_online_mask);
|
||||||
|
cpu_clear(this_cpu, online_new);
|
||||||
|
|
||||||
|
this_count = 0;
|
||||||
|
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
|
||||||
|
irq = __this_cpu_read(vector_irq[vector]);
|
||||||
|
if (irq >= 0) {
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
data = irq_desc_get_irq_data(desc);
|
||||||
|
cpumask_copy(&affinity_new, data->affinity);
|
||||||
|
cpu_clear(this_cpu, affinity_new);
|
||||||
|
|
||||||
|
/* Do not count inactive or per-cpu irqs. */
|
||||||
|
if (!irq_has_action(irq) || irqd_is_per_cpu(data))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A single irq may be mapped to multiple
|
||||||
|
* cpu's vector_irq[] (for example IOAPIC cluster
|
||||||
|
* mode). In this case we have two
|
||||||
|
* possibilities:
|
||||||
|
*
|
||||||
|
* 1) the resulting affinity mask is empty; that is
|
||||||
|
* this the down'd cpu is the last cpu in the irq's
|
||||||
|
* affinity mask, or
|
||||||
|
*
|
||||||
|
* 2) the resulting affinity mask is no longer
|
||||||
|
* a subset of the online cpus but the affinity
|
||||||
|
* mask is not zero; that is the down'd cpu is the
|
||||||
|
* last online cpu in a user set affinity mask.
|
||||||
|
*/
|
||||||
|
if (cpumask_empty(&affinity_new) ||
|
||||||
|
!cpumask_subset(&affinity_new, &online_new))
|
||||||
|
this_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for_each_online_cpu(cpu) {
|
||||||
|
if (cpu == this_cpu)
|
||||||
|
continue;
|
||||||
|
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
|
||||||
|
vector++) {
|
||||||
|
if (per_cpu(vector_irq, cpu)[vector] < 0)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < this_count) {
|
||||||
|
pr_warn("CPU %d disable failed: CPU has %u vectors assigned and there are only %u available.\n",
|
||||||
|
this_cpu, this_count, count);
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
|
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
|
||||||
void fixup_irqs(void)
|
void fixup_irqs(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1312,6 +1312,12 @@ void cpu_disable_common(void)
|
||||||
|
|
||||||
int native_cpu_disable(void)
|
int native_cpu_disable(void)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = check_irq_vectors_for_cpu_disable();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
clear_local_APIC();
|
clear_local_APIC();
|
||||||
|
|
||||||
cpu_disable_common();
|
cpu_disable_common();
|
||||||
|
|
Loading…
Reference in New Issue