Commit 34e00acc 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 Ingo Molnar:
 "Misc fixes:

   - two microcode loader fixes

   - two FPU xstate handling fixes

   - an MCE timer handling related crash fix"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mce: Make timer handling more robust
  x86/microcode: Do not access the initrd after it has been freed
  x86/fpu/xstate: Fix xcomp_bv in XSAVES header
  x86/fpu: Set the xcomp_bv when we fake up a XSAVES area
  x86/microcode/intel: Drop stashed AP patch pointer optimization
parents 891aa1e0 0becc0ae
...@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void); ...@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void); extern void load_ucode_ap(void);
void reload_early_microcode(void); void reload_early_microcode(void);
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
extern bool initrd_gone;
#else #else
static inline int __init microcode_init(void) { return 0; }; static inline int __init microcode_init(void) { return 0; };
static inline void __init load_ucode_bsp(void) { } static inline void __init load_ucode_bsp(void) { }
......
...@@ -1373,20 +1373,15 @@ static unsigned long mce_adjust_timer_default(unsigned long interval) ...@@ -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 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 when = jiffies + interval;
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
if (timer_pending(t)) { if (!timer_pending(t) || time_before(when, t->expires))
if (time_before(when, t->expires)) mod_timer(t, round_jiffies(when));
mod_timer(t, when);
} else {
t->expires = round_jiffies(when);
add_timer_on(t, smp_processor_id());
}
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -1421,7 +1416,7 @@ static void mce_timer_fn(unsigned long data) ...@@ -1421,7 +1416,7 @@ static void mce_timer_fn(unsigned long data)
done: done:
__this_cpu_write(mce_next_interval, iv); __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) ...@@ -1432,7 +1427,7 @@ void mce_timer_kick(unsigned long interval)
struct timer_list *t = this_cpu_ptr(&mce_timer); struct timer_list *t = this_cpu_ptr(&mce_timer);
unsigned long iv = __this_cpu_read(mce_next_interval); unsigned long iv = __this_cpu_read(mce_next_interval);
__restart_timer(t, interval); __start_timer(t, interval);
if (interval < iv) if (interval < iv)
__this_cpu_write(mce_next_interval, interval); __this_cpu_write(mce_next_interval, interval);
...@@ -1779,17 +1774,15 @@ static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c) ...@@ -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; unsigned long iv = check_interval * HZ;
if (mca_cfg.ignore_ce || !iv) if (mca_cfg.ignore_ce || !iv)
return; return;
per_cpu(mce_next_interval, cpu) = iv; this_cpu_write(mce_next_interval, iv);
__start_timer(t, iv);
t->expires = round_jiffies(jiffies + iv);
add_timer_on(t, cpu);
} }
static void __mcheck_cpu_setup_timer(void) static void __mcheck_cpu_setup_timer(void)
...@@ -1806,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void) ...@@ -1806,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void)
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
setup_pinned_timer(t, mce_timer_fn, cpu); setup_pinned_timer(t, mce_timer_fn, cpu);
mce_start_timer(cpu, t); mce_start_timer(t);
} }
/* Handle unconfigured int18 (should never happen) */ /* Handle unconfigured int18 (should never happen) */
...@@ -2566,7 +2559,7 @@ static int mce_cpu_dead(unsigned int cpu) ...@@ -2566,7 +2559,7 @@ static int mce_cpu_dead(unsigned int cpu)
static int mce_cpu_online(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; int ret;
mce_device_create(cpu); mce_device_create(cpu);
...@@ -2577,13 +2570,13 @@ static int mce_cpu_online(unsigned int cpu) ...@@ -2577,13 +2570,13 @@ static int mce_cpu_online(unsigned int cpu)
return ret; return ret;
} }
mce_reenable_cpu(); mce_reenable_cpu();
mce_start_timer(cpu, t); mce_start_timer(t);
return 0; return 0;
} }
static int mce_cpu_pre_down(unsigned int cpu) 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(); mce_disable_cpu();
del_timer_sync(t); del_timer_sync(t);
......
...@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family) ...@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family)
reget: reget:
if (!get_builtin_microcode(&cp, family)) { if (!get_builtin_microcode(&cp, family)) {
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
cp = find_cpio_data(ucode_path, (void *)initrd_start, if (!initrd_gone)
initrd_end - initrd_start, NULL); cp = find_cpio_data(ucode_path, (void *)initrd_start,
initrd_end - initrd_start, NULL);
#endif #endif
if (!(cp.data && cp.size)) { if (!(cp.data && cp.size)) {
/* /*
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
static struct microcode_ops *microcode_ops; static struct microcode_ops *microcode_ops;
static bool dis_ucode_ldr = true; static bool dis_ucode_ldr = true;
bool initrd_gone;
LIST_HEAD(microcode_cache); LIST_HEAD(microcode_cache);
/* /*
...@@ -190,21 +192,24 @@ void load_ucode_ap(void) ...@@ -190,21 +192,24 @@ void load_ucode_ap(void)
static int __init save_microcode_in_initrd(void) static int __init save_microcode_in_initrd(void)
{ {
struct cpuinfo_x86 *c = &boot_cpu_data; struct cpuinfo_x86 *c = &boot_cpu_data;
int ret = -EINVAL;
switch (c->x86_vendor) { switch (c->x86_vendor) {
case X86_VENDOR_INTEL: case X86_VENDOR_INTEL:
if (c->x86 >= 6) if (c->x86 >= 6)
return save_microcode_in_initrd_intel(); ret = save_microcode_in_initrd_intel();
break; break;
case X86_VENDOR_AMD: case X86_VENDOR_AMD:
if (c->x86 >= 0x10) if (c->x86 >= 0x10)
return save_microcode_in_initrd_amd(c->x86); ret = save_microcode_in_initrd_amd(c->x86);
break; break;
default: default:
break; break;
} }
return -EINVAL; initrd_gone = true;
return ret;
} }
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa) 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) ...@@ -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 * has the virtual address of the beginning of the initrd. It also
* possibly relocates the ramdisk. In either case, initrd_start contains * possibly relocates the ramdisk. In either case, initrd_start contains
* the updated address so use that instead. * 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) if (!use_pa) {
start = initrd_start; if (initrd_gone)
return (struct cpio_data){ NULL, 0, "" };
if (initrd_start)
start = initrd_start;
}
return find_cpio_data(path, (void *)start, size, NULL); return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */ #else /* !CONFIG_BLK_DEV_INITRD */
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin"; 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; struct microcode_intel *intel_ucode_patch;
static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1, static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
...@@ -607,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void) ...@@ -607,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void)
struct ucode_cpu_info uci; struct ucode_cpu_info uci;
struct cpio_data cp; 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)) if (!load_builtin_intel_microcode(&cp))
cp = find_microcode_in_initrd(ucode_path, false); cp = find_microcode_in_initrd(ucode_path, false);
...@@ -628,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void) ...@@ -628,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void)
return 0; return 0;
} }
/* /*
* @res_patch, output: a pointer to the patch we found. * @res_patch, output: a pointer to the patch we found.
*/ */
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <asm/fpu/regset.h> #include <asm/fpu/regset.h>
#include <asm/fpu/signal.h> #include <asm/fpu/signal.h>
#include <asm/fpu/types.h> #include <asm/fpu/types.h>
#include <asm/fpu/xstate.h>
#include <asm/traps.h> #include <asm/traps.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
...@@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state) ...@@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state)
* it will #GP. Make sure it is replaced after the memset(). * it will #GP. Make sure it is replaced after the memset().
*/ */
if (static_cpu_has(X86_FEATURE_XSAVES)) 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)) if (static_cpu_has(X86_FEATURE_FXSR))
fpstate_init_fxstate(&state->fxsave); fpstate_init_fxstate(&state->fxsave);
......
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