diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
|---|---|---|
| committer | <> | 2014-05-08 15:03:54 +0000 |
| commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
| tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/VMM/VMMR3/SELM.cpp | |
| parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
| download | VirtualBox-master.tar.gz | |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/VMM/VMMR3/SELM.cpp')
| -rw-r--r-- | src/VBox/VMM/VMMR3/SELM.cpp | 598 |
1 files changed, 339 insertions, 259 deletions
diff --git a/src/VBox/VMM/VMMR3/SELM.cpp b/src/VBox/VMM/VMMR3/SELM.cpp index 4e4149ac..1504a37f 100644 --- a/src/VBox/VMM/VMMR3/SELM.cpp +++ b/src/VBox/VMM/VMMR3/SELM.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2012 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; @@ -62,6 +62,8 @@ #include <VBox/vmm/selm.h> #include <VBox/vmm/cpum.h> #include <VBox/vmm/stam.h> +#include <VBox/vmm/em.h> +#include <VBox/vmm/hm.h> #include <VBox/vmm/mm.h> #include <VBox/vmm/ssm.h> #include <VBox/vmm/pgm.h> @@ -79,15 +81,7 @@ #include <iprt/thread.h> #include <iprt/string.h> - -/** - * Enable or disable tracking of Shadow GDT/LDT/TSS. - * @{ - */ -#define SELM_TRACK_SHADOW_GDT_CHANGES -#define SELM_TRACK_SHADOW_LDT_CHANGES -#define SELM_TRACK_SHADOW_TSS_CHANGES -/** @} */ +#include "SELMInline.h" /** SELM saved state version. */ @@ -128,6 +122,7 @@ static char const g_aszSRegNms[X86_SREG_COUNT][4] = { "ES", "CS", "SS", "DS", "F */ VMMR3DECL(int) SELMR3Init(PVM pVM) { + int rc; LogFlow(("SELMR3Init\n")); /* @@ -154,18 +149,21 @@ VMMR3DECL(int) SELMR3Init(PVM pVM) pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] = (SELM_GDT_ELEMENTS - 0x4) << 3; pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] = (SELM_GDT_ELEMENTS - 0x5) << 3; - /* - * Allocate GDT table. - */ - int rc = MMR3HyperAllocOnceNoRel(pVM, sizeof(pVM->selm.s.paGdtR3[0]) * SELM_GDT_ELEMENTS, + if (HMIsRawModeCtxNeeded(pVM)) + { + /* + * Allocate GDT table. + */ + rc = MMR3HyperAllocOnceNoRel(pVM, sizeof(pVM->selm.s.paGdtR3[0]) * SELM_GDT_ELEMENTS, PAGE_SIZE, MM_TAG_SELM, (void **)&pVM->selm.s.paGdtR3); - AssertRCReturn(rc, rc); + AssertRCReturn(rc, rc); - /* - * Allocate LDT area. - */ - rc = MMR3HyperAllocOnceNoRel(pVM, _64K + PAGE_SIZE, PAGE_SIZE, MM_TAG_SELM, &pVM->selm.s.pvLdtR3); - AssertRCReturn(rc, rc); + /* + * Allocate LDT area. + */ + rc = MMR3HyperAllocOnceNoRel(pVM, _64K + PAGE_SIZE, PAGE_SIZE, MM_TAG_SELM, &pVM->selm.s.pvLdtR3); + AssertRCReturn(rc, rc); + } /* * Init Guest's and Shadow GDT, LDT, TSS changes control variables. @@ -180,11 +178,11 @@ VMMR3DECL(int) SELMR3Init(PVM pVM) pVM->selm.s.pvMonShwTssRC = RTRCPTR_MAX; pVM->selm.s.GCSelTss = RTSEL_MAX; - pVM->selm.s.fDisableMonitoring = false; pVM->selm.s.fSyncTSSRing0Stack = false; - /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. Outside the TSS on purpose; the CPU will not check it - * for I/O operations. */ + /* The I/O bitmap starts right after the virtual interrupt redirection + bitmap. Outside the TSS on purpose; the CPU will not check it for + I/O operations. */ pVM->selm.s.Tss.offIoBitmap = sizeof(VBOXTSS); /* bit set to 1 means no redirection */ memset(pVM->selm.s.Tss.IntRedirBitmap, 0xff, sizeof(pVM->selm.s.Tss.IntRedirBitmap)); @@ -202,63 +200,74 @@ VMMR3DECL(int) SELMR3Init(PVM pVM) /* * Statistics. */ - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestGDTHandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/GDTInt", STAMUNIT_OCCURENCES, "The number of handled writes to the Guest GDT."); - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestGDTUnhandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/GDTEmu", STAMUNIT_OCCURENCES, "The number of unhandled writes to the Guest GDT."); - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestLDT, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/LDT", STAMUNIT_OCCURENCES, "The number of writes to the Guest LDT was detected."); - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSHandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSInt", STAMUNIT_OCCURENCES, "The number of handled writes to the Guest TSS."); - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSRedir, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSRedir",STAMUNIT_OCCURENCES, "The number of handled redir bitmap writes to the Guest TSS."); - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSHandledChanged,STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSIntChg", STAMUNIT_OCCURENCES, "The number of handled writes to the Guest TSS where the R0 stack changed."); - STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSUnhandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSEmu", STAMUNIT_OCCURENCES, "The number of unhandled writes to the Guest TSS."); - STAM_REG(pVM, &pVM->selm.s.StatTSSSync, STAMTYPE_PROFILE, "/PROF/SELM/TSSSync", STAMUNIT_TICKS_PER_CALL, "Profiling of the SELMR3SyncTSS() body."); - STAM_REG(pVM, &pVM->selm.s.StatUpdateFromCPUM, STAMTYPE_PROFILE, "/PROF/SELM/UpdateFromCPUM", STAMUNIT_TICKS_PER_CALL, "Profiling of the SELMR3UpdateFromCPUM() body."); - - STAM_REL_REG(pVM, &pVM->selm.s.StatHyperSelsChanged, STAMTYPE_COUNTER, "/SELM/HyperSels/Changed", STAMUNIT_OCCURENCES, "The number of times we had to relocate our hypervisor selectors."); - STAM_REL_REG(pVM, &pVM->selm.s.StatScanForHyperSels, STAMTYPE_COUNTER, "/SELM/HyperSels/Scan", STAMUNIT_OCCURENCES, "The number of times we had find free hypervisor selectors."); - - STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_ES], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleES", STAMUNIT_OCCURENCES, "Stale ES was detected in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_CS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleCS", STAMUNIT_OCCURENCES, "Stale CS was detected in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_SS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleSS", STAMUNIT_OCCURENCES, "Stale SS was detected in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_DS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleDS", STAMUNIT_OCCURENCES, "Stale DS was detected in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_FS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleFS", STAMUNIT_OCCURENCES, "Stale FS was detected in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_GS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleGS", STAMUNIT_OCCURENCES, "Stale GS was detected in UpdateFromCPUM."); - - STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_ES], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleES", STAMUNIT_OCCURENCES, "Already stale ES in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_CS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleCS", STAMUNIT_OCCURENCES, "Already stale CS in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_SS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleSS", STAMUNIT_OCCURENCES, "Already stale SS in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_DS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleDS", STAMUNIT_OCCURENCES, "Already stale DS in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_FS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleFS", STAMUNIT_OCCURENCES, "Already stale FS in UpdateFromCPUM."); - STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_GS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleGS", STAMUNIT_OCCURENCES, "Already stale GS in UpdateFromCPUM."); - - STAM_REL_REG(pVM, &pVM->selm.s.StatStaleToUnstaleSReg, STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/StaleToUnstale", STAMUNIT_OCCURENCES, "Transitions from stale to unstale UpdateFromCPUM."); - - STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_ES], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedES", STAMUNIT_OCCURENCES, "Updated hidden ES values in UpdateFromCPUM."); - STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_CS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedCS", STAMUNIT_OCCURENCES, "Updated hidden CS values in UpdateFromCPUM."); - STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_SS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedSS", STAMUNIT_OCCURENCES, "Updated hidden SS values in UpdateFromCPUM."); - STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_DS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedDS", STAMUNIT_OCCURENCES, "Updated hidden DS values in UpdateFromCPUM."); - STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_FS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedFS", STAMUNIT_OCCURENCES, "Updated hidden FS values in UpdateFromCPUM."); - STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_GS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedGS", STAMUNIT_OCCURENCES, "Updated hidden GS values in UpdateFromCPUM."); + if (!HMIsEnabled(pVM)) + { + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestGDTHandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/GDTInt", STAMUNIT_OCCURENCES, "The number of handled writes to the Guest GDT."); + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestGDTUnhandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/GDTEmu", STAMUNIT_OCCURENCES, "The number of unhandled writes to the Guest GDT."); + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestLDT, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/LDT", STAMUNIT_OCCURENCES, "The number of writes to the Guest LDT was detected."); + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSHandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSInt", STAMUNIT_OCCURENCES, "The number of handled writes to the Guest TSS."); + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSRedir, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSRedir",STAMUNIT_OCCURENCES, "The number of handled redir bitmap writes to the Guest TSS."); + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSHandledChanged,STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSIntChg", STAMUNIT_OCCURENCES, "The number of handled writes to the Guest TSS where the R0 stack changed."); + STAM_REG(pVM, &pVM->selm.s.StatRCWriteGuestTSSUnhandled, STAMTYPE_COUNTER, "/SELM/GC/Write/Guest/TSSEmu", STAMUNIT_OCCURENCES, "The number of unhandled writes to the Guest TSS."); + STAM_REG(pVM, &pVM->selm.s.StatTSSSync, STAMTYPE_PROFILE, "/PROF/SELM/TSSSync", STAMUNIT_TICKS_PER_CALL, "Profiling of the SELMR3SyncTSS() body."); + STAM_REG(pVM, &pVM->selm.s.StatUpdateFromCPUM, STAMTYPE_PROFILE, "/PROF/SELM/UpdateFromCPUM", STAMUNIT_TICKS_PER_CALL, "Profiling of the SELMR3UpdateFromCPUM() body."); + + STAM_REL_REG(pVM, &pVM->selm.s.StatHyperSelsChanged, STAMTYPE_COUNTER, "/SELM/HyperSels/Changed", STAMUNIT_OCCURENCES, "The number of times we had to relocate our hypervisor selectors."); + STAM_REL_REG(pVM, &pVM->selm.s.StatScanForHyperSels, STAMTYPE_COUNTER, "/SELM/HyperSels/Scan", STAMUNIT_OCCURENCES, "The number of times we had find free hypervisor selectors."); + + STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_ES], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleES", STAMUNIT_OCCURENCES, "Stale ES was detected in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_CS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleCS", STAMUNIT_OCCURENCES, "Stale CS was detected in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_SS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleSS", STAMUNIT_OCCURENCES, "Stale SS was detected in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_DS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleDS", STAMUNIT_OCCURENCES, "Stale DS was detected in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_FS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleFS", STAMUNIT_OCCURENCES, "Stale FS was detected in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatDetectedStaleSReg[X86_SREG_GS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/DetectedStaleGS", STAMUNIT_OCCURENCES, "Stale GS was detected in UpdateFromCPUM."); + + STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_ES], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleES", STAMUNIT_OCCURENCES, "Already stale ES in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_CS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleCS", STAMUNIT_OCCURENCES, "Already stale CS in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_SS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleSS", STAMUNIT_OCCURENCES, "Already stale SS in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_DS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleDS", STAMUNIT_OCCURENCES, "Already stale DS in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_FS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleFS", STAMUNIT_OCCURENCES, "Already stale FS in UpdateFromCPUM."); + STAM_REL_REG(pVM, &pVM->selm.s.aStatAlreadyStaleSReg[X86_SREG_GS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/AlreadyStaleGS", STAMUNIT_OCCURENCES, "Already stale GS in UpdateFromCPUM."); + + STAM_REL_REG(pVM, &pVM->selm.s.StatStaleToUnstaleSReg, STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/StaleToUnstale", STAMUNIT_OCCURENCES, "Transitions from stale to unstale UpdateFromCPUM."); + + STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_ES], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedES", STAMUNIT_OCCURENCES, "Updated hidden ES values in UpdateFromCPUM."); + STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_CS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedCS", STAMUNIT_OCCURENCES, "Updated hidden CS values in UpdateFromCPUM."); + STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_SS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedSS", STAMUNIT_OCCURENCES, "Updated hidden SS values in UpdateFromCPUM."); + STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_DS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedDS", STAMUNIT_OCCURENCES, "Updated hidden DS values in UpdateFromCPUM."); + STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_FS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedFS", STAMUNIT_OCCURENCES, "Updated hidden FS values in UpdateFromCPUM."); + STAM_REG( pVM, &pVM->selm.s.aStatUpdatedSReg[X86_SREG_GS], STAMTYPE_COUNTER, "/SELM/UpdateFromCPUM/UpdatedGS", STAMUNIT_OCCURENCES, "Updated hidden GS values in UpdateFromCPUM."); + } STAM_REG( pVM, &pVM->selm.s.StatLoadHidSelGst, STAMTYPE_COUNTER, "/SELM/LoadHidSel/LoadedGuest", STAMUNIT_OCCURENCES, "SELMLoadHiddenSelectorReg: Loaded from guest tables."); STAM_REG( pVM, &pVM->selm.s.StatLoadHidSelShw, STAMTYPE_COUNTER, "/SELM/LoadHidSel/LoadedShadow", STAMUNIT_OCCURENCES, "SELMLoadHiddenSelectorReg: Loaded from shadow tables."); STAM_REL_REG(pVM, &pVM->selm.s.StatLoadHidSelReadErrors, STAMTYPE_COUNTER, "/SELM/LoadHidSel/GstReadErrors", STAMUNIT_OCCURENCES, "SELMLoadHiddenSelectorReg: Guest table read errors."); STAM_REL_REG(pVM, &pVM->selm.s.StatLoadHidSelGstNoGood, STAMTYPE_COUNTER, "/SELM/LoadHidSel/NoGoodGuest", STAMUNIT_OCCURENCES, "SELMLoadHiddenSelectorReg: No good guest table entry."); +#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_SELM_SYNC_TSS); - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); + if (!HMIsEnabled(pVM)) + { + PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); + } +#endif /* * Register info handlers. */ - DBGFR3InfoRegisterInternal(pVM, "gdt", "Displays the shadow GDT. No arguments.", &selmR3InfoGdt); + if (HMIsRawModeCtxNeeded(pVM)) + { + DBGFR3InfoRegisterInternal(pVM, "gdt", "Displays the shadow GDT. No arguments.", &selmR3InfoGdt); + DBGFR3InfoRegisterInternal(pVM, "ldt", "Displays the shadow LDT. No arguments.", &selmR3InfoLdt); + //DBGFR3InfoRegisterInternal(pVM, "tss", "Displays the shadow TSS. No arguments.", &selmR3InfoTss); + } DBGFR3InfoRegisterInternal(pVM, "gdtguest", "Displays the guest GDT. No arguments.", &selmR3InfoGdtGuest); - DBGFR3InfoRegisterInternal(pVM, "ldt", "Displays the shadow LDT. No arguments.", &selmR3InfoLdt); DBGFR3InfoRegisterInternal(pVM, "ldtguest", "Displays the guest LDT. No arguments.", &selmR3InfoLdtGuest); - //DBGFR3InfoRegisterInternal(pVM, "tss", "Displays the shadow TSS. No arguments.", &selmR3InfoTss); //DBGFR3InfoRegisterInternal(pVM, "tssguest", "Displays the guest TSS. No arguments.", &selmR3InfoTssGuest); return rc; @@ -273,6 +282,7 @@ VMMR3DECL(int) SELMR3Init(PVM pVM) */ VMMR3DECL(int) SELMR3InitFinalize(PVM pVM) { +#ifdef VBOX_WITH_RAW_MODE /** @cfgm{/DoubleFault,bool,false} * Enables catching of double faults in the raw-mode context VMM code. This can * be used when the triple faults or hangs occur and one suspect an unhandled @@ -283,13 +293,13 @@ VMMR3DECL(int) SELMR3InitFinalize(PVM pVM) * 8 TSS for the back link. */ bool f; -#if defined(DEBUG_bird) +# if defined(DEBUG_bird) int rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "DoubleFault", &f, true); -#else +# else int rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "DoubleFault", &f, false); -#endif +# endif AssertLogRelRCReturn(rc, rc); - if (f) + if (f && HMIsRawModeCtxNeeded(pVM)) { PX86DESC paGdt = pVM->selm.s.paGdtR3; rc = PGMMapSetPage(pVM, MMHyperR3ToRC(pVM, &paGdt[pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] >> 3]), sizeof(paGdt[0]), @@ -305,6 +315,7 @@ VMMR3DECL(int) SELMR3InitFinalize(PVM pVM) X86_PTE_RW | X86_PTE_P | X86_PTE_A | X86_PTE_D); AssertRC(rc); } +#endif /* VBOX_WITH_RAW_MODE */ return VINF_SUCCESS; } @@ -420,72 +431,74 @@ VMMR3DECL(void) SELMR3Relocate(PVM pVM) PX86DESC paGdt = pVM->selm.s.paGdtR3; LogFlow(("SELMR3Relocate\n")); - for (VMCPUID i = 0; i < pVM->cCpus; i++) + if (HMIsRawModeCtxNeeded(pVM)) { - PVMCPU pVCpu = &pVM->aCpus[i]; - - /* - * Update GDTR and selector. - */ - CPUMSetHyperGDTR(pVCpu, MMHyperR3ToRC(pVM, paGdt), SELM_GDT_ELEMENTS * sizeof(paGdt[0]) - 1); + for (VMCPUID i = 0; i < pVM->cCpus; i++) + { + PVMCPU pVCpu = &pVM->aCpus[i]; - /** @todo selector relocations should be a separate operation? */ - CPUMSetHyperCS(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]); - CPUMSetHyperDS(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]); - CPUMSetHyperES(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]); - CPUMSetHyperSS(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]); - CPUMSetHyperTR(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS]); - } + /* + * Update GDTR and selector. + */ + CPUMSetHyperGDTR(pVCpu, MMHyperR3ToRC(pVM, paGdt), SELM_GDT_ELEMENTS * sizeof(paGdt[0]) - 1); + + /** @todo selector relocations should be a separate operation? */ + CPUMSetHyperCS(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]); + CPUMSetHyperDS(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]); + CPUMSetHyperES(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]); + CPUMSetHyperSS(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]); + CPUMSetHyperTR(pVCpu, pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS]); + } - selmR3SetupHyperGDTSelectors(pVM); + selmR3SetupHyperGDTSelectors(pVM); /** @todo SELM must be called when any of the CR3s changes during a cpu mode change. */ /** @todo PGM knows the proper CR3 values these days, not CPUM. */ - /* - * Update the TSSes. - */ - /* Only applies to raw mode which supports only 1 VCPU */ - PVMCPU pVCpu = &pVM->aCpus[0]; - - /* Current TSS */ - pVM->selm.s.Tss.cr3 = PGMGetHyperCR3(pVCpu); - pVM->selm.s.Tss.ss0 = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.Tss.esp0 = VMMGetStackRC(pVCpu); - pVM->selm.s.Tss.cs = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]; - pVM->selm.s.Tss.ds = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.Tss.es = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.Tss.offIoBitmap = sizeof(VBOXTSS); - - /* trap 08 */ - pVM->selm.s.TssTrap08.cr3 = PGMGetInterRCCR3(pVM, pVCpu); /* this should give use better survival chances. */ - pVM->selm.s.TssTrap08.ss0 = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.TssTrap08.ss = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.TssTrap08.esp0 = VMMGetStackRC(pVCpu) - PAGE_SIZE / 2; /* upper half can be analysed this way. */ - pVM->selm.s.TssTrap08.esp = pVM->selm.s.TssTrap08.esp0; - pVM->selm.s.TssTrap08.ebp = pVM->selm.s.TssTrap08.esp0; - pVM->selm.s.TssTrap08.cs = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]; - pVM->selm.s.TssTrap08.ds = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.TssTrap08.es = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; - pVM->selm.s.TssTrap08.fs = 0; - pVM->selm.s.TssTrap08.gs = 0; - pVM->selm.s.TssTrap08.selLdt = 0; - pVM->selm.s.TssTrap08.eflags = 0x2; /* all cleared */ - pVM->selm.s.TssTrap08.ecx = VM_RC_ADDR(pVM, &pVM->selm.s.Tss); /* setup ecx to normal Hypervisor TSS address. */ - pVM->selm.s.TssTrap08.edi = pVM->selm.s.TssTrap08.ecx; - pVM->selm.s.TssTrap08.eax = pVM->selm.s.TssTrap08.ecx; - pVM->selm.s.TssTrap08.edx = VM_RC_ADDR(pVM, pVM); /* setup edx VM address. */ - pVM->selm.s.TssTrap08.edi = pVM->selm.s.TssTrap08.edx; - pVM->selm.s.TssTrap08.ebx = pVM->selm.s.TssTrap08.edx; - pVM->selm.s.TssTrap08.offIoBitmap = sizeof(VBOXTSS); - /* TRPM will be updating the eip */ - - if ( !pVM->selm.s.fDisableMonitoring - && !VMMIsHwVirtExtForced(pVM)) + /* + * Update the TSSes. + */ + /* Only applies to raw mode which supports only 1 VCPU */ + PVMCPU pVCpu = &pVM->aCpus[0]; + + /* Current TSS */ + pVM->selm.s.Tss.cr3 = PGMGetHyperCR3(pVCpu); + pVM->selm.s.Tss.ss0 = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.Tss.esp0 = VMMGetStackRC(pVCpu); + pVM->selm.s.Tss.cs = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]; + pVM->selm.s.Tss.ds = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.Tss.es = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.Tss.offIoBitmap = sizeof(VBOXTSS); + + /* trap 08 */ + pVM->selm.s.TssTrap08.cr3 = PGMGetInterRCCR3(pVM, pVCpu); /* this should give use better survival chances. */ + pVM->selm.s.TssTrap08.ss0 = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.TssTrap08.ss = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.TssTrap08.esp0 = VMMGetStackRC(pVCpu) - PAGE_SIZE / 2; /* upper half can be analysed this way. */ + pVM->selm.s.TssTrap08.esp = pVM->selm.s.TssTrap08.esp0; + pVM->selm.s.TssTrap08.ebp = pVM->selm.s.TssTrap08.esp0; + pVM->selm.s.TssTrap08.cs = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]; + pVM->selm.s.TssTrap08.ds = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.TssTrap08.es = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; + pVM->selm.s.TssTrap08.fs = 0; + pVM->selm.s.TssTrap08.gs = 0; + pVM->selm.s.TssTrap08.selLdt = 0; + pVM->selm.s.TssTrap08.eflags = 0x2; /* all cleared */ + pVM->selm.s.TssTrap08.ecx = VM_RC_ADDR(pVM, &pVM->selm.s.Tss); /* setup ecx to normal Hypervisor TSS address. */ + pVM->selm.s.TssTrap08.edi = pVM->selm.s.TssTrap08.ecx; + pVM->selm.s.TssTrap08.eax = pVM->selm.s.TssTrap08.ecx; + pVM->selm.s.TssTrap08.edx = VM_RC_ADDR(pVM, pVM); /* setup edx VM address. */ + pVM->selm.s.TssTrap08.edi = pVM->selm.s.TssTrap08.edx; + pVM->selm.s.TssTrap08.ebx = pVM->selm.s.TssTrap08.edx; + pVM->selm.s.TssTrap08.offIoBitmap = sizeof(VBOXTSS); + /* TRPM will be updating the eip */ + } + + if (!HMIsEnabled(pVM)) { /* * Update shadow GDT/LDT/TSS write access handlers. */ - int rc; + int rc; NOREF(rc); #ifdef SELM_TRACK_SHADOW_GDT_CHANGES if (pVM->selm.s.paGdtRC != NIL_RTRCPTR) { @@ -544,7 +557,7 @@ VMMR3DECL(void) SELMR3Relocate(PVM pVM) VMMR3DECL(int) SELMR3Term(PVM pVM) { NOREF(pVM); - return 0; + return VINF_SUCCESS; } @@ -564,25 +577,31 @@ VMMR3DECL(void) SELMR3Reset(PVM pVM) /* * Uninstall guest GDT/LDT/TSS write access handlers. */ - int rc; + int rc = VINF_SUCCESS; if (pVM->selm.s.GuestGdtr.pGdt != RTRCPTR_MAX && pVM->selm.s.fGDTRangeRegistered) { +#ifdef SELM_TRACK_GUEST_GDT_CHANGES rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GuestGdtr.pGdt); AssertRC(rc); +#endif pVM->selm.s.GuestGdtr.pGdt = RTRCPTR_MAX; pVM->selm.s.GuestGdtr.cbGdt = 0; } pVM->selm.s.fGDTRangeRegistered = false; if (pVM->selm.s.GCPtrGuestLdt != RTRCPTR_MAX) { +#ifdef SELM_TRACK_GUEST_LDT_CHANGES rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestLdt); AssertRC(rc); +#endif pVM->selm.s.GCPtrGuestLdt = RTRCPTR_MAX; } if (pVM->selm.s.GCPtrGuestTss != RTRCPTR_MAX) { +#ifdef SELM_TRACK_GUEST_TSS_CHANGES rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestTss); AssertRC(rc); +#endif pVM->selm.s.GCPtrGuestTss = RTRCPTR_MAX; pVM->selm.s.GCSelTss = RTSEL_MAX; } @@ -596,82 +615,18 @@ VMMR3DECL(void) SELMR3Reset(PVM pVM) pVM->selm.s.fSyncTSSRing0Stack = false; - /* - * 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_SELM_SYNC_TSS); - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); -} - -/** - * Disable GDT/LDT/TSS monitoring and syncing - * - * @param pVM Pointer to the VM. - */ -VMMR3DECL(void) SELMR3DisableMonitoring(PVM pVM) -{ - /* - * Uninstall guest GDT/LDT/TSS write access handlers. - */ - int rc; - if (pVM->selm.s.GuestGdtr.pGdt != RTRCPTR_MAX && pVM->selm.s.fGDTRangeRegistered) - { - rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GuestGdtr.pGdt); - AssertRC(rc); - pVM->selm.s.GuestGdtr.pGdt = RTRCPTR_MAX; - pVM->selm.s.GuestGdtr.cbGdt = 0; - } - pVM->selm.s.fGDTRangeRegistered = false; - if (pVM->selm.s.GCPtrGuestLdt != RTRCPTR_MAX) - { - rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestLdt); - AssertRC(rc); - pVM->selm.s.GCPtrGuestLdt = RTRCPTR_MAX; - } - if (pVM->selm.s.GCPtrGuestTss != RTRCPTR_MAX) - { - rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestTss); - AssertRC(rc); - pVM->selm.s.GCPtrGuestTss = RTRCPTR_MAX; - pVM->selm.s.GCSelTss = RTSEL_MAX; - } - - /* - * Unregister shadow GDT/LDT/TSS write access handlers. - */ -#ifdef SELM_TRACK_SHADOW_GDT_CHANGES - if (pVM->selm.s.paGdtRC != NIL_RTRCPTR) - { - rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.paGdtRC); - AssertRC(rc); - pVM->selm.s.paGdtRC = NIL_RTRCPTR; - } -#endif -#ifdef SELM_TRACK_SHADOW_TSS_CHANGES - if (pVM->selm.s.pvMonShwTssRC != RTRCPTR_MAX) +#ifdef VBOX_WITH_RAW_MODE + if (!HMIsEnabled(pVM)) { - rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.pvMonShwTssRC); - AssertRC(rc); - pVM->selm.s.pvMonShwTssRC = RTRCPTR_MAX; - } -#endif -#ifdef SELM_TRACK_SHADOW_LDT_CHANGES - if (pVM->selm.s.pvLdtRC != RTRCPTR_MAX) - { - rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.pvLdtRC); - AssertRC(rc); - pVM->selm.s.pvLdtRC = RTRCPTR_MAX; + /* + * 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_SELM_SYNC_TSS); + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); } #endif - - PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies on VCPU */ - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_TSS); - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_GDT); - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_LDT); - - pVM->selm.s.fDisableMonitoring = true; } @@ -691,7 +646,7 @@ static DECLCALLBACK(int) selmR3Save(PVM pVM, PSSMHANDLE pSSM) */ PSELM pSelm = &pVM->selm.s; - SSMR3PutBool(pSSM, pSelm->fDisableMonitoring); + SSMR3PutBool(pSSM, HMIsEnabled(pVM)); SSMR3PutBool(pSSM, pSelm->fSyncTSSRing0Stack); SSMR3PutSel(pSSM, pSelm->aHyperSel[SELM_HYPER_SEL_CS]); SSMR3PutSel(pSSM, pSelm->aHyperSel[SELM_HYPER_SEL_DS]); @@ -731,7 +686,8 @@ static DECLCALLBACK(int) selmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, SELMR3Reset(pVM); /* Get the monitoring flag. */ - SSMR3GetBool(pSSM, &pVM->selm.s.fDisableMonitoring); + bool fIgnored; + SSMR3GetBool(pSSM, &fIgnored); /* Get the TSS state flag. */ SSMR3GetBool(pSSM, &pVM->selm.s.fSyncTSSRing0Stack); @@ -776,38 +732,43 @@ static DECLCALLBACK(int) selmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, */ static DECLCALLBACK(int) selmR3LoadDone(PVM pVM, PSSMHANDLE pSSM) { - PVMCPU pVCpu = VMMGetCpu(pVM); +#ifdef VBOX_WITH_RAW_MODE + if (!HMIsEnabled(pVM)) + { + PVMCPU pVCpu = VMMGetCpu(pVM); - LogFlow(("selmR3LoadDone:\n")); + LogFlow(("selmR3LoadDone:\n")); - /* - * Don't do anything if it's a load failure. - */ - int rc = SSMR3HandleGetStatus(pSSM); - if (RT_FAILURE(rc)) - return VINF_SUCCESS; + /* + * Don't do anything if it's a load failure. + */ + int rc = SSMR3HandleGetStatus(pSSM); + if (RT_FAILURE(rc)) + return VINF_SUCCESS; - /* - * Do the syncing if we're in protected mode. - */ - if (PGMGetGuestMode(pVCpu) != PGMMODE_REAL) - { + /* + * Do the syncing if we're in protected mode and using raw-mode. + */ + if (PGMGetGuestMode(pVCpu) != PGMMODE_REAL) + { + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); + VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); + SELMR3UpdateFromCPUM(pVM, pVCpu); + } + + /* + * Flag everything for resync on next raw mode entry. + */ VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); - SELMR3UpdateFromCPUM(pVM, pVCpu); } - - /* - * Flag everything for resync on next raw mode entry. - */ - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT); - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT); - VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS); - +#endif /*VBOX_WITH_RAW_MODE*/ return VINF_SUCCESS; } +#ifdef VBOX_WITH_RAW_MODE /** * Updates (syncs) the shadow GDT. @@ -818,6 +779,8 @@ static DECLCALLBACK(int) selmR3LoadDone(PVM pVM, PSSMHANDLE pSSM) */ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) { + Assert(!HMIsEnabled(pVM)); + /* * Always assume the best... */ @@ -921,7 +884,7 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) Log(("Internal SELM GDT conflict: use non-present entries\n")); STAM_REL_COUNTER_INC(&pVM->selm.s.StatScanForHyperSels); - while (pGDTECur > pGDTEStart) + while ((uintptr_t)pGDTECur > (uintptr_t)pGDTEStart) { /* We can reuse non-present entries */ if (!pGDTECur->Gen.u1Present) @@ -951,6 +914,15 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] = SELM_HYPER_DEFAULT_SEL_TSS_TRAP08; } +# ifdef VBOX_WITH_SAFE_STR + /* Use the guest's TR selector to plug the str virtualization hole. */ + if (CPUMGetGuestTR(pVCpu, NULL) != 0) + { + Log(("SELM: Use guest TSS selector %x\n", CPUMGetGuestTR(pVCpu, NULL))); + aHyperSel[SELM_HYPER_SEL_TSS] = CPUMGetGuestTR(pVCpu, NULL); + } +# endif + /* * Work thru the copied GDT entries adjusting them for correct virtualization. */ @@ -958,7 +930,7 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) while (pGDTE < pGDTEEnd) { if (pGDTE->Gen.u1Present) - selmGuestToShadowDesc(pGDTE); + selmGuestToShadowDesc(pVM, pGDTE); /* Next GDT entry. */ pGDTE++; @@ -988,7 +960,12 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) */ VMR3Relocate(pVM, 0); } +# ifdef VBOX_WITH_SAFE_STR + else if ( cbEffLimit >= SELM_HYPER_DEFAULT_BASE + || CPUMGetGuestTR(pVCpu, NULL) != 0) /* Our shadow TR entry was overwritten when we synced the guest's GDT. */ +# else else if (cbEffLimit >= SELM_HYPER_DEFAULT_BASE) +# endif /* We overwrote all entries above, so we have to save them again. */ selmR3SetupHyperGDTSelectors(pVM); @@ -1010,6 +987,7 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) { Log(("SELMR3UpdateFromCPUM: Guest's GDT is changed to pGdt=%016RX64 cbGdt=%08X\n", GDTR.pGdt, GDTR.cbGdt)); +# ifdef SELM_TRACK_GUEST_GDT_CHANGES /* * [Re]Register write virtual handler for guest's GDT. */ @@ -1023,8 +1001,28 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) GDTR.pGdt, GDTR.pGdt + GDTR.cbGdt /* already inclusive */, 0, selmR3GuestGDTWriteHandler, "selmRCGuestGDTWriteHandler", 0, "Guest GDT write access handler"); +# ifdef VBOX_WITH_RAW_RING1 + /** @todo !HACK ALERT! + * Some guest OSes (QNX) share code and the GDT on the same page; + * PGMR3HandlerVirtualRegister doesn't support more than one handler, + * so we kick out the PATM handler as this one is more important. + * Fix this properly in PGMR3HandlerVirtualRegister? + */ + if (rc == VERR_PGM_HANDLER_VIRTUAL_CONFLICT) + { + LogRel(("selmR3UpdateShadowGdt: Virtual handler conflict %RGv -> kick out PATM handler for the higher priority GDT page monitor\n", GDTR.pGdt)); + rc = PGMHandlerVirtualDeregister(pVM, GDTR.pGdt & PAGE_BASE_GC_MASK); + AssertRC(rc); + + rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, + GDTR.pGdt, GDTR.pGdt + GDTR.cbGdt /* already inclusive */, + 0, selmR3GuestGDTWriteHandler, "selmRCGuestGDTWriteHandler", 0, + "Guest GDT write access handler"); + } +# endif if (RT_FAILURE(rc)) return rc; +# endif /* SELM_TRACK_GUEST_GDT_CHANGES */ /* Update saved Guest GDTR. */ pVM->selm.s.GuestGdtr = GDTR; @@ -1045,6 +1043,7 @@ static int selmR3UpdateShadowGdt(PVM pVM, PVMCPU pVCpu) static int selmR3UpdateShadowLdt(PVM pVM, PVMCPU pVCpu) { int rc = VINF_SUCCESS; + Assert(!HMIsEnabled(pVM)); /* * Always assume the best... @@ -1135,6 +1134,7 @@ static int selmR3UpdateShadowLdt(PVM pVM, PVMCPU pVCpu) Log(("SELMR3UpdateFromCPUM: Guest LDT changed to from %RGv:%04x to %RGv:%04x. (GDTR=%016RX64:%04x)\n", pVM->selm.s.GCPtrGuestLdt, pVM->selm.s.cbLdtLimit, GCPtrLdt, cbLdt, pVM->selm.s.GuestGdtr.pGdt, pVM->selm.s.GuestGdtr.cbGdt)); +# ifdef SELM_TRACK_GUEST_LDT_CHANGES /* * [Re]Register write virtual handler for guest's GDT. * In the event of LDT overlapping something, don't install it just assume it's being updated. @@ -1144,10 +1144,10 @@ static int selmR3UpdateShadowLdt(PVM pVM, PVMCPU pVCpu) rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestLdt); AssertRC(rc); } -#ifdef DEBUG +# ifdef LOG_ENABLED if (pDesc->Gen.u1Present) Log(("LDT selector marked not present!!\n")); -#endif +# endif rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtrLdt, GCPtrLdt + cbLdt /* already inclusive */, 0, selmR3GuestLDTWriteHandler, "selmRCGuestLDTWriteHandler", 0, "Guest LDT write access handler"); if (rc == VERR_PGM_HANDLER_VIRTUAL_CONFLICT) @@ -1164,7 +1164,9 @@ static int selmR3UpdateShadowLdt(PVM pVM, PVMCPU pVCpu) CPUMSetHyperLDTR(pVCpu, 0); return rc; } - +# else + pVM->selm.s.GCPtrGuestLdt = GCPtrLdt; +# endif pVM->selm.s.cbLdtLimit = cbLdt; } } @@ -1237,7 +1239,7 @@ static int selmR3UpdateShadowLdt(PVM pVM, PVMCPU pVCpu) while (pLDTE <= pLDTEEnd) { if (pLDTE->Gen.u1Present) - selmGuestToShadowDesc(pLDTE); + selmGuestToShadowDesc(pVM, pLDTE); /* Next LDT entry. */ pLDTE++; @@ -1276,6 +1278,7 @@ static int selmR3UpdateShadowLdt(PVM pVM, PVMCPU pVCpu) static VBOXSTRICTRC selmR3UpdateSegmentRegisters(PVM pVM, PVMCPU pVCpu) { Assert(CPUMIsGuestInProtectedMode(pVCpu)); + Assert(!HMIsEnabled(pVM)); /* * No stale selectors in V8086 mode. @@ -1377,21 +1380,14 @@ static VBOXSTRICTRC selmR3UpdateSegmentRegisters(PVM pVM, PVMCPU pVCpu) */ VMMR3DECL(VBOXSTRICTRC) SELMR3UpdateFromCPUM(PVM pVM, PVMCPU pVCpu) { - if (pVM->selm.s.fDisableMonitoring) - { - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_GDT); - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_LDT); - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_TSS); - return VINF_SUCCESS; - } - STAM_PROFILE_START(&pVM->selm.s.StatUpdateFromCPUM, a); + AssertReturn(!HMIsEnabled(pVM), VERR_SELM_HM_IPE); /* * GDT sync */ int rc; - if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_SELM_SYNC_GDT)) + if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT)) { rc = selmR3UpdateShadowGdt(pVM, pVCpu); if (RT_FAILURE(rc)) @@ -1402,7 +1398,7 @@ VMMR3DECL(VBOXSTRICTRC) SELMR3UpdateFromCPUM(PVM pVM, PVMCPU pVCpu) /* * TSS sync */ - if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_SELM_SYNC_TSS)) + if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS)) { rc = SELMR3SyncTSS(pVM, pVCpu); if (RT_FAILURE(rc)) @@ -1413,7 +1409,7 @@ VMMR3DECL(VBOXSTRICTRC) SELMR3UpdateFromCPUM(PVM pVM, PVMCPU pVCpu) /* * LDT sync */ - if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_SELM_SYNC_LDT)) + if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT)) { rc = selmR3UpdateShadowLdt(pVM, pVCpu); if (RT_FAILURE(rc)) @@ -1430,7 +1426,9 @@ VMMR3DECL(VBOXSTRICTRC) SELMR3UpdateFromCPUM(PVM pVM, PVMCPU pVCpu) return rcStrict; } +#endif /*VBOX_WITH_RAW_MODE*/ +#ifdef SELM_TRACK_GUEST_GDT_CHANGES /** * \#PF Handler callback for virtual access handler ranges. * @@ -1457,8 +1455,9 @@ static DECLCALLBACK(int) selmR3GuestGDTWriteHandler(PVM pVM, RTGCPTR GCPtr, void VMCPU_FF_SET(VMMGetCpu(pVM), VMCPU_FF_SELM_SYNC_GDT); return VINF_PGM_HANDLER_DO_DEFAULT; } +#endif - +#ifdef SELM_TRACK_GUEST_LDT_CHANGES /** * \#PF Handler callback for virtual access handler ranges. * @@ -1485,8 +1484,10 @@ static DECLCALLBACK(int) selmR3GuestLDTWriteHandler(PVM pVM, RTGCPTR GCPtr, void VMCPU_FF_SET(VMMGetCpu(pVM), VMCPU_FF_SELM_SYNC_LDT); return VINF_PGM_HANDLER_DO_DEFAULT; } +#endif +#ifdef SELM_TRACK_GUEST_TSS_CHANGES /** * \#PF Handler callback for virtual access handler ranges. * @@ -1518,7 +1519,9 @@ static DECLCALLBACK(int) selmR3GuestTSSWriteHandler(PVM pVM, RTGCPTR GCPtr, void VMCPU_FF_SET(VMMGetCpu(pVM), VMCPU_FF_SELM_SYNC_TSS); return VINF_PGM_HANDLER_DO_DEFAULT; } +#endif +#ifdef VBOX_WITH_RAW_MODE /** * Synchronize the shadowed fields in the TSS. @@ -1534,16 +1537,11 @@ static DECLCALLBACK(int) selmR3GuestTSSWriteHandler(PVM pVM, RTGCPTR GCPtr, void */ VMMR3DECL(int) SELMR3SyncTSS(PVM pVM, PVMCPU pVCpu) { - int rc; - - if (pVM->selm.s.fDisableMonitoring) - { - VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_TSS); - return VINF_SUCCESS; - } + int rc; + AssertReturnStmt(!HMIsEnabled(pVM), VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_TSS), VINF_SUCCESS); STAM_PROFILE_START(&pVM->selm.s.StatTSSSync, a); - Assert(VMCPU_FF_ISSET(pVCpu, VMCPU_FF_SELM_SYNC_TSS)); + Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS)); /* * Get TR and extract and store the basic info. @@ -1641,7 +1639,7 @@ VMMR3DECL(int) SELMR3SyncTSS(PVM pVM, PVMCPU pVCpu) */ if (RT_SUCCESS(rc)) { -#ifdef LOG_ENABLED +# ifdef LOG_ENABLED if (LogIsEnabled()) { uint32_t ssr0, espr0; @@ -1658,12 +1656,23 @@ VMMR3DECL(int) SELMR3SyncTSS(PVM pVM, PVMCPU pVCpu) } Log(("offIoBitmap=%#x\n", Tss.offIoBitmap)); } -#endif /* LOG_ENABLED */ +# endif /* LOG_ENABLED */ AssertMsg(!(Tss.ss0 & 3), ("ring-1 leak into TSS.SS0? %04X:%08X\n", Tss.ss0, Tss.esp0)); /* Update our TSS structure for the guest's ring 1 stack */ selmSetRing1Stack(pVM, Tss.ss0 | 1, Tss.esp0); pVM->selm.s.fSyncTSSRing0Stack = fNoRing1Stack = false; + +# ifdef VBOX_WITH_RAW_RING1 + /* Update our TSS structure for the guest's ring 2 stack */ + if (EMIsRawRing1Enabled(pVM)) + { + if ( (pVM->selm.s.Tss.ss2 != ((Tss.ss1 & ~2) | 1)) + || pVM->selm.s.Tss.esp2 != Tss.esp1) + Log(("SELMR3SyncTSS: Updating TSS ring 1 stack to %04X:%08X from %04X:%08X\n", Tss.ss1, Tss.esp1, (pVM->selm.s.Tss.ss2 & ~2) | 1, pVM->selm.s.Tss.esp2)); + selmSetRing2Stack(pVM, (Tss.ss1 & ~1) | 2, Tss.esp1); + } +# endif } } @@ -1700,14 +1709,40 @@ VMMR3DECL(int) SELMR3SyncTSS(PVM pVM, PVMCPU pVCpu) /* Register the write handler if TS != 0. */ if (cbMonitoredTss != 0) { +# ifdef SELM_TRACK_GUEST_TSS_CHANGES rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtrTss, GCPtrTss + cbMonitoredTss - 1, 0, selmR3GuestTSSWriteHandler, "selmRCGuestTSSWriteHandler", 0, "Guest TSS write access handler"); if (RT_FAILURE(rc)) { +# ifdef VBOX_WITH_RAW_RING1 + /** @todo !HACK ALERT! + * Some guest OSes (QNX) share code and the TSS on the same page; + * PGMR3HandlerVirtualRegister doesn't support more than one + * handler, so we kick out the PATM handler as this one is more + * important. Fix this properly in PGMR3HandlerVirtualRegister? + */ + if (rc == VERR_PGM_HANDLER_VIRTUAL_CONFLICT) + { + LogRel(("SELMR3SyncTSS: Virtual handler conflict %RGv -> kick out PATM handler for the higher priority TSS page monitor\n", GCPtrTss)); + rc = PGMHandlerVirtualDeregister(pVM, GCPtrTss & PAGE_BASE_GC_MASK); + AssertRC(rc); + + rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtrTss, GCPtrTss + cbMonitoredTss - 1, + 0, selmR3GuestTSSWriteHandler, + "selmRCGuestTSSWriteHandler", 0, "Guest TSS write access handler"); + if (RT_FAILURE(rc)) + { + STAM_PROFILE_STOP(&pVM->selm.s.StatUpdateFromCPUM, a); + return rc; + } + } +# else STAM_PROFILE_STOP(&pVM->selm.s.StatUpdateFromCPUM, a); return rc; - } +# endif + } +# endif /* SELM_TRACK_GUEST_TSS_CHANGES */ /* Update saved Guest TSS info. */ pVM->selm.s.GCPtrGuestTss = GCPtrTss; @@ -1740,6 +1775,7 @@ VMMR3DECL(int) SELMR3DebugCheck(PVM pVM) { #ifdef VBOX_STRICT PVMCPU pVCpu = VMMGetCpu(pVM); + AssertReturn(!HMIsEnabled(pVM), VERR_SELM_HM_IPE); /* * Get GDTR and check for conflict. @@ -1875,10 +1911,10 @@ VMMR3DECL(int) SELMR3DebugCheck(PVM pVM) */ VMMR3DECL(bool) SELMR3CheckTSS(PVM pVM) { -#ifdef VBOX_STRICT +#if defined(VBOX_STRICT) && defined(SELM_TRACK_GUEST_TSS_CHANGES) PVMCPU pVCpu = VMMGetCpu(pVM); - if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_SELM_SYNC_TSS)) + if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS)) return true; /* @@ -2008,6 +2044,50 @@ VMMR3DECL(bool) SELMR3CheckTSS(PVM pVM) } +# ifdef VBOX_WITH_SAFE_STR +/** + * Validates the RawR0 TR shadow GDT entry. + * + * @returns true if it matches. + * @returns false and assertions on mismatch.. + * @param pVM Pointer to the VM. + */ +VMMR3DECL(bool) SELMR3CheckShadowTR(PVM pVM) +{ +# ifdef VBOX_STRICT + PX86DESC paGdt = pVM->selm.s.paGdtR3; + + /* + * TSS descriptor + */ + PX86DESC pDesc = &paGdt[pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] >> 3]; + RTRCPTR RCPtrTSS = VM_RC_ADDR(pVM, &pVM->selm.s.Tss); + + if ( pDesc->Gen.u16BaseLow != RT_LOWORD(RCPtrTSS) + || pDesc->Gen.u8BaseHigh1 != RT_BYTE3(RCPtrTSS) + || pDesc->Gen.u8BaseHigh2 != RT_BYTE4(RCPtrTSS) + || pDesc->Gen.u16LimitLow != sizeof(VBOXTSS) - 1 + || pDesc->Gen.u4LimitHigh != 0 + || (pDesc->Gen.u4Type != X86_SEL_TYPE_SYS_386_TSS_AVAIL && pDesc->Gen.u4Type != X86_SEL_TYPE_SYS_386_TSS_BUSY) + || pDesc->Gen.u1DescType != 0 /* system */ + || pDesc->Gen.u2Dpl != 0 /* supervisor */ + || pDesc->Gen.u1Present != 1 + || pDesc->Gen.u1Available != 0 + || pDesc->Gen.u1Long != 0 + || pDesc->Gen.u1DefBig != 0 + || pDesc->Gen.u1Granularity != 0 /* byte limit */ + ) + { + AssertFailed(); + return false; + } +# endif + return true; +} +# endif /* VBOX_WITH_SAFE_STR */ + +#endif /* VBOX_WITH_RAW_MODE */ + /** * Gets information about a 64-bit selector, SELMR3GetSelectorInfo helper. * @@ -2627,7 +2707,7 @@ static DECLCALLBACK(void) selmR3InfoLdtGuest(PVM pVM, PCDBGFINFOHLP pHlp, const */ VMMR3DECL(void) SELMR3DumpHyperGDT(PVM pVM) { - DBGFR3Info(pVM, "gdt", NULL, NULL); + DBGFR3Info(pVM->pUVM, "gdt", NULL, NULL); } @@ -2638,7 +2718,7 @@ VMMR3DECL(void) SELMR3DumpHyperGDT(PVM pVM) */ VMMR3DECL(void) SELMR3DumpHyperLDT(PVM pVM) { - DBGFR3Info(pVM, "ldt", NULL, NULL); + DBGFR3Info(pVM->pUVM, "ldt", NULL, NULL); } @@ -2649,7 +2729,7 @@ VMMR3DECL(void) SELMR3DumpHyperLDT(PVM pVM) */ VMMR3DECL(void) SELMR3DumpGuestGDT(PVM pVM) { - DBGFR3Info(pVM, "gdtguest", NULL, NULL); + DBGFR3Info(pVM->pUVM, "gdtguest", NULL, NULL); } @@ -2660,6 +2740,6 @@ VMMR3DECL(void) SELMR3DumpGuestGDT(PVM pVM) */ VMMR3DECL(void) SELMR3DumpGuestLDT(PVM pVM) { - DBGFR3Info(pVM, "ldtguest", NULL, NULL); + DBGFR3Info(pVM->pUVM, "ldtguest", NULL, NULL); } |
