VirtualBox

Changeset 87371 in vbox


Ignore:
Timestamp:
Jan 22, 2021 2:42:17 PM (4 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Handle the case where an access might result in non-contiguous physical addresses after address translation via the IOMMU.

Location:
trunk
Files:
7 edited

Legend:

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

    r87127 r87371  
    12831283     *
    12841284     * @returns VBox status code.
    1285      * @param   pDevIns     The IOMMU device instance.
    1286      * @param   uDevId      The device identifier (bus, device, function).
    1287      * @param   uIova       The I/O virtual address being accessed.
    1288      * @param   cbAccess    The number of bytes being accessed.
    1289      * @param   fFlags      Access flags, see PDMIOMMU_MEM_F_XXX.
    1290      * @param   pGCPhysSpa  Where to store the translated system physical address.
     1285     * @param   pDevIns         The IOMMU device instance.
     1286     * @param   uDevId          The device identifier (bus, device, function).
     1287     * @param   uIova           The I/O virtual address being accessed.
     1288     * @param   cbAccess        The number of bytes being accessed.
     1289     * @param   fFlags          Access flags, see PDMIOMMU_MEM_F_XXX.
     1290     * @param   pGCPhysSpa      Where to store the translated system physical address.
     1291     * @param   pcbContiguous   Where to store the number of contiguous bytes translated
     1292     *                          and permission-checked.
    12911293     *
    12921294     * @thread  Any.
    12931295     */
    12941296    DECLR0CALLBACKMEMBER(int, pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess,
    1295                                             uint32_t fFlags, PRTGCPHYS pGCPhysSpa));
     1297                                            uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous));
    12961298
    12971299    /**
     
    13331335
    13341336/** Current PDMIOMMUREG version number. */
    1335 #define PDM_IOMMUREGR0_VERSION                      PDM_VERSION_MAKE(0xff10, 2, 0)
     1337#define PDM_IOMMUREGR0_VERSION                      PDM_VERSION_MAKE(0xff10, 3, 0)
    13361338
    13371339
     
    13511353     *
    13521354     * @returns VBox status code.
    1353      * @param   pDevIns     The IOMMU device instance.
    1354      * @param   uDevId      The device identifier (bus, device, function).
    1355      * @param   uIova       The I/O virtual address being accessed.
    1356      * @param   cbAccess    The number of bytes being accessed.
    1357      * @param   fFlags      Access flags, see PDMIOMMU_MEM_F_XXX.
    1358      * @param   pGCPhysSpa  Where to store the translated system physical address.
     1355     * @param   pDevIns         The IOMMU device instance.
     1356     * @param   uDevId          The device identifier (bus, device, function).
     1357     * @param   uIova           The I/O virtual address being accessed.
     1358     * @param   cbAccess        The number of bytes being accessed.
     1359     * @param   fFlags          Access flags, see PDMIOMMU_MEM_F_XXX.
     1360     * @param   pGCPhysSpa      Where to store the translated system physical address.
     1361     * @param   pcbContiguous   Where to store the number of contiguous bytes translated
     1362     *                          and permission-checked.
    13591363     *
    13601364     * @thread  Any.
    13611365     */
    13621366    DECLRCCALLBACKMEMBER(int, pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess,
    1363                                             uint32_t fFlags, PRTGCPHYS pGCPhysSpa));
     1367                                            uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous));
    13641368
    13651369    /**
     
    14011405
    14021406/** Current PDMIOMMUREG version number. */
    1403 #define PDM_IOMMUREGRC_VERSION                      PDM_VERSION_MAKE(0xff11, 2, 0)
     1407#define PDM_IOMMUREGRC_VERSION                      PDM_VERSION_MAKE(0xff11, 3, 0)
    14041408
    14051409
     
    14191423     *
    14201424     * @returns VBox status code.
    1421      * @param   pDevIns     The IOMMU device instance.
    1422      * @param   uDevId      The device identifier (bus, device, function).
    1423      * @param   uIova       The I/O virtual address being accessed.
    1424      * @param   cbAccess    The number of bytes being accessed.
    1425      * @param   fFlags      Access flags, see PDMIOMMU_MEM_F_XXX.
    1426      * @param   pGCPhysSpa  Where to store the translated system physical address.
     1425     * @param   pDevIns         The IOMMU device instance.
     1426     * @param   uDevId          The device identifier (bus, device, function).
     1427     * @param   uIova           The I/O virtual address being accessed.
     1428     * @param   cbAccess        The number of bytes being accessed.
     1429     * @param   fFlags          Access flags, see PDMIOMMU_MEM_F_XXX.
     1430     * @param   pGCPhysSpa      Where to store the translated system physical address.
     1431     * @param   pcbContiguous   Where to store the number of contiguous bytes translated
     1432     *                          and permission-checked.
    14271433     *
    14281434     * @thread  Any.
    14291435     */
    14301436    DECLR3CALLBACKMEMBER(int, pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess,
    1431                                             uint32_t fFlags, PRTGCPHYS pGCPhysSpa));
     1437                                            uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous));
    14321438
    14331439    /**
     
    14691475
    14701476/** Current PDMIOMMUREG version number. */
    1471 #define PDM_IOMMUREGR3_VERSION                      PDM_VERSION_MAKE(0xff12, 2, 0)
     1477#define PDM_IOMMUREGR3_VERSION                      PDM_VERSION_MAKE(0xff12, 3, 0)
    14721478
    14731479/** IOMMU registration structure for the current context. */
  • trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp

    r87343 r87371  
    28822882 *
    28832883 * @returns VBox status code.
    2884  * @param   pDevIns     The IOMMU instance data.
    2885  * @param   uDevId      The device ID.
    2886  * @param   uIova       The I/O virtual address to lookup.
    2887  * @param   cbAccess    The size of the access.
    2888  * @param   fAccess     The access permissions (IOMMU_IO_PERM_XXX). This is the
    2889  *                      permissions for the access being made.
    2890  * @param   enmOp       The IOMMU operation being performed.
    2891  * @param   pGCPhysSpa  Where to store the translated system physical address. Only
    2892  *                      valid when translation succeeds and VINF_SUCCESS is
    2893  *                      returned!
     2884 * @param   pDevIns         The IOMMU instance data.
     2885 * @param   uDevId          The device ID.
     2886 * @param   uIova           The I/O virtual address to lookup.
     2887 * @param   cbAccess        The size of the access.
     2888 * @param   fAccess         The access permissions (IOMMU_IO_PERM_XXX). This is the
     2889 *                          permissions for the access being made.
     2890 * @param   enmOp           The IOMMU operation being performed.
     2891 * @param   pGCPhysSpa      Where to store the translated system physical address. Only
     2892 *                          valid when VINF_SUCCESS is returned!
     2893 * @param   pcbContiguous   Where to store the number of contiguous bytes translated
     2894 *                          and permission-checked. Only valid when VINF_SUCCESS is
     2895 *                          returned!
    28942896 *
    28952897 * @thread  Any.
    28962898 */
    28972899static int iommuAmdLookupDeviceTable(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint8_t fAccess,
    2898                                      IOMMUOP enmOp, PRTGCPHYS pGCPhysSpa)
     2900                                     IOMMUOP enmOp, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
    28992901{
    29002902    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     
    29122914        {
    29132915            /** @todo IOMMU: Add to IOLTB cache. */
    2914             *pGCPhysSpa = uIova;
     2916            *pGCPhysSpa    = uIova;
     2917            *pcbContiguous = cbAccess;
    29152918            STAM_PROFILE_ADV_STOP(&pThis->StatDteLookup, a);
    29162919            return VINF_SUCCESS;
     
    29402943        {
    29412944            /** @todo IOMMU: Add to IOLTB cache. */
    2942             *pGCPhysSpa = uIova;
     2945            *pGCPhysSpa    = uIova;
     2946            *pcbContiguous = cbAccess;
    29432947            STAM_PROFILE_ADV_STOP(&pThis->StatDteLookup, a);
    29442948            return VINF_SUCCESS;
    29452949        }
    29462950
    2947         /** @todo IOMMU: Perhaps do the <= 4K access case first, if the generic loop
    2948          *        below gets too expensive and when we have iommuAmdWalkIoPageDirectory. */
    2949 
    2950         uint64_t uBaseIova   = uIova & X86_PAGE_4K_BASE_MASK;
     2951        RTGCPHYS GCPhysSpa   = NIL_RTGCPHYS;
     2952        size_t   cbRemaining = cbAccess;
     2953        uint64_t uIovaPage   = uIova & X86_PAGE_4K_BASE_MASK;
    29512954        uint64_t offIova     = uIova & X86_PAGE_4K_OFFSET_MASK;
    2952         uint64_t cbRemaining = cbAccess;
     2955        uint64_t cbPages     = 0;
    29532956        for (;;)
    29542957        {
    29552958            /* Walk the I/O page tables to translate the IOVA and check permission for the access. */
    29562959            IOWALKRESULT WalkResult;
    2957             rc = iommuAmdWalkIoPageTable(pDevIns, uDevId, uBaseIova, fAccess, &Dte, enmOp, &WalkResult);
     2960            RT_ZERO(WalkResult);
     2961            rc = iommuAmdWalkIoPageTable(pDevIns, uDevId, uIovaPage, fAccess, &Dte, enmOp, &WalkResult);
    29582962            if (RT_SUCCESS(rc))
    29592963            {
    2960                 /** @todo IOMMU: Split large pages into 4K IOTLB entries and add to IOTLB cache. */
    2961 
    29622964                /* If translation is disabled for this device (root paging mode is 0), we're done. */
    29632965                if (WalkResult.cShift == 0)
    29642966                {
    2965                     *pGCPhysSpa = uIova;
     2967                    GCPhysSpa   = uIova;
     2968                    cbRemaining = 0;
    29662969                    break;
    29672970                }
    29682971
    2969                 /* Store the translated base address before continuing to check permissions for any more pages. */
     2972                /* Store the translated address before continuing to access more pages. */
    29702973                Assert(WalkResult.cShift >= X86_PAGE_4K_SHIFT);
    29712974                if (cbRemaining == cbAccess)
     
    29732976                    uint64_t const offMask = ~(UINT64_C(0xffffffffffffffff) << WalkResult.cShift);
    29742977                    uint64_t const offSpa  = uIova & offMask;
    2975                     *pGCPhysSpa = WalkResult.GCPhysSpa | offSpa;
     2978                    GCPhysSpa = WalkResult.GCPhysSpa | offSpa;
    29762979                }
    2977 
    2978                 /* If the access exceeds the page size, check permissions for the subsequent page. */
    2979                 uint64_t const cbPhysPage = UINT64_C(1) << WalkResult.cShift;
    2980                 if (cbRemaining > cbPhysPage - offIova)
     2980                /* Check if addresses translated so far are physically contiguous. */
     2981                else if ((GCPhysSpa & X86_PAGE_4K_BASE_MASK) + cbPages == WalkResult.GCPhysSpa)
     2982                { /* likely */ }
     2983                else
     2984                    break;
     2985
     2986                /* Check if we need to access more pages. */
     2987                uint64_t const cbSpa = UINT64_C(1) << WalkResult.cShift;
     2988                if (cbRemaining > cbSpa - offIova)
    29812989                {
    2982                     cbRemaining -= (cbPhysPage - offIova);
    2983                     uBaseIova   += cbPhysPage;      /** @todo r=ramshankar: Should we mask the offset based on page size here? */
    2984                     offIova      = 0;
     2990                    cbRemaining -= (cbSpa - offIova);   /* Calculate how much more we need to access. */
     2991                    cbPages     += cbSpa;               /* Update size of all pages read thus far. */
     2992                    uIovaPage   += cbSpa;               /* Update address of the next access. */
     2993                    offIova      = 0;                   /* After the first page, all pages are accessed from offset 0. */
    29852994                }
    29862995                else
     2996                {
     2997                    cbRemaining = 0;
    29872998                    break;
     2999                }
    29883000            }
    29893001            else
    29903002            {
    2991                 LogFunc(("I/O page table walk failed. uIova=%#RX64 uBaseIova=%#RX64 fAccess=%u rc=%Rrc\n", uIova,
    2992                      uBaseIova, fAccess, rc));
    2993                 *pGCPhysSpa = NIL_RTGCPHYS;
    2994                 STAM_PROFILE_ADV_STOP(&pThis->StatDteLookup, a);
    2995                 return rc;
     3003                GCPhysSpa   = NIL_RTGCPHYS;
     3004                cbRemaining = 0;
     3005                break;
    29963006            }
    29973007        }
    29983008
     3009        *pGCPhysSpa    = GCPhysSpa;
     3010        *pcbContiguous = cbAccess - cbRemaining;
     3011        AssertMsg(*pcbContiguous > 0 && *pcbContiguous <= cbAccess, ("cbAccess=%zu pcbContig=%zu\n", cbAccess, *pcbContiguous));
    29993012        STAM_PROFILE_ADV_STOP(&pThis->StatDteLookup, a);
    30003013        return rc;
    30013014    }
    30023015
     3016    *pGCPhysSpa    = NIL_RTGCPHYS;
     3017    *pcbContiguous = 0;
    30033018    LogFunc(("Failed to read device table entry. uDevId=%#x rc=%Rrc\n", uDevId, rc));
    30043019    STAM_PROFILE_ADV_STOP(&pThis->StatDteLookup, a);
     
    30113026 *
    30123027 * @returns VBox status code.
    3013  * @param   pDevIns     The IOMMU device instance.
    3014  * @param   uDevId      The device ID (bus, device, function).
    3015  * @param   uIova       The I/O virtual address being accessed.
    3016  * @param   cbAccess    The number of bytes being accessed.
    3017  * @param   fFlags      The access flags, see PDMIOMMU_MEM_F_XXX.
    3018  * @param   pGCPhysSpa  Where to store the translated system physical address.
    3019  *
     3028 * @param   pDevIns         The IOMMU device instance.
     3029 * @param   uDevId          The device ID (bus, device, function).
     3030 * @param   uIova           The I/O virtual address being accessed.
     3031 * @param   cbAccess        The number of bytes being accessed.
     3032 * @param   fFlags          The access flags, see PDMIOMMU_MEM_F_XXX.
     3033 * @param   pGCPhysSpa      Where to store the translated system physical address. Only
     3034 *                          valid when VINF_SUCCESS is returned!
     3035 * @param   pcbContiguous   Where to store the number of contiguous bytes translated
     3036 *                          and permission-checked. Only valid when VINF_SUCCESS is
     3037 *                          returned!
    30203038 * @thread  Any.
    30213039 */
    30223040static DECLCALLBACK(int) iommuAmdDeviceMemAccess(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess,
    3023                                                  uint32_t fFlags, PRTGCPHYS pGCPhysSpa)
     3041                                                 uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
    30243042{
    30253043    /* Validate. */
     
    30293047    Assert(!(fFlags & ~PDMIOMMU_MEM_F_VALID_MASK));
    30303048
    3031     PIOMMU  pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     3049    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
    30323050    IOMMU_CTRL_T const Ctrl = iommuAmdGetCtrl(pThis);
    30333051    if (Ctrl.n.u1IommuEn)
     
    30593077
    30603078        /* Lookup the IOVA from the device table. */
    3061         int rc = iommuAmdLookupDeviceTable(pDevIns, uDevId, uIova, cbAccess, fAccess, enmOp, pGCPhysSpa);
     3079        int rc = iommuAmdLookupDeviceTable(pDevIns, uDevId, uIova, cbAccess, fAccess, enmOp, pGCPhysSpa, pcbContiguous);
    30623080        if (RT_SUCCESS(rc))
    30633081        { /* likely */ }
     
    30693087
    30703088    /* Addresses are forwarded without translation when the IOMMU is disabled. */
    3071     *pGCPhysSpa = uIova;
     3089    *pGCPhysSpa    = uIova;
     3090    *pcbContiguous = cbAccess;
    30723091    return VINF_SUCCESS;
    30733092}
     
    31293148        for (size_t i = 0; i < cIovas; i++)
    31303149        {
    3131             int rc = iommuAmdLookupDeviceTable(pDevIns, uDevId, pauIovas[i], X86_PAGE_SIZE, fAccess, enmOp, &paGCPhysSpa[i]);
     3150            size_t cbContig;
     3151            int rc = iommuAmdLookupDeviceTable(pDevIns, uDevId, pauIovas[i], X86_PAGE_SIZE, fAccess, enmOp, &paGCPhysSpa[i],
     3152                                               &cbContig);
    31323153            if (RT_SUCCESS(rc))
    31333154            { /* likely */ }
     
    31373158                return rc;
    31383159            }
     3160            Assert(cbContig == X86_PAGE_SIZE);
    31393161        }
    31403162    }
  • trunk/src/VBox/VMM/VMMR0/PDMR0DevHlp.cpp

    r86661 r87371  
    162162        Assert(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
    163163        PPDMPCIBUSR0 pBus = &pGVM->pdmr0.s.aPciBuses[idxBus];
    164 
    165         RTGCPHYS GCPhysOut;
    166164        uint16_t const uDeviceId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    167         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut);
    168         if (RT_SUCCESS(rc))
    169             GCPhys = GCPhysOut;
    170         else
     165        int rc = VINF_SUCCESS;
     166        while (cbRead > 0)
    171167        {
    172             Log(("pdmR0DevHlp_PCIPhysRead: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
    173                  GCPhys, cbRead, rc));
    174             return rc;
     168            RTGCPHYS GCPhysOut;
     169            size_t   cbContig;
     170            rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut, &cbContig);
     171            if (RT_SUCCESS(rc))
     172            {
     173                /** @todo Handle strict return codes from PGMPhysRead. */
     174                rc = pDevIns->pHlpR0->pfnPhysRead(pDevIns, GCPhysOut, pvBuf, cbRead, fFlags);
     175                if (RT_SUCCESS(rc))
     176                {
     177                    cbRead -= cbContig;
     178                    pvBuf   = (void *)((uintptr_t)pvBuf + cbContig);
     179                    GCPhys += cbContig;
     180                }
     181                else
     182                    break;
     183            }
     184            else
     185            {
     186                Log(("pdmR0DevHlp_PCIPhysRead: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
     187                     GCPhys, cbRead, rc));
     188                break;
     189            }
    175190        }
     191        return rc;
    176192    }
    177193#endif
     
    207223#ifdef VBOX_WITH_IOMMU_AMD
    208224    /** @todo IOMMU: Optimize/re-organize things here later. */
    209     PGVM        pGVM          = pDevIns->Internal.s.pGVM;
    210     PPDMIOMMUR0 pIommu        = &pGVM->pdmr0.s.aIommus[0];
    211     PPDMDEVINS   pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
     225    PGVM        pGVM         = pDevIns->Internal.s.pGVM;
     226    PPDMIOMMUR0 pIommu       = &pGVM->pdmr0.s.aIommus[0];
     227    PPDMDEVINS  pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
    212228    if (   pDevInsIommu
    213229        && pDevInsIommu != pDevIns)
     
    216232        Assert(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
    217233        PPDMPCIBUSR0 pBus = &pGVM->pdmr0.s.aPciBuses[idxBus];
    218 
    219         RTGCPHYS GCPhysOut;
    220234        uint16_t const uDeviceId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    221         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut);
    222         if (RT_SUCCESS(rc))
    223             GCPhys = GCPhysOut;
    224         else
     235        int rc = VINF_SUCCESS;
     236        while (cbWrite > 0)
    225237        {
    226             Log(("pdmR0DevHlp_PCIPhysWrite: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
    227                  GCPhys, cbWrite, rc));
    228             return rc;
     238            RTGCPHYS GCPhysOut;
     239            size_t   cbContig;
     240            rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut, &cbContig);
     241            if (RT_SUCCESS(rc))
     242            {
     243                /** @todo Handle strict return codes from PGMPhysWrite. */
     244                rc = pDevIns->pHlpR0->pfnPhysWrite(pDevIns, GCPhysOut, pvBuf, cbWrite, fFlags);
     245                if (RT_SUCCESS(rc))
     246                {
     247                    cbWrite -= cbContig;
     248                    pvBuf    = (const void *)((uintptr_t)pvBuf + cbContig);
     249                    GCPhys  += cbContig;
     250                }
     251                else
     252                    break;
     253            }
     254            else
     255            {
     256                Log(("pdmR0DevHlp_PCIPhysWrite: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
     257                     GCPhys, cbWrite, rc));
     258                break;
     259            }
    229260        }
     261        return rc;
    230262    }
    231263#endif
  • trunk/src/VBox/VMM/VMMR0/PDMR0DevHlpTracing.cpp

    r86661 r87371  
    323323        Assert(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
    324324        PPDMPCIBUSR0 pBus = &pGVM->pdmr0.s.aPciBuses[idxBus];
    325 
    326         RTGCPHYS GCPhysOut;
    327325        uint16_t const uDeviceId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    328         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut);
    329         if (RT_SUCCESS(rc))
    330             GCPhys = GCPhysOut;
    331         else
     326        int rc = VINF_SUCCESS;
     327        while (cbRead > 0)
    332328        {
    333             Log(("pdmR0DevHlp_PCIPhysRead: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
    334                  GCPhys, cbRead, rc));
    335             return rc;
     329            RTGCPHYS GCPhysOut;
     330            size_t   cbContig;
     331            rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut, &cbContig);
     332            if (RT_SUCCESS(rc))
     333            {
     334                /** @todo Handle strict return codes from PGMPhysRead. */
     335                rc = pDevIns->pHlpR0->pfnPhysRead(pDevIns, GCPhysOut, pvBuf, cbRead, fFlags);
     336                if (RT_SUCCESS(rc))
     337                {
     338                    cbRead -= cbContig;
     339                    pvBuf   = (void *)((uintptr_t)pvBuf + cbContig);
     340                    GCPhys += cbContig;
     341                }
     342                else
     343                    break;
     344            }
     345            else
     346            {
     347                Log(("pdmR0DevHlp_PCIPhysRead: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
     348                     GCPhys, cbRead, rc));
     349                break;
     350            }
    336351        }
     352        return rc;
    337353    }
    338354#endif
     
    377393        Assert(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
    378394        PPDMPCIBUSR0 pBus = &pGVM->pdmr0.s.aPciBuses[idxBus];
    379 
    380         RTGCPHYS GCPhysOut;
    381395        uint16_t const uDeviceId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    382         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut);
    383         if (RT_SUCCESS(rc))
    384             GCPhys = GCPhysOut;
    385         else
     396        int rc = VINF_SUCCESS;
     397        while (cbWrite > 0)
    386398        {
    387             Log(("pdmR0DevHlp_PCIPhysWrite: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
    388                  GCPhys, cbWrite, rc));
    389             return rc;
     399            RTGCPHYS GCPhysOut;
     400            size_t   cbContig;
     401            rc = pIommu->pfnMemAccess(pDevInsIommu, uDeviceId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut, &cbContig);
     402            if (RT_SUCCESS(rc))
     403            {
     404                /** @todo Handle strict return codes from PGMPhysWrite. */
     405                rc = pDevIns->pHlpR0->pfnPhysWrite(pDevIns, GCPhysOut, pvBuf, cbWrite, fFlags);
     406                if (RT_SUCCESS(rc))
     407                {
     408                    cbWrite -= cbContig;
     409                    pvBuf    = (const void *)((uintptr_t)pvBuf + cbContig);
     410                    GCPhys  += cbContig;
     411                }
     412                else
     413                    break;
     414            }
     415            else
     416            {
     417                Log(("pdmR0DevHlp_PCIPhysWrite: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
     418                     GCPhys, cbWrite, rc));
     419                break;
     420            }
    390421        }
     422        return rc;
    391423    }
    392424#endif
  • trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp

    r87127 r87371  
    18311831        Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
    18321832        PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
    1833 
    1834         RTGCPHYS GCPhysOut;
    18351833        uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    1836         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut);
    1837         if (RT_SUCCESS(rc))
    1838             GCPhys = GCPhysOut;
    1839         else
     1834        int rc = VINF_SUCCESS;
     1835        while (cbRead > 0)
    18401836        {
    1841             Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
    1842                  cbRead, rc));
    1843             return rc;
     1837            RTGCPHYS GCPhysOut;
     1838            size_t   cbContig;
     1839            rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut, &cbContig);
     1840            if (RT_SUCCESS(rc))
     1841            {
     1842                /** @todo Handle strict return codes from PGMPhysRead. */
     1843                rc = pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhysOut, pvBuf, cbContig, fFlags);
     1844                if (RT_SUCCESS(rc))
     1845                {
     1846                    cbRead -= cbContig;
     1847                    pvBuf   = (void *)((uintptr_t)pvBuf + cbContig);
     1848                    GCPhys += cbContig;
     1849                }
     1850                else
     1851                    break;
     1852            }
     1853            else
     1854            {
     1855                AssertMsgFailed(("Here\n"));
     1856                Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
     1857                     cbRead, rc));
     1858                break;
     1859            }
    18441860        }
     1861        return rc;
    18451862    }
    18461863#endif
     
    18851902        Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
    18861903        PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
    1887 
    1888         RTGCPHYS GCPhysOut;
    18891904        uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    1890         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut);
    1891         if (RT_SUCCESS(rc))
    1892             GCPhys = GCPhysOut;
    1893         else
     1905        int rc = VINF_SUCCESS;
     1906        while (cbWrite > 0)
    18941907        {
    1895             Log(("pdmR3DevHlp_PCIPhysWrite: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
    1896                  cbWrite, rc));
    1897             return rc;
     1908            RTGCPHYS GCPhysOut;
     1909            size_t   cbContig;
     1910            rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut, &cbContig);
     1911            if (RT_SUCCESS(rc))
     1912            {
     1913                /** @todo Handle strict return codes from PGMPhysWrite. */
     1914                rc = pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhysOut, pvBuf, cbContig, fFlags);
     1915                if (RT_SUCCESS(rc))
     1916                {
     1917                    cbWrite -= cbContig;
     1918                    pvBuf    = (const void *)((uintptr_t)pvBuf + cbContig);
     1919                    GCPhys  += cbContig;
     1920                }
     1921                else
     1922                    break;
     1923            }
     1924            else
     1925            {
     1926                Log(("pdmR3DevHlp_PCIPhysWrite: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
     1927                     cbWrite, rc));
     1928                break;
     1929            }
    18981930        }
     1931        return rc;
    18991932    }
    19001933#endif
     
    19361969        Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
    19371970        PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
    1938 
     1971        uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    19391972        RTGCPHYS GCPhysOut;
    1940         uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    1941         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, X86_PAGE_SIZE, PDMIOMMU_MEM_F_WRITE, &GCPhysOut);
     1973        size_t cbContig;
     1974        int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys & X86_PAGE_BASE_MASK, X86_PAGE_SIZE, PDMIOMMU_MEM_F_WRITE,
     1975                                      &GCPhysOut, &cbContig);
    19421976        if (RT_SUCCESS(rc))
     1977        {
    19431978            GCPhys = GCPhysOut;
     1979            Assert(cbContig == X86_PAGE_SIZE);
     1980        }
    19441981        else
    19451982        {
     
    19862023        Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
    19872024        PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
    1988 
     2025        uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    19892026        RTGCPHYS GCPhysOut;
    1990         uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    1991         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, X86_PAGE_SIZE, PDMIOMMU_MEM_F_READ, &GCPhysOut);
     2027        size_t cbContig;
     2028        int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys & X86_PAGE_BASE_MASK, X86_PAGE_SIZE, PDMIOMMU_MEM_F_READ,
     2029                                      &GCPhysOut, &cbContig);
    19922030        if (RT_SUCCESS(rc))
     2031        {
    19932032            GCPhys = GCPhysOut;
     2033            Assert(cbContig == X86_PAGE_SIZE);
     2034        }
    19942035        else
    19952036        {
  • trunk/src/VBox/VMM/VMMR3/PDMDevHlpTracing.cpp

    r86661 r87371  
    429429        Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
    430430        PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
    431 
    432         RTGCPHYS GCPhysOut;
    433431        uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    434         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut);
    435         if (RT_SUCCESS(rc))
    436             GCPhys = GCPhysOut;
    437         else
     432        int rc = VINF_SUCCESS;
     433        while (cbRead > 0)
    438434        {
    439             Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
    440                  cbRead, rc));
    441             return rc;
     435            RTGCPHYS GCPhysOut;
     436            size_t   cbContig;
     437            rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbRead, PDMIOMMU_MEM_F_READ, &GCPhysOut, &cbContig);
     438            if (RT_SUCCESS(rc))
     439            {
     440                /** @todo Handle strict return codes from PGMPhysRead. */
     441                rc = pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhysOut, pvBuf, cbRead, fFlags);
     442                if (RT_SUCCESS(rc))
     443                {
     444                    cbRead -= cbContig;
     445                    pvBuf   = (void *)((uintptr_t)pvBuf + cbContig);
     446                    GCPhys += cbContig;
     447                }
     448                else
     449                    break;
     450            }
     451            else
     452            {
     453                Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
     454                     cbRead, rc));
     455                break;
     456            }
    442457        }
    443 
    444         GCPhys = GCPhysOut;
     458        return rc;
    445459    }
    446460#endif
     
    485499        Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
    486500        PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
    487 
    488         RTGCPHYS GCPhysOut;
    489501        uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
    490         int rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, & GCPhysOut);
    491         if (RT_SUCCESS(rc))
    492             GCPhys = GCPhysOut;
    493         else
     502        int rc = VINF_SUCCESS;
     503        while (cbWrite > 0)
    494504        {
    495             Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
    496                  cbWrite, rc));
    497             return rc;
     505            RTGCPHYS GCPhysOut;
     506            size_t   cbContig;
     507            rc = pIommu->pfnMemAccess(pDevInsIommu, uDevId, GCPhys, cbWrite, PDMIOMMU_MEM_F_WRITE, &GCPhysOut, &cbContig);
     508            if (RT_SUCCESS(rc))
     509            {
     510                /** @todo Handle strict return codes from PGMPhysWrite. */
     511                rc = pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhysOut, pvBuf, cbContig, fFlags);
     512                if (RT_SUCCESS(rc))
     513                {
     514                    cbWrite -= cbContig;
     515                    pvBuf    = (const void *)((uintptr_t)pvBuf + cbContig);
     516                    GCPhys  += cbContig;
     517                }
     518                else
     519                    break;
     520            }
     521            else
     522            {
     523                Log(("pdmR3DevHlp_PCIPhysWrite: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
     524                     cbWrite, rc));
     525                break;
     526            }
    498527        }
    499 
    500         GCPhys = GCPhysOut;
     528        return rc;
    501529    }
    502530#endif
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r86661 r87371  
    700700    /** @copydoc PDMIOMMUREGR3::pfnMemAccess */
    701701    DECLR3CALLBACKMEMBER(int,   pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbAccess,
    702                                               uint32_t fFlags, PRTGCPHYS pGCPhysSpa));
     702                                              uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContig));
    703703    /** @copydoc PDMIOMMUREGR3::pfnMemBulkAccess */
    704704    DECLR3CALLBACKMEMBER(int,   pfnMemBulkAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, size_t cIovas, uint64_t const *pauIovas,
     
    722722    /** @copydoc PDMIOMMUREGR3::pfnMemAccess */
    723723    DECLR0CALLBACKMEMBER(int,   pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbAccess,
    724                                               uint32_t fFlags, PRTGCPHYS pGCPhysSpa));
     724                                              uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContig));
    725725    /** @copydoc PDMIOMMUREGR3::pfnMemBulkAccess */
    726726    DECLR0CALLBACKMEMBER(int,   pfnMemBulkAccess,(PPDMDEVINS pDevIns, uint16_t uDevId, size_t cIovas, uint64_t const *pauIovas,
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