VirtualBox

Changeset 55937 in vbox for trunk


Ignore:
Timestamp:
May 19, 2015 2:27:00 PM (10 years ago)
Author:
vboxsync
Message:

CSAM,PATM: Changed csamRCCodePageWritePfHandler to store the pvFault address in pvDirtyFaultPage and made csamR3FlushDirtyPages make it instead of pvDirtyBasePage read-only (+ tell REM about it). Preparing ring-3 access handlers for raw-mode.

Location:
trunk
Files:
9 edited

Legend:

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

    r55001 r55937  
    165165 */
    166166
    167 VMMRC_INT_DECL(int)     PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
    168 VMMRC_INT_DECL(int)     PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite);
    169 VMMRC_INT_DECL(int)     PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
     167VMMRC_INT_DECL(int)             PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
     168VMMRC_INT_DECL(VBOXSTRICTRC)    PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite);
     169VMMRC_INT_DECL(int)             PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
    170170
    171171/** @} */
  • trunk/src/VBox/VMM/VMMAll/CSAMAll.cpp

    r45620 r55937  
    2929#include <VBox/vmm/hm.h>
    3030#include <VBox/vmm/mm.h>
     31#ifdef VBOX_WITH_REM
     32# include <VBox/vmm/rem.h>
     33#endif
    3134#include <VBox/sup.h>
    3235#include <VBox/vmm/mm.h>
     
    4548#include <iprt/string.h>
    4649
     50#ifdef IN_RING0
     51# error "IN_RING3 & IN_RC only!"
     52#endif
     53
     54
     55/**
     56 * Access handler callback for virtual access handler ranges.
     57 *
     58 * Important to realize that a physical page in a range can have aliases, and
     59 * for ALL and WRITE handlers these will also trigger.
     60 *
     61 * @returns VINF_SUCCESS if the handler have carried out the operation.
     62 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
     63 * @param   pVM             Pointer to the VM.
     64 * @param   pVCpu       Pointer to the cross context CPU context for the
     65 *                      calling EMT.
     66 * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
     67 * @param   pvPtr           The HC mapping of that address.
     68 * @param   pvBuf           What the guest is reading/writing.
     69 * @param   cbBuf           How much it's reading/writing.
     70 * @param   enmAccessType   The access type.
     71 * @param   enmOrigin       Who is making this write.
     72 * @param   pvUser          User argument.
     73 */
     74PGM_ALL_CB2_DECL(int) csamCodePageWriteHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
     75                                               PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
     76{
     77    RTGCPTR const GCPtrMonitored = (uintptr_t)pvUser | (GCPtr & PAGE_OFFSET_MASK);
     78    Log(("csamCodePageWriteHandler: write to %RGv LB %zu\n", GCPtr, cbBuf));
     79
     80    Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
     81    Assert(VMCPU_IS_EMT(pVCpu));
     82
     83    /*
     84     * Check if it's a dummy write that doesn't change anything.
     85     */
     86    if (   PAGE_ADDRESS(pvPtr) == PAGE_ADDRESS((uintptr_t)pvPtr + cbBuf - 1)
     87        && !memcmp(pvPtr, pvBuf, cbBuf))
     88    {
     89        Log(("csamCodePageWriteHandler: dummy write -> ignore\n"));
     90        return VINF_PGM_HANDLER_DO_DEFAULT;
     91    }
     92
     93#ifdef IN_RING3
     94    /*
     95     * Ring-3: Do proper handling.
     96     */
     97    int rc = PATMR3PatchWrite(pVM, GCPtrMonitored, (uint32_t)cbBuf);
     98    AssertRC(rc);
     99    return VINF_PGM_HANDLER_DO_DEFAULT;
     100
     101#else
     102    /*
     103     * Raw-mode: Try avoid needing to go to ring-3 (same as csamRCCodePageWritePfHandler).
     104     */
     105    uint32_t     const cpl            = CPUMGetGuestCPL(pVCpu);
     106    bool         const fPatchCode     = PATMIsPatchGCAddr(pVM, CPUMGetGuestRIP(pVCpu));
     107    PPATMGCSTATE       pPATMGCState   = PATMGetGCState(pVM);
     108
     109    Assert(pVM->csam.s.cDirtyPages < CSAM_MAX_DIRTY_PAGES);
     110    Assert(pPATMGCState);
     111    Assert(pPATMGCState->fPIF || fPatchCode);
     112
     113# ifdef VBOX_WITH_REM
     114    /* Flush the recompilers translation block cache as the guest seems to be modifying instructions. */
     115    /** @todo a bit overkill?? */
     116    REMFlushTBs(pVM);
     117# endif
     118
     119    /*
     120     * When patch code is executing instructions that must complete, then we
     121     * must *never* interrupt it.
     122     */
     123    if (!pPATMGCState->fPIF && fPatchCode)
     124    {
     125        Log(("csamRCCodePageWriteHandler: fPIF=0 -> stack fault in patch generated code at %08RX32!\n", CPUMGetGuestRIP(pVCpu)));
     126        return VINF_PGM_HANDLER_DO_DEFAULT;
     127    }
     128
     129    Log(("csamRCCodePageWriteHandler: code page write at %RGv original address %RGv (cpl=%d)\n", GCPtr, GCPtrMonitored, cpl));
     130
     131    /*
     132     * If user code is modifying one of our monitored pages, then we can safely
     133     * write to it as it's no longer being used for supervisor code.
     134     */
     135    if (cpl != 3)
     136    {
     137        VBOXSTRICTRC rcStrict = PATMRCHandleWriteToPatchPage(pVM, NULL /* pRegFrame = no interpret */,
     138                                                             (RTRCPTR)GCPtrMonitored, cbBuf);
     139        if (   rcStrict == VINF_PGM_HANDLER_DO_DEFAULT
     140            || rcStrict == VINF_SUCCESS)
     141            return VBOXSTRICTRC_TODO(rcStrict);
     142        if (rcStrict == VINF_EM_RAW_EMULATE_INSTR)
     143        {
     144            STAM_COUNTER_INC(&pVM->csam.s.StatDangerousWrite);
     145            return VINF_EM_RAW_EMULATE_INSTR;
     146        }
     147        Assert(rcStrict == VERR_PATCH_NOT_FOUND);
     148    }
     149
     150    /*
     151     * Schedule ring-3 activity.
     152     * Note that GCPtr might be a different address in case of aliases.  So,
     153     * take down both alternatives.
     154     */
     155    VMCPU_FF_SET(pVCpu, VMCPU_FF_CSAM_PENDING_ACTION);
     156    pVM->csam.s.pvDirtyBasePage[pVM->csam.s.cDirtyPages]  = (RTRCPTR)GCPtrMonitored;
     157    pVM->csam.s.pvDirtyFaultPage[pVM->csam.s.cDirtyPages] = (RTRCPTR)GCPtr;
     158    if (++pVM->csam.s.cDirtyPages == CSAM_MAX_DIRTY_PAGES)
     159        return VINF_CSAM_PENDING_ACTION;
     160
     161    /*
     162     * Continue with the write. The VM_FF_CSAM_FLUSH_DIRTY_PAGE handler will reset it to readonly again.
     163     */
     164    Log(("csamRCCodePageWriteHandler: enabled r/w for page %RGv (%RGv)\n", GCPtr, GCPtrMonitored));
     165    STAM_COUNTER_INC(&pVM->csam.s.StatCodePageModified);
     166    return VINF_PGM_HANDLER_DO_DEFAULT;
     167#endif
     168}
     169
     170
    47171/**
    48172 * Check if this page needs to be analysed by CSAM
  • trunk/src/VBox/VMM/VMMAll/PATMAll.cpp

    r55001 r55937  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3737#include <iprt/assert.h>
    3838#include <iprt/string.h>
     39
     40
     41/**
     42 * Access handler callback for virtual access handler ranges.
     43 *
     44 * Important to realize that a physical page in a range can have aliases, and
     45 * for ALL and WRITE handlers these will also trigger.
     46 *
     47 * @returns VINF_SUCCESS if the handler have carried out the operation.
     48 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
     49 * @param   pVM             Pointer to the VM.
     50 * @param   pVCpu           Pointer to the cross context CPU context for the
     51 *                          calling EMT.
     52 * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
     53 * @param   pvPtr           The HC mapping of that address.
     54 * @param   pvBuf           What the guest is reading/writing.
     55 * @param   cbBuf           How much it's reading/writing.
     56 * @param   enmAccessType   The access type.
     57 * @param   enmOrigin       Who is making this write.
     58 * @param   pvUser          The address of the guest page we're monitoring.
     59 */
     60PGM_ALL_CB2_DECL(int) patmVirtPageHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
     61                                          PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
     62{
     63    Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
     64    NOREF(pvPtr); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(pvUser);
     65    Assert(pvUser); Assert(!((uintptr_t)pvUser & PAGE_OFFSET_MASK));
     66
     67    pVM->patm.s.pvFaultMonitor = (RTRCPTR)((uintptr_t)pvUser + (GCPtr & PAGE_OFFSET_MASK));
     68#ifdef IN_RING3
     69    PATMR3HandleMonitoredPage(pVM);
     70    return VINF_PGM_HANDLER_DO_DEFAULT;
     71#else
     72    /* RC: Go handle this in ring-3. */
     73    return VINF_PATM_CHECK_PATCH_PAGE;
     74#endif
     75}
    3976
    4077
  • trunk/src/VBox/VMM/VMMR3/CSAM.cpp

    r55900 r55937  
    7272static DECLCALLBACK(int) csamR3Save(PVM pVM, PSSMHANDLE pSSM);
    7373static DECLCALLBACK(int) csamR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
    74 static FNPGMR3VIRTHANDLER    csamR3CodePageWriteHandler;
    7574static FNPGMR3VIRTINVALIDATE csamR3CodePageInvalidate;
    7675
     
    255254    rc = PGMR3HandlerVirtualTypeRegister(pVM, PGMVIRTHANDLERKIND_WRITE, false /*fRelocUserRC*/,
    256255                                         NULL /*pfnInvalidateR3 */,
    257                                          csamR3CodePageWriteHandler,
     256                                         csamCodePageWriteHandler,
    258257                                         "csamRCCodePageWritePfHandler",
    259258                                         "CSAM code page write handler",
     
    262261    rc = PGMR3HandlerVirtualTypeRegister(pVM, PGMVIRTHANDLERKIND_WRITE, false /*fRelocUserRC*/,
    263262                                         csamR3CodePageInvalidate,
    264                                          csamR3CodePageWriteHandler,
     263                                         csamCodePageWriteHandler,
    265264                                         "csamRCCodePageWritePfHandler",
    266265                                         "CSAM code page write and invlpg handler",
     
    21642163
    21652164/**
    2166  * \#PF Handler callback for virtual access handler ranges.
    2167  *
    2168  * Important to realize that a physical page in a range can have aliases, and
    2169  * for ALL and WRITE handlers these will also trigger.
    2170  *
    2171  * @returns VINF_SUCCESS if the handler have carried out the operation.
    2172  * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
    2173  * @param   pVM             Pointer to the VM.
    2174  * @param   pVCpu       Pointer to the cross context CPU context for the
    2175  *                      calling EMT.
    2176  * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
    2177  * @param   pvPtr           The HC mapping of that address.
    2178  * @param   pvBuf           What the guest is reading/writing.
    2179  * @param   cbBuf           How much it's reading/writing.
    2180  * @param   enmAccessType   The access type.
    2181  * @param   enmOrigin       Who is making this write.
    2182  * @param   pvUser          User argument.
    2183  */
    2184 static DECLCALLBACK(int) csamR3CodePageWriteHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
    2185                                                     PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
    2186 {
    2187     int rc;
    2188 
    2189     Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
    2190     Log(("csamR3CodePageWriteHandler: write to %RGv size=%zu\n", GCPtr, cbBuf));
    2191     NOREF(pvUser);
    2192 
    2193     if (    PAGE_ADDRESS(pvPtr) == PAGE_ADDRESS((uintptr_t)pvPtr + cbBuf - 1)
    2194          && !memcmp(pvPtr, pvBuf, cbBuf))
    2195     {
    2196         Log(("csamR3CodePageWriteHandler: dummy write -> ignore\n"));
    2197         return VINF_PGM_HANDLER_DO_DEFAULT;
    2198     }
    2199 
    2200     if (VM_IS_EMT(pVM))
    2201         rc = PATMR3PatchWrite(pVM, GCPtr, (uint32_t)cbBuf);
    2202     else
    2203     {
    2204         AssertFailed(); /* PGM should make sure this does not happen anymore! */
    2205         /* Queue the write instead otherwise we'll get concurrency issues. */
    2206         /** @note in theory not correct to let it write the data first before disabling a patch!
    2207          *        (if it writes the same data as the patch jump and we replace it with obsolete opcodes)
    2208          */
    2209         Log(("csamR3CodePageWriteHandler: delayed write!\n"));
    2210         AssertCompileSize(RTRCPTR, 4);
    2211         rc = VMR3ReqCallVoidNoWait(pVM, VMCPUID_ANY, (PFNRT)CSAMDelayedWriteHandler, 3, pVM, (RTRCPTR)GCPtr, cbBuf);
    2212     }
    2213     AssertRC(rc);
    2214 
    2215     return VINF_PGM_HANDLER_DO_DEFAULT;
    2216 }
    2217 
    2218 /**
    22192165 * \#PF Handler callback for invalidation of virtual access handler ranges.
    22202166 *
     
    24352381    STAM_PROFILE_START(&pVM->csam.s.StatFlushDirtyPages, a);
    24362382
    2437     for (uint32_t i=0;i<pVM->csam.s.cDirtyPages;i++)
     2383    for (uint32_t i = 0; i < pVM->csam.s.cDirtyPages; i++)
    24382384    {
    24392385        int          rc;
    24402386        PCSAMPAGEREC pPageRec;
    2441         RTRCPTR      GCPtr = pVM->csam.s.pvDirtyBasePage[i];
    2442 
    2443         GCPtr = GCPtr & PAGE_BASE_GC_MASK;
     2387        RTRCPTR      GCPtr = pVM->csam.s.pvDirtyBasePage[i] & PAGE_BASE_GC_MASK;
    24442388
    24452389#ifdef VBOX_WITH_REM
    24462390         /* Notify the recompiler that this page has been changed. */
    24472391        REMR3NotifyCodePageChanged(pVM, pVCpu, GCPtr);
     2392        if (pVM->csam.s.pvDirtyFaultPage[i] != pVM->csam.s.pvDirtyBasePage[i])
     2393            REMR3NotifyCodePageChanged(pVM, pVCpu, pVM->csam.s.pvDirtyFaultPage[i] & PAGE_BASE_GC_MASK);
    24482394#endif
    24492395
  • trunk/src/VBox/VMM/VMMR3/PATM.cpp

    r55900 r55937  
    9292*   Internal Functions                                                         *
    9393*******************************************************************************/
    94 static FNPGMR3VIRTHANDLER patmR3VirtPageHandler;
    95 
    9694static int          patmDisableUnusablePatch(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictAddr, PPATCHINFO pPatch);
    9795static int          patmActivateInt3Patch(PVM pVM, PPATCHINFO pPatch);
     
    224222    rc = PGMR3HandlerVirtualTypeRegister(pVM, PGMVIRTHANDLERKIND_ALL, false /*fRelocUserRC*/,
    225223                                         NULL /*pfnInvalidateR3*/,
    226                                          patmR3VirtPageHandler,
     224                                         patmVirtPageHandler,
    227225                                         "patmRCVirtPagePfHandler",
    228226                                         "PATMMonitorPatchJump", &pVM->patm.s.hMonitorPageType);
     
    975973}
    976974
    977 /**
    978  * \#PF Handler callback for virtual access handler ranges.
    979  *
    980  * Important to realize that a physical page in a range can have aliases, and
    981  * for ALL and WRITE handlers these will also trigger.
    982  *
    983  * @returns VINF_SUCCESS if the handler have carried out the operation.
    984  * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
    985  * @param   pVM             Pointer to the VM.
    986  * @param   pVCpu           Pointer to the cross context CPU context for the
    987  *                          calling EMT.
    988  * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
    989  * @param   pvPtr           The HC mapping of that address.
    990  * @param   pvBuf           What the guest is reading/writing.
    991  * @param   cbBuf           How much it's reading/writing.
    992  * @param   enmAccessType   The access type.
    993  * @param   enmOrigin       Who is making this write.
    994  * @param   pvUser          The address of the guest page we're monitoring.
    995  */
    996 static DECLCALLBACK(int) patmR3VirtPageHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
    997                                                PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
    998 {
    999     Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
    1000     NOREF(pVCpu); NOREF(pvPtr); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(pvUser);
    1001 
    1002     /** @todo could be the wrong virtual address (alias) */
    1003     pVM->patm.s.pvFaultMonitor = GCPtr;
    1004     PATMR3HandleMonitoredPage(pVM);
    1005     return VINF_PGM_HANDLER_DO_DEFAULT;
    1006 }
    1007 
    1008975#ifdef VBOX_WITH_DEBUGGER
    1009976
  • trunk/src/VBox/VMM/VMMRC/CSAMRC.cpp

    r55900 r55937  
    7272    PPATMGCSTATE pPATMGCState;
    7373    bool         fPatchCode = PATMIsPatchGCAddr(pVM, pRegFrame->eip);
    74     int          rc;
    7574    NOREF(uErrorCode);
    7675
     
    9695         * Make this particular page R/W.
    9796         */
    98         rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
     97        int rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
    9998        AssertMsgRC(rc, ("PGMShwModifyPage -> rc=%Rrc\n", rc));
    10099        ASMInvalidatePage((void *)(uintptr_t)pvFault);
     
    114113    if (cpl != 3)
    115114    {
    116         rc = PATMRCHandleWriteToPatchPage(pVM, pRegFrame, (RTRCPTR)((RTRCUINTPTR)pvRange + offRange), 4 /** @todo */);
    117         if (rc == VINF_SUCCESS)
    118             return rc;
    119         if (rc == VINF_EM_RAW_EMULATE_INSTR)
     115        VBOXSTRICTRC rcStrict = PATMRCHandleWriteToPatchPage(pVM, pRegFrame, (RTRCPTR)((RTRCUINTPTR)pvRange + offRange),
     116                                                             4 /** @todo */);
     117        if (rcStrict == VINF_SUCCESS)
     118            return rcStrict;
     119        if (rcStrict == VINF_EM_RAW_EMULATE_INSTR)
    120120        {
    121121            STAM_COUNTER_INC(&pVM->csam.s.StatDangerousWrite);
    122122            return VINF_EM_RAW_EMULATE_INSTR;
    123123        }
    124         Assert(rc == VERR_PATCH_NOT_FOUND);
     124        Assert(rcStrict == VERR_PATCH_NOT_FOUND);
    125125    }
    126126
     
    129129    /* Note that pvFault might be a different address in case of aliases. So use pvRange + offset instead!. */
    130130    pVM->csam.s.pvDirtyBasePage[pVM->csam.s.cDirtyPages] = (RTRCPTR)((RTRCUINTPTR)pvRange + offRange);
    131     pVM->csam.s.pvDirtyFaultPage[pVM->csam.s.cDirtyPages] = (RTRCPTR)((RTRCUINTPTR)pvRange + offRange);
     131    pVM->csam.s.pvDirtyFaultPage[pVM->csam.s.cDirtyPages] = (RTRCPTR)pvFault;
    132132    if (++pVM->csam.s.cDirtyPages == CSAM_MAX_DIRTY_PAGES)
    133133        return VINF_CSAM_PENDING_ACTION;
     
    137137     */
    138138    Log(("csamRCCodePageWriteHandler: enabled r/w for page %RGv\n", pvFault));
    139     rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
     139    int rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
    140140    AssertMsgRC(rc, ("PGMShwModifyPage -> rc=%Rrc\n", rc));
    141141    ASMInvalidatePage((void *)(uintptr_t)pvFault);
  • trunk/src/VBox/VMM/VMMRC/PATMRC.cpp

    r55900 r55937  
    6363                                        RTGCPTR pvRange, uintptr_t offRange, void *pvUser)
    6464{
    65     NOREF(pVCpu); NOREF(uErrorCode); NOREF(pRegFrame); NOREF(pvFault); NOREF(pvRange); NOREF(offRange); NOREF(pvUser);
    66     pVM->patm.s.pvFaultMonitor = (RTRCPTR)(RTRCUINTPTR)pvFault;
     65    NOREF(pVCpu); NOREF(uErrorCode); NOREF(pRegFrame); NOREF(pvFault); NOREF(pvRange); NOREF(offRange);
     66    Assert(pvUser); Assert(!((uintptr_t)pvUser & PAGE_OFFSET_MASK));
     67    pVM->patm.s.pvFaultMonitor = (RTRCPTR)((uintptr_t)pvUser + (pvFault & PAGE_OFFSET_MASK));
    6768    return VINF_PATM_CHECK_PATCH_PAGE;
    6869}
     
    7374 * (if so, then we are not allowed to turn on r/w)
    7475 *
    75  * @returns VBox status
     76 * @returns Strict VBox status code.
     77 * @retval  VINF_SUCCESS if access interpreted (@a pRegFrame != NULL).
     78 * @retval  VINF_PGM_HANDLER_DO_DEFAULT (@a pRegFrame == NULL).
     79 * @retval  VINF_EM_RAW_EMULATE_INSTR on needing to go to ring-3 to do this.
     80 * @retval  VERR_PATCH_NOT_FOUND if no patch was found.
     81 *
    7682 * @param   pVM         Pointer to the VM.
    77  * @param   pRegFrame   CPU context
    78  * @param   GCPtr       GC pointer to write address
    79  * @param   cbWrite     Nr of bytes to write
     83 * @param   pRegFrame   CPU context if \#PF, NULL if other write..
     84 * @param   GCPtr       GC pointer to write address.
     85 * @param   cbWrite     Number of bytes to write.
    8086 *
    8187 */
    82 VMMRC_INT_DECL(int) PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite)
     88VMMRC_INT_DECL(VBOXSTRICTRC) PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite)
    8389{
    84     RTGCUINTPTR          pWritePageStart, pWritePageEnd;
    85     PPATMPATCHPAGE       pPatchPage;
     90    Assert(cbWrite > 0);
    8691
    8792    /* Quick boundary check */
    88     if (    PAGE_ADDRESS(GCPtr) < PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCLowest)
    89         ||  PAGE_ADDRESS(GCPtr) > PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCHighest)
    90        )
    91        return VERR_PATCH_NOT_FOUND;
     93    if (   PAGE_ADDRESS(GCPtr) < PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCLowest)
     94        || PAGE_ADDRESS(GCPtr) > PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCHighest))
     95        return VERR_PATCH_NOT_FOUND;
    9296
    9397    STAM_PROFILE_ADV_START(&pVM->patm.s.StatPatchWriteDetect, a);
    9498
    95     pWritePageStart = (RTRCUINTPTR)GCPtr & PAGE_BASE_GC_MASK;
    96     pWritePageEnd   = ((RTRCUINTPTR)GCPtr + cbWrite - 1) & PAGE_BASE_GC_MASK;
    97 
    98     pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(CTXSUFF(&pVM->patm.s.PatchLookupTree)->PatchTreeByPage, (AVLOU32KEY)pWritePageStart);
     99    /*
     100     * Lookup the patch page record for the write.
     101     */
     102    RTRCUINTPTR pWritePageStart = (RTRCUINTPTR)GCPtr & PAGE_BASE_GC_MASK;
     103    RTRCUINTPTR pWritePageEnd   = ((RTRCUINTPTR)GCPtr + cbWrite - 1) & PAGE_BASE_GC_MASK;
     104
     105    PPATMPATCHPAGE pPatchPage;
     106    pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(&pVM->patm.s.CTXSUFF(PatchLookupTree)->PatchTreeByPage, pWritePageStart);
    99107    if (    !pPatchPage
    100         &&  pWritePageStart != pWritePageEnd
    101        )
    102     {
    103         pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(CTXSUFF(&pVM->patm.s.PatchLookupTree)->PatchTreeByPage, (AVLOU32KEY)pWritePageEnd);
    104     }
    105 
    106 #ifdef LOG_ENABLED
    107     if (pPatchPage)
    108         Log(("PATMGCHandleWriteToPatchPage: Found page %RRv for write to %RRv %d bytes (page low:high %RRv:%RRv\n", pPatchPage->Core.Key, GCPtr, cbWrite, pPatchPage->pLowestAddrGC, pPatchPage->pHighestAddrGC));
    109 #endif
    110 
     108        &&  pWritePageStart != pWritePageEnd)
     109        pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(&pVM->patm.s.CTXSUFF(PatchLookupTree)->PatchTreeByPage, pWritePageEnd);
    111110    if (pPatchPage)
    112111    {
    113         if (    pPatchPage->pLowestAddrGC  > (RTRCPTR)((RTRCUINTPTR)GCPtr + cbWrite - 1)
    114             ||  pPatchPage->pHighestAddrGC < (RTRCPTR)GCPtr)
     112        Log(("PATMGCHandleWriteToPatchPage: Found page %RRv for write to %RRv %d bytes (page low:high %RRv:%RRv\n",
     113             pPatchPage->Core.Key, GCPtr, cbWrite, pPatchPage->pLowestAddrGC, pPatchPage->pHighestAddrGC));
     114        if (   (RTRCUINTPTR)pPatchPage->pLowestAddrGC  > (RTRCUINTPTR)GCPtr + cbWrite - 1U
     115            || (RTRCUINTPTR)pPatchPage->pHighestAddrGC < (RTRCUINTPTR)GCPtr)
    115116        {
    116             /* This part of the page was not patched; try to emulate the instruction. */
     117            /* This part of the page was not patched; try to emulate the instruction / tell the caller to do so. */
     118            if (!pRegFrame)
     119            {
     120                LogFlow(("PATMHandleWriteToPatchPage: Allow writing %RRv LB %#x\n", pRegFrame->eip, GCPtr, cbWrite));
     121                STAM_COUNTER_INC(&pVM->patm.s.StatPatchWriteInterpreted);
     122                STAM_PROFILE_ADV_STOP(&pVM->patm.s.StatPatchWriteDetect, a);
     123                return VINF_PGM_HANDLER_DO_DEFAULT;
     124            }
    117125            LogFlow(("PATMHandleWriteToPatchPage: Interpret %x accessing %RRv\n", pRegFrame->eip, GCPtr));
    118126            int rc = EMInterpretInstruction(VMMGetCpu0(pVM), pRegFrame, (RTGCPTR)(RTRCUINTPTR)GCPtr);
  • trunk/src/VBox/VMM/include/CSAMInternal.h

    r55895 r55937  
    283283
    284284RT_C_DECLS_BEGIN
    285 DECLEXPORT(FNPGMRCVIRTPFHANDLER) csamRCCodePageWritePfHandler;
     285DECLEXPORT(FNPGMRCVIRTPFHANDLER)    csamRCCodePageWritePfHandler;
    286286RT_C_DECLS_END
    287 
    288 #endif
     287PGM_ALL_CB2_DECL(FNPGMR3VIRTHANDLER)  csamCodePageWriteHandler;
     288
     289#endif
  • trunk/src/VBox/VMM/include/PATMInternal.h

    r55895 r55937  
    687687void patmR3DbgAddPatch(PVM pVM, PPATMPATCHREC pPatchRec);
    688688
    689 #endif
     689PGM_ALL_CB2_DECL(FNPGMPHYSHANDLER) patmVirtPageHandler;
     690
     691#endif
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