Merge branch 'x86/mm' into x86/platform, to pick up TLB flush dependency
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -548,8 +548,12 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
|
||||
|
||||
static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 dummy;
|
||||
|
||||
early_init_amd_mc(c);
|
||||
|
||||
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
|
||||
|
||||
/*
|
||||
* c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
|
||||
* with P/T states and does not stop in deep C-states
|
||||
@@ -612,6 +616,27 @@ static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
*/
|
||||
if (cpu_has_amd_erratum(c, amd_erratum_400))
|
||||
set_cpu_bug(c, X86_BUG_AMD_E400);
|
||||
|
||||
/*
|
||||
* BIOS support is required for SME. If BIOS has enabled SME then
|
||||
* adjust x86_phys_bits by the SME physical address space reduction
|
||||
* value. If BIOS has not enabled SME then don't advertise the
|
||||
* feature (set in scattered.c). Also, since the SME support requires
|
||||
* long mode, don't advertise the feature under CONFIG_X86_32.
|
||||
*/
|
||||
if (cpu_has(c, X86_FEATURE_SME)) {
|
||||
u64 msr;
|
||||
|
||||
/* Check if SME is enabled */
|
||||
rdmsrl(MSR_K8_SYSCFG, msr);
|
||||
if (msr & MSR_K8_SYSCFG_MEM_ENCRYPT) {
|
||||
c->x86_phys_bits -= (cpuid_ebx(0x8000001f) >> 6) & 0x3f;
|
||||
if (IS_ENABLED(CONFIG_X86_32))
|
||||
clear_cpu_cap(c, X86_FEATURE_SME);
|
||||
} else {
|
||||
clear_cpu_cap(c, X86_FEATURE_SME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void init_amd_k8(struct cpuinfo_x86 *c)
|
||||
@@ -730,8 +755,6 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
|
||||
|
||||
static void init_amd(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 dummy;
|
||||
|
||||
early_init_amd(c);
|
||||
|
||||
/*
|
||||
@@ -793,8 +816,6 @@ static void init_amd(struct cpuinfo_x86 *c)
|
||||
if (c->x86 > 0x11)
|
||||
set_cpu_cap(c, X86_FEATURE_ARAT);
|
||||
|
||||
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
|
||||
|
||||
/* 3DNow or LM implies PREFETCHW */
|
||||
if (!cpu_has(c, X86_FEATURE_3DNOWPREFETCH))
|
||||
if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))
|
||||
|
@@ -40,13 +40,16 @@ static void aperfmperf_snapshot_khz(void *dummy)
|
||||
struct aperfmperf_sample *s = this_cpu_ptr(&samples);
|
||||
ktime_t now = ktime_get();
|
||||
s64 time_delta = ktime_ms_delta(now, s->time);
|
||||
unsigned long flags;
|
||||
|
||||
/* Don't bother re-computing within the cache threshold time. */
|
||||
if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
rdmsrl(MSR_IA32_APERF, aperf);
|
||||
rdmsrl(MSR_IA32_MPERF, mperf);
|
||||
local_irq_restore(flags);
|
||||
|
||||
aperf_delta = aperf - s->aperf;
|
||||
mperf_delta = mperf - s->mperf;
|
||||
|
@@ -21,6 +21,14 @@
|
||||
|
||||
void __init check_bugs(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
* Regardless of whether PCID is enumerated, the SDM says
|
||||
* that it can't be enabled in 32-bit mode.
|
||||
*/
|
||||
setup_clear_cpu_cap(X86_FEATURE_PCID);
|
||||
#endif
|
||||
|
||||
identify_boot_cpu();
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SMP)) {
|
||||
|
@@ -168,6 +168,24 @@ static int __init x86_mpx_setup(char *s)
|
||||
}
|
||||
__setup("nompx", x86_mpx_setup);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
static int __init x86_pcid_setup(char *s)
|
||||
{
|
||||
/* require an exact match without trailing characters */
|
||||
if (strlen(s))
|
||||
return 0;
|
||||
|
||||
/* do not emit a message if the feature is not present */
|
||||
if (!boot_cpu_has(X86_FEATURE_PCID))
|
||||
return 1;
|
||||
|
||||
setup_clear_cpu_cap(X86_FEATURE_PCID);
|
||||
pr_info("nopcid: PCID feature disabled\n");
|
||||
return 1;
|
||||
}
|
||||
__setup("nopcid", x86_pcid_setup);
|
||||
#endif
|
||||
|
||||
static int __init x86_noinvpcid_setup(char *s)
|
||||
{
|
||||
/* noinvpcid doesn't accept parameters */
|
||||
@@ -311,6 +329,25 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c)
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_pcid(struct cpuinfo_x86 *c)
|
||||
{
|
||||
if (cpu_has(c, X86_FEATURE_PCID)) {
|
||||
if (cpu_has(c, X86_FEATURE_PGE)) {
|
||||
cr4_set_bits(X86_CR4_PCIDE);
|
||||
} else {
|
||||
/*
|
||||
* flush_tlb_all(), as currently implemented, won't
|
||||
* work if PCID is on but PGE is not. Since that
|
||||
* combination doesn't exist on real hardware, there's
|
||||
* no reason to try to fully support it, but it's
|
||||
* polite to avoid corrupting data if we're on
|
||||
* an improperly configured VM.
|
||||
*/
|
||||
clear_cpu_cap(c, X86_FEATURE_PCID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Protection Keys are not available in 32-bit mode.
|
||||
*/
|
||||
@@ -1125,6 +1162,9 @@ static void identify_cpu(struct cpuinfo_x86 *c)
|
||||
setup_smep(c);
|
||||
setup_smap(c);
|
||||
|
||||
/* Set up PCID */
|
||||
setup_pcid(c);
|
||||
|
||||
/*
|
||||
* The vendor-specific functions might have changed features.
|
||||
* Now we do "generic changes."
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include <asm/mce.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
#include "mce-internal.h"
|
||||
|
||||
@@ -1051,6 +1052,48 @@ static int do_memory_failure(struct mce *m)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(arch_unmap_kpfn) && defined(CONFIG_MEMORY_FAILURE)
|
||||
|
||||
void arch_unmap_kpfn(unsigned long pfn)
|
||||
{
|
||||
unsigned long decoy_addr;
|
||||
|
||||
/*
|
||||
* Unmap this page from the kernel 1:1 mappings to make sure
|
||||
* we don't log more errors because of speculative access to
|
||||
* the page.
|
||||
* We would like to just call:
|
||||
* set_memory_np((unsigned long)pfn_to_kaddr(pfn), 1);
|
||||
* but doing that would radically increase the odds of a
|
||||
* speculative access to the posion page because we'd have
|
||||
* the virtual address of the kernel 1:1 mapping sitting
|
||||
* around in registers.
|
||||
* Instead we get tricky. We create a non-canonical address
|
||||
* that looks just like the one we want, but has bit 63 flipped.
|
||||
* This relies on set_memory_np() not checking whether we passed
|
||||
* a legal address.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Build time check to see if we have a spare virtual bit. Don't want
|
||||
* to leave this until run time because most developers don't have a
|
||||
* system that can exercise this code path. This will only become a
|
||||
* problem if/when we move beyond 5-level page tables.
|
||||
*
|
||||
* Hard code "9" here because cpp doesn't grok ilog2(PTRS_PER_PGD)
|
||||
*/
|
||||
#if PGDIR_SHIFT + 9 < 63
|
||||
decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
|
||||
#else
|
||||
#error "no unused virtual bit available"
|
||||
#endif
|
||||
|
||||
if (set_memory_np(decoy_addr, 1))
|
||||
pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The actual machine check handler. This only handles real
|
||||
* exceptions when something got corrupted coming in through int 18.
|
||||
|
@@ -122,7 +122,7 @@ static struct attribute *thermal_throttle_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group thermal_attr_group = {
|
||||
static const struct attribute_group thermal_attr_group = {
|
||||
.attrs = thermal_throttle_attrs,
|
||||
.name = "thermal_throttle"
|
||||
};
|
||||
|
@@ -561,7 +561,7 @@ static struct attribute *mc_default_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group mc_attr_group = {
|
||||
static const struct attribute_group mc_attr_group = {
|
||||
.attrs = mc_default_attrs,
|
||||
.name = "microcode",
|
||||
};
|
||||
@@ -707,7 +707,7 @@ static struct attribute *cpu_root_microcode_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group cpu_root_microcode_group = {
|
||||
static const struct attribute_group cpu_root_microcode_group = {
|
||||
.name = "microcode",
|
||||
.attrs = cpu_root_microcode_attrs,
|
||||
};
|
||||
|
@@ -237,6 +237,18 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
||||
stop_machine(mtrr_rendezvous_handler, &data, cpu_online_mask);
|
||||
}
|
||||
|
||||
static void set_mtrr_cpuslocked(unsigned int reg, unsigned long base,
|
||||
unsigned long size, mtrr_type type)
|
||||
{
|
||||
struct set_mtrr_data data = { .smp_reg = reg,
|
||||
.smp_base = base,
|
||||
.smp_size = size,
|
||||
.smp_type = type
|
||||
};
|
||||
|
||||
stop_machine_cpuslocked(mtrr_rendezvous_handler, &data, cpu_online_mask);
|
||||
}
|
||||
|
||||
static void set_mtrr_from_inactive_cpu(unsigned int reg, unsigned long base,
|
||||
unsigned long size, mtrr_type type)
|
||||
{
|
||||
@@ -370,7 +382,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
|
||||
/* Search for an empty MTRR */
|
||||
i = mtrr_if->get_free_region(base, size, replace);
|
||||
if (i >= 0) {
|
||||
set_mtrr(i, base, size, type);
|
||||
set_mtrr_cpuslocked(i, base, size, type);
|
||||
if (likely(replace < 0)) {
|
||||
mtrr_usage_table[i] = 1;
|
||||
} else {
|
||||
@@ -378,7 +390,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
|
||||
if (increment)
|
||||
mtrr_usage_table[i]++;
|
||||
if (unlikely(replace != i)) {
|
||||
set_mtrr(replace, 0, 0, 0);
|
||||
set_mtrr_cpuslocked(replace, 0, 0, 0);
|
||||
mtrr_usage_table[replace] = 0;
|
||||
}
|
||||
}
|
||||
@@ -506,7 +518,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
|
||||
goto out;
|
||||
}
|
||||
if (--mtrr_usage_table[reg] < 1)
|
||||
set_mtrr(reg, 0, 0, 0);
|
||||
set_mtrr_cpuslocked(reg, 0, 0, 0);
|
||||
error = reg;
|
||||
out:
|
||||
mutex_unlock(&mtrr_mutex);
|
||||
|
@@ -31,6 +31,7 @@ static const struct cpuid_bit cpuid_bits[] = {
|
||||
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
|
||||
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
|
||||
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
|
||||
{ X86_FEATURE_SME, CPUID_EAX, 0, 0x8000001f, 0 },
|
||||
{ 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user