Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34e00acc authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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)			{ }
+12 −19
Original line number Diff line number Diff line
@@ -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);
+3 −2
Original line number Diff line number Diff line
@@ -384,6 +384,7 @@ void load_ucode_amd_ap(unsigned int family)
reget:
		if (!get_builtin_microcode(&cp, family)) {
#ifdef CONFIG_BLK_DEV_INITRD
			if (!initrd_gone)
				cp = find_cpio_data(ucode_path, (void *)initrd_start,
						    initrd_end - initrd_start, NULL);
#endif
+17 −5
Original line number Diff line number Diff line
@@ -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)
	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 */
+1 −8
Original line number Diff line number Diff line
@@ -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.
 */
Loading