Commit d4e860ea 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 fixes for x86:

   - Make Xen PV guest deal with speculative store bypass correctly

   - Address more fallout from the 5-Level pagetable handling. Undo an
     __initdata annotation to avoid section mismatch and malfunction
     when post init code would touch the freed variable.

   - Handle exception fixup in math_error() before calling notify_die().
     The reverse call order incorrectly triggers notify_die() listeners
     for soemthing which is handled correctly at the site which issues
     the floating point instruction.

   - Fix an off by one in the LLC topology calculation on AMD

   - Handle non standard memory block sizes gracefully un UV platforms

   - Plug a memory leak in the microcode loader

   - Sanitize the purgatory build magic

   - Add the x86 specific device tree bindings directory to the x86
     MAINTAINER file patterns"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm: Fix 'no5lvl' handling
  Revert "x86/mm: Mark __pgtable_l5_enabled __initdata"
  x86/CPU/AMD: Fix LLC ID bit-shift calculation
  MAINTAINERS: Add file patterns for x86 device tree bindings
  x86/microcode/intel: Fix memleak in save_microcode_patch()
  x86/platform/UV: Add kernel parameter to set memory block size
  x86/platform/UV: Use new set memory block size function
  x86/platform/UV: Add adjustable set memory block size function
  x86/build: Remove unnecessary preparation for purgatory
  Revert "kexec/purgatory: Add clean-up for purgatory directory"
  x86/xen: Add call of speculative_store_bypass_ht_init() to PV paths
  x86: Call fixup_exception() before notify_die() in math_error()
parents 177d363e 2458e53f
...@@ -15572,6 +15572,7 @@ M: x86@kernel.org ...@@ -15572,6 +15572,7 @@ 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
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/x86/
F: Documentation/x86/ F: Documentation/x86/
F: arch/x86/ F: arch/x86/
......
...@@ -258,11 +258,6 @@ archscripts: scripts_basic ...@@ -258,11 +258,6 @@ archscripts: scripts_basic
archheaders: archheaders:
$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
archprepare:
ifeq ($(CONFIG_KEXEC_FILE),y)
$(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c
endif
### ###
# Kernel objects # Kernel objects
...@@ -327,7 +322,6 @@ archclean: ...@@ -327,7 +322,6 @@ archclean:
$(Q)rm -rf $(objtree)/arch/x86_64 $(Q)rm -rf $(objtree)/arch/x86_64
$(Q)$(MAKE) $(clean)=$(boot) $(Q)$(MAKE) $(clean)=$(boot)
$(Q)$(MAKE) $(clean)=arch/x86/tools $(Q)$(MAKE) $(clean)=arch/x86/tools
$(Q)$(MAKE) $(clean)=arch/x86/purgatory
define archhelp define archhelp
echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)' echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/memory.h>
#include <asm/uv/uv_mmrs.h> #include <asm/uv/uv_mmrs.h>
#include <asm/uv/uv_hub.h> #include <asm/uv/uv_hub.h>
...@@ -392,6 +393,51 @@ extern int uv_hub_info_version(void) ...@@ -392,6 +393,51 @@ extern int uv_hub_info_version(void)
} }
EXPORT_SYMBOL(uv_hub_info_version); EXPORT_SYMBOL(uv_hub_info_version);
/* Default UV memory block size is 2GB */
static unsigned long mem_block_size = (2UL << 30);
/* Kernel parameter to specify UV mem block size */
static int parse_mem_block_size(char *ptr)
{
unsigned long size = memparse(ptr, NULL);
/* Size will be rounded down by set_block_size() below */
mem_block_size = size;
return 0;
}
early_param("uv_memblksize", parse_mem_block_size);
static __init int adj_blksize(u32 lgre)
{
unsigned long base = (unsigned long)lgre << UV_GAM_RANGE_SHFT;
unsigned long size;
for (size = mem_block_size; size > MIN_MEMORY_BLOCK_SIZE; size >>= 1)
if (IS_ALIGNED(base, size))
break;
if (size >= mem_block_size)
return 0;
mem_block_size = size;
return 1;
}
static __init void set_block_size(void)
{
unsigned int order = ffs(mem_block_size);
if (order) {
/* adjust for ffs return of 1..64 */
set_memory_block_size_order(order - 1);
pr_info("UV: mem_block_size set to 0x%lx\n", mem_block_size);
} else {
/* bad or zero value, default to 1UL << 31 (2GB) */
pr_err("UV: mem_block_size error with 0x%lx\n", mem_block_size);
set_memory_block_size_order(31);
}
}
/* Build GAM range lookup table: */ /* Build GAM range lookup table: */
static __init void build_uv_gr_table(void) static __init void build_uv_gr_table(void)
{ {
...@@ -1180,23 +1226,30 @@ static void __init decode_gam_rng_tbl(unsigned long ptr) ...@@ -1180,23 +1226,30 @@ static void __init decode_gam_rng_tbl(unsigned long ptr)
<< UV_GAM_RANGE_SHFT); << UV_GAM_RANGE_SHFT);
int order = 0; int order = 0;
char suffix[] = " KMGTPE"; char suffix[] = " KMGTPE";
int flag = ' ';
while (size > 9999 && order < sizeof(suffix)) { while (size > 9999 && order < sizeof(suffix)) {
size /= 1024; size /= 1024;
order++; order++;
} }
/* adjust max block size to current range start */
if (gre->type == 1 || gre->type == 2)
if (adj_blksize(lgre))
flag = '*';
if (!index) { if (!index) {
pr_info("UV: GAM Range Table...\n"); pr_info("UV: GAM Range Table...\n");
pr_info("UV: # %20s %14s %5s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN"); pr_info("UV: # %20s %14s %6s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN");
} }
pr_info("UV: %2d: 0x%014lx-0x%014lx %5lu%c %3d %04x %02x %02x\n", pr_info("UV: %2d: 0x%014lx-0x%014lx%c %5lu%c %3d %04x %02x %02x\n",
index++, index++,
(unsigned long)lgre << UV_GAM_RANGE_SHFT, (unsigned long)lgre << UV_GAM_RANGE_SHFT,
(unsigned long)gre->limit << UV_GAM_RANGE_SHFT, (unsigned long)gre->limit << UV_GAM_RANGE_SHFT,
size, suffix[order], flag, size, suffix[order],
gre->type, gre->nasid, gre->sockid, gre->pnode); gre->type, gre->nasid, gre->sockid, gre->pnode);
/* update to next range start */
lgre = gre->limit; lgre = gre->limit;
if (sock_min > gre->sockid) if (sock_min > gre->sockid)
sock_min = gre->sockid; sock_min = gre->sockid;
...@@ -1427,6 +1480,7 @@ static void __init uv_system_init_hub(void) ...@@ -1427,6 +1480,7 @@ static void __init uv_system_init_hub(void)
build_socket_tables(); build_socket_tables();
build_uv_gr_table(); build_uv_gr_table();
set_block_size();
uv_init_hub_info(&hub_info); uv_init_hub_info(&hub_info);
uv_possible_blades = num_possible_nodes(); uv_possible_blades = num_possible_nodes();
if (!_node_to_pnode) if (!_node_to_pnode)
......
...@@ -671,7 +671,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id) ...@@ -671,7 +671,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
num_sharing_cache = ((eax >> 14) & 0xfff) + 1; num_sharing_cache = ((eax >> 14) & 0xfff) + 1;
if (num_sharing_cache) { if (num_sharing_cache) {
int bits = get_count_order(num_sharing_cache) - 1; int bits = get_count_order(num_sharing_cache);
per_cpu(cpu_llc_id, cpu) = c->apicid >> bits; per_cpu(cpu_llc_id, cpu) = c->apicid >> bits;
} }
......
/* cpu_feature_enabled() cannot be used this early */
#define USE_EARLY_PGTABLE_L5
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/bitops.h> #include <linux/bitops.h>
......
...@@ -190,8 +190,11 @@ static void save_microcode_patch(void *data, unsigned int size) ...@@ -190,8 +190,11 @@ static void save_microcode_patch(void *data, unsigned int size)
p = memdup_patch(data, size); p = memdup_patch(data, size);
if (!p) if (!p)
pr_err("Error allocating buffer %p\n", data); pr_err("Error allocating buffer %p\n", data);
else else {
list_replace(&iter->plist, &p->plist); list_replace(&iter->plist, &p->plist);
kfree(iter->data);
kfree(iter);
}
} }
} }
......
...@@ -44,7 +44,7 @@ static unsigned int __initdata next_early_pgt; ...@@ -44,7 +44,7 @@ static unsigned int __initdata next_early_pgt;
pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX); pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
#ifdef CONFIG_X86_5LEVEL #ifdef CONFIG_X86_5LEVEL
unsigned int __pgtable_l5_enabled __initdata; unsigned int __pgtable_l5_enabled __ro_after_init;
unsigned int pgdir_shift __ro_after_init = 39; unsigned int pgdir_shift __ro_after_init = 39;
EXPORT_SYMBOL(pgdir_shift); EXPORT_SYMBOL(pgdir_shift);
unsigned int ptrs_per_p4d __ro_after_init = 1; unsigned int ptrs_per_p4d __ro_after_init = 1;
......
...@@ -835,16 +835,18 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) ...@@ -835,16 +835,18 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" : char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" :
"simd exception"; "simd exception";
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
return;
cond_local_irq_enable(regs); cond_local_irq_enable(regs);
if (!user_mode(regs)) { if (!user_mode(regs)) {
if (!fixup_exception(regs, trapnr)) { if (fixup_exception(regs, trapnr))
return;
task->thread.error_code = error_code; task->thread.error_code = error_code;
task->thread.trap_nr = trapnr; task->thread.trap_nr = trapnr;
if (notify_die(DIE_TRAP, str, regs, error_code,
trapnr, SIGFPE) != NOTIFY_STOP)
die(str, regs, error_code); die(str, regs, error_code);
}
return; return;
} }
......
...@@ -1350,16 +1350,28 @@ int kern_addr_valid(unsigned long addr) ...@@ -1350,16 +1350,28 @@ int kern_addr_valid(unsigned long addr)
/* Amount of ram needed to start using large blocks */ /* Amount of ram needed to start using large blocks */
#define MEM_SIZE_FOR_LARGE_BLOCK (64UL << 30) #define MEM_SIZE_FOR_LARGE_BLOCK (64UL << 30)
/* Adjustable memory block size */
static unsigned long set_memory_block_size;
int __init set_memory_block_size_order(unsigned int order)
{
unsigned long size = 1UL << order;
if (size > MEM_SIZE_FOR_LARGE_BLOCK || size < MIN_MEMORY_BLOCK_SIZE)
return -EINVAL;
set_memory_block_size = size;
return 0;
}
static unsigned long probe_memory_block_size(void) static unsigned long probe_memory_block_size(void)
{ {
unsigned long boot_mem_end = max_pfn << PAGE_SHIFT; unsigned long boot_mem_end = max_pfn << PAGE_SHIFT;
unsigned long bz; unsigned long bz;
/* If this is UV system, always set 2G block size */ /* If memory block size has been set, then use it */
if (is_uv_system()) { bz = set_memory_block_size;
bz = MAX_BLOCK_SIZE; if (bz)
goto done; goto done;
}
/* Use regular block if RAM is smaller than MEM_SIZE_FOR_LARGE_BLOCK */ /* Use regular block if RAM is smaller than MEM_SIZE_FOR_LARGE_BLOCK */
if (boot_mem_end < MEM_SIZE_FOR_LARGE_BLOCK) { if (boot_mem_end < MEM_SIZE_FOR_LARGE_BLOCK) {
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <xen/interface/vcpu.h> #include <xen/interface/vcpu.h>
#include <xen/interface/xenpmu.h> #include <xen/interface/xenpmu.h>
#include <asm/spec-ctrl.h>
#include <asm/xen/interface.h> #include <asm/xen/interface.h>
#include <asm/xen/hypercall.h> #include <asm/xen/hypercall.h>
...@@ -70,6 +71,8 @@ static void cpu_bringup(void) ...@@ -70,6 +71,8 @@ static void cpu_bringup(void)
cpu_data(cpu).x86_max_cores = 1; cpu_data(cpu).x86_max_cores = 1;
set_cpu_sibling_map(cpu); set_cpu_sibling_map(cpu);
speculative_store_bypass_ht_init();
xen_setup_cpu_clockevents(); xen_setup_cpu_clockevents();
notify_cpu_starting(cpu); notify_cpu_starting(cpu);
...@@ -250,6 +253,8 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus) ...@@ -250,6 +253,8 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus)
} }
set_cpu_sibling_map(0); set_cpu_sibling_map(0);
speculative_store_bypass_ht_init();
xen_pmu_init(0); xen_pmu_init(0);
if (xen_smp_intr_init(0) || xen_smp_intr_init_pv(0)) if (xen_smp_intr_init(0) || xen_smp_intr_init_pv(0))
......
...@@ -38,6 +38,7 @@ struct memory_block { ...@@ -38,6 +38,7 @@ struct memory_block {
int arch_get_memory_phys_device(unsigned long start_pfn); int arch_get_memory_phys_device(unsigned long start_pfn);
unsigned long memory_block_size_bytes(void); unsigned long memory_block_size_bytes(void);
int set_memory_block_size_order(unsigned int order);
/* These states are exposed to userspace as text strings in sysfs */ /* These states are exposed to userspace as text strings in sysfs */
#define MEM_ONLINE (1<<0) /* exposed to userspace */ #define MEM_ONLINE (1<<0) /* exposed to userspace */
......
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