VirtualBox

Changeset 42704 in vbox for trunk


Ignore:
Timestamp:
Aug 9, 2012 8:03:21 AM (12 years ago)
Author:
vboxsync
Message:

IEM: Eflags fixes, added API variants that bypasses access handlers, ...

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/iem.h

    r41799 r42704  
    4343VMMDECL(VBOXSTRICTRC)       IEMExecOneWithPrefetchedByPC(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint64_t OpcodeBytesPC,
    4444                                                         const void *pvOpcodeBytes, size_t cbOpcodeBytes);
     45VMMDECL(VBOXSTRICTRC)       IEMExecOneBypassEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten);
     46VMMDECL(VBOXSTRICTRC)       IEMExecOneBypassWithPrefetchedByPC(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint64_t OpcodeBytesPC,
     47                                                               const void *pvOpcodeBytes, size_t cbOpcodeBytes);
    4548VMMDECL(VBOXSTRICTRC)       IEMExecLots(PVMCPU pVCpu);
    4649VMM_INT_DECL(VBOXSTRICTRC)  IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2);
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r42676 r42704  
    173173*   Defined Constants And Macros                                               *
    174174*******************************************************************************/
     175/** @def IEM_LOG_MEMORY_ACCESS
     176 * Can be used to log memory accesses when debugging problematic guest behavior. */
     177#if 0
     178# define IEM_LOG_MEMORY_ACCESS
     179#endif
     180
    175181/** @name IEM status codes.
    176182 *
     
    709715 *
    710716 * @param   pIemCpu             The per CPU IEM state.
    711  */
    712 DECLINLINE(void) iemInitDecoder(PIEMCPU pIemCpu)
     717 * @param   fBypassHandlers     Whether to bypass access handlers.
     718 */
     719DECLINLINE(void) iemInitDecoder(PIEMCPU pIemCpu, bool fBypassHandlers)
    713720{
    714721    PCPUMCTX pCtx  = pIemCpu->CTX_SUFF(pCtx);
     
    754761    pIemCpu->iNextMapping       = 0;
    755762    pIemCpu->rcPassUp           = VINF_SUCCESS;
     763    pIemCpu->fBypassHandlers    = fBypassHandlers;
     764
    756765}
    757766
     
    762771 * @returns Strict VBox status code.
    763772 * @param   pIemCpu             The IEM state.
    764  */
    765 static VBOXSTRICTRC iemInitDecoderAndPrefetchOpcodes(PIEMCPU pIemCpu)
     773 * @param   fBypassHandlers     Whether to bypass access handlers.
     774 */
     775static VBOXSTRICTRC iemInitDecoderAndPrefetchOpcodes(PIEMCPU pIemCpu, bool fBypassHandlers)
    766776{
    767777#ifdef IEM_VERIFICATION_MODE
    768778    uint8_t const cbOldOpcodes = pIemCpu->cbOpcode;
    769779#endif
    770     iemInitDecoder(pIemCpu);
     780    iemInitDecoder(pIemCpu, fBypassHandlers);
    771781
    772782    /*
     
    796806    }
    797807
     808#if defined(IN_RC) && defined(VBOX_WITH_RAW_MODE)
     809    /* Allow interpretation of patch manager code blocks since they can for
     810       instance throw #PFs for perfectly good reasons. */
     811    if (   (pCtx->cs.Sel & X86_SEL_RPL) == 1
     812        && PATMIsPatchGCAddr(IEMCPU_TO_VM(pIemCpu), GCPtrPC))
     813    {
     814        uint32_t cbLeftOnPage = PAGE_SIZE - (GCPtrPC & PAGE_OFFSET_MASK);
     815        if (cbToTryRead > cbLeftOnPage)
     816            cbToTryRead = cbLeftOnPage;
     817        if (cbToTryRead > sizeof(pIemCpu->abOpcode))
     818            cbToTryRead = sizeof(pIemCpu->abOpcode);
     819        memcpy(pIemCpu->abOpcode, (void const *)(uintptr_t)GCPtrPC, cbToTryRead);
     820        pIemCpu->cbOpcode = cbToTryRead;
     821        return VINF_SUCCESS;
     822    }
     823#endif
     824
    798825    RTGCPHYS    GCPhys;
    799826    uint64_t    fFlags;
     
    801828    if (RT_FAILURE(rc))
    802829    {
    803 #if defined(IN_RC) && defined(VBOX_WITH_RAW_MODE)
    804         /* Allow interpretation of patch manager code blocks since they can for
    805            instance throw #PFs for perfectly good reasons. */
    806         if (   (pCtx->cs.Sel & X86_SEL_RPL) == 1
    807             && PATMIsPatchGCAddr(IEMCPU_TO_VM(pIemCpu), GCPtrPC))
    808         {
    809             uint32_t cbLeftOnPage = PAGE_SIZE - (GCPtrPC & PAGE_OFFSET_MASK);
    810             if (cbToTryRead > cbLeftOnPage)
    811                 cbToTryRead = cbLeftOnPage;
    812             if (cbToTryRead > sizeof(pIemCpu->abOpcode))
    813                 cbToTryRead = sizeof(pIemCpu->abOpcode);
    814             memcpy(pIemCpu->abOpcode, (void const *)(uintptr_t)GCPtrPC, cbToTryRead);
    815             pIemCpu->cbOpcode = cbToTryRead;
    816             return VINF_SUCCESS;
    817         }
    818 #endif
    819830        Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - rc=%Rrc\n", GCPtrPC, rc));
    820831        return iemRaisePageFault(pIemCpu, GCPtrPC, IEM_ACCESS_INSTRUCTION, rc);
     
    863874    /** @todo PATM: Read original, unpatched bytes? EMAll.cpp doesn't seem to be
    864875     *        doing that. */
    865     if (!pIemCpu->fByPassHandlers)
     876    if (!pIemCpu->fBypassHandlers)
    866877        rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhys, pIemCpu->abOpcode, cbToTryRead);
    867878    else
     
    870881    {
    871882        /** @todo status code handling */
    872         Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - read error - rc=%Rrc (!!)\n", GCPtrPC, rc));
     883        Log(("iemInitDecoderAndPrefetchOpcodes: %RGv/%RGp LB %#x - read error - rc=%Rrc (!!)\n",
     884             GCPtrPC, GCPhys, rc, cbToTryRead));
    873885        return rc;
    874886    }
     
    953965        cbToTryRead = sizeof(pIemCpu->abOpcode) - pIemCpu->cbOpcode;
    954966    Assert(cbToTryRead >= cbMin - cbLeft);
    955     if (!pIemCpu->fByPassHandlers)
     967    if (!pIemCpu->fBypassHandlers)
    956968        rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhys, &pIemCpu->abOpcode[pIemCpu->cbOpcode], cbToTryRead);
    957969    else
     
    17711783    return VINF_SUCCESS;
    17721784}
     1785
     1786
     1787/**
     1788 * Gets the correct EFLAGS regardless of whether PATM stores parts of them or
     1789 * not.
     1790 *
     1791 * @param   a_pIemCpu           The IEM per CPU data.
     1792 * @param   a_pCtx              The CPU context.
     1793 */
     1794#ifdef VBOX_WITH_RAW_MODE_NOT_R0
     1795# define IEMMISC_GET_EFL(a_pIemCpu, a_pCtx) \
     1796    ( IEM_VERIFICATION_ENABLED(a_pIemCpu) \
     1797      ? (a_pCtx)->eflags.u \
     1798      : CPUMRawGetEFlags(IEMCPU_TO_VMCPU(a_pIemCpu)) )
     1799#else
     1800# define IEMMISC_GET_EFL(a_pIemCpu, a_pCtx) \
     1801    ( (a_pCtx)->eflags.u  )
     1802#endif
     1803
     1804/**
     1805 * Updates the EFLAGS in the correct manner wrt. PATM.
     1806 *
     1807 * @param   a_pIemCpu           The IEM per CPU data.
     1808 * @param   a_pCtx              The CPU context.
     1809 */
     1810#ifdef VBOX_WITH_RAW_MODE_NOT_R0
     1811# define IEMMISC_SET_EFL(a_pIemCpu, a_pCtx, a_fEfl) \
     1812    do { \
     1813        if (IEM_VERIFICATION_ENABLED(a_pIemCpu)) \
     1814            (a_pCtx)->eflags.u = (a_fEfl); \
     1815        else \
     1816            CPUMRawSetEFlags(IEMCPU_TO_VMCPU(a_pIemCpu), a_fEfl); \
     1817    } while (0)
     1818#else
     1819# define IEMMISC_SET_EFL(a_pIemCpu, a_pCtx, a_fEfl) \
     1820    do { \
     1821        (a_pCtx)->eflags.u = (a_fEfl); \
     1822    } while (0)
     1823#endif
    17731824
    17741825
     
    19371988        return rcStrict;
    19381989
    1939     pu16Frame[2] = (uint16_t)pCtx->eflags.u;
     1990    uint32_t fEfl = IEMMISC_GET_EFL(pIemCpu, pCtx);
     1991    pu16Frame[2] = (uint16_t)fEfl;
    19401992    pu16Frame[1] = (uint16_t)pCtx->cs.Sel;
    19411993    pu16Frame[0] = pCtx->ip + cbInstr;
     
    19542006    /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */
    19552007    pCtx->rip              = Idte.off;
    1956     pCtx->eflags.Bits.u1IF = 0;
     2008    fEfl &= ~X86_EFL_IF;
     2009    IEMMISC_SET_EFL(pIemCpu, pCtx, fEfl);
    19572010
    19582011    /** @todo do we actually do this in real mode? */
     
    21342187     * This in turns means validating the new SS and ESP...
    21352188     */
     2189    uint32_t        fEfl    = IEMMISC_GET_EFL(pIemCpu, pCtx);
    21362190    uint8_t const   uNewCpl = DescCS.Legacy.Gen.u4Type & X86_SEL_TYPE_CONF
    21372191                            ? pIemCpu->uCpl : DescCS.Legacy.Gen.u2Dpl;
     
    21822236                            ? pCtx->eip + cbInstr : pCtx->eip;
    21832237        uStackFrame.pu32[1] = (pCtx->cs.Sel & ~X86_SEL_RPL) | pIemCpu->uCpl;
    2184         uStackFrame.pu32[2] = pCtx->eflags.u;
     2238        uStackFrame.pu32[2] = fEfl;
    21852239        uStackFrame.pu32[3] = pCtx->esp;
    21862240        uStackFrame.pu32[4] = pCtx->ss.Sel;
     
    22392293                            ? pCtx->eip + cbInstr : pCtx->eip;
    22402294        uStackFrame.pu32[1] = (pCtx->cs.Sel & ~X86_SEL_RPL) | pIemCpu->uCpl;
    2241         uStackFrame.pu32[2] = pCtx->eflags.u;
     2295        uStackFrame.pu32[2] = fEfl;
    22422296        rcStrict = iemMemCommitAndUnmap(pIemCpu, pvStackFrame, IEM_ACCESS_STACK_W); /* don't use the commit here */
    22432297        if (rcStrict != VINF_SUCCESS)
     
    22682322
    22692323    pCtx->rip               = uNewEip;
    2270     pCtx->rflags.u         &= ~fEflToClear;
     2324    fEfl &= ~fEflToClear;
     2325    IEMMISC_SET_EFL(pIemCpu, pCtx, fEfl);
    22712326
    22722327    if (fFlags & IEM_XCPT_FLAGS_CR2)
     
    44284483
    44294484/**
     4485 * Updates the IEMCPU::cbWritten counter if applicable.
     4486 *
     4487 * @param   pIemCpu             The IEM per CPU data.
     4488 * @param   fAccess             The access being accounted for.
     4489 * @param   cbMem               The access size.
     4490 */
     4491DECL_FORCE_INLINE(void) iemMemUpdateWrittenCounter(PIEMCPU pIemCpu, uint32_t fAccess, size_t cbMem)
     4492{
     4493    if (   (fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_WRITE)) == (IEM_ACCESS_WHAT_STACK | IEM_ACCESS_TYPE_WRITE)
     4494        || (fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_WRITE)) == (IEM_ACCESS_WHAT_DATA | IEM_ACCESS_TYPE_WRITE) )
     4495        pIemCpu->cbWritten += (uint32_t)cbMem;
     4496}
     4497
     4498
     4499/**
    44304500 * Checks if the given segment can be written to, raise the appropriate
    44314501 * exception if not.
     
    46624732        return VERR_PGM_PHYS_TLB_CATCH_ALL;
    46634733#endif
     4734#ifdef IEM_LOG_MEMORY_ACCESS
     4735    return VERR_PGM_PHYS_TLB_CATCH_ALL;
     4736#endif
    46644737
    46654738    /** @todo This API may require some improving later.  A private deal with PGM
     
    46704743                                  GCPhysMem,
    46714744                                  RT_BOOL(fAccess & IEM_ACCESS_TYPE_WRITE),
    4672                                   pIemCpu->fByPassHandlers,
     4745                                  pIemCpu->fBypassHandlers,
    46734746                                  ppvMem,
    46744747                                  pLock);
     
    47724845        uint16_t const  cbSecond = pIemCpu->aMemBbMappings[iMemMap].cbSecond;
    47734846        uint8_t const  *pbBuf    = &pIemCpu->aBounceBuffers[iMemMap].ab[0];
    4774         if (!pIemCpu->fByPassHandlers)
     4847        if (!pIemCpu->fBypassHandlers)
    47754848        {
    47764849            rc = PGMPhysWrite(IEMCPU_TO_VM(pIemCpu),
     
    48004873            /** @todo status code handling */
    48014874            Log(("iemMemBounceBufferCommitAndUnmap: %s GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (!!)\n",
    4802                  pIemCpu->fByPassHandlers ? "PGMPhysWrite" : "PGMPhysSimpleWriteGCPhys",
     4875                 pIemCpu->fBypassHandlers ? "PGMPhysWrite" : "PGMPhysSimpleWriteGCPhys",
    48034876                 pIemCpu->aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    48044877                 pIemCpu->aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, rc));
     
    48424915    }
    48434916#endif
     4917#ifdef IEM_LOG_MEMORY_ACCESS
     4918    if (rc == VINF_SUCCESS)
     4919    {
     4920        Log(("IEM Wrote %RGp: %.*Rhxs\n", pIemCpu->aMemBbMappings[iMemMap].GCPhysFirst,
     4921             RT_MAX(RT_MIN(pIemCpu->aMemBbMappings[iMemMap].cbFirst, 64), 1), &pIemCpu->aBounceBuffers[iMemMap].ab[0]));
     4922        if (pIemCpu->aMemBbMappings[iMemMap].cbSecond)
     4923            Log(("IEM Wrote %RGp: %.*Rhxs [2nd page]\n", pIemCpu->aMemBbMappings[iMemMap].GCPhysSecond,
     4924                 RT_MIN(pIemCpu->aMemBbMappings[iMemMap].cbSecond, 64),
     4925                 &pIemCpu->aBounceBuffers[iMemMap].ab[pIemCpu->aMemBbMappings[iMemMap].cbFirst]));
     4926    }
     4927#endif
    48444928
    48454929    /*
     
    48844968    {
    48854969        int rc;
    4886         if (!pIemCpu->fByPassHandlers)
     4970        if (!pIemCpu->fBypassHandlers)
    48874971        {
    48884972            rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhysFirst, pbBuf, cbFirstPage);
     
    49685052    pIemCpu->cActiveMappings++;
    49695053
     5054    iemMemUpdateWrittenCounter(pIemCpu, fAccess, cbMem);
    49705055    *ppvMem = pbBuf;
    49715056    return VINF_SUCCESS;
     
    50035088        {
    50045089            int rc;
    5005             if (!pIemCpu->fByPassHandlers)
     5090            if (!pIemCpu->fBypassHandlers)
    50065091                rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhysFirst, pbBuf, cbMem);
    50075092            else
     
    50115096                /** @todo status code handling */
    50125097                Log(("iemMemBounceBufferMapPhys: %s GCPhysFirst=%RGp rc=%Rrc (!!)\n",
    5013                      pIemCpu->fByPassHandlers ? "PGMPhysRead" : "PGMPhysSimpleReadGCPhys",  GCPhysFirst, rc));
     5098                     pIemCpu->fBypassHandlers ? "PGMPhysRead" : "PGMPhysSimpleReadGCPhys",  GCPhysFirst, rc));
    50145099                return rc;
    50155100            }
     
    50565141    pIemCpu->cActiveMappings++;
    50575142
     5143    iemMemUpdateWrittenCounter(pIemCpu, fAccess, cbMem);
    50585144    *ppvMem = pbBuf;
    50595145    return VINF_SUCCESS;
     
    51355221    pIemCpu->cActiveMappings++;
    51365222
    5137     if (   (fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_WRITE)) == (IEM_ACCESS_WHAT_STACK | IEM_ACCESS_TYPE_WRITE)
    5138         || (fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_WRITE)) == (IEM_ACCESS_WHAT_DATA | IEM_ACCESS_TYPE_WRITE) )
    5139         pIemCpu->cbWritten += (uint32_t)cbMem;
     5223    iemMemUpdateWrittenCounter(pIemCpu, fAccess, cbMem);
    51405224    *ppvMem = pvMem;
    51415225    return VINF_SUCCESS;
     
    63246408#define IEM_MC_FETCH_TR_U32(a_u32Dst)                   (a_u32Dst) = (pIemCpu)->CTX_SUFF(pCtx)->tr.Sel
    63256409#define IEM_MC_FETCH_TR_U64(a_u64Dst)                   (a_u64Dst) = (pIemCpu)->CTX_SUFF(pCtx)->tr.Sel
     6410/** @note Not for IOPL or IF testing or modification. */
    63266411#define IEM_MC_FETCH_EFLAGS(a_EFlags)                   (a_EFlags) = (pIemCpu)->CTX_SUFF(pCtx)->eflags.u
    63276412#define IEM_MC_FETCH_EFLAGS_U8(a_EFlags)                (a_EFlags) = (uint8_t)(pIemCpu)->CTX_SUFF(pCtx)->eflags.u
     
    63486433#define IEM_MC_REF_GREG_U32(a_pu32Dst, a_iGReg)         (a_pu32Dst) = (uint32_t *)iemGRegRef(pIemCpu, (a_iGReg))
    63496434#define IEM_MC_REF_GREG_U64(a_pu64Dst, a_iGReg)         (a_pu64Dst) = (uint64_t *)iemGRegRef(pIemCpu, (a_iGReg))
     6435/** @note Not for IOPL or IF testing or modification. */
    63506436#define IEM_MC_REF_EFLAGS(a_pEFlags)                    (a_pEFlags) = &(pIemCpu)->CTX_SUFF(pCtx)->eflags.u
    63516437
     
    64236509
    64246510
     6511/** @note Not for IOPL or IF modification. */
    64256512#define IEM_MC_SET_EFL_BIT(a_fBit)                      do { (pIemCpu)->CTX_SUFF(pCtx)->eflags.u |= (a_fBit); } while (0)
     6513/** @note Not for IOPL or IF modification. */
    64266514#define IEM_MC_CLEAR_EFL_BIT(a_fBit)                    do { (pIemCpu)->CTX_SUFF(pCtx)->eflags.u &= ~(a_fBit); } while (0)
     6515/** @note Not for IOPL or IF modification. */
    64276516#define IEM_MC_FLIP_EFL_BIT(a_fBit)                     do { (pIemCpu)->CTX_SUFF(pCtx)->eflags.u ^= (a_fBit); } while (0)
    64286517
     
    68756964    CPUMSetChangedFlags(IEMCPU_TO_VMCPU(pIemCpu), CPUM_CHANGED_FPU_REM)
    68766965
     6966/** @note Not for IOPL or IF testing. */
    68776967#define IEM_MC_IF_EFL_BIT_SET(a_fBit)                   if (pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit)) {
     6968/** @note Not for IOPL or IF testing. */
    68786969#define IEM_MC_IF_EFL_BIT_NOT_SET(a_fBit)               if (!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit))) {
     6970/** @note Not for IOPL or IF testing. */
    68796971#define IEM_MC_IF_EFL_ANY_BITS_SET(a_fBits)             if (pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBits)) {
     6972/** @note Not for IOPL or IF testing. */
    68806973#define IEM_MC_IF_EFL_NO_BITS_SET(a_fBits)              if (!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBits))) {
     6974/** @note Not for IOPL or IF testing. */
    68816975#define IEM_MC_IF_EFL_BITS_NE(a_fBit1, a_fBit2)         \
    68826976    if (   !!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit1)) \
    68836977        != !!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit2)) ) {
     6978/** @note Not for IOPL or IF testing. */
    68846979#define IEM_MC_IF_EFL_BITS_EQ(a_fBit1, a_fBit2)         \
    68856980    if (   !!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit1)) \
    68866981        == !!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit2)) ) {
     6982/** @note Not for IOPL or IF testing. */
    68876983#define IEM_MC_IF_EFL_BIT_SET_OR_BITS_NE(a_fBit, a_fBit1, a_fBit2) \
    68886984    if (   (pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit)) \
    68896985        ||    !!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit1)) \
    68906986           != !!(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit2)) ) {
     6987/** @note Not for IOPL or IF testing. */
    68916988#define IEM_MC_IF_EFL_BIT_NOT_SET_AND_BITS_EQ(a_fBit, a_fBit1, a_fBit2) \
    68926989    if (   !(pIemCpu->CTX_SUFF(pCtx)->eflags.u & (a_fBit)) \
     
    68966993#define IEM_MC_IF_ECX_IS_NZ()                           if (pIemCpu->CTX_SUFF(pCtx)->ecx != 0) {
    68976994#define IEM_MC_IF_RCX_IS_NZ()                           if (pIemCpu->CTX_SUFF(pCtx)->rcx != 0) {
     6995/** @note Not for IOPL or IF testing. */
    68986996#define IEM_MC_IF_CX_IS_NZ_AND_EFL_BIT_SET(a_fBit) \
    68996997        if (   pIemCpu->CTX_SUFF(pCtx)->cx != 0 \
    69006998            && (pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) {
     6999/** @note Not for IOPL or IF testing. */
    69017000#define IEM_MC_IF_ECX_IS_NZ_AND_EFL_BIT_SET(a_fBit) \
    69027001        if (   pIemCpu->CTX_SUFF(pCtx)->ecx != 0 \
    69037002            && (pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) {
     7003/** @note Not for IOPL or IF testing. */
    69047004#define IEM_MC_IF_RCX_IS_NZ_AND_EFL_BIT_SET(a_fBit) \
    69057005        if (   pIemCpu->CTX_SUFF(pCtx)->rcx != 0 \
    69067006            && (pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) {
     7007/** @note Not for IOPL or IF testing. */
    69077008#define IEM_MC_IF_CX_IS_NZ_AND_EFL_BIT_NOT_SET(a_fBit) \
    69087009        if (   pIemCpu->CTX_SUFF(pCtx)->cx != 0 \
    69097010            && !(pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) {
     7011/** @note Not for IOPL or IF testing. */
    69107012#define IEM_MC_IF_ECX_IS_NZ_AND_EFL_BIT_NOT_SET(a_fBit) \
    69117013        if (   pIemCpu->CTX_SUFF(pCtx)->ecx != 0 \
    69127014            && !(pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) {
     7015/** @note Not for IOPL or IF testing. */
    69137016#define IEM_MC_IF_RCX_IS_NZ_AND_EFL_BIT_NOT_SET(a_fBit) \
    69147017        if (   pIemCpu->CTX_SUFF(pCtx)->rcx != 0 \
     
    81508253 * @param   pVCpu       The current virtual CPU.
    81518254 * @param   pIemCpu     The IEM per CPU data.
    8152  */
    8153 DECL_FORCE_INLINE(VBOXSTRICTRC) iemExecOneInner(PVMCPU pVCpu, PIEMCPU pIemCpu)
     8255 * @param   fExecuteInhibit     If set, execute the instruction following CLI,
     8256 *                      POP SS and MOV SS,GR.
     8257 */
     8258DECL_FORCE_INLINE(VBOXSTRICTRC) iemExecOneInner(PVMCPU pVCpu, PIEMCPU pIemCpu, bool fExecuteInhibit)
    81548259{
    81558260    uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
     
    81638268    /* Execute the next instruction as well if a cli, pop ss or
    81648269       mov ss, Gr has just completed successfully. */
    8165     if (   rcStrict == VINF_SUCCESS
     8270    if (   fExecuteInhibit
     8271        && rcStrict == VINF_SUCCESS
    81668272        && VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
    81678273        && EMGetInhibitInterruptsPC(pVCpu) == pIemCpu->CTX_SUFF(pCtx)->rip )
    81688274    {
    8169         rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu);
     8275        rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu, pIemCpu->fBypassHandlers);
    81708276        if (rcStrict == VINF_SUCCESS)
    81718277        {
     
    82828388     * Do the decoding and emulation.
    82838389     */
    8284     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu);
     8390    VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu, false);
    82858391    if (rcStrict == VINF_SUCCESS)
    8286         rcStrict = iemExecOneInner(pVCpu, pIemCpu);
     8392        rcStrict = iemExecOneInner(pVCpu, pIemCpu, true);
    82878393
    82888394#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
     
    83058411    AssertReturn(CPUMCTX2CORE(pCtx) == pCtxCore, VERR_IEM_IPE_3);
    83068412
    8307     iemInitDecoder(pIemCpu);
     8413    iemInitDecoder(pIemCpu, false);
    83088414    uint32_t const cbOldWritten = pIemCpu->cbWritten;
    83098415
    8310     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu);
     8416    VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu, false);
    83118417    if (rcStrict == VINF_SUCCESS)
    83128418    {
    8313         rcStrict = iemExecOneInner(pVCpu, pIemCpu);
     8419        rcStrict = iemExecOneInner(pVCpu, pIemCpu, true);
    83148420        if (pcbWritten)
    83158421            *pcbWritten = pIemCpu->cbWritten - cbOldWritten;
     
    83308436        && pCtx->rip == OpcodeBytesPC)
    83318437    {
    8332         iemInitDecoder(pIemCpu);
     8438        iemInitDecoder(pIemCpu, false);
    83338439        pIemCpu->cbOpcode = (uint8_t)RT_MIN(cbOpcodeBytes, sizeof(pIemCpu->abOpcode));
    83348440        memcpy(pIemCpu->abOpcode, pvOpcodeBytes, pIemCpu->cbOpcode);
     
    83368442    }
    83378443    else
    8338         rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu);
     8444        rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu, false);
    83398445    if (rcStrict == VINF_SUCCESS)
    83408446    {
    8341         rcStrict = iemExecOneInner(pVCpu, pIemCpu);
    8342     }
     8447        rcStrict = iemExecOneInner(pVCpu, pIemCpu, true);
     8448    }
     8449    return rcStrict;
     8450}
     8451
     8452
     8453VMMDECL(VBOXSTRICTRC)       IEMExecOneBypassEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten)
     8454{
     8455    PIEMCPU  pIemCpu = &pVCpu->iem.s;
     8456    PCPUMCTX pCtx    = pVCpu->iem.s.CTX_SUFF(pCtx);
     8457    AssertReturn(CPUMCTX2CORE(pCtx) == pCtxCore, VERR_IEM_IPE_3);
     8458
     8459    iemInitDecoder(pIemCpu, true);
     8460    uint32_t const cbOldWritten = pIemCpu->cbWritten;
     8461
     8462    VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu, true);
     8463    if (rcStrict == VINF_SUCCESS)
     8464    {
     8465        rcStrict = iemExecOneInner(pVCpu, pIemCpu, false);
     8466        if (pcbWritten)
     8467            *pcbWritten = pIemCpu->cbWritten - cbOldWritten;
     8468    }
     8469    return rcStrict;
     8470}
     8471
     8472
     8473VMMDECL(VBOXSTRICTRC)       IEMExecOneBypassWithPrefetchedByPC(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint64_t OpcodeBytesPC,
     8474                                                               const void *pvOpcodeBytes, size_t cbOpcodeBytes)
     8475{
     8476    PIEMCPU  pIemCpu = &pVCpu->iem.s;
     8477    PCPUMCTX pCtx    = pVCpu->iem.s.CTX_SUFF(pCtx);
     8478    AssertReturn(CPUMCTX2CORE(pCtx) == pCtxCore, VERR_IEM_IPE_3);
     8479
     8480    VBOXSTRICTRC rcStrict;
     8481    if (   cbOpcodeBytes
     8482        && pCtx->rip == OpcodeBytesPC)
     8483    {
     8484        iemInitDecoder(pIemCpu, true);
     8485        pIemCpu->cbOpcode = (uint8_t)RT_MIN(cbOpcodeBytes, sizeof(pIemCpu->abOpcode));
     8486        memcpy(pIemCpu->abOpcode, pvOpcodeBytes, pIemCpu->cbOpcode);
     8487        rcStrict = VINF_SUCCESS;
     8488    }
     8489    else
     8490        rcStrict = iemInitDecoderAndPrefetchOpcodes(pIemCpu, true);
     8491    if (rcStrict == VINF_SUCCESS)
     8492        rcStrict = iemExecOneInner(pVCpu, pIemCpu, false);
    83438493    return rcStrict;
    83448494}
     
    83678517VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2)
    83688518{
    8369     iemInitDecoder(&pVCpu->iem.s);
     8519    iemInitDecoder(&pVCpu->iem.s, false);
    83708520
    83718521    uint32_t fFlags;
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r42677 r42704  
    3535DECLINLINE(VBOXSTRICTRC) iemHlpCheckPortIOPermission(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint16_t u16Port, uint8_t cbOperand)
    3636{
     37    X86EFLAGS Efl;
     38    Efl.u = IEMMISC_GET_EFL(pIemCpu, pCtx);
    3739    if (   (pCtx->cr0 & X86_CR0_PE)
    38         && (    pIemCpu->uCpl > pCtx->eflags.Bits.u2IOPL
    39             ||  pCtx->eflags.Bits.u1VM) )
     40        && (    pIemCpu->uCpl > Efl.Bits.u2IOPL
     41            ||  Efl.Bits.u1VM) )
    4042    {
    4143        NOREF(u16Port); NOREF(cbOperand); /** @todo I/O port permission bitmap check */
     
    469471     * doing this in a C implementation).
    470472     */
    471     uint32_t fEfl = pCtx->eflags.u;
     473    uint32_t fEfl = IEMMISC_GET_EFL(pIemCpu, pCtx);
    472474    if (   (fEfl & X86_EFL_VM)
    473475        && X86_EFL_GET_IOPL(fEfl) != 3 )
     
    517519{
    518520    PCPUMCTX        pCtx    = pIemCpu->CTX_SUFF(pCtx);
    519     uint32_t const  fEflOld = pCtx->eflags.u;
     521    PVMCPU          pVCpu   = IEMCPU_TO_VMCPU(pIemCpu);
     522    uint32_t const  fEflOld = IEMMISC_GET_EFL(pIemCpu, pCtx);
    520523    VBOXSTRICTRC    rcStrict;
    521524    uint32_t        fEflNew;
     
    633636     */
    634637    Assert(fEflNew & RT_BIT_32(1));
    635     pCtx->eflags.u = fEflNew;
     638    IEMMISC_SET_EFL(pIemCpu, pCtx, fEflNew);
    636639    iemRegAddToRip(pIemCpu, cbInstr);
    637640
     
    19121915IEM_CIMPL_DEF_1(iemCImpl_iret_real_v8086, IEMMODE, enmEffOpSize)
    19131916{
    1914     PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     1917    PCPUMCTX  pCtx  = pIemCpu->CTX_SUFF(pCtx);
     1918    PVMCPU    pVCpu = IEMCPU_TO_VMCPU(pIemCpu);
     1919    X86EFLAGS Efl;
     1920    Efl.u = IEMMISC_GET_EFL(pIemCpu, pCtx);
    19151921    NOREF(cbInstr);
    19161922
     
    19451951                   | X86_EFL_RF /*| X86_EFL_VM*/ | X86_EFL_AC /*|X86_EFL_VIF*/ /*|X86_EFL_VIP*/
    19461952                   | X86_EFL_ID;
    1947         uNewFlags |= pCtx->eflags.u & (X86_EFL_VM | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_1);
     1953        uNewFlags |= Efl.u & (X86_EFL_VM | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_1);
    19481954    }
    19491955    else
     
    19571963        uNewFlags &= X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF
    19581964                   | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT;
    1959         uNewFlags |= pCtx->eflags.u & (UINT32_C(0xffff0000) | X86_EFL_1);
     1965        uNewFlags |= Efl.u & (UINT32_C(0xffff0000) | X86_EFL_1);
    19601966        /** @todo The intel pseudo code does not indicate what happens to
    19611967         *        reserved flags. We just ignore them. */
     
    19741980     * V8086 checks and flag adjustments
    19751981     */
    1976     if (pCtx->eflags.Bits.u1VM)
    1977     {
    1978         if (pCtx->eflags.Bits.u2IOPL == 3)
     1982    if (Efl.Bits.u1VM)
     1983    {
     1984        if (Efl.Bits.u2IOPL == 3)
    19791985        {
    19801986            /* Preserve IOPL and clear RF. */
    1981             uNewFlags &=                 ~(X86_EFL_IOPL | X86_EFL_RF);
    1982             uNewFlags |= pCtx->eflags.u & (X86_EFL_IOPL);
     1987            uNewFlags &=        ~(X86_EFL_IOPL | X86_EFL_RF);
     1988            uNewFlags |= Efl.u & (X86_EFL_IOPL);
    19831989        }
    19841990        else if (   enmEffOpSize == IEMMODE_16BIT
    19851991                 && (   !(uNewFlags & X86_EFL_IF)
    1986                      || !pCtx->eflags.Bits.u1VIP )
     1992                     || !Efl.Bits.u1VIP )
    19871993                 && !(uNewFlags & X86_EFL_TF)   )
    19881994        {
     
    19901996            uNewFlags &= ~X86_EFL_VIF;
    19911997            uNewFlags |= (uNewFlags & X86_EFL_IF) << (19 - 9);
    1992             uNewFlags &=                 ~(X86_EFL_IF | X86_EFL_IOPL | X86_EFL_RF);
    1993             uNewFlags |= pCtx->eflags.u & (X86_EFL_IF | X86_EFL_IOPL);
     1998            uNewFlags &=        ~(X86_EFL_IF | X86_EFL_IOPL | X86_EFL_RF);
     1999            uNewFlags |= Efl.u & (X86_EFL_IF | X86_EFL_IOPL);
    19942000        }
    19952001        else
     
    20102016    /** @todo do we load attribs and limit as well? */
    20112017    Assert(uNewFlags & X86_EFL_1);
    2012     pCtx->eflags.u      = uNewFlags;
     2018    IEMMISC_SET_EFL(pIemCpu, pCtx, uNewFlags);
    20132019
    20142020    return VINF_SUCCESS;
     
    23452351        else if (pIemCpu->uCpl <= pCtx->eflags.Bits.u2IOPL)
    23462352            fEFlagsMask |= X86_EFL_IF;
    2347         pCtx->eflags.u     &= ~fEFlagsMask;
    2348         pCtx->eflags.u     |= fEFlagsMask & uNewFlags;
     2353        uint32_t fEFlagsNew = IEMMISC_GET_EFL(pIemCpu, pCtx);
     2354        fEFlagsNew         &= ~fEFlagsMask;
     2355        fEFlagsNew         |= uNewFlags & fEFlagsMask;
     2356        IEMMISC_SET_EFL(pIemCpu, pCtx, fEFlagsNew);
    23492357
    23502358        pIemCpu->uCpl       = uNewCs & X86_SEL_RPL;
     
    23892397        pCtx->rsp           = uNewRsp;
    23902398
     2399        X86EFLAGS NewEfl;
     2400        NewEfl.u = IEMMISC_GET_EFL(pIemCpu, pCtx);
    23912401        uint32_t fEFlagsMask = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF  | X86_EFL_SF
    23922402                             | X86_EFL_TF | X86_EFL_DF | X86_EFL_OF | X86_EFL_NT;
     
    23952405        if (pIemCpu->uCpl == 0)
    23962406            fEFlagsMask |= X86_EFL_IF | X86_EFL_IOPL | X86_EFL_VIF | X86_EFL_VIP; /* VM is 0 */
    2397         else if (pIemCpu->uCpl <= pCtx->eflags.Bits.u2IOPL)
     2407        else if (pIemCpu->uCpl <= NewEfl.Bits.u2IOPL)
    23982408            fEFlagsMask |= X86_EFL_IF;
    2399         pCtx->eflags.u         &= ~fEFlagsMask;
    2400         pCtx->eflags.u         |= fEFlagsMask & uNewFlags;
     2409        NewEfl.u           &= ~fEFlagsMask;
     2410        NewEfl.u           |= fEFlagsMask & uNewFlags;
     2411        IEMMISC_SET_EFL(pIemCpu, pCtx, NewEfl.u);
    24012412        /* Done! */
    24022413    }
     
    32773288            else
    32783289                rcStrict = VINF_SUCCESS;
     3290
     3291#ifdef IN_RC
     3292            /* Return to ring-3 for rescheduling if WP or AM changes. */
     3293            if (   rcStrict == VINF_SUCCESS
     3294                && (   (uNewCrX & (X86_CR0_WP | X86_CR0_AM))
     3295                    != (uOldCrX & (X86_CR0_WP | X86_CR0_AM))) )
     3296                rcStrict = VINF_EM_RESCHEDULE;
     3297#endif
    32793298            break;
    32803299        }
     
    38713890     * CPL check
    38723891     */
    3873     if (   (pCtx->cr0 & X86_CR0_PE)
    3874         && (    pIemCpu->uCpl > pCtx->eflags.Bits.u2IOPL
    3875             ||  pCtx->eflags.Bits.u1VM) )
    3876     {
    3877         /** @todo I/O port permission bitmap check */
    3878         IEM_RETURN_ASPECT_NOT_IMPLEMENTED_LOG(("Implement I/O permission bitmap checks.\n"));
    3879     }
     3892    VBOXSTRICTRC rcStrict = iemHlpCheckPortIOPermission(pIemCpu, pCtx, u16Port, cbReg);
     3893    if (rcStrict != VINF_SUCCESS)
     3894        return rcStrict;
    38803895
    38813896    /*
     
    38903905        default: AssertFailedReturn(VERR_INTERNAL_ERROR_3);
    38913906    }
    3892     VBOXSTRICTRC rcStrict;
    38933907    if (!IEM_VERIFICATION_ENABLED(pIemCpu))
    38943908        rcStrict = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), u16Port, u32Value, cbReg);
     
    39223936IEM_CIMPL_DEF_0(iemCImpl_cli)
    39233937{
    3924     PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
    3925 
     3938    PCPUMCTX        pCtx    = pIemCpu->CTX_SUFF(pCtx);
     3939    PVMCPU          pVCpu   = IEMCPU_TO_VMCPU(pIemCpu);
     3940    uint32_t        fEfl    = IEMMISC_GET_EFL(pIemCpu, pCtx);
     3941    uint32_t const  fEflOld = fEfl;
    39263942    if (pCtx->cr0 & X86_CR0_PE)
    39273943    {
    3928         uint8_t const uIopl = pCtx->eflags.Bits.u2IOPL;
    3929         if (!pCtx->eflags.Bits.u1VM)
     3944        uint8_t const uIopl = X86_EFL_GET_IOPL(fEfl);
     3945        if (!(fEfl & X86_EFL_VM))
    39303946        {
    39313947            if (pIemCpu->uCpl <= uIopl)
    3932                 pCtx->eflags.Bits.u1IF = 0;
     3948                fEfl &= ~X86_EFL_IF;
    39333949            else if (   pIemCpu->uCpl == 3
    39343950                     && (pCtx->cr4 & X86_CR4_PVI) )
    3935                 pCtx->eflags.Bits.u1VIF = 0;
     3951                fEfl &= ~X86_EFL_VIF;
    39363952            else
    39373953                return iemRaiseGeneralProtectionFault0(pIemCpu);
     
    39393955        /* V8086 */
    39403956        else if (uIopl == 3)
    3941             pCtx->eflags.Bits.u1IF = 0;
     3957            fEfl &= ~X86_EFL_IF;
    39423958        else if (   uIopl < 3
    39433959                 && (pCtx->cr4 & X86_CR4_VME) )
    3944             pCtx->eflags.Bits.u1VIF = 0;
     3960            fEfl &= ~X86_EFL_VIF;
    39453961        else
    39463962            return iemRaiseGeneralProtectionFault0(pIemCpu);
     
    39483964    /* real mode */
    39493965    else
    3950         pCtx->eflags.Bits.u1IF = 0;
     3966        fEfl &= ~X86_EFL_IF;
     3967
     3968    /* Commit. */
     3969    IEMMISC_SET_EFL(pIemCpu, pCtx, fEfl);
    39513970    iemRegAddToRip(pIemCpu, cbInstr);
     3971    Log2(("CLI: %#x -> %#x\n", fEflOld, fEfl)); NOREF(fEflOld);
    39523972    return VINF_SUCCESS;
    39533973}
     
    39593979IEM_CIMPL_DEF_0(iemCImpl_sti)
    39603980{
    3961     PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3981    PCPUMCTX        pCtx    = pIemCpu->CTX_SUFF(pCtx);
     3982    PVMCPU          pVCpu   = IEMCPU_TO_VMCPU(pIemCpu);
     3983    uint32_t        fEfl    = IEMMISC_GET_EFL(pIemCpu, pCtx);
     3984    uint32_t const  fEflOld = fEfl;
    39623985
    39633986    if (pCtx->cr0 & X86_CR0_PE)
    39643987    {
    3965         uint8_t const uIopl = pCtx->eflags.Bits.u2IOPL;
    3966         if (!pCtx->eflags.Bits.u1VM)
     3988        uint8_t const uIopl = X86_EFL_GET_IOPL(fEfl);
     3989        if (!(fEfl & X86_EFL_VM))
    39673990        {
    39683991            if (pIemCpu->uCpl <= uIopl)
    3969                 pCtx->eflags.Bits.u1IF = 1;
     3992                fEfl |= X86_EFL_IF;
    39703993            else if (   pIemCpu->uCpl == 3
    39713994                     && (pCtx->cr4 & X86_CR4_PVI)
    3972                      && !pCtx->eflags.Bits.u1VIP )
    3973                 pCtx->eflags.Bits.u1VIF = 1;
     3995                     && !(fEfl & X86_EFL_VIP) )
     3996                fEfl |= X86_EFL_VIF;
    39743997            else
    39753998                return iemRaiseGeneralProtectionFault0(pIemCpu);
     
    39774000        /* V8086 */
    39784001        else if (uIopl == 3)
    3979             pCtx->eflags.Bits.u1IF = 1;
     4002            fEfl |= X86_EFL_IF;
    39804003        else if (   uIopl < 3
    39814004                 && (pCtx->cr4 & X86_CR4_VME)
    3982                  && !pCtx->eflags.Bits.u1VIP )
    3983             pCtx->eflags.Bits.u1VIF = 1;
     4005                 && !(fEfl & X86_EFL_VIP) )
     4006            fEfl |= X86_EFL_VIF;
    39844007        else
    39854008            return iemRaiseGeneralProtectionFault0(pIemCpu);
     
    39874010    /* real mode */
    39884011    else
    3989         pCtx->eflags.Bits.u1IF = 1;
    3990 
     4012        fEfl |= X86_EFL_IF;
     4013
     4014    /* Commit. */
     4015    IEMMISC_SET_EFL(pIemCpu, pCtx, fEfl);
    39914016    iemRegAddToRip(pIemCpu, cbInstr);
    3992     /** @todo don't do this unconditionally... */
    3993     EMSetInhibitInterruptsPC(IEMCPU_TO_VMCPU(pIemCpu), pCtx->rip);
     4017    if (!(fEflOld & X86_EFL_IF) && (fEfl & X86_EFL_IF))
     4018        EMSetInhibitInterruptsPC(IEMCPU_TO_VMCPU(pIemCpu), pCtx->rip);
     4019    Log2(("STI: %#x -> %#x\n", fEflOld, fEfl));
    39944020    return VINF_SUCCESS;
    39954021}
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r42662 r42704  
    205205
    206206    /** Whether to bypass access handlers or not. */
    207     bool                    fByPassHandlers;
     207    bool                    fBypassHandlers;
    208208    /** Explicit alignment padding. */
    209209    bool                    afAlignment0[3];
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette