Changeset 74005 in vbox
- Timestamp:
- Aug 31, 2018 5:23:00 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/hm_vmx.h
r73984 r74005 839 839 /** Plain unsigned int representation. */ 840 840 uint32_t u; 841 841 842 /** INS and OUTS information. */ 842 843 struct … … 850 851 uint32_t uReserved2 : 14; 851 852 } StrIo; 853 852 854 struct 853 855 { … … 873 875 uint32_t iReg2 : 4; 874 876 } Inv; 877 875 878 /** VMCLEAR, VMPTRLD, VMPTRST, VMXON, XRSTORS, XSAVES information. */ 876 879 struct … … 897 900 uint32_t iReg2 : 4; 898 901 } VmxXsave; 902 899 903 /** LIDT, LGDT, SIDT, SGDT information. */ 900 904 struct … … 924 928 uint32_t u2Undef0 : 2; 925 929 } GdtIdt; 930 926 931 /** LLDT, LTR, SLDT, STR information. */ 927 932 struct … … 951 956 uint32_t u2Undef0 : 2; 952 957 } LdtTr; 958 953 959 /** RDRAND, RDSEED information. */ 954 960 struct … … 963 969 uint32_t u19Def0 : 20; 964 970 } RdrandRdseed; 971 965 972 struct 966 973 { … … 989 996 uint32_t iReg2 : 4; 990 997 } VmreadVmwrite; 998 991 999 /** This is a combination field of all instruction information. Note! Not all field 992 * combinations are valid (e.g., iReg1 is undefined for memory operands). */ 1000 * combinations are valid (e.g., iReg1 is undefined for memory operands) and 1001 * specialized fields are overwritten by their generic counterparts (e.g. no 1002 * instruction identity field). */ 993 1003 struct 994 1004 { -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r73998 r74005 205 205 } \ 206 206 } while (0) 207 208 /** Macro that decodes a memory operand for an instruction VM-exit. */ 209 # define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \ 210 do \ 211 { \ 212 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \ 213 (a_pGCPtrEffAddr)); \ 214 if (rcStrictTmp == VINF_SUCCESS) \ 215 { /* likely */ } \ 216 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \ 217 { \ 218 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \ 219 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \ 220 return VINF_SUCCESS; \ 221 } \ 222 else \ 223 { \ 224 Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \ 225 return rcStrictTmp; \ 226 } \ 227 } while (0) 228 207 229 #endif /* VBOX_WITH_NESTED_HWVIRT_VMX */ 208 230 … … 285 307 typedef VMXTRANSIENT *PVMXTRANSIENT; 286 308 287 288 309 /** 289 310 * MSR-bitmap read permissions. … … 312 333 typedef VMXMSREXITWRITE* PVMXMSREXITWRITE; 313 334 335 /** 336 * Memory operand read or write access. 337 */ 338 typedef enum VMXMEMACCESS 339 { 340 VMXMEMACCESS_READ = 0, 341 VMXMEMACCESS_WRITE = 1 342 } VMXMEMACCESS; 314 343 315 344 /** … … 368 397 # define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL 369 398 #endif 370 371 399 372 400 /** @name VM-exit handlers. … … 5878 5906 * operand. 5879 5907 * @param pVCpu The cross context virtual CPU structure. 5880 * @param pExitInstrInfo Pointer to the VM-exit instruction information. 5881 * @param fIsDstOperand Whether the operand is a destination memory 5882 * operand (i.e. writeable memory location) or not. 5908 * @param uExitInstrInfo The VM-exit instruction information field. 5909 * @param enmMemAccess The memory operand's access type (read or write). 5883 5910 * @param GCPtrDisp The instruction displacement field, if any. For 5884 5911 * RIP-relative addressing pass RIP + displacement here. 5885 5912 * @param pGCPtrMem Where to store the effective destination memory address. 5886 5913 */ 5887 static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, PCVMXEXITINSTRINFO pExitInstrInfo, RTGCPTR GCPtrDisp, 5888 bool fIsDstOperand, PRTGCPTR pGCPtrMem) 5889 { 5890 Assert(pExitInstrInfo); 5914 static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess, 5915 PRTGCPTR pGCPtrMem) 5916 { 5891 5917 Assert(pGCPtrMem); 5892 5918 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu)); … … 5897 5923 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks)); 5898 5924 5899 uint8_t const uAddrSize = pExitInstrInfo->All.u3AddrSize; 5900 uint8_t const iSegReg = pExitInstrInfo->All.iSegReg; 5901 bool const fIdxRegValid = !pExitInstrInfo->All.fIdxRegInvalid; 5902 uint8_t const iIdxReg = pExitInstrInfo->All.iIdxReg; 5903 uint8_t const uScale = pExitInstrInfo->All.u2Scaling; 5904 bool const fBaseRegValid = !pExitInstrInfo->All.fBaseRegInvalid; 5905 uint8_t const iBaseReg = pExitInstrInfo->All.iBaseReg; 5906 bool const fIsMemOperand = !pExitInstrInfo->All.fIsRegOperand; 5925 VMXEXITINSTRINFO ExitInstrInfo; 5926 ExitInstrInfo.u = uExitInstrInfo; 5927 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize; 5928 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg; 5929 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid; 5930 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg; 5931 uint8_t const uScale = ExitInstrInfo.All.u2Scaling; 5932 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid; 5933 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg; 5934 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand; 5907 5935 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx); 5908 5936 … … 5912 5940 */ 5913 5941 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks), 5914 ("Invalid address size. ExitInstrInfo=%#RX32\n", pExitInstrInfo->u), VERR_VMX_IPE_1);5942 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1); 5915 5943 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT, 5916 ("Invalid segment register. ExitInstrInfo=%#RX32\n", pExitInstrInfo->u), VERR_VMX_IPE_2);5944 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2); 5917 5945 AssertLogRelMsgReturn(fIsMemOperand, 5918 ("Expected memory operand. ExitInstrInfo=%#RX32\n", pExitInstrInfo->u), VERR_VMX_IPE_3);5946 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3); 5919 5947 5920 5948 /* … … 5974 6002 { 5975 6003 /* Check permissions for the data segment. */ 5976 if ( fIsDstOperand6004 if ( enmMemAccess == VMXMEMACCESS_WRITE 5977 6005 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE)) 5978 6006 { … … 6019 6047 { 6020 6048 /* Check permissions for the code segment. */ 6021 if ( fIsDstOperand 6022 || !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)) 6049 if ( enmMemAccess == VMXMEMACCESS_WRITE 6050 || ( enmMemAccess == VMXMEMACCESS_READ 6051 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ))) 6023 6052 { 6024 6053 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u)); … … 13432 13461 ExitInfo.cbInstr = pVmxTransient->cbInstr; 13433 13462 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand) 13434 { 13435 RTGCPTR GCPtrVal; 13436 VBOXSTRICTRC rcStrict = hmR0VmxDecodeMemOperand(pVCpu, &ExitInfo.InstrInfo, ExitInfo.u64Qual, false /* fIsDstOperand */, 13437 &GCPtrVal); 13438 if (rcStrict == VINF_SUCCESS) 13439 { /* likely */ } 13440 else if (rcStrict == VINF_HM_PENDING_XCPT) 13441 { 13442 Assert(pVCpu->hm.s.Event.fPending); 13443 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", 13444 VMX_ENTRY_INT_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo))); 13445 return VINF_SUCCESS; 13446 } 13447 else 13448 { 13449 Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 13450 return rcStrict; 13451 } 13452 ExitInfo.GCPtrEffAddr = GCPtrVal; 13453 } 13463 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr); 13454 13464 13455 13465 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo); … … 13501 13511 ExitInfo.cbInstr = pVmxTransient->cbInstr; 13502 13512 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand) 13503 { 13504 RTGCPTR GCPtrVal; 13505 VBOXSTRICTRC rcStrict = hmR0VmxDecodeMemOperand(pVCpu, &ExitInfo.InstrInfo, ExitInfo.u64Qual, false /* fIsDstOperand */, 13506 &GCPtrVal); 13507 if (rcStrict == VINF_SUCCESS) 13508 { /* likely */ } 13509 else if (rcStrict == VINF_HM_PENDING_XCPT) 13510 { 13511 Assert(pVCpu->hm.s.Event.fPending); 13512 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", 13513 VMX_ENTRY_INT_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo))); 13514 return VINF_SUCCESS; 13515 } 13516 else 13517 { 13518 Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 13519 return rcStrict; 13520 } 13521 ExitInfo.GCPtrEffAddr = GCPtrVal; 13522 } 13513 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr); 13523 13514 13524 13515 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo); … … 13584 13575 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u; 13585 13576 ExitInfo.cbInstr = pVmxTransient->cbInstr; 13586 13587 RTGCPTR GCPtrVmxon; 13588 VBOXSTRICTRC rcStrict = hmR0VmxDecodeMemOperand(pVCpu, &ExitInfo.InstrInfo, ExitInfo.u64Qual, false /* fIsDstOperand */, 13589 &GCPtrVmxon); 13590 if (rcStrict == VINF_SUCCESS) 13591 { /* likely */ } 13592 else if (rcStrict == VINF_HM_PENDING_XCPT) 13593 { 13594 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", VMX_ENTRY_INT_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo))); 13595 return VINF_SUCCESS; 13596 } 13597 else 13598 { 13599 Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 13600 return rcStrict; 13601 } 13602 ExitInfo.GCPtrEffAddr = GCPtrVmxon; 13603 13604 rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo); 13577 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr); 13578 13579 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo); 13605 13580 if (RT_LIKELY(rcStrict == VINF_SUCCESS)) 13606 13581 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
Note:
See TracChangeset
for help on using the changeset viewer.