From: VMware, Inc <> Date: Tue, 29 Mar 2011 20:20:39 +0000 (-0700) Subject: lib/misc: move hypervisor-related functions into a new file. X-Git-Tag: 2011.03.28-387002~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e85ce0ad847e9fa7ccb364bd3c8a32ed3b6f6b75;p=thirdparty%2Fopen-vm-tools.git lib/misc: move hypervisor-related functions into a new file. While working on bug 692831, the "checkvm" utility was changed to call some Hostinfo functions. The compilation unit where those functions lived referenced a whole bunch of other symbols that ended up pulling lib/unicode into checkvm. That made the binary size blow up from 5kB to 450kB, stripped. Putting these functions into a separate compilation unit avoids that issue, and makes the binary grow much less (it's now ~45kB). Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/misc/Makefile.am b/open-vm-tools/lib/misc/Makefile.am index 3946d4a5f..0089f56ab 100644 --- a/open-vm-tools/lib/misc/Makefile.am +++ b/open-vm-tools/lib/misc/Makefile.am @@ -27,6 +27,7 @@ libMisc_la_SOURCES += dynbuf.c libMisc_la_SOURCES += escape.c libMisc_la_SOURCES += hashTable.c libMisc_la_SOURCES += hostinfo.c +libMisc_la_SOURCES += hostinfoHV.c libMisc_la_SOURCES += hostinfoPosix.c libMisc_la_SOURCES += hostname.c libMisc_la_SOURCES += hostType.c diff --git a/open-vm-tools/lib/misc/hostinfo.c b/open-vm-tools/lib/misc/hostinfo.c index cc2528ece..375ef6b18 100644 --- a/open-vm-tools/lib/misc/hostinfo.c +++ b/open-vm-tools/lib/misc/hostinfo.c @@ -296,204 +296,3 @@ Hostinfo_GetOSName(uint32 outBufFullLen, // IN: length of osFullName buffer return retval; } - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_HypervisorCPUIDSig -- - * - * Get the hypervisor signature string from CPUID. - * - * Results: - * Unqualified 16 byte nul-terminated hypervisor string - * String may contain garbage and caller must free - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -char * -Hostinfo_HypervisorCPUIDSig(void) -{ - uint32 *name = NULL; -#if defined(__i386__) || defined(__x86_64__) - CPUIDRegs regs; - - __GET_CPUID(1, ®s); - if (!(regs.ecx & CPUID_FEATURE_COMMON_ID1ECX_HYPERVISOR)) { - return NULL; - } - - regs.ebx = 0; - regs.ecx = 0; - regs.edx = 0; - - __GET_CPUID(0x40000000, ®s); - - if (regs.eax < 0x40000000) { - Log(LGPFX" CPUID hypervisor bit is set, but no " - "hypervisor vendor signature is present\n"); - } - - name = Util_SafeMalloc(4 * sizeof *name); - - name[0] = regs.ebx; - name[1] = regs.ecx; - name[2] = regs.edx; - name[3] = 0; -#endif // defined(__i386__) || defined(__x86_64__) - - return (char *)name; -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_TouchXen -- - * - * Check for Xen. - * - * Official way is to call Hostinfo_HypervisorCPUIDSig(), which - * returns a hypervisor string. This is a secondary check - * that guards against a backdoor failure. See PR156185, - * http://xenbits.xensource.com/xen-unstable.hg?file/6a383beedf83/tools/misc/xen-detect.c - * (Canonical way is /proc/xen, but CPUID is better). - * - * Results: - * TRUE if we are running in a Xen dom0 or domU. - * Linux: - * Illegal instruction exception on real hardware. - * Obscure Xen implementations might return FALSE. - * Windows: - * FALSE on real hardware. - * - * Side effects: - * Linux: Will raise exception on native hardware. - * Windows: None. - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_TouchXen(void) -{ -#if defined(linux) && (defined(__i386__) || defined(__x86_64__)) -#define XEN_CPUID 0x40000000 - CPUIDRegs regs; - uint32 name[4]; - - /* - * PV mode: ud2a "xen" cpuid (faults on native hardware). - * (Only Linux can run PV, so skip others here). - * Since PV cannot trap CPUID, this is a Xen hook. - */ - - regs.eax = XEN_CPUID; - __asm__ __volatile__( - "xchgl %%ebx, %0" "\n\t" - "ud2a ; .ascii \"xen\" ; cpuid" "\n\t" - "xchgl %%ebx, %0" - : "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx) - : "a" (regs.eax) - ); - - name[0] = regs.ebx; - name[1] = regs.ecx; - name[2] = regs.edx; - name[3] = 0; - - if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) { - return TRUE; - } - - /* Passed checks. But native and anything non-Xen would #UD before here. */ - NOT_TESTED(); - Log("Xen detected but hypervisor unrecognized (Xen variant?)\n"); - Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n", - regs.eax, regs.ebx, regs.ecx, regs.edx); -#endif - - return FALSE; -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_SLC64Supported -- - * - * Access the backdoor with an SLC64 control query. This is used - * to determine if we are running in a VM that supports SLC64. - * This function should only be called after determining that the - * backdoor is present with Hostinfo_TouchBackdoor(). - * - * Results: - * TRUE if the outer VM supports SLC64. - * FALSE otherwise. - * - * Side effects: - * Exception if not in a VM, so don't do that! - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_SLC64Supported(void) -{ - return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64); -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_NestedHVReplaySupported -- - * - * Access the backdoor with a HV replay control query. This is used - * to determine if we are running in a VM that supports nested HV replay. - * This function should only be called after determining that the - * backdoor is present with Hostinfo_TouchBackdoor(). - * - * Results: - * TRUE if the outer VM supports nexted HV replay. - * FALSE otherwise. - * - * Side effects: - * Exception if not in a VM, so don't do that! - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_NestedHVReplaySupported(void) -{ - return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK); -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_SynchronizedVTSCs -- - * - * Access the backdoor to determine if the VCPUs' TSCs are - * synchronized. - * - * Results: - * TRUE if the outer VM provides synchronized VTSCs. - * FALSE otherwise. - * - * Side effects: - * Exception if not in a VM, so don't do that! - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_SynchronizedVTSCs(void) -{ - return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS); -} diff --git a/open-vm-tools/lib/misc/hostinfoHV.c b/open-vm-tools/lib/misc/hostinfoHV.c new file mode 100644 index 000000000..d07d243d3 --- /dev/null +++ b/open-vm-tools/lib/misc/hostinfoHV.c @@ -0,0 +1,678 @@ +/********************************************************* + * Copyright (C) 2011 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation version 2.1 and no 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. See the Lesser GNU General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser 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. + * + *********************************************************/ + +/* + * hostinfoHV.c -- + * + * Code to detect different hypervisors and features. + */ + +#include +#include "vmware.h" +#if defined(__i386__) || defined(__x86_64__) +# include "cpuid_info.h" +#endif +#include "backdoor_def.h" +#include "backdoor_types.h" +#include "hostinfo.h" +#include "util.h" + +#define LGPFX "HOSTINFO:" +#define LOGLEVEL_MODULE hostinfo +#include "loglevel_user.h" + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_HypervisorCPUIDSig -- + * + * Get the hypervisor signature string from CPUID. + * + * Results: + * Unqualified 16 byte nul-terminated hypervisor string + * String may contain garbage and caller must free + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +char * +Hostinfo_HypervisorCPUIDSig(void) +{ + uint32 *name = NULL; +#if defined(__i386__) || defined(__x86_64__) + CPUIDRegs regs; + + __GET_CPUID(1, ®s); + if (!(regs.ecx & CPUID_FEATURE_COMMON_ID1ECX_HYPERVISOR)) { + return NULL; + } + + regs.ebx = 0; + regs.ecx = 0; + regs.edx = 0; + + __GET_CPUID(0x40000000, ®s); + + if (regs.eax < 0x40000000) { + Log(LGPFX" CPUID hypervisor bit is set, but no " + "hypervisor vendor signature is present\n"); + } + + name = Util_SafeMalloc(4 * sizeof *name); + + name[0] = regs.ebx; + name[1] = regs.ecx; + name[2] = regs.edx; + name[3] = 0; +#endif // defined(__i386__) || defined(__x86_64__) + + return (char *)name; +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_TouchXen -- + * + * Check for Xen. + * + * Official way is to call Hostinfo_HypervisorCPUIDSig(), which + * returns a hypervisor string. This is a secondary check + * that guards against a backdoor failure. See PR156185, + * http://xenbits.xensource.com/xen-unstable.hg?file/6a383beedf83/tools/misc/xen-detect.c + * (Canonical way is /proc/xen, but CPUID is better). + * + * Results: + * TRUE if we are running in a Xen dom0 or domU. + * Linux: + * Illegal instruction exception on real hardware. + * Obscure Xen implementations might return FALSE. + * Windows: + * FALSE on real hardware. + * + * Side effects: + * Linux: Will raise exception on native hardware. + * Windows: None. + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_TouchXen(void) +{ +#if defined(linux) && (defined(__i386__) || defined(__x86_64__)) +#define XEN_CPUID 0x40000000 + CPUIDRegs regs; + uint32 name[4]; + + /* + * PV mode: ud2a "xen" cpuid (faults on native hardware). + * (Only Linux can run PV, so skip others here). + * Since PV cannot trap CPUID, this is a Xen hook. + */ + + regs.eax = XEN_CPUID; + __asm__ __volatile__( + "xchgl %%ebx, %0" "\n\t" + "ud2a ; .ascii \"xen\" ; cpuid" "\n\t" + "xchgl %%ebx, %0" + : "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx) + : "a" (regs.eax) + ); + + name[0] = regs.ebx; + name[1] = regs.ecx; + name[2] = regs.edx; + name[3] = 0; + + if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) { + return TRUE; + } + + /* Passed checks. But native and anything non-Xen would #UD before here. */ + NOT_TESTED(); + Log("Xen detected but hypervisor unrecognized (Xen variant?)\n"); + Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n", + regs.eax, regs.ebx, regs.ecx, regs.edx); +#endif + + return FALSE; +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_SLC64Supported -- + * + * Access the backdoor with an SLC64 control query. This is used + * to determine if we are running in a VM that supports SLC64. + * This function should only be called after determining that the + * backdoor is present with Hostinfo_TouchBackdoor(). + * + * Results: + * TRUE if the outer VM supports SLC64. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_SLC64Supported(void) +{ + return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64); +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_NestedHVReplaySupported -- + * + * Access the backdoor with a HV replay control query. This is used + * to determine if we are running in a VM that supports nested HV replay. + * This function should only be called after determining that the + * backdoor is present with Hostinfo_TouchBackdoor(). + * + * Results: + * TRUE if the outer VM supports nexted HV replay. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_NestedHVReplaySupported(void) +{ + return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK); +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_SynchronizedVTSCs -- + * + * Access the backdoor to determine if the VCPUs' TSCs are + * synchronized. + * + * Results: + * TRUE if the outer VM provides synchronized VTSCs. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_SynchronizedVTSCs(void) +{ + return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS); +} + + +#if defined(_WIN32) + +#if defined(_WIN64) +// from touchBackdoorMasm64.asm +void Hostinfo_BackdoorInOut(Backdoor_proto *myBp); +#endif + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_TouchBackDoor -- + * + * Access the backdoor. This is used to determine if we are + * running in a VM or on a physical host. On a physical host + * this should generate a GP which we catch and thereby determine + * that we are not in a VM. However some OSes do not handle the + * GP correctly and the process continues running returning garbage. + * In this case we check the EBX register which should be + * BDOOR_MAGIC if the IN was handled in a VM. Based on this we + * return either TRUE or FALSE. + * + * Results: + * TRUE if we succesfully accessed the backdoor, FALSE or segfault + * if not. + * + * Side effects: + * Exception if not in a VM. + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_TouchBackDoor(void) +{ + uint32 ebxval; + +#if defined(_WIN64) + Backdoor_proto bp; + + bp.in.ax.quad = BDOOR_MAGIC; + bp.in.size = ~BDOOR_MAGIC; + bp.in.cx.quad = BDOOR_CMD_GETVERSION; + bp.in.dx.quad = BDOOR_PORT; + + Hostinfo_BackdoorInOut(&bp); + + ebxval = bp.out.bx.words.low; +#else // _WIN64 + _asm { + push edx + push ecx + push ebx + mov ecx, BDOOR_CMD_GETVERSION + mov ebx, ~BDOOR_MAGIC + mov eax, BDOOR_MAGIC + mov dx, BDOOR_PORT + in eax, dx + mov ebxval, ebx + pop ebx + pop ecx + pop edx + } +#endif // _WIN64 + + return (ebxval == BDOOR_MAGIC) ? TRUE : FALSE; +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_TouchVirtualPC -- + * + * Access MS Virtual PC's backdoor. This is used to determine if + * we are running in a MS Virtual PC or on a physical host. Works + * the same as Hostinfo_TouchBackDoor, except the entry to MS VPC + * is an invalid opcode instead or writing to a port. Since + * MS VPC is 32-bit only, the WIN64 path returns FALSE. + * See: See: http://www.codeproject.com/KB/system/VmDetect.aspx + * + * Results: + * TRUE if we succesfully accessed MS Virtual PC, FALSE or + * segfault if not. + * + * Side effects: + * Exception if not in a VM. + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_TouchVirtualPC(void) +{ +#if defined(_WIN64) + return FALSE; // MS Virtual PC is 32-bit only +#else // _WIN32 + uint32 ebxval; + + _asm { + push ebx + mov ebx, 0 + + mov eax, 1 // Virtual PC function number + + // execute invalid opcode to call into MS Virtual PC + + __emit 0Fh + __emit 3Fh + __emit 07h + __emit 0Bh + + mov ebxval, ebx + pop ebx + } + return !ebxval; // ebx is zero if inside Virtual PC +#endif +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_NestingSupported -- + * + * Access the backdoor with a nesting control query. This is used + * to determine if we are running in a VM that supports nesting. + * This function should only be called after determining that the + * backdoor is present with Hostinfo_TouchBackdoor(). + * + * Results: + * TRUE if the outer VM supports nesting. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_NestingSupported(void) +{ + uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL; + uint32 result; + +#if defined(_WIN64) + Backdoor_proto bp; + + bp.in.ax.quad = BDOOR_MAGIC; + bp.in.cx.quad = cmd; + bp.in.dx.quad = BDOOR_PORT; + + Hostinfo_BackdoorInOut(&bp); + + result = bp.out.ax.words.low; +#else + _asm { + push edx + push ecx + mov ecx, cmd + mov eax, BDOOR_MAGIC + mov dx, BDOOR_PORT + in eax, dx + mov result, eax + pop ecx + pop edx + } +#endif + + if (result >= NESTING_CONTROL_QUERY && result != ~0U) { + return TRUE; + } + return FALSE; +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_VCPUInfoBackdoor -- + * + * Access the backdoor with an VCPU info query. This is used to + * determine whether a VCPU supports a particular feature, + * determined by 'bit'. This function should only be called after + * determining that the backdoor is present with + * Hostinfo_TouchBackdoor(). + * + * Results: + * TRUE if the outer VM supports the feature. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_VCPUInfoBackdoor(unsigned bit) +{ + uint32 cmd = BDOOR_CMD_GET_VCPU_INFO; + uint32 result; + +#if defined(_WIN64) + Backdoor_proto bp; + + bp.in.ax.quad = BDOOR_MAGIC; + bp.in.cx.quad = cmd; + bp.in.dx.quad = BDOOR_PORT; + + Hostinfo_BackdoorInOut(&bp); + + result = bp.out.ax.words.low; +#else + _asm { + push edx + push ecx + mov ecx, cmd + mov eax, BDOOR_MAGIC + mov dx, BDOOR_PORT + in eax, dx + mov result, eax + pop ecx + pop edx + } +#endif + /* If reserved bit is 1, this command wasn't implemented. */ + return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 && + (result & (1 << bit)) != 0; +} + + +#else + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_TouchBackDoor -- + * + * Access the backdoor. This is used to determine if we are + * running in a VM or on a physical host. On a physical host + * this should generate a GP which we catch and thereby determine + * that we are not in a VM. However some OSes do not handle the + * GP correctly and the process continues running returning garbage. + * In this case we check the EBX register which should be + * BDOOR_MAGIC if the IN was handled in a VM. Based on this we + * return either TRUE or FALSE. + * + * Results: + * TRUE if we succesfully accessed the backdoor, FALSE or segfault + * if not. + * + * Side effects: + * Exception if not in a VM. + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_TouchBackDoor(void) +{ + /* + * XXX: This can cause Apple's Crash Reporter to erroneously display + * a crash, even though the process has caught the SIGILL and handled + * it. + */ + +#if !defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) + uint32 eax; + uint32 ebx; + uint32 ecx; + + __asm__ __volatile__( +# if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler. + "xchgl %%ebx, %1" "\n\t" + "inl %%dx, %%eax" "\n\t" + "xchgl %%ebx, %1" + : "=a" (eax), + "=&rm" (ebx), +# else + "inl %%dx, %%eax" + : "=a" (eax), + "=b" (ebx), +# endif + "=c" (ecx) + : "0" (BDOOR_MAGIC), + "1" (~BDOOR_MAGIC), + "2" (BDOOR_CMD_GETVERSION), + "d" (BDOOR_PORT) + ); + if (ebx == BDOOR_MAGIC) { + return TRUE; + } +#endif + + return FALSE; +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_TouchVirtualPC -- + * + * Access MS Virtual PC's backdoor. This is used to determine if + * we are running in a MS Virtual PC or on a physical host. Works + * the same as Hostinfo_TouchBackDoor, except the entry to MS VPC + * is an invalid opcode instead or writing to a port. Since + * MS VPC is 32-bit only, the 64-bit path returns FALSE. + * See: http://www.codeproject.com/KB/system/VmDetect.aspx + * + * Results: + * TRUE if we succesfully accessed MS Virtual PC, FALSE or + * segfault if not. + * + * Side effects: + * Exception if not in a VM. + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_TouchVirtualPC(void) +{ +#if defined vm_x86_64 + return FALSE; +#else + + uint32 ebxval; + + __asm__ __volatile__ ( +# if defined __PIC__ // %ebx is reserved by the compiler. + "xchgl %%ebx, %1" "\n\t" + ".long 0x0B073F0F" "\n\t" + "xchgl %%ebx, %1" + : "=&rm" (ebxval) + : "a" (1), + "0" (0) +# else + ".long 0x0B073F0F" + : "=b" (ebxval) + : "a" (1), + "b" (0) +# endif + ); + return !ebxval; // %%ebx is zero if inside Virtual PC +#endif +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_NestingSupported -- + * + * Access the backdoor with a nesting control query. This is used + * to determine if we are running inside a VM that supports nesting. + * This function should only be called after determining that the + * backdoor is present with Hostinfo_TouchBackdoor(). + * + * Results: + * TRUE if the outer VM supports nesting. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_NestingSupported(void) +{ +#if defined(__i386__) || defined(__x86_64__) + uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL; + uint32 result; + + __asm__ __volatile__( + "inl %%dx, %%eax" + : "=a" (result) + : "0" (BDOOR_MAGIC), + "c" (cmd), + "d" (BDOOR_PORT) + ); + + if (result >= NESTING_CONTROL_QUERY && result != ~0U) { + return TRUE; + } +#endif + + return FALSE; +} + + +/* + *---------------------------------------------------------------------- + * + * Hostinfo_VCPUInfoBackdoor -- + * + * Access the backdoor with an VCPU info query. This is used to + * determine whether a VCPU supports a particular feature, + * determined by 'bit'. This function should only be called after + * determining that the backdoor is present with + * Hostinfo_TouchBackdoor(). + * + * Results: + * TRUE if the outer VM supports the feature. + * FALSE otherwise. + * + * Side effects: + * Exception if not in a VM, so don't do that! + * + *---------------------------------------------------------------------- + */ + +Bool +Hostinfo_VCPUInfoBackdoor(unsigned bit) +{ +#if defined(__i386__) || defined(__x86_64__) + uint32 result; + __asm__ __volatile__( + "inl %%dx, %%eax" + : "=a" (result) + : "0" (BDOOR_MAGIC), + "c" (BDOOR_CMD_GET_VCPU_INFO), + "d" (BDOOR_PORT) + ); + /* If reserved bit is 1, this command wasn't implemented. */ + return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 && + (result & (1 << bit)) != 0; +#endif + return FALSE; +} + +#endif + diff --git a/open-vm-tools/lib/misc/hostinfoPosix.c b/open-vm-tools/lib/misc/hostinfoPosix.c index fd0a59f8c..9f1dc4dc4 100644 --- a/open-vm-tools/lib/misc/hostinfoPosix.c +++ b/open-vm-tools/lib/misc/hostinfoPosix.c @@ -1810,207 +1810,6 @@ Hostinfo_LogMemUsage(void) } -/* - *---------------------------------------------------------------------- - * - * Hostinfo_TouchBackDoor -- - * - * Access the backdoor. This is used to determine if we are - * running in a VM or on a physical host. On a physical host - * this should generate a GP which we catch and thereby determine - * that we are not in a VM. However some OSes do not handle the - * GP correctly and the process continues running returning garbage. - * In this case we check the EBX register which should be - * BDOOR_MAGIC if the IN was handled in a VM. Based on this we - * return either TRUE or FALSE. - * - * Results: - * TRUE if we succesfully accessed the backdoor, FALSE or segfault - * if not. - * - * Side effects: - * Exception if not in a VM. - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_TouchBackDoor(void) -{ - /* - * XXX: This can cause Apple's Crash Reporter to erroneously display - * a crash, even though the process has caught the SIGILL and handled - * it. - */ - -#if !defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) - uint32 eax; - uint32 ebx; - uint32 ecx; - - __asm__ __volatile__( -# if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler. - "xchgl %%ebx, %1" "\n\t" - "inl %%dx, %%eax" "\n\t" - "xchgl %%ebx, %1" - : "=a" (eax), - "=&rm" (ebx), -# else - "inl %%dx, %%eax" - : "=a" (eax), - "=b" (ebx), -# endif - "=c" (ecx) - : "0" (BDOOR_MAGIC), - "1" (~BDOOR_MAGIC), - "2" (BDOOR_CMD_GETVERSION), - "d" (BDOOR_PORT) - ); - if (ebx == BDOOR_MAGIC) { - return TRUE; - } -#endif - - return FALSE; -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_TouchVirtualPC -- - * - * Access MS Virtual PC's backdoor. This is used to determine if - * we are running in a MS Virtual PC or on a physical host. Works - * the same as Hostinfo_TouchBackDoor, except the entry to MS VPC - * is an invalid opcode instead or writing to a port. Since - * MS VPC is 32-bit only, the 64-bit path returns FALSE. - * See: http://www.codeproject.com/KB/system/VmDetect.aspx - * - * Results: - * TRUE if we succesfully accessed MS Virtual PC, FALSE or - * segfault if not. - * - * Side effects: - * Exception if not in a VM. - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_TouchVirtualPC(void) -{ -#if defined vm_x86_64 - return FALSE; -#else - - uint32 ebxval; - - __asm__ __volatile__ ( -# if defined __PIC__ // %ebx is reserved by the compiler. - "xchgl %%ebx, %1" "\n\t" - ".long 0x0B073F0F" "\n\t" - "xchgl %%ebx, %1" - : "=&rm" (ebxval) - : "a" (1), - "0" (0) -# else - ".long 0x0B073F0F" - : "=b" (ebxval) - : "a" (1), - "b" (0) -# endif - ); - return !ebxval; // %%ebx is zero if inside Virtual PC -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_NestingSupported -- - * - * Access the backdoor with a nesting control query. This is used - * to determine if we are running inside a VM that supports nesting. - * This function should only be called after determining that the - * backdoor is present with Hostinfo_TouchBackdoor(). - * - * Results: - * TRUE if the outer VM supports nesting. - * FALSE otherwise. - * - * Side effects: - * Exception if not in a VM, so don't do that! - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_NestingSupported(void) -{ -#if defined(__i386__) || defined(__x86_64__) - uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL; - uint32 result; - - __asm__ __volatile__( - "inl %%dx, %%eax" - : "=a" (result) - : "0" (BDOOR_MAGIC), - "c" (cmd), - "d" (BDOOR_PORT) - ); - - if (result >= NESTING_CONTROL_QUERY && result != ~0U) { - return TRUE; - } -#endif - - return FALSE; -} - - -/* - *---------------------------------------------------------------------- - * - * Hostinfo_VCPUInfoBackdoor -- - * - * Access the backdoor with an VCPU info query. This is used to - * determine whether a VCPU supports a particular feature, - * determined by 'bit'. This function should only be called after - * determining that the backdoor is present with - * Hostinfo_TouchBackdoor(). - * - * Results: - * TRUE if the outer VM supports the feature. - * FALSE otherwise. - * - * Side effects: - * Exception if not in a VM, so don't do that! - * - *---------------------------------------------------------------------- - */ - -Bool -Hostinfo_VCPUInfoBackdoor(unsigned bit) -{ -#if defined(__i386__) || defined(__x86_64__) - uint32 result; - __asm__ __volatile__( - "inl %%dx, %%eax" - : "=a" (result) - : "0" (BDOOR_MAGIC), - "c" (BDOOR_CMD_GET_VCPU_INFO), - "d" (BDOOR_PORT) - ); - /* If reserved bit is 1, this command wasn't implemented. */ - return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 && - (result & (1 << bit)) != 0; -#endif - return FALSE; -} - - /* *---------------------------------------------------------------------- *