VirtualBox

Changeset 17510 in vbox for trunk/src


Ignore:
Timestamp:
Mar 7, 2009 3:54:02 AM (16 years ago)
Author:
vboxsync
Message:

PGM,EM,PDMDevHlp: Added PGMPhysInterpretedReadNoHandlers and PGMPhysInterpretedWriteNoHandlers for EM, and PGMR3PhysReadExternal and PGMR3PhysWriteExternal for PDMDevHlp. The former because PGMPhysRead/Write aren't the right APIs there (enforced now), and the latter because we have to make sure non-EMTs doesn't execute handlers or allocate pages.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMDevHlp.cpp

    r17371 r17510  
    4747*   Defined Constants And Macros                                               *
    4848*******************************************************************************/
    49 /** Allow physical read and writes from any thread.
    50  * (pdmR3DevHlp_PhysRead and pdmR3DevHlp_PhysWrite.)
    51  */
    52 #define PDM_PHYS_READWRITE_FROM_ANY_THREAD
    53 
    54 
    5549/** @name R3 DevHlp
    5650 * @{
     
    20332027{
    20342028    PDMDEV_ASSERT_DEVINS(pDevIns);
     2029    PVM pVM = pDevIns->Internal.s.pVMR3;
    20352030    LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
    20362031             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
    20372032
    2038     /*
    2039      * For the convenience of the device we put no thread restriction on this interface.
    2040      * That means we'll have to check which thread we're in and choose our path.
    2041      */
    2042 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    2043     PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    2044 #else
    2045     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    2046         PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
     2033    int rc = VINF_SUCCESS;
     2034#ifdef VBOX_WITH_NEW_PHYS_CODE
     2035    if (!VM_IS_EMT(pVM))
     2036        rc = PGMR3PhysReadExternal(pVM, GCPhys, pvBuf, cbRead);
    20472037    else
    2048     {
    2049         Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2050         PVMREQ pReq;
    2051         AssertCompileSize(RTGCPHYS, 4);
    2052         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    2053                                  (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    2054         while (rc == VERR_TIMEOUT)
    2055             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    2056         AssertReleaseRC(rc);
    2057         VMR3ReqFree(pReq);
    2058     }
    20592038#endif
    2060     Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2039        PGMPhysRead(pVM, GCPhys, pvBuf, cbRead);
     2040    Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2041    /** @todo return rc; */ NOREF(rc);
    20612042}
    20622043
     
    20662047{
    20672048    PDMDEV_ASSERT_DEVINS(pDevIns);
     2049    PVM pVM = pDevIns->Internal.s.pVMR3;
    20682050    LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
    20692051             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
    20702052
    2071     /*
    2072      * For the convenience of the device we put no thread restriction on this interface.
    2073      * That means we'll have to check which thread we're in and choose our path.
    2074      */
    2075 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    2076     PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    2077 #else
    2078     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    2079         PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
     2053    int rc = VINF_SUCCESS;
     2054#ifdef VBOX_WITH_NEW_PHYS_CODE
     2055    if (!VM_IS_EMT(pVM))
     2056        rc = PGMR3PhysWriteExternal(pVM, GCPhys, pvBuf, cbWrite);
    20802057    else
    2081     {
    2082         Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2083         PVMREQ pReq;
    2084         AssertCompileSize(RTGCPHYS, 4);
    2085         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    2086                                  (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    2087         while (rc == VERR_TIMEOUT)
    2088             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    2089         AssertReleaseRC(rc);
    2090         VMR3ReqFree(pReq);
    2091     }
    20922058#endif
    2093     Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2059        PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite);
     2060    Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2061    /** @todo return rc; */ NOREF(rc);
    20942062}
    20952063
  • trunk/src/VBox/VMM/PGMPhys.cpp

    r17509 r17510  
    8787#define PGMPHYS_DATATYPE    uint64_t
    8888#include "PGMPhysRWTmpl.h"
     89
     90
     91/**
     92 * EMT worker for PGMR3PhysReadExternal.
     93 */
     94static DECLCALLBACK(int) pgmR3PhysReadExternalEMT(PVM pVM, PRTGCPHYS pGCPhys, void *pvBuf, size_t cbRead)
     95{
     96    PGMPhysRead(pVM, *pGCPhys, pvBuf, cbRead);
     97    return VINF_SUCCESS;
     98}
     99
     100
     101/**
     102 * Write to physical memory, external users.
     103 *
     104 * @returns VBox status code.
     105 * @retval  VINF_SUCCESS.
     106 *
     107 * @param   pVM             VM Handle.
     108 * @param   GCPhys          Physical address to write to.
     109 * @param   pvBuf           What to write.
     110 * @param   cbWrite         How many bytes to write.
     111 *
     112 * @thread  Any but EMTs.
     113 */
     114VMMR3DECL(int) PGMR3PhysReadExternal(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
     115{
     116    VM_ASSERT_OTHER_THREAD(pVM);
     117
     118    AssertMsgReturn(cbRead > 0, ("don't even think about reading zero bytes!\n"), VINF_SUCCESS);
     119    LogFlow(("PGMR3PhysReadExternal: %RGp %d\n", GCPhys, cbRead));
     120
     121    pgmLock(pVM);
     122
     123    /*
     124     * Copy loop on ram ranges.
     125     */
     126    PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
     127    for (;;)
     128    {
     129        /* Find range. */
     130        while (pRam && GCPhys > pRam->GCPhysLast)
     131            pRam = pRam->CTX_SUFF(pNext);
     132        /* Inside range or not? */
     133        if (pRam && GCPhys >= pRam->GCPhys)
     134        {
     135            /*
     136             * Must work our way thru this page by page.
     137             */
     138            RTGCPHYS off = GCPhys - pRam->GCPhys;
     139            while (off < pRam->cb)
     140            {
     141                unsigned iPage = off >> PAGE_SHIFT;
     142                PPGMPAGE pPage = &pRam->aPages[iPage];
     143
     144                /*
     145                 * If the page has an ALL access handler, we'll have to
     146                 * delegate the job to EMT.
     147                 */
     148                if (PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage))
     149                {
     150                    pgmUnlock(pVM);
     151
     152                    PVMREQ pReq = NULL;
     153                    int rc = VMR3ReqCall(pVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT,
     154                                         (PFNRT)pgmR3PhysReadExternalEMT, 4, pVM, &GCPhys, pvBuf, cbRead);
     155                    if (RT_SUCCESS(rc))
     156                    {
     157                        rc = pReq->iStatus;
     158                        VMR3ReqFree(pReq);
     159                    }
     160                    return rc;
     161                }
     162                Assert(!PGM_PAGE_IS_MMIO(pPage));
     163
     164                /*
     165                 * Simple stuff, go ahead.
     166                 */
     167                size_t   cb    = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
     168                if (cb > cbRead)
     169                    cb = cbRead;
     170                const void *pvSrc;
     171                int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, pRam->GCPhys + off, &pvSrc);
     172                if (RT_SUCCESS(rc))
     173                    memcpy(pvBuf, pvSrc, cb);
     174                else
     175                {
     176                    AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternalReadOnly failed on %RGp / %R[pgmpage] -> %Rrc\n",
     177                                           pRam->GCPhys + off, pPage, rc));
     178                    memset(pvBuf, 0xff, cb);
     179                }
     180
     181                /* next page */
     182                if (cb >= cbRead)
     183                {
     184                    pgmUnlock(pVM);
     185                    return VINF_SUCCESS;
     186                }
     187                cbRead -= cb;
     188                off    += cb;
     189                GCPhys += cb;
     190                pvBuf   = (char *)pvBuf + cb;
     191            } /* walk pages in ram range. */
     192        }
     193        else
     194        {
     195            LogFlow(("PGMPhysRead: Unassigned %RGp size=%u\n", GCPhys, cbRead));
     196
     197            /*
     198             * Unassigned address space.
     199             */
     200            if (!pRam)
     201                break;
     202            size_t cb = pRam->GCPhys - GCPhys;
     203            if (cb >= cbRead)
     204            {
     205                memset(pvBuf, 0xff, cbRead);
     206                break;
     207            }
     208            memset(pvBuf, 0xff, cb);
     209
     210            cbRead -= cb;
     211            pvBuf   = (char *)pvBuf + cb;
     212            GCPhys += cb;
     213        }
     214    } /* Ram range walk */
     215
     216    pgmUnlock(pVM);
     217
     218    return VINF_SUCCESS;
     219}
     220
     221
     222/**
     223 * EMT worker for PGMR3PhysWriteExternal.
     224 */
     225static DECLCALLBACK(int) pgmR3PhysWriteExternalEMT(PVM pVM, PRTGCPHYS pGCPhys, const void *pvBuf, size_t cbWrite)
     226{
     227    /** @todo VERR_EM_NO_MEMORY */
     228    PGMPhysWrite(pVM, *pGCPhys, pvBuf, cbWrite);
     229    return VINF_SUCCESS;
     230}
     231
     232
     233/**
     234 * Write to physical memory, external users.
     235 *
     236 * @returns VBox status code.
     237 * @retval  VINF_SUCCESS.
     238 * @retval  VERR_EM_NO_MEMORY.
     239 *
     240 * @param   pVM             VM Handle.
     241 * @param   GCPhys          Physical address to write to.
     242 * @param   pvBuf           What to write.
     243 * @param   cbWrite         How many bytes to write.
     244 *
     245 * @thread  Any but EMTs.
     246 */
     247VMMDECL(int) PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
     248{
     249    VM_ASSERT_OTHER_THREAD(pVM);
     250
     251    AssertMsg(!pVM->pgm.s.fNoMorePhysWrites, ("Calling PGMR3PhysWriteExternal after pgmR3Save()!\n"));
     252    AssertMsgReturn(cbWrite > 0, ("don't even think about writing zero bytes!\n"), VINF_SUCCESS);
     253    LogFlow(("PGMR3PhysWriteExternal: %RGp %d\n", GCPhys, cbWrite));
     254
     255    pgmLock(pVM);
     256
     257    /*
     258     * Copy loop on ram ranges, stop when we hit something difficult.
     259     */
     260    PPGMRAMRANGE    pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
     261    for (;;)
     262    {
     263        /* Find range. */
     264        while (pRam && GCPhys > pRam->GCPhysLast)
     265            pRam = pRam->CTX_SUFF(pNext);
     266        /* Inside range or not? */
     267        if (pRam && GCPhys >= pRam->GCPhys)
     268        {
     269            /*
     270             * Must work our way thru this page by page.
     271             */
     272            RTGCPTR off = GCPhys - pRam->GCPhys;
     273            while (off < pRam->cb)
     274            {
     275                RTGCPTR     iPage = off >> PAGE_SHIFT;
     276                PPGMPAGE    pPage = &pRam->aPages[iPage];
     277
     278                /*
     279                 * It the page is in any way problematic, we have to
     280                 * do the work on the EMT. Anything that needs to be made
     281                 * writable or involves access handlers is problematic.
     282                 */
     283                if (    PGM_PAGE_HAS_ACTIVE_HANDLERS(pPage)
     284                    ||  PGM_PAGE_GET_STATE(pPage) != PGM_PAGE_STATE_ALLOCATED)
     285                {
     286                    pgmUnlock(pVM);
     287
     288                    PVMREQ pReq = NULL;
     289                    int rc = VMR3ReqCall(pVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT,
     290                                         (PFNRT)pgmR3PhysWriteExternalEMT, 4, pVM, &GCPhys, pvBuf, cbWrite);
     291                    if (RT_SUCCESS(rc))
     292                    {
     293                        rc = pReq->iStatus;
     294                        VMR3ReqFree(pReq);
     295                    }
     296                    return rc;
     297                }
     298                Assert(!PGM_PAGE_IS_MMIO(pPage));
     299
     300                /*
     301                 * Simple stuff, go ahead.
     302                 */
     303                size_t      cb    = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
     304                if (cb > cbWrite)
     305                    cb = cbWrite;
     306                void *pvDst;
     307                int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, pRam->GCPhys + off, &pvDst);
     308                if (RT_SUCCESS(rc))
     309                    memcpy(pvDst, pvBuf, cb);
     310                else
     311                    AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     312                                           pRam->GCPhys + off, pPage, rc));
     313
     314                /* next page */
     315                if (cb >= cbWrite)
     316                {
     317                    pgmUnlock(pVM);
     318                    return VINF_SUCCESS;
     319                }
     320
     321                cbWrite -= cb;
     322                off     += cb;
     323                GCPhys  += cb;
     324                pvBuf    = (const char *)pvBuf + cb;
     325            } /* walk pages in ram range */
     326        }
     327        else
     328        {
     329            /*
     330             * Unassigned address space, skip it.
     331             */
     332            if (!pRam)
     333                break;
     334            size_t cb = pRam->GCPhys - GCPhys;
     335            if (cb >= cbWrite)
     336                break;
     337            cbWrite -= cb;
     338            pvBuf   = (const char *)pvBuf + cb;
     339            GCPhys += cb;
     340        }
     341    } /* Ram range walk */
     342
     343    pgmUnlock(pVM);
     344    return VINF_SUCCESS;
     345}
    89346
    90347
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r17505 r17510  
    299299
    300300
    301 DECLINLINE(int) emRamRead(PVM pVM, void *pDest, RTGCPTR GCSrc, uint32_t cb)
    302 {
    303 #ifdef IN_RC
    304     int rc = MMGCRamRead(pVM, pDest, (void *)GCSrc, cb);
     301DECLINLINE(int) emRamRead(PVM pVM, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb)
     302{
     303#ifdef IN_RC
     304    int rc = MMGCRamRead(pVM, pvDst, (void *)GCPtrSrc, cb);
    305305    if (RT_LIKELY(rc != VERR_ACCESS_DENIED))
    306306        return rc;
     
    310310     * instruction and it either flushed the TLB or the CPU reused it.
    311311     */
     312#endif
     313#ifdef VBOX_WITH_NEW_PHYS_CODE
     314    return PGMPhysInterpretedReadNoHandlers(pVM, pCtxCore, pvDst, GCPtrSrc, cb, /*fMayTrap*/ false);
     315#else
     316    NOREF(pCtxCore);
     317# ifdef IN_RC
    312318    RTGCPHYS GCPhys;
    313     rc = PGMPhysGCPtr2GCPhys(pVM, GCSrc, &GCPhys);
     319    rc = PGMPhysGCPtr2GCPhys(pVM, GCPtrSrc, &GCPhys);
    314320    AssertRCReturn(rc, rc);
    315     PGMPhysRead(pVM, GCPhys, pDest, cb);
     321    PGMPhysRead(pVM, GCPhys, pvDst, cb);
    316322    return VINF_SUCCESS;
    317 #else
    318     return PGMPhysReadGCPtr(pVM, pDest, GCSrc, cb);
    319 #endif
    320 }
    321 
    322 
    323 DECLINLINE(int) emRamWrite(PVM pVM, RTGCPTR GCDest, void *pSrc, uint32_t cb)
    324 {
    325 #ifdef IN_RC
    326     int rc = MMGCRamWrite(pVM, (void *)GCDest, pSrc, cb);
     323# else
     324    return PGMPhysReadGCPtr(pVM, pvDst, GCPtrSrc, cb);
     325# endif
     326#endif
     327}
     328
     329
     330DECLINLINE(int) emRamWrite(PVM pVM, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, uint32_t cb)
     331{
     332#ifdef IN_RC
     333    int rc = MMGCRamWrite(pVM, (void *)(uintptr_t)GCPtrDst, (void *)pvSrc, cb);
    327334    if (RT_LIKELY(rc != VERR_ACCESS_DENIED))
    328335        return rc;
     
    334341     * access doesn't cost us much (see PGMPhysGCPtr2GCPhys()).
    335342     */
     343#endif
     344#ifdef VBOX_WITH_NEW_PHYS_CODE
     345    return PGMPhysInterpretedWriteNoHandlers(pVM, pCtxCore, GCPtrDst, pvSrc, cb, /*fMayTrap*/ false);
     346#else
     347    NOREF(pCtxCore);
     348# ifdef IN_RC
    336349    uint64_t fFlags;
    337350    RTGCPHYS GCPhys;
    338     rc = PGMGstGetPage(pVM, GCDest, &fFlags, &GCPhys);
     351    rc = PGMGstGetPage(pVM, GCPtrDst, &fFlags, &GCPhys);
    339352    if (RT_FAILURE(rc))
    340353        return rc;
     
    345358    PGMPhysWrite(pVM, GCPhys + ((RTGCUINTPTR)GCDest & PAGE_OFFSET_MASK), pSrc, cb);
    346359    return VINF_SUCCESS;
    347 
    348 #else
    349     return PGMPhysWriteGCPtr(pVM, GCDest, pSrc, cb);
     360# else
     361    return PGMPhysWriteGCPtr(pVM, GCPtrDst, pvSrc, cb);
     362# endif
    350363#endif
    351364}
     
    455468                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    456469                EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    457                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     470                rc = emRamRead(pVM, pRegFrame, &valpar1, pParam1, param1.size);
    458471                if (RT_FAILURE(rc))
    459472                {
     
    474487                pParam2 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param2, pParam2);
    475488                EM_ASSERT_FAULT_RETURN(pParam2 == pvFault, VERR_EM_INTERPRETER);
    476                 rc = emRamRead(pVM, &valpar2, pParam2, param2.size);
     489                rc = emRamRead(pVM, pRegFrame, &valpar2, pParam2, param2.size);
    477490                if (RT_FAILURE(rc))
    478491                {
     
    508521            else
    509522            {
    510                 rc = emRamWrite(pVM, pParam1, &valpar2, param1.size);
     523                rc = emRamWrite(pVM, pRegFrame, pParam1, &valpar2, param1.size);
    511524                if (RT_FAILURE(rc))
    512525                {
     
    534547            else
    535548            {
    536                 rc = emRamWrite(pVM, pParam2, &valpar1, param2.size);
     549                rc = emRamWrite(pVM, pRegFrame, pParam2, &valpar1, param2.size);
    537550                if (RT_FAILURE(rc))
    538551                {
     
    581594                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
    582595#endif
    583                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     596                rc = emRamRead(pVM, pRegFrame, &valpar1, pParam1, param1.size);
    584597                if (RT_FAILURE(rc))
    585598                {
     
    599612
    600613            /* Write result back */
    601             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     614            rc = emRamWrite(pVM, pRegFrame, pParam1, &valpar1, param1.size);
    602615            if (RT_FAILURE(rc))
    603616            {
     
    651664                return VERR_EM_INTERPRETER;
    652665
    653             rc = emRamRead(pVM, &valpar1, pStackVal, param1.size);
     666            rc = emRamRead(pVM, pRegFrame, &valpar1, pStackVal, param1.size);
    654667            if (RT_FAILURE(rc))
    655668            {
     
    672685                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    673686                EM_ASSERT_FAULT_RETURN(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, VERR_EM_INTERPRETER);
    674                 rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     687                rc = emRamWrite(pVM, pRegFrame, pParam1, &valpar1, param1.size);
    675688                if (RT_FAILURE(rc))
    676689                {
     
    744757                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    745758                EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    746                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     759                rc = emRamRead(pVM, pRegFrame, &valpar1, pParam1, param1.size);
    747760                if (RT_FAILURE(rc))
    748761                {
     
    781794
    782795            /* And write it back */
    783             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     796            rc = emRamWrite(pVM, pRegFrame, pParam1, &valpar1, param1.size);
    784797            if (RT_SUCCESS(rc))
    785798            {
     
    922935                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    923936                EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    924                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     937                rc = emRamRead(pVM, pRegFrame, &valpar1, pParam1, param1.size);
    925938                if (RT_FAILURE(rc))
    926939                {
     
    957970
    958971            /* And write it back */
    959             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     972            rc = emRamWrite(pVM, pRegFrame, pParam1, &valpar1, param1.size);
    960973            if (RT_SUCCESS(rc))
    961974            {
     
    10311044            pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + valpar2/8);
    10321045            EM_ASSERT_FAULT_RETURN((RTGCPTR)((RTGCUINTPTR)pParam1 & ~3) == pvFault, VERR_EM_INTERPRETER);
    1033             rc = emRamRead(pVM, &valpar1, pParam1, 1);
     1046            rc = emRamRead(pVM, pRegFrame, &valpar1, pParam1, 1);
    10341047            if (RT_FAILURE(rc))
    10351048            {
     
    10491062
    10501063            /* And write it back */
    1051             rc = emRamWrite(pVM, pParam1, &valpar1, 1);
     1064            rc = emRamWrite(pVM, pRegFrame, pParam1, &valpar1, 1);
    10521065            if (RT_SUCCESS(rc))
    10531066            {
     
    12021215            Assert(param2.size <= 8 && param2.size > 0);
    12031216            EM_ASSERT_FAULT_RETURN(pDest == pvFault, VERR_EM_INTERPRETER);
    1204             rc = emRamWrite(pVM, pDest, &val64, param2.size);
     1217            rc = emRamWrite(pVM, pRegFrame, pDest, &val64, param2.size);
    12051218            if (RT_FAILURE(rc))
    12061219                return VERR_EM_INTERPRETER;
     
    12321245            Assert(param1.size <= 8 && param1.size > 0);
    12331246            EM_ASSERT_FAULT_RETURN(pSrc == pvFault, VERR_EM_INTERPRETER);
    1234             rc = emRamRead(pVM, &val64, pSrc, param1.size);
     1247            rc = emRamRead(pVM, pRegFrame, &val64, pSrc, param1.size);
    12351248            if (RT_FAILURE(rc))
    12361249                return VERR_EM_INTERPRETER;
     
    17731786    Assert(!CPUMIsGuestIn64BitCode(pVM, pRegFrame));
    17741787
    1775     rc  = emRamRead(pVM, &eip,      (RTGCPTR)pIretStack      , 4);
    1776     rc |= emRamRead(pVM, &cs,       (RTGCPTR)(pIretStack + 4), 4);
    1777     rc |= emRamRead(pVM, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
     1788    rc  = emRamRead(pVM, pRegFrame, &eip,      (RTGCPTR)pIretStack      , 4);
     1789    rc |= emRamRead(pVM, pRegFrame, &cs,       (RTGCPTR)(pIretStack + 4), 4);
     1790    rc |= emRamRead(pVM, pRegFrame, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
    17781791    AssertRCReturn(rc, VERR_EM_INTERPRETER);
    17791792    AssertReturn(eflags & X86_EFL_VM, VERR_EM_INTERPRETER);
    17801793
    1781     rc |= emRamRead(pVM, &esp,      (RTGCPTR)(pIretStack + 12), 4);
    1782     rc |= emRamRead(pVM, &ss,       (RTGCPTR)(pIretStack + 16), 4);
    1783     rc |= emRamRead(pVM, &es,       (RTGCPTR)(pIretStack + 20), 4);
    1784     rc |= emRamRead(pVM, &ds,       (RTGCPTR)(pIretStack + 24), 4);
    1785     rc |= emRamRead(pVM, &fs,       (RTGCPTR)(pIretStack + 28), 4);
    1786     rc |= emRamRead(pVM, &gs,       (RTGCPTR)(pIretStack + 32), 4);
     1794    rc |= emRamRead(pVM, pRegFrame, &esp,      (RTGCPTR)(pIretStack + 12), 4);
     1795    rc |= emRamRead(pVM, pRegFrame, &ss,       (RTGCPTR)(pIretStack + 16), 4);
     1796    rc |= emRamRead(pVM, pRegFrame, &es,       (RTGCPTR)(pIretStack + 20), 4);
     1797    rc |= emRamRead(pVM, pRegFrame, &ds,       (RTGCPTR)(pIretStack + 24), 4);
     1798    rc |= emRamRead(pVM, pRegFrame, &fs,       (RTGCPTR)(pIretStack + 28), 4);
     1799    rc |= emRamRead(pVM, pRegFrame, &gs,       (RTGCPTR)(pIretStack + 32), 4);
    17871800    AssertRCReturn(rc, VERR_EM_INTERPRETER);
    17881801
     
    22572270        LogFlow(("emInterpretSmsw %VGv <- cr0 (%x)\n", pParam1, cr0));
    22582271
    2259         rc = emRamWrite(pVM, pParam1, &cr0, sizeof(uint16_t));
     2272        rc = emRamWrite(pVM, pRegFrame, pParam1, &cr0, sizeof(uint16_t));
    22602273        if (RT_FAILURE(rc))
    22612274        {
     
    24512464    }
    24522465
    2453     rc = emRamRead(pVM, &dtr32, pParam1, sizeof(dtr32));
     2466    rc = emRamRead(pVM, pRegFrame, &dtr32, pParam1, sizeof(dtr32));
    24542467    AssertRCReturn(rc, VERR_EM_INTERPRETER);
    24552468
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r17509 r17510  
    15381538            if (cb >= cbRead)
    15391539            {
    1540 #if 0 /** @todo enable this later. */
    15411540                memset(pvBuf, 0xff, cbRead);
    1542 #else
    1543                 memset(pvBuf, 0, cbRead);
    1544 #endif
    15451541                break;
    15461542            }
    15471543
    1548 #if 0 /** @todo enable this later. */
    15491544            memset(pvBuf, 0xff, cb);
    1550 #else
    1551             memset(pvBuf, 0, cb);
    1552 #endif
    15531545            cbRead -= cb;
    15541546            pvBuf   = (char *)pvBuf + cb;
     
    25832575#endif /* Old PGMPhysWrite */
    25842576
     2577
    25852578/**
    25862579 * Read from guest physical memory by GC physical address, bypassing
     
    32573250}
    32583251
    3259 /// @todo VMMDECL(int) PGMPhysInterpretedWrite(PVM pVM, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb)
    3260 
    3261 
     3252
     3253/**
     3254 * Performs a read of guest virtual memory for instruction emulation.
     3255 *
     3256 * This will check permissions, raise exceptions and update the access bits.
     3257 *
     3258 * The current implementation will bypass all access handlers. It may later be
     3259 * changed to at least respect MMIO.
     3260 *
     3261 *
     3262 * @returns VBox status code suitable to scheduling.
     3263 * @retval  VINF_SUCCESS if the read was performed successfully.
     3264 * @retval  VINF_EM_RAW_GUEST_TRAP if an exception was raised but not dispatched yet.
     3265 * @retval  VINF_TRPM_XCPT_DISPATCHED if an exception was raised and dispatched.
     3266 *
     3267 * @param   pVM         The VM handle.
     3268 * @param   pCtxCore    The context core.
     3269 * @param   pvDst       Where to put the bytes we've read.
     3270 * @param   GCPtrSrc    The source address.
     3271 * @param   cb          The number of bytes to read. Not more than a page.
     3272 * @param   fRaiseTrap  If set the trap will be raised on as per spec, if clear
     3273 *                      an appropriate error status will be returned (no
     3274 *                      informational at all).
     3275 *
     3276 *
     3277 * @remarks Takes the PGM lock.
     3278 * @remarks A page fault on the 2nd page of the access will be raised without
     3279 *          writing the bits on the first page since we're ASSUMING that the
     3280 *          caller is emulating an instruction access.
     3281 * @remarks This function will dynamically map physical pages in GC. This may
     3282 *          unmap mappings done by the caller. Be careful!
     3283 */
     3284VMMDECL(int) PGMPhysInterpretedReadNoHandlers(PVM pVM, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCUINTPTR GCPtrSrc, size_t cb, bool fRaiseTrap)
     3285{
     3286    Assert(cb <= PAGE_SIZE);
     3287
     3288    /*
     3289     * 1. Translate virtual to physical. This may fault.
     3290     * 2. Map the physical address.
     3291     * 3. Do the read operation.
     3292     * 4. Set access bits if required.
     3293     */
     3294    int rc;
     3295    unsigned cb1 = PAGE_SIZE - (GCPtrSrc & PAGE_OFFSET_MASK);
     3296    if (cb <= cb1)
     3297    {
     3298        /*
     3299         * Not crossing pages.
     3300         */
     3301        RTGCPHYS    GCPhys;
     3302        uint64_t    fFlags;
     3303        rc = PGM_GST_PFN(GetPage,pVM)(pVM, GCPtrSrc, &fFlags, &GCPhys);
     3304        if (RT_SUCCESS(rc))
     3305        {
     3306            if (1) /** @todo we should check reserved bits ... */
     3307            {
     3308                const void *pvSrc;
     3309                PGMPAGEMAPLOCK Lock;
     3310                rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvSrc, &Lock);
     3311                switch (rc)
     3312                {
     3313                    case VINF_SUCCESS:
     3314                        Log(("PGMPhysInterpretedReadNoHandlers: pvDst=%p pvSrc=%p (%RGv) cb=%d\n",
     3315                               pvDst, (const uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), GCPtrSrc, cb));
     3316                        memcpy(pvDst, (const uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), cb);
     3317                        break;
     3318                    case VERR_PGM_PHYS_PAGE_RESERVED:
     3319                    case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
     3320                        memset(pvDst, 0xff, cb);
     3321                        break;
     3322                    default:
     3323                        AssertMsgFailed(("%Rrc\n", rc));
     3324                        AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3325                        return rc;
     3326                }
     3327                PGMPhysReleasePageMappingLock(pVM, &Lock);
     3328
     3329                if (!(fFlags & X86_PTE_A))
     3330                {
     3331                    /** @todo access bit emulation isn't 100% correct. */
     3332                    rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrSrc, 1, X86_PTE_A, ~(uint64_t)X86_PTE_A);
     3333                    AssertRC(rc);
     3334                }
     3335                return VINF_SUCCESS;
     3336            }
     3337        }
     3338    }
     3339    else
     3340    {
     3341        /*
     3342         * Crosses pages.
     3343         */
     3344        size_t      cb2 = cb - cb1;
     3345        uint64_t    fFlags1;
     3346        RTGCPHYS    GCPhys1;
     3347        uint64_t    fFlags2;
     3348        RTGCPHYS    GCPhys2;
     3349        rc = PGM_GST_PFN(GetPage,pVM)(pVM, GCPtrSrc, &fFlags1, &GCPhys1);
     3350        if (RT_SUCCESS(rc))
     3351        {
     3352            rc = PGM_GST_PFN(GetPage,pVM)(pVM, GCPtrSrc + cb1, &fFlags2, &GCPhys2);
     3353            if (RT_SUCCESS(rc))
     3354            {
     3355                if (1) /** @todo we should check reserved bits ... */
     3356                {
     3357                    const void *pvSrc;
     3358                    PGMPAGEMAPLOCK Lock;
     3359                    rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys1, &pvSrc, &Lock);
     3360                    switch (rc)
     3361                    {
     3362                        case VINF_SUCCESS:
     3363                            Log(("PGMPhysInterpretedReadNoHandlers: pvDst=%p pvSrc=%p (%RGv) cb=%d [2]\n",
     3364                                   pvDst, (const uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), GCPtrSrc, cb1));
     3365                            memcpy(pvDst, (const uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), cb1);
     3366                            PGMPhysReleasePageMappingLock(pVM, &Lock);
     3367                            break;
     3368                        case VERR_PGM_PHYS_PAGE_RESERVED:
     3369                        case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
     3370                            memset(pvDst, 0xff, cb1);
     3371                            break;
     3372                        default:
     3373                            AssertMsgFailed(("%Rrc\n", rc));
     3374                            AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3375                            return rc;
     3376                    }
     3377
     3378                    rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys2, &pvSrc, &Lock);
     3379                    switch (rc)
     3380                    {
     3381                        case VINF_SUCCESS:
     3382                            memcpy((uint8_t *)pvDst + cb1, pvSrc, cb2);
     3383                            PGMPhysReleasePageMappingLock(pVM, &Lock);
     3384                            break;
     3385                        case VERR_PGM_PHYS_PAGE_RESERVED:
     3386                        case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
     3387                            memset((uint8_t *)pvDst + cb1, 0xff, cb2);
     3388                            break;
     3389                        default:
     3390                            AssertMsgFailed(("%Rrc\n", rc));
     3391                            AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3392                            return rc;
     3393                    }
     3394
     3395                    if (!(fFlags1 & X86_PTE_A))
     3396                    {
     3397                        rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrSrc, 1, X86_PTE_A, ~(uint64_t)X86_PTE_A);
     3398                        AssertRC(rc);
     3399                    }
     3400                    if (!(fFlags2 & X86_PTE_A))
     3401                    {
     3402                        rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrSrc + cb1, 1, X86_PTE_A, ~(uint64_t)X86_PTE_A);
     3403                        AssertRC(rc);
     3404                    }
     3405                    return VINF_SUCCESS;
     3406                }
     3407                /* sort out which page */
     3408            }
     3409            else
     3410                GCPtrSrc += cb1; /* fault on 2nd page */
     3411        }
     3412    }
     3413
     3414    /*
     3415     * Raise a #PF if we're allowed to do that.
     3416     */
     3417    /* Calc the error bits. */
     3418    uint32_t cpl = CPUMGetGuestCPL(pVM, pCtxCore);
     3419    uint32_t uErr;
     3420    switch (rc)
     3421    {
     3422        case VINF_SUCCESS:
     3423            uErr = (cpl >= 2) ? X86_TRAP_PF_RSVD | X86_TRAP_PF_US : X86_TRAP_PF_RSVD;
     3424            rc = VERR_ACCESS_DENIED;
     3425            break;
     3426
     3427        case VERR_PAGE_NOT_PRESENT:
     3428        case VERR_PAGE_TABLE_NOT_PRESENT:
     3429            uErr = (cpl >= 2) ? X86_TRAP_PF_US : 0;
     3430            break;
     3431
     3432        default:
     3433            AssertMsgFailed(("rc=%Rrc GCPtrSrc=%RGv cb=%#x\n", rc, GCPtrSrc, cb));
     3434            AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3435            return rc;
     3436    }
     3437    if (fRaiseTrap)
     3438    {
     3439        Log(("PGMPhysInterpretedReadNoHandlers: GCPtrSrc=%RGv cb=%#x -> Raised #PF(%#x)\n", GCPtrSrc, cb, uErr));
     3440        return TRPMRaiseXcptErrCR2(pVM, pCtxCore, X86_XCPT_PF, uErr, GCPtrSrc);
     3441    }
     3442    Log(("PGMPhysInterpretedReadNoHandlers: GCPtrSrc=%RGv cb=%#x -> #PF(%#x) [!raised]\n", GCPtrSrc, cb, uErr));
     3443    return rc;
     3444}
     3445
     3446
     3447/**
     3448 * Performs a write to guest virtual memory for instruction emulation.
     3449 *
     3450 * This will check permissions, raise exceptions and update the dirty and access
     3451 * bits.
     3452 *
     3453 * @returns VBox status code suitable to scheduling.
     3454 * @retval  VINF_SUCCESS if the read was performed successfully.
     3455 * @retval  VINF_EM_RAW_GUEST_TRAP if an exception was raised but not dispatched yet.
     3456 * @retval  VINF_TRPM_XCPT_DISPATCHED if an exception was raised and dispatched.
     3457 *
     3458 * @param   pVM         The VM handle.
     3459 * @param   pCtxCore    The context core.
     3460 * @param   GCPtrDst    The destination address.
     3461 * @param   pvSrc       What to write.
     3462 * @param   cb          The number of bytes to write. Not more than a page.
     3463 * @param   fRaiseTrap  If set the trap will be raised on as per spec, if clear
     3464 *                      an appropriate error status will be returned (no
     3465 *                      informational at all).
     3466 *
     3467 * @remarks Takes the PGM lock.
     3468 * @remarks A page fault on the 2nd page of the access will be raised without
     3469 *          writing the bits on the first page since we're ASSUMING that the
     3470 *          caller is emulating an instruction access.
     3471 * @remarks This function will dynamically map physical pages in GC. This may
     3472 *          unmap mappings done by the caller. Be careful!
     3473 */
     3474VMMDECL(int) PGMPhysInterpretedWriteNoHandlers(PVM pVM, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb, bool fRaiseTrap)
     3475{
     3476    Assert(cb <= PAGE_SIZE);
     3477
     3478    /*
     3479     * 1. Translate virtual to physical. This may fault.
     3480     * 2. Map the physical address.
     3481     * 3. Do the write operation.
     3482     * 4. Set access bits if required.
     3483     */
     3484    int rc;
     3485    unsigned cb1 = PAGE_SIZE - (GCPtrDst & PAGE_OFFSET_MASK);
     3486    if (cb <= cb1)
     3487    {
     3488        /*
     3489         * Not crossing pages.
     3490         */
     3491        RTGCPHYS    GCPhys;
     3492        uint64_t    fFlags;
     3493        rc = PGM_GST_PFN(GetPage,pVM)(pVM, GCPtrDst, &fFlags, &GCPhys);
     3494        if (RT_SUCCESS(rc))
     3495        {
     3496            if (    (fFlags & X86_PTE_RW)                   /** @todo Also check reserved bits. */
     3497                ||  (   !(CPUMGetGuestCR0(pVM) & X86_CR0_WP)
     3498                     &&   CPUMGetGuestCPL(pVM, pCtxCore) <= 2) ) /** @todo it's 2, right? Check cpl check below as well. */
     3499            {
     3500                void *pvDst;
     3501                PGMPAGEMAPLOCK Lock;
     3502                rc = PGMPhysGCPhys2CCPtr(pVM, GCPhys, &pvDst, &Lock);
     3503                switch (rc)
     3504                {
     3505                    case VINF_SUCCESS:
     3506                        Log(("PGMPhysInterpretedWriteNoHandlers: pvDst=%p (%RGv) pvSrc=%p cb=%d\n",
     3507                               (uint8_t *)pvDst + (GCPtrDst & PAGE_OFFSET_MASK), GCPtrDst, pvSrc,  cb));
     3508                        memcpy((uint8_t *)pvDst + (GCPtrDst & PAGE_OFFSET_MASK), pvSrc, cb);
     3509                        PGMPhysReleasePageMappingLock(pVM, &Lock);
     3510                        break;
     3511                    case VERR_PGM_PHYS_PAGE_RESERVED:
     3512                    case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
     3513                        /* bit bucket */
     3514                        break;
     3515                    default:
     3516                        AssertMsgFailed(("%Rrc\n", rc));
     3517                        AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3518                        return rc;
     3519                }
     3520
     3521                if (!(fFlags & (X86_PTE_A | X86_PTE_D)))
     3522                {
     3523                    /** @todo dirty & access bit emulation isn't 100% correct. */
     3524                    rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrDst, 1, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D));
     3525                    AssertRC(rc);
     3526                }
     3527                return VINF_SUCCESS;
     3528            }
     3529            rc = VERR_ACCESS_DENIED;
     3530        }
     3531    }
     3532    else
     3533    {
     3534        /*
     3535         * Crosses pages.
     3536         */
     3537        size_t      cb2 = cb - cb1;
     3538        uint64_t    fFlags1;
     3539        RTGCPHYS    GCPhys1;
     3540        uint64_t    fFlags2;
     3541        RTGCPHYS    GCPhys2;
     3542        rc = PGM_GST_PFN(GetPage,pVM)(pVM, GCPtrDst, &fFlags1, &GCPhys1);
     3543        if (RT_SUCCESS(rc))
     3544        {
     3545            rc = PGM_GST_PFN(GetPage,pVM)(pVM, GCPtrDst + cb1, &fFlags2, &GCPhys2);
     3546            if (RT_SUCCESS(rc))
     3547            {
     3548                if (    (   (fFlags1 & X86_PTE_RW)  /** @todo Also check reserved bits. */
     3549                         && (fFlags2 & X86_PTE_RW))
     3550                    ||  (   !(CPUMGetGuestCR0(pVM) & X86_CR0_WP)
     3551                         &&   CPUMGetGuestCPL(pVM, pCtxCore) <= 2) )
     3552                {
     3553                    void *pvDst;
     3554                    PGMPAGEMAPLOCK Lock;
     3555                    rc = PGMPhysGCPhys2CCPtr(pVM, GCPhys1, &pvDst, &Lock);
     3556                    switch (rc)
     3557                    {
     3558                        case VINF_SUCCESS:
     3559                            Log(("PGMPhysInterpretedWriteNoHandlers: pvDst=%p (%RGv) pvSrc=%p cb=%d\n",
     3560                                   (uint8_t *)pvDst + (GCPtrDst & PAGE_OFFSET_MASK), GCPtrDst, pvSrc, cb1));
     3561                            memcpy((uint8_t *)pvDst + (GCPtrDst & PAGE_OFFSET_MASK), pvSrc, cb1);
     3562                            PGMPhysReleasePageMappingLock(pVM, &Lock);
     3563                            break;
     3564                        case VERR_PGM_PHYS_PAGE_RESERVED:
     3565                        case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
     3566                            /* bit bucket */
     3567                            break;
     3568                        default:
     3569                            AssertMsgFailed(("%Rrc\n", rc));
     3570                            AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3571                            return rc;
     3572                    }
     3573
     3574                    rc = PGMPhysGCPhys2CCPtr(pVM, GCPhys2, &pvDst, &Lock);
     3575                    switch (rc)
     3576                    {
     3577                        case VINF_SUCCESS:
     3578                            memcpy(pvDst, (const uint8_t *)pvSrc + cb1, cb2);
     3579                            PGMPhysReleasePageMappingLock(pVM, &Lock);
     3580                            break;
     3581                        case VERR_PGM_PHYS_PAGE_RESERVED:
     3582                        case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
     3583                            /* bit bucket */
     3584                            break;
     3585                        default:
     3586                            AssertMsgFailed(("%Rrc\n", rc));
     3587                            AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3588                            return rc;
     3589                    }
     3590
     3591                    if (!(fFlags1 & (X86_PTE_A | X86_PTE_RW)))
     3592                    {
     3593                        rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrDst, 1, (X86_PTE_A | X86_PTE_RW), ~(uint64_t)(X86_PTE_A | X86_PTE_RW));
     3594                        AssertRC(rc);
     3595                    }
     3596                    if (!(fFlags2 & (X86_PTE_A | X86_PTE_RW)))
     3597                    {
     3598                        rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrDst + cb1, 1, (X86_PTE_A | X86_PTE_RW), ~(uint64_t)(X86_PTE_A | X86_PTE_RW));
     3599                        AssertRC(rc);
     3600                    }
     3601                    return VINF_SUCCESS;
     3602                }
     3603                if ((fFlags1 & (X86_PTE_RW)) == X86_PTE_RW)
     3604                    GCPtrDst += cb1; /* fault on the 2nd page. */
     3605                rc = VERR_ACCESS_DENIED;
     3606            }
     3607            else
     3608                GCPtrDst += cb1; /* fault on the 2nd page. */
     3609        }
     3610    }
     3611
     3612    /*
     3613     * Raise a #PF if we're allowed to do that.
     3614     */
     3615    /* Calc the error bits. */
     3616    uint32_t uErr;
     3617    uint32_t cpl = CPUMGetGuestCPL(pVM, pCtxCore);
     3618    switch (rc)
     3619    {
     3620        case VINF_SUCCESS:
     3621            uErr = (cpl >= 2) ? X86_TRAP_PF_RSVD | X86_TRAP_PF_US : X86_TRAP_PF_RSVD;
     3622            rc = VERR_ACCESS_DENIED;
     3623            break;
     3624
     3625        case VERR_ACCESS_DENIED:
     3626            uErr = (cpl >= 2) ? X86_TRAP_PF_RW | X86_TRAP_PF_US : X86_TRAP_PF_RW;
     3627            break;
     3628
     3629        case VERR_PAGE_NOT_PRESENT:
     3630        case VERR_PAGE_TABLE_NOT_PRESENT:
     3631            uErr = (cpl >= 2) ? X86_TRAP_PF_US : 0;
     3632            break;
     3633
     3634        default:
     3635            AssertMsgFailed(("rc=%Rrc GCPtrDst=%RGv cb=%#x\n", rc, GCPtrDst, cb));
     3636            AssertReturn(RT_FAILURE(rc), VERR_INTERNAL_ERROR);
     3637            return rc;
     3638    }
     3639    if (fRaiseTrap)
     3640    {
     3641        Log(("PGMPhysInterpretedWriteNoHandlers: GCPtrDst=%RGv cb=%#x -> Raised #PF(%#x)\n", GCPtrDst, cb, uErr));
     3642        return TRPMRaiseXcptErrCR2(pVM, pCtxCore, X86_XCPT_PF, uErr, GCPtrDst);
     3643    }
     3644    Log(("PGMPhysInterpretedWriteNoHandlers: GCPtrDst=%RGv cb=%#x -> #PF(%#x) [!raised]\n", GCPtrDst, cb, uErr));
     3645    return rc;
     3646}
     3647
     3648
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