diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-23 16:54:46 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-23 16:54:46 -0800 |
commit | 6ac3bb167fed0b3d02b4fd3daa0d819841d5f6f4 (patch) | |
tree | 49f73d917f1cd7d848e9a48c9efffea8ab2f7142 /arch/x86/kernel/cpu | |
parent | eb3e8d9de28a5385f75e5c42eba5fb5b0c7625be (diff) | |
parent | c280f7736ab26a601932b1ce017a3840dbedcfdc (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
"There's a number of fixes:
- a round of fixes for CPUID-less legacy CPUs
- a number of microcode loader fixes
- i8042 detection robustization fixes
- stack dump/unwinder fixes
- x86 SoC platform driver fixes
- a GCC 7 warning fix
- virtualization related fixes"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits)
Revert "x86/unwind: Detect bad stack return address"
x86/paravirt: Mark unused patch_default label
x86/microcode/AMD: Reload proper initrd start address
x86/platform/intel/quark: Add printf attribute to imr_self_test_result()
x86/platform/intel-mid: Switch MPU3050 driver to IIO
x86/alternatives: Do not use sync_core() to serialize I$
x86/topology: Document cpu_llc_id
x86/hyperv: Handle unknown NMIs on one CPU when unknown_nmi_panic
x86/asm: Rewrite sync_core() to use IRET-to-self
x86/microcode/intel: Replace sync_core() with native_cpuid()
Revert "x86/boot: Fail the boot if !M486 and CPUID is missing"
x86/asm/32: Make sync_core() handle missing CPUID on all 32-bit kernels
x86/cpu: Probe CPUID leaf 6 even when cpuid_level == 6
x86/tools: Fix gcc-7 warning in relocs.c
x86/unwind: Dump stack data on warnings
x86/unwind: Adjust last frame check for aligned function stacks
x86/init: Fix a couple of comment typos
x86/init: Remove i8042_detect() from platform ops
Input: i8042 - Trust firmware a bit more when probing on X86
x86/init: Add i8042 state to the platform data
...
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 56 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 40 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 26 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mshyperv.c | 24 |
5 files changed, 108 insertions, 45 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 1f6b50a449ab..dc1697ca5191 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -667,13 +667,14 @@ void get_cpu_cap(struct cpuinfo_x86 *c) c->x86_capability[CPUID_1_EDX] = edx; } + /* Thermal and Power Management Leaf: level 0x00000006 (eax) */ + if (c->cpuid_level >= 0x00000006) + c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006); + /* Additional Intel-defined flags: level 0x00000007 */ if (c->cpuid_level >= 0x00000007) { cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); - c->x86_capability[CPUID_7_0_EBX] = ebx; - - c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006); c->x86_capability[CPUID_7_ECX] = ecx; } diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 6f353bdb3a25..6a31e2691f3a 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -116,10 +116,11 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table, /* * This scans the ucode blob for the proper container as we can have multiple - * containers glued together. + * containers glued together. Returns the equivalence ID from the equivalence + * table or 0 if none found. */ -static struct container -find_proper_container(u8 *ucode, size_t size, u16 *ret_id) +static u16 +find_proper_container(u8 *ucode, size_t size, struct container *ret_cont) { struct container ret = { NULL, 0 }; u32 eax, ebx, ecx, edx; @@ -138,7 +139,7 @@ find_proper_container(u8 *ucode, size_t size, u16 *ret_id) if (header[0] != UCODE_MAGIC || header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */ header[2] == 0) /* size */ - return ret; + return eq_id; eax = 0x00000001; ecx = 0; @@ -163,8 +164,9 @@ find_proper_container(u8 *ucode, size_t size, u16 *ret_id) * ucode update loop below */ left = ret.size - offset; - *ret_id = eq_id; - return ret; + + *ret_cont = ret; + return eq_id; } /* @@ -189,7 +191,7 @@ find_proper_container(u8 *ucode, size_t size, u16 *ret_id) ucode = data; } - return ret; + return eq_id; } static int __apply_microcode_amd(struct microcode_amd *mc_amd) @@ -214,17 +216,18 @@ static int __apply_microcode_amd(struct microcode_amd *mc_amd) * and on 32-bit during save_microcode_in_initrd_amd() -- we can call * load_microcode_amd() to save equivalent cpu table and microcode patches in * kernel heap memory. + * + * Returns true if container found (sets @ret_cont), false otherwise. */ -static struct container -apply_microcode_early_amd(void *ucode, size_t size, bool save_patch) +static bool apply_microcode_early_amd(void *ucode, size_t size, bool save_patch, + struct container *ret_cont) { - struct container ret = { NULL, 0 }; u8 (*patch)[PATCH_MAX_SIZE]; + u32 rev, *header, *new_rev; + struct container ret; int offset, left; - u32 rev, *header; - u8 *data; u16 eq_id = 0; - u32 *new_rev; + u8 *data; #ifdef CONFIG_X86_32 new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); @@ -235,11 +238,11 @@ apply_microcode_early_amd(void *ucode, size_t size, bool save_patch) #endif if (check_current_patch_level(&rev, true)) - return (struct container){ NULL, 0 }; + return false; - ret = find_proper_container(ucode, size, &eq_id); + eq_id = find_proper_container(ucode, size, &ret); if (!eq_id) - return (struct container){ NULL, 0 }; + return false; this_equiv_id = eq_id; header = (u32 *)ret.data; @@ -273,7 +276,11 @@ apply_microcode_early_amd(void *ucode, size_t size, bool save_patch) data += offset; left -= offset; } - return ret; + + if (ret_cont) + *ret_cont = ret; + + return true; } static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family) @@ -294,6 +301,7 @@ static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family) void __init load_ucode_amd_bsp(unsigned int family) { struct ucode_cpu_info *uci; + u32 eax, ebx, ecx, edx; struct cpio_data cp; const char *path; bool use_pa; @@ -315,9 +323,12 @@ void __init load_ucode_amd_bsp(unsigned int family) return; /* Get BSP's CPUID.EAX(1), needed in load_microcode_amd() */ - uci->cpu_sig.sig = cpuid_eax(1); + eax = 1; + ecx = 0; + native_cpuid(&eax, &ebx, &ecx, &edx); + uci->cpu_sig.sig = eax; - apply_microcode_early_amd(cp.data, cp.size, true); + apply_microcode_early_amd(cp.data, cp.size, true, NULL); } #ifdef CONFIG_X86_32 @@ -349,7 +360,7 @@ void load_ucode_amd_ap(unsigned int family) * This would set amd_ucode_patch above so that the following APs can * use it directly instead of going down this path again. */ - apply_microcode_early_amd(cp.data, cp.size, true); + apply_microcode_early_amd(cp.data, cp.size, true, NULL); } #else void load_ucode_amd_ap(unsigned int family) @@ -387,8 +398,7 @@ reget: } } - cont = apply_microcode_early_amd(cp.data, cp.size, false); - if (!(cont.data && cont.size)) { + if (!apply_microcode_early_amd(cp.data, cp.size, false, &cont)) { cont.size = -1; return; } @@ -443,7 +453,7 @@ int __init save_microcode_in_initrd_amd(unsigned int fam) return -EINVAL; } - cont = find_proper_container(cp.data, cp.size, &eq_id); + eq_id = find_proper_container(cp.data, cp.size, &cont); if (!eq_id) { cont.size = -1; return -EINVAL; diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 6996413c78c3..2af69d27da62 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -44,7 +44,7 @@ #define DRIVER_VERSION "2.2" static struct microcode_ops *microcode_ops; -static bool dis_ucode_ldr; +static bool dis_ucode_ldr = true; LIST_HEAD(microcode_cache); @@ -76,6 +76,7 @@ struct cpu_info_ctx { static bool __init check_loader_disabled_bsp(void) { static const char *__dis_opt_str = "dis_ucode_ldr"; + u32 a, b, c, d; #ifdef CONFIG_X86_32 const char *cmdline = (const char *)__pa_nodebug(boot_command_line); @@ -88,8 +89,23 @@ static bool __init check_loader_disabled_bsp(void) bool *res = &dis_ucode_ldr; #endif - if (cmdline_find_option_bool(cmdline, option)) - *res = true; + if (!have_cpuid_p()) + return *res; + + a = 1; + c = 0; + native_cpuid(&a, &b, &c, &d); + + /* + * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not + * completely accurate as xen pv guests don't see that CPUID bit set but + * that's good enough as they don't land on the BSP path anyway. + */ + if (c & BIT(31)) + return *res; + + if (cmdline_find_option_bool(cmdline, option) <= 0) + *res = false; return *res; } @@ -121,9 +137,6 @@ void __init load_ucode_bsp(void) if (check_loader_disabled_bsp()) return; - if (!have_cpuid_p()) - return; - vendor = x86_cpuid_vendor(); family = x86_cpuid_family(); @@ -157,9 +170,6 @@ void load_ucode_ap(void) if (check_loader_disabled_ap()) return; - if (!have_cpuid_p()) - return; - vendor = x86_cpuid_vendor(); family = x86_cpuid_family(); @@ -233,14 +243,12 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa) # endif /* - * Did we relocate the ramdisk? - * - * So we possibly relocate the ramdisk *after* applying microcode on the - * BSP so we rely on use_pa (use physical addresses) - even if it is not - * absolutely correct - to determine whether we've done the ramdisk - * relocation already. + * Fixup the start address: after reserve_initrd() runs, initrd_start + * has the virtual address of the beginning of the initrd. It also + * possibly relocates the ramdisk. In either case, initrd_start contains + * the updated address so use that instead. */ - if (!use_pa && relocated_ramdisk) + if (!use_pa && initrd_start) start = initrd_start; return find_cpio_data(path, (void *)start, size, NULL); diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 54d50c3694d8..b624b54912e1 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -368,6 +368,26 @@ next: return patch; } +static void cpuid_1(void) +{ + /* + * According to the Intel SDM, Volume 3, 9.11.7: + * + * CPUID returns a value in a model specific register in + * addition to its usual register return values. The + * semantics of CPUID cause it to deposit an update ID value + * in the 64-bit model-specific register at address 08BH + * (IA32_BIOS_SIGN_ID). If no update is present in the + * processor, the value in the MSR remains unmodified. + * + * Use native_cpuid -- this code runs very early and we don't + * want to mess with paravirt. + */ + unsigned int eax = 1, ebx, ecx = 0, edx; + + native_cpuid(&eax, &ebx, &ecx, &edx); +} + static int collect_cpu_info_early(struct ucode_cpu_info *uci) { unsigned int val[2]; @@ -393,7 +413,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) native_wrmsrl(MSR_IA32_UCODE_REV, 0); /* As documented in the SDM: Do a CPUID 1 here */ - sync_core(); + cpuid_1(); /* get the current revision from MSR 0x8B */ native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); @@ -593,7 +613,7 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) native_wrmsrl(MSR_IA32_UCODE_REV, 0); /* As documented in the SDM: Do a CPUID 1 here */ - sync_core(); + cpuid_1(); /* get the current revision from MSR 0x8B */ native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); @@ -805,7 +825,7 @@ static int apply_microcode_intel(int cpu) wrmsrl(MSR_IA32_UCODE_REV, 0); /* As documented in the SDM: Do a CPUID 1 here */ - sync_core(); + cpuid_1(); /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 6c044543545e..f37e02e41a77 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -30,6 +30,7 @@ #include <asm/apic.h> #include <asm/timer.h> #include <asm/reboot.h> +#include <asm/nmi.h> struct ms_hyperv_info ms_hyperv; EXPORT_SYMBOL_GPL(ms_hyperv); @@ -157,6 +158,26 @@ static unsigned char hv_get_nmi_reason(void) return 0; } +#ifdef CONFIG_X86_LOCAL_APIC +/* + * Prior to WS2016 Debug-VM sends NMIs to all CPUs which makes + * it dificult to process CHANNELMSG_UNLOAD in case of crash. Handle + * unknown NMI on the first CPU which gets it. + */ +static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs) +{ + static atomic_t nmi_cpu = ATOMIC_INIT(-1); + + if (!unknown_nmi_panic) + return NMI_DONE; + + if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1) + return NMI_HANDLED; + + return NMI_DONE; +} +#endif + static void __init ms_hyperv_init_platform(void) { /* @@ -182,6 +203,9 @@ static void __init ms_hyperv_init_platform(void) pr_info("HyperV: LAPIC Timer Frequency: %#x\n", lapic_timer_frequency); } + + register_nmi_handler(NMI_UNKNOWN, hv_nmi_unknown, NMI_FLAG_FIRST, + "hv_nmi_unknown"); #endif if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) |