VirtualBox

Changeset 30263 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Jun 16, 2010 6:31:42 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
62771
Message:

VMM,REM: Only invalidate hidden registers when using raw-mode. Fixes save restore during mode switching code like the windows boot menu. (#5057)

Location:
trunk/src/VBox/VMM/VMMAll
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r30164 r30263  
    18541854
    18551855
    1856 
    1857 #ifndef IN_RING0  /** @todo I don't think we need this in R0, so move it to CPUMAll.cpp? */
    1858 
    1859 /**
    1860  * Transforms the guest CPU state to raw-ring mode.
    1861  *
    1862  * This function will change the any of the cs and ss register with DPL=0 to DPL=1.
    1863  *
    1864  * @returns VBox status. (recompiler failure)
    1865  * @param   pVCpu       The VMCPU handle.
    1866  * @param   pCtxCore    The context core (for trap usage).
    1867  * @see     @ref pg_raw
    1868  */
    1869 VMMDECL(int) CPUMRawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore)
    1870 {
    1871     PVM pVM = pVCpu->CTX_SUFF(pVM);
    1872 
    1873     Assert(!pVM->cpum.s.fRawEntered);
    1874     if (!pCtxCore)
    1875         pCtxCore = CPUMCTX2CORE(&pVCpu->cpum.s.Guest);
    1876 
    1877     /*
    1878      * Are we in Ring-0?
    1879      */
    1880     if (    pCtxCore->ss && (pCtxCore->ss & X86_SEL_RPL) == 0
    1881         &&  !pCtxCore->eflags.Bits.u1VM)
    1882     {
    1883         /*
    1884          * Enter execution mode.
    1885          */
    1886         PATMRawEnter(pVM, pCtxCore);
    1887 
    1888         /*
    1889          * Set CPL to Ring-1.
    1890          */
    1891         pCtxCore->ss |= 1;
    1892         if (pCtxCore->cs && (pCtxCore->cs & X86_SEL_RPL) == 0)
    1893             pCtxCore->cs |= 1;
    1894     }
    1895     else
    1896     {
    1897         AssertMsg((pCtxCore->ss & X86_SEL_RPL) >= 2 || pCtxCore->eflags.Bits.u1VM,
    1898                   ("ring-1 code not supported\n"));
    1899         /*
    1900          * PATM takes care of IOPL and IF flags for Ring-3 and Ring-2 code as well.
    1901          */
    1902         PATMRawEnter(pVM, pCtxCore);
    1903     }
    1904 
    1905     /*
    1906      * Assert sanity.
    1907      */
    1908     AssertMsg((pCtxCore->eflags.u32 & X86_EFL_IF), ("X86_EFL_IF is clear\n"));
    1909     AssertReleaseMsg(   pCtxCore->eflags.Bits.u2IOPL < (unsigned)(pCtxCore->ss & X86_SEL_RPL)
    1910                      || pCtxCore->eflags.Bits.u1VM,
    1911                      ("X86_EFL_IOPL=%d CPL=%d\n", pCtxCore->eflags.Bits.u2IOPL, pCtxCore->ss & X86_SEL_RPL));
    1912     Assert((pVCpu->cpum.s.Guest.cr0 & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE)) == (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP));
    1913     pCtxCore->eflags.u32        |= X86_EFL_IF; /* paranoia */
    1914 
    1915     pVM->cpum.s.fRawEntered = true;
    1916     return VINF_SUCCESS;
    1917 }
    1918 
    1919 
    1920 /**
    1921  * Transforms the guest CPU state from raw-ring mode to correct values.
    1922  *
    1923  * This function will change any selector registers with DPL=1 to DPL=0.
    1924  *
    1925  * @returns Adjusted rc.
    1926  * @param   pVCpu       The VMCPU handle.
    1927  * @param   rc          Raw mode return code
    1928  * @param   pCtxCore    The context core (for trap usage).
    1929  * @see     @ref pg_raw
    1930  */
    1931 VMMDECL(int) CPUMRawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc)
    1932 {
    1933     PVM pVM = pVCpu->CTX_SUFF(pVM);
    1934 
    1935     /*
    1936      * Don't leave if we've already left (in GC).
    1937      */
    1938     Assert(pVM->cpum.s.fRawEntered);
    1939     if (!pVM->cpum.s.fRawEntered)
    1940         return rc;
    1941     pVM->cpum.s.fRawEntered = false;
    1942 
    1943     PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
    1944     if (!pCtxCore)
    1945         pCtxCore = CPUMCTX2CORE(pCtx);
    1946     Assert(pCtxCore->eflags.Bits.u1VM || (pCtxCore->ss & X86_SEL_RPL));
    1947     AssertMsg(pCtxCore->eflags.Bits.u1VM || pCtxCore->eflags.Bits.u2IOPL < (unsigned)(pCtxCore->ss & X86_SEL_RPL),
    1948               ("X86_EFL_IOPL=%d CPL=%d\n", pCtxCore->eflags.Bits.u2IOPL, pCtxCore->ss & X86_SEL_RPL));
    1949 
    1950     /*
    1951      * Are we executing in raw ring-1?
    1952      */
    1953     if (    (pCtxCore->ss & X86_SEL_RPL) == 1
    1954         &&  !pCtxCore->eflags.Bits.u1VM)
    1955     {
    1956         /*
    1957          * Leave execution mode.
    1958          */
    1959         PATMRawLeave(pVM, pCtxCore, rc);
    1960         /* Not quite sure if this is really required, but shouldn't harm (too much anyways). */
    1961         /** @todo See what happens if we remove this. */
    1962         if ((pCtxCore->ds & X86_SEL_RPL) == 1)
    1963             pCtxCore->ds &= ~X86_SEL_RPL;
    1964         if ((pCtxCore->es & X86_SEL_RPL) == 1)
    1965             pCtxCore->es &= ~X86_SEL_RPL;
    1966         if ((pCtxCore->fs & X86_SEL_RPL) == 1)
    1967             pCtxCore->fs &= ~X86_SEL_RPL;
    1968         if ((pCtxCore->gs & X86_SEL_RPL) == 1)
    1969             pCtxCore->gs &= ~X86_SEL_RPL;
    1970 
    1971         /*
    1972          * Ring-1 selector => Ring-0.
    1973          */
    1974         pCtxCore->ss &= ~X86_SEL_RPL;
    1975         if ((pCtxCore->cs & X86_SEL_RPL) == 1)
    1976             pCtxCore->cs &= ~X86_SEL_RPL;
    1977     }
    1978     else
    1979     {
    1980         /*
    1981          * PATM is taking care of the IOPL and IF flags for us.
    1982          */
    1983         PATMRawLeave(pVM, pCtxCore, rc);
    1984         if (!pCtxCore->eflags.Bits.u1VM)
    1985         {
    1986             /** @todo See what happens if we remove this. */
    1987             if ((pCtxCore->ds & X86_SEL_RPL) == 1)
    1988                 pCtxCore->ds &= ~X86_SEL_RPL;
    1989             if ((pCtxCore->es & X86_SEL_RPL) == 1)
    1990                 pCtxCore->es &= ~X86_SEL_RPL;
    1991             if ((pCtxCore->fs & X86_SEL_RPL) == 1)
    1992                 pCtxCore->fs &= ~X86_SEL_RPL;
    1993             if ((pCtxCore->gs & X86_SEL_RPL) == 1)
    1994                 pCtxCore->gs &= ~X86_SEL_RPL;
    1995         }
    1996     }
    1997 
    1998     return rc;
    1999 }
    2000 
     1856#ifndef IN_RING0
    20011857/**
    20021858 * Updates the EFLAGS while we're in raw-mode.
     
    20101866    PVM pVM = pVCpu->CTX_SUFF(pVM);
    20111867
    2012     if (!pVM->cpum.s.fRawEntered)
     1868    if (!pVCpu->cpum.s.fRawEntered)
    20131869    {
    20141870        pCtxCore->eflags.u32 = eflags;
     
    20171873    PATMRawSetEFlags(pVM, pCtxCore, eflags);
    20181874}
    2019 
    20201875#endif /* !IN_RING0 */
     1876
    20211877
    20221878/**
     
    20341890    PVM pVM = pVCpu->CTX_SUFF(pVM);
    20351891
    2036     if (!pVM->cpum.s.fRawEntered)
     1892    if (!pVCpu->cpum.s.fRawEntered)
    20371893        return pCtxCore->eflags.u32;
    20381894    return PATMRawGetEFlags(pVM, pCtxCore);
    20391895#endif
    2040 }
    2041 
    2042 
    2043 /**
    2044  * Gets and resets the changed flags (CPUM_CHANGED_*).
    2045  * Only REM should call this function.
    2046  *
    2047  * @returns The changed flags.
    2048  * @param   pVCpu       The VMCPU handle.
    2049  */
    2050 VMMDECL(unsigned) CPUMGetAndClearChangedFlagsREM(PVMCPU pVCpu)
    2051 {
    2052     unsigned fFlags = pVCpu->cpum.s.fChanged;
    2053     pVCpu->cpum.s.fChanged = 0;
    2054     /** @todo change the switcher to use the fChanged flags. */
    2055     if (pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_SINCE_REM)
    2056     {
    2057         fFlags |= CPUM_CHANGED_FPU_REM;
    2058         pVCpu->cpum.s.fUseFlags &= ~CPUM_USED_FPU_SINCE_REM;
    2059     }
    2060     return fFlags;
    20611896}
    20621897
     
    21692004
    21702005/**
    2171  * Mark the guest's debug state as inactive
     2006 * Mark the guest's debug state as inactive.
    21722007 *
    21732008 * @returns boolean
     
    21812016
    21822017/**
    2183  * Mark the hypervisor's debug state as inactive
     2018 * Mark the hypervisor's debug state as inactive.
    21842019 *
    21852020 * @returns boolean
     
    21922027
    21932028/**
    2194  * Checks if the hidden selector registers are valid
     2029 * Checks if the hidden selector registers are valid for the specified CPU.
     2030 *
    21952031 * @returns true if they are.
    21962032 * @returns false if not.
    2197  * @param   pVM     The VM handle.
    2198  */
    2199 VMMDECL(bool) CPUMAreHiddenSelRegsValid(PVM pVM)
    2200 {
    2201     return HWACCMIsEnabled(pVM);
     2033 * @param   pVCpu     The VM handle.
     2034 */
     2035VMMDECL(bool) CPUMAreHiddenSelRegsValid(PVMCPU pVCpu)
     2036{
     2037    bool const fRc = !(pVCpu->cpum.s.fChanged & CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID);
     2038    Assert(fRc || !HWACCMIsEnabled(pVCpu->CTX_SUFF(pVM)));
     2039    Assert(!pVCpu->cpum.s.fRemEntered);
     2040    return fRc;
    22022041}
    22032042
     
    22152054    uint32_t cpl;
    22162055
    2217     if (CPUMAreHiddenSelRegsValid(pVCpu->CTX_SUFF(pVM)))
     2056    if (CPUMAreHiddenSelRegsValid(pVCpu))
    22182057    {
    22192058        /*
  • trunk/src/VBox/VMM/VMMAll/PGMAllBth.h

    r29676 r30263  
    773773                             */
    774774                            RTGCPTR PC;
    775                             rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC);
     775                            rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs,
     776                                                              &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC);
    776777                            if (rc == VINF_SUCCESS)
    777778                            {
  • trunk/src/VBox/VMM/VMMAll/SELMAll.cpp

    r28800 r30263  
    9898    {
    9999        RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
    100         if (CPUMAreHiddenSelRegsValid(pVM))
     100        if (CPUMAreHiddenSelRegsValid(pVCpu))
    101101            uFlat += pHiddenSel->u64Base;
    102102        else
     
    106106
    107107#ifdef IN_RING0
    108     Assert(CPUMAreHiddenSelRegsValid(pVM));
     108    Assert(CPUMAreHiddenSelRegsValid(pVCpu));
    109109#else
    110110    /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
    111     if (!CPUMAreHiddenSelRegsValid(pVM))
     111    if (!CPUMAreHiddenSelRegsValid(pVCpu))
    112112        return SELMToFlatBySel(pVM, Sel, Addr);
    113113#endif
     
    170170        {
    171171            if (    pHiddenSel
    172                 &&  CPUMAreHiddenSelRegsValid(pVM))
     172                &&  CPUMAreHiddenSelRegsValid(pVCpu))
    173173                *ppvGC = (RTGCPTR)(pHiddenSel->u64Base + uFlat);
    174174            else
     
    186186#ifndef IN_RC
    187187    if (    pHiddenSel
    188         &&  CPUMAreHiddenSelRegsValid(pVM))
     188        &&  CPUMAreHiddenSelRegsValid(pVCpu))
    189189    {
    190190        bool fCheckLimit = true;
     
    460460 * @remarks Don't use when in long mode.
    461461 */
    462 VMMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
     462VMMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, PCCPUMSELREGHID pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
    463463{
    464464    PVMCPU pVCpu = VMMGetCpu(pVM);
     
    476476        {
    477477            if (    pHiddenSel
    478                 &&  CPUMAreHiddenSelRegsValid(pVM))
     478                &&  CPUMAreHiddenSelRegsValid(pVCpu))
    479479                *ppvGC = (RTGCPTR)(pHiddenSel->u64Base + uFlat);
    480480            else
     
    493493    /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
    494494    if (    pHiddenSel
    495         &&  CPUMAreHiddenSelRegsValid(pVM))
     495        &&  CPUMAreHiddenSelRegsValid(pVCpu))
    496496    {
    497497        u1Present     = pHiddenSel->Attr.n.u1Present;
     
    665665 *
    666666 * @returns VINF_SUCCESS.
    667  * @param   pVM     VM Handle.
     667 * @param   pVCpu   The Virtual CPU handle.
    668668 * @param   SelCS   Selector part.
    669669 * @param   pHidCS  The hidden CS register part. Optional.
     
    671671 * @param   ppvFlat Where to store the flat address.
    672672 */
    673 DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVM pVM, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
     673DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVMCPU pVCpu, RTSEL SelCS, PCCPUMSELREGHID pHidCS, RTGCPTR Addr,
     674                                                     PRTGCPTR ppvFlat)
    674675{
    675676    RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
    676     if (!pHidCS || !CPUMAreHiddenSelRegsValid(pVM))
     677    if (!pHidCS || !CPUMAreHiddenSelRegsValid(pVCpu))
    677678        uFlat += ((RTGCUINTPTR)SelCS << 4);
    678679    else
     
    690691 * @returns VBox status code.
    691692 * @param   pVM     VM Handle.
     693 * @param   pVCpu   The virtual CPU handle.
    692694 * @param   SelCPL  Current privilege level. Get this from SS - CS might be conforming!
    693695 *                  A full selector can be passed, we'll only use the RPL part.
     
    697699 * @param   pcBits  Where to store the segment bitness (16/32/64). Optional.
    698700 */
    699 DECLINLINE(int) selmValidateAndConvertCSAddrStd(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits)
    700 {
    701     Assert(!CPUMAreHiddenSelRegsValid(pVM));
    702 
     701DECLINLINE(int) selmValidateAndConvertCSAddrStd(PVM pVM, PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr,
     702                                                PRTGCPTR ppvFlat, uint32_t *pcBits)
     703{
    703704    /** @todo validate limit! */
    704705    X86DESC    Desc;
     
    771772 * @param   ppvFlat Where to store the flat address.
    772773 */
    773 DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
     774DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, PCCPUMSELREGHID pHidCS,
     775                                                   RTGCPTR Addr, PRTGCPTR ppvFlat)
    774776{
    775777    /*
     
    849851    {
    850852        *pcBits = 16;
    851         return selmValidateAndConvertCSAddrRealMode(pVM, SelCS, NULL, Addr, ppvFlat);
    852     }
    853     return selmValidateAndConvertCSAddrStd(pVM, SelCPL, SelCS, Addr, ppvFlat, pcBits);
     853        return selmValidateAndConvertCSAddrRealMode(pVCpu, SelCS, NULL, Addr, ppvFlat);
     854    }
     855    Assert(!CPUMAreHiddenSelRegsValid(pVCpu));
     856    return selmValidateAndConvertCSAddrStd(pVM, pVCpu, SelCPL, SelCS, Addr, ppvFlat, pcBits);
    854857}
    855858#endif /* IN_RC */
     
    869872 * @param   ppvFlat      Where to store the flat address.
    870873 */
    871 VMMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, CPUMSELREGHID *pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat)
     874VMMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, PCCPUMSELREGHID pHiddenCSSel,
     875                                          RTGCPTR Addr, PRTGCPTR ppvFlat)
    872876{
    873877    PVMCPU pVCpu = VMMGetCpu(pVM);
     
    875879    if (    eflags.Bits.u1VM
    876880        ||  CPUMIsGuestInRealMode(pVCpu))
    877         return selmValidateAndConvertCSAddrRealMode(pVM, SelCS, pHiddenCSSel, Addr, ppvFlat);
     881        return selmValidateAndConvertCSAddrRealMode(pVCpu, SelCS, pHiddenCSSel, Addr, ppvFlat);
    878882
    879883#ifdef IN_RING0
    880     Assert(CPUMAreHiddenSelRegsValid(pVM));
     884    Assert(CPUMAreHiddenSelRegsValid(pVCpu));
    881885#else
    882886    /** @todo when we're in 16 bits mode, we should cut off the address as well? (like in selmValidateAndConvertCSAddrRealMode) */
    883     if (!CPUMAreHiddenSelRegsValid(pVM))
    884         return selmValidateAndConvertCSAddrStd(pVM, SelCPL, SelCS, Addr, ppvFlat, NULL);
     887    if (!CPUMAreHiddenSelRegsValid(pVCpu) || !pHiddenCSSel)
     888        return selmValidateAndConvertCSAddrStd(pVM, pVCpu, SelCPL, SelCS, Addr, ppvFlat, NULL);
    885889#endif
    886890    return selmValidateAndConvertCSAddrHidden(pVCpu, SelCPL, SelCS, pHiddenCSSel, Addr, ppvFlat);
     
    894898 * @returns DISCPUMODE according to the selector type (16, 32 or 64 bits)
    895899 * @param   pVM     VM Handle.
     900 * @param   pVCpu   The virtual CPU handle.
    896901 * @param   Sel     The selector.
    897902 */
    898 static DISCPUMODE selmGetCpuModeFromSelector(PVM pVM, RTSEL Sel)
    899 {
    900     Assert(!CPUMAreHiddenSelRegsValid(pVM));
     903static DISCPUMODE selmGetCpuModeFromSelector(PVM pVM, PVMCPU pVCpu, RTSEL Sel)
     904{
     905    Assert(!CPUMAreHiddenSelRegsValid(pVCpu));
    901906
    902907    /** @todo validate limit! */
     
    924929 * @param   pHiddenSel The hidden selector register.
    925930 */
    926 VMMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, CPUMSELREGHID *pHiddenSel)
     931VMMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, PCCPUMSELREGHID pHiddenSel)
    927932{
    928933    PVMCPU pVCpu = VMMGetCpu(pVM);
    929934#ifdef IN_RING0
    930     Assert(CPUMAreHiddenSelRegsValid(pVM));
     935    Assert(CPUMAreHiddenSelRegsValid(pVCpu));
    931936#else  /* !IN_RING0 */
    932     if (!CPUMAreHiddenSelRegsValid(pVM))
     937    if (!CPUMAreHiddenSelRegsValid(pVCpu))
    933938    {
    934939        /*
     
    939944            return CPUMODE_16BIT;
    940945
    941         return selmGetCpuModeFromSelector(pVM, Sel);
     946        return selmGetCpuModeFromSelector(pVM, pVCpu, Sel);
    942947    }
    943948#endif /* !IN_RING0 */
     
    947952
    948953    /* Else compatibility or 32 bits mode. */
    949     return (pHiddenSel->Attr.n.u1DefBig) ? CPUMODE_32BIT : CPUMODE_16BIT;
     954    return pHiddenSel->Attr.n.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT;
    950955}
    951956
  • trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp

    r29250 r30263  
    358358 * @internal
    359359 */
    360 VMMDECL(int) TRPMForwardTrap(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t iGate, uint32_t opsize, TRPMERRORCODE enmError, TRPMEVENT enmType, int32_t iOrgTrap)
     360VMMDECL(int) TRPMForwardTrap(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t iGate, uint32_t opsize,
     361                             TRPMERRORCODE enmError, TRPMEVENT enmType, int32_t iOrgTrap)
    361362{
    362363#ifdef TRPM_FORWARD_TRAPS_IN_GC
Note: See TracChangeset for help on using the changeset viewer.

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