From: Alok Kataria Subject: x86: Hypervisor detection and get tsc_freq from hypervisor Patch-mainline: References: bnc#441338 Impact: Changes timebase calibration on Vmware. v3->v2 : Abstract the hypervisor detection and feature (tsc_freq) request behind a hypervisor.c file v2->v1 : Add a x86_hyper_vendor field to the cpuinfo_x86 structure. This avoids multiple calls to the hypervisor detection function. This patch adds function to detect if we are running under VMware. The current way to check if we are on VMware is following, # check if "hypervisor present bit" is set, if so read the 0x40000000 cpuid leaf and check for "VMwareVMware" signature. # if the above fails, check the DMI vendors name for "VMware" string if we find one we query the VMware hypervisor port to check if we are under VMware. The DMI + "VMware hypervisor port check" is needed for older VMware products, which don't implement the hypervisor signature cpuid leaf. Also note that since we are checking for the DMI signature the hypervisor port should never be accessed on native hardware. This patch also adds a hypervisor_get_tsc_freq function, instead of calibrating the frequency which can be error prone in virtualized environment, we ask the hypervisor for it. We get the frequency from the hypervisor by accessing the hypervisor port if we are running on VMware. Other hypervisors too can add code to the generic routine to get frequency on their platform. Signed-off-by: Alok N Kataria Signed-off-by: Dan Hecht Signed-off-by: H. Peter Anvin Signed-off-by: Takashi Iwai Automatically created from "patches.arch/x86-vmware-tsc-03-detect-from-hypervisor" by xen-port-patches.py --- sle11-2009-03-04.orig/arch/x86/kernel/cpu/Makefile 2009-03-12 16:02:36.000000000 +0100 +++ sle11-2009-03-04/arch/x86/kernel/cpu/Makefile 2009-02-16 17:03:24.000000000 +0100 @@ -23,3 +23,5 @@ obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o + +disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o --- sle11-2009-03-04.orig/arch/x86/kernel/cpu/common-xen.c 2009-03-04 11:29:03.000000000 +0100 +++ sle11-2009-03-04/arch/x86/kernel/cpu/common-xen.c 2009-02-16 17:03:24.000000000 +0100 @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include @@ -514,6 +515,7 @@ static void __cpuinit identify_cpu(struc c->x86, c->x86_model); } + init_hypervisor(c); /* * On SMP, boot_cpu_data holds the common feature set between * all CPUs; so make sure that we indicate which features are --- sle11-2009-03-04.orig/arch/x86/kernel/cpu/common_64-xen.c 2009-03-04 11:29:03.000000000 +0100 +++ sle11-2009-03-04/arch/x86/kernel/cpu/common_64-xen.c 2009-02-16 17:03:24.000000000 +0100 @@ -36,6 +36,7 @@ #include #include #include +#include #include "cpu.h" @@ -399,6 +400,7 @@ static void __cpuinit identify_cpu(struc detect_ht(c); + init_hypervisor(c); /* * On SMP, boot_cpu_data holds the common feature set between * all CPUs; so make sure that we indicate which features are --- sle11-2009-03-04.orig/arch/x86/kernel/setup-xen.c 2008-12-23 09:40:12.000000000 +0100 +++ sle11-2009-03-04/arch/x86/kernel/setup-xen.c 2009-02-16 17:03:24.000000000 +0100 @@ -98,6 +98,7 @@ #include #include +#include #include #include @@ -1120,6 +1121,12 @@ void __init setup_arch(char **cmdline_p) e820_reserve_resources(); #endif + /* + * VMware detection requires dmi to be available, so this + * needs to be done after dmi_scan_machine, for the BP. + */ + init_hypervisor(&boot_cpu_data); + #ifdef CONFIG_X86_32 request_resource(&iomem_resource, &video_ram_resource); #endif --- sle11-2009-03-04.orig/include/asm-x86/hypervisor.h 2009-03-12 16:02:36.000000000 +0100 +++ sle11-2009-03-04/include/asm-x86/hypervisor.h 2009-02-16 17:03:24.000000000 +0100 @@ -24,3 +24,7 @@ extern unsigned long get_hypervisor_tsc_ extern void init_hypervisor(struct cpuinfo_x86 *c); #endif + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include_next +#endif --- sle11-2009-03-04.orig/include/asm-x86/mach-xen/asm/hypervisor.h 2009-03-12 16:27:52.000000000 +0100 +++ sle11-2009-03-04/include/asm-x86/mach-xen/asm/hypervisor.h 2009-03-12 16:42:09.000000000 +0100 @@ -67,6 +67,8 @@ extern start_info_t *xen_start_info; #define is_initial_xendomain() 0 #endif +#define init_hypervisor(c) ((void)((c)->x86_hyper_vendor = X86_HYPER_VENDOR_XEN)) + /* arch/xen/kernel/evtchn.c */ /* Force a proper event-channel callback from Xen. */ void force_evtchn_callback(void); --- sle11-2009-03-04.orig/include/asm-x86/mach-xen/asm/processor.h 2009-03-12 00:00:00.000000000 +0100 +++ sle11-2009-03-04/include/asm-x86/mach-xen/asm/processor.h 2009-02-16 17:03:24.000000000 +0100 @@ -110,6 +110,7 @@ struct cpuinfo_x86 { /* Index into per_cpu list: */ u16 cpu_index; #endif + unsigned int x86_hyper_vendor; } __attribute__((__aligned__(SMP_CACHE_BYTES))); #define X86_VENDOR_INTEL 0 @@ -123,6 +124,10 @@ struct cpuinfo_x86 { #define X86_VENDOR_UNKNOWN 0xff +#define X86_HYPER_VENDOR_NONE 0 +#define X86_HYPER_VENDOR_VMWARE 1 +#define X86_HYPER_VENDOR_XEN 'X' + /* * capabilities of CPUs */