VirtualBox

Changeset 97183 in vbox for trunk


Ignore:
Timestamp:
Oct 17, 2022 10:27:05 PM (2 years ago)
Author:
vboxsync
Message:

VMM/CPUM,HMVMX,IEM: Use the individual CPUMCTX_INHIBIT_SHADOW_SS and CPUMCTX_INHIBIT_SHADOW_STI flags with IEM (only setting), VT-x and NEM/kvm. bugref:9941

Location:
trunk
Files:
5 edited

Legend:

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

    r97182 r97183  
    19391939
    19401940/**
    1941  * Checks if we're in an "interrupt shadow", i.e. after a STI, POPF or MOV SS,
     1941 * Checks if we're in an "interrupt shadow", i.e. after a STI, POP SS or MOV SS,
    19421942 * updating the state if stale.
    19431943 *
    19441944 * This also inhibit NMIs, except perhaps for nested guests.
    19451945 *
    1946  * @returns true if interrupts are inhibited by interrupt shadow, false if not.
     1946 * @retval  true if interrupts are inhibited by interrupt shadow.
     1947 * @retval  false if not.
    19471948 * @param   pCtx    Current guest CPU context.
    19481949 * @note    Requires pCtx->rip to be up to date.
     
    19621963
    19631964/**
    1964  * Sets the "interrupt shadow" flag, after a STI, POPF or MOV SS instruction.
     1965 * Checks if we're in an "interrupt shadow" due to a POP SS or MOV SS
     1966 * instruction.
     1967 *
     1968 * This also inhibit NMIs, except perhaps for nested guests.
     1969 *
     1970 * @retval  true if interrupts are inhibited due to POP/MOV SS.
     1971 * @retval  false if not.
     1972 * @param   pCtx    Current guest CPU context.
     1973 * @note    Requires pCtx->rip to be up to date.
     1974 * @note    Does not clear fInhibit when CPUMCTX::uRipInhibitInt differs
     1975 *          from CPUMCTX::rip.
     1976 * @note    Both CPUMIsInInterruptShadowAfterSti() and this function may return
     1977 *          true depending on the execution engine being used.
     1978 */
     1979DECLINLINE(bool) CPUMIsInInterruptShadowAfterSs(PCCPUMCTX pCtx)
     1980{
     1981    if (!(pCtx->fInhibit & CPUMCTX_INHIBIT_SHADOW_SS))
     1982        return false;
     1983
     1984    CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
     1985    return pCtx->uRipInhibitInt == pCtx->rip;
     1986}
     1987
     1988/**
     1989 * Checks if we're in an "interrupt shadow" due to an STI instruction.
     1990 *
     1991 * This also inhibit NMIs, except perhaps for nested guests.
     1992 *
     1993 * @retval  true if interrupts are inhibited due to STI.
     1994 * @retval  false if not.
     1995 * @param   pCtx    Current guest CPU context.
     1996 * @note    Requires pCtx->rip to be up to date.
     1997 * @note    Does not clear fInhibit when CPUMCTX::uRipInhibitInt differs
     1998 *          from CPUMCTX::rip.
     1999 * @note    Both CPUMIsInInterruptShadowAfterSs() and this function may return
     2000 *          true depending on the execution engine being used.
     2001 */
     2002DECLINLINE(bool) CPUMIsInInterruptShadowAfterSti(PCCPUMCTX pCtx)
     2003{
     2004    if (!(pCtx->fInhibit & CPUMCTX_INHIBIT_SHADOW_STI))
     2005        return false;
     2006
     2007    CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
     2008    return pCtx->uRipInhibitInt == pCtx->rip;
     2009}
     2010
     2011/**
     2012 * Sets the "interrupt shadow" flag, after a STI, POP SS or MOV SS instruction.
    19652013 *
    19662014 * @param   pCtx    Current guest CPU context.
     
    19752023
    19762024/**
    1977  * Sets the "interrupt shadow" flag, after a STI, POPF or MOV SS instruction,
     2025 * Sets the "interrupt shadow" flag, after a STI, POP SS or MOV SS instruction,
    19782026 * extended version.
    19792027 *
     
    19852033    pCtx->fInhibit |= CPUMCTX_INHIBIT_SHADOW;
    19862034    pCtx->uRipInhibitInt = rip;
     2035}
     2036
     2037/**
     2038 * Sets the "interrupt shadow" flag after a POP SS or MOV SS instruction.
     2039 *
     2040 * @param   pCtx    Current guest CPU context.
     2041 * @note    Requires pCtx->rip to be up to date.
     2042 */
     2043DECLINLINE(void) CPUMSetInInterruptShadowSs(PCPUMCTX pCtx)
     2044{
     2045    CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
     2046    pCtx->fInhibit |= CPUMCTX_INHIBIT_SHADOW_SS;
     2047    pCtx->uRipInhibitInt = pCtx->rip;
     2048}
     2049
     2050/**
     2051 * Sets the "interrupt shadow" flag after an STI instruction.
     2052 *
     2053 * @param   pCtx    Current guest CPU context.
     2054 * @note    Requires pCtx->rip to be up to date.
     2055 */
     2056DECLINLINE(void) CPUMSetInInterruptShadowSti(PCPUMCTX pCtx)
     2057{
     2058    CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
     2059    pCtx->fInhibit |= CPUMCTX_INHIBIT_SHADOW_STI;
     2060    pCtx->uRipInhibitInt = pCtx->rip;
    19872061}
    19882062
     
    20342108    }
    20352109    return fInhibited;
     2110}
     2111
     2112/**
     2113 * Update the two "interrupt shadow" flags separately, extended version.
     2114 *
     2115 * @param   pCtx            Current guest CPU context.
     2116 * @param   fInhibitedBySs  The new state for the MOV SS & POP SS aspect.
     2117 * @param   fInhibitedBySti The new state for the STI aspect.
     2118 * @param   rip             The RIP for which it is inhibited.
     2119 */
     2120DECLINLINE(void) CPUMUpdateInterruptShadowSsStiEx(PCPUMCTX pCtx, bool fInhibitedBySs, bool fInhibitedBySti, uint64_t rip)
     2121{
     2122    if (!(fInhibitedBySs | fInhibitedBySti))
     2123        pCtx->fInhibit &= (uint8_t)~CPUMCTX_INHIBIT_SHADOW;
     2124    else
     2125    {
     2126        pCtx->fInhibit |= (fInhibitedBySs  ? CPUMCTX_INHIBIT_SHADOW_SS  : 0)
     2127                       |  (fInhibitedBySti ? CPUMCTX_INHIBIT_SHADOW_STI : 0);
     2128        pCtx->uRipInhibitInt = rip;
     2129    }
    20362130}
    20372131
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp

    r97178 r97183  
    47044704    VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_LoadSReg, iSegReg, uSel);
    47054705    if (iSegReg == X86_SREG_SS && rcStrict == VINF_SUCCESS)
    4706         CPUMSetInInterruptShadow(&pVCpu->cpum.GstCtx);
     4706        CPUMSetInInterruptShadowSs(&pVCpu->cpum.GstCtx);
    47074707    return rcStrict;
    47084708}
     
    47624762        pVCpu->cpum.GstCtx.rsp = TmpRsp.u;
    47634763        if (iSegReg == X86_SREG_SS)
    4764             CPUMSetInInterruptShadow(&pVCpu->cpum.GstCtx);
     4764            CPUMSetInInterruptShadowSs(&pVCpu->cpum.GstCtx);
    47654765    }
    47664766    return rcStrict;
     
    75127512    iemRegAddToRipAndClearRF(pVCpu, cbInstr);
    75137513    if (!(fEflOld & X86_EFL_IF) && (fEfl & X86_EFL_IF))
    7514         CPUMSetInInterruptShadow(&pVCpu->cpum.GstCtx);
     7514        CPUMSetInInterruptShadowSti(&pVCpu->cpum.GstCtx);
    75157515    Log2(("STI: %#x -> %#x\n", fEflOld, fEfl));
    75167516    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h

    r97178 r97183  
    16981698static uint32_t vmxHCGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
    16991699{
    1700     uint32_t fIntrState = 0;
     1700    uint32_t fIntrState;
    17011701
    17021702    /*
    17031703     * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
    17041704     */
    1705     if (CPUMIsInInterruptShadowWithUpdate(&pVCpu->cpum.GstCtx))
    1706     {
    1707         /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
    1708         HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
    1709 
    1710         /** @todo r=bird: This heuristic isn't all that correct, it would be safer
    1711          * to always use MOVSS here.  Best deal would be to track both bits in CPUM. */
    1712         if (pVCpu->cpum.GstCtx.eflags.Bits.u1IF)
     1705    if (!CPUMIsInInterruptShadowWithUpdate(&pVCpu->cpum.GstCtx))
     1706        fIntrState = 0;
     1707    else
     1708    {
     1709        /* If inhibition is active, RIP should've been imported from the VMCS already. */
     1710        HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
     1711
     1712        if (CPUMIsInInterruptShadowAfterSs(&pVCpu->cpum.GstCtx))
     1713            fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
     1714        else
     1715        {
    17131716            fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
    1714         else
    1715             fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
     1717
     1718            /* Block-by-STI must not be set when interrupts are disabled. */
     1719            AssertStmt(pVCpu->cpum.GstCtx.eflags.Bits.u1IF, fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
     1720        }
    17161721    }
    17171722
     
    17191724     * Check if we should inhibit NMI delivery.
    17201725     */
    1721     if (CPUMAreInterruptsInhibitedByNmiEx(&pVCpu->cpum.GstCtx))
     1726    if (!CPUMAreInterruptsInhibitedByNmiEx(&pVCpu->cpum.GstCtx))
     1727    { /* likely */ }
     1728    else
    17221729        fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
    17231730
     
    17251732     * Validate.
    17261733     */
    1727 #ifdef VBOX_STRICT
    17281734    /* We don't support block-by-SMI yet.*/
    17291735    Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
    1730 
    1731     /* Block-by-STI must not be set when interrupts are disabled. */
    1732     if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
    1733     {
    1734         HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
    1735         Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
    1736     }
    1737 #endif
    17381736
    17391737    return fIntrState;
     
    33833381    vmxHCImportGuestRFlags(pVCpu, pVmcsInfo);
    33843382
    3385     CPUMUpdateInterruptShadowEx(&pVCpu->cpum.GstCtx,
    3386                                 RT_BOOL(fGstIntState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)),
    3387                                 pVCpu->cpum.GstCtx.rip);
     3383    CPUMUpdateInterruptShadowSsStiEx(&pVCpu->cpum.GstCtx,
     3384                                     RT_BOOL(fGstIntState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
     3385                                     RT_BOOL(fGstIntState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
     3386                                     pVCpu->cpum.GstCtx.rip);
    33883387    CPUMUpdateInterruptInhibitingByNmiEx(&pVCpu->cpum.GstCtx, RT_BOOL(fGstIntState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
    33893388}
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r97178 r97183  
    30893089 *
    30903090 * @param   pszEFlags   Where to write the mnemonics. (Assumes sufficient buffer space.)
    3091  * @param   efl         The EFLAGS value.
     3091 * @param   efl         The EFLAGS value with fInhibit in bits 31:24.
    30923092 */
    30933093static void cpumR3InfoFormatFlags(char *pszEFlags, uint32_t efl)
     
    31163116        { "po", "pe", X86_EFL_PF },
    31173117        { "cy", "nc", X86_EFL_CF },
     3118        { "inh-ss",  NULL, (uint32_t)CPUMCTX_INHIBIT_SHADOW_SS  << 24 },
     3119        { "inh-sti", NULL, (uint32_t)CPUMCTX_INHIBIT_SHADOW_STI << 24 },
     3120        { "inh-nmi", NULL, (uint32_t)CPUMCTX_INHIBIT_NMI        << 24 },
    31183121    };
    31193122    char *psz = pszEFlags;
     
    31523155    uint32_t efl = pCtxCore->eflags.u32;
    31533156    char szEFlags[80];
    3154     cpumR3InfoFormatFlags(&szEFlags[0], efl);
     3157    cpumR3InfoFormatFlags(&szEFlags[0], efl | ((uint32_t)pCtx->fInhibit << 24));
    31553158
    31563159    /*
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-linux.cpp

    r97178 r97183  
    14761476            pVCpu->cpum.GstCtx.rip = pRun->s.regs.regs.rip;
    14771477
    1478         CPUMUpdateInterruptShadowEx(&pVCpu->cpum.GstCtx, KvmEvents.interrupt.shadow != 0, pVCpu->cpum.GstCtx.rip);
     1478        CPUMUpdateInterruptShadowSsStiEx(&pVCpu->cpum.GstCtx,
     1479                                         RT_BOOL(KvmEvents.interrupt.shadow & KVM_X86_SHADOW_INT_MOV_SS),
     1480                                         RT_BOOL(KvmEvents.interrupt.shadow & KVM_X86_SHADOW_INT_STI),
     1481                                         pVCpu->cpum.GstCtx.rip);
    14791482        CPUMUpdateInterruptInhibitingByNmi(&pVCpu->cpum.GstCtx, KvmEvents.nmi.masked != 0);
    14801483
     
    18651868        { /* probably likely */ }
    18661869        else
    1867             KvmEvents.interrupt.shadow = KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI;
     1870            KvmEvents.interrupt.shadow = (CPUMIsInInterruptShadowAfterSs()  ? KVM_X86_SHADOW_INT_MOV_SS : 0)
     1871                                       | (CPUMIsInInterruptShadowAfterSti() ? KVM_X86_SHADOW_INT_STI    : 0);
    18681872
    18691873        /* No flag - this is updated unconditionally. */
     
    20492053    if (!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_INHIBIT_INT))
    20502054        KvmEvents.interrupt.shadow = !CPUMIsInInterruptShadowWithUpdate(&pVCpu->cpum.GstCtx) ? 0
    2051                                    : KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI;
     2055                                   :   (CPUMIsInInterruptShadowAfterSs()  ? KVM_X86_SHADOW_INT_MOV_SS : 0)
     2056                                     | (CPUMIsInInterruptShadowAfterSti() ? KVM_X86_SHADOW_INT_STI    : 0);
    20522057    else
    2053         CPUMUpdateInterruptShadowEx(&pVCpu->cpum.GstCtx, KvmEvents.interrupt.shadow != 0, pRun->s.regs.regs.rip);
     2058        CPUMUpdateInterruptShadowSsStiEx(&pVCpu->cpum.GstCtx,
     2059                                         RT_BOOL(KvmEvents.interrupt.shadow & KVM_X86_SHADOW_INT_MOV_SS),
     2060                                         RT_BOOL(KvmEvents.interrupt.shadow & KVM_X86_SHADOW_INT_MOV_STI),
     2061                                         pRun->s.regs.regs.rip);
    20542062
    20552063    if (!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_INHIBIT_NMI))
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