Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * VMware Detection code.
  3 *
  4 * Copyright (C) 2008, VMware, Inc.
  5 * Author : Alok N Kataria <akataria@vmware.com>
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License as published by
  9 * the Free Software Foundation; either version 2 of the License, or
 10 * (at your option) any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful, but
 13 * WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 15 * NON INFRINGEMENT.  See the GNU General Public License for more
 16 * details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 21 *
 22 */
 23
 24#include <linux/dmi.h>
 25#include <linux/module.h>
 26#include <asm/div64.h>
 27#include <asm/x86_init.h>
 28#include <asm/hypervisor.h>
 29
 30#define CPUID_VMWARE_INFO_LEAF	0x40000000
 31#define VMWARE_HYPERVISOR_MAGIC	0x564D5868
 32#define VMWARE_HYPERVISOR_PORT	0x5658
 33
 34#define VMWARE_PORT_CMD_GETVERSION	10
 35#define VMWARE_PORT_CMD_GETHZ		45
 
 
 
 36
 37#define VMWARE_PORT(cmd, eax, ebx, ecx, edx)				\
 38	__asm__("inl (%%dx)" :						\
 39			"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :	\
 40			"0"(VMWARE_HYPERVISOR_MAGIC),			\
 41			"1"(VMWARE_PORT_CMD_##cmd),			\
 42			"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) :	\
 43			"memory");
 44
 45static inline int __vmware_platform(void)
 46{
 47	uint32_t eax, ebx, ecx, edx;
 48	VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx);
 49	return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC;
 50}
 51
 52static unsigned long vmware_get_tsc_khz(void)
 53{
 54	uint64_t tsc_hz, lpj;
 55	uint32_t eax, ebx, ecx, edx;
 56
 57	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
 58
 59	tsc_hz = eax | (((uint64_t)ebx) << 32);
 60	do_div(tsc_hz, 1000);
 61	BUG_ON(tsc_hz >> 32);
 62	printk(KERN_INFO "TSC freq read from hypervisor : %lu.%03lu MHz\n",
 63			 (unsigned long) tsc_hz / 1000,
 64			 (unsigned long) tsc_hz % 1000);
 65
 66	if (!preset_lpj) {
 67		lpj = ((u64)tsc_hz * 1000);
 68		do_div(lpj, HZ);
 69		preset_lpj = lpj;
 70	}
 71
 72	return tsc_hz;
 73}
 74
 75static void __init vmware_platform_setup(void)
 76{
 77	uint32_t eax, ebx, ecx, edx;
 78
 79	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
 80
 81	if (ebx != UINT_MAX)
 82		x86_platform.calibrate_tsc = vmware_get_tsc_khz;
 83	else
 84		printk(KERN_WARNING
 85		       "Failed to get TSC freq from the hypervisor\n");
 86}
 87
 88/*
 89 * While checking the dmi string information, just checking the product
 90 * serial key should be enough, as this will always have a VMware
 91 * specific string when running under VMware hypervisor.
 92 */
 93static bool __init vmware_platform(void)
 94{
 95	if (cpu_has_hypervisor) {
 96		unsigned int eax;
 97		unsigned int hyper_vendor_id[3];
 98
 99		cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0],
100		      &hyper_vendor_id[1], &hyper_vendor_id[2]);
101		if (!memcmp(hyper_vendor_id, "VMwareVMware", 12))
102			return true;
103	} else if (dmi_available && dmi_name_in_serial("VMware") &&
104		   __vmware_platform())
105		return true;
106
107	return false;
108}
109
110/*
111 * VMware hypervisor takes care of exporting a reliable TSC to the guest.
112 * Still, due to timing difference when running on virtual cpus, the TSC can
113 * be marked as unstable in some cases. For example, the TSC sync check at
114 * bootup can fail due to a marginal offset between vcpus' TSCs (though the
115 * TSCs do not drift from each other).  Also, the ACPI PM timer clocksource
116 * is not suitable as a watchdog when running on a hypervisor because the
117 * kernel may miss a wrap of the counter if the vcpu is descheduled for a
118 * long time. To skip these checks at runtime we set these capability bits,
119 * so that the kernel could just trust the hypervisor with providing a
120 * reliable virtual TSC that is suitable for timekeeping.
121 */
122static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c)
123{
124	set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
125	set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
126}
127
 
 
 
 
 
 
 
 
 
128const __refconst struct hypervisor_x86 x86_hyper_vmware = {
129	.name			= "VMware",
130	.detect			= vmware_platform,
131	.set_cpu_features	= vmware_set_cpu_features,
132	.init_platform		= vmware_platform_setup,
 
133};
134EXPORT_SYMBOL(x86_hyper_vmware);
v4.6
  1/*
  2 * VMware Detection code.
  3 *
  4 * Copyright (C) 2008, VMware, Inc.
  5 * Author : Alok N Kataria <akataria@vmware.com>
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License as published by
  9 * the Free Software Foundation; either version 2 of the License, or
 10 * (at your option) any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful, but
 13 * WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 15 * NON INFRINGEMENT.  See the GNU General Public License for more
 16 * details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 21 *
 22 */
 23
 24#include <linux/dmi.h>
 25#include <linux/module.h>
 26#include <asm/div64.h>
 27#include <asm/x86_init.h>
 28#include <asm/hypervisor.h>
 29
 30#define CPUID_VMWARE_INFO_LEAF	0x40000000
 31#define VMWARE_HYPERVISOR_MAGIC	0x564D5868
 32#define VMWARE_HYPERVISOR_PORT	0x5658
 33
 34#define VMWARE_PORT_CMD_GETVERSION	10
 35#define VMWARE_PORT_CMD_GETHZ		45
 36#define VMWARE_PORT_CMD_GETVCPU_INFO	68
 37#define VMWARE_PORT_CMD_LEGACY_X2APIC	3
 38#define VMWARE_PORT_CMD_VCPU_RESERVED	31
 39
 40#define VMWARE_PORT(cmd, eax, ebx, ecx, edx)				\
 41	__asm__("inl (%%dx)" :						\
 42			"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) :	\
 43			"0"(VMWARE_HYPERVISOR_MAGIC),			\
 44			"1"(VMWARE_PORT_CMD_##cmd),			\
 45			"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) :	\
 46			"memory");
 47
 48static inline int __vmware_platform(void)
 49{
 50	uint32_t eax, ebx, ecx, edx;
 51	VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx);
 52	return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC;
 53}
 54
 55static unsigned long vmware_get_tsc_khz(void)
 56{
 57	uint64_t tsc_hz, lpj;
 58	uint32_t eax, ebx, ecx, edx;
 59
 60	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
 61
 62	tsc_hz = eax | (((uint64_t)ebx) << 32);
 63	do_div(tsc_hz, 1000);
 64	BUG_ON(tsc_hz >> 32);
 65	pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
 66			 (unsigned long) tsc_hz / 1000,
 67			 (unsigned long) tsc_hz % 1000);
 68
 69	if (!preset_lpj) {
 70		lpj = ((u64)tsc_hz * 1000);
 71		do_div(lpj, HZ);
 72		preset_lpj = lpj;
 73	}
 74
 75	return tsc_hz;
 76}
 77
 78static void __init vmware_platform_setup(void)
 79{
 80	uint32_t eax, ebx, ecx, edx;
 81
 82	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
 83
 84	if (ebx != UINT_MAX)
 85		x86_platform.calibrate_tsc = vmware_get_tsc_khz;
 86	else
 87		pr_warn("Failed to get TSC freq from the hypervisor\n");
 
 88}
 89
 90/*
 91 * While checking the dmi string information, just checking the product
 92 * serial key should be enough, as this will always have a VMware
 93 * specific string when running under VMware hypervisor.
 94 */
 95static uint32_t __init vmware_platform(void)
 96{
 97	if (cpu_has_hypervisor) {
 98		unsigned int eax;
 99		unsigned int hyper_vendor_id[3];
100
101		cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0],
102		      &hyper_vendor_id[1], &hyper_vendor_id[2]);
103		if (!memcmp(hyper_vendor_id, "VMwareVMware", 12))
104			return CPUID_VMWARE_INFO_LEAF;
105	} else if (dmi_available && dmi_name_in_serial("VMware") &&
106		   __vmware_platform())
107		return 1;
108
109	return 0;
110}
111
112/*
113 * VMware hypervisor takes care of exporting a reliable TSC to the guest.
114 * Still, due to timing difference when running on virtual cpus, the TSC can
115 * be marked as unstable in some cases. For example, the TSC sync check at
116 * bootup can fail due to a marginal offset between vcpus' TSCs (though the
117 * TSCs do not drift from each other).  Also, the ACPI PM timer clocksource
118 * is not suitable as a watchdog when running on a hypervisor because the
119 * kernel may miss a wrap of the counter if the vcpu is descheduled for a
120 * long time. To skip these checks at runtime we set these capability bits,
121 * so that the kernel could just trust the hypervisor with providing a
122 * reliable virtual TSC that is suitable for timekeeping.
123 */
124static void vmware_set_cpu_features(struct cpuinfo_x86 *c)
125{
126	set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
127	set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
128}
129
130/* Checks if hypervisor supports x2apic without VT-D interrupt remapping. */
131static bool __init vmware_legacy_x2apic_available(void)
132{
133	uint32_t eax, ebx, ecx, edx;
134	VMWARE_PORT(GETVCPU_INFO, eax, ebx, ecx, edx);
135	return (eax & (1 << VMWARE_PORT_CMD_VCPU_RESERVED)) == 0 &&
136	       (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
137}
138
139const __refconst struct hypervisor_x86 x86_hyper_vmware = {
140	.name			= "VMware",
141	.detect			= vmware_platform,
142	.set_cpu_features	= vmware_set_cpu_features,
143	.init_platform		= vmware_platform_setup,
144	.x2apic_available	= vmware_legacy_x2apic_available,
145};
146EXPORT_SYMBOL(x86_hyper_vmware);