Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Succesfully launches and jumps into the exit handler. Need to write a proper exit...
[palacios.git] / palacios / include / palacios / vmx_lowlevel.h
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #ifndef __VMX_LOWLEVEL_H__
21 #define __VMX_LOWLEVEL_H__
22
23 #ifdef __V3VEE__
24
25
26 #define VMX_SUCCESS         0 
27 #define VMX_FAIL_INVALID    1
28 #define VMX_FAIL_VALID      2
29
30 // vmfail macro
31 #define CHECK_VMXFAIL(ret_valid, ret_invalid)   \
32     if (ret_valid) {                            \
33         return VMX_FAIL_VALID;                  \
34     } else if (ret_invalid) {                   \
35         return VMX_FAIL_INVALID;                \
36     }
37
38 /* Opcode definitions for all the VM instructions */
39
40 #define VMCLEAR_OPCODE  ".byte 0x66,0xf,0xc7;" /* reg=/6 */
41 #define VMRESUME_OPCODE ".byte 0x0f,0x01,0xc3;"
42 #define VMPTRLD_OPCODE  ".byte 0x0f,0xc7;" /* reg=/6 */
43 #define VMPTRST_OPCODE  ".byte 0x0f,0xc7;" /* reg=/7 */
44 #define VMREAD_OPCODE   ".byte 0x0f,0x78;"
45 #define VMWRITE_OPCODE  ".byte 0x0f,0x79;"
46 #define VMXOFF_OPCODE   ".byte 0x0f,0x01,0xc4;"
47 #define VMXON_OPCODE    ".byte 0xf3,0x0f,0xc7;" /* reg=/6 */
48
49
50 /* Mod/rm definitions for intel registers/memory */
51 #define EAX_ECX_MODRM   ".byte 0xc1;"
52 // %eax with /6 reg
53 #define EAX_06_MODRM    ".byte 0x30;"
54 // %eax with /7 reg
55 #define EAX_07_MODRM    ".byte 0x38;"
56
57
58
59 static inline int v3_enable_vmx(addr_t vmxon_ptr) {
60     uint64_t vmxon_ptr_64 __attribute__((aligned(8))) = (uint64_t)vmxon_ptr;
61     uint8_t ret_invalid = 0;
62
63     __asm__ __volatile__ (
64                 VMXON_OPCODE
65                 EAX_06_MODRM
66                 "setnaeb %0;" // fail invalid (CF=1)
67                 : "=q"(ret_invalid)
68                 : "a"(&vmxon_ptr_64),"0"(ret_invalid)
69                 : "memory");
70
71     if (ret_invalid) {
72         return VMX_FAIL_INVALID;
73     } else {
74         return VMX_SUCCESS;
75     }
76 }
77
78 static inline int vmcs_clear(addr_t vmcs_ptr) {
79     uint64_t vmcs_ptr_64 __attribute__ ((aligned(8))) = (uint64_t)vmcs_ptr;
80     uint8_t ret_valid = 0;
81     uint8_t ret_invalid = 0;
82
83     __asm__ __volatile__ (
84             VMCLEAR_OPCODE
85             EAX_06_MODRM
86             "seteb %0;" // fail valid (ZF=1)
87             "setnaeb %1;" // fail invalid (CF=1)
88             : "=q"(ret_valid), "=q"(ret_invalid)
89             : "a"(&vmcs_ptr_64), "0"(ret_valid), "1"(ret_invalid)
90             : "memory");
91
92     CHECK_VMXFAIL(ret_valid, ret_invalid);
93   
94     return VMX_SUCCESS;
95 }
96
97 static inline int vmcs_load(addr_t vmcs_ptr) {
98     uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr;
99     uint8_t ret_valid = 0;
100     uint8_t ret_invalid = 0;
101     
102     __asm__ __volatile__ (
103                 VMPTRLD_OPCODE
104                 EAX_06_MODRM
105                 "seteb %0;" // fail valid (ZF=1)
106                 "setnaeb %1;"  // fail invalid (CF=1)
107                 : "=q"(ret_valid), "=q"(ret_invalid)
108                 : "a"(&vmcs_ptr_64), "0"(ret_valid), "1"(ret_invalid)
109                 : "memory");
110     
111     CHECK_VMXFAIL(ret_valid, ret_invalid);
112
113     return VMX_SUCCESS;
114 }
115
116 static inline int vmcs_store(addr_t vmcs_ptr) {
117     uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr;
118
119     __asm__ __volatile__ (
120                VMPTRST_OPCODE
121                EAX_07_MODRM
122                :
123                : "a"(&vmcs_ptr_64)
124                : "memory");
125
126     return VMX_SUCCESS;
127 }
128
129 static inline int vmcs_read(vmcs_field_t vmcs_field, void * dst, int len) {
130     uint64_t val = 0;
131     uint8_t ret_valid = 0;
132     uint8_t ret_invalid = 0;
133
134     __asm__ __volatile__ (  
135                 VMREAD_OPCODE
136                 EAX_ECX_MODRM
137                 "seteb %0;" // fail valid
138                 "setnaeb %1;" // fail invalid
139                 : "=q"(ret_valid), "=q"(ret_invalid), "=c"(val) // Use ECX
140                 : "a" (vmcs_field), "0"(ret_valid), "1"(ret_invalid)
141                 : "memory"
142                 );
143
144     CHECK_VMXFAIL(ret_valid, ret_invalid);
145
146     switch(len)
147     {
148         case 2:
149             *((uint16_t*)dst) = (uint16_t)val;
150             break;
151         case 4:
152             *((uint32_t*)dst) = (uint32_t)val;
153             break;
154         case 8:
155             *((uint64_t*)dst) = (uint64_t)val;
156             break;
157     }
158
159
160     return VMX_SUCCESS;
161 }
162
163 static inline int vmcs_write(vmcs_field_t vmcs_field, addr_t value) {
164     uint8_t ret_valid = 0;
165     uint8_t ret_invalid = 0;
166
167     __asm__ __volatile__ (
168                 VMWRITE_OPCODE
169                 EAX_ECX_MODRM
170                 "seteb %0;" // fail valid (ZF=1)
171                 "setnaeb %1;" // fail invalid (CF=1)
172                 : "=q" (ret_valid), "=q" (ret_invalid)
173                 : "a" (vmcs_field), "c"(value), "0"(ret_valid), "1"(ret_invalid)
174                 : "memory");
175
176     CHECK_VMXFAIL(ret_valid, ret_invalid);
177
178     return VMX_SUCCESS;
179 }
180
181 static inline int vmx_off() {
182     uint8_t ret_valid = 0;
183     uint8_t ret_invalid = 0;
184
185     __asm__ __volatile__ (
186                 VMXOFF_OPCODE
187                 "seteb %0;"
188                 "setnaeb %1;"
189                 : "=q"(ret_valid), "=q"(ret_invalid)
190                 : "0"(ret_valid), "1"(ret_invalid)
191                 : "memory");
192
193     CHECK_VMXFAIL(ret_valid, ret_invalid);
194
195     return VMX_SUCCESS;
196 }
197
198 #endif
199
200 #endif