SELMAll.cpp revision 19964cb6303141f460ac94ae46782cdb3df48d9a
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * SELM All contexts.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * available from http://www.virtualbox.org. This file is free software;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * General Public License (GPL) as published by the Free Software
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a3d06a524c4f1cde2f0eada83656543d5a24115dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * additional information or have any questions.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/*******************************************************************************
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync* Header Files *
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync*******************************************************************************/
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Converts a GC selector based address to a flat address.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * for that.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @returns Flat address.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param pVM VM Handle.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param Sel Selector part.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param Addr Address part.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @remarks Don't use when in long mode.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsyncSELMDECL(RTGCPTR) SELMToFlatBySel(PVM pVM, RTSEL Sel, RTGCPTR Addr)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync Assert(!CPUMIsGuestInLongMode(pVM)); /* DON'T USE! */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo check the limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo handle LDT pages not present! */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync return (RTGCPTR)((RTGCUINTPTR)Addr + X86DESC_BASE(Desc));
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Converts a GC selector based address to a flat address.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * for that.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @returns Flat address.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param pVM VM Handle.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param SelReg Selector register
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param pCtxCore CPU context
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param Addr Address part.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsyncSELMDECL(RTGCPTR) SELMToFlat(PVM pVM, DIS_SELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync rc = DISFetchRegSegEx(pCtxCore, SelReg, &Sel, &pHiddenSel); AssertRC(rc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Deal with real & v86 mode first.
c48c4d769ded37e2496f97dddbbd36dc62f244b1vboxsync /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
a3d06a524c4f1cde2f0eada83656543d5a24115dvboxsync /* 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). */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync return (RTGCPTR)(pHiddenSel->u64Base + (RTGCUINTPTR)Addr);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Converts a GC selector based address to a flat address.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Some basic checking is done, but not all kinds yet.
73e8df2e481cb3697372a3cf4acffd068a7f1296vboxsync * @returns VBox status
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param pVM VM Handle.
d293c8e7a1adaf427e7a361add878676749b7da6vboxsync * @param SelReg Selector register
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param pCtxCore CPU context
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param Addr Address part.
73e8df2e481cb3697372a3cf4acffd068a7f1296vboxsync * @param fFlags SELMTOFLAT_FLAGS_*
9704f1d0180960069e2c4eb8fe2ddee350910e5dvboxsync * GDT entires are valid.
d293c8e7a1adaf427e7a361add878676749b7da6vboxsync * @param ppvGC Where to store the GC flat address.
9704f1d0180960069e2c4eb8fe2ddee350910e5dvboxsyncSELMDECL(int) SELMToFlatEx(PVM pVM, DIS_SELREG SelReg, PCCPUMCTXCORE pCtxCore, RTGCPTR Addr, unsigned fFlags, PRTGCPTR ppvGC)
a3d06a524c4f1cde2f0eada83656543d5a24115dvboxsync rc = DISFetchRegSegEx(pCtxCore, SelReg, &Sel, &pHiddenSel); AssertRC(rc);
a3d06a524c4f1cde2f0eada83656543d5a24115dvboxsync * Deal with real & v86 mode first.
17d67aeb3722c094c6493a3e9a9d0cdfb9453ecdvboxsync *ppvGC = (RTGCPTR)(((RTGCUINTPTR)Sel << 4) + uFlat);
58b7773f17a933ab8d53f450bed0afcf2f003508vboxsync uint32_t u1Present, u1DescType, u1Granularity, u4Type;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync /* 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). */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync pvFlat = (RTGCPTR)(pHiddenSel->u64Base + (RTGCUINTPTR)Addr);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Check if present.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Type check.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** Read only selector type. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo fix this mess */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* check limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo fix this mess */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* check limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo fix this mess */
d15e1d56958bda40cd12a7c3a71c962b5a710be2vboxsync /* check limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync if (!u1Granularity && (RTGCUINTPTR)Addr > (RTGCUINTPTR)0xffff)
c48c4d769ded37e2496f97dddbbd36dc62f244b1vboxsync#endif /* !IN_GC */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync && (unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.GuestGdtr.cbGdt)
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync if ((unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.cbLdtLimit)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo handle LDT page(s) not present! */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /* calc limit. */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /* calc address assuming straight stuff. */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync pvFlat = (RTGCPTR)((RTGCUINTPTR)Addr + X86DESC_BASE(Desc));
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync * Check if present.
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync * Type check.
aca7a56d52c58d8b388343450503c22822fd6620vboxsync /** Read only selector type. */
aca7a56d52c58d8b388343450503c22822fd6620vboxsync /** @todo fix this mess */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync /* check limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo fix this mess */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* check limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo fix this mess */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* check limit. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync if (!u1Granularity && (RTGCUINTPTR)Addr > (RTGCUINTPTR)0xffff)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** @todo fix this mess */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* check limit. */
17d67aeb3722c094c6493a3e9a9d0cdfb9453ecdvboxsync#endif /* !IN_RING0 */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Converts a GC selector based address to a flat address.
c48c4d769ded37e2496f97dddbbd36dc62f244b1vboxsync * Some basic checking is done, but not all kinds yet.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @returns VBox status
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * @param pVM VM Handle.
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;