Skip to content

Commit 34e00ac

Browse files
committed
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
2 parents 891aa1e + 0becc0a commit 34e00ac

File tree

6 files changed

+37
-35
lines changed

6 files changed

+37
-35
lines changed

arch/x86/include/asm/microcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);
140140
extern void load_ucode_ap(void);
141141
void reload_early_microcode(void);
142142
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
143+
extern bool initrd_gone;
143144
#else
144145
static inline int __init microcode_init(void) { return 0; };
145146
static inline void __init load_ucode_bsp(void) { }

arch/x86/kernel/cpu/mcheck/mce.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,20 +1373,15 @@ static unsigned long mce_adjust_timer_default(unsigned long interval)
13731373

13741374
static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default;
13751375

1376-
static void __restart_timer(struct timer_list *t, unsigned long interval)
1376+
static void __start_timer(struct timer_list *t, unsigned long interval)
13771377
{
13781378
unsigned long when = jiffies + interval;
13791379
unsigned long flags;
13801380

13811381
local_irq_save(flags);
13821382

1383-
if (timer_pending(t)) {
1384-
if (time_before(when, t->expires))
1385-
mod_timer(t, when);
1386-
} else {
1387-
t->expires = round_jiffies(when);
1388-
add_timer_on(t, smp_processor_id());
1389-
}
1383+
if (!timer_pending(t) || time_before(when, t->expires))
1384+
mod_timer(t, round_jiffies(when));
13901385

13911386
local_irq_restore(flags);
13921387
}
@@ -1421,7 +1416,7 @@ static void mce_timer_fn(unsigned long data)
14211416

14221417
done:
14231418
__this_cpu_write(mce_next_interval, iv);
1424-
__restart_timer(t, iv);
1419+
__start_timer(t, iv);
14251420
}
14261421

14271422
/*
@@ -1432,7 +1427,7 @@ void mce_timer_kick(unsigned long interval)
14321427
struct timer_list *t = this_cpu_ptr(&mce_timer);
14331428
unsigned long iv = __this_cpu_read(mce_next_interval);
14341429

1435-
__restart_timer(t, interval);
1430+
__start_timer(t, interval);
14361431

14371432
if (interval < iv)
14381433
__this_cpu_write(mce_next_interval, interval);
@@ -1779,17 +1774,15 @@ static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c)
17791774
}
17801775
}
17811776

1782-
static void mce_start_timer(unsigned int cpu, struct timer_list *t)
1777+
static void mce_start_timer(struct timer_list *t)
17831778
{
17841779
unsigned long iv = check_interval * HZ;
17851780

17861781
if (mca_cfg.ignore_ce || !iv)
17871782
return;
17881783

1789-
per_cpu(mce_next_interval, cpu) = iv;
1790-
1791-
t->expires = round_jiffies(jiffies + iv);
1792-
add_timer_on(t, cpu);
1784+
this_cpu_write(mce_next_interval, iv);
1785+
__start_timer(t, iv);
17931786
}
17941787

17951788
static void __mcheck_cpu_setup_timer(void)
@@ -1806,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void)
18061799
unsigned int cpu = smp_processor_id();
18071800

18081801
setup_pinned_timer(t, mce_timer_fn, cpu);
1809-
mce_start_timer(cpu, t);
1802+
mce_start_timer(t);
18101803
}
18111804

18121805
/* Handle unconfigured int18 (should never happen) */
@@ -2566,7 +2559,7 @@ static int mce_cpu_dead(unsigned int cpu)
25662559

25672560
static int mce_cpu_online(unsigned int cpu)
25682561
{
2569-
struct timer_list *t = &per_cpu(mce_timer, cpu);
2562+
struct timer_list *t = this_cpu_ptr(&mce_timer);
25702563
int ret;
25712564

25722565
mce_device_create(cpu);
@@ -2577,13 +2570,13 @@ static int mce_cpu_online(unsigned int cpu)
25772570
return ret;
25782571
}
25792572
mce_reenable_cpu();
2580-
mce_start_timer(cpu, t);
2573+
mce_start_timer(t);
25812574
return 0;
25822575
}
25832576

25842577
static int mce_cpu_pre_down(unsigned int cpu)
25852578
{
2586-
struct timer_list *t = &per_cpu(mce_timer, cpu);
2579+
struct timer_list *t = this_cpu_ptr(&mce_timer);
25872580

25882581
mce_disable_cpu();
25892582
del_timer_sync(t);

arch/x86/kernel/cpu/microcode/amd.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family)
384384
reget:
385385
if (!get_builtin_microcode(&cp, family)) {
386386
#ifdef CONFIG_BLK_DEV_INITRD
387-
cp = find_cpio_data(ucode_path, (void *)initrd_start,
388-
initrd_end - initrd_start, NULL);
387+
if (!initrd_gone)
388+
cp = find_cpio_data(ucode_path, (void *)initrd_start,
389+
initrd_end - initrd_start, NULL);
389390
#endif
390391
if (!(cp.data && cp.size)) {
391392
/*

arch/x86/kernel/cpu/microcode/core.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
static struct microcode_ops *microcode_ops;
4747
static bool dis_ucode_ldr = true;
4848

49+
bool initrd_gone;
50+
4951
LIST_HEAD(microcode_cache);
5052

5153
/*
@@ -190,21 +192,24 @@ void load_ucode_ap(void)
190192
static int __init save_microcode_in_initrd(void)
191193
{
192194
struct cpuinfo_x86 *c = &boot_cpu_data;
195+
int ret = -EINVAL;
193196

194197
switch (c->x86_vendor) {
195198
case X86_VENDOR_INTEL:
196199
if (c->x86 >= 6)
197-
return save_microcode_in_initrd_intel();
200+
ret = save_microcode_in_initrd_intel();
198201
break;
199202
case X86_VENDOR_AMD:
200203
if (c->x86 >= 0x10)
201-
return save_microcode_in_initrd_amd(c->x86);
204+
ret = save_microcode_in_initrd_amd(c->x86);
202205
break;
203206
default:
204207
break;
205208
}
206209

207-
return -EINVAL;
210+
initrd_gone = true;
211+
212+
return ret;
208213
}
209214

210215
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)
247252
* has the virtual address of the beginning of the initrd. It also
248253
* possibly relocates the ramdisk. In either case, initrd_start contains
249254
* the updated address so use that instead.
255+
*
256+
* initrd_gone is for the hotplug case where we've thrown out initrd
257+
* already.
250258
*/
251-
if (!use_pa && initrd_start)
252-
start = initrd_start;
259+
if (!use_pa) {
260+
if (initrd_gone)
261+
return (struct cpio_data){ NULL, 0, "" };
262+
if (initrd_start)
263+
start = initrd_start;
264+
}
253265

254266
return find_cpio_data(path, (void *)start, size, NULL);
255267
#else /* !CONFIG_BLK_DEV_INITRD */

arch/x86/kernel/cpu/microcode/intel.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
4343

44-
/* Current microcode patch used in early patching */
44+
/* Current microcode patch used in early patching on the APs. */
4545
struct microcode_intel *intel_ucode_patch;
4646

4747
static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
@@ -607,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void)
607607
struct ucode_cpu_info uci;
608608
struct cpio_data cp;
609609

610-
/*
611-
* AP loading didn't find any microcode patch, no need to save anything.
612-
*/
613-
if (!intel_ucode_patch || IS_ERR(intel_ucode_patch))
614-
return 0;
615-
616610
if (!load_builtin_intel_microcode(&cp))
617611
cp = find_microcode_in_initrd(ucode_path, false);
618612

@@ -628,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void)
628622
return 0;
629623
}
630624

631-
632625
/*
633626
* @res_patch, output: a pointer to the patch we found.
634627
*/

arch/x86/kernel/fpu/core.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <asm/fpu/regset.h>
1010
#include <asm/fpu/signal.h>
1111
#include <asm/fpu/types.h>
12+
#include <asm/fpu/xstate.h>
1213
#include <asm/traps.h>
1314

1415
#include <linux/hardirq.h>
@@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state)
183184
* it will #GP. Make sure it is replaced after the memset().
184185
*/
185186
if (static_cpu_has(X86_FEATURE_XSAVES))
186-
state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT;
187+
state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
188+
xfeatures_mask;
187189

188190
if (static_cpu_has(X86_FEATURE_FXSR))
189191
fpstate_init_fxstate(&state->fxsave);

0 commit comments

Comments
 (0)