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 <hypervisor/state_invalidator.h> 10 11// clang-format off 12 13#define X86_MSR_IA32_VMX_PINBASED_CTLS 0x0481 14#define X86_MSR_IA32_VMX_PROCBASED_CTLS 0x0482 15#define X86_MSR_IA32_VMX_EXIT_CTLS 0x0483 16#define X86_MSR_IA32_VMX_ENTRY_CTLS 0x0484 17#define X86_MSR_IA32_VMX_PROCBASED_CTLS2 0x048b 18#define X86_MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x048d 19#define X86_MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x048e 20#define X86_MSR_IA32_VMX_TRUE_EXIT_CTLS 0x048f 21#define X86_MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x0490 22 23// PROCBASED_CTLS2 flags. 24static const uint32_t kProcbasedCtls2Ept = 1u << 1; 25static const uint32_t kProcbasedCtls2Rdtscp = 1u << 3; 26static const uint32_t kProcbasedCtls2x2Apic = 1u << 4; 27static const uint32_t kProcbasedCtls2Vpid = 1u << 5; 28static const uint32_t kProcbasedCtls2UnrestrictedGuest = 1u << 7; 29static const uint32_t kProcbasedCtls2Invpcid = 1u << 12; 30 31// PROCBASED_CTLS flags. 32static const uint32_t kProcbasedCtlsIntWindowExiting = 1u << 2; 33static const uint32_t kProcbasedCtlsHltExiting = 1u << 7; 34static const uint32_t kProcbasedCtlsCr3LoadExiting = 1u << 15; 35static const uint32_t kProcbasedCtlsCr3StoreExiting = 1u << 16; 36static const uint32_t kProcbasedCtlsCr8LoadExiting = 1u << 19; 37static const uint32_t kProcbasedCtlsCr8StoreExiting = 1u << 20; 38static const uint32_t kProcbasedCtlsTprShadow = 1u << 21; 39static const uint32_t kProcbasedCtlsIoExiting = 1u << 24; 40static const uint32_t kProcbasedCtlsMsrBitmaps = 1u << 28; 41static const uint32_t kProcbasedCtlsPauseExiting = 1u << 30; 42static const uint32_t kProcbasedCtlsProcbasedCtls2 = 1u << 31; 43 44// PINBASED_CTLS flags. 45static const uint32_t kPinbasedCtlsExtIntExiting = 1u << 0; 46static const uint32_t kPinbasedCtlsNmiExiting = 1u << 3; 47 48// EXIT_CTLS flags. 49static const uint32_t kExitCtls64bitMode = 1u << 9; 50static const uint32_t kExitCtlsAckIntOnExit = 1u << 15; 51static const uint32_t kExitCtlsSaveIa32Pat = 1u << 18; 52static const uint32_t kExitCtlsLoadIa32Pat = 1u << 19; 53static const uint32_t kExitCtlsSaveIa32Efer = 1u << 20; 54static const uint32_t kExitCtlsLoadIa32Efer = 1u << 21; 55 56// ENTRY_CTLS flags. 57static const uint32_t kEntryCtlsIa32eMode = 1u << 9; 58static const uint32_t kEntryCtlsLoadIa32Pat = 1u << 14; 59static const uint32_t kEntryCtlsLoadIa32Efer = 1u << 15; 60 61// LINK_POINTER values. 62static const uint64_t kLinkPointerInvalidate = UINT64_MAX; 63 64// GUEST_XX_ACCESS_RIGHTS flags. 65static const uint32_t kGuestXxAccessRightsUnusable = 1u << 16; 66// See Volume 3, Section 24.4.1 for access rights format. 67static const uint32_t kGuestXxAccessRightsTypeA = 1u << 0; 68static const uint32_t kGuestXxAccessRightsTypeW = 1u << 1; 69static const uint32_t kGuestXxAccessRightsTypeE = 1u << 2; 70static const uint32_t kGuestXxAccessRightsTypeCode = 1u << 3; 71// See Volume 3, Section 3.4.5.1 for valid non-system selector types. 72static const uint32_t kGuestXxAccessRightsS = 1u << 4; 73static const uint32_t kGuestXxAccessRightsP = 1u << 7; 74static const uint32_t kGuestXxAccessRightsL = 1u << 13; 75static const uint32_t kGuestXxAccessRightsD = 1u << 14; 76// See Volume 3, Section 3.5 for valid system selectors types. 77static const uint32_t kGuestTrAccessRightsTssBusy16Bit = 3u << 0; 78static const uint32_t kGuestTrAccessRightsTssBusy = 11u << 0; 79 80static const uint32_t kGuestXxAccessRightsDefault = kGuestXxAccessRightsTypeA | 81 kGuestXxAccessRightsTypeW | 82 kGuestXxAccessRightsS | 83 kGuestXxAccessRightsP; 84 85// GUEST_INTERRUPTIBILITY_STATE flags. 86static const uint32_t kInterruptibilityStiBlocking = 1u << 0; 87static const uint32_t kInterruptibilityMovSsBlocking = 1u << 1; 88 89// VMCS fields. 90enum class VmcsField16 : uint64_t { 91 VPID = 0x0000, 92 GUEST_CS_SELECTOR = 0x0802, 93 GUEST_TR_SELECTOR = 0x080e, 94 HOST_ES_SELECTOR = 0x0c00, 95 HOST_CS_SELECTOR = 0x0c02, 96 HOST_SS_SELECTOR = 0x0c04, 97 HOST_DS_SELECTOR = 0x0c06, 98 HOST_FS_SELECTOR = 0x0c08, 99 HOST_GS_SELECTOR = 0x0c0a, 100 HOST_TR_SELECTOR = 0x0c0c, 101}; 102 103enum class VmcsField64 : uint64_t { 104 MSR_BITMAPS_ADDRESS = 0x2004, 105 EXIT_MSR_STORE_ADDRESS = 0x2006, 106 EXIT_MSR_LOAD_ADDRESS = 0x2008, 107 ENTRY_MSR_LOAD_ADDRESS = 0x200a, 108 EPT_POINTER = 0x201a, 109 GUEST_PHYSICAL_ADDRESS = 0x2400, 110 LINK_POINTER = 0x2800, 111 GUEST_IA32_PAT = 0x2804, 112 GUEST_IA32_EFER = 0x2806, 113 HOST_IA32_PAT = 0x2c00, 114 HOST_IA32_EFER = 0x2c02, 115}; 116 117enum class VmcsField32 : uint64_t { 118 PINBASED_CTLS = 0x4000, 119 PROCBASED_CTLS = 0x4002, 120 EXCEPTION_BITMAP = 0x4004, 121 PAGEFAULT_ERRORCODE_MASK = 0x4006, 122 PAGEFAULT_ERRORCODE_MATCH = 0x4008, 123 EXIT_CTLS = 0x400c, 124 EXIT_MSR_STORE_COUNT = 0x400e, 125 EXIT_MSR_LOAD_COUNT = 0x4010, 126 ENTRY_CTLS = 0x4012, 127 ENTRY_MSR_LOAD_COUNT = 0x4014, 128 ENTRY_INTERRUPTION_INFORMATION = 0x4016, 129 ENTRY_EXCEPTION_ERROR_CODE = 0x4018, 130 PROCBASED_CTLS2 = 0x401e, 131 INSTRUCTION_ERROR = 0x4400, 132 EXIT_REASON = 0x4402, 133 EXIT_INTERRUPTION_INFORMATION = 0x4404, 134 EXIT_INTERRUPTION_ERROR_CODE = 0x4406, 135 EXIT_INSTRUCTION_LENGTH = 0x440c, 136 EXIT_INSTRUCTION_INFORMATION = 0x440e, 137 HOST_IA32_SYSENTER_CS = 0x4c00, 138 139 GUEST_ES_LIMIT = 0x4800, 140 GUEST_CS_LIMIT = 0x4802, 141 GUEST_SS_LIMIT = 0x4804, 142 GUEST_DS_LIMIT = 0x4806, 143 GUEST_FS_LIMIT = 0x4808, 144 GUEST_GS_LIMIT = 0x480a, 145 GUEST_LDTR_LIMIT = 0x480c, 146 GUEST_TR_LIMIT = 0x480e, 147 148 GUEST_GDTR_LIMIT = 0x4810, 149 GUEST_IDTR_LIMIT = 0x4812, 150 GUEST_CS_ACCESS_RIGHTS = 0x4816, 151 GUEST_ES_ACCESS_RIGHTS = 0x4814, 152 GUEST_SS_ACCESS_RIGHTS = 0x4818, 153 GUEST_DS_ACCESS_RIGHTS = 0x481a, 154 GUEST_FS_ACCESS_RIGHTS = 0x481c, 155 GUEST_GS_ACCESS_RIGHTS = 0x481e, 156 GUEST_LDTR_ACCESS_RIGHTS = 0x4820, 157 GUEST_TR_ACCESS_RIGHTS = 0x4822, 158 GUEST_INTERRUPTIBILITY_STATE = 0x4824, 159 GUEST_ACTIVITY_STATE = 0x4826, 160 GUEST_IA32_SYSENTER_CS = 0x482a, 161}; 162 163enum class VmcsFieldXX : uint64_t { 164 CR0_GUEST_HOST_MASK = 0x6000, 165 CR4_GUEST_HOST_MASK = 0x6002, 166 CR0_READ_SHADOW = 0x6004, 167 CR4_READ_SHADOW = 0x6006, 168 EXIT_QUALIFICATION = 0x6400, 169 GUEST_LINEAR_ADDRESS = 0x640a, 170 GUEST_CR0 = 0x6800, 171 GUEST_CR3 = 0x6802, 172 GUEST_CR4 = 0x6804, 173 174 GUEST_ES_BASE = 0x6806, 175 GUEST_CS_BASE = 0x6808, 176 GUEST_SS_BASE = 0x680A, 177 GUEST_DS_BASE = 0x680C, 178 GUEST_FS_BASE = 0x680E, 179 GUEST_GS_BASE = 0x6810, 180 GUEST_TR_BASE = 0x6814, 181 182 GUEST_GDTR_BASE = 0x6816, 183 GUEST_IDTR_BASE = 0x6818, 184 GUEST_RSP = 0x681c, 185 GUEST_RIP = 0x681e, 186 GUEST_RFLAGS = 0x6820, 187 GUEST_PENDING_DEBUG_EXCEPTIONS = 0x6822, 188 GUEST_IA32_SYSENTER_ESP = 0x6824, 189 GUEST_IA32_SYSENTER_EIP = 0x6826, 190 HOST_CR0 = 0x6c00, 191 HOST_CR3 = 0x6c02, 192 HOST_CR4 = 0x6c04, 193 HOST_FS_BASE = 0x6c06, 194 HOST_GS_BASE = 0x6c08, 195 HOST_TR_BASE = 0x6c0a, 196 HOST_GDTR_BASE = 0x6c0c, 197 HOST_IDTR_BASE = 0x6c0e, 198 HOST_IA32_SYSENTER_ESP = 0x6c10, 199 HOST_IA32_SYSENTER_EIP = 0x6c12, 200 HOST_RSP = 0x6c14, 201 HOST_RIP = 0x6c16, 202}; 203 204// INVEPT invalidation types. 205enum class InvEpt : uint64_t { 206 SINGLE_CONTEXT = 1, 207 ALL_CONTEXT = 2, 208}; 209 210// clang-format on 211 212// Loads a VMCS within a given scope. 213class AutoVmcs : public hypervisor::StateInvalidator { 214public: 215 AutoVmcs(paddr_t vmcs_address_); 216 ~AutoVmcs(); 217 218 void Invalidate() override; 219 void InterruptWindowExiting(bool enable); 220 void IssueInterrupt(uint32_t vector); 221 222 uint16_t Read(VmcsField16 field) const; 223 uint32_t Read(VmcsField32 field) const; 224 uint64_t Read(VmcsField64 field) const; 225 uint64_t Read(VmcsFieldXX field) const; 226 void Write(VmcsField16 field, uint16_t val); 227 void Write(VmcsField32 field, uint32_t val); 228 void Write(VmcsField64 field, uint64_t val); 229 void Write(VmcsFieldXX field, uint64_t val); 230 231 zx_status_t SetControl(VmcsField32 controls, uint64_t true_msr, uint64_t old_msr, uint32_t set, 232 uint32_t clear); 233 234private: 235 paddr_t vmcs_address_; 236}; 237 238// Pins execution to a CPU within a given scope. 239class AutoPin { 240public: 241 AutoPin(uint16_t vpid); 242 ~AutoPin(); 243 244private: 245 cpu_mask_t prev_cpu_mask_; 246 thread_t* thread_; 247}; 248 249bool cr0_is_invalid(AutoVmcs* vmcs, uint64_t cr0_value); 250