2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #ifndef __VMX_LOWLEVEL_H__
21 #define __VMX_LOWLEVEL_H__
25 #include <palacios/vmcs.h>
28 #define VMX_FAIL_INVALID 1
29 #define VMX_FAIL_VALID 2
32 #define CHECK_VMXFAIL(ret_valid, ret_invalid) \
34 return VMX_FAIL_VALID; \
35 } else if (ret_invalid) { \
36 return VMX_FAIL_INVALID; \
39 /* Opcode definitions for all the VM instructions */
41 #define VMCLEAR_OPCODE ".byte 0x66,0xf,0xc7;" /* reg=/6 */
42 #define VMRESUME_OPCODE ".byte 0x0f,0x01,0xc3;"
43 #define VMPTRLD_OPCODE ".byte 0x0f,0xc7;" /* reg=/6 */
44 #define VMPTRST_OPCODE ".byte 0x0f,0xc7;" /* reg=/7 */
45 #define VMREAD_OPCODE ".byte 0x0f,0x78;"
46 #define VMWRITE_OPCODE ".byte 0x0f,0x79;"
47 #define VMXOFF_OPCODE ".byte 0x0f,0x01,0xc4;"
48 #define VMXON_OPCODE ".byte 0xf3,0x0f,0xc7;" /* reg=/6 */
51 /* Mod/rm definitions for intel registers/memory */
52 #define EAX_ECX_MODRM ".byte 0xc1;"
54 #define EAX_06_MODRM ".byte 0x30;"
56 #define EAX_07_MODRM ".byte 0x38;"
62 static inline int vmcs_clear(addr_t vmcs_ptr) {
63 uint64_t vmcs_ptr_64 __attribute__ ((aligned(8))) = (uint64_t)vmcs_ptr;
64 uint8_t ret_valid = 0;
65 uint8_t ret_invalid = 0;
67 __asm__ __volatile__ (
70 "seteb %0;" // fail valid (ZF=1)
71 "setnaeb %1;" // fail invalid (CF=1)
72 : "=q"(ret_valid), "=q"(ret_invalid)
73 : "a"(&vmcs_ptr_64), "0"(ret_valid), "1"(ret_invalid)
76 CHECK_VMXFAIL(ret_valid, ret_invalid);
81 static inline int vmcs_load(addr_t vmcs_ptr) {
82 uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr;
83 uint8_t ret_valid = 0;
84 uint8_t ret_invalid = 0;
86 __asm__ __volatile__ (
89 "seteb %0;" // fail valid (ZF=1)
90 "setnaeb %1;" // fail invalid (CF=1)
91 : "=q"(ret_valid), "=q"(ret_invalid)
92 : "a"(&vmcs_ptr_64), "0"(ret_valid), "1"(ret_invalid)
95 CHECK_VMXFAIL(ret_valid, ret_invalid);
100 static inline uint64_t vmcs_store() {
101 uint64_t vmcs_ptr = 0;
103 __asm__ __volatile__ (
113 static inline int vmcs_read(vmcs_field_t vmcs_field, void * dst) {
115 uint8_t ret_valid = 0;
116 uint8_t ret_invalid = 0;
118 __asm__ __volatile__ (
121 "seteb %1;" // fail valid
122 "setnaeb %1;" // fail invalid
123 : "=c"(val), "=d"(ret_valid) //, "=r"(ret_invalid) // Use ECX
124 : "a" (vmcs_field), "0"(0), "1"(ret_valid)
128 CHECK_VMXFAIL(ret_valid, ret_invalid);
130 switch(v3_vmcs_get_field_len(vmcs_field))
133 *((uint16_t*)dst) = (uint16_t)val;
136 *((uint32_t*)dst) = (uint32_t)val;
139 *((uint64_t*)dst) = (uint64_t)val;
149 static inline int vmcs_write(vmcs_field_t vmcs_field, addr_t value) {
150 uint8_t ret_valid = 0;
151 uint8_t ret_invalid = 0;
153 __asm__ __volatile__ (
156 "seteb %0;" // fail valid (ZF=1)
157 "setnaeb %1;" // fail invalid (CF=1)
158 : "=q" (ret_valid), "=q" (ret_invalid)
159 : "a" (vmcs_field), "c"(value)
162 CHECK_VMXFAIL(ret_valid, ret_invalid);
168 static inline int vmx_on(addr_t vmxon_ptr) {
169 uint64_t vmxon_ptr_64 __attribute__((aligned(8))) = (uint64_t)vmxon_ptr;
170 uint8_t ret_invalid = 0;
172 __asm__ __volatile__ (
175 "setnaeb %0;" // fail invalid (CF=1)
177 : "a"(&vmxon_ptr_64),"0"(ret_invalid)
181 return VMX_FAIL_INVALID;
187 static inline int vmx_off() {
188 uint8_t ret_valid = 0;
189 uint8_t ret_invalid = 0;
191 __asm__ __volatile__ (
195 : "=q"(ret_valid), "=q"(ret_invalid)
196 : "0"(ret_valid), "1"(ret_invalid)
199 CHECK_VMXFAIL(ret_valid, ret_invalid);
205 static inline int enable_vmx() {
207 __asm__ __volatile__ (
209 "orq $0x00002000, %%rbx;"
217 __asm__ __volatile__ (
218 "movq %%cr0, %%rbx; "
219 "orq $0x00000020,%%rbx; "
226 __asm__ __volatile__ (
228 "orl $0x00002000, %%ecx;"
237 __asm__ __volatile__ (
238 "movl %%cr0, %%ecx; "
239 "orl $0x00000020,%%ecx; "