summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/VMMAll/SELMAll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/VMMAll/SELMAll.cpp')
-rw-r--r--src/VBox/VMM/VMMAll/SELMAll.cpp106
1 files changed, 58 insertions, 48 deletions
diff --git a/src/VBox/VMM/VMMAll/SELMAll.cpp b/src/VBox/VMM/VMMAll/SELMAll.cpp
index 0b9a9c6d..317727dc 100644
--- a/src/VBox/VMM/VMMAll/SELMAll.cpp
+++ b/src/VBox/VMM/VMMAll/SELMAll.cpp
@@ -22,9 +22,11 @@
#define LOG_GROUP LOG_GROUP_SELM
#include <VBox/vmm/selm.h>
#include <VBox/vmm/stam.h>
+#include <VBox/vmm/em.h>
#include <VBox/vmm/mm.h>
+#include <VBox/vmm/hm.h>
#include <VBox/vmm/pgm.h>
-#include <VBox/vmm/hwaccm.h>
+#include <VBox/vmm/hm.h>
#include "SELMInternal.h"
#include <VBox/vmm/vm.h>
#include <VBox/err.h>
@@ -33,6 +35,8 @@
#include <VBox/vmm/vmm.h>
#include <iprt/x86.h>
+#include "SELMInline.h"
+
/*******************************************************************************
* Global Variables *
@@ -60,6 +64,7 @@ static char const g_aszSRegNms[X86_SREG_COUNT][4] = { "ES", "CS", "SS", "DS", "F
VMMDECL(RTGCPTR) SELMToFlatBySel(PVM pVM, RTSEL Sel, RTGCPTR Addr)
{
Assert(pVM->cCpus == 1 && !CPUMIsGuestInLongMode(VMMGetCpu(pVM))); /* DON'T USE! */
+ Assert(!HMIsEnabled(pVM));
/** @todo check the limit. */
X86DESC Desc;
@@ -183,7 +188,6 @@ VMMDECL(int) SELMToFlatEx(PVMCPU pVCpu, DISSELREG SelReg, PCPUMCTXCORE pCtxCore,
return VINF_SUCCESS;
}
-
#ifdef VBOX_WITH_RAW_MODE_NOT_R0
if (!CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg))
CPUMGuestLazyLoadHiddenSelectorReg(pVCpu, pSReg);
@@ -318,6 +322,7 @@ VMMDECL(int) SELMToFlatBySelEx(PVMCPU pVCpu, X86EFLAGS eflags, RTSEL Sel, RTGCPT
uint32_t fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
{
Assert(!CPUMIsGuestInLongMode(pVCpu)); /* DON'T USE! (Accessing shadow GDT/LDT.) */
+ Assert(!HMIsEnabled(pVCpu->CTX_SUFF(pVM)));
/*
* Deal with real & v86 mode first.
@@ -484,6 +489,8 @@ VMMDECL(int) SELMToFlatBySelEx(PVMCPU pVCpu, X86EFLAGS eflags, RTSEL Sel, RTGCPT
static void selLoadHiddenSelectorRegFromGuestTable(PVMCPU pVCpu, PCCPUMCTX pCtx, PCPUMSELREG pSReg,
RTGCPTR GCPtrDesc, RTSEL const Sel, uint32_t const iSReg)
{
+ Assert(!HMIsEnabled(pVCpu->CTX_SUFF(pVM)));
+
/*
* Try read the entry.
*/
@@ -537,6 +544,7 @@ VMM_INT_DECL(void) SELMLoadHiddenSelectorReg(PVMCPU pVCpu, PCCPUMCTX pCtx, PCPUM
PVM pVM = pVCpu->CTX_SUFF(pVM);
Assert(pVM->cCpus == 1);
+ Assert(!HMIsEnabled(pVM));
/*
@@ -630,6 +638,8 @@ DECLINLINE(int) selmValidateAndConvertCSAddrRawMode(PVM pVM, PVMCPU pVCpu, RTSEL
PRTGCPTR ppvFlat, uint32_t *pcBits)
{
NOREF(pVCpu);
+ Assert(!HMIsEnabled(pVM));
+
/** @todo validate limit! */
X86DESC Desc;
if (!(SelCS & X86_SEL_LDT))
@@ -714,40 +724,27 @@ DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, R
if ( pSRegCS->Attr.n.u1DescType == 1
&& (pSRegCS->Attr.n.u4Type & X86_SEL_TYPE_CODE))
{
+ /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
+ (Intel® 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
+ if ( pSRegCS->Attr.n.u1Long
+ && CPUMIsGuestInLongMode(pVCpu))
+ {
+ *ppvFlat = Addr;
+ return VINF_SUCCESS;
+ }
+
/*
- * Check level.
+ * Limit check. Note that the limit in the hidden register is the
+ * final value. The granularity bit was included in its calculation.
*/
- unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL);
- if ( !(pSRegCS->Attr.n.u4Type & X86_SEL_TYPE_CONF)
- ? uLevel <= pSRegCS->Attr.n.u2Dpl
- : uLevel >= pSRegCS->Attr.n.u2Dpl /* hope I got this right now... */
- )
+ uint32_t u32Limit = pSRegCS->u32Limit;
+ if ((RTGCUINTPTR)Addr <= u32Limit)
{
- /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
- (Intel® 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
- if ( pSRegCS->Attr.n.u1Long
- && CPUMIsGuestInLongMode(pVCpu))
- {
- *ppvFlat = Addr;
- return VINF_SUCCESS;
- }
-
- /*
- * Limit check. Note that the limit in the hidden register is the
- * final value. The granularity bit was included in its calculation.
- */
- uint32_t u32Limit = pSRegCS->u32Limit;
- if ((RTGCUINTPTR)Addr <= u32Limit)
- {
- *ppvFlat = Addr + pSRegCS->u64Base;
- return VINF_SUCCESS;
- }
-
- return VERR_OUT_OF_SELECTOR_BOUNDS;
+ *ppvFlat = Addr + pSRegCS->u64Base;
+ return VINF_SUCCESS;
}
- Log(("selmValidateAndConvertCSAddrHidden: Invalid RPL Attr.n.u4Type=%x cpl=%x dpl=%x\n",
- pSRegCS->Attr.n.u4Type, uLevel, pSRegCS->Attr.n.u2Dpl));
- return VERR_INVALID_RPL;
+
+ return VERR_OUT_OF_SELECTOR_BOUNDS;
}
return VERR_NOT_CODE_SELECTOR;
}
@@ -785,10 +782,10 @@ VMMDECL(int) SELMValidateAndConvertCSAddr(PVMCPU pVCpu, X86EFLAGS Efl, RTSEL Sel
CPUMGuestLazyLoadHiddenSelectorReg(pVCpu, pSRegCS);
/* Undo ring compression. */
- if ((SelCPL & X86_SEL_RPL) == 1 && !HWACCMIsEnabled(pVCpu->CTX_SUFF(pVM)))
+ if ((SelCPL & X86_SEL_RPL) == 1 && !HMIsEnabled(pVCpu->CTX_SUFF(pVM)))
SelCPL &= ~X86_SEL_RPL;
Assert(pSRegCS->Sel == SelCS);
- if ((SelCS & X86_SEL_RPL) == 1 && !HWACCMIsEnabled(pVCpu->CTX_SUFF(pVM)))
+ if ((SelCS & X86_SEL_RPL) == 1 && !HMIsEnabled(pVCpu->CTX_SUFF(pVM)))
SelCS &= ~X86_SEL_RPL;
#else
Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSRegCS));
@@ -832,12 +829,31 @@ VMMDECL(void) SELMSetTrap8EIP(PVM pVM, uint32_t u32EIP)
*/
void selmSetRing1Stack(PVM pVM, uint32_t ss, RTGCPTR32 esp)
{
+ Assert(!HMIsEnabled(pVM));
Assert((ss & 1) || esp == 0);
pVM->selm.s.Tss.ss1 = ss;
pVM->selm.s.Tss.esp1 = (uint32_t)esp;
}
+#ifdef VBOX_WITH_RAW_RING1
+/**
+ * Sets ss:esp for ring1 in main Hypervisor's TSS.
+ *
+ * @param pVM Pointer to the VM.
+ * @param ss Ring2 SS register value. Pass 0 if invalid.
+ * @param esp Ring2 ESP register value.
+ */
+void selmSetRing2Stack(PVM pVM, uint32_t ss, RTGCPTR32 esp)
+{
+ Assert(!HMIsEnabled(pVM));
+ Assert((ss & 3) == 2 || esp == 0);
+ pVM->selm.s.Tss.ss2 = ss;
+ pVM->selm.s.Tss.esp2 = (uint32_t)esp;
+}
+#endif
+
+
#ifdef VBOX_WITH_RAW_MODE_NOT_R0
/**
* Gets ss:esp for ring1 in main Hypervisor's TSS.
@@ -851,11 +867,14 @@ void selmSetRing1Stack(PVM pVM, uint32_t ss, RTGCPTR32 esp)
*/
VMMDECL(int) SELMGetRing1Stack(PVM pVM, uint32_t *pSS, PRTGCPTR32 pEsp)
{
+ Assert(!HMIsEnabled(pVM));
Assert(pVM->cCpus == 1);
PVMCPU pVCpu = &pVM->aCpus[0];
+#ifdef SELM_TRACK_GUEST_TSS_CHANGES
if (pVM->selm.s.fSyncTSSRing0Stack)
{
+#endif
RTGCPTR GCPtrTss = pVM->selm.s.GCPtrGuestTss;
int rc;
VBOXTSS tss;
@@ -912,7 +931,9 @@ l_tryagain:
/* Update our TSS structure for the guest's ring 1 stack */
selmSetRing1Stack(pVM, tss.ss0 | 1, (RTGCPTR32)tss.esp0);
pVM->selm.s.fSyncTSSRing0Stack = false;
+#ifdef SELM_TRACK_GUEST_TSS_CHANGES
}
+#endif
*pSS = pVM->selm.s.Tss.ss1;
*pEsp = (RTGCPTR32)pVM->selm.s.Tss.esp1;
@@ -922,18 +943,7 @@ l_tryagain:
#endif /* VBOX_WITH_RAW_MODE_NOT_R0 */
-/**
- * Returns Guest TSS pointer
- *
- * @returns Pointer to the guest TSS, RTRCPTR_MAX if not being monitored.
- * @param pVM Pointer to the VM.
- */
-VMMDECL(RTGCPTR) SELMGetGuestTSS(PVM pVM)
-{
- return (RTGCPTR)pVM->selm.s.GCPtrGuestTss;
-}
-
-#ifdef VBOX_WITH_RAW_MODE_NOT_R0
+#if defined(VBOX_WITH_RAW_MODE) || (HC_ARCH_BITS != 64 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL))
/**
* Gets the hypervisor code selector (CS).
@@ -1007,7 +1017,7 @@ VMMDECL(RTRCPTR) SELMGetHyperGDT(PVM pVM)
return (RTRCPTR)MMHyperR3ToRC(pVM, pVM->selm.s.paGdtR3);
}
-#endif /* VBOX_WITH_RAW_MODE_NOT_R0 */
+#endif /* defined(VBOX_WITH_RAW_MODE) || (HC_ARCH_BITS != 64 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)) */
/**
* Gets info about the current TSS.
@@ -1054,7 +1064,7 @@ VMMDECL(int) SELMGetTSSInfo(PVM pVM, PVMCPU pVCpu, PRTGCUINTPTR pGCPtrTss, PRTGC
*/
VMMDECL(void) SELMShadowCR3Changed(PVM pVM, PVMCPU pVCpu)
{
- /** @todo SMP support!! */
+ /** @todo SMP support!! (64-bit guest scenario, primarily) */
pVM->selm.s.Tss.cr3 = PGMGetHyperCR3(pVCpu);
pVM->selm.s.TssTrap08.cr3 = PGMGetInterRCCR3(pVM, pVCpu);
}