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