summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorFrank Van Der Linden <Frank.Vanderlinden@Sun.COM>2010-04-07 19:19:36 -0700
committerFrank Van Der Linden <Frank.Vanderlinden@Sun.COM>2010-04-07 19:19:36 -0700
commit6e5580c92a7a7c64dd50b768bda246808fb1ee17 (patch)
treebc2653c1ba4d3b21e973348d14796e6370aaa9ac /usr/src
parent00d1d19828f3122eb24ae7a68175ba64744f8366 (diff)
downloadillumos-gate-6e5580c92a7a7c64dd50b768bda246808fb1ee17.tar.gz
6941777 determine_platform needs to do a better job inside a Xen HVM guest
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c41
-rw-r--r--usr/src/uts/i86pc/os/xpv_platform.c42
2 files changed, 48 insertions, 35 deletions
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index d47d680939..447ad1c5f1 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright (c) 2009, Intel Corporation.
@@ -476,7 +475,7 @@ determine_platform()
{
struct cpuid_regs cp;
char *xen_str;
- uint32_t xen_signature[4];
+ uint32_t xen_signature[4], base;
platform_type = HW_NATIVE;
@@ -485,22 +484,30 @@ determine_platform()
/*
* In a fully virtualized domain, Xen's pseudo-cpuid function
- * 0x40000000 returns a string representing the Xen signature in
- * %ebx, %ecx, and %edx. %eax contains the maximum supported cpuid
- * function.
+ * returns a string representing the Xen signature in %ebx, %ecx,
+ * and %edx. %eax contains the maximum supported cpuid function.
+ * We need at least a (base + 2) leaf value to do what we want
+ * to do. Try different base values, since the hypervisor might
+ * use a different one depending on whether hyper-v emulation
+ * is switched on by default or not.
*/
- cp.cp_eax = 0x40000000;
- (void) __cpuid_insn(&cp);
- xen_signature[0] = cp.cp_ebx;
- xen_signature[1] = cp.cp_ecx;
- xen_signature[2] = cp.cp_edx;
- xen_signature[3] = 0;
- xen_str = (char *)xen_signature;
- if (strcmp("XenVMMXenVMM", xen_str) == 0 && cp.cp_eax <= 0x40000002) {
- platform_type = HW_XEN_HVM;
- } else if (vmware_platform()) { /* running under vmware hypervisor? */
- platform_type = HW_VMWARE;
+ for (base = 0x40000000; base < 0x40010000; base += 0x100) {
+ cp.cp_eax = base;
+ (void) __cpuid_insn(&cp);
+ xen_signature[0] = cp.cp_ebx;
+ xen_signature[1] = cp.cp_ecx;
+ xen_signature[2] = cp.cp_edx;
+ xen_signature[3] = 0;
+ xen_str = (char *)xen_signature;
+ if (strcmp("XenVMMXenVMM", xen_str) == 0 &&
+ cp.cp_eax >= (base + 2)) {
+ platform_type = HW_XEN_HVM;
+ return;
+ }
}
+
+ if (vmware_platform()) /* running under vmware hypervisor? */
+ platform_type = HW_VMWARE;
}
int
diff --git a/usr/src/uts/i86pc/os/xpv_platform.c b/usr/src/uts/i86pc/os/xpv_platform.c
index 351672141a..14bdb1ab44 100644
--- a/usr/src/uts/i86pc/os/xpv_platform.c
+++ b/usr/src/uts/i86pc/os/xpv_platform.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -94,7 +93,7 @@ void
xen_hvm_init(void)
{
struct cpuid_regs cp;
- uint32_t xen_signature[4];
+ uint32_t xen_signature[4], base;
char *xen_str;
struct xen_add_to_physmap xatp;
xen_capabilities_info_t caps;
@@ -107,27 +106,34 @@ xen_hvm_init(void)
xen_hvm_inited = 1;
/*
- * Xen's pseudo-cpuid function 0x40000000 returns a string
- * representing the Xen signature in %ebx, %ecx, and %edx.
+ * Xen's pseudo-cpuid function returns a string representing
+ * the Xen signature in %ebx, %ecx, and %edx.
+ * Loop over the base values, since it may be different if
+ * the hypervisor has hyper-v emulation switched on.
+ *
* %eax contains the maximum supported cpuid function.
*/
- cp.cp_eax = 0x40000000;
- (void) __cpuid_insn(&cp);
- xen_signature[0] = cp.cp_ebx;
- xen_signature[1] = cp.cp_ecx;
- xen_signature[2] = cp.cp_edx;
- xen_signature[3] = 0;
- xen_str = (char *)xen_signature;
- if (strcmp("XenVMMXenVMM", xen_str) != 0 ||
- cp.cp_eax < 0x40000002)
+ for (base = 0x40000000; base < 0x40010000; base += 0x100) {
+ cp.cp_eax = base;
+ (void) __cpuid_insn(&cp);
+ xen_signature[0] = cp.cp_ebx;
+ xen_signature[1] = cp.cp_ecx;
+ xen_signature[2] = cp.cp_edx;
+ xen_signature[3] = 0;
+ xen_str = (char *)xen_signature;
+ if (strcmp("XenVMMXenVMM", xen_str) == 0 &&
+ cp.cp_eax >= (base + 2))
+ break;
+ }
+ if (base >= 0x40010000)
return;
/*
- * cpuid function 0x40000001 returns the Xen version in %eax. The
+ * cpuid function at base + 1 returns the Xen version in %eax. The
* top 16 bits are the major version, the bottom 16 are the minor
* version.
*/
- cp.cp_eax = 0x40000001;
+ cp.cp_eax = base + 1;
(void) __cpuid_insn(&cp);
xen_major = cp.cp_eax >> 16;
xen_minor = cp.cp_eax & 0xffff;
@@ -141,7 +147,7 @@ xen_hvm_init(void)
return;
/*
- * cpuid function 0x40000002 returns information about the
+ * cpuid function at base + 2 returns information about the
* hypercall page. %eax nominally contains the number of pages
* with hypercall code, but according to the Xen guys, "I'll
* guarantee that remains one forever more, so you can just
@@ -149,7 +155,7 @@ xen_hvm_init(void)
* return more than one page." %ebx contains an MSR we use to ask
* Xen to remap each page at a specific pfn.
*/
- cp.cp_eax = 0x40000002;
+ cp.cp_eax = base + 2;
(void) __cpuid_insn(&cp);
/*