diff options
author | Frank Van Der Linden <Frank.Vanderlinden@Sun.COM> | 2010-04-07 19:19:36 -0700 |
---|---|---|
committer | Frank Van Der Linden <Frank.Vanderlinden@Sun.COM> | 2010-04-07 19:19:36 -0700 |
commit | 6e5580c92a7a7c64dd50b768bda246808fb1ee17 (patch) | |
tree | bc2653c1ba4d3b21e973348d14796e6370aaa9ac /usr/src | |
parent | 00d1d19828f3122eb24ae7a68175ba64744f8366 (diff) | |
download | illumos-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.c | 41 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/xpv_platform.c | 42 |
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); /* |