SELMAll.cpp revision b4e71cf6c41e074860ef96c394f6708caa94deb5
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * SELM All contexts.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * available from http://www.virtualbox.org. This file is free software;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * General Public License (GPL) as published by the Free Software
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * additional information or have any questions.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Header Files *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Converts a GC selector based address to a flat address.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * for that.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns Flat address.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pVM VM Handle.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param Sel Selector part.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param Addr Address part.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @remarks Don't use when in long mode.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncSELMDECL(RTGCPTR) SELMToFlatBySel(PVM pVM, RTSEL Sel, RTGCPTR Addr)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Assert(!CPUMIsGuestInLongMode(pVM)); /* DON'T USE! */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** @todo check the limit. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** @todo handle LDT pages not present! */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PX86DESC paLDT = (PX86DESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PX86DESC paLDT = (PX86DESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync return (RTGCPTR)((RTGCUINTPTR)Addr + X86DESC_BASE(Desc));
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Converts a GC selector based address to a flat address.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * for that.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns Flat address.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pVM VM Handle.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param SelReg Selector register
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pCtxCore CPU context
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param Addr Address part.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncSELMDECL(RTGCPTR) SELMToFlat(PVM pVM, DIS_SELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync rc = DISFetchRegSegEx(pCtxCore, SelReg, &Sel, &pHiddenSel); AssertRC(rc);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Deal with real & v86 mode first.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /* 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). */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync return (RTGCPTR)(pHiddenSel->u64Base + (RTGCUINTPTR)Addr);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Converts a GC selector based address to a flat address.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Some basic checking is done, but not all kinds yet.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns VBox status
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pVM VM Handle.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param SelReg Selector register
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pCtxCore CPU context
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param Addr Address part.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param fFlags SELMTOFLAT_FLAGS_*
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * GDT entires are valid.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param ppvGC Where to store the GC flat address.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncSELMDECL(int) SELMToFlatEx(PVM pVM, DIS_SELREG SelReg, PCCPUMCTXCORE pCtxCore, RTGCPTR Addr, unsigned fFlags, PRTGCPTR ppvGC)
if (ppvGC)
if ( pHiddenSel
return VINF_SUCCESS;
#ifndef IN_GC
if ( pHiddenSel
bool fCheckLimit = true;
/* 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). */
fCheckLimit = false;
switch (SelReg)
case DIS_SELREG_FS:
case DIS_SELREG_GS:
if (u1Present)
switch (u4Type)
case X86_SEL_TYPE_RO:
case X86_SEL_TYPE_RO_ACC:
case X86_SEL_TYPE_RW:
case X86_SEL_TYPE_RW_ACC:
case X86_SEL_TYPE_EO:
case X86_SEL_TYPE_EO_ACC:
case X86_SEL_TYPE_ER:
case X86_SEL_TYPE_ER_ACC:
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
case X86_SEL_TYPE_EO_CONF:
case X86_SEL_TYPE_EO_CONF_ACC:
case X86_SEL_TYPE_ER_CONF:
case X86_SEL_TYPE_ER_CONF_ACC:
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
case X86_SEL_TYPE_RO_DOWN:
case X86_SEL_TYPE_RO_DOWN_ACC:
case X86_SEL_TYPE_RW_DOWN:
case X86_SEL_TYPE_RW_DOWN_ACC:
if (fCheckLimit)
return VERR_OUT_OF_SELECTOR_BOUNDS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
return VERR_INVALID_SELECTOR;
#ifndef IN_RING0
return VERR_INVALID_SELECTOR;
return VERR_INVALID_SELECTOR;
#ifdef IN_GC
if (u1Present)
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
return VINF_SUCCESS;
return VERR_INVALID_SELECTOR;
return VERR_SELECTOR_NOT_PRESENT;
#ifndef IN_RING0
SELMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
if (ppvGC)
if ( pHiddenSel
if (pcb)
return VINF_SUCCESS;
if ( pHiddenSel
return VERR_INVALID_SELECTOR;
return VERR_INVALID_SELECTOR;
#ifdef IN_GC
if (u1Present)
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
if (pcb)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
if (pcb)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
if (pcb)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
if (ppvGC)
if (pcb)
return VINF_SUCCESS;
return VERR_INVALID_SELECTOR;
return VERR_SELECTOR_NOT_PRESENT;
DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVM pVM, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
return VINF_SUCCESS;
DECLINLINE(int) selmValidateAndConvertCSAddrStd(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits)
#ifdef IN_GC
if (pcBits)
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
return VERR_INVALID_RPL;
return VERR_NOT_CODE_SELECTOR;
return VERR_SELECTOR_NOT_PRESENT;
DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVM pVM, RTSEL SelCPL, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
/* 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). */
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_OUT_OF_SELECTOR_BOUNDS;
Log(("Invalid RPL Attr.n.u4Type=%x cpl=%x dpl=%x\n", pHidCS->Attr.n.u4Type, uLevel, pHidCS->Attr.n.u2Dpl));
return VERR_INVALID_RPL;
return VERR_NOT_CODE_SELECTOR;
return VERR_SELECTOR_NOT_PRESENT;
SELMDECL(int) SELMValidateAndConvertCSAddrGCTrap(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits)
SELMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, CPUMSELREGHID *pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat)
/** @todo when we're in 16 bits mode, we should cut off the address as well? (like in selmValidateAndConvertCSAddrRealMode) */
SELMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, CPUMSELREGHID *pHiddenSel)
return CPUMODE_16BIT;
return CPUMODE_64BIT;
#ifndef IN_RING0
int rc;
#ifdef IN_GC
bool fTriedAlready = false;
rc = MMGCRamRead(pVM, &tss.ss0, (RCPTRTYPE(void *))(GCPtrTss + RT_OFFSETOF(VBOXTSS, ss0)), sizeof(tss.ss0));
rc |= MMGCRamRead(pVM, &tss.esp0, (RCPTRTYPE(void *))(GCPtrTss + RT_OFFSETOF(VBOXTSS, esp0)), sizeof(tss.esp0));
#ifdef DEBUG
rc |= MMGCRamRead(pVM, &tss.offIoBitmap, (RCPTRTYPE(void *))(GCPtrTss + RT_OFFSETOF(VBOXTSS, offIoBitmap)), sizeof(tss.offIoBitmap));
if (!fTriedAlready)
fTriedAlready = true;
return rc;
goto l_tryagain;
return rc;
return rc;
#ifdef LOG_ENABLED
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_INVALID_RPL;
return VERR_NOT_CODE_SELECTOR;
return VERR_SELECTOR_NOT_PRESENT;
#ifndef IN_RING0
* @param pfCanHaveIOBitmap Where to store the can-have-I/O-bitmap indicator. (optional)
SELMDECL(int) SELMGetTSSInfo(PVM pVM, PRTGCUINTPTR pGCPtrTss, PRTGCUINTPTR pcbTss, bool *pfCanHaveIOBitmap)
return VERR_SELM_NO_TSS;
if (pfCanHaveIOBitmap)
if (pfCanHaveIOBitmap)
return VINF_SUCCESS;