~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/misc/hostinfoHV.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2011 VMware, Inc. All rights reserved.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * hostinfoHV.c --
 
21
 *
 
22
 *    Code to detect different hypervisors and features.
 
23
 */
 
24
 
 
25
#include <string.h>
 
26
#include "vmware.h"
 
27
#if defined(__i386__) || defined(__x86_64__)
 
28
#  include "cpuid_info.h"
 
29
#  include "backdoor_def.h"
 
30
#  include "backdoor_types.h"
 
31
#endif
 
32
#include "hostinfo.h"
 
33
#include "util.h"
 
34
 
 
35
#define LGPFX "HOSTINFO:"
 
36
#define LOGLEVEL_MODULE hostinfo
 
37
#include "loglevel_user.h"
 
38
 
 
39
 
 
40
/*
 
41
 *----------------------------------------------------------------------
 
42
 *
 
43
 *  Hostinfo_HypervisorCPUIDSig --
 
44
 *
 
45
 *      Get the hypervisor signature string from CPUID.
 
46
 *
 
47
 * Results:
 
48
 *      Unqualified 16 byte nul-terminated hypervisor string
 
49
 *      String may contain garbage and caller must free
 
50
 *
 
51
 * Side effects:
 
52
 *      None
 
53
 *
 
54
 *----------------------------------------------------------------------
 
55
 */
 
56
 
 
57
char *
 
58
Hostinfo_HypervisorCPUIDSig(void)
 
59
{
 
60
   uint32 *name = NULL;
 
61
#if defined(__i386__) || defined(__x86_64__)
 
62
   CPUIDRegs regs;
 
63
 
 
64
   __GET_CPUID(1, &regs);
 
65
   if (!(regs.ecx & CPUID_FEATURE_COMMON_ID1ECX_HYPERVISOR)) {
 
66
      return NULL;
 
67
   }
 
68
 
 
69
   regs.ebx = 0;
 
70
   regs.ecx = 0;
 
71
   regs.edx = 0;
 
72
 
 
73
   __GET_CPUID(0x40000000, &regs);
 
74
 
 
75
   if (regs.eax < 0x40000000) {
 
76
      Log(LGPFX" CPUID hypervisor bit is set, but no "
 
77
          "hypervisor vendor signature is present\n");
 
78
   }
 
79
 
 
80
   name = Util_SafeMalloc(4 * sizeof *name);
 
81
 
 
82
   name[0] = regs.ebx;
 
83
   name[1] = regs.ecx;
 
84
   name[2] = regs.edx;
 
85
   name[3] = 0;
 
86
#endif // defined(__i386__) || defined(__x86_64__)
 
87
 
 
88
   return (char *)name;
 
89
}
 
90
 
 
91
 
 
92
/*
 
93
 *----------------------------------------------------------------------
 
94
 *
 
95
 *  Hostinfo_TouchXen --
 
96
 *
 
97
 *      Check for Xen.
 
98
 *
 
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).
 
104
 *
 
105
 * Results:
 
106
 *      TRUE if we are running in a Xen dom0 or domU.
 
107
 *      Linux:
 
108
 *         Illegal instruction exception on real hardware.
 
109
 *         Obscure Xen implementations might return FALSE.
 
110
 *      Windows:
 
111
 *         FALSE on real hardware.
 
112
 *
 
113
 * Side effects:
 
114
 *      Linux: Will raise exception on native hardware.
 
115
 *      Windows: None.
 
116
 *
 
117
 *----------------------------------------------------------------------
 
118
 */
 
119
 
 
120
Bool
 
121
Hostinfo_TouchXen(void)
 
122
{
 
123
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
 
124
#define XEN_CPUID 0x40000000
 
125
   CPUIDRegs regs;
 
126
   uint32 name[4];
 
127
 
 
128
   /*
 
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.
 
132
    */
 
133
 
 
134
   regs.eax = XEN_CPUID;
 
135
   __asm__ __volatile__(
 
136
      "xchgl %%ebx, %0"  "\n\t"
 
137
      "ud2a ; .ascii \"xen\" ; cpuid" "\n\t"
 
138
      "xchgl %%ebx, %0"
 
139
      : "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx)
 
140
      : "a" (regs.eax)
 
141
   );
 
142
 
 
143
   name[0] = regs.ebx;
 
144
   name[1] = regs.ecx;
 
145
   name[2] = regs.edx;
 
146
   name[3] = 0;
 
147
 
 
148
   if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) {
 
149
      return TRUE;
 
150
   }
 
151
 
 
152
   /* Passed checks.  But native and anything non-Xen would #UD before here. */
 
153
   NOT_TESTED();
 
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);
 
157
#endif
 
158
 
 
159
   return FALSE;
 
160
}
 
161
 
 
162
 
 
163
/*
 
164
 *----------------------------------------------------------------------
 
165
 *
 
166
 *  Hostinfo_SLC64Supported --
 
167
 *
 
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().
 
172
 *
 
173
 * Results:
 
174
 *      TRUE if the outer VM supports SLC64.
 
175
 *      FALSE otherwise.
 
176
 *
 
177
 * Side effects:
 
178
 *      Exception if not in a VM, so don't do that!
 
179
 *
 
180
 *----------------------------------------------------------------------
 
181
 */
 
182
 
 
183
Bool
 
184
Hostinfo_SLC64Supported(void)
 
185
{
 
186
#if defined(__i386__) || defined(__x86_64__)
 
187
   return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64);
 
188
#else
 
189
   return FALSE;
 
190
#endif
 
191
}
 
192
 
 
193
 
 
194
/*
 
195
 *----------------------------------------------------------------------
 
196
 *
 
197
 *  Hostinfo_NestedHVReplaySupported --
 
198
 *
 
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().
 
203
 *
 
204
 * Results:
 
205
 *      TRUE if the outer VM supports nexted HV replay.
 
206
 *      FALSE otherwise.
 
207
 *
 
208
 * Side effects:
 
209
 *      Exception if not in a VM, so don't do that!
 
210
 *
 
211
 *----------------------------------------------------------------------
 
212
 */
 
213
 
 
214
Bool
 
215
Hostinfo_NestedHVReplaySupported(void)
 
216
{
 
217
#if defined(__i386__) || defined(__x86_64__)
 
218
   return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK);
 
219
#else
 
220
   return FALSE;
 
221
#endif
 
222
}
 
223
 
 
224
 
 
225
/*
 
226
 *----------------------------------------------------------------------
 
227
 *
 
228
 *  Hostinfo_SynchronizedVTSCs --
 
229
 *
 
230
 *      Access the backdoor to determine if the VCPUs' TSCs are
 
231
 *      synchronized.
 
232
 *
 
233
 * Results:
 
234
 *      TRUE if the outer VM provides synchronized VTSCs.
 
235
 *      FALSE otherwise.
 
236
 *
 
237
 * Side effects:
 
238
 *      Exception if not in a VM, so don't do that!
 
239
 *
 
240
 *----------------------------------------------------------------------
 
241
 */
 
242
 
 
243
Bool
 
244
Hostinfo_SynchronizedVTSCs(void)
 
245
{
 
246
#if defined(__i386__) || defined(__x86_64__)
 
247
   return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS);
 
248
#else
 
249
   return FALSE;
 
250
#endif
 
251
}
 
252
 
 
253
 
 
254
#if defined(_WIN32)
 
255
 
 
256
#if defined(_WIN64)
 
257
// from touchBackdoorMasm64.asm
 
258
void Hostinfo_BackdoorInOut(Backdoor_proto *myBp);
 
259
#endif
 
260
 
 
261
 
 
262
/*
 
263
 *----------------------------------------------------------------------
 
264
 *
 
265
 *  Hostinfo_TouchBackDoor --
 
266
 *
 
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.
 
275
 *
 
276
 * Results:
 
277
 *      TRUE if we succesfully accessed the backdoor, FALSE or segfault
 
278
 *      if not.
 
279
 *
 
280
 * Side effects:
 
281
 *      Exception if not in a VM.
 
282
 *
 
283
 *----------------------------------------------------------------------
 
284
 */
 
285
 
 
286
Bool
 
287
Hostinfo_TouchBackDoor(void)
 
288
{
 
289
   uint32 ebxval;
 
290
 
 
291
#if defined(_WIN64)
 
292
   Backdoor_proto bp;
 
293
 
 
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;
 
298
 
 
299
   Hostinfo_BackdoorInOut(&bp);
 
300
 
 
301
   ebxval = bp.out.bx.words.low;
 
302
#else // _WIN64
 
303
   _asm {
 
304
         push edx
 
305
         push ecx
 
306
         push ebx
 
307
         mov ecx, BDOOR_CMD_GETVERSION
 
308
         mov ebx, ~BDOOR_MAGIC
 
309
         mov eax, BDOOR_MAGIC
 
310
         mov dx, BDOOR_PORT
 
311
         in eax, dx
 
312
         mov ebxval, ebx
 
313
         pop ebx
 
314
         pop ecx
 
315
         pop edx
 
316
   }
 
317
#endif // _WIN64
 
318
 
 
319
   return (ebxval == BDOOR_MAGIC) ? TRUE : FALSE;
 
320
}
 
321
 
 
322
 
 
323
/*
 
324
 *----------------------------------------------------------------------
 
325
 *
 
326
 *  Hostinfo_TouchVirtualPC --
 
327
 *
 
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
 
334
 *
 
335
 * Results:
 
336
 *      TRUE if we succesfully accessed MS Virtual PC, FALSE or
 
337
 *      segfault if not.
 
338
 *
 
339
 * Side effects:
 
340
 *      Exception if not in a VM.
 
341
 *
 
342
 *----------------------------------------------------------------------
 
343
 */
 
344
 
 
345
Bool
 
346
Hostinfo_TouchVirtualPC(void)
 
347
{
 
348
#if defined(_WIN64)
 
349
   return FALSE; // MS Virtual PC is 32-bit only
 
350
#else  // _WIN32
 
351
   uint32 ebxval;
 
352
 
 
353
   _asm {
 
354
      push ebx
 
355
      mov  ebx, 0
 
356
 
 
357
      mov  eax, 1 // Virtual PC function number
 
358
 
 
359
      // execute invalid opcode to call into MS Virtual PC
 
360
 
 
361
      __emit 0Fh
 
362
      __emit 3Fh
 
363
      __emit 07h
 
364
      __emit 0Bh
 
365
 
 
366
      mov ebxval, ebx
 
367
      pop ebx
 
368
   }
 
369
   return !ebxval; // ebx is zero if inside Virtual PC
 
370
#endif
 
371
}
 
372
 
 
373
 
 
374
/*
 
375
 *----------------------------------------------------------------------
 
376
 *
 
377
 *  Hostinfo_NestingSupported --
 
378
 *
 
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().
 
383
 *
 
384
 * Results:
 
385
 *      TRUE if the outer VM supports nesting.
 
386
 *      FALSE otherwise.
 
387
 *
 
388
 * Side effects:
 
389
 *      Exception if not in a VM, so don't do that!
 
390
 *
 
391
 *----------------------------------------------------------------------
 
392
 */
 
393
 
 
394
Bool
 
395
Hostinfo_NestingSupported(void)
 
396
{
 
397
   uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
 
398
   uint32 result;
 
399
 
 
400
#if defined(_WIN64)
 
401
   Backdoor_proto bp;
 
402
 
 
403
   bp.in.ax.quad = BDOOR_MAGIC;
 
404
   bp.in.cx.quad = cmd;
 
405
   bp.in.dx.quad = BDOOR_PORT;
 
406
 
 
407
   Hostinfo_BackdoorInOut(&bp);
 
408
 
 
409
   result = bp.out.ax.words.low;
 
410
#else
 
411
   _asm {
 
412
         push edx
 
413
         push ecx
 
414
         mov ecx, cmd
 
415
         mov eax, BDOOR_MAGIC
 
416
         mov dx, BDOOR_PORT
 
417
         in eax, dx
 
418
         mov result, eax
 
419
         pop ecx
 
420
         pop edx
 
421
   }
 
422
#endif
 
423
 
 
424
   if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
 
425
      return TRUE;
 
426
   }
 
427
   return FALSE;
 
428
}
 
429
 
 
430
 
 
431
/*
 
432
 *----------------------------------------------------------------------
 
433
 *
 
434
 *  Hostinfo_VCPUInfoBackdoor --
 
435
 *
 
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().
 
441
 *
 
442
 * Results:
 
443
 *      TRUE if the outer VM supports the feature.
 
444
 *      FALSE otherwise.
 
445
 *
 
446
 * Side effects:
 
447
 *      Exception if not in a VM, so don't do that!
 
448
 *
 
449
 *----------------------------------------------------------------------
 
450
 */
 
451
 
 
452
Bool
 
453
Hostinfo_VCPUInfoBackdoor(unsigned bit)
 
454
{
 
455
   uint32 cmd = BDOOR_CMD_GET_VCPU_INFO;
 
456
   uint32 result;
 
457
 
 
458
#if defined(_WIN64)
 
459
   Backdoor_proto bp;
 
460
 
 
461
   bp.in.ax.quad = BDOOR_MAGIC;
 
462
   bp.in.cx.quad = cmd;
 
463
   bp.in.dx.quad = BDOOR_PORT;
 
464
 
 
465
   Hostinfo_BackdoorInOut(&bp);
 
466
 
 
467
   result = bp.out.ax.words.low;
 
468
#else
 
469
   _asm {
 
470
         push edx
 
471
         push ecx
 
472
         mov ecx, cmd
 
473
         mov eax, BDOOR_MAGIC
 
474
         mov dx, BDOOR_PORT
 
475
         in eax, dx
 
476
         mov result, eax
 
477
         pop ecx
 
478
         pop edx
 
479
   }
 
480
#endif
 
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;
 
484
}
 
485
 
 
486
 
 
487
#else
 
488
 
 
489
/*
 
490
 *----------------------------------------------------------------------
 
491
 *
 
492
 *  Hostinfo_TouchBackDoor --
 
493
 *
 
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.
 
502
 *
 
503
 * Results:
 
504
 *      TRUE if we succesfully accessed the backdoor, FALSE or segfault
 
505
 *      if not.
 
506
 *
 
507
 * Side effects:
 
508
 *      Exception if not in a VM.
 
509
 *
 
510
 *----------------------------------------------------------------------
 
511
 */
 
512
 
 
513
Bool
 
514
Hostinfo_TouchBackDoor(void)
 
515
{
 
516
   /*
 
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
 
519
    * it.
 
520
    */
 
521
 
 
522
#if !defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
 
523
   uint32 eax;
 
524
   uint32 ebx;
 
525
   uint32 ecx;
 
526
 
 
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"
 
531
      "xchgl %%ebx, %1"
 
532
      : "=a" (eax),
 
533
        "=&rm" (ebx),
 
534
#   else
 
535
      "inl %%dx, %%eax"
 
536
      : "=a" (eax),
 
537
        "=b" (ebx),
 
538
#   endif
 
539
        "=c" (ecx)
 
540
      : "0" (BDOOR_MAGIC),
 
541
        "1" (~BDOOR_MAGIC),
 
542
        "2" (BDOOR_CMD_GETVERSION),
 
543
        "d" (BDOOR_PORT)
 
544
   );
 
545
   if (ebx == BDOOR_MAGIC) {
 
546
      return TRUE;
 
547
   }
 
548
#endif
 
549
 
 
550
   return FALSE;
 
551
}
 
552
 
 
553
 
 
554
/*
 
555
 *----------------------------------------------------------------------
 
556
 *
 
557
 *  Hostinfo_TouchVirtualPC --
 
558
 *
 
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
 
565
 *
 
566
 * Results:
 
567
 *      TRUE if we succesfully accessed MS Virtual PC, FALSE or
 
568
 *      segfault if not.
 
569
 *
 
570
 * Side effects:
 
571
 *      Exception if not in a VM.
 
572
 *
 
573
 *----------------------------------------------------------------------
 
574
 */
 
575
 
 
576
Bool
 
577
Hostinfo_TouchVirtualPC(void)
 
578
{
 
579
#if defined vm_x86_64
 
580
   return FALSE;
 
581
#else
 
582
 
 
583
   uint32 ebxval;
 
584
 
 
585
   __asm__ __volatile__ (
 
586
#  if defined __PIC__        // %ebx is reserved by the compiler.
 
587
     "xchgl %%ebx, %1" "\n\t"
 
588
     ".long 0x0B073F0F" "\n\t"
 
589
     "xchgl %%ebx, %1"
 
590
     : "=&rm" (ebxval)
 
591
     : "a" (1),
 
592
       "0" (0)
 
593
#  else
 
594
     ".long 0x0B073F0F"
 
595
     : "=b" (ebxval)
 
596
     : "a" (1),
 
597
       "b" (0)
 
598
#  endif
 
599
  );
 
600
  return !ebxval; // %%ebx is zero if inside Virtual PC
 
601
#endif
 
602
}
 
603
 
 
604
 
 
605
/*
 
606
 *----------------------------------------------------------------------
 
607
 *
 
608
 *  Hostinfo_NestingSupported --
 
609
 *
 
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().
 
614
 *
 
615
 * Results:
 
616
 *      TRUE if the outer VM supports nesting.
 
617
 *      FALSE otherwise.
 
618
 *
 
619
 * Side effects:
 
620
 *      Exception if not in a VM, so don't do that!
 
621
 *
 
622
 *----------------------------------------------------------------------
 
623
 */
 
624
 
 
625
Bool
 
626
Hostinfo_NestingSupported(void)
 
627
{
 
628
#if defined(__i386__) || defined(__x86_64__)
 
629
   uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
 
630
   uint32 result;
 
631
 
 
632
   __asm__ __volatile__(
 
633
      "inl %%dx, %%eax"
 
634
      : "=a" (result)
 
635
      : "0"  (BDOOR_MAGIC),
 
636
        "c"  (cmd),
 
637
        "d"  (BDOOR_PORT)
 
638
   );
 
639
 
 
640
   if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
 
641
      return TRUE;
 
642
   }
 
643
#endif
 
644
 
 
645
   return FALSE;
 
646
}
 
647
 
 
648
 
 
649
/*
 
650
 *----------------------------------------------------------------------
 
651
 *
 
652
 *  Hostinfo_VCPUInfoBackdoor --
 
653
 *
 
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().
 
659
 *
 
660
 * Results:
 
661
 *      TRUE if the outer VM supports the feature.
 
662
 *      FALSE otherwise.
 
663
 *
 
664
 * Side effects:
 
665
 *      Exception if not in a VM, so don't do that!
 
666
 *
 
667
 *----------------------------------------------------------------------
 
668
 */
 
669
 
 
670
Bool
 
671
Hostinfo_VCPUInfoBackdoor(unsigned bit)
 
672
{
 
673
#if defined(__i386__) || defined(__x86_64__)
 
674
   uint32 result;
 
675
   __asm__ __volatile__(
 
676
      "inl %%dx, %%eax"
 
677
      : "=a" (result)
 
678
      : "0"  (BDOOR_MAGIC),
 
679
        "c"  (BDOOR_CMD_GET_VCPU_INFO),
 
680
        "d"  (BDOOR_PORT)
 
681
   );
 
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;
 
685
#endif
 
686
   return FALSE;
 
687
}
 
688
 
 
689
#endif
 
690