RT_C_DECLS_END /** * Save and load our IDT. * * @param pTst Pointer to the instance data. * @param iIDT The index of the IDT entry which should be hooked. */ void idtInstall(PTSTMICRO pTst, int iIDT) { RTIDTR Idtr; ASMGetIDTR(&Idtr); if (Idtr.pIdt == (uintptr_t)&pTst->aIDT[0]) return; pTst->OriginalIDTR.cbIdt = Idtr.cbIdt; pTst->OriginalIDTR.pIdt = Idtr.pIdt; /* * Copy the IDT. */ if (Idtr.cbIdt >= sizeof(pTst->aIDT)) Idtr.cbIdt = sizeof(pTst->aIDT) - 1; memcpy(&pTst->aIDT[0], (void *)Idtr.pIdt, Idtr.cbIdt + 1); /* Hook up IDT entry. */ if (iIDT >= 0) { uintptr_t uHandler = (uintptr_t)tstTrapHandlerNoErr; if ( iIDT == 8 || iIDT == 0xa || iIDT == 0xb || iIDT == 0xc || iIDT == 0xd || iIDT == 0xe || iIDT == 0x11) uHandler = (uintptr_t)tstTrapHandler; pTst->aIDT[iIDT].Int.u16OffsetHigh = uHandler >> 16; pTst->aIDT[iIDT].Int.u16OffsetLow = uHandler & 0xffff; pTst->aIDT[iIDT].Int.u16SegSel = SELMGetHyperCS(&g_VM); pTst->aIDT[iIDT].Int.u2DPL = 3; pTst->aIDT[iIDT].Int.u1Present = 1; pTst->aIDT[iIDT].Int.u1Fixed0 = 0; pTst->aIDT[iIDT].Int.u1Fixed1 = 0; pTst->aIDT[iIDT].Int.u1Fixed2 = 0; pTst->aIDT[iIDT].Int.u1Fixed3 = 0; pTst->aIDT[iIDT].Int.u1Fixed4 = 1; pTst->aIDT[iIDT].Int.u1Fixed5 = 1; pTst->aIDT[iIDT].Int.u132BitGate = 1; pTst->aIDT[iIDT].Int.u1Fixed6 = 0; pTst->aIDT[iIDT].Int.u5Reserved2 = 0; }
/** * Dispatches an interrupt that arrived while we were in the guest context. * * @param pVM The VM handle. * @remark Must be called with interrupts disabled. */ VMMR0DECL(void) TRPMR0DispatchHostInterrupt(PVM pVM) { /* * Get the active interrupt vector number. */ PVMCPU pVCpu = VMMGetCpu0(pVM); RTUINT uActiveVector = pVCpu->trpm.s.uActiveVector; pVCpu->trpm.s.uActiveVector = ~0; AssertMsgReturnVoid(uActiveVector < 256, ("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n", uActiveVector)); #if HC_ARCH_BITS == 64 && defined(RT_OS_DARWIN) /* * Do it the simple and safe way. * * This is a workaround for an optimization bug in the code below * or a gcc 4.2 on mac (snow leopard seed 314). */ trpmR0DispatchHostInterruptSimple(uActiveVector); #else /* The complicated way: */ # ifdef VBOX_WITH_HYBRID_32BIT_KERNEL /* * Check if we're in long mode or not. */ if ( (ASMCpuId_EDX(0x80000001) & X86_CPUID_AMD_FEATURE_EDX_LONG_MODE) && (ASMRdMsr(MSR_K6_EFER) & MSR_K6_EFER_LMA)) { trpmR0DispatchHostInterruptSimple(uActiveVector); return; } # endif /* * Get the handler pointer (16:32 ptr) / (16:48 ptr). */ RTIDTR Idtr; ASMGetIDTR(&Idtr); # if HC_ARCH_BITS == 32 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector]; # else PVBOXIDTE64 pIdte = &((PVBOXIDTE64)Idtr.pIdt)[uActiveVector]; # endif AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector)); AssertMsgReturnVoid( pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1 || pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32, ("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n", uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2)); # if HC_ARCH_BITS == 32 RTFAR32 pfnHandler; pfnHandler.off = VBOXIDTE_OFFSET(*pIdte); pfnHandler.sel = pIdte->Gen.u16SegSel; const RTR0UINTREG uRSP = ~(RTR0UINTREG)0; # else /* 64-bit: */ RTFAR64 pfnHandler; pfnHandler.off = VBOXIDTE64_OFFSET(*pIdte); pfnHandler.sel = pIdte->Gen.u16SegSel; const RTR0UINTREG uRSP = ~(RTR0UINTREG)0; if (pIdte->Gen.u3Ist) { trpmR0DispatchHostInterruptSimple(uActiveVector); return; } # endif /* * Dispatch it. */ trpmR0DispatchHostInterrupt(pfnHandler.off, pfnHandler.sel, uRSP); #endif }