Commit e1449007 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-hyperv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 hyperv updates from Ingo Molnar:
 "Avoid boot time TSC calibration on Hyper-V hosts, to improve
  calibration robustness. (Vitaly Kuznetsov)"

* 'x86-hyperv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/hyperv: Read TSC frequency from a synthetic MSR
  x86/hyperv: Check frequency MSRs presence according to the specification
parents e6529f6f 71c2a2d0
Loading
Loading
Loading
Loading
+6 −9
Original line number Original line Diff line number Diff line
@@ -34,16 +34,10 @@
#define HV_X64_MSR_REFERENCE_TSC		0x40000021
#define HV_X64_MSR_REFERENCE_TSC		0x40000021


/*
/*
 * There is a single feature flag that signifies the presence of the MSR
 * There is a single feature flag that signifies if the partition has access
 * that can be used to retrieve both the local APIC Timer frequency as
 * to MSRs with local APIC and TSC frequencies.
 * well as the TSC frequency.
 */
 */

#define HV_X64_ACCESS_FREQUENCY_MSRS		(1 << 11)
/* Local APIC timer frequency MSR (HV_X64_MSR_APIC_FREQUENCY) is available */
#define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11)

/* TSC frequency MSR (HV_X64_MSR_TSC_FREQUENCY) is available */
#define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11)


/*
/*
 * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
 * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
@@ -73,6 +67,9 @@
  */
  */
#define HV_X64_MSR_STAT_PAGES_AVAILABLE		(1 << 8)
#define HV_X64_MSR_STAT_PAGES_AVAILABLE		(1 << 8)


/* Frequency MSRs available */
#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE	(1 << 8)

/* Crash MSR available */
/* Crash MSR available */
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)


+17 −1
Original line number Original line Diff line number Diff line
@@ -161,6 +161,15 @@ static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
}
}
#endif
#endif


static unsigned long hv_get_tsc_khz(void)
{
	unsigned long freq;

	rdmsrl(HV_X64_MSR_TSC_FREQUENCY, freq);

	return freq / 1000;
}

static void __init ms_hyperv_init_platform(void)
static void __init ms_hyperv_init_platform(void)
{
{
	int hv_host_info_eax;
	int hv_host_info_eax;
@@ -193,8 +202,15 @@ static void __init ms_hyperv_init_platform(void)
			hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
			hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
	}
	}


	if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
	    ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
		x86_platform.calibrate_tsc = hv_get_tsc_khz;
		x86_platform.calibrate_cpu = hv_get_tsc_khz;
	}

#ifdef CONFIG_X86_LOCAL_APIC
#ifdef CONFIG_X86_LOCAL_APIC
	if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
	if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
	    ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
		/*
		/*
		 * Get the APIC frequency.
		 * Get the APIC frequency.
		 */
		 */