4 * \brief X86 virtualization interface.
7 * (c) 2010-2013 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8 * Alexander Warg <warg@os.inf.tu-dresden.de>
9 * economic rights: Technische Universität Dresden (Germany)
11 * This file is part of TUD:OS and distributed under the terms of the
12 * GNU General Public License 2.
13 * Please see the COPYING-GPL-2 file for details.
15 * As a special exception, you may use this file as part of a free software
16 * library without restriction. Specifically, if other files instantiate
17 * templates or use macros or inline functions from this file, or you compile
18 * this file and link it with other files to produce an executable, this
19 * file does not by itself cause the resulting executable to be covered by
20 * the GNU General Public License. This exception does not however
21 * invalidate any other reasons why the executable file might be covered by
22 * the GNU General Public License.
26 #include <l4/sys/vcpu.h>
29 * \defgroup l4_vm_vmx_api VM API for VMX
30 * \brief Virtual machine API for VMX.
36 * \brief Exported VMX capability regsiters.
37 * \ingroup l4_vm_vmx_api
39 enum L4_vm_vmx_caps_regs
41 L4_VM_VMX_BASIC_REG = 0, /**< Basic VMX capabilities */
42 L4_VM_VMX_TRUE_PINBASED_CTLS_REG = 1, /**< True pin-based control caps */
43 L4_VM_VMX_TRUE_PROCBASED_CTLS_REG = 2, /**< True processor based control caps */
44 L4_VM_VMX_TRUE_EXIT_CTLS_REG = 3, /**< True exit control caps */
45 L4_VM_VMX_TRUE_ENTRY_CTLS_REG = 4, /**< True entry control caps */
46 L4_VM_VMX_MISC_REG = 5, /**< Misc caps */
47 L4_VM_VMX_CR0_FIXED0_REG = 6, /**< Fixed to 0 bits of CR0 */
48 L4_VM_VMX_CR0_FIXED1_REG = 7, /**< Fixed to 1 bits of CR0 */
49 L4_VM_VMX_CR4_FIXED0_REG = 8, /**< Fixed to 0 bits of CR4 */
50 L4_VM_VMX_CR4_FIXED1_REG = 9, /**< Fixed to 1 bits of CR4 */
51 L4_VM_VMX_VMCS_ENUM_REG = 0xa, /**< VMCS enumeration info */
52 L4_VM_VMX_PROCBASED_CTLS2_REG = 0xb, /**< Processor based control 2 caps */
53 L4_VM_VMX_EPT_VPID_CAP_REG = 0xc, /**< EPT and VPID caps */
54 L4_VM_VMX_NUM_CAPS_REGS /**< Total number of VMX capability registers */
59 * \brief Exported VMX capability regsiters (default to 1 bits).
60 * \ingroup l4_vm_vmx_api
62 enum L4_vm_vmx_dfl1_regs
64 L4_VM_VMX_PINBASED_CTLS_DFL1_REG = 0x1, /**< Default 1 bits in pin-based controls */
65 L4_VM_VMX_PROCBASED_CTLS_DFL1_REG = 0x2, /**< Default 1 bits in processor-based controls */
66 L4_VM_VMX_EXIT_CTLS_DFL1_REG = 0x3, /**< Default 1 bits in exit controls */
67 L4_VM_VMX_ENTRY_CTLS_DFL1_REG = 0x4, /**< Default 1 bits in entry controls */
68 L4_VM_VMX_NUM_DFL1_REGS /**< Total number of default on registers */
72 * \brief Get a capability register for VMX.
73 * \ingroup l4_vm_vmx_api
75 * \param vcpu_state Pointer to the VCPU state of the VCPU.
76 * \param cap_msr Caps register index (\see L4_vm_vmx_caps_regs).
77 * \return The value of the capability register.
81 l4_vm_vmx_get_caps(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW;
84 * \brief Get a default to one capability register for VMX.
85 * \ingroup l4_vm_vmx_api
87 * \param vcpu_state Pointer to the VCPU state of the VCPU.
88 * \param cap_msr Default 1 caps register index (\see L4_vm_vmx_dfl1_regs).
89 * \return The value of the capability register.
93 l4_vm_vmx_get_caps_default1(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW;
97 * \brief Additional VMCS fields.
98 * \ingroup l4_vm_vmx_api
103 * \brief (virtual) VMCS offset for CR2.
105 * The CR2 register is actually not in the hardware VMCS, however our VMMs
106 * run in user mode and need to have access to this register so we put it
107 * into our version of the VMCS.
109 * \note You usually need to check this value against the value you get from
110 * l4_vm_vmx_get_cr2_index() to make sure you are running on a
113 L4_VM_VMX_VMCS_CR2 = 0x683e,
117 * \brief Return length in bytes of a VMCS field.
118 * \ingroup l4_vm_vmx_api
120 * \param field Field number.
121 * \return Width of field in bytes.
125 l4_vm_vmx_field_len(unsigned field) L4_NOTHROW;
128 * \brief Return length in power of two (bytes) of a VMCS field.
129 * \ingroup l4_vm_vmx_api
131 * \param field Field number.
132 * \return Width of field in power of two (bytes).
136 l4_vm_vmx_field_order(unsigned field) L4_NOTHROW;
139 * \brief Get pointer into VMCS.
141 * \ingroup l4_vm_vmx_api
143 * \param vmcs Pointer to VMCS buffer.
144 * \param field Field number.
146 * \param Pointer to field in the VMCS.
150 l4_vm_vmx_field_ptr(void *vmcs, unsigned field) L4_NOTHROW;
153 * \brief Saves cached state from the kernel VMCS to the user VMCS.
154 * \ingroup l4_vm_vmx_api
155 * \param vmcs Pointer to the kernel VMCS.
156 * \param user_vmcs Pointer to the user VMCS.
158 * This function is comparable to VMX vmclear.
162 l4_vm_vmx_clear(void *vmcs, void *user_vmcs) L4_NOTHROW;
165 * \brief Loades the user_vmcs as the current VMCS.
166 * \ingroup l4_vm_vmx_api
167 * \param vmcs Pointer to the kernel VMCS.
168 * \param user_vmcs Pointer to the user VMCS.
170 * This function is comparable to VMX vmptrld.
174 l4_vm_vmx_ptr_load(void *vmcs, void *user_vmcs) L4_NOTHROW;
178 * \brief Get the VMCS field index of the virtual CR2 register.
179 * \ingroup l4_vm_vmx_api
181 * \param vmcs Pointer to the software VMCS.
182 * \return The field index used for the virtual CR2 register as used by the
183 * current Fiasco.OC interface.
185 * The CR2 register is actually not in the hardware VMCS, however our VMMs run
186 * in user mode and need to have access to this register so we put it into our
187 * software version of the VMCS.
189 * \see #L4_VM_VMX_VMCS_CR2
193 l4_vm_vmx_get_cr2_index(void const *vmcs) L4_NOTHROW;
196 * \brief Read a natural width VMCS field.
197 * \ingroup l4_vm_vmx_api
199 * \param vmcs Pointer to the software VMCS.
200 * \param field The VMCS field index as used on VMX hardware.
201 * \return The value of the VMCS field with the given index.
205 l4_vm_vmx_read_nat(void *vmcs, unsigned field) L4_NOTHROW;
208 * \brief Read a 16bit VMCS field.
209 * \ingroup l4_vm_vmx_api
211 * \param vmcs Pointer to the software VMCS.
212 * \param field The VMCS field index as used on VMX hardware.
213 * \return The value of the VMCS field with the given index.
217 l4_vm_vmx_read_16(void *vmcs, unsigned field) L4_NOTHROW;
220 * \brief Read a 32bit VMCS field.
221 * \ingroup l4_vm_vmx_api
223 * \param vmcs Pointer to the software VMCS.
224 * \param field The VMCS field index as used on VMX hardware.
225 * \return The value of the VMCS field with the given index.
229 l4_vm_vmx_read_32(void *vmcs, unsigned field) L4_NOTHROW;
232 * \brief Read a 64bit VMCS field.
233 * \ingroup l4_vm_vmx_api
235 * \param vmcs Pointer to the software VMCS.
236 * \param field The VMCS field index as used on VMX hardware.
237 * \return The value of the VMCS field with the given index.
241 l4_vm_vmx_read_64(void *vmcs, unsigned field) L4_NOTHROW;
244 * \brief Read any VMCS field.
245 * \ingroup l4_vm_vmx_api
247 * \param vmcs Pointer to the software VMCS.
248 * \param field The VMCS field index as used on VMX hardware.
249 * \return The value of the VMCS field with the given index.
253 L4_vm_vmx_read(void *vmcs, unsigned field) L4_NOTHROW;
256 * \brief Write to a natural width VMCS field.
257 * \ingroup l4_vm_vmx_api
259 * \param vmcs Pointer to the software VMCS.
260 * \param field The VMCS field index as used on VMX hardware.
261 * \param val The value that shall be written to the given field.
265 l4_vm_vmx_write_nat(void *vmcs, unsigned field, l4_umword_t val) L4_NOTHROW;
268 * \brief Write to a 16bit VMCS field.
269 * \ingroup l4_vm_vmx_api
271 * \param vmcs Pointer to the software VMCS.
272 * \param field The VMCS field index as used on VMX hardware.
273 * \param val The value that shall be written to the given field.
277 l4_vm_vmx_write_16(void *vmcs, unsigned field, l4_uint16_t val) L4_NOTHROW;
280 * \brief Write to a 32bit VMCS field.
281 * \ingroup l4_vm_vmx_api
283 * \param vmcs Pointer to the software VMCS.
284 * \param field The VMCS field index as used on VMX hardware.
285 * \param val The value that shall be written to the given field.
289 l4_vm_vmx_write_32(void *vmcs, unsigned field, l4_uint32_t val) L4_NOTHROW;
292 * \brief Write to a 64bit VMCS field.
293 * \ingroup l4_vm_vmx_api
295 * \param vmcs Pointer to the software VMCS.
296 * \param field The VMCS field index as used on VMX hardware.
297 * \param val The value that shall be written to the given field.
301 l4_vm_vmx_write_64(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW;
304 * \brief Write to an arbitrary VMCS field.
305 * \ingroup l4_vm_vmx_api
307 * \param vmcs Pointer to the software VMCS.
308 * \param field The VMCS field index as used on VMX hardware.
309 * \param val The value that shall be written to the given field.
313 l4_vm_vmx_write(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW;
316 /* Implementations */
320 l4_vm_vmx_field_order(unsigned field) L4_NOTHROW
327 case 3: if (sizeof(l4_umword_t) == 8) return 3; else return 2;
335 l4_vm_vmx_field_len(unsigned field) L4_NOTHROW
337 return 1 << l4_vm_vmx_field_order(field);
341 /* Internal VCPU state layout:
344 * 0 - xxx: normal IA32 VCPU state (l4_vcpu_state_t)
345 * 200h: VMX capabilities (see l4_vm_vmx_get_caps)
346 * 400h: Fiasco.OC VMCS
350 * 8h - Fh: ignored by kernel, stores current VMCS for l4_vm_vmx_clear...
351 * 10h - 13h: L4_VM_VMX_VMCS_CR2 value used by the kernel
352 * 14h - 1Fh: Reserved
353 * 20h - 3Fh: VMCS field offset table
354 * 40h - BFFh: Data (VMCS field data)
356 * VMCS field offset table:
357 * 0h - 2h: 3 offsets for 16bit fields:
358 * 0: Control fields, 1: read-only fields, 2: guest state
359 * all offsets in 64byte granules relative to the start of the VMCS
361 * 4h - 7h: Index shift values for 16bit, 64bit, 32bit, and natural width fields
362 * 8h - Ah: 3 offsets for 64bit fields
364 * 10h - 12h: 3 offsets for 32bit fields
365 * 13h - 17h: Reserved
366 * 18h - 1Ah: 3 offsets for natural width fields
368 * 1Ch: Offset of first VMCS field
369 * 1Dh: Full size of VMCS fields
370 * 1Eh - 1Fh: Reserved
376 l4_vm_vmx_field_offset(void const *vmcs, unsigned field) L4_NOTHROW
378 // the offset table is at 0x20 offset
380 l4_uint8_t const *offsets = (l4_uint8_t const *)vmcs;
382 return (unsigned)offsets[field >> 10] * 64 + ((field & 0x3ff) << offsets[Si + (field >> 13)]);
387 l4_vm_vmx_field_ptr(void *vmcs, unsigned field) L4_NOTHROW
389 return (void *)((char *)vmcs + l4_vm_vmx_field_offset(vmcs, field));
393 * \brief Copy full vmcs state
398 l4_vm_vmx_copy_state(void const *vmcs, void *_dst, void const *_src) L4_NOTHROW
400 l4_uint8_t const *offsets = (l4_uint8_t const *)vmcs + 0x20;
402 unsigned offs = offsets[28] * 64;
403 unsigned size = offsets[29] * 64;
404 char *const dst = (char*)_dst + offs;
405 char const *const src = (char const *)_src + offs;
406 __builtin_memcpy(dst, src, size);
411 l4_vm_vmx_clear(void *vmcs, void *user_vmcs) L4_NOTHROW
413 void **current_vmcs = (void **)((char *)vmcs + 8);
414 if (*current_vmcs != user_vmcs)
417 l4_vm_vmx_copy_state(vmcs, user_vmcs, vmcs);
423 l4_vm_vmx_ptr_load(void *vmcs, void *user_vmcs) L4_NOTHROW
425 void **current_vmcs = (void **)((char *)vmcs + 8);
426 if (*current_vmcs == user_vmcs)
429 if (*current_vmcs && *current_vmcs != user_vmcs)
430 l4_vm_vmx_clear(vmcs, *current_vmcs);
432 *current_vmcs = user_vmcs;
433 l4_vm_vmx_copy_state(vmcs, vmcs, user_vmcs);
439 l4_vm_vmx_read_nat(void *vmcs, unsigned field) L4_NOTHROW
440 { return *(l4_umword_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
444 l4_vm_vmx_read_16(void *vmcs, unsigned field) L4_NOTHROW
445 { return *(l4_uint16_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
449 l4_vm_vmx_read_32(void *vmcs, unsigned field) L4_NOTHROW
450 { return *(l4_uint32_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
454 l4_vm_vmx_read_64(void *vmcs, unsigned field) L4_NOTHROW
455 { return *(l4_uint64_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
459 L4_vm_vmx_read(void *vmcs, unsigned field) L4_NOTHROW
463 case 0: return l4_vm_vmx_read_16(vmcs, field);
464 case 1: return l4_vm_vmx_read_64(vmcs, field);
465 case 2: return l4_vm_vmx_read_32(vmcs, field);
466 case 3: return l4_vm_vmx_read_nat(vmcs, field);
472 l4_vm_vmx_write_nat(void *vmcs, unsigned field, l4_umword_t val) L4_NOTHROW
473 { *(l4_umword_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
477 l4_vm_vmx_write_16(void *vmcs, unsigned field, l4_uint16_t val) L4_NOTHROW
478 { *(l4_uint16_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
482 l4_vm_vmx_write_32(void *vmcs, unsigned field, l4_uint32_t val) L4_NOTHROW
483 { *(l4_uint32_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
487 l4_vm_vmx_write_64(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW
488 { *(l4_uint64_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
493 l4_vm_vmx_write(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW
497 case 0: l4_vm_vmx_write_16(vmcs, field, val); break;
498 case 1: l4_vm_vmx_write_64(vmcs, field, val); break;
499 case 2: l4_vm_vmx_write_32(vmcs, field, val); break;
500 case 3: l4_vm_vmx_write_nat(vmcs, field, val); break;
506 l4_vm_vmx_get_caps(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW
508 l4_uint64_t const *caps = (l4_uint64_t const *)((char const *)(vcpu_state) + L4_VCPU_OFFSET_EXT_INFOS);
509 return caps[cap_msr & 0xf];
514 l4_vm_vmx_get_caps_default1(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW
516 l4_uint32_t const *caps = (l4_uint32_t const *)((char const *)(vcpu_state) + L4_VCPU_OFFSET_EXT_INFOS);
517 return caps[L4_VM_VMX_NUM_CAPS_REGS * 2 + ((cap_msr & 0xf) - L4_VM_VMX_PINBASED_CTLS_DFL1_REG)];
522 l4_vm_vmx_get_cr2_index(void const *vmcs) L4_NOTHROW
524 l4_uint32_t const *infos = (l4_uint32_t const *)vmcs;