b3057172dfab48824897d2ca9fb946b54d246dee
[akaros.git] / kern / arch / x86 / vmm / intel / vmx.h
1 #pragma once
2
3 /*
4  * vmx.h: VMX Architecture related definitions
5  * Copyright (c) 2004, Intel Corporation.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18  * Place - Suite 330, Boston, MA 02111-1307 USA.
19  *
20  * A few random additions are:
21  * Copyright (C) 2006 Qumranet
22  *    Avi Kivity <avi@qumranet.com>
23  *    Yaniv Kamay <yaniv@qumranet.com>
24  *
25  */
26
27 #include <ros/arch/vmx.h>
28
29 int vmx_init(void);
30 void vmx_exit(void);
31 int intel_vmm_init(void);
32 int intel_vmm_pcpu_init(void);
33 int ept_fault_pages(void *dir, uint32_t start, uint32_t end);
34 int ept_check_page(void *dir, unsigned long addr);
35 int vmx_do_ept_fault(void *dir, unsigned long gpa, unsigned long gva, int fault_flags);
36
37 static inline void native_store_idt(pseudodesc_t *dtr);
38 static inline unsigned long get_desc_base(const struct desc_struct *desc);
39 static inline void native_store_gdt(pseudodesc_t *dtr);
40 static inline bool cpu_has_secondary_exec_ctrls(void);
41 static inline bool cpu_has_vmx_vpid(void);
42 static inline bool cpu_has_vmx_invpcid(void);
43 static inline bool cpu_has_vmx_invvpid_single(void);
44 static inline bool cpu_has_vmx_invvpid_global(void);
45 static inline bool cpu_has_vmx_ept(void);
46 static inline bool cpu_has_vmx_invept(void);
47 static inline bool cpu_has_vmx_invept_individual_addr(void);
48 static inline bool cpu_has_vmx_invept_context(void);
49 static inline bool cpu_has_vmx_invept_global(void);
50 static inline bool cpu_has_vmx_ept_ad_bits(void);
51 static inline bool cpu_has_vmx_ept_execute_only(void);
52 static inline bool cpu_has_vmx_eptp_uncacheable(void);
53 static inline bool cpu_has_vmx_eptp_writeback(void);
54 static inline bool cpu_has_vmx_ept_2m_page(void);
55 static inline bool cpu_has_vmx_ept_1g_page(void);
56 static inline bool cpu_has_vmx_ept_4levels(void);
57 static inline void __invept(int ext, uint64_t eptp, gpa_t gpa);
58 static inline void ept_sync_global(void);
59 static inline void ept_sync_context(uint64_t eptp);
60 static inline void ept_sync_individual_addr(uint64_t eptp, gpa_t gpa);
61 static inline void __vmxon(uint64_t addr);
62 static inline void __vmxoff(void);
63 static inline void __invvpid(int ext, uint16_t vpid, gva_t gva);
64 static inline void vpid_sync_gpc_single(uint16_t vpid);
65 static inline void vpid_sync_gpc_global(void);
66 static inline void vpid_sync_context(uint16_t vpid);
67 static inline uint64_t gpc_get_eptp(struct guest_pcore *gpc);
68
69 /* no way to get around some of this stuff. */
70 /* we will do the bare minimum required. */
71 static inline void native_store_idt(pseudodesc_t *dtr)
72 {
73         asm volatile("sidt %0":"=m" (*dtr));
74 }
75
76 static inline unsigned long get_desc_base(const struct desc_struct *desc)
77 {
78         return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
79 }
80
81 #define store_gdt(dtr)                          native_store_gdt(dtr)
82 static inline void native_store_gdt(pseudodesc_t *dtr)
83 {
84         asm volatile("sgdt %0":"=m" (*dtr));
85 }
86
87 static inline bool cpu_has_secondary_exec_ctrls(void)
88 {
89         return vmcs_config.cpu_based_exec_ctrl &
90                 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
91 }
92
93 static inline bool cpu_has_vmx_vpid(void)
94 {
95         return vmcs_config.cpu_based_2nd_exec_ctrl &
96                 SECONDARY_EXEC_ENABLE_VPID;
97 }
98
99 static inline bool cpu_has_vmx_invpcid(void)
100 {
101         return vmcs_config.cpu_based_2nd_exec_ctrl &
102                 SECONDARY_EXEC_ENABLE_INVPCID;
103 }
104
105 static inline bool cpu_has_vmx_invvpid_single(void)
106 {
107         return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
108 }
109
110 static inline bool cpu_has_vmx_invvpid_global(void)
111 {
112         return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
113 }
114
115 static inline bool cpu_has_vmx_ept(void)
116 {
117         return vmcs_config.cpu_based_2nd_exec_ctrl &
118                 SECONDARY_EXEC_ENABLE_EPT;
119 }
120
121 static inline bool cpu_has_vmx_invept(void)
122 {
123         return vmx_capability.ept & VMX_EPT_INVEPT_BIT;
124 }
125
126 /* the SDM (2015-01) doesn't mention this ability (still?) */
127 static inline bool cpu_has_vmx_invept_individual_addr(void)
128 {
129         return vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT;
130 }
131
132 static inline bool cpu_has_vmx_invept_context(void)
133 {
134         return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
135 }
136
137 static inline bool cpu_has_vmx_invept_global(void)
138 {
139         return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
140 }
141
142 static inline bool cpu_has_vmx_ept_ad_bits(void)
143 {
144         return vmx_capability.ept & VMX_EPT_AD_BIT;
145 }
146
147 static inline bool cpu_has_vmx_ept_execute_only(void)
148 {
149         return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT;
150 }
151
152 static inline bool cpu_has_vmx_eptp_uncacheable(void)
153 {
154         return vmx_capability.ept & VMX_EPTP_UC_BIT;
155 }
156
157 static inline bool cpu_has_vmx_eptp_writeback(void)
158 {
159         return vmx_capability.ept & VMX_EPTP_WB_BIT;
160 }
161
162 static inline bool cpu_has_vmx_ept_2m_page(void)
163 {
164         return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
165 }
166
167 static inline bool cpu_has_vmx_ept_1g_page(void)
168 {
169         return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
170 }
171
172 static inline bool cpu_has_vmx_ept_4levels(void)
173 {
174         return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
175 }
176
177 static inline void __invept(int ext, uint64_t eptp, gpa_t gpa)
178 {
179         struct {
180                 uint64_t eptp, gpa;
181         } operand = {eptp, gpa};
182
183         asm volatile (ASM_VMX_INVEPT
184                         /* CF==1 or ZF==1 --> rc = -1 */
185                         "; ja 1f ; ud2 ; 1:\n"
186                         : : "a" (&operand), "c" (ext) : "cc", "memory");
187 }
188
189 /* We assert support for the global flush during ept_init() */
190 static inline void ept_sync_global(void)
191 {
192         __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
193 }
194
195 static inline void ept_sync_context(uint64_t eptp)
196 {
197         if (cpu_has_vmx_invept_context())
198                 __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
199         else
200                 ept_sync_global();
201 }
202
203 static inline void ept_sync_individual_addr(uint64_t eptp, gpa_t gpa)
204 {
205         if (cpu_has_vmx_invept_individual_addr())
206                 __invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
207                                 eptp, gpa);
208         else
209                 ept_sync_context(eptp);
210 }
211
212 static inline void __vmxon(uint64_t addr)
213 {
214         asm volatile (ASM_VMX_VMXON_RAX
215                         : : "a"(&addr), "m"(addr)
216                         : "memory", "cc");
217 }
218
219 static inline void __vmxoff(void)
220 {
221         asm volatile (ASM_VMX_VMXOFF : : : "cc");
222 }
223
224 static inline void __invvpid(int ext, uint16_t vpid, gva_t gva)
225 {
226     struct {
227         uint64_t vpid : 16;
228         uint64_t rsvd : 48;
229         uint64_t gva;
230     } operand = { vpid, 0, gva };
231
232     asm volatile (ASM_VMX_INVVPID
233                   /* CF==1 or ZF==1 --> rc = -1 */
234                   "; ja 1f ; ud2 ; 1:"
235                   : : "a"(&operand), "c"(ext) : "cc", "memory");
236 }
237
238 static inline void vpid_sync_gpc_single(uint16_t vpid)
239 {
240         if (vpid == 0) {
241                 return;
242         }
243
244         if (cpu_has_vmx_invvpid_single())
245                 __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid, 0);
246 }
247
248 static inline void vpid_sync_gpc_global(void)
249 {
250         if (cpu_has_vmx_invvpid_global())
251                 __invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
252 }
253
254 static inline void vpid_sync_context(uint16_t vpid)
255 {
256         if (cpu_has_vmx_invvpid_single())
257                 vpid_sync_gpc_single(vpid);
258         else
259                 vpid_sync_gpc_global();
260 }
261
262 static inline uint64_t gpc_get_eptp(struct guest_pcore *gpc)
263 {
264         return gpc->proc->env_pgdir.eptp;
265 }
266
267 static inline unsigned long vmcs_read(unsigned long field)
268 {
269         unsigned long value;
270
271         asm volatile (ASM_VMX_VMREAD_RDX_RAX : "=a"(value) : "d"(field) : "cc");
272         return value;
273 }
274
275 /* Returns true if the op succeeded.  It can fail if the field is unsupported */
276 static inline bool vmcs_write(unsigned long field, unsigned long value)
277 {
278         uint8_t error;
279
280         asm volatile (ASM_VMX_VMWRITE_RAX_RDX "; setna %0"
281                       : "=q"(error) : "a"(value), "d"(field) : "cc");
282         return error ? FALSE : TRUE;
283 }
284
285 /*
286  * VMX Execution Controls (vmxec)
287  * Some bits can be set, others can not (i.e. they are reserved).
288  *
289  * o all bits listed in here must set or clear all the bits in a word
290  *   that are not reserved (coverage).
291  * o no bits listed in one of these elements is listed in
292  *   another element (conflict)
293  * o you are allowed to specify a bit that matches a reserved value
294  *   (because it might be settable at some future time).
295  * o do your best to find symbolic names for the set_to_1 and set_to_0 values.
296  *   In the one case we could not find a name, it turned out to be an
297  *   error in kvm constants that went back to the earliest days.
298  * We're hoping you almost never have to change this. It's painful.
299  * The assumption going in is that the 5 MSRs that define the vmxec
300  * values are relatively static. This has been the case for a while.
301  */
302 struct vmxec {
303         char *name;
304         uint32_t msr;
305         uint32_t truemsr;
306         uint32_t must_be_1;
307         uint32_t must_be_0;
308         uint32_t try_set_1;
309         uint32_t try_set_0;
310 };
311
312 void vmx_load_guest_pcore(struct guest_pcore *gpc);
313 void vmx_unload_guest_pcore(struct guest_pcore *gpc);