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