- Timestamp:
- Feb 28, 2022 8:39:45 AM (3 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r93922 r93964 16460 16460 RT_NOREF4(pVM, pRegFrame, pvFault, uUser); 16461 16461 16462 /** @todo We lack information about such as the current instruction length, IDT 16463 * vectoring info etc. These need to be queried from HMR0. */ 16462 /* 16463 * Handle the VMX APIC-access page only when the guest is in VMX non-root mode. 16464 * Otherwise we must deregister the page and allow regular RAM access. 16465 * Failing to do so lands us with endless EPT misconfiguration VM-exits. 16466 */ 16464 16467 RTGCPHYS const GCPhysAccessBase = GCPhysFault & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK; 16465 16468 if (CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu))) … … 16468 16471 Assert(CPUMGetGuestVmxApicAccessPageAddrEx(IEM_GET_CTX(pVCpu)) == GCPhysAccessBase); 16469 16472 16473 /* 16474 * Check if the access causes an APIC-access VM-exit. 16475 */ 16470 16476 uint32_t fAccess; 16471 16477 if (uErr & X86_TRAP_PF_ID) … … 16480 16486 if (fIntercept) 16481 16487 { 16482 /** @todo Once HMR0 interface for querying VMXTRANSIENT info is available, use 16483 * iemVmxVmexitApicAccessWithInfo instead. This is R0-only code anyway. */ 16484 VBOXSTRICTRC rcStrict = iemVmxVmexitApicAccess(pVCpu, offAccess, fAccess); 16488 /* 16489 * Query the source VM-exit (from the execution engine) that caused this access 16490 * within the APIC-access page. Currently only HM is supported. 16491 */ 16492 AssertMsgReturn(VM_IS_HM_ENABLED(pVM), 16493 ("VM-exit auxiliary info. fetching not supported for execution engine %d\n", 16494 pVM->bMainExecutionEngine), VERR_IEM_ASPECT_NOT_IMPLEMENTED); 16495 HMEXITAUX HmExitAux; 16496 RT_ZERO(HmExitAux); 16497 int const rc = HMR0GetExitAuxInfo(pVCpu, &HmExitAux, HMVMX_READ_EXIT_INSTR_LEN 16498 | HMVMX_READ_EXIT_QUALIFICATION 16499 | HMVMX_READ_IDT_VECTORING_INFO 16500 | HMVMX_READ_IDT_VECTORING_ERROR_CODE); 16501 AssertRCReturn(rc, rc); 16502 16503 /* 16504 * Verify the VM-exit reason must be an EPT violation. 16505 * Other accesses should go through the other handler (iemVmxApicAccessPageHandler). 16506 */ 16507 AssertLogRelMsgReturn(HmExitAux.Vmx.uReason == VMX_EXIT_EPT_VIOLATION, 16508 ("Unexpected call to the VMX APIC-access page #PF handler for %#RGp (off=%u) uReason=%#RX32\n", 16509 GCPhysAccessBase, offAccess, HmExitAux.Vmx.uReason), VERR_IEM_IPE_9); 16510 16511 /* 16512 * Construct the virtual APIC-access VM-exit. 16513 */ 16514 VMXAPICACCESS enmAccess; 16515 if (HmExitAux.Vmx.u64Qual & VMX_EXIT_QUAL_EPT_LINEAR_ADDR_VALID) 16516 { 16517 if (VMX_IDT_VECTORING_INFO_IS_VALID(HmExitAux.Vmx.uIdtVectoringInfo)) 16518 enmAccess = VMXAPICACCESS_LINEAR_EVENT_DELIVERY; 16519 else if (fAccess == IEM_ACCESS_INSTRUCTION) 16520 enmAccess = VMXAPICACCESS_LINEAR_INSTR_FETCH; 16521 else if (fAccess & IEM_ACCESS_TYPE_WRITE) 16522 enmAccess = VMXAPICACCESS_LINEAR_WRITE; 16523 else 16524 enmAccess = VMXAPICACCESS_LINEAR_READ; 16525 } 16526 else 16527 { 16528 if (VMX_IDT_VECTORING_INFO_IS_VALID(HmExitAux.Vmx.uIdtVectoringInfo)) 16529 enmAccess = VMXAPICACCESS_PHYSICAL_EVENT_DELIVERY; 16530 else 16531 { 16532 /** @todo How to distinguish between monitoring/trace vs other instructions 16533 * here? */ 16534 enmAccess = VMXAPICACCESS_PHYSICAL_INSTR; 16535 } 16536 } 16537 16538 VMXVEXITINFO ExitInfo; 16539 RT_ZERO(ExitInfo); 16540 ExitInfo.uReason = VMX_EXIT_APIC_ACCESS; 16541 ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_APIC_ACCESS_OFFSET, offAccess) 16542 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_APIC_ACCESS_TYPE, enmAccess); 16543 ExitInfo.cbInstr = HmExitAux.Vmx.cbInstr; 16544 16545 VMXVEXITEVENTINFO ExitEventInfo; 16546 RT_ZERO(ExitEventInfo); 16547 ExitEventInfo.uIdtVectoringInfo = HmExitAux.Vmx.uIdtVectoringInfo; 16548 ExitEventInfo.uIdtVectoringErrCode = HmExitAux.Vmx.uIdtVectoringErrCode; 16549 16550 /* 16551 * Raise the APIC-access VM-exit. 16552 */ 16553 VBOXSTRICTRC rcStrict = iemVmxVmexitApicAccessWithInfo(pVCpu, &ExitInfo, &ExitEventInfo); 16485 16554 return iemExecStatusCodeFiddling(pVCpu, rcStrict); 16486 16555 } 16487 16556 16488 /* The access isn't intercepted, which means it needs to be virtualized. */ 16557 /* 16558 * The access isn't intercepted, which means it needs to be virtualized. 16559 * 16560 * This requires emulating the instruction because we need the bytes being 16561 * read/written by the instruction not just the offset being accessed within 16562 * the APIC-access (which we derive from the faulting address). 16563 */ 16489 16564 return VINF_EM_RAW_EMULATE_INSTR; 16490 16565 }
Note:
See TracChangeset
for help on using the changeset viewer.

