Commit 32c6cdf7 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:
 "A set of small fixes for 4.15:

   - Fix vmapped stack synchronization on systems with 4-level paging
     and a large amount of memory caused by a missing 5-level folding
     which made the pgd synchronization logic to fail and causing double
     faults.

   - Add a missing sanity check in the vmalloc_fault() logic on 5-level
     paging systems.

   - Bring back protection against accessing a freed initrd in the
     microcode loader which was lost by a wrong merge conflict
     resolution.

   - Extend the Broadwell micro code loading sanity check.

   - Add a missing ENDPROC annotation in ftrace assembly code which
     makes ORC unhappy.

   - Prevent loading the AMD power module on !AMD platforms. The load
     itself is uncritical, but an unload attempt results in a kernel
     crash.

   - Update Peter Anvins role in the MAINTAINERS file"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/ftrace: Add one more ENDPROC annotation
  x86: Mark hpa as a "Designated Reviewer" for the time being
  x86/mm/64: Tighten up vmalloc_fault() sanity checks on 5-level kernels
  x86/mm/64: Fix vmapped stack syncing on very-large-memory 4-level systems
  x86/microcode: Fix again accessing initrd after having been freed
  x86/microcode/intel: Extend BDW late-loading further with LLC size check
  perf/x86/amd/power: Do not load AMD power module on !AMD platforms
parents 07b0137c dd085168
...@@ -6617,16 +6617,6 @@ L: linux-i2c@vger.kernel.org ...@@ -6617,16 +6617,6 @@ L: linux-i2c@vger.kernel.org
S: Maintained S: Maintained
F: drivers/i2c/i2c-stub.c F: drivers/i2c/i2c-stub.c
i386 BOOT CODE
M: "H. Peter Anvin" <hpa@zytor.com>
S: Maintained
F: arch/x86/boot/
i386 SETUP CODE / CPU ERRATA WORKAROUNDS
M: "H. Peter Anvin" <hpa@zytor.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup.git
S: Maintained
IA64 (Itanium) PLATFORM IA64 (Itanium) PLATFORM
M: Tony Luck <tony.luck@intel.com> M: Tony Luck <tony.luck@intel.com>
M: Fenghua Yu <fenghua.yu@intel.com> M: Fenghua Yu <fenghua.yu@intel.com>
...@@ -14866,7 +14856,7 @@ F: net/x25/ ...@@ -14866,7 +14856,7 @@ F: net/x25/
X86 ARCHITECTURE (32-BIT AND 64-BIT) X86 ARCHITECTURE (32-BIT AND 64-BIT)
M: Thomas Gleixner <tglx@linutronix.de> M: Thomas Gleixner <tglx@linutronix.de>
M: Ingo Molnar <mingo@redhat.com> M: Ingo Molnar <mingo@redhat.com>
M: "H. Peter Anvin" <hpa@zytor.com> R: "H. Peter Anvin" <hpa@zytor.com>
M: x86@kernel.org M: x86@kernel.org
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
......
...@@ -277,7 +277,7 @@ static int __init amd_power_pmu_init(void) ...@@ -277,7 +277,7 @@ static int __init amd_power_pmu_init(void)
int ret; int ret;
if (!x86_match_cpu(cpu_match)) if (!x86_match_cpu(cpu_match))
return 0; return -ENODEV;
if (!boot_cpu_has(X86_FEATURE_ACC_POWER)) if (!boot_cpu_has(X86_FEATURE_ACC_POWER))
return -ENODEV; return -ENODEV;
......
...@@ -239,7 +239,7 @@ static int __init save_microcode_in_initrd(void) ...@@ -239,7 +239,7 @@ static int __init save_microcode_in_initrd(void)
break; break;
case X86_VENDOR_AMD: case X86_VENDOR_AMD:
if (c->x86 >= 0x10) if (c->x86 >= 0x10)
return save_microcode_in_initrd_amd(cpuid_eax(1)); ret = save_microcode_in_initrd_amd(cpuid_eax(1));
break; break;
default: default:
break; break;
......
...@@ -45,6 +45,9 @@ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin"; ...@@ -45,6 +45,9 @@ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
/* Current microcode patch used in early patching on the APs. */ /* Current microcode patch used in early patching on the APs. */
static struct microcode_intel *intel_ucode_patch; static struct microcode_intel *intel_ucode_patch;
/* last level cache size per core */
static int llc_size_per_core;
static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1, static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
unsigned int s2, unsigned int p2) unsigned int s2, unsigned int p2)
{ {
...@@ -912,12 +915,14 @@ static bool is_blacklisted(unsigned int cpu) ...@@ -912,12 +915,14 @@ static bool is_blacklisted(unsigned int cpu)
/* /*
* Late loading on model 79 with microcode revision less than 0x0b000021 * Late loading on model 79 with microcode revision less than 0x0b000021
* may result in a system hang. This behavior is documented in item * and LLC size per core bigger than 2.5MB may result in a system hang.
* BDF90, #334165 (Intel Xeon Processor E7-8800/4800 v4 Product Family). * This behavior is documented in item BDF90, #334165 (Intel Xeon
* Processor E7-8800/4800 v4 Product Family).
*/ */
if (c->x86 == 6 && if (c->x86 == 6 &&
c->x86_model == INTEL_FAM6_BROADWELL_X && c->x86_model == INTEL_FAM6_BROADWELL_X &&
c->x86_mask == 0x01 && c->x86_mask == 0x01 &&
llc_size_per_core > 2621440 &&
c->microcode < 0x0b000021) { c->microcode < 0x0b000021) {
pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode); pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
...@@ -975,6 +980,15 @@ static struct microcode_ops microcode_intel_ops = { ...@@ -975,6 +980,15 @@ static struct microcode_ops microcode_intel_ops = {
.apply_microcode = apply_microcode_intel, .apply_microcode = apply_microcode_intel,
}; };
static int __init calc_llc_size_per_core(struct cpuinfo_x86 *c)
{
u64 llc_size = c->x86_cache_size * 1024;
do_div(llc_size, c->x86_max_cores);
return (int)llc_size;
}
struct microcode_ops * __init init_intel_microcode(void) struct microcode_ops * __init init_intel_microcode(void)
{ {
struct cpuinfo_x86 *c = &boot_cpu_data; struct cpuinfo_x86 *c = &boot_cpu_data;
...@@ -985,5 +999,7 @@ struct microcode_ops * __init init_intel_microcode(void) ...@@ -985,5 +999,7 @@ struct microcode_ops * __init init_intel_microcode(void)
return NULL; return NULL;
} }
llc_size_per_core = calc_llc_size_per_core(c);
return &microcode_intel_ops; return &microcode_intel_ops;
} }
...@@ -295,7 +295,7 @@ trace: ...@@ -295,7 +295,7 @@ trace:
restore_mcount_regs restore_mcount_regs
jmp fgraph_trace jmp fgraph_trace
END(function_hook) ENDPROC(function_hook)
#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_DYNAMIC_FTRACE */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
......
...@@ -439,19 +439,14 @@ static noinline int vmalloc_fault(unsigned long address) ...@@ -439,19 +439,14 @@ static noinline int vmalloc_fault(unsigned long address)
if (pgd_none(*pgd_ref)) if (pgd_none(*pgd_ref))
return -1; return -1;
if (CONFIG_PGTABLE_LEVELS > 4) {
if (pgd_none(*pgd)) { if (pgd_none(*pgd)) {
set_pgd(pgd, *pgd_ref); set_pgd(pgd, *pgd_ref);
arch_flush_lazy_mmu_mode(); arch_flush_lazy_mmu_mode();
} else if (CONFIG_PGTABLE_LEVELS > 4) { } else {
/*
* With folded p4d, pgd_none() is always false, so the pgd may
* point to an empty page table entry and pgd_page_vaddr()
* will return garbage.
*
* We will do the correct sanity check on the p4d level.
*/
BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
} }
}
/* With 4-level paging, copying happens on the p4d level. */ /* With 4-level paging, copying happens on the p4d level. */
p4d = p4d_offset(pgd, address); p4d = p4d_offset(pgd, address);
...@@ -459,7 +454,7 @@ static noinline int vmalloc_fault(unsigned long address) ...@@ -459,7 +454,7 @@ static noinline int vmalloc_fault(unsigned long address)
if (p4d_none(*p4d_ref)) if (p4d_none(*p4d_ref))
return -1; return -1;
if (p4d_none(*p4d)) { if (p4d_none(*p4d) && CONFIG_PGTABLE_LEVELS == 4) {
set_p4d(p4d, *p4d_ref); set_p4d(p4d, *p4d_ref);
arch_flush_lazy_mmu_mode(); arch_flush_lazy_mmu_mode();
} else { } else {
...@@ -470,6 +465,7 @@ static noinline int vmalloc_fault(unsigned long address) ...@@ -470,6 +465,7 @@ static noinline int vmalloc_fault(unsigned long address)
* Below here mismatches are bugs because these lower tables * Below here mismatches are bugs because these lower tables
* are shared: * are shared:
*/ */
BUILD_BUG_ON(CONFIG_PGTABLE_LEVELS < 4);
pud = pud_offset(p4d, address); pud = pud_offset(p4d, address);
pud_ref = pud_offset(p4d_ref, address); pud_ref = pud_offset(p4d_ref, address);
......
...@@ -151,6 +151,34 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -151,6 +151,34 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
local_irq_restore(flags); local_irq_restore(flags);
} }
static void sync_current_stack_to_mm(struct mm_struct *mm)
{
unsigned long sp = current_stack_pointer;
pgd_t *pgd = pgd_offset(mm, sp);
if (CONFIG_PGTABLE_LEVELS > 4) {
if (unlikely(pgd_none(*pgd))) {
pgd_t *pgd_ref = pgd_offset_k(sp);
set_pgd(pgd, *pgd_ref);
}
} else {
/*
* "pgd" is faked. The top level entries are "p4d"s, so sync
* the p4d. This compiles to approximately the same code as
* the 5-level case.
*/
p4d_t *p4d = p4d_offset(pgd, sp);
if (unlikely(p4d_none(*p4d))) {
pgd_t *pgd_ref = pgd_offset_k(sp);
p4d_t *p4d_ref = p4d_offset(pgd_ref, sp);
set_p4d(p4d, *p4d_ref);
}
}
}
void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk) struct task_struct *tsk)
{ {
...@@ -226,11 +254,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, ...@@ -226,11 +254,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
* mapped in the new pgd, we'll double-fault. Forcibly * mapped in the new pgd, we'll double-fault. Forcibly
* map it. * map it.
*/ */
unsigned int index = pgd_index(current_stack_pointer); sync_current_stack_to_mm(next);
pgd_t *pgd = next->pgd + index;
if (unlikely(pgd_none(*pgd)))
set_pgd(pgd, init_mm.pgd[index]);
} }
/* Stop remote flushes for the previous mm */ /* Stop remote flushes for the previous mm */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment