IEMAllCImpl.cpp.h revision d7df7c08b02258693dde2798b5af5add5f47cc20
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * IEM - Instruction Implementation in C/C++ (code include).
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Copyright (C) 2011-2013 Oracle Corporation
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * available from http://www.virtualbox.org. This file is free software;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * General Public License (GPL) as published by the Free Software
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/** @name Misc Helpers
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * Worker function for iemHlpCheckPortIOPermission, don't call directly.
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * @returns Strict VBox status code.
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * @param pIemCpu The IEM per CPU data.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pCtx The register context.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param u16Port The port number.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param cbOperand The operand size.
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic VBOXSTRICTRC iemHlpCheckPortIOPermissionBitmap(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint16_t u16Port, uint8_t cbOperand)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* The TSS bits we're interested in are the same on 386 and AMD64. */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync AssertCompile(AMD64_SEL_TYPE_SYS_TSS_BUSY == X86_SEL_TYPE_SYS_386_TSS_BUSY);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync AssertCompile(AMD64_SEL_TYPE_SYS_TSS_AVAIL == X86_SEL_TYPE_SYS_386_TSS_AVAIL);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync AssertCompileMembersAtSameOffset(X86TSS32, offIoBitmap, X86TSS64, offIoBitmap);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync AssertCompile(sizeof(X86TSS32) == sizeof(X86TSS64));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Check the TSS type, 16-bit TSSes doesn't have any I/O permission bitmap.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (RT_UNLIKELY( pCtx->tr.Attr.n.u4Type != AMD64_SEL_TYPE_SYS_TSS_BUSY
a180a41bba1d50822df23fff0099e90b86638b89vboxsync && pCtx->tr.Attr.n.u4Type != AMD64_SEL_TYPE_SYS_TSS_AVAIL))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Log(("iemHlpCheckPortIOPermissionBitmap: Port=%#x cb=%d - TSS type %#x (attr=%#x) has no I/O bitmap -> #GP(0)\n",
a180a41bba1d50822df23fff0099e90b86638b89vboxsync u16Port, cbOperand, pCtx->tr.Attr.n.u4Type, pCtx->tr.Attr.u));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Read the bitmap offset (may #PF).
a180a41bba1d50822df23fff0099e90b86638b89vboxsync VBOXSTRICTRC rcStrict = iemMemFetchSysU16(pIemCpu, &offBitmap, UINT8_MAX,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync pCtx->tr.u64Base + RT_OFFSETOF(X86TSS64, offIoBitmap));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Log(("iemHlpCheckPortIOPermissionBitmap: Error reading offIoBitmap (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * The bit range from u16Port to (u16Port + cbOperand - 1), however intel
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * describes the CPU actually reading two bytes regardless of whether the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * bit range crosses a byte boundrary. Thus the + 1 in the test below.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32_t offFirstBit = (uint32_t)u16Port / 8 + offBitmap;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /** @todo check if real CPUs ensures that offBitmap has a minimum value of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * for instance sizeof(X86TSS32). */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (offFirstBit + 1 > pCtx->tr.u32Limit) /* the limit is inclusive */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Log(("iemHlpCheckPortIOPermissionBitmap: offFirstBit=%#x + 1 is beyond u32Limit=%#x -> #GP(0)\n",
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Read the necessary bits.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /** @todo Test the assertion in the intel manual that the CPU reads two
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * bytes. The question is how this works wrt to #PF and #GP on the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * 2nd byte when it's not required. */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rcStrict = iemMemFetchSysU16(pIemCpu, &bmBytes, UINT8_MAX, pCtx->tr.u64Base + offFirstBit);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Log(("iemHlpCheckPortIOPermissionBitmap: Error reading I/O bitmap @%#x (%Rrc)\n", offFirstBit, VBOXSTRICTRC_VAL(rcStrict)));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Perform the check.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Log(("iemHlpCheckPortIOPermissionBitmap: u16Port=%#x LB %u - access denied (bm=%#x mask=%#x) -> #GP(0)\n",
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Checks if we are allowed to access the given I/O port, raising the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * appropriate exceptions if we aren't (or if the I/O bitmap is not
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * accessible).
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @returns Strict VBox status code.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pIemCpu The IEM per CPU data.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pCtx The register context.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param u16Port The port number.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param cbOperand The operand size.
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncDECLINLINE(VBOXSTRICTRC) iemHlpCheckPortIOPermission(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint16_t u16Port, uint8_t cbOperand)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return iemHlpCheckPortIOPermissionBitmap(pIemCpu, pCtx, u16Port, cbOperand);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Calculates the parity bit.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @returns true if the bit is set, false if not.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param u8Result The least significant byte of the result.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Parity is set if the number of bits in the least significant byte of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * the result is even.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#endif /* not used */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Updates the specified flags according to a 8-bit result.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pIemCpu The IEM state of the calling EMT.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param u8Result The result to set the flags according to.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param fToUpdate The flags to update.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param fUndefined The flags that are specified as undefined.
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void iemHlpUpdateArithEFlagsU8(PIEMCPU pIemCpu, uint8_t u8Result, uint32_t fToUpdate, uint32_t fUndefined)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync pCtx->eflags.u |= (fToUpdate | fUndefined) & fEFlags;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Loads a NULL data selector into a selector register, both the hidden and
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * visible parts, in protected mode.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pSReg Pointer to the segment register.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param uRpl The RPL.
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void iemHlpLoadNullDataSelectorProt(PCPUMSELREG pSReg, RTSEL uRpl)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /** @todo Testcase: write a testcase checking what happends when loading a NULL
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * data selector in protected mode. */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Helper used by iret.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param uCpl The new CPL.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pSReg Pointer to the segment register.
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void iemHlpAdjustSelectorForNewCpl(PIEMCPU pIemCpu, uint8_t uCpl, PCPUMSELREG pSReg)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!CPUMSELREG_ARE_HIDDEN_PARTS_VALID(IEMCPU_TO_VMCPU(pIemCpu), pSReg))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync CPUMGuestLazyLoadHiddenSelectorReg(IEMCPU_TO_VMCPU(pIemCpu), pSReg);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(IEMCPU_TO_VMCPU(pIemCpu), pSReg));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync && pSReg->Attr.n.u1DescType /* code or data, not system */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync && (pSReg->Attr.n.u4Type & (X86_SEL_TYPE_CODE | X86_SEL_TYPE_CONF))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync != (X86_SEL_TYPE_CODE | X86_SEL_TYPE_CONF)) /* not conforming code */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Indicates that we have modified the FPU state.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * @param pIemCpu The IEM state of the calling EMT.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync CPUMSetChangedFlags(IEMCPU_TO_VMCPU(pIemCpu), CPUM_CHANGED_FPU_REM);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/** @name C Implementations
return rcStrict;
return rcStrict;
GCPtrBottom--;
return rcStrict;
GCPtrBottom--;
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
return VINF_SUCCESS;
switch (enmEffOpSize)
case IEMMODE_16BIT:
return rcStrict;
case IEMMODE_32BIT:
return rcStrict;
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
return rcStrict;
case IEMMODE_32BIT:
return rcStrict;
case IEMMODE_64BIT:
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
IEM_CIMPL_DEF_4(iemCImpl_BranchTaskSegment, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
IEM_CIMPL_DEF_4(iemCImpl_BranchTaskGate, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
IEM_CIMPL_DEF_4(iemCImpl_BranchCallGate, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
IEM_CIMPL_DEF_4(iemCImpl_BranchSysSel, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
case AMD64_SEL_TYPE_SYS_LDT:
case X86_SEL_TYPE_SYS_LDT:
return VINF_SUCCESS;
return rcStrict;
Log(("jmpf %04x:%08RX64 -> not a code selector (u4Type=%#x).\n", uSel, offSeg, Desc.Legacy.Gen.u4Type));
Log(("jmpf %04x:%08RX64 -> CPL != DPL; DPL=%d CPL=%u\n", uSel, offSeg, Desc.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
Log(("jmpf %04x:%08RX64 -> RPL > DPL; RPL=%d CPL=%u\n", uSel, offSeg, (uSel & X86_SEL_RPL), pIemCpu->uCpl));
u64Base = 0;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
Log(("callf %04x:%08RX64 -> not a code selector (u4Type=%#x).\n", uSel, offSeg, Desc.Legacy.Gen.u4Type));
Log(("callf %04x:%08RX64 -> CPL != DPL; DPL=%d CPL=%u\n", uSel, offSeg, Desc.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
Log(("callf %04x:%08RX64 -> RPL > DPL; RPL=%d CPL=%u\n", uSel, offSeg, (uSel & X86_SEL_RPL), pIemCpu->uCpl));
return rcStrict;
u64Base = 0;
return rcStrict;
uPtrRet.pu32[1] = pCtx->cs.Sel; /** @todo Testcase: What is written to the high word when callf is pushing CS? */
uPtrRet.pu64[1] = pCtx->cs.Sel; /** @todo Testcase: What is written to the high words when callf is pushing CS? */
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
if (cbPop)
return VINF_SUCCESS;
return rcStrict;
if ( DescCs.Legacy.Gen.u1Long /** @todo Testcase: far return to a selector with both L and D set. */
return rcStrict;
return rcStrict;
Log(("retf %04x:%08RX64 %04x:%08RX64 - SS.RPL != CS.RPL -> #GP(SS)\n", uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp));
Log(("retf %04x:%08RX64 %04x:%08RX64 - SS not a writable data segment (u1DescType=%u u4Type=%#x) -> #GP(SS).\n",
uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp, DescSs.Legacy.Gen.u1DescType, DescSs.Legacy.Gen.u4Type));
if ( DescSs.Legacy.Gen.u1Long /** @todo Testcase: far return to a stack selector with both L and D set. */
uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp, DescSs.Legacy.Gen.u1DescType, DescSs.Legacy.Gen.u4Type));
Log(("retf %04x:%08RX64 %04x:%08RX64 - SS not present -> #NP(SS).\n", uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp));
Log(("retf %04x:%08RX64 %04x:%08RX64 - not canonical -> #GP.\n", uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp));
u64Base = 0;
return rcStrict;
return rcStrict;
return rcStrict;
pCtx->rip = uNewRip & UINT16_MAX; /** @todo Testcase: When exactly does this occur? With call it happens prior to the limit check according to Intel... */
if (cbPop)
u64Base = 0;
return rcStrict;
return rcStrict;
pCtx->rip = uNewRip & UINT16_MAX; /** @todo Testcase: When exactly does this occur? With call it happens prior to the limit check according to Intel... */
if (cbPop)
return VINF_SUCCESS;
switch (enmEffOpSize)
case IEMMODE_16BIT:
NewRip.u = 0;
case IEMMODE_32BIT:
NewRip.u = 0;
case IEMMODE_64BIT:
return rcStrict;
if (cbPop)
return VINF_SUCCESS;
return rcStrict;
if (cParameters > 0)
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
NewRbp.u = 0;
case IEMMODE_64BIT:
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
| X86_EFL_ID;
return rcStrict;
return rcStrict;
#ifdef DBGFTRACE_ENABLED
RTTraceBufAddMsgF(IEMCPU_TO_VM(pIemCpu)->CTX_SUFF(hTraceBuf), "iret/rm %04x:%04x -> %04x:%04x %x %04llx",
return VINF_SUCCESS;
pSReg->Attr.u = X86_SEL_TYPE_RW_ACC | RT_BIT(4) /*!sys*/ | RT_BIT(7) /*P*/ | (3 /*DPL*/ << 5); /* VT-x wants 0xf3 */
if (!LogIs6Enabled())
return VERR_IEM_RESTART_INSTRUCTION;
return rcStrict;
rcStrict = iemMemCommitAndUnmap(pIemCpu, (void *)uFrame.pv, IEM_ACCESS_STACK_R); /* don't use iemMemStackPopCommitSpecial here. */
return rcStrict;
#ifdef DBGFTRACE_ENABLED
RTTraceBufAddMsgF(IEMCPU_TO_VM(pIemCpu)->CTX_SUFF(hTraceBuf), "iret/p/v %04x:%08x -> %04x:%04x %x %04x:%04x",
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
rcStrict = iemMemCommitAndUnmap(pIemCpu, (void *)uFrame.pv, IEM_ACCESS_STACK_R); /* don't use iemMemStackPopCommitSpecial here. */
return rcStrict;
Log(("iret %04x:%08x - rcStrict=%Rrc when fetching CS\n", uNewCs, uNewEip, VBOXSTRICTRC_VAL(rcStrict)));
return rcStrict;
Log(("iret %04x:%08x - CS is system segment (%#x) -> #GP\n", uNewCs, uNewEip, DescCS.Legacy.Gen.u4Type));
Log(("iret %04x:%08x - not code segment (%#x) -> #GP\n", uNewCs, uNewEip, DescCS.Legacy.Gen.u4Type));
return rcStrict;
return rcStrict;
return rcStrict;
Log(("iret %04x:%08x/%04x:%08x -> invalid SS selector, #GP(0)\n", uNewCs, uNewEip, uNewSS, uNewESP));
rcStrict = iemMemFetchSelDesc(pIemCpu, &DescSS, uNewSS, X86_XCPT_GP); /** @todo Correct exception? */
return rcStrict;
return rcStrict;
return rcStrict;
#ifdef DBGFTRACE_ENABLED
RTTraceBufAddMsgF(IEMCPU_TO_VM(pIemCpu)->CTX_SUFF(hTraceBuf), "iret/%up%u %04x:%08x -> %04x:%04x %x %04x:%04x",
return rcStrict;
#ifdef DBGFTRACE_ENABLED
RTTraceBufAddMsgF(IEMCPU_TO_VM(pIemCpu)->CTX_SUFF(hTraceBuf), "iret/%up %04x:%08x -> %04x:%04x %x %04x:%04llx",
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
return rcStrict;
rcStrict = iemMemCommitAndUnmap(pIemCpu, (void *)uFrame.pv, IEM_ACCESS_STACK_R); /* don't use iemMemStackPopCommitSpecial here. */
return rcStrict;
Log(("iret %04x:%016RX64/%04x:%016RX64 -> invalid CS selector, #GP(0)\n", uNewCs, uNewRip, uNewSs, uNewRsp));
return rcStrict;
Log(("iret %04x:%016RX64/%04x:%016RX64 - RPL < CPL (%d) -> #GP\n", uNewCs, uNewRip, uNewSs, uNewRsp, pIemCpu->uCpl));
Log(("iret %04x:%016RX64/%04x:%016RX64 - CS not present -> #NP\n", uNewCs, uNewRip, uNewSs, uNewRsp));
|| DescCS.Legacy.Gen.u1DefBig /** @todo exactly how does iret (and others) behave with u1Long=1 and u1DefBig=1? \#GP(sel)? */
Log(("iret %04x:%016RX64/%04x:%016RX64 -> invalid SS selector, #GP(0)\n", uNewCs, uNewRip, uNewSs, uNewRsp));
rcStrict = iemMemFetchSelDesc(pIemCpu, &DescSS, uNewSs, X86_XCPT_GP); /** @todo Correct exception? */
return rcStrict;
Log(("iret %04x:%016RX64/%04x:%016RX64 -> SS.RPL != CS.RPL -> #GP\n", uNewCs, uNewRip, uNewSs, uNewRsp));
Log(("iret %04x:%016RX64/%04x:%016RX64 -> SS not present -> #SS\n", uNewCs, uNewRip, uNewSs, uNewRsp));
return rcStrict;
return rcStrict;
#ifdef DBGFTRACE_ENABLED
RTTraceBufAddMsgF(IEMCPU_TO_VM(pIemCpu)->CTX_SUFF(hTraceBuf), "iret/%ul%u %08llx -> %04x:%04llx %llx %04x:%04llx",
Log2(("iretq new SS: base=%#RX64 lim=%#x attr=%#x\n", pCtx->ss.u64Base, pCtx->ss.u32Limit, pCtx->ss.Attr.u));
return VINF_SUCCESS;
Log(("syscall: %04x:%016RX64 [efl=%#llx] -> %04x:%016RX64\n", pCtx->cs, pCtx->rip, pCtx->rflags.u, uNewCs, uNewRip));
pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_L | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC;
pCtx->ss.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_L | X86DESCATTR_DT | X86_SEL_TYPE_RW_ACC;
pCtx->cs, pCtx->eip, pCtx->eflags.u, uNewCs, (uint32_t)(pCtx->msrSTAR & MSR_K6_STAR_SYSCALL_EIP_MASK)));
pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC;
pCtx->ss.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_RW_ACC;
return VINF_SUCCESS;
pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_L | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC
pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC
Log(("sysret: %04x:%08RX32 [efl=%#x] -> %04x:%08RX32\n", pCtx->cs, pCtx->eip, pCtx->eflags.u, uNewCs, pCtx->ecx));
pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC
return VINF_SUCCESS;
#if 0 /* AMD Volume 2, chapter 4.1 - "real mode segmentation" - states that limit and attributes are untouched. */
return VINF_SUCCESS;
/** @todo We cannot 'mov ss, 3' in 64-bit kernel mode, can we? There is a testcase (bs-cpu-xcpt-1), but double check this! */
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemFetchSelDesc(pIemCpu, &Desc, uSel, X86_XCPT_GP); /** @todo Correct exception? */
return rcStrict;
Log(("load sreg SS, %#x - DPL (%d) and CPL (%d) differs -> #GP\n", uSel, Desc.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
u64Base = 0;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
static VBOXSTRICTRC iemCImpl_LoadDescHelper(PIEMCPU pIemCpu, uint16_t uSel, bool fAllowSysDesc, PIEMSELDESC pDesc)
return VINF_IEM_SELECTOR_NOT_OK;
return VINF_IEM_SELECTOR_NOT_OK;
return VINF_IEM_SELECTOR_NOT_OK;
VBOXSTRICTRC rcStrict = iemMemFetchSysU64(pIemCpu, &pDesc->Legacy.u, UINT8_MAX, GCPtrBase + (uSel & X86_SEL_MASK));
return rcStrict;
if (!fAllowSysDesc)
return VINF_IEM_SELECTOR_NOT_OK;
rcStrict = iemMemFetchSysU64(pIemCpu, &pDesc->Long.au64[1], UINT8_MAX, GCPtrBase + (uSel & X86_SEL_MASK) + 8);
return rcStrict;
return VINF_SUCCESS;
bool fAccessible = true;
fAccessible = false;
if ( fWrite
fAccessible = false;
fAccessible = false;
fAccessible = false;
fAccessible = false;
return rcStrict;
return VINF_SUCCESS;
IEM_CIMPL_DEF_4(iemCImpl_LarLsl_u64, uint64_t *, pu64Dst, uint16_t, uSel, uint32_t *, pEFlags, bool, fIsLar)
bool fDescOk = true;
fDescOk = false;
case AMD64_SEL_TYPE_SYS_LDT: /** @todo Intel lists this as invalid for LAR, AMD and 32-bit does otherwise. */
fDescOk = false;
case X86_SEL_TYPE_SYS_LDT:
fDescOk = false;
if (fDescOk)
if ( (Desc.Legacy.Gen.u4Type & (X86_SEL_TYPE_CODE | X86_SEL_TYPE_CONF)) != (X86_SEL_TYPE_CODE | X86_SEL_TYPE_CONF)
fDescOk = false;
fDescOk = false;
if (fDescOk)
if (fIsLar)
fDescOk = false;
return rcStrict;
return VINF_SUCCESS;
IEM_CIMPL_DEF_4(iemCImpl_LarLsl_u16, uint16_t *, pu16Dst, uint16_t, uSel, uint32_t *, pEFlags, bool, fIsLar)
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemFetchDataXdtr(pIemCpu, &cbLimit, &GCPtrBase, iEffSeg, GCPtrEffSrc, enmEffOpSize);
return rcStrict;
VBOXSTRICTRC rcStrict = iemMemStoreDataXdtr(pIemCpu, pCtx->gdtr.cbGdt, pCtx->gdtr.pGdt, iEffSeg, GCPtrEffDst, enmEffOpSize);
return rcStrict;
VBOXSTRICTRC rcStrict = iemMemFetchDataXdtr(pIemCpu, &cbLimit, &GCPtrBase, iEffSeg, GCPtrEffSrc, enmEffOpSize);
return rcStrict;
VBOXSTRICTRC rcStrict = iemMemStoreDataXdtr(pIemCpu, pCtx->idtr.cbIdt, pCtx->idtr.pIdt, iEffSeg, GCPtrEffDst, enmEffOpSize);
return rcStrict;
if (!IEM_IS_GUEST_CPU_AMD(pIemCpu) || !IEM_VERIFICATION_ENABLED(pIemCpu)) /* See bs-cpu-hidden-regs-1 on AMD. */
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemFetchSelDesc(pIemCpu, &Desc, uNewLdt, X86_XCPT_GP); /** @todo Correct exception? */
return rcStrict;
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemFetchSelDesc(pIemCpu, &Desc, uNewTr, X86_XCPT_GP); /** @todo Correct exception? */
return rcStrict;
if ( Desc.Legacy.Gen.u4Type != X86_SEL_TYPE_SYS_386_TSS_AVAIL /* same as AMD64_SEL_TYPE_SYS_TSS_AVAIL */
Log(("ltr %#x - not an available TSS selector (type %x) -> #GP\n", uNewTr, Desc.Legacy.Gen.u4Type));
void *pvDesc;
rcStrict = iemMemMap(pIemCpu, &pvDesc, 8, UINT8_MAX, pCtx->gdtr.pGdt + (uNewTr & X86_SEL_MASK_OFF_RPL), IEM_ACCESS_DATA_RW);
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
switch (iCrReg)
crX = 0;
return VINF_SUCCESS;
int rc;
switch (iCrReg)
Log(("Trying to set reserved CR0 bits: NewCR0=%#llx InvalidBits=%#llx\n", uNewCrX, uNewCrX & ~(uint64_t)fValid));
#ifdef IN_RC
Log(("Trying to set reserved CR4 bits: NewCR4=%#llx InvalidBits=%#llx\n", uNewCrX, uNewCrX & ~(uint64_t)fValid));
#ifdef VBOX_WITH_RAW_MODE
return rcStrict;
switch (iDrReg)
return VINF_SUCCESS;
switch (iDrReg)
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
#ifdef IEM_VERIFICATION_MODE_FULL
return VINF_SUCCESS;
return VINF_SUCCESS;
int rc;
return VINF_SUCCESS;
return rcStrict;
rcStrict = IOMIOPortRead(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu), u16Port, &u32Value, cbReg);
switch (cbReg)
return rcStrict;
return rcStrict;
switch (cbReg)
rcStrict = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu), u16Port, u32Value, cbReg);
return rcStrict;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_EM_HALT;
if (uEcx != 0)
VBOXSTRICTRC rcStrict = iemMemApplySegment(pIemCpu, IEM_ACCESS_TYPE_READ | IEM_ACCESS_WHAT_DATA, iEffSeg, 1, &GCPtrMem);
return rcStrict;
rcStrict = iemMemPageTranslateAndCheckAccess(pIemCpu, GCPtrMem, IEM_ACCESS_TYPE_READ | IEM_ACCESS_WHAT_DATA, &GCPhysMem);
return rcStrict;
rcStrict = EMMonitorWaitPrepare(IEMCPU_TO_VMCPU(pIemCpu), pCtx->rax, pCtx->rcx, pCtx->rdx, GCPhysMem);
return rcStrict;
if (uEcx != 0)
Log2(("mwait eax=%RX32, ecx=%RX32; break-on-IRQ-IF=0 extension not enabled -> #GP(0)\n", uEax, uEcx));
return rcStrict;
return VINF_SUCCESS;
CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), pCtx->eax, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx);
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
return VINF_SUCCESS;
void *pvMem512;
VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, &pvMem512, 512, iEffSeg, GCPtrEff, IEM_ACCESS_DATA_W | IEM_ACCESS_PARTIAL_WRITE);
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
void *pvMem512;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
static void iemCImplCommonFpuStoreEnv(PIEMCPU pIemCpu, IEMMODE enmEffOpSize, RTPTRUNION uPtr, PCCPUMCTX pCtx)
static void iemCImplCommonFpuRestoreEnv(PIEMCPU pIemCpu, IEMMODE enmEffOpSize, RTCPTRUNION uPtr, PCPUMCTX pCtx)
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, (void **)&uPtr.pv, enmEffOpSize == IEMMODE_16BIT ? 14 : 28,
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, (void **)&uPtr.pv, enmEffOpSize == IEMMODE_16BIT ? 94 : 108,
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
uint32_t u32Eflags = pfnAImpl(&pCtx->fpu, &u16Fsw, &pCtx->fpu.aRegs[0].r80, &pCtx->fpu.aRegs[iStReg].r80);
fPop = false;
if (fPop)
return VINF_SUCCESS;