x86 fixes
Subsystems (2)
Linus,
Please pull the latest x86-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus
# HEAD: 0becc0ae5b42828785b589f686725ff5bc3b9b25 x86/mce: Make timer handling more robust
Misc fixes:
- two microcode loader fixes
- two FPU xstate handling fixes
- an MCE timer handling related crash fix
Thanks,
Ingo
------------------>
Borislav Petkov (2):
x86/microcode/intel: Drop stashed AP patch pointer optimization x86/microcode: Do not access the initrd after it has been freed
Kevin Hao (1):
x86/fpu: Set the xcomp_bv when we fake up a XSAVES area
Thomas Gleixner (1):
x86/mce: Make timer handling more robust
Yu-cheng Yu (1):
x86/fpu/xstate: Fix xcomp_bv in XSAVES header
arch/x86/include/asm/microcode.h | 1 + arch/x86/kernel/cpu/mcheck/mce.c | 31 ++++++++++++------------------- arch/x86/kernel/cpu/microcode/amd.c | 5 +++-- arch/x86/kernel/cpu/microcode/core.c | 22 +++++++++++++++++----- arch/x86/kernel/cpu/microcode/intel.c | 9 +-------- arch/x86/kernel/fpu/core.c | 4 +++- 6 files changed, 37 insertions(+), 35 deletions(-)
arch/x86/include/asm/microcode.h +1 -0
@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);extern void load_ucode_ap (void );void reload_early_microcode (void );extern bool get_builtin_firmware (struct cpio_data *cd,const char *name); +extern bool initrd_gone;#else static inline int __init microcode_init (void ) {return 0 ; };static inline void __init load_ucode_bsp (void ) { }
arch/x86/kernel/cpu/mcheck/mce.c +12 -19
@@ -1373,20 +1373,15 @@ static unsigned long mce_adjust_timer_default(unsigned long interval)static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default; -static void __restart_timer (struct timer_list *t,unsigned long interval) +static void __start_timer (struct timer_list *t,unsigned long interval) {unsigned long when = jiffies + interval;unsigned long flags;local_irq_save (flags); -if (timer_pending (t)) { -if (time_before (when, t->expires)) -mod_timer (t, when); - }else { - t->expires =round_jiffies (when); -add_timer_on (t,smp_processor_id ()); - } +if (!timer_pending (t) ||time_before (when, t->expires)) +mod_timer (t,round_jiffies (when));local_irq_restore (flags); }
@@ -1421,7 +1416,7 @@ static void mce_timer_fn(unsigned long data) done:__this_cpu_write (mce_next_interval, iv); -__restart_timer (t, iv); +__start_timer (t, iv); }/*
@@ -1432,7 +1427,7 @@ void mce_timer_kick(unsigned long interval)struct timer_list *t =this_cpu_ptr (&mce_timer);unsigned long iv =__this_cpu_read (mce_next_interval); -__restart_timer (t, interval); +__start_timer (t, interval);if (interval < iv)__this_cpu_write (mce_next_interval, interval);
@@ -1779,17 +1774,15 @@ static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c) } } -static void mce_start_timer (unsigned int cpu,struct timer_list *t) +static void mce_start_timer (struct timer_list *t) {unsigned long iv = check_interval *HZ ;if (mca_cfg.ignore_ce || !iv)return ; -per_cpu (mce_next_interval, cpu) = iv; - - t->expires =round_jiffies (jiffies + iv); -add_timer_on (t, cpu); +this_cpu_write (mce_next_interval, iv); +__start_timer (t, iv); }static void __mcheck_cpu_setup_timer (void )
@@ -1806,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void)unsigned int cpu =smp_processor_id ();setup_pinned_timer (t, mce_timer_fn, cpu); -mce_start_timer (cpu, t); +mce_start_timer (t); }/* Handle unconfigured int18 (should never happen) */
@@ -2566,7 +2559,7 @@ static int mce_cpu_dead(unsigned int cpu)static int mce_cpu_online (unsigned int cpu) { -struct timer_list *t = &per_cpu (mce_timer, cpu); +struct timer_list *t =this_cpu_ptr (&mce_timer);int ret;mce_device_create (cpu);
@@ -2577,13 +2570,13 @@ static int mce_cpu_online(unsigned int cpu)return ret; }mce_reenable_cpu (); -mce_start_timer (cpu, t); +mce_start_timer (t);return 0 ; }static int mce_cpu_pre_down (unsigned int cpu) { -struct timer_list *t = &per_cpu (mce_timer, cpu); +struct timer_list *t =this_cpu_ptr (&mce_timer);mce_disable_cpu ();del_timer_sync (t);
arch/x86/kernel/cpu/microcode/amd.c +3 -2
@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family) reget:if (!get_builtin_microcode (&cp, family)) {#ifdef CONFIG_BLK_DEV_INITRD - cp =find_cpio_data (ucode_path, (void *)initrd_start, - initrd_end - initrd_start,NULL ); +if (!initrd_gone) + cp =find_cpio_data (ucode_path, (void *)initrd_start, + initrd_end - initrd_start,NULL );#endif if (!(cp.data && cp.size)) {/*
arch/x86/kernel/cpu/microcode/core.c +17 -5
@@ -46,6 +46,8 @@static struct microcode_ops *microcode_ops;static bool dis_ucode_ldr = true; +bool initrd_gone; +LIST_HEAD (microcode_cache);/*
@@ -190,21 +192,24 @@ void load_ucode_ap(void)static int __init save_microcode_in_initrd (void ) {struct cpuinfo_x86 *c = &boot_cpu_data; +int ret = -EINVAL ;switch (c->x86_vendor) {case X86_VENDOR_INTEL :if (c->x86 >=6 ) -return save_microcode_in_initrd_intel (); + ret =save_microcode_in_initrd_intel ();break ;case X86_VENDOR_AMD :if (c->x86 >=0x10 ) -return save_microcode_in_initrd_amd (c->x86); + ret =save_microcode_in_initrd_amd (c->x86);break ;default :break ; } -return -EINVAL ; + initrd_gone = true; + +return ret; }struct cpio_data find_microcode_in_initrd (const char *path,bool use_pa)
@@ -247,9 +252,16 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)* 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. +* +* initrd_gone is for the hotplug case where we've thrown out initrd +* already. */ -if (!use_pa && initrd_start) - start = initrd_start; +if (!use_pa) { +if (initrd_gone) +return (struct cpio_data ){NULL ,0 ,"" }; +if (initrd_start) + start = initrd_start; + }return find_cpio_data (path, (void *)start, size,NULL );#else /* !CONFIG_BLK_DEV_INITRD */
arch/x86/kernel/cpu/microcode/intel.c +1 -8
@@ -41,7 +41,7 @@static const char ucode_path[] ="kernel/x86/microcode/GenuineIntel.bin" ; -/* Current microcode patch used in early patching */ +/* Current microcode patch used in early patching on the APs. */ struct microcode_intel *intel_ucode_patch; static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
@@ -607,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void)struct ucode_cpu_info uci;struct cpio_data cp; -/* -* AP loading didn't find any microcode patch, no need to save anything. -*/ -if (!intel_ucode_patch ||IS_ERR (intel_ucode_patch)) -return 0 ; -if (!load_builtin_intel_microcode (&cp)) cp =find_microcode_in_initrd (ucode_path, false);
@@ -628,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void)return 0 ; } -/* * @res_patch, output: a pointer to the patch we found. */
arch/x86/kernel/fpu/core.c +3 -1
@@ -9,6 +9,7 @@#include <asm/fpu/regset.h> #include <asm/fpu/signal.h> #include <asm/fpu/types.h> +#include <asm/fpu/xstate.h> #include <asm/traps.h> #include <linux/hardirq.h>
@@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state)* it will #GP. Make sure it is replaced after the memset(). */ if (static_cpu_has (X86_FEATURE_XSAVES )) - state->xsave.header.xcomp_bv =XCOMP_BV_COMPACTED_FORMAT ; + state->xsave.header.xcomp_bv =XCOMP_BV_COMPACTED_FORMAT | + xfeatures_mask;if (static_cpu_has (X86_FEATURE_FXSR ))fpstate_init_fxstate (&state->fxsave);