1
/*********************************************************
2
* Copyright (C) 2011 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Code to detect different hypervisors and features.
27
#if defined(__i386__) || defined(__x86_64__)
28
# include "cpuid_info.h"
29
# include "backdoor_def.h"
30
# include "backdoor_types.h"
35
#define LGPFX "HOSTINFO:"
36
#define LOGLEVEL_MODULE hostinfo
37
#include "loglevel_user.h"
41
*----------------------------------------------------------------------
43
* Hostinfo_HypervisorCPUIDSig --
45
* Get the hypervisor signature string from CPUID.
48
* Unqualified 16 byte nul-terminated hypervisor string
49
* String may contain garbage and caller must free
54
*----------------------------------------------------------------------
58
Hostinfo_HypervisorCPUIDSig(void)
61
#if defined(__i386__) || defined(__x86_64__)
64
__GET_CPUID(1, ®s);
65
if (!(regs.ecx & CPUID_FEATURE_COMMON_ID1ECX_HYPERVISOR)) {
73
__GET_CPUID(0x40000000, ®s);
75
if (regs.eax < 0x40000000) {
76
Log(LGPFX" CPUID hypervisor bit is set, but no "
77
"hypervisor vendor signature is present\n");
80
name = Util_SafeMalloc(4 * sizeof *name);
86
#endif // defined(__i386__) || defined(__x86_64__)
93
*----------------------------------------------------------------------
95
* Hostinfo_TouchXen --
99
* Official way is to call Hostinfo_HypervisorCPUIDSig(), which
100
* returns a hypervisor string. This is a secondary check
101
* that guards against a backdoor failure. See PR156185,
102
* http://xenbits.xensource.com/xen-unstable.hg?file/6a383beedf83/tools/misc/xen-detect.c
103
* (Canonical way is /proc/xen, but CPUID is better).
106
* TRUE if we are running in a Xen dom0 or domU.
108
* Illegal instruction exception on real hardware.
109
* Obscure Xen implementations might return FALSE.
111
* FALSE on real hardware.
114
* Linux: Will raise exception on native hardware.
117
*----------------------------------------------------------------------
121
Hostinfo_TouchXen(void)
123
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
124
#define XEN_CPUID 0x40000000
129
* PV mode: ud2a "xen" cpuid (faults on native hardware).
130
* (Only Linux can run PV, so skip others here).
131
* Since PV cannot trap CPUID, this is a Xen hook.
134
regs.eax = XEN_CPUID;
135
__asm__ __volatile__(
136
"xchgl %%ebx, %0" "\n\t"
137
"ud2a ; .ascii \"xen\" ; cpuid" "\n\t"
139
: "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx)
148
if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) {
152
/* Passed checks. But native and anything non-Xen would #UD before here. */
154
Log("Xen detected but hypervisor unrecognized (Xen variant?)\n");
155
Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n",
156
regs.eax, regs.ebx, regs.ecx, regs.edx);
164
*----------------------------------------------------------------------
166
* Hostinfo_SLC64Supported --
168
* Access the backdoor with an SLC64 control query. This is used
169
* to determine if we are running in a VM that supports SLC64.
170
* This function should only be called after determining that the
171
* backdoor is present with Hostinfo_TouchBackdoor().
174
* TRUE if the outer VM supports SLC64.
178
* Exception if not in a VM, so don't do that!
180
*----------------------------------------------------------------------
184
Hostinfo_SLC64Supported(void)
186
#if defined(__i386__) || defined(__x86_64__)
187
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64);
195
*----------------------------------------------------------------------
197
* Hostinfo_NestedHVReplaySupported --
199
* Access the backdoor with a HV replay control query. This is used
200
* to determine if we are running in a VM that supports nested HV replay.
201
* This function should only be called after determining that the
202
* backdoor is present with Hostinfo_TouchBackdoor().
205
* TRUE if the outer VM supports nexted HV replay.
209
* Exception if not in a VM, so don't do that!
211
*----------------------------------------------------------------------
215
Hostinfo_NestedHVReplaySupported(void)
217
#if defined(__i386__) || defined(__x86_64__)
218
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK);
226
*----------------------------------------------------------------------
228
* Hostinfo_SynchronizedVTSCs --
230
* Access the backdoor to determine if the VCPUs' TSCs are
234
* TRUE if the outer VM provides synchronized VTSCs.
238
* Exception if not in a VM, so don't do that!
240
*----------------------------------------------------------------------
244
Hostinfo_SynchronizedVTSCs(void)
246
#if defined(__i386__) || defined(__x86_64__)
247
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS);
257
// from touchBackdoorMasm64.asm
258
void Hostinfo_BackdoorInOut(Backdoor_proto *myBp);
263
*----------------------------------------------------------------------
265
* Hostinfo_TouchBackDoor --
267
* Access the backdoor. This is used to determine if we are
268
* running in a VM or on a physical host. On a physical host
269
* this should generate a GP which we catch and thereby determine
270
* that we are not in a VM. However some OSes do not handle the
271
* GP correctly and the process continues running returning garbage.
272
* In this case we check the EBX register which should be
273
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
274
* return either TRUE or FALSE.
277
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
281
* Exception if not in a VM.
283
*----------------------------------------------------------------------
287
Hostinfo_TouchBackDoor(void)
294
bp.in.ax.quad = BDOOR_MAGIC;
295
bp.in.size = ~BDOOR_MAGIC;
296
bp.in.cx.quad = BDOOR_CMD_GETVERSION;
297
bp.in.dx.quad = BDOOR_PORT;
299
Hostinfo_BackdoorInOut(&bp);
301
ebxval = bp.out.bx.words.low;
307
mov ecx, BDOOR_CMD_GETVERSION
308
mov ebx, ~BDOOR_MAGIC
319
return (ebxval == BDOOR_MAGIC) ? TRUE : FALSE;
324
*----------------------------------------------------------------------
326
* Hostinfo_TouchVirtualPC --
328
* Access MS Virtual PC's backdoor. This is used to determine if
329
* we are running in a MS Virtual PC or on a physical host. Works
330
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
331
* is an invalid opcode instead or writing to a port. Since
332
* MS VPC is 32-bit only, the WIN64 path returns FALSE.
333
* See: See: http://www.codeproject.com/KB/system/VmDetect.aspx
336
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
340
* Exception if not in a VM.
342
*----------------------------------------------------------------------
346
Hostinfo_TouchVirtualPC(void)
349
return FALSE; // MS Virtual PC is 32-bit only
357
mov eax, 1 // Virtual PC function number
359
// execute invalid opcode to call into MS Virtual PC
369
return !ebxval; // ebx is zero if inside Virtual PC
375
*----------------------------------------------------------------------
377
* Hostinfo_NestingSupported --
379
* Access the backdoor with a nesting control query. This is used
380
* to determine if we are running in a VM that supports nesting.
381
* This function should only be called after determining that the
382
* backdoor is present with Hostinfo_TouchBackdoor().
385
* TRUE if the outer VM supports nesting.
389
* Exception if not in a VM, so don't do that!
391
*----------------------------------------------------------------------
395
Hostinfo_NestingSupported(void)
397
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
403
bp.in.ax.quad = BDOOR_MAGIC;
405
bp.in.dx.quad = BDOOR_PORT;
407
Hostinfo_BackdoorInOut(&bp);
409
result = bp.out.ax.words.low;
424
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
432
*----------------------------------------------------------------------
434
* Hostinfo_VCPUInfoBackdoor --
436
* Access the backdoor with an VCPU info query. This is used to
437
* determine whether a VCPU supports a particular feature,
438
* determined by 'bit'. This function should only be called after
439
* determining that the backdoor is present with
440
* Hostinfo_TouchBackdoor().
443
* TRUE if the outer VM supports the feature.
447
* Exception if not in a VM, so don't do that!
449
*----------------------------------------------------------------------
453
Hostinfo_VCPUInfoBackdoor(unsigned bit)
455
uint32 cmd = BDOOR_CMD_GET_VCPU_INFO;
461
bp.in.ax.quad = BDOOR_MAGIC;
463
bp.in.dx.quad = BDOOR_PORT;
465
Hostinfo_BackdoorInOut(&bp);
467
result = bp.out.ax.words.low;
481
/* If reserved bit is 1, this command wasn't implemented. */
482
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
483
(result & (1 << bit)) != 0;
490
*----------------------------------------------------------------------
492
* Hostinfo_TouchBackDoor --
494
* Access the backdoor. This is used to determine if we are
495
* running in a VM or on a physical host. On a physical host
496
* this should generate a GP which we catch and thereby determine
497
* that we are not in a VM. However some OSes do not handle the
498
* GP correctly and the process continues running returning garbage.
499
* In this case we check the EBX register which should be
500
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
501
* return either TRUE or FALSE.
504
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
508
* Exception if not in a VM.
510
*----------------------------------------------------------------------
514
Hostinfo_TouchBackDoor(void)
517
* XXX: This can cause Apple's Crash Reporter to erroneously display
518
* a crash, even though the process has caught the SIGILL and handled
522
#if !defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
527
__asm__ __volatile__(
528
# if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
529
"xchgl %%ebx, %1" "\n\t"
530
"inl %%dx, %%eax" "\n\t"
542
"2" (BDOOR_CMD_GETVERSION),
545
if (ebx == BDOOR_MAGIC) {
555
*----------------------------------------------------------------------
557
* Hostinfo_TouchVirtualPC --
559
* Access MS Virtual PC's backdoor. This is used to determine if
560
* we are running in a MS Virtual PC or on a physical host. Works
561
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
562
* is an invalid opcode instead or writing to a port. Since
563
* MS VPC is 32-bit only, the 64-bit path returns FALSE.
564
* See: http://www.codeproject.com/KB/system/VmDetect.aspx
567
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
571
* Exception if not in a VM.
573
*----------------------------------------------------------------------
577
Hostinfo_TouchVirtualPC(void)
579
#if defined vm_x86_64
585
__asm__ __volatile__ (
586
# if defined __PIC__ // %ebx is reserved by the compiler.
587
"xchgl %%ebx, %1" "\n\t"
588
".long 0x0B073F0F" "\n\t"
600
return !ebxval; // %%ebx is zero if inside Virtual PC
606
*----------------------------------------------------------------------
608
* Hostinfo_NestingSupported --
610
* Access the backdoor with a nesting control query. This is used
611
* to determine if we are running inside a VM that supports nesting.
612
* This function should only be called after determining that the
613
* backdoor is present with Hostinfo_TouchBackdoor().
616
* TRUE if the outer VM supports nesting.
620
* Exception if not in a VM, so don't do that!
622
*----------------------------------------------------------------------
626
Hostinfo_NestingSupported(void)
628
#if defined(__i386__) || defined(__x86_64__)
629
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
632
__asm__ __volatile__(
640
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
650
*----------------------------------------------------------------------
652
* Hostinfo_VCPUInfoBackdoor --
654
* Access the backdoor with an VCPU info query. This is used to
655
* determine whether a VCPU supports a particular feature,
656
* determined by 'bit'. This function should only be called after
657
* determining that the backdoor is present with
658
* Hostinfo_TouchBackdoor().
661
* TRUE if the outer VM supports the feature.
665
* Exception if not in a VM, so don't do that!
667
*----------------------------------------------------------------------
671
Hostinfo_VCPUInfoBackdoor(unsigned bit)
673
#if defined(__i386__) || defined(__x86_64__)
675
__asm__ __volatile__(
679
"c" (BDOOR_CMD_GET_VCPU_INFO),
682
/* If reserved bit is 1, this command wasn't implemented. */
683
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
684
(result & (1 << bit)) != 0;