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: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: kevin.b.stanton@intel.com Link: http://lkml.kernel.org/r/20170531155306.050849877@infradead.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
		
							parent
							
								
									c6e9f42bbe
								
							
						
					
					
						commit
						bd9240a18e
					
				| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user