-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
x86: Hypervisor detection and get tsc_freq from hypervisor
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 <akataria@vmware.com> Signed-off-by: Dan Hecht <dhecht@vmware.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
- Loading branch information
Alok Kataria
authored and
H. Peter Anvin
committed
Nov 2, 2008
1 parent
49ab56a
commit 88b094f
Showing
9 changed files
with
210 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright (C) 2008, VMware, Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
* NON INFRINGEMENT. See the GNU General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
#ifndef ASM_X86__HYPERVISOR_H | ||
#define ASM_X86__HYPERVISOR_H | ||
|
||
extern unsigned long get_hypervisor_tsc_freq(void); | ||
extern void init_hypervisor(struct cpuinfo_x86 *c); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright (C) 2008, VMware, Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
* NON INFRINGEMENT. See the GNU General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
#ifndef ASM_X86__VMWARE_H | ||
#define ASM_X86__VMWARE_H | ||
|
||
extern unsigned long vmware_get_tsc_khz(void); | ||
extern int vmware_platform(void); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Common hypervisor code | ||
* | ||
* Copyright (C) 2008, VMware, Inc. | ||
* Author : Alok N Kataria <akataria@vmware.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
* NON INFRINGEMENT. See the GNU General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
|
||
#include <asm/processor.h> | ||
#include <asm/vmware.h> | ||
|
||
static inline void __cpuinit | ||
detect_hypervisor_vendor(struct cpuinfo_x86 *c) | ||
{ | ||
if (vmware_platform()) { | ||
c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE; | ||
} else { | ||
c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE; | ||
} | ||
} | ||
|
||
unsigned long get_hypervisor_tsc_freq(void) | ||
{ | ||
if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) | ||
return vmware_get_tsc_khz(); | ||
return 0; | ||
} | ||
|
||
void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) | ||
{ | ||
detect_hypervisor_vendor(c); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* VMware Detection code. | ||
* | ||
* Copyright (C) 2008, VMware, Inc. | ||
* Author : Alok N Kataria <akataria@vmware.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
* NON INFRINGEMENT. See the GNU General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
|
||
#include <linux/dmi.h> | ||
#include <asm/div64.h> | ||
|
||
#define CPUID_VMWARE_INFO_LEAF 0x40000000 | ||
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868 | ||
#define VMWARE_HYPERVISOR_PORT 0x5658 | ||
|
||
#define VMWARE_PORT_CMD_GETVERSION 10 | ||
#define VMWARE_PORT_CMD_GETHZ 45 | ||
|
||
#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ | ||
__asm__("inl (%%dx)" : \ | ||
"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \ | ||
"0"(VMWARE_HYPERVISOR_MAGIC), \ | ||
"1"(VMWARE_PORT_CMD_##cmd), \ | ||
"2"(VMWARE_HYPERVISOR_PORT), "3"(0) : \ | ||
"memory"); | ||
|
||
static inline int __vmware_platform(void) | ||
{ | ||
uint32_t eax, ebx, ecx, edx; | ||
VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx); | ||
return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC; | ||
} | ||
|
||
static unsigned long __vmware_get_tsc_khz(void) | ||
{ | ||
uint64_t tsc_hz; | ||
uint32_t eax, ebx, ecx, edx; | ||
|
||
VMWARE_PORT(GETHZ, eax, ebx, ecx, edx); | ||
|
||
if (eax == (uint32_t)-1) | ||
return 0; | ||
tsc_hz = eax | (((uint64_t)ebx) << 32); | ||
do_div(tsc_hz, 1000); | ||
BUG_ON(tsc_hz >> 32); | ||
return tsc_hz; | ||
} | ||
|
||
int vmware_platform(void) | ||
{ | ||
if (cpu_has_hypervisor) { | ||
unsigned int eax, ebx, ecx, edx; | ||
char hyper_vendor_id[13]; | ||
|
||
cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &ebx, &ecx, &edx); | ||
memcpy(hyper_vendor_id + 0, &ebx, 4); | ||
memcpy(hyper_vendor_id + 4, &ecx, 4); | ||
memcpy(hyper_vendor_id + 8, &edx, 4); | ||
hyper_vendor_id[12] = '\0'; | ||
if (!strcmp(hyper_vendor_id, "VMwareVMware")) | ||
return 1; | ||
} else if (dmi_available && dmi_name_in_vendors("VMware") && | ||
__vmware_platform()) | ||
return 1; | ||
|
||
return 0; | ||
} | ||
|
||
unsigned long vmware_get_tsc_khz(void) | ||
{ | ||
BUG_ON(!vmware_platform()); | ||
return __vmware_get_tsc_khz(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters