|
1 | 1 | /* |
2 | 2 | * Copyright (c) 2009 Intel Corporation |
| 3 | + * Copyright (c) 2018 Kryptos Logic |
3 | 4 | * |
4 | 5 | * Redistribution and use in source and binary forms, with or without |
5 | 6 | * modification, are permitted provided that the following conditions are met: |
@@ -257,6 +258,208 @@ enum component_index_t { |
257 | 258 |
|
258 | 259 | typedef enum component_index_t component_index_t; |
259 | 260 |
|
| 261 | +// VMCS component types |
| 262 | +#define COMP_TYPE_W_16 uint16_t |
| 263 | +#define COMP_TYPE_W_32 uint32_t |
| 264 | +#define COMP_TYPE_W_64 uint64_t |
| 265 | +#ifdef HAX_ARCH_X86_64 |
| 266 | +#define COMP_TYPE_W_UL uint64_t |
| 267 | +#else |
| 268 | +#define COMP_TYPE_W_UL uint32_t |
| 269 | +#endif |
| 270 | + |
| 271 | +/** |
| 272 | + * VMCS Cache |
| 273 | + * ========== |
| 274 | + * Stores all VMCS components declared through the macro |
| 275 | + * COMP(cache_r, cache_w, width, value), with the arguments: |
| 276 | + * - cache_r: Boolean value to toggle read-cache: |
| 277 | + * - 0 Reading cache disabled |
| 278 | + * - 1 Reading cache enabled |
| 279 | + * - cache_w: Boolean value to toggle write-cache: |
| 280 | + * - 0 Writing cache disabled |
| 281 | + * - 1 Writing cache enabled |
| 282 | + * - width: Component width. |
| 283 | + * - W_16 (0): 16-bit unsigned integer. |
| 284 | + * - W_64 (1): 64-bit unsigned integer. |
| 285 | + * - W_32 (2): 32-bit unsigned integer. |
| 286 | + * - W_UL (3): Natural-width unsigned integer. |
| 287 | + * - name: Component name, defined as encoding value. |
| 288 | + * |
| 289 | + * For optimal memory packing, components should be declared |
| 290 | + * in the following order: W_64, W_UL, W_32, W_16. |
| 291 | + */ |
| 292 | +#define VMCS_COMPS \ |
| 293 | + /* 64-bit components */ \ |
| 294 | + COMP(1, 1, W_64, VMX_IO_BITMAP_A) \ |
| 295 | + COMP(0, 0, W_64, VMX_IO_BITMAP_B) \ |
| 296 | + COMP(0, 0, W_64, VMX_MSR_BITMAP) \ |
| 297 | + COMP(0, 0, W_64, VMX_EXIT_MSR_STORE_ADDRESS) \ |
| 298 | + COMP(0, 0, W_64, VMX_EXIT_MSR_LOAD_ADDRESS) \ |
| 299 | + COMP(0, 0, W_64, VMX_ENTRY_MSR_LOAD_ADDRESS) \ |
| 300 | + COMP(0, 0, W_64, VMX_TSC_OFFSET) \ |
| 301 | + COMP(0, 0, W_64, VMX_VAPIC_PAGE) \ |
| 302 | + COMP(0, 0, W_64, VMX_APIC_ACCESS_PAGE) \ |
| 303 | + COMP(0, 0, W_64, VMX_EPTP) \ |
| 304 | + COMP(0, 0, W_64, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS) \ |
| 305 | + COMP(0, 0, W_64, HOST_PAT) \ |
| 306 | + COMP(0, 0, W_64, HOST_EFER) \ |
| 307 | + COMP(0, 0, W_64, HOST_PERF_GLOBAL_CTRL) \ |
| 308 | + COMP(0, 0, W_64, GUEST_VMCS_LINK_PTR) \ |
| 309 | + COMP(0, 0, W_64, GUEST_DEBUGCTL) \ |
| 310 | + COMP(0, 0, W_64, GUEST_PAT) \ |
| 311 | + COMP(0, 0, W_64, GUEST_EFER) \ |
| 312 | + COMP(0, 0, W_64, GUEST_PERF_GLOBAL_CTRL) \ |
| 313 | + COMP(0, 0, W_64, GUEST_PDPTE0) \ |
| 314 | + COMP(0, 0, W_64, GUEST_PDPTE1) \ |
| 315 | + COMP(0, 0, W_64, GUEST_PDPTE2) \ |
| 316 | + COMP(0, 0, W_64, GUEST_PDPTE3) \ |
| 317 | + /* Natural-width components */ \ |
| 318 | + COMP(0, 0, W_UL, VMX_CR0_MASK) \ |
| 319 | + COMP(0, 0, W_UL, VMX_CR4_MASK) \ |
| 320 | + COMP(0, 0, W_UL, VMX_CR0_READ_SHADOW) \ |
| 321 | + COMP(0, 0, W_UL, VMX_CR4_READ_SHADOW) \ |
| 322 | + COMP(0, 0, W_UL, VMX_CR3_TARGET_VAL_BASE) \ |
| 323 | + COMP(0, 0, W_UL, VM_EXIT_INFO_QUALIFICATION) \ |
| 324 | + COMP(0, 0, W_UL, VM_EXIT_INFO_IO_ECX) \ |
| 325 | + COMP(0, 0, W_UL, VM_EXIT_INFO_IO_ESI) \ |
| 326 | + COMP(0, 0, W_UL, VM_EXIT_INFO_IO_EDI) \ |
| 327 | + COMP(0, 0, W_UL, VM_EXIT_INFO_IO_EIP) \ |
| 328 | + COMP(0, 0, W_UL, VM_EXIT_INFO_GUEST_LINEAR_ADDRESS) \ |
| 329 | + COMP(0, 0, W_UL, HOST_RIP) \ |
| 330 | + COMP(0, 0, W_UL, HOST_RSP) \ |
| 331 | + COMP(0, 0, W_UL, HOST_CR0) \ |
| 332 | + COMP(0, 0, W_UL, HOST_CR3) \ |
| 333 | + COMP(0, 0, W_UL, HOST_CR4) \ |
| 334 | + COMP(0, 0, W_UL, HOST_FS_BASE) \ |
| 335 | + COMP(0, 0, W_UL, HOST_GS_BASE) \ |
| 336 | + COMP(0, 0, W_UL, HOST_TR_BASE) \ |
| 337 | + COMP(0, 0, W_UL, HOST_GDTR_BASE) \ |
| 338 | + COMP(0, 0, W_UL, HOST_IDTR_BASE) \ |
| 339 | + COMP(0, 0, W_UL, HOST_SYSENTER_ESP) \ |
| 340 | + COMP(0, 0, W_UL, HOST_SYSENTER_EIP) \ |
| 341 | + COMP(0, 0, W_UL, GUEST_RIP) \ |
| 342 | + COMP(0, 0, W_UL, GUEST_RFLAGS) \ |
| 343 | + COMP(0, 0, W_UL, GUEST_RSP) \ |
| 344 | + COMP(0, 0, W_UL, GUEST_CR0) \ |
| 345 | + COMP(0, 0, W_UL, GUEST_CR3) \ |
| 346 | + COMP(0, 0, W_UL, GUEST_CR4) \ |
| 347 | + COMP(0, 0, W_UL, GUEST_ES_BASE) \ |
| 348 | + COMP(0, 0, W_UL, GUEST_CS_BASE) \ |
| 349 | + COMP(0, 0, W_UL, GUEST_SS_BASE) \ |
| 350 | + COMP(0, 0, W_UL, GUEST_DS_BASE) \ |
| 351 | + COMP(0, 0, W_UL, GUEST_FS_BASE) \ |
| 352 | + COMP(0, 0, W_UL, GUEST_GS_BASE) \ |
| 353 | + COMP(0, 0, W_UL, GUEST_LDTR_BASE) \ |
| 354 | + COMP(0, 0, W_UL, GUEST_TR_BASE) \ |
| 355 | + COMP(0, 0, W_UL, GUEST_GDTR_BASE) \ |
| 356 | + COMP(0, 0, W_UL, GUEST_IDTR_BASE) \ |
| 357 | + COMP(0, 0, W_UL, GUEST_DR7) \ |
| 358 | + COMP(0, 0, W_UL, GUEST_PENDING_DBE) \ |
| 359 | + COMP(0, 0, W_UL, GUEST_SYSENTER_ESP) \ |
| 360 | + COMP(0, 0, W_UL, GUEST_SYSENTER_EIP) \ |
| 361 | + /* 32-bit components */ \ |
| 362 | + COMP(0, 0, W_32, VMX_PIN_CONTROLS) \ |
| 363 | + COMP(0, 0, W_32, VMX_PRIMARY_PROCESSOR_CONTROLS) \ |
| 364 | + COMP(0, 0, W_32, VMX_SECONDARY_PROCESSOR_CONTROLS) \ |
| 365 | + COMP(0, 0, W_32, VMX_EXCEPTION_BITMAP) \ |
| 366 | + COMP(0, 0, W_32, VMX_PAGE_FAULT_ERROR_CODE_MASK) \ |
| 367 | + COMP(0, 0, W_32, VMX_PAGE_FAULT_ERROR_CODE_MATCH) \ |
| 368 | + COMP(0, 0, W_32, VMX_EXIT_CONTROLS) \ |
| 369 | + COMP(0, 0, W_32, VMX_EXIT_MSR_STORE_COUNT) \ |
| 370 | + COMP(0, 0, W_32, VMX_EXIT_MSR_LOAD_COUNT) \ |
| 371 | + COMP(0, 0, W_32, VMX_ENTRY_CONTROLS) \ |
| 372 | + COMP(0, 0, W_32, VMX_ENTRY_MSR_LOAD_COUNT) \ |
| 373 | + COMP(0, 0, W_32, VMX_ENTRY_INTERRUPT_INFO) \ |
| 374 | + COMP(0, 0, W_32, VMX_ENTRY_EXCEPTION_ERROR_CODE) \ |
| 375 | + COMP(0, 0, W_32, VMX_ENTRY_INSTRUCTION_LENGTH) \ |
| 376 | + COMP(0, 0, W_32, VMX_TPR_THRESHOLD) \ |
| 377 | + COMP(0, 0, W_32, VMX_CR3_TARGET_COUNT) \ |
| 378 | + COMP(0, 0, W_32, VMX_PREEMPTION_TIMER) \ |
| 379 | + COMP(0, 0, W_32, VMX_INSTRUCTION_ERROR_CODE) \ |
| 380 | + COMP(0, 0, W_32, VM_EXIT_INFO_REASON) \ |
| 381 | + COMP(0, 0, W_32, VM_EXIT_INFO_INTERRUPT_INFO) \ |
| 382 | + COMP(0, 0, W_32, VM_EXIT_INFO_EXCEPTION_ERROR_CODE) \ |
| 383 | + COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING) \ |
| 384 | + COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE) \ |
| 385 | + COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_LENGTH) \ |
| 386 | + COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_INFO) \ |
| 387 | + COMP(0, 0, W_32, HOST_SYSENTER_CS) \ |
| 388 | + COMP(0, 0, W_32, GUEST_ES_AR) \ |
| 389 | + COMP(0, 0, W_32, GUEST_CS_AR) \ |
| 390 | + COMP(0, 0, W_32, GUEST_SS_AR) \ |
| 391 | + COMP(0, 0, W_32, GUEST_DS_AR) \ |
| 392 | + COMP(0, 0, W_32, GUEST_FS_AR) \ |
| 393 | + COMP(0, 0, W_32, GUEST_GS_AR) \ |
| 394 | + COMP(0, 0, W_32, GUEST_LDTR_AR) \ |
| 395 | + COMP(0, 0, W_32, GUEST_TR_AR) \ |
| 396 | + COMP(0, 0, W_32, GUEST_ES_LIMIT) \ |
| 397 | + COMP(0, 0, W_32, GUEST_CS_LIMIT) \ |
| 398 | + COMP(0, 0, W_32, GUEST_SS_LIMIT) \ |
| 399 | + COMP(0, 0, W_32, GUEST_DS_LIMIT) \ |
| 400 | + COMP(0, 0, W_32, GUEST_FS_LIMIT) \ |
| 401 | + COMP(0, 0, W_32, GUEST_GS_LIMIT) \ |
| 402 | + COMP(0, 0, W_32, GUEST_LDTR_LIMIT) \ |
| 403 | + COMP(0, 0, W_32, GUEST_TR_LIMIT) \ |
| 404 | + COMP(0, 0, W_32, GUEST_GDTR_LIMIT) \ |
| 405 | + COMP(0, 0, W_32, GUEST_IDTR_LIMIT) \ |
| 406 | + COMP(0, 0, W_32, GUEST_SYSENTER_CS) \ |
| 407 | + COMP(0, 0, W_32, GUEST_SMBASE) \ |
| 408 | + COMP(0, 0, W_32, GUEST_INTERRUPTIBILITY) \ |
| 409 | + COMP(0, 0, W_32, GUEST_ACTIVITY_STATE) \ |
| 410 | + /* 16-bit components */ \ |
| 411 | + COMP(0, 0, W_16, VMX_VPID) \ |
| 412 | + COMP(0, 0, W_16, HOST_CS_SELECTOR) \ |
| 413 | + COMP(0, 0, W_16, HOST_DS_SELECTOR) \ |
| 414 | + COMP(0, 0, W_16, HOST_ES_SELECTOR) \ |
| 415 | + COMP(0, 0, W_16, HOST_FS_SELECTOR) \ |
| 416 | + COMP(0, 0, W_16, HOST_GS_SELECTOR) \ |
| 417 | + COMP(0, 0, W_16, HOST_SS_SELECTOR) \ |
| 418 | + COMP(0, 0, W_16, HOST_TR_SELECTOR) \ |
| 419 | + COMP(0, 0, W_16, GUEST_ES_SELECTOR) \ |
| 420 | + COMP(0, 0, W_16, GUEST_CS_SELECTOR) \ |
| 421 | + COMP(0, 0, W_16, GUEST_SS_SELECTOR) \ |
| 422 | + COMP(0, 0, W_16, GUEST_DS_SELECTOR) \ |
| 423 | + COMP(0, 0, W_16, GUEST_FS_SELECTOR) \ |
| 424 | + COMP(0, 0, W_16, GUEST_GS_SELECTOR) \ |
| 425 | + COMP(0, 0, W_16, GUEST_LDTR_SELECTOR) \ |
| 426 | + COMP(0, 0, W_16, GUEST_TR_SELECTOR) |
| 427 | + |
| 428 | + // Macros for declaring cache and R/W-flags declarations |
| 429 | +#define COMP_CACHE_R_0(name) |
| 430 | +#define COMP_CACHE_R_1(name) \ |
| 431 | + bool name##_cache : 1; |
| 432 | +#define COMP_CACHE_W_0(name) |
| 433 | +#define COMP_CACHE_W_1(name) \ |
| 434 | + bool name##_dirty : 1; |
| 435 | + |
| 436 | +#define COMP_CACHE_R(cache_r, cache_w, width, name) \ |
| 437 | + COMP_CACHE_R_##cache_r(name) |
| 438 | +#define COMP_CACHE_W(cache_r, cache_w, width, name) \ |
| 439 | + COMP_CACHE_W_##cache_w(name) |
| 440 | +#define COMP_DECLARE(cache_r, cache_w, width, name) \ |
| 441 | + COMP_TYPE_##width name##_value; |
| 442 | + |
| 443 | +// Structures |
| 444 | +struct vmx_vmcs_t { |
| 445 | +#define COMP COMP_DECLARE |
| 446 | + VMCS_COMPS |
| 447 | +#undef COMP |
| 448 | +}; |
| 449 | + |
| 450 | +struct vmx_vmcs_cache_r_t { |
| 451 | +#define COMP COMP_CACHE_R |
| 452 | + VMCS_COMPS |
| 453 | +#undef COMP |
| 454 | +}; |
| 455 | + |
| 456 | +struct vmx_vmcs_cache_w_t { |
| 457 | + bool dirty : 1; |
| 458 | +#define COMP COMP_CACHE_W |
| 459 | + VMCS_COMPS |
| 460 | +#undef COMP |
| 461 | +}; |
| 462 | + |
260 | 463 | // PIN-BASED CONTROLS |
261 | 464 | #define EXT_INTERRUPT_EXITING 0x00000001 |
262 | 465 | #define NMI_EXITING 0x00000008 |
@@ -653,6 +856,11 @@ struct vcpu_state_t; |
653 | 856 | struct vcpu_t; |
654 | 857 |
|
655 | 858 | struct vcpu_vmx_data { |
| 859 | + struct vcpu_t *parent; |
| 860 | + struct vmx_vmcs_t vmcs; |
| 861 | + struct vmx_vmcs_cache_r_t vmcs_cache_r; |
| 862 | + struct vmx_vmcs_cache_w_t vmcs_cache_w; |
| 863 | + |
656 | 864 | uint32_t pin_ctls_base; |
657 | 865 | uint32_t pcpu_ctls_base; |
658 | 866 | uint32_t scpu_ctls_base; |
@@ -706,6 +914,64 @@ void vmx_vmwrite(struct vcpu_t *vcpu, const char *name, |
706 | 914 |
|
707 | 915 | #define vmwrite(vcpu, x, y) vmx_vmwrite(vcpu, #x, x, y) |
708 | 916 |
|
| 917 | +/** |
| 918 | + * vmcs_read_<name> |
| 919 | + * Reads the VMCS-component <name> from the specified VCPU (cached if enabled). |
| 920 | + */ |
| 921 | +#define COMP_R_0(width, name) \ |
| 922 | + static inline COMP_TYPE_##width \ |
| 923 | + vmcs_read_##name(struct vcpu_vmx_data* vcpu_vmx) { \ |
| 924 | + return vmread(vcpu_vmx->parent, name); \ |
| 925 | + } |
| 926 | +#define COMP_R_1(width, name) \ |
| 927 | + static inline COMP_TYPE_##width \ |
| 928 | + vmcs_read_##name(struct vcpu_vmx_data* vcpu_vmx) { \ |
| 929 | + if (vcpu_vmx->vmcs_cache_r.name##_cache) \ |
| 930 | + return vcpu_vmx->vmcs.name##_value; \ |
| 931 | + vcpu_vmx->vmcs.name##_value = vmread(vcpu_vmx->parent, name); \ |
| 932 | + vcpu_vmx->vmcs_cache_r.name##_cache = 1; \ |
| 933 | + return vcpu_vmx->vmcs.name##_value; \ |
| 934 | + } |
| 935 | + |
| 936 | + /** |
| 937 | + * vmcs_write_<name> |
| 938 | + * Writes the VMCS-component <name> to the specified VCPU (cached if enabled). |
| 939 | + */ |
| 940 | +#define COMP_W_0(width, name) \ |
| 941 | + static inline void vmcs_write_##name(struct vcpu_vmx_data* vcpu_vmx, \ |
| 942 | + COMP_TYPE_##width value) { \ |
| 943 | + vmwrite(vcpu_vmx->parent, name, value); \ |
| 944 | + } |
| 945 | +#define COMP_W_1(width, name) \ |
| 946 | + static inline void vmcs_write_##name(struct vcpu_vmx_data* vcpu_vmx, \ |
| 947 | + COMP_TYPE_##width value) { \ |
| 948 | + vcpu_vmx->vmcs.name##_value = value; \ |
| 949 | + vcpu_vmx->vmcs_cache_r.name##_cache = 1; \ |
| 950 | + vcpu_vmx->vmcs_cache_w.name##_dirty = 1; \ |
| 951 | + } |
| 952 | + |
| 953 | + // Declarations |
| 954 | +#define COMP_R(cache_r, cache_w, width, name) \ |
| 955 | + COMP_R_##cache_r(width, name); |
| 956 | +#define COMP_W(cache_r, cache_w, width, name) \ |
| 957 | + COMP_W_##cache_w(width, name); |
| 958 | + |
| 959 | +// Helper functions |
| 960 | +#define COMP COMP_R |
| 961 | +VMCS_COMPS |
| 962 | +#undef COMP |
| 963 | + |
| 964 | +#define COMP COMP_W |
| 965 | +VMCS_COMPS |
| 966 | +#undef COMP |
| 967 | + |
| 968 | +#define vmcs_read(vcpu, name) \ |
| 969 | + vmcs_read_##name(&vcpu->vmx) |
| 970 | +#define vmcs_write(vcpu, name, value) \ |
| 971 | + vmcs_write_##name(&vcpu->vmx, value) |
| 972 | + |
| 973 | +void vmcs_write_pending(struct vcpu_t *vcpu); |
| 974 | + |
709 | 975 | #define VMREAD_SEG(vcpu, seg, val) \ |
710 | 976 | ((val).selector = vmread(vcpu, GUEST_##seg##_SELECTOR), \ |
711 | 977 | (val).base = vmread(vcpu, GUEST_##seg##_BASE), \ |
|
0 commit comments