1
/*********************************************************
2
* Copyright (C) 2003-2009 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
*********************************************************/
19
/*********************************************************
20
* The contents of this file are subject to the terms of the Common
21
* Development and Distribution License (the "License") version 1.0
22
* and no later version. You may not use this file except in
23
* compliance with the License.
25
* You can obtain a copy of the License at
26
* http://www.opensource.org/licenses/cddl1.php
28
* See the License for the specific language governing permissions
29
* and limitations under the License.
31
*********************************************************/
36
* CPUID-related assembly functions.
39
#ifndef _X86CPUID_ASM_H_
40
#define _X86CPUID_ASM_H_
42
#define INCLUDE_ALLOW_USERLEVEL
43
#define INCLUDE_ALLOW_VMMEXT
44
#define INCLUDE_ALLOW_MODULE
45
#define INCLUDE_ALLOW_VMMON
46
#define INCLUDE_ALLOW_VMNIXMOD
47
#define INCLUDE_ALLOW_VMK_MODULE
48
#define INCLUDE_ALLOW_VMKERNEL
49
#define INCLUDE_ALLOW_DISTRIBUTE
50
#define INCLUDE_ALLOW_VMCORE
51
#include "includeCheck.h"
53
#include "vm_basic_asm.h"
58
* x86-64 windows doesn't support inline asm so we have to use these
59
* intrinsic functions defined in the compiler. Not all of these are well
60
* documented. There is an array in the compiler dll (c1.dll) which has
61
* an array of the names of all the intrinsics minus the leading
62
* underscore. Searching around in the ntddk.h file can also be helpful.
64
* The declarations for the intrinsic functions were taken from the DDK.
65
* Our declarations must match the ddk's otherwise the 64-bit c++ compiler
66
* will complain about second linkage of the intrinsic functions.
67
* We define the intrinsic using the basic types corresponding to the
68
* Windows typedefs. This avoids having to include windows header files
69
* to get to the windows types.
77
* intrinsic functions only supported by x86-64 windows as of 2k3sp1
79
void __cpuid(unsigned int*, unsigned int);
80
#pragma intrinsic(__cpuid)
81
#endif /* VM_X86_64 */
92
* Checked against the Intel manual and GCC --hpreg
94
* Need __volatile__ and "memory" since CPUID has a synchronizing effect.
95
* The CPUID may also change at runtime (APIC flag, etc).
100
__GET_CPUID(int eax, // IN
101
CPUIDRegs *regs) // OUT
103
__asm__ __volatile__(
104
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
105
"movl %%ebx, %1" "\n\t"
108
: "=a" (regs->eax), "=&rm" (regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
111
: "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
119
__GET_CPUID2(int eax, // IN
121
CPUIDRegs *regs) // OUT
123
__asm__ __volatile__(
124
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
125
"movl %%ebx, %1" "\n\t"
128
: "=a" (regs->eax), "=&rm" (regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
131
: "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
133
: "a" (eax), "c" (ecx)
139
__GET_EAX_FROM_CPUID(int eax) // IN
141
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
144
__asm__ __volatile__(
145
"movl %%ebx, %1" "\n\t"
148
: "=a" (eax), "=&rm" (ebx)
150
: "memory", "%ecx", "%edx"
153
__asm__ __volatile__(
157
: "memory", "%ebx", "%ecx", "%edx"
165
__GET_EBX_FROM_CPUID(int eax) // IN
169
__asm__ __volatile__(
170
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
171
"movl %%ebx, %1" "\n\t"
174
: "=a" (eax), "=&rm" (ebx)
177
: "=a" (eax), "=b" (ebx)
180
: "memory", "%ecx", "%edx"
187
__GET_ECX_FROM_CPUID(int eax) // IN
190
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
193
__asm__ __volatile__(
194
"movl %%ebx, %1" "\n\t"
197
: "=a" (eax), "=&rm" (ebx), "=c" (ecx)
203
__asm__ __volatile__(
205
: "=a" (eax), "=c" (ecx)
207
: "memory", "%ebx", "%edx"
215
__GET_EDX_FROM_CPUID(int eax) // IN
218
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
221
__asm__ __volatile__(
222
"movl %%ebx, %1" "\n\t"
225
: "=a" (eax), "=&rm" (ebx), "=d" (edx)
231
__asm__ __volatile__(
233
: "=a" (eax), "=d" (edx)
235
: "memory", "%ebx", "%ecx"
244
__GET_EAX_FROM_CPUID4(int ecx) // IN
247
#if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
250
__asm__ __volatile__(
251
"movl %%ebx, %1" "\n\t"
254
: "=a" (eax), "=&rm" (ebx), "=c" (ecx)
260
__asm__ __volatile__(
262
: "=a" (eax), "=c" (ecx)
264
: "memory", "%ebx", "%edx"
271
#elif defined(_MSC_VER) // } {
274
__GET_CPUID(int input, CPUIDRegs *regs)
277
__cpuid((unsigned int *)regs, input);
286
__asm _emit 0x0f __asm _emit 0xa2
287
__asm mov 0x0[esi], eax
288
__asm mov 0x4[esi], ebx
289
__asm mov 0x8[esi], ecx
290
__asm mov 0xC[esi], edx
302
* No inline assembly in Win64. Implemented in bora/lib/user in
307
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs);
312
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
319
__asm mov eax, inputEax
320
__asm mov ecx, inputEcx
322
__asm _emit 0x0f __asm _emit 0xa2
323
__asm mov 0x0[esi], eax
324
__asm mov 0x4[esi], ebx
325
__asm mov 0x8[esi], ecx
326
__asm mov 0xC[esi], edx
336
__GET_EAX_FROM_CPUID(int input)
340
__cpuid((unsigned int *)®s, input);
351
__asm _emit 0x0f __asm _emit 0xa2
352
__asm mov output, eax
363
__GET_EBX_FROM_CPUID(int input)
367
__cpuid((unsigned int *)®s, input);
378
__asm _emit 0x0f __asm _emit 0xa2
379
__asm mov output, ebx
390
__GET_ECX_FROM_CPUID(int input)
394
__cpuid((unsigned int *)®s, input);
405
__asm _emit 0x0f __asm _emit 0xa2
406
__asm mov output, ecx
417
__GET_EDX_FROM_CPUID(int input)
421
__cpuid((unsigned int *)®s, input);
432
__asm _emit 0x0f __asm _emit 0xa2
433
__asm mov output, edx
446
* No inline assembly in Win64. Implemented in bora/lib/user in
451
__GET_EAX_FROM_CPUID4(int inputEcx);
456
__GET_EAX_FROM_CPUID4(int inputEcx)
466
__asm mov ecx, inputEcx
467
__asm _emit 0x0f __asm _emit 0xa2
468
__asm mov output, eax
483
#define CPUID_FOR_SIDE_EFFECTS() ((void)__GET_EAX_FROM_CPUID(0))
486
__GET_CPUID4(int inputEcx, CPUIDRegs *regs)
488
__GET_CPUID2(4, inputEcx, regs);
491
/* The first parameter is used as an rvalue and then as an lvalue. */
492
#define GET_CPUID(_ax, _bx, _cx, _dx) { \
494
__GET_CPUID(_ax, ®s); \