diff options
Diffstat (limited to 'src/VBox/VMM/VMMR3/TRPM.cpp')
| -rw-r--r-- | src/VBox/VMM/VMMR3/TRPM.cpp | 295 |
1 files changed, 144 insertions, 151 deletions
diff --git a/src/VBox/VMM/VMMR3/TRPM.cpp b/src/VBox/VMM/VMMR3/TRPM.cpp index c87ea4c2..656f215e 100644 --- a/src/VBox/VMM/VMMR3/TRPM.cpp +++ b/src/VBox/VMM/VMMR3/TRPM.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -92,7 +92,7 @@ #ifdef VBOX_WITH_REM # include <VBox/vmm/rem.h> #endif -#include <VBox/vmm/hwaccm.h> +#include <VBox/vmm/hm.h> #include <VBox/err.h> #include <VBox/param.h> @@ -423,11 +423,12 @@ static VBOXIDTE_GENERIC g_aIdt[256] = }; +#ifdef VBOX_WITH_RAW_MODE /** Enable or disable tracking of Guest's IDT. */ -#define TRPM_TRACK_GUEST_IDT_CHANGES - +# define TRPM_TRACK_GUEST_IDT_CHANGES /** Enable or disable tracking of Shadow IDT. */ -#define TRPM_TRACK_SHADOW_IDT_CHANGES +# define TRPM_TRACK_SHADOW_IDT_CHANGES +#endif /** TRPM saved state version. */ #define TRPM_SAVED_STATE_VERSION 9 @@ -439,7 +440,9 @@ static VBOXIDTE_GENERIC g_aIdt[256] = *******************************************************************************/ static DECLCALLBACK(int) trpmR3Save(PVM pVM, PSSMHANDLE pSSM); static DECLCALLBACK(int) trpmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); +#ifdef TRPM_TRACK_GUEST_IDT_CHANGES static DECLCALLBACK(int) trpmR3GuestIDTWriteHandler(PVM pVM, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser); +#endif /** @@ -472,12 +475,11 @@ VMMR3DECL(int) TRPMR3Init(PVM pVM) pVCpu->trpm.s.offVM = RT_OFFSETOF(VM, aCpus[i].trpm); pVCpu->trpm.s.offVMCpu = RT_OFFSETOF(VMCPU, trpm); - pVCpu->trpm.s.uActiveVector = ~0; + pVCpu->trpm.s.uActiveVector = ~0U; } pVM->trpm.s.GuestIdtr.pIdt = RTRCPTR_MAX; - pVM->trpm.s.pvMonShwIdtRC = RTRCPTR_MAX; - pVM->trpm.s.fDisableMonitoring = false; + pVM->trpm.s.pvMonShwIdtRC = RTRCPTR_MAX; pVM->trpm.s.fSafeToDropGuestIDTMonitoring = false; /* @@ -516,65 +518,83 @@ VMMR3DECL(int) TRPMR3Init(PVM pVM) /* * Statistics. */ - STAM_REG(pVM, &pVM->trpm.s.StatRCWriteGuestIDTFault, STAMTYPE_COUNTER, "/TRPM/RC/IDTWritesFault", STAMUNIT_OCCURENCES, "Guest IDT writes the we returned to R3 to handle."); - STAM_REG(pVM, &pVM->trpm.s.StatRCWriteGuestIDTHandled, STAMTYPE_COUNTER, "/TRPM/RC/IDTWritesHandled", STAMUNIT_OCCURENCES, "Guest IDT writes that we handled successfully."); - STAM_REG(pVM, &pVM->trpm.s.StatSyncIDT, STAMTYPE_PROFILE, "/PROF/TRPM/SyncIDT", STAMUNIT_TICKS_PER_CALL, "Profiling of TRPMR3SyncIDT()."); - - /* traps */ - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x00], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/00", STAMUNIT_TICKS_PER_CALL, "#DE - Divide error."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x01], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/01", STAMUNIT_TICKS_PER_CALL, "#DB - Debug (single step and more)."); - //STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x02], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/02", STAMUNIT_TICKS_PER_CALL, "NMI"); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x03], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/03", STAMUNIT_TICKS_PER_CALL, "#BP - Breakpoint."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x04], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/04", STAMUNIT_TICKS_PER_CALL, "#OF - Overflow."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x05], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/05", STAMUNIT_TICKS_PER_CALL, "#BR - Bound range exceeded."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x06], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/06", STAMUNIT_TICKS_PER_CALL, "#UD - Undefined opcode."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x07], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/07", STAMUNIT_TICKS_PER_CALL, "#NM - Device not available (FPU)."); - //STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x08], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/08", STAMUNIT_TICKS_PER_CALL, "#DF - Double fault."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x09], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/09", STAMUNIT_TICKS_PER_CALL, "#?? - Coprocessor segment overrun (obsolete)."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0a], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0a", STAMUNIT_TICKS_PER_CALL, "#TS - Task switch fault."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0b], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0b", STAMUNIT_TICKS_PER_CALL, "#NP - Segment not present."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0c], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0c", STAMUNIT_TICKS_PER_CALL, "#SS - Stack segment fault."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0d], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0d", STAMUNIT_TICKS_PER_CALL, "#GP - General protection fault."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0e], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0e", STAMUNIT_TICKS_PER_CALL, "#PF - Page fault."); - //STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0f], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0f", STAMUNIT_TICKS_PER_CALL, "Reserved."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x10], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/10", STAMUNIT_TICKS_PER_CALL, "#MF - Math fault.."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x11], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/11", STAMUNIT_TICKS_PER_CALL, "#AC - Alignment check."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x12], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/12", STAMUNIT_TICKS_PER_CALL, "#MC - Machine check."); - STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x13], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/13", STAMUNIT_TICKS_PER_CALL, "#XF - SIMD Floating-Point Exception."); - -#ifdef VBOX_WITH_STATISTICS +#ifdef VBOX_WITH_RAW_MODE + if (!HMIsEnabled(pVM)) + { + STAM_REG(pVM, &pVM->trpm.s.StatRCWriteGuestIDTFault, STAMTYPE_COUNTER, "/TRPM/RC/IDTWritesFault", STAMUNIT_OCCURENCES, "Guest IDT writes the we returned to R3 to handle."); + STAM_REG(pVM, &pVM->trpm.s.StatRCWriteGuestIDTHandled, STAMTYPE_COUNTER, "/TRPM/RC/IDTWritesHandled", STAMUNIT_OCCURENCES, "Guest IDT writes that we handled successfully."); + STAM_REG(pVM, &pVM->trpm.s.StatSyncIDT, STAMTYPE_PROFILE, "/PROF/TRPM/SyncIDT", STAMUNIT_TICKS_PER_CALL, "Profiling of TRPMR3SyncIDT()."); + + /* traps */ + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x00], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/00", STAMUNIT_TICKS_PER_CALL, "#DE - Divide error."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x01], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/01", STAMUNIT_TICKS_PER_CALL, "#DB - Debug (single step and more)."); + //STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x02], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/02", STAMUNIT_TICKS_PER_CALL, "NMI"); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x03], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/03", STAMUNIT_TICKS_PER_CALL, "#BP - Breakpoint."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x04], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/04", STAMUNIT_TICKS_PER_CALL, "#OF - Overflow."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x05], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/05", STAMUNIT_TICKS_PER_CALL, "#BR - Bound range exceeded."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x06], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/06", STAMUNIT_TICKS_PER_CALL, "#UD - Undefined opcode."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x07], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/07", STAMUNIT_TICKS_PER_CALL, "#NM - Device not available (FPU)."); + //STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x08], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/08", STAMUNIT_TICKS_PER_CALL, "#DF - Double fault."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x09], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/09", STAMUNIT_TICKS_PER_CALL, "#?? - Coprocessor segment overrun (obsolete)."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0a], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0a", STAMUNIT_TICKS_PER_CALL, "#TS - Task switch fault."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0b], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0b", STAMUNIT_TICKS_PER_CALL, "#NP - Segment not present."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0c], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0c", STAMUNIT_TICKS_PER_CALL, "#SS - Stack segment fault."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0d], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0d", STAMUNIT_TICKS_PER_CALL, "#GP - General protection fault."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0e], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0e", STAMUNIT_TICKS_PER_CALL, "#PF - Page fault."); + //STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x0f], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/0f", STAMUNIT_TICKS_PER_CALL, "Reserved."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x10], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/10", STAMUNIT_TICKS_PER_CALL, "#MF - Math fault.."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x11], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/11", STAMUNIT_TICKS_PER_CALL, "#AC - Alignment check."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x12], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/12", STAMUNIT_TICKS_PER_CALL, "#MC - Machine check."); + STAM_REG(pVM, &pVM->trpm.s.aStatGCTraps[0x13], STAMTYPE_PROFILE_ADV, "/TRPM/GC/Traps/13", STAMUNIT_TICKS_PER_CALL, "#XF - SIMD Floating-Point Exception."); + } +#endif + +# ifdef VBOX_WITH_STATISTICS rc = MMHyperAlloc(pVM, sizeof(STAMCOUNTER) * 256, sizeof(STAMCOUNTER), MM_TAG_TRPM, (void **)&pVM->trpm.s.paStatForwardedIRQR3); AssertRCReturn(rc, rc); pVM->trpm.s.paStatForwardedIRQRC = MMHyperR3ToRC(pVM, pVM->trpm.s.paStatForwardedIRQR3); - pVM->trpm.s.paStatForwardedIRQR0 = MMHyperR3ToR0(pVM, pVM->trpm.s.paStatForwardedIRQR3); for (unsigned i = 0; i < 256; i++) STAMR3RegisterF(pVM, &pVM->trpm.s.paStatForwardedIRQR3[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, "Forwarded interrupts.", i < 0x20 ? "/TRPM/ForwardRaw/TRAP/%02X" : "/TRPM/ForwardRaw/IRQ/%02X", i); - rc = MMHyperAlloc(pVM, sizeof(STAMCOUNTER) * 256, sizeof(STAMCOUNTER), MM_TAG_TRPM, (void **)&pVM->trpm.s.paStatHostIrqR3); - AssertRCReturn(rc, rc); - pVM->trpm.s.paStatHostIrqRC = MMHyperR3ToRC(pVM, pVM->trpm.s.paStatHostIrqR3); - pVM->trpm.s.paStatHostIrqR0 = MMHyperR3ToR0(pVM, pVM->trpm.s.paStatHostIrqR3); - for (unsigned i = 0; i < 256; i++) - STAMR3RegisterF(pVM, &pVM->trpm.s.paStatHostIrqR3[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, - "Host interrupts.", "/TRPM/HostIRQs/%02x", i); -#endif - - STAM_REG(pVM, &pVM->trpm.s.StatForwardProfR3, STAMTYPE_PROFILE_ADV, "/TRPM/ForwardRaw/ProfR3", STAMUNIT_TICKS_PER_CALL, "Profiling TRPMForwardTrap."); - STAM_REG(pVM, &pVM->trpm.s.StatForwardProfRZ, STAMTYPE_PROFILE_ADV, "/TRPM/ForwardRaw/ProfRZ", STAMUNIT_TICKS_PER_CALL, "Profiling TRPMForwardTrap."); - STAM_REG(pVM, &pVM->trpm.s.StatForwardFailNoHandler, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailNoHandler", STAMUNIT_OCCURENCES,"Failure to forward interrupt in raw mode."); - STAM_REG(pVM, &pVM->trpm.s.StatForwardFailPatchAddr, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailPatchAddr", STAMUNIT_OCCURENCES,"Failure to forward interrupt in raw mode."); - STAM_REG(pVM, &pVM->trpm.s.StatForwardFailR3, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailR3", STAMUNIT_OCCURENCES, "Failure to forward interrupt in raw mode."); - STAM_REG(pVM, &pVM->trpm.s.StatForwardFailRZ, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailRZ", STAMUNIT_OCCURENCES, "Failure to forward interrupt in raw mode."); +# ifdef VBOX_WITH_RAW_MODE + if (!HMIsEnabled(pVM)) + { + rc = MMHyperAlloc(pVM, sizeof(STAMCOUNTER) * 256, sizeof(STAMCOUNTER), MM_TAG_TRPM, (void **)&pVM->trpm.s.paStatHostIrqR3); + AssertRCReturn(rc, rc); + pVM->trpm.s.paStatHostIrqRC = MMHyperR3ToRC(pVM, pVM->trpm.s.paStatHostIrqR3); + for (unsigned i = 0; i < 256; i++) + STAMR3RegisterF(pVM, &pVM->trpm.s.paStatHostIrqR3[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, + "Host interrupts.", "/TRPM/HostIRQs/%02x", i); + } +# endif +# endif - STAM_REG(pVM, &pVM->trpm.s.StatTrap0dDisasm, STAMTYPE_PROFILE, "/TRPM/RC/Traps/0d/Disasm", STAMUNIT_TICKS_PER_CALL, "Profiling disassembly part of trpmGCTrap0dHandler."); - STAM_REG(pVM, &pVM->trpm.s.StatTrap0dRdTsc, STAMTYPE_COUNTER, "/TRPM/RC/Traps/0d/RdTsc", STAMUNIT_OCCURENCES, "Number of RDTSC #GPs."); +#ifdef VBOX_WITH_RAW_MODE + if (!HMIsEnabled(pVM)) + { + STAM_REG(pVM, &pVM->trpm.s.StatForwardProfR3, STAMTYPE_PROFILE_ADV, "/TRPM/ForwardRaw/ProfR3", STAMUNIT_TICKS_PER_CALL, "Profiling TRPMForwardTrap."); + STAM_REG(pVM, &pVM->trpm.s.StatForwardProfRZ, STAMTYPE_PROFILE_ADV, "/TRPM/ForwardRaw/ProfRZ", STAMUNIT_TICKS_PER_CALL, "Profiling TRPMForwardTrap."); + STAM_REG(pVM, &pVM->trpm.s.StatForwardFailNoHandler, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailNoHandler", STAMUNIT_OCCURENCES,"Failure to forward interrupt in raw mode."); + STAM_REG(pVM, &pVM->trpm.s.StatForwardFailPatchAddr, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailPatchAddr", STAMUNIT_OCCURENCES,"Failure to forward interrupt in raw mode."); + STAM_REG(pVM, &pVM->trpm.s.StatForwardFailR3, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailR3", STAMUNIT_OCCURENCES, "Failure to forward interrupt in raw mode."); + STAM_REG(pVM, &pVM->trpm.s.StatForwardFailRZ, STAMTYPE_COUNTER, "/TRPM/ForwardRaw/FailRZ", STAMUNIT_OCCURENCES, "Failure to forward interrupt in raw mode."); + + STAM_REG(pVM, &pVM->trpm.s.StatTrap0dDisasm, STAMTYPE_PROFILE, "/TRPM/RC/Traps/0d/Disasm", STAMUNIT_TICKS_PER_CALL, "Profiling disassembly part of trpmGCTrap0dHandler."); + STAM_REG(pVM, &pVM->trpm.s.StatTrap0dRdTsc, STAMTYPE_COUNTER, "/TRPM/RC/Traps/0d/RdTsc", STAMUNIT_OCCURENCES, "Number of RDTSC #GPs."); + } +#endif +#ifdef VBOX_WITH_RAW_MODE /* * Default action when entering raw mode for the first time */ - PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ - VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); + if (!HMIsEnabled(pVM)) + { + PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ + VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); + } +#endif return 0; } @@ -590,10 +610,14 @@ VMMR3DECL(int) TRPMR3Init(PVM pVM) */ VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta) { +#ifdef VBOX_WITH_RAW_MODE + if (HMIsEnabled(pVM)) + return; + /* Only applies to raw mode which supports only 1 VCPU. */ PVMCPU pVCpu = &pVM->aCpus[0]; - LogFlow(("TRPMR3Relocate\n")); + /* * Get the trap handler addresses. * @@ -664,21 +688,17 @@ VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta) */ CPUMSetHyperIDTR(pVCpu, VM_RC_ADDR(pVM, &pVM->trpm.s.aIdt[0]), sizeof(pVM->trpm.s.aIdt)-1); - if ( !pVM->trpm.s.fDisableMonitoring - && !VMMIsHwVirtExtForced(pVM)) +# ifdef TRPM_TRACK_SHADOW_IDT_CHANGES + if (pVM->trpm.s.pvMonShwIdtRC != RTRCPTR_MAX) { -#ifdef TRPM_TRACK_SHADOW_IDT_CHANGES - if (pVM->trpm.s.pvMonShwIdtRC != RTRCPTR_MAX) - { - rc = PGMHandlerVirtualDeregister(pVM, pVM->trpm.s.pvMonShwIdtRC); - AssertRC(rc); - } - pVM->trpm.s.pvMonShwIdtRC = VM_RC_ADDR(pVM, &pVM->trpm.s.aIdt[0]); - rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_HYPERVISOR, pVM->trpm.s.pvMonShwIdtRC, pVM->trpm.s.pvMonShwIdtRC + sizeof(pVM->trpm.s.aIdt) - 1, - 0, 0, "trpmRCShadowIDTWriteHandler", 0, "Shadow IDT write access handler"); + rc = PGMHandlerVirtualDeregister(pVM, pVM->trpm.s.pvMonShwIdtRC); AssertRC(rc); -#endif } + pVM->trpm.s.pvMonShwIdtRC = VM_RC_ADDR(pVM, &pVM->trpm.s.aIdt[0]); + rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_HYPERVISOR, pVM->trpm.s.pvMonShwIdtRC, pVM->trpm.s.pvMonShwIdtRC + sizeof(pVM->trpm.s.aIdt) - 1, + 0, 0, "trpmRCShadowIDTWriteHandler", 0, "Shadow IDT write access handler"); + AssertRC(rc); +# endif /* Relocate IDT handlers for forwarding guest traps/interrupts. */ for (uint32_t iTrap = 0; iTrap < RT_ELEMENTS(pVM->trpm.s.aGuestTrapHandler); iTrap++) @@ -702,12 +722,11 @@ VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta) } } -#ifdef VBOX_WITH_STATISTICS +# ifdef VBOX_WITH_STATISTICS pVM->trpm.s.paStatForwardedIRQRC += offDelta; - pVM->trpm.s.paStatForwardedIRQR0 = MMHyperR3ToR0(pVM, pVM->trpm.s.paStatForwardedIRQR3); pVM->trpm.s.paStatHostIrqRC += offDelta; - pVM->trpm.s.paStatHostIrqR0 = MMHyperR3ToR0(pVM, pVM->trpm.s.paStatHostIrqR3); -#endif +# endif +#endif /* VBOX_WITH_RAW_MODE */ } @@ -720,7 +739,7 @@ VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta) VMMR3DECL(int) TRPMR3Term(PVM pVM) { NOREF(pVM); - return 0; + return VINF_SUCCESS; } @@ -733,7 +752,7 @@ VMMR3DECL(int) TRPMR3Term(PVM pVM) */ VMMR3DECL(void) TRPMR3ResetCpu(PVMCPU pVCpu) { - pVCpu->trpm.s.uActiveVector = ~0; + pVCpu->trpm.s.uActiveVector = ~0U; } @@ -772,14 +791,20 @@ VMMR3DECL(void) TRPMR3Reset(PVM pVM) memset(pVM->trpm.s.aGuestTrapHandler, 0, sizeof(pVM->trpm.s.aGuestTrapHandler)); TRPMR3Relocate(pVM, 0); +#ifdef VBOX_WITH_RAW_MODE /* * Default action when entering raw mode for the first time */ - PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ - VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); + if (!HMIsEnabled(pVM)) + { + PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ + VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); + } +#endif } +# ifdef VBOX_WITH_RAW_MODE /** * Resolve a builtin RC symbol. * @@ -812,6 +837,7 @@ VMMR3_INT_DECL(int) TRPMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR p return VERR_SYMBOL_NOT_FOUND; return VINF_SUCCESS; } +#endif /* VBOX_WITH_RAW_MODE */ /** @@ -842,9 +868,9 @@ static DECLCALLBACK(int) trpmR3Save(PVM pVM, PSSMHANDLE pSSM) SSMR3PutGCUIntPtr(pSSM, pTrpmCpu->uSavedCR2); SSMR3PutGCUInt(pSSM, pTrpmCpu->uPrevVector); } - SSMR3PutBool(pSSM, pTrpm->fDisableMonitoring); + SSMR3PutBool(pSSM, HMIsEnabled(pVM)); PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies 1 VCPU */ - SSMR3PutUInt(pSSM, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT)); + SSMR3PutUInt(pSSM, VM_WHEN_RAW_MODE(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT), 0)); SSMR3PutMem(pSSM, &pTrpm->au32IdtPatched[0], sizeof(pTrpm->au32IdtPatched)); SSMR3PutU32(pSSM, ~0); /* separator. */ @@ -915,7 +941,8 @@ static DECLCALLBACK(int) trpmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, SSMR3GetGCUInt(pSSM, &pTrpmCpu->uPrevVector); } - SSMR3GetBool(pSSM, &pVM->trpm.s.fDisableMonitoring); + bool fIgnored; + SSMR3GetBool(pSSM, &fIgnored); } else { @@ -930,9 +957,8 @@ static DECLCALLBACK(int) trpmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, SSMR3GetGCUIntPtr(pSSM, &pTrpmCpu->uSavedCR2); SSMR3GetGCUInt(pSSM, &pTrpmCpu->uPrevVector); - RTGCUINT fDisableMonitoring; - SSMR3GetGCUInt(pSSM, &fDisableMonitoring); - pTrpm->fDisableMonitoring = !!fDisableMonitoring; + RTGCUINT fIgnored; + SSMR3GetGCUInt(pSSM, &fIgnored); } RTUINT fSyncIDT; @@ -944,12 +970,14 @@ static DECLCALLBACK(int) trpmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, AssertMsgFailed(("fSyncIDT=%#x\n", fSyncIDT)); return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; } +#ifdef VBOX_WITH_RAW_MODE if (fSyncIDT) { PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies 1 VCPU */ VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); } /* else: cleared by reset call above. */ +#endif SSMR3GetMem(pSSM, &pTrpm->au32IdtPatched[0], sizeof(pTrpm->au32IdtPatched)); @@ -997,6 +1025,7 @@ static DECLCALLBACK(int) trpmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, return VINF_SUCCESS; } +#ifdef VBOX_WITH_RAW_MODE /** * Check if gate handlers were updated @@ -1012,11 +1041,7 @@ VMMR3DECL(int) TRPMR3SyncIDT(PVM pVM, PVMCPU pVCpu) const bool fRawRing0 = EMIsRawRing0Enabled(pVM); int rc; - if (pVM->trpm.s.fDisableMonitoring) - { - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); - return VINF_SUCCESS; /* Nothing to do */ - } + AssertReturn(!HMIsEnabled(pVM), VERR_TRPM_HM_IPE); if (fRawRing0 && CSAMIsEnabled(pVM)) { @@ -1041,7 +1066,7 @@ VMMR3DECL(int) TRPMR3SyncIDT(PVM pVM, PVMCPU pVCpu) return DBGFSTOP(pVM); } -#ifdef TRPM_TRACK_GUEST_IDT_CHANGES +# ifdef TRPM_TRACK_GUEST_IDT_CHANGES /* * Check if Guest's IDTR has changed. */ @@ -1080,7 +1105,7 @@ VMMR3DECL(int) TRPMR3SyncIDT(PVM pVM, PVMCPU pVCpu) /* Update saved Guest IDTR. */ pVM->trpm.s.GuestIdtr = IDTR; } -#endif +# endif /* * Sync the interrupt gate. @@ -1108,45 +1133,7 @@ VMMR3DECL(int) TRPMR3SyncIDT(PVM pVM, PVMCPU pVCpu) } -/** - * Disable IDT monitoring and syncing - * - * @param pVM Pointer to the VM. - */ -VMMR3DECL(void) TRPMR3DisableMonitoring(PVM pVM) -{ - /* - * Deregister any virtual handlers. - */ -#ifdef TRPM_TRACK_GUEST_IDT_CHANGES - if (pVM->trpm.s.GuestIdtr.pIdt != RTRCPTR_MAX) - { - if (!pVM->trpm.s.fSafeToDropGuestIDTMonitoring) - { - int rc = PGMHandlerVirtualDeregister(pVM, pVM->trpm.s.GuestIdtr.pIdt); - AssertRC(rc); - } - pVM->trpm.s.GuestIdtr.pIdt = RTRCPTR_MAX; - } - pVM->trpm.s.GuestIdtr.cbIdt = 0; -#endif - -#ifdef TRPM_TRACK_SHADOW_IDT_CHANGES - if (pVM->trpm.s.pvMonShwIdtRC != RTRCPTR_MAX) - { - int rc = PGMHandlerVirtualDeregister(pVM, pVM->trpm.s.pvMonShwIdtRC); - AssertRC(rc); - pVM->trpm.s.pvMonShwIdtRC = RTRCPTR_MAX; - } -#endif - - PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); - - pVM->trpm.s.fDisableMonitoring = true; -} - - +# ifdef TRPM_TRACK_GUEST_IDT_CHANGES /** * \#PF Handler callback for virtual access handler ranges. * @@ -1169,10 +1156,12 @@ static DECLCALLBACK(int) trpmR3GuestIDTWriteHandler(PVM pVM, RTGCPTR GCPtr, void Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType); Log(("trpmR3GuestIDTWriteHandler: write to %RGv size %d\n", GCPtr, cbBuf)); NOREF(GCPtr); NOREF(cbBuf); NOREF(pvPtr); NOREF(pvUser); NOREF(pvBuf); + Assert(!HMIsEnabled(pVM)); VMCPU_FF_SET(VMMGetCpu(pVM), VMCPU_FF_TRPM_SYNC_IDT); return VINF_PGM_HANDLER_DO_DEFAULT; } +# endif /* TRPM_TRACK_GUEST_IDT_CHANGES */ /** @@ -1182,10 +1171,11 @@ static DECLCALLBACK(int) trpmR3GuestIDTWriteHandler(PVM pVM, RTGCPTR GCPtr, void * @param pVM Pointer to the VM. * @param iTrap Trap/interrupt gate number. */ -VMMR3DECL(int) trpmR3ClearPassThroughHandler(PVM pVM, unsigned iTrap) +int trpmR3ClearPassThroughHandler(PVM pVM, unsigned iTrap) { /* Only applies to raw mode which supports only 1 VCPU. */ PVMCPU pVCpu = &pVM->aCpus[0]; + Assert(!HMIsEnabled(pVM)); /** @todo cleanup trpmR3ClearPassThroughHandler()! */ RTRCPTR aGCPtrs[TRPM_HANDLER_MAX]; @@ -1246,6 +1236,8 @@ VMMR3DECL(int) trpmR3ClearPassThroughHandler(PVM pVM, unsigned iTrap) */ VMMR3DECL(uint32_t) TRPMR3QueryGateByHandler(PVM pVM, RTRCPTR GCPtr) { + AssertReturn(!HMIsEnabled(pVM), ~0U); + for (uint32_t iTrap = 0; iTrap < RT_ELEMENTS(pVM->trpm.s.aGuestTrapHandler); iTrap++) { if (pVM->trpm.s.aGuestTrapHandler[iTrap] == GCPtr) @@ -1275,6 +1267,7 @@ VMMR3DECL(uint32_t) TRPMR3QueryGateByHandler(PVM pVM, RTRCPTR GCPtr) VMMR3DECL(RTRCPTR) TRPMR3GetGuestTrapHandler(PVM pVM, unsigned iTrap) { AssertReturn(iTrap < RT_ELEMENTS(pVM->trpm.s.aIdt), TRPM_INVALID_HANDLER); + AssertReturn(!HMIsEnabled(pVM), TRPM_INVALID_HANDLER); return pVM->trpm.s.aGuestTrapHandler[iTrap]; } @@ -1293,6 +1286,7 @@ VMMR3DECL(int) TRPMR3SetGuestTrapHandler(PVM pVM, unsigned iTrap, RTRCPTR pHandl { /* Only valid in raw mode which implies 1 VCPU */ Assert(PATMIsEnabled(pVM) && pVM->cCpus == 1); + AssertReturn(!HMIsEnabled(pVM), VERR_TRPM_HM_IPE); PVMCPU pVCpu = &pVM->aCpus[0]; /* @@ -1329,7 +1323,8 @@ VMMR3DECL(int) TRPMR3SetGuestTrapHandler(PVM pVM, unsigned iTrap, RTRCPTR pHandl return rc; } - if (EMIsRawRing0Enabled(pVM)) + if ( EMIsRawRing0Enabled(pVM) + && !EMIsRawRing1Enabled(pVM)) /* can't deal with the ambiguity of ring 1 & 2 in the patch code. */ { /* * Only replace handlers for which we are 100% certain there won't be @@ -1482,6 +1477,7 @@ VMMR3DECL(bool) TRPMR3IsGateHandler(PVM pVM, RTRCPTR GCPtr) return false; } +#endif /* VBOX_WITH_RAW_MODE */ /** * Inject event (such as external irq or trap) @@ -1493,12 +1489,11 @@ VMMR3DECL(bool) TRPMR3IsGateHandler(PVM pVM, RTRCPTR GCPtr) */ VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent) { - PCPUMCTX pCtx; - int rc; - - pCtx = CPUMQueryGuestCtxPtr(pVCpu); + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); +#ifdef VBOX_WITH_RAW_MODE Assert(!PATMIsPatchGCAddr(pVM, pCtx->eip)); - Assert(!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); +#endif + Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); /* Currently only useful for external hardware interrupts. */ Assert(enmEvent == TRPM_HARDWARE_INT); @@ -1512,23 +1507,23 @@ VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent) #ifdef TRPM_FORWARD_TRAPS_IN_GC # ifdef LOG_ENABLED - DBGFR3InfoLog(pVM, "cpumguest", "TRPMInject"); - DBGFR3DisasInstrCurrentLog(pVCpu, "TRPMInject"); + DBGFR3_INFO_LOG(pVM, "cpumguest", "TRPMInject"); + DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "TRPMInject"); # endif uint8_t u8Interrupt; - rc = PDMGetInterrupt(pVCpu, &u8Interrupt); + int rc = PDMGetInterrupt(pVCpu, &u8Interrupt); Log(("TRPMR3InjectEvent: CPU%d u8Interrupt=%d (%#x) rc=%Rrc\n", pVCpu->idCpu, u8Interrupt, u8Interrupt, rc)); if (RT_SUCCESS(rc)) { # ifndef IEM_VERIFICATION_MODE - if (HWACCMIsEnabled(pVM)) + if (HMIsEnabled(pVM)) # endif { rc = TRPMAssertTrap(pVCpu, u8Interrupt, enmEvent); AssertRC(rc); STAM_COUNTER_INC(&pVM->trpm.s.paStatForwardedIRQR3[u8Interrupt]); - return HWACCMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HWACC : VINF_EM_RESCHEDULE_REM; + return HMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HM : VINF_EM_RESCHEDULE_REM; } /* If the guest gate is not patched, then we will check (again) if we can patch it. */ if (pVM->trpm.s.aGuestTrapHandler[u8Interrupt] == TRPM_INVALID_HANDLER) @@ -1547,7 +1542,7 @@ VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent) rc = TRPMForwardTrap(pVCpu, CPUMCTX2CORE(pCtx), u8Interrupt, 0, TRPM_TRAP_NO_ERRORCODE, enmEvent, -1); if (rc == VINF_SUCCESS /* Don't use RT_SUCCESS */) { - Assert(!VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS)); + Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS)); STAM_COUNTER_INC(&pVM->trpm.s.paStatForwardedIRQR3[u8Interrupt]); return VINF_EM_RESCHEDULE_RAW; @@ -1556,32 +1551,30 @@ VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent) } else STAM_COUNTER_INC(&pVM->trpm.s.StatForwardFailNoHandler); -#ifdef VBOX_WITH_REM +# ifdef VBOX_WITH_REM REMR3NotifyPendingInterrupt(pVM, pVCpu, u8Interrupt); -#endif +# endif } else { AssertRC(rc); - return HWACCMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HWACC : VINF_EM_RESCHEDULE_REM; /* (Heed the halted state if this is changed!) */ + return HMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HM : VINF_EM_RESCHEDULE_REM; /* (Heed the halted state if this is changed!) */ } -#else - if (HWACCMR3IsActive(pVCpu)) +#else /* !TRPM_FORWARD_TRAPS_IN_GC */ + if (HMR3IsActive(pVCpu)) { uint8_t u8Interrupt; - rc = PDMGetInterrupt(pVCpu, &u8Interrupt); + int rc = PDMGetInterrupt(pVCpu, &u8Interrupt); Log(("TRPMR3InjectEvent: u8Interrupt=%d (%#x) rc=%Rrc\n", u8Interrupt, u8Interrupt, rc)); if (RT_SUCCESS(rc)) { rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT); AssertRC(rc); STAM_COUNTER_INC(&pVM->trpm.s.paStatForwardedIRQR3[u8Interrupt]); - return VINF_EM_RESCHEDULE_HWACC; + return VINF_EM_RESCHEDULE_HM; } } - else - AssertRC(rc); -#endif +#endif /* !TRPM_FORWARD_TRAPS_IN_GC */ } /** @todo check if it's safe to translate the patch address to the original guest address. * this implies a safe state in translated instructions and should take sti successors into account (instruction fusing) |
