1 /////////////////////////////////////////////////////////////////////////
2 // $Id: svm.h 14193 2021-03-21 15:33:18Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2011-2015 Stanislav Shwartsman
6 //          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23 
24 #ifndef _BX_SVM_AMD_H_
25 #define _BX_SVM_AMD_H_
26 
27 #if BX_SUPPORT_SVM
28 
29 #define BX_SVM_REVISION 0x01 /* FIXME: check what is real SVM revision */
30 
31 enum SVM_intercept_codes {
32    SVM_VMEXIT_CR0_READ  = 0,
33    SVM_VMEXIT_CR2_READ  = 2,
34    SVM_VMEXIT_CR3_READ  = 3,
35    SVM_VMEXIT_CR4_READ  = 4,
36    SVM_VMEXIT_CR8_READ  = 8,
37    SVM_VMEXIT_CR0_WRITE = 16,
38    SVM_VMEXIT_CR2_WRITE = 18,
39    SVM_VMEXIT_CR3_WRITE = 19,
40    SVM_VMEXIT_CR4_WRITE = 20,
41    SVM_VMEXIT_CR8_WRITE = 24,
42    SVM_VMEXIT_DR0_READ  = 32,
43    SVM_VMEXIT_DR0_WRITE = 48,
44    SVM_VMEXIT_EXCEPTION = 64,
45    SVM_VMEXIT_PF_EXCEPTION = (64+BX_PF_EXCEPTION),
46    SVM_VMEXIT_INTR = 96,
47    SVM_VMEXIT_NMI = 97,
48    SVM_VMEXIT_SMI = 98,
49    SVM_VMEXIT_INIT = 99,
50    SVM_VMEXIT_VINTR = 100,
51    SVM_VMEXIT_CR0_SEL_WRITE = 101,
52    SVM_VMEXIT_IDTR_READ = 102,
53    SVM_VMEXIT_GDTR_READ = 103,
54    SVM_VMEXIT_LDTR_READ = 104,
55    SVM_VMEXIT_TR_READ = 105,
56    SVM_VMEXIT_IDTR_WRITE = 106,
57    SVM_VMEXIT_GDTR_WRITE = 107,
58    SVM_VMEXIT_LDTR_WRITE = 108,
59    SVM_VMEXIT_TR_WRITE = 109,
60    SVM_VMEXIT_RDTSC = 110,
61    SVM_VMEXIT_RDPMC = 111,
62    SVM_VMEXIT_PUSHF = 112,
63    SVM_VMEXIT_POPF = 113,
64    SVM_VMEXIT_CPUID = 114,
65    SVM_VMEXIT_RSM = 115,
66    SVM_VMEXIT_IRET = 116,
67    SVM_VMEXIT_SOFTWARE_INTERRUPT = 117,
68    SVM_VMEXIT_INVD = 118,
69    SVM_VMEXIT_PAUSE = 119,
70    SVM_VMEXIT_HLT = 120,
71    SVM_VMEXIT_INVLPG = 121,
72    SVM_VMEXIT_INVLPGA = 122,
73    SVM_VMEXIT_IO = 123,
74    SVM_VMEXIT_MSR = 124,
75    SVM_VMEXIT_TASK_SWITCH = 125,
76    SVM_VMEXIT_FERR_FREEZE = 126,
77    SVM_VMEXIT_SHUTDOWN = 127,
78    SVM_VMEXIT_VMRUN = 128,
79    SVM_VMEXIT_VMMCALL = 129,
80    SVM_VMEXIT_VMLOAD = 130,
81    SVM_VMEXIT_VMSAVE = 131,
82    SVM_VMEXIT_STGI = 132,
83    SVM_VMEXIT_CLGI = 133,
84    SVM_VMEXIT_SKINIT = 134,
85    SVM_VMEXIT_RDTSCP = 135,
86    SVM_VMEXIT_ICEBP = 136,
87    SVM_VMEXIT_WBINVD = 137,
88    SVM_VMEXIT_MONITOR = 138,
89    SVM_VMEXIT_MWAIT = 139,
90    SVM_VMEXIT_MWAIT_CONDITIONAL = 140,
91    SVM_VMEXIT_XSETBV = 141,
92    SVM_VMEXIT_NPF = 1024,
93    SVM_VMEXIT_AVIC_INCOMPLETE_IPI = 1025,
94    SVM_VMEXIT_AVIC_NOACCEL = 1026
95 };
96 
97 #define SVM_VMEXIT_INVALID (-1)
98 
99 // =====================
100 //  VMCB control fields
101 // =====================
102 
103 #define SVM_CONTROL16_INTERCEPT_CR_READ         (0x000)
104 #define SVM_CONTROL16_INTERCEPT_CR_WRITE        (0x002)
105 #define SVM_CONTROL16_INTERCEPT_DR_READ         (0x004)
106 #define SVM_CONTROL16_INTERCEPT_DR_WRITE        (0x006)
107 #define SVM_CONTROL32_INTERCEPT_EXCEPTIONS      (0x008)
108 #define SVM_CONTROL32_INTERCEPT1                (0x00c)
109 #define SVM_CONTROL32_INTERCEPT2                (0x010)
110 
111 #define SVM_CONTROL16_PAUSE_FILTER_THRESHOLD    (0x03c)
112 #define SVM_CONTROL16_PAUSE_FILTER_COUNT        (0x03e)
113 #define SVM_CONTROL64_IOPM_BASE_PHY_ADDR        (0x040)
114 #define SVM_CONTROL64_MSRPM_BASE_PHY_ADDR       (0x048)
115 #define SVM_CONTROL64_TSC_OFFSET                (0x050)
116 #define SVM_CONTROL32_GUEST_ASID                (0x058)
117 #define SVM_CONTROL32_TLB_CONTROL               (0x05c)
118 #define SVM_CONTROL_VTPR                        (0x060)
119 #define SVM_CONTROL_VIRQ                        (0x061)
120 #define SVM_CONTROL_VINTR_PRIO_IGN_TPR          (0x062)
121 #define SVM_CONTROL_VINTR_MASKING               (0x063)
122 #define SVM_CONTROL_VINTR_VECTOR                (0x064)
123 #define SVM_CONTROL_INTERRUPT_SHADOW            (0x068)
124 #define SVM_CONTROL64_EXITCODE                  (0x070)
125 #define SVM_CONTROL64_EXITINFO1                 (0x078)
126 #define SVM_CONTROL64_EXITINFO2                 (0x080)
127 #define SVM_CONTROL32_EXITINTINFO               (0x088)
128 #define SVM_CONTROL32_EXITINTINFO_ERROR_CODE    (0x08c)
129 #define SVM_CONTROL_NESTED_PAGING_ENABLE        (0x090)
130 
131 #define SVM_VIRTUAL_APIC_BAR                    (0x098)
132 
133 #define SVM_CONTROL32_EVENT_INJECTION           (0x0a8)
134 #define SVM_CONTROL32_EVENT_INJECTION_ERRORCODE (0x0ac)
135 #define SVM_CONTROL64_NESTED_PAGING_HOST_CR3    (0x0b0)
136 #define SVM_CONTROL_LBR_VIRTUALIZATION_ENABLE   (0x0b8)
137 #define SVM_CONTROL32_VMCB_CLEAN_BITS           (0x0c0)
138 #define SVM_CONTROL64_NRIP                      (0x0c8)
139 
140 #define SVM_CONTROL64_GUEST_INSTR_BYTES         (0x0d0)
141 #define SVM_CONTROL64_GUEST_INSTR_BYTES_HI      (0x0d8)
142 
143 #define SVM_AVIC_BACKING_PAGE                   (0x0e0)
144 #define SVM_AVIC_LOGICAL_TABLE_PTR              (0x0f0)
145 #define SVM_AVIC_PHYSICAL_TABLE_PTR             (0x0f8)
146 
147 // ======================
148 //  VMCB save state area
149 // ======================
150 
151 // ES
152 #define SVM_GUEST_ES_SELECTOR                   (0x400)
153 #define SVM_GUEST_ES_ATTR                       (0x402)
154 #define SVM_GUEST_ES_LIMIT                      (0x404)
155 #define SVM_GUEST_ES_BASE                       (0x408)
156 
157 // CS
158 #define SVM_GUEST_CS_SELECTOR                   (0x410)
159 #define SVM_GUEST_CS_ATTR                       (0x412)
160 #define SVM_GUEST_CS_LIMIT                      (0x414)
161 #define SVM_GUEST_CS_BASE                       (0x418)
162 
163 // SS
164 #define SVM_GUEST_SS_SELECTOR                   (0x420)
165 #define SVM_GUEST_SS_ATTR                       (0x422)
166 #define SVM_GUEST_SS_LIMIT                      (0x424)
167 #define SVM_GUEST_SS_BASE                       (0x428)
168 
169 // DS
170 #define SVM_GUEST_DS_SELECTOR                   (0x430)
171 #define SVM_GUEST_DS_ATTR                       (0x432)
172 #define SVM_GUEST_DS_LIMIT                      (0x434)
173 #define SVM_GUEST_DS_BASE                       (0x438)
174 
175 // FS
176 #define SVM_GUEST_FS_SELECTOR                   (0x440)
177 #define SVM_GUEST_FS_ATTR                       (0x442)
178 #define SVM_GUEST_FS_LIMIT                      (0x444)
179 #define SVM_GUEST_FS_BASE                       (0x448)
180 
181 // GS
182 #define SVM_GUEST_GS_SELECTOR                   (0x450)
183 #define SVM_GUEST_GS_ATTR                       (0x452)
184 #define SVM_GUEST_GS_LIMIT                      (0x454)
185 #define SVM_GUEST_GS_BASE                       (0x458)
186 
187 // GDTR
188 #define SVM_GUEST_GDTR_LIMIT                    (0x464)
189 #define SVM_GUEST_GDTR_BASE                     (0x468)
190 
191 // LDTR
192 #define SVM_GUEST_LDTR_SELECTOR                 (0x470)
193 #define SVM_GUEST_LDTR_ATTR                     (0x472)
194 #define SVM_GUEST_LDTR_LIMIT                    (0x474)
195 #define SVM_GUEST_LDTR_BASE                     (0x478)
196 
197 // IDTR
198 #define SVM_GUEST_IDTR_LIMIT                    (0x484)
199 #define SVM_GUEST_IDTR_BASE                     (0x488)
200 
201 // TR
202 #define SVM_GUEST_TR_SELECTOR                   (0x490)
203 #define SVM_GUEST_TR_ATTR                       (0x492)
204 #define SVM_GUEST_TR_LIMIT                      (0x494)
205 #define SVM_GUEST_TR_BASE                       (0x498)
206 
207 #define SVM_GUEST_CPL                           (0x4cb)
208 #define SVM_GUEST_EFER_MSR                      (0x4d0)
209 #define SVM_GUEST_EFER_MSR_HI                   (0x4d4)
210 
211 #define SVM_GUEST_CR4                           (0x548)
212 #define SVM_GUEST_CR4_HI                        (0x54c)
213 #define SVM_GUEST_CR3                           (0x550)
214 #define SVM_GUEST_CR0                           (0x558)
215 #define SVM_GUEST_CR0_HI                        (0x55c)
216 #define SVM_GUEST_DR7                           (0x560)
217 #define SVM_GUEST_DR7_HI                        (0x564)
218 #define SVM_GUEST_DR6                           (0x568)
219 #define SVM_GUEST_DR6_HI                        (0x56c)
220 #define SVM_GUEST_RFLAGS                        (0x570)
221 #define SVM_GUEST_RFLAGS_HI                     (0x574)
222 #define SVM_GUEST_RIP                           (0x578)
223 #define SVM_GUEST_RSP                           (0x5d8)
224 #define SVM_GUEST_RAX                           (0x5f8)
225 #define SVM_GUEST_STAR_MSR                      (0x600)
226 #define SVM_GUEST_LSTAR_MSR                     (0x608)
227 #define SVM_GUEST_CSTAR_MSR                     (0x610)
228 #define SVM_GUEST_FMASK_MSR                     (0x618)
229 #define SVM_GUEST_KERNEL_GSBASE_MSR             (0x620)
230 #define SVM_GUEST_SYSENTER_CS_MSR               (0x628)
231 #define SVM_GUEST_SYSENTER_ESP_MSR              (0x630)
232 #define SVM_GUEST_SYSENTER_EIP_MSR              (0x638)
233 #define SVM_GUEST_CR2                           (0x640)
234 
235 #define SVM_GUEST_PAT                           (0x668) /* used only when nested paging is enabled */
236 #define SVM_GUEST_DBGCTL_MSR                    (0x670)
237 #define SVM_GUEST_BR_FROM_MSR                   (0x678)
238 #define SVM_GUEST_BR_TO_MSR                     (0x680)
239 #define SVM_GUEST_LAST_EXCEPTION_FROM_MSR       (0x688)
240 #define SVM_GUEST_LAST_EXCEPTION_TO_MSR         (0x690)
241 
242 typedef struct bx_SVM_HOST_STATE
243 {
244   bx_segment_reg_t sregs[4];
245 
246   bx_global_segment_reg_t gdtr;
247   bx_global_segment_reg_t idtr;
248 
249   bx_efer_t efer;
250   bx_cr0_t cr0;
251   bx_cr4_t cr4;
252   bx_phy_address cr3;
253   Bit32u eflags;
254   Bit64u rip;
255   Bit64u rsp;
256   Bit64u rax;
257 
258   BxPackedRegister pat_msr;
259 
260 } SVM_HOST_STATE;
261 
262 typedef struct bx_SVM_GUEST_STATE
263 {
264   bx_segment_reg_t sregs[4];
265 
266   bx_global_segment_reg_t gdtr;
267   bx_global_segment_reg_t idtr;
268 
269   bx_efer_t efer;
270   bx_cr0_t cr0;
271   bx_cr4_t cr4;
272   bx_address cr2;
273   Bit32u dr6;
274   Bit32u dr7;
275   bx_phy_address cr3;
276   BxPackedRegister pat_msr;
277   Bit32u eflags;
278   Bit64u rip;
279   Bit64u rsp;
280   Bit64u rax;
281 
282   unsigned cpl;
283 
284   bool inhibit_interrupts;
285 
286 } SVM_GUEST_STATE;
287 
288 typedef struct bx_SVM_CONTROLS
289 {
290   Bit16u cr_rd_ctrl;
291   Bit16u cr_wr_ctrl;
292   Bit16u dr_rd_ctrl;
293   Bit16u dr_wr_ctrl;
294   Bit32u exceptions_intercept;
295 
296   Bit32u intercept_vector[2];
297 
298   Bit32u exitintinfo;
299   Bit32u exitintinfo_error_code;
300 
301   Bit32u eventinj;
302 
303   bx_phy_address iopm_base;
304   bx_phy_address msrpm_base;
305 
306   Bit8u v_tpr;
307   Bit8u v_intr_prio;
308   bool v_ignore_tpr;
309   bool v_intr_masking;
310   Bit8u v_intr_vector;
311 
312   bool nested_paging;
313   Bit64u ncr3;
314 
315   Bit16u pause_filter_count;
316 //Bit16u pause_filter_threshold;
317 
318 } SVM_CONTROLS;
319 
320 #if defined(NEED_CPU_REG_SHORTCUTS)
321 
322 #define SVM_V_TPR          (BX_CPU_THIS_PTR vmcb.ctrls.v_tpr)
323 #define SVM_V_INTR_PRIO    (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_prio)
324 #define SVM_V_IGNORE_TPR   (BX_CPU_THIS_PTR vmcb.ctrls.v_ignore_tpr)
325 #define SVM_V_INTR_MASKING (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_masking)
326 #define SVM_V_INTR_VECTOR  (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_vector)
327 
328 #define SVM_HOST_IF (BX_CPU_THIS_PTR vmcb.host_state.eflags & EFlagsIFMask)
329 
330 #endif
331 
332 typedef struct bx_VMCB_CACHE
333 {
334   SVM_HOST_STATE host_state;
335   SVM_CONTROLS ctrls;
336 } VMCB_CACHE;
337 
338 // ========================
339 //  SVM intercept controls
340 // ========================
341 
342 enum {
343   SVM_INTERCEPT0_INTR = 0,
344   SVM_INTERCEPT0_NMI = 1,
345   SVM_INTERCEPT0_SMI = 2,
346   SVM_INTERCEPT0_INIT = 3,
347   SVM_INTERCEPT0_VINTR = 4,
348   SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP = 5,
349   SVM_INTERCEPT0_IDTR_READ = 6,
350   SVM_INTERCEPT0_GDTR_READ = 7,
351   SVM_INTERCEPT0_LDTR_READ = 8,
352   SVM_INTERCEPT0_TR_READ = 9,
353   SVM_INTERCEPT0_IDTR_WRITE = 10,
354   SVM_INTERCEPT0_GDTR_WRITE = 11,
355   SVM_INTERCEPT0_LDTR_WRITE = 12,
356   SVM_INTERCEPT0_TR_WRITE = 13,
357   SVM_INTERCEPT0_RDTSC = 14,
358   SVM_INTERCEPT0_RDPMC = 15,
359   SVM_INTERCEPT0_PUSHF = 16,
360   SVM_INTERCEPT0_POPF = 17,
361   SVM_INTERCEPT0_CPUID = 18,
362   SVM_INTERCEPT0_RSM = 19,
363   SVM_INTERCEPT0_IRET = 20,
364   SVM_INTERCEPT0_SOFTINT = 21,
365   SVM_INTERCEPT0_INVD = 22,
366   SVM_INTERCEPT0_PAUSE = 23,
367   SVM_INTERCEPT0_HLT = 24,
368   SVM_INTERCEPT0_INVLPG = 25,
369   SVM_INTERCEPT0_INVLPGA = 26,
370   SVM_INTERCEPT0_IO = 27,
371   SVM_INTERCEPT0_MSR = 28,
372   SVM_INTERCEPT0_TASK_SWITCH = 29,
373   SVM_INTERCEPT0_FERR_FREEZE = 30,
374   SVM_INTERCEPT0_SHUTDOWN = 31,
375   SVM_INTERCEPT1_VMRUN = 32,
376   SVM_INTERCEPT1_VMMCALL = 33,
377   SVM_INTERCEPT1_VMLOAD = 34,
378   SVM_INTERCEPT1_VMSAVE = 35,
379   SVM_INTERCEPT1_STGI = 36,
380   SVM_INTERCEPT1_CLGI = 37,
381   SVM_INTERCEPT1_SKINIT = 38,
382   SVM_INTERCEPT1_RDTSCP = 39,
383   SVM_INTERCEPT1_ICEBP = 40,
384   SVM_INTERCEPT1_WBINVD = 41,
385   SVM_INTERCEPT1_MONITOR = 42,
386   SVM_INTERCEPT1_MWAIT = 43,
387   SVM_INTERCEPT1_MWAIT_ARMED = 44,
388   SVM_INTERCEPT1_XSETBV = 45,
389 };
390 
391 #define SVM_INTERCEPT(intercept_bitnum) \
392   (BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[intercept_bitnum / 32] & (1 << (intercept_bitnum & 31)))
393 
394 #define SVM_EXCEPTION_INTERCEPTED(vector) \
395   (BX_CPU_THIS_PTR vmcb.ctrls.exceptions_intercept & (1<<(vector)))
396 
397 #define SVM_CR_READ_INTERCEPTED(reg_num) \
398   (BX_CPU_THIS_PTR vmcb.ctrls.cr_rd_ctrl & (1<<(reg_num)))
399 
400 #define SVM_CR_WRITE_INTERCEPTED(reg_num) \
401   (BX_CPU_THIS_PTR vmcb.ctrls.cr_wr_ctrl & (1<<(reg_num)))
402 
403 #define SVM_DR_READ_INTERCEPTED(reg_num) \
404   (BX_CPU_THIS_PTR vmcb.ctrls.dr_rd_ctrl & (1<<(reg_num)))
405 
406 #define SVM_DR_WRITE_INTERCEPTED(reg_num) \
407   (BX_CPU_THIS_PTR vmcb.ctrls.dr_wr_ctrl & (1<<(reg_num)))
408 
409 #define SVM_NESTED_PAGING_ENABLED (BX_CPU_THIS_PTR vmcb.ctrls.nested_paging)
410 
411 #endif // BX_SUPPORT_SVM
412 
413 #endif // _BX_SVM_AMD_H_
414