tests/linux: use Akaros's CFLAGS
[akaros.git] / kern / arch / x86 / vmm / intel / vmx.h
1 /*
2  * vmx.h: VMX Architecture related definitions
3  * Copyright (c) 2004, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16  * Place - Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * A few random additions are:
19  * Copyright (C) 2006 Qumranet
20  *    Avi Kivity <avi@qumranet.com>
21  *    Yaniv Kamay <yaniv@qumranet.com>
22  *
23  */
24
25 #pragma once
26
27 #include <ros/arch/vmx.h>
28
29 /* Additional bits for VMMCPs, originally from the Dune version of kvm. */
30 /*
31  * vmx.h - header file for USM VMX driver.
32  */
33
34 /* This is per-guest per-core, and the implementation specific area
35  * should be assumed to have hidden fields.
36  */
37 struct vmcs {
38         uint32_t revision_id;
39         uint32_t abort_code;
40         char _impl_specific[PGSIZE - sizeof(uint32_t) * 2];
41 };
42
43 typedef uint64_t gpa_t;
44 typedef uint64_t gva_t;
45
46 struct vmx_capability {
47         uint32_t ept;
48         uint32_t vpid;
49 };
50
51 struct vmcs_config {
52         int size;
53         uint32_t revision_id;
54         uint32_t pin_based_exec_ctrl;
55         uint32_t cpu_based_exec_ctrl;
56         uint32_t cpu_based_2nd_exec_ctrl;
57         uint32_t vmexit_ctrl;
58         uint32_t vmentry_ctrl;
59 };
60
61 struct guest_pcore {
62         int cpu;
63         struct proc *proc;
64         unsigned long *posted_irq_desc;
65         struct vmcs *vmcs;
66         int vmcs_core_id;
67         bool should_vmresume;
68         uint64_t xcr0;
69         uint64_t msr_kern_gs_base;
70         uint64_t msr_star;
71         uint64_t msr_lstar;
72         uint64_t msr_sfmask;
73 };
74
75 #define NR_AUTOLOAD_MSRS 8
76
77 /* the horror. */
78 struct desc_struct {
79         union {
80                 struct {
81                         unsigned int a;
82                         unsigned int b;
83                 };
84                 struct {
85                         uint16_t limit0;
86                         uint16_t base0;
87                         unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
88                         unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
89                 };
90         };
91 } __attribute__((packed));
92
93 /* LDT or TSS descriptor in the GDT. 16 bytes. */
94 struct ldttss_desc64 {
95         uint16_t limit0;
96         uint16_t base0;
97         unsigned base1 : 8, type : 5, dpl : 2, p : 1;
98         unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
99         uint32_t base3;
100         uint32_t zero1;
101 } __attribute__((packed));
102
103 #define INTEL_MSR_WRITE_OFFSET                  2048
104
105 #define INTEL_X2APIC_MSR_START                  0x100
106 #define INTEL_X2APIC_MSR_LENGTH                 (0x40/8)
107
108 #define MSR_IA32_VMX_BASIC_MSR                  0x480
109 #define MSR_IA32_VMX_PINBASED_CTLS_MSR  0x481
110 #define MSR_IA32_VMX_PROCBASED_CTLS_MSR 0x482
111 #define MSR_IA32_VMX_EXIT_CTLS_MSR              0x483
112 #define MSR_IA32_VMX_ENTRY_CTLS_MSR             0x484
113
114 extern char * const VMX_EXIT_REASON_NAMES[];
115
116 static inline void native_store_idt(pseudodesc_t *dtr);
117 static inline unsigned long get_desc_base(const struct desc_struct *desc);
118 static inline void native_store_gdt(pseudodesc_t *dtr);
119 static inline bool cpu_has_secondary_exec_ctrls(void);
120 static inline bool cpu_has_vmx_vpid(void);
121 static inline bool cpu_has_vmx_invpcid(void);
122 static inline bool cpu_has_vmx_invvpid_single(void);
123 static inline bool cpu_has_vmx_invvpid_global(void);
124 static inline bool cpu_has_vmx_ept(void);
125 static inline bool cpu_has_vmx_invept(void);
126 static inline bool cpu_has_vmx_invept_individual_addr(void);
127 static inline bool cpu_has_vmx_invept_context(void);
128 static inline bool cpu_has_vmx_invept_global(void);
129 static inline bool cpu_has_vmx_ept_ad_bits(void);
130 static inline bool cpu_has_vmx_ept_execute_only(void);
131 static inline bool cpu_has_vmx_eptp_uncacheable(void);
132 static inline bool cpu_has_vmx_eptp_writeback(void);
133 static inline bool cpu_has_vmx_ept_2m_page(void);
134 static inline bool cpu_has_vmx_ept_1g_page(void);
135 static inline bool cpu_has_vmx_ept_4levels(void);
136 static inline void __invept(int ext, uint64_t eptp, gpa_t gpa);
137 static inline void ept_sync_global(void);
138 static inline void ept_sync_context(uint64_t eptp);
139 static inline void ept_sync_individual_addr(uint64_t eptp, gpa_t gpa);
140 static inline void __vmxon(uint64_t addr);
141 static inline void __vmxoff(void);
142 static inline void __invvpid(int ext, uint16_t vpid, gva_t gva);
143 static inline void vpid_sync_gpc_single(uint16_t vpid);
144 static inline void vpid_sync_gpc_global(void);
145 static inline void vpid_sync_context(uint16_t vpid);
146
147 /* no way to get around some of this stuff. */
148 /* we will do the bare minimum required. */
149 static inline void native_store_idt(pseudodesc_t *dtr)
150 {
151         asm volatile("sidt %0":"=m" (*dtr));
152 }
153
154 static inline unsigned long get_desc_base(const struct desc_struct *desc)
155 {
156         return (unsigned)(desc->base0 | ((desc->base1) << 16) |
157                           ((desc->base2) << 24));
158 }
159
160 #define store_gdt(dtr) native_store_gdt(dtr)
161 static inline void native_store_gdt(pseudodesc_t *dtr)
162 {
163         asm volatile("sgdt %0":"=m" (*dtr));
164 }
165
166 /* TODO: somewhat nasty - two structs, only used by the helpers.  Maybe use cpu
167  * features. */
168 extern struct vmcs_config vmcs_config;
169 extern struct vmx_capability vmx_capability;
170
171 static inline bool cpu_has_secondary_exec_ctrls(void)
172 {
173         return vmcs_config.cpu_based_exec_ctrl &
174                 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
175 }
176
177 static inline bool cpu_has_vmx_vpid(void)
178 {
179         return vmcs_config.cpu_based_2nd_exec_ctrl &
180                 SECONDARY_EXEC_ENABLE_VPID;
181 }
182
183 static inline bool cpu_has_vmx_invpcid(void)
184 {
185         return vmcs_config.cpu_based_2nd_exec_ctrl &
186                 SECONDARY_EXEC_ENABLE_INVPCID;
187 }
188
189 static inline bool cpu_has_vmx_invvpid_single(void)
190 {
191         return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
192 }
193
194 static inline bool cpu_has_vmx_invvpid_global(void)
195 {
196         return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
197 }
198
199 static inline bool cpu_has_vmx_ept(void)
200 {
201         return vmcs_config.cpu_based_2nd_exec_ctrl &
202                 SECONDARY_EXEC_ENABLE_EPT;
203 }
204
205 static inline bool cpu_has_vmx_invept(void)
206 {
207         return vmx_capability.ept & VMX_EPT_INVEPT_BIT;
208 }
209
210 /* the SDM (2015-01) doesn't mention this ability (still?) */
211 static inline bool cpu_has_vmx_invept_individual_addr(void)
212 {
213         return vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT;
214 }
215
216 static inline bool cpu_has_vmx_invept_context(void)
217 {
218         return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
219 }
220
221 static inline bool cpu_has_vmx_invept_global(void)
222 {
223         return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
224 }
225
226 static inline bool cpu_has_vmx_ept_ad_bits(void)
227 {
228         return vmx_capability.ept & VMX_EPT_AD_BIT;
229 }
230
231 static inline bool cpu_has_vmx_ept_execute_only(void)
232 {
233         return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT;
234 }
235
236 static inline bool cpu_has_vmx_eptp_uncacheable(void)
237 {
238         return vmx_capability.ept & VMX_EPTP_UC_BIT;
239 }
240
241 static inline bool cpu_has_vmx_eptp_writeback(void)
242 {
243         return vmx_capability.ept & VMX_EPTP_WB_BIT;
244 }
245
246 static inline bool cpu_has_vmx_ept_2m_page(void)
247 {
248         return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
249 }
250
251 static inline bool cpu_has_vmx_ept_1g_page(void)
252 {
253         return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
254 }
255
256 static inline bool cpu_has_vmx_ept_4levels(void)
257 {
258         return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
259 }
260
261 static inline void __invept(int ext, uint64_t eptp, gpa_t gpa)
262 {
263         struct {
264                 uint64_t eptp, gpa;
265         } operand = {eptp, gpa};
266
267         asm volatile (ASM_VMX_INVEPT
268                         /* CF==1 or ZF==1 --> rc = -1 */
269                         "; ja 1f ; ud2 ; 1:\n"
270                         : : "a" (&operand), "c" (ext) : "cc", "memory");
271 }
272
273 /* We assert support for the global flush during ept_init() */
274 static inline void ept_sync_global(void)
275 {
276         __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
277 }
278
279 static inline void ept_sync_context(uint64_t eptp)
280 {
281         if (cpu_has_vmx_invept_context())
282                 __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
283         else
284                 ept_sync_global();
285 }
286
287 static inline void ept_sync_individual_addr(uint64_t eptp, gpa_t gpa)
288 {
289         if (cpu_has_vmx_invept_individual_addr())
290                 __invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
291                                 eptp, gpa);
292         else
293                 ept_sync_context(eptp);
294 }
295
296 static inline void __vmxon(uint64_t addr)
297 {
298         asm volatile (ASM_VMX_VMXON_RAX
299                         : : "a"(&addr), "m"(addr)
300                         : "memory", "cc");
301 }
302
303 static inline void __vmxoff(void)
304 {
305         asm volatile (ASM_VMX_VMXOFF : : : "cc");
306 }
307
308 static inline void __invvpid(int ext, uint16_t vpid, gva_t gva)
309 {
310     struct {
311         uint64_t vpid : 16;
312         uint64_t rsvd : 48;
313         uint64_t gva;
314     } operand = { vpid, 0, gva };
315
316     asm volatile (ASM_VMX_INVVPID
317                   /* CF==1 or ZF==1 --> rc = -1 */
318                   "; ja 1f ; ud2 ; 1:"
319                   : : "a"(&operand), "c"(ext) : "cc", "memory");
320 }
321
322 static inline void vpid_sync_gpc_single(uint16_t vpid)
323 {
324         if (vpid == 0) {
325                 return;
326         }
327
328         if (cpu_has_vmx_invvpid_single())
329                 __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid, 0);
330 }
331
332 static inline void vpid_sync_gpc_global(void)
333 {
334         if (cpu_has_vmx_invvpid_global())
335                 __invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
336 }
337
338 static inline void vpid_sync_context(uint16_t vpid)
339 {
340         if (cpu_has_vmx_invvpid_single())
341                 vpid_sync_gpc_single(vpid);
342         else
343                 vpid_sync_gpc_global();
344 }
345
346 static inline unsigned long vmcs_read(unsigned long field)
347 {
348         unsigned long value;
349
350         asm volatile (ASM_VMX_VMREAD_RDX_RAX : "=a"(value) : "d"(field) : "cc");
351         return value;
352 }
353
354 /* Returns true if the op succeeded.  It can fail if the field is unsupported */
355 static inline bool vmcs_write(unsigned long field, unsigned long value)
356 {
357         uint8_t error;
358
359         asm volatile (ASM_VMX_VMWRITE_RAX_RDX "; setna %0"
360                       : "=q"(error) : "a"(value), "d"(field) : "cc");
361         return error ? FALSE : TRUE;
362 }
363
364 /*
365  * VMX Execution Controls (vmxec)
366  * Some bits can be set, others can not (i.e. they are reserved).
367  *
368  * o all bits listed in here must set or clear all the bits in a word
369  *   that are not reserved (coverage).
370  * o no bits listed in one of these elements is listed in
371  *   another element (conflict)
372  * o you are allowed to specify a bit that matches a reserved value
373  *   (because it might be settable at some future time).
374  * o do your best to find symbolic names for the set_to_1 and set_to_0 values.
375  *   In the one case we could not find a name, it turned out to be an
376  *   error in kvm constants that went back to the earliest days.
377  * We're hoping you almost never have to change this. It's painful.
378  * The assumption going in is that the 5 MSRs that define the vmxec
379  * values are relatively static. This has been the case for a while.
380  */
381 struct vmxec {
382         char *name;
383         uint32_t msr;
384         uint32_t truemsr;
385         uint32_t must_be_1;
386         uint32_t must_be_0;
387         uint32_t try_set_1;
388         uint32_t try_set_0;
389         uint32_t hw_changeable;
390         uint32_t policy_changeable;
391 };
392
393 /* Per-VM VMX info */
394 struct vmx_vmm {
395         uint32_t                        pin_exec_ctls;
396         uint32_t                        cpu_exec_ctls;
397         uint32_t                        cpu2_exec_ctls;
398 };
399
400 int intel_vmm_init(void);
401 int intel_vmm_pcpu_init(void);
402 void vmx_load_guest_pcore(struct guest_pcore *gpc);
403 void vmx_unload_guest_pcore(struct guest_pcore *gpc);
404 uint64_t gpc_get_eptp(struct guest_pcore *gpc);
405 void vmx_clear_vmcs(void);
406 void vmx_setup_vmx_vmm(struct vmx_vmm *vmx);
407 int vmx_ctl_get_exits(struct vmx_vmm *vmx);
408 int vmx_ctl_set_exits(struct vmx_vmm *vmx, int vmm_exits);