1 // Copyright 2017 The Fuchsia Authors 2 // 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file or at 5 // https://opensource.org/licenses/MIT 6 7 #pragma once 8 9 #include <zircon/compiler.h> 10 11 #define VS_RESUME 0 12 13 #define HS_RIP (VS_RESUME + 8) 14 #define HS_RBX (HS_RIP + 8) 15 #define HS_RSP (HS_RBX + 8) 16 #define HS_RBP (HS_RSP + 8) 17 #define HS_R12 (HS_RBP + 8) 18 #define HS_R13 (HS_R12 + 8) 19 #define HS_R14 (HS_R13 + 8) 20 #define HS_R15 (HS_R14 + 8) 21 #define HS_RFLAGS (HS_R15 + 8) 22 23 #define GS_RAX (HS_RFLAGS + 16) 24 #define GS_RCX (GS_RAX + 8) 25 #define GS_RDX (GS_RCX + 8) 26 #define GS_RBX (GS_RDX + 8) 27 #define GS_RBP (GS_RBX + 8) 28 #define GS_RSI (GS_RBP + 8) 29 #define GS_RDI (GS_RSI + 8) 30 #define GS_R8 (GS_RDI + 8) 31 #define GS_R9 (GS_R8 + 8) 32 #define GS_R10 (GS_R9 + 8) 33 #define GS_R11 (GS_R10 + 8) 34 #define GS_R12 (GS_R11 + 8) 35 #define GS_R13 (GS_R12 + 8) 36 #define GS_R14 (GS_R13 + 8) 37 #define GS_R15 (GS_R14 + 8) 38 #define GS_CR2 (GS_R15 + 8) 39 40 #ifndef __ASSEMBLER__ 41 42 #include <zircon/types.h> 43 44 /* Holds the register state used to restore a host. */ 45 struct HostState { 46 // Return address. 47 uint64_t rip; 48 49 // Callee-save registers. 50 uint64_t rbx; 51 uint64_t rsp; 52 uint64_t rbp; 53 uint64_t r12; 54 uint64_t r13; 55 uint64_t r14; 56 uint64_t r15; 57 58 // Processor flags. 59 uint64_t rflags; 60 61 // Extended control registers. 62 uint64_t xcr0; 63 }; 64 65 struct GuestState { 66 // RIP, RSP, and RFLAGS are automatically saved by VMX in the VMCS. 67 uint64_t rax; 68 uint64_t rcx; 69 uint64_t rdx; 70 uint64_t rbx; 71 uint64_t rbp; 72 uint64_t rsi; 73 uint64_t rdi; 74 uint64_t r8; 75 uint64_t r9; 76 uint64_t r10; 77 uint64_t r11; 78 uint64_t r12; 79 uint64_t r13; 80 uint64_t r14; 81 uint64_t r15; 82 83 // Control registers. 84 uint64_t cr2; 85 86 // Extended control registers. 87 uint64_t xcr0; 88 }; 89 90 struct VmxState { 91 bool resume; 92 HostState host_state; 93 GuestState guest_state; 94 }; 95 96 static_assert(__offsetof(VmxState, resume) == VS_RESUME, ""); 97 98 static_assert(__offsetof(VmxState, host_state.rip) == HS_RIP, ""); 99 static_assert(__offsetof(VmxState, host_state.rsp) == HS_RSP, ""); 100 static_assert(__offsetof(VmxState, host_state.rbp) == HS_RBP, ""); 101 static_assert(__offsetof(VmxState, host_state.rbx) == HS_RBX, ""); 102 static_assert(__offsetof(VmxState, host_state.r12) == HS_R12, ""); 103 static_assert(__offsetof(VmxState, host_state.r13) == HS_R13, ""); 104 static_assert(__offsetof(VmxState, host_state.r14) == HS_R14, ""); 105 static_assert(__offsetof(VmxState, host_state.r15) == HS_R15, ""); 106 static_assert(__offsetof(VmxState, host_state.rflags) == HS_RFLAGS, ""); 107 108 static_assert(__offsetof(VmxState, guest_state.rax) == GS_RAX, ""); 109 static_assert(__offsetof(VmxState, guest_state.rbx) == GS_RBX, ""); 110 static_assert(__offsetof(VmxState, guest_state.rcx) == GS_RCX, ""); 111 static_assert(__offsetof(VmxState, guest_state.rdx) == GS_RDX, ""); 112 static_assert(__offsetof(VmxState, guest_state.rdi) == GS_RDI, ""); 113 static_assert(__offsetof(VmxState, guest_state.rsi) == GS_RSI, ""); 114 static_assert(__offsetof(VmxState, guest_state.rbp) == GS_RBP, ""); 115 static_assert(__offsetof(VmxState, guest_state.r8) == GS_R8, ""); 116 static_assert(__offsetof(VmxState, guest_state.r9) == GS_R9, ""); 117 static_assert(__offsetof(VmxState, guest_state.r10) == GS_R10, ""); 118 static_assert(__offsetof(VmxState, guest_state.r11) == GS_R11, ""); 119 static_assert(__offsetof(VmxState, guest_state.r12) == GS_R12, ""); 120 static_assert(__offsetof(VmxState, guest_state.r13) == GS_R13, ""); 121 static_assert(__offsetof(VmxState, guest_state.r14) == GS_R14, ""); 122 static_assert(__offsetof(VmxState, guest_state.r15) == GS_R15, ""); 123 static_assert(__offsetof(VmxState, guest_state.cr2) == GS_CR2, ""); 124 125 __BEGIN_CDECLS 126 127 /* Launch the guest and save the host state. 128 * If we return 0, we have exited from the guest, otherwise we have failed to 129 * launch the guest. 130 */ 131 zx_status_t vmx_enter(VmxState* vmx_state); 132 133 /* Exit from the guest, and load the saved host state. 134 * This function is never called directly, but is executed on exit from a guest. 135 * It calls vmx_exit before returning through vmx_enter. 136 */ 137 void vmx_exit_entry(); 138 void vmx_exit(VmxState* vmx_state); 139 140 __END_CDECLS 141 142 #endif // __ASSEMBLER__ 143