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

Commit bd9240a1 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Thomas Gleixner
Browse files

x86/apic: Add TSC_DEADLINE quirk due to errata



Due to errata it is possible for the TSC_DEADLINE timer to misbehave
after using TSC_ADJUST. A microcode update is available to fix this
situation.

Avoid using the TSC_DEADLINE timer if it is affected by this issue and
report the required microcode version.

[ tglx: Renamed function to apic_check_deadline_errata() ]

Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: kevin.b.stanton@intel.com
Link: http://lkml.kernel.org/r/20170531155306.050849877@infradead.org


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent c6e9f42b
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@
#include <asm/mce.h>
#include <asm/tsc.h>
#include <asm/hypervisor.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>

unsigned int num_processors;

@@ -545,6 +547,81 @@ static struct clock_event_device lapic_clockevent = {
};
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);

#define DEADLINE_MODEL_MATCH_FUNC(model, func)	\
	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&func }

#define DEADLINE_MODEL_MATCH_REV(model, rev)	\
	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)rev }

static u32 hsx_deadline_rev(void)
{
	switch (boot_cpu_data.x86_mask) {
	case 0x02: return 0x3a; /* EP */
	case 0x04: return 0x0f; /* EX */
	}

	return ~0U;
}

static u32 bdx_deadline_rev(void)
{
	switch (boot_cpu_data.x86_mask) {
	case 0x02: return 0x00000011;
	case 0x03: return 0x0700000e;
	case 0x04: return 0x0f00000c;
	case 0x05: return 0x0e000003;
	}

	return ~0U;
}

static const struct x86_cpu_id deadline_match[] = {
	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_HASWELL_X,	hsx_deadline_rev),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_X,	0x0b000020),
	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_BROADWELL_XEON_D,	bdx_deadline_rev),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_X,	0x02000014),

	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_CORE,	0x22),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_ULT,	0x20),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_GT3E,	0x17),

	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_CORE,	0x25),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_GT3E,	0x17),

	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_MOBILE,	0xb2),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_DESKTOP,	0xb2),

	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_MOBILE,	0x52),
	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_DESKTOP,	0x52),

	{},
};

static void apic_check_deadline_errata(void)
{
	const struct x86_cpu_id *m = x86_match_cpu(deadline_match);
	u32 rev;

	if (!m)
		return;

	/*
	 * Function pointers will have the MSB set due to address layout,
	 * immediate revisions will not.
	 */
	if ((long)m->driver_data < 0)
		rev = ((u32 (*)(void))(m->driver_data))();
	else
		rev = (u32)m->driver_data;

	if (boot_cpu_data.microcode >= rev)
		return;

	setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
	pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
	       "please update microcode to version: 0x%x (or later)\n", rev);
}

/*
 * Setup the local APIC timer for this CPU. Copy the initialized values
 * of the boot CPU and register the clock event in the framework.
@@ -1780,6 +1857,8 @@ void __init init_apic_mappings(void)
{
	unsigned int new_apicid;

	apic_check_deadline_errata();

	if (x2apic_mode) {
		boot_cpu_physical_apicid = read_apic_id();
		return;