| // Copyright 2017 The Fuchsia Authors |
| // |
| // Use of this source code is governed by a MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT |
| |
| #pragma once |
| |
| #include <hypervisor/packet_mux.h> |
| |
| // clang-format off |
| |
| #define X86_MSR_IA32_VMX_PINBASED_CTLS 0x0481 // Pin-based controls |
| #define X86_MSR_IA32_VMX_PROCBASED_CTLS 0x0482 // Primary processor-based controls |
| #define X86_MSR_IA32_VMX_EXIT_CTLS 0x0483 // VM-exit controls |
| #define X86_MSR_IA32_VMX_ENTRY_CTLS 0x0484 // VM-entry controls |
| #define X86_MSR_IA32_VMX_PROCBASED_CTLS2 0x048b // Secondary processor-based controls |
| #define X86_MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x048d // True pin-based controls |
| #define X86_MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x048e // True primary processor-based controls |
| #define X86_MSR_IA32_VMX_TRUE_EXIT_CTLS 0x048f // True VM-exit controls |
| #define X86_MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x0490 // True VM-entry controls |
| |
| /* PROCBASED_CTLS2 flags */ |
| #define PROCBASED_CTLS2_APIC_ACCESS (1u << 0) |
| #define PROCBASED_CTLS2_EPT (1u << 1) |
| #define PROCBASED_CTLS2_RDTSCP (1u << 3) |
| #define PROCBASED_CTLS2_VPID (1u << 5) |
| #define PROCBASED_CTLS2_INVPCID (1u << 12) |
| |
| /* PROCBASED_CTLS flags */ |
| #define PROCBASED_CTLS_INT_WINDOW_EXITING (1u << 2) |
| #define PROCBASED_CTLS_HLT_EXITING (1u << 7) |
| #define PROCBASED_CTLS_CR3_LOAD_EXITING (1u << 15) |
| #define PROCBASED_CTLS_CR3_STORE_EXITING (1u << 16) |
| #define PROCBASED_CTLS_CR8_LOAD_EXITING (1u << 19) |
| #define PROCBASED_CTLS_CR8_STORE_EXITING (1u << 20) |
| #define PROCBASED_CTLS_TPR_SHADOW (1u << 21) |
| #define PROCBASED_CTLS_IO_EXITING (1u << 24) |
| #define PROCBASED_CTLS_MSR_BITMAPS (1u << 28) |
| #define PROCBASED_CTLS_PROCBASED_CTLS2 (1u << 31) |
| |
| /* PINBASED_CTLS flags */ |
| #define PINBASED_CTLS_EXT_INT_EXITING (1u << 0) |
| #define PINBASED_CTLS_NMI_EXITING (1u << 3) |
| |
| /* EXIT_CTLS flags */ |
| #define EXIT_CTLS_64BIT_MODE (1u << 9) |
| #define EXIT_CTLS_SAVE_IA32_PAT (1u << 18) |
| #define EXIT_CTLS_LOAD_IA32_PAT (1u << 19) |
| #define EXIT_CTLS_SAVE_IA32_EFER (1u << 20) |
| #define EXIT_CTLS_LOAD_IA32_EFER (1u << 21) |
| |
| /* ENTRY_CTLS flags */ |
| #define ENTRY_CTLS_IA32E_MODE (1u << 9) |
| #define ENTRY_CTLS_LOAD_IA32_PAT (1u << 14) |
| #define ENTRY_CTLS_LOAD_IA32_EFER (1u << 15) |
| |
| /* LINK_POINTER values */ |
| #define LINK_POINTER_INVALIDATE UINT64_MAX |
| |
| /* GUEST_XX_ACCESS_RIGHTS flags */ |
| #define GUEST_XX_ACCESS_RIGHTS_UNUSABLE (1u << 16) |
| // See Volume 3, Section 24.4.1 for access rights format. |
| #define GUEST_XX_ACCESS_RIGHTS_TYPE_A (1u << 0) |
| #define GUEST_XX_ACCESS_RIGHTS_TYPE_W (1u << 1) |
| #define GUEST_XX_ACCESS_RIGHTS_TYPE_E (1u << 2) |
| #define GUEST_XX_ACCESS_RIGHTS_TYPE_CODE (1u << 3) |
| // See Volume 3, Section 3.4.5.1 for valid non-system selector types. |
| #define GUEST_XX_ACCESS_RIGHTS_S (1u << 4) |
| #define GUEST_XX_ACCESS_RIGHTS_P (1u << 7) |
| #define GUEST_XX_ACCESS_RIGHTS_L (1u << 13) |
| // See Volume 3, Section 3.5 for valid system selectors types. |
| #define GUEST_TR_ACCESS_RIGHTS_TSS_BUSY (11u << 0) |
| |
| /* VMCS fields */ |
| enum class VmcsField16 : uint64_t { |
| VPID = 0x0000, // Virtual processor ID |
| GUEST_CS_SELECTOR = 0x0802, // Guest CS selector |
| GUEST_TR_SELECTOR = 0x080e, // Guest TR selector |
| HOST_ES_SELECTOR = 0x0c00, // Host ES selector |
| HOST_CS_SELECTOR = 0x0c02, // Host CS selector |
| HOST_SS_SELECTOR = 0x0c04, // Host SS selector |
| HOST_DS_SELECTOR = 0x0c06, // Host DS selector |
| HOST_FS_SELECTOR = 0x0c08, // Host FS selector |
| HOST_GS_SELECTOR = 0x0c0a, // Host GS selector |
| HOST_TR_SELECTOR = 0x0c0c, // Host TR selector |
| }; |
| |
| enum class VmcsField64 : uint64_t { |
| MSR_BITMAPS_ADDRESS = 0x2004, // Address of MSR bitmaps |
| EXIT_MSR_STORE_ADDRESS = 0x2006, // VM-exit MSR-store address |
| EXIT_MSR_LOAD_ADDRESS = 0x2008, // VM-exit MSR-load address |
| ENTRY_MSR_LOAD_ADDRESS = 0x200a, // VM-entry MSR-load address |
| VIRTUAL_APIC_ADDRESS = 0x2012, // Virtual-APIC address |
| APIC_ACCESS_ADDRESS = 0x2014, // APIC-access address |
| EPT_POINTER = 0x201a, // EPT pointer |
| GUEST_PHYSICAL_ADDRESS = 0x2400, // Guest physical address |
| LINK_POINTER = 0x2800, // VMCS link pointer |
| GUEST_IA32_PAT = 0x2804, // Guest PAT |
| GUEST_IA32_EFER = 0x2806, // Guest EFER |
| HOST_IA32_PAT = 0x2c00, // Host PAT |
| HOST_IA32_EFER = 0x2c02, // Host EFER |
| }; |
| |
| enum class VmcsField32 : uint64_t { |
| PINBASED_CTLS = 0x4000, // Pin-based controls |
| PROCBASED_CTLS = 0x4002, // Primary processor-based controls |
| EXCEPTION_BITMAP = 0x4004, // Exception bitmap |
| PAGEFAULT_ERRORCODE_MASK = 0x4006, // Page-fault error-code mask |
| PAGEFAULT_ERRORCODE_MATCH = 0x4008, // Page-fault error-code match |
| EXIT_CTLS = 0x400c, // VM-exit controls |
| EXIT_MSR_STORE_COUNT = 0x400e, // VM-exit MSR-store count |
| EXIT_MSR_LOAD_COUNT = 0x4010, // VM-exit MSR-load count |
| ENTRY_CTLS = 0x4012, // VM-entry controls |
| ENTRY_MSR_LOAD_COUNT = 0x4014, // VM-entry MSR-load count |
| ENTRY_INTERRUPTION_INFORMATION = 0x4016, // VM-entry interruption-information field |
| ENTRY_EXCEPTION_ERROR_CODE = 0x4018, // VM-entry exception error code |
| PROCBASED_CTLS2 = 0x401e, // Secondary processor-based controls |
| INSTRUCTION_ERROR = 0x4400, // VM instruction error |
| EXIT_REASON = 0x4402, // Exit reason |
| EXIT_INTERRUPTION_INFORMATION = 0x4404, // VM-exit interruption information |
| EXIT_INTERRUPTION_ERROR_CODE = 0x4406, // VM-exit interruption error code |
| EXIT_INSTRUCTION_LENGTH = 0x440c, // VM-exit instruction length |
| EXIT_INSTRUCTION_INFORMATION = 0x440e, // VM-exit instruction information |
| HOST_IA32_SYSENTER_CS = 0x4c00, // Host SYSENTER CS |
| GUEST_GDTR_LIMIT = 0x4810, // Guest GDTR Limit |
| GUEST_IDTR_LIMIT = 0x4812, // Guest IDTR Limit |
| GUEST_CS_ACCESS_RIGHTS = 0x4816, // Guest CS Access Rights |
| GUEST_ES_ACCESS_RIGHTS = 0x4814, // Guest ES Access Rights |
| GUEST_SS_ACCESS_RIGHTS = 0x4818, // Guest SS Access Rights |
| GUEST_DS_ACCESS_RIGHTS = 0x481a, // Guest DS Access Rights |
| GUEST_FS_ACCESS_RIGHTS = 0x481c, // Guest FS Access Rights |
| GUEST_GS_ACCESS_RIGHTS = 0x481e, // Guest GS Access Rights |
| GUEST_LDTR_ACCESS_RIGHTS = 0x4820, // Guest LDTR Access Rights |
| GUEST_TR_ACCESS_RIGHTS = 0x4822, // Guest TR Access Rights |
| GUEST_INTERRUPTIBILITY_STATE = 0x4824, // Guest interruptibility state |
| GUEST_ACTIVITY_STATE = 0x4826, // Guest activity state |
| GUEST_IA32_SYSENTER_CS = 0x482a, // Guest SYSENTER CS |
| }; |
| |
| enum class VmcsFieldXX : uint64_t { |
| CR4_GUEST_HOST_MASK = 0x6002, // CR4 guest/host mask |
| CR4_READ_SHADOW = 0x6006, // CR4 read shadow |
| EXIT_QUALIFICATION = 0x6400, // Exit qualification |
| GUEST_LINEAR_ADDRESS = 0x640a, // Guest linear address |
| GUEST_CR0 = 0x6800, // Guest CR0 |
| GUEST_CR3 = 0x6802, // Guest CR3 |
| GUEST_CR4 = 0x6804, // Guest CR4 |
| GUEST_GDTR_BASE = 0x6816, // Guest GDTR base |
| GUEST_IDTR_BASE = 0x6818, // Guest IDTR base |
| GUEST_RSP = 0x681c, // Guest RSP |
| GUEST_RIP = 0x681e, // Guest RIP |
| GUEST_RFLAGS = 0x6820, // Guest RFLAGS |
| GUEST_PENDING_DEBUG_EXCEPTIONS = 0x6822, // Guest pending debug exceptions |
| GUEST_IA32_SYSENTER_ESP = 0x6824, // Guest SYSENTER ESP |
| GUEST_IA32_SYSENTER_EIP = 0x6826, // Guest SYSENTER EIP |
| HOST_CR0 = 0x6c00, // Host CR0 |
| HOST_CR3 = 0x6c02, // Host CR3 |
| HOST_CR4 = 0x6c04, // Host CR4 |
| HOST_FS_BASE = 0x6c06, // Host FS base |
| HOST_GS_BASE = 0x6c08, // Host GS base |
| HOST_TR_BASE = 0x6c0a, // Host TR base |
| HOST_GDTR_BASE = 0x6c0c, // Host GDTR base |
| HOST_IDTR_BASE = 0x6c0e, // Host IDTR base |
| HOST_IA32_SYSENTER_ESP = 0x6c10, // Host SYSENTER ESP |
| HOST_IA32_SYSENTER_EIP = 0x6c12, // Host SYSENTER EIP |
| HOST_RSP = 0x6c14, // Host RSP |
| HOST_RIP = 0x6c16, // Host RIP |
| }; |
| |
| // clang-format on |
| |
| class Vcpu; |
| |
| /* Loads a VMCS within a given scope. */ |
| class AutoVmcs : public StateReloader { |
| public: |
| AutoVmcs(const paddr_t vmcs_address_); |
| ~AutoVmcs(); |
| |
| void Reload() override; |
| void InterruptibleReload(); |
| void InterruptWindowExiting(bool enable); |
| void IssueInterrupt(uint32_t vector); |
| |
| uint16_t Read(VmcsField16 field) const; |
| uint32_t Read(VmcsField32 field) const; |
| uint64_t Read(VmcsField64 field) const; |
| uint64_t Read(VmcsFieldXX field) const; |
| void Write(VmcsField16 field, uint16_t val); |
| void Write(VmcsField32 field, uint32_t val); |
| void Write(VmcsField64 field, uint64_t val); |
| void Write(VmcsFieldXX field, uint64_t val); |
| |
| mx_status_t SetControl(VmcsField32 controls, uint64_t true_msr, uint64_t old_msr, uint32_t set, |
| uint32_t clear); |
| |
| private: |
| const paddr_t vmcs_address_; |
| }; |
| |
| /* Pins execution to a CPU within a given scope. */ |
| class AutoPin { |
| public: |
| AutoPin(const Vcpu* vcpu); |
| ~AutoPin(); |
| |
| private: |
| thread_t* thread_; |
| int prev_cpu_; |
| }; |