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.


Rewrote /include/vmx_lowlevel.h to include all the possible asm VMX instructions...
[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,0x67;" /* 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(uint64_t host_state) {
60     uint8_t ret_invalid = 0;
61
62     __asm__ __volatile__ (
63                 VMXON_OPCODE
64                 EAX_06_MODRM
65                 "setnaeb %0;" // fail invalid (CF=1)
66                 : "=q"(ret_invalid)
67                 : "a"(&host_state),"0"(ret_invalid)
68                 : "memory");
69
70     if (ret_invalid) {
71         return VMX_FAIL_INVALID;
72     } else {
73         return VMX_SUCCESS;
74     }
75 }
76
77 // No vmcall necessary - is only executed by the guest
78
79 static inline int vmcs_clear(uint64_t addr) {
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"(&addr), "0"(ret_valid), "1"(ret_invalid)
90             : "memory");
91
92     CHECK_VMXFAIL(ret_valid, ret_invalid);
93   
94     return VMX_SUCCESS;
95 }
96
97
98 static inline int vmcs_resume() {
99     uint8_t ret_valid = 0;
100     uint8_t ret_invalid = 0;
101
102     __asm__ __volatile__ (
103                 VMRESUME_OPCODE
104                 "seteb %0;"
105                 "setnaeb %1;"
106                 : "=q"(ret_valid), "=q"(ret_invalid)
107                 : "0"(ret_valid), "1"(ret_invalid)
108                 : "memory");
109
110     CHECK_VMXFAIL(ret_valid, ret_invalid);
111
112     return VMX_SUCCESS;
113 }
114
115
116 static inline int vmcs_load(vmcs_t * vmcs_ptr) {
117     uint64_t addr = (uint64_t)vmcs_ptr;
118     uint8_t ret_valid = 0;
119     uint8_t ret_invalid = 0;
120     
121     __asm__ __volatile__ (
122                 VMPTRLD_OPCODE
123                 EAX_06_MODRM
124                 "seteb %0;" // fail valid (ZF=1)
125                 "setnaeb %1;"  // fail invalid (CF=1)
126                 : "=q"(ret_valid), "=q"(ret_invalid)
127                 : "a"(&addr), "0"(ret_valid), "1"(ret_invalid)
128                 : "memory");
129     
130     CHECK_VMXFAIL(ret_valid, ret_invalid);
131
132     return VMX_SUCCESS;
133 }
134
135 static inline int vmcs_store(vmcs_t * vmcs_ptr) {
136     uint64_t addr = (uint64_t)vmcs_ptr;
137
138     __asm__ __volatile__ (
139                VMPTRSRT_OPCODE
140                EAX_07_MODRM
141                :
142                : "a"(&addr)
143                : "memory");
144
145     return VMX_SUCCESS;
146 }
147
148 /* According to Intel, vmread will return an architecure sized type - be sure that
149  * dst is at least 64-bits in IA-32e and 32 otherwise */
150 static inline int vmcs_read(addr_t vmcs_index, void * dst) {
151     addr_t val = 0;
152     uint8_t ret_valid = 0;
153     uint8_t ret_invalid = 0;
154
155     __asm__ __volatile__ (  
156                 VMREAD_OPCODE
157                 EAX_ECX_MODRM
158                 "seteb %0;" // fail valid
159                 "setnaeb %1;" // fail invalid
160                 : "=q"(ret_valid), "=q"(ret_invalid), "=c"(val) // Use ECX
161                 : "a" (vmcs_index), "0"(ret_valid), "1"(ret_invalid)
162                 : "memory"
163                 );
164
165     CHECK_VMXFAIL(ret_valid, ret_invalid);
166
167     // TODO: Fix this, will have to do a cast because dst will be variable length
168     *dst = val;
169
170     return VMX_SUCCESS;
171 }
172
173 static inline int vmcs_write(addr_t vmcs_index, addr_t value) {
174     uint8_t ret_valid = 0;
175     uint8_t ret_invalid = 0;
176
177     __asm__ __volatile__ (
178                 VMWRITE_OPCODE
179                 EAX_ECX_MODRM
180                 "seteb %0;" // fail valid (ZF=1)
181                 "setnaeb %1;" // fail invalid (CF=1)
182                 : "=q" (ret_valid), "=q" (ret_invalid)
183                 : "a" (vmcs_index), "c"(value), "0"(ret_valid), "1"(ret_invalid)
184                 : "memory");
185
186     CHECK_VMXFAIL(ret_valid, ret_invalid);
187
188     return VMX_SUCCESS;
189 }
190
191 static inline int vmx_off() {
192     uint8_t ret_valid = 0;
193     uint8_t ret_invalid = 0;
194
195     __asm__ __volatile__ (
196                 VMXOFF_OPCODE
197                 "seteb %0;"
198                 "setnaeb %1;"
199                 : "=q"(ret_valid), "=q"(ret_invalid)
200                 : "0"(ret_valid), "1"(ret_invalid)
201                 : "memory");
202
203     CHECK_VMXFAIL(ret_valid, ret_invalid);
204
205     return VMX_SUCCESS;
206 }
207
208 #endif
209
210 #endif