VirtualBox

Changeset 86763 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Oct 30, 2020 5:29:14 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141157
Message:

AMD IOMMU: bugref:9654 Ensure the DTE falls within the device table segment limit and use uint32_t for offDte, uint16_t isn't enough.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp

    r86732 r86763  
    891891    /* Update the register. */
    892892    pThis->aDevTabBaseAddrs[0].u64 = u64Value;
     893
     894    /* Paranoia. */
     895    Assert(pThis->aDevTabBaseAddrs[0].n.u9Size <= g_auDevTabSegMaxSizes[0]);
    893896    return VINF_SUCCESS;
    894897}
     
    26672670    IOMMU_CTRL_T const Ctrl = iommuAmdGetCtrl(pThis);
    26682671
     2672    /* Figure out which device table segment is being accessed. */
    26692673    uint8_t const idxSegsEn = Ctrl.n.u3DevTabSegEn;
    26702674    Assert(idxSegsEn < RT_ELEMENTS(g_auDevTabSegShifts));
     
    26752679
    26762680    RTGCPHYS const GCPhysDevTab = pThis->aDevTabBaseAddrs[idxSeg].n.u40Base << X86_PAGE_4K_SHIFT;
    2677     uint16_t const offDte       = (uDevId & ~g_auDevTabSegMasks[idxSegsEn]) * sizeof(DTE_T);
     2681    uint32_t const offDte       = (uDevId & ~g_auDevTabSegMasks[idxSegsEn]) * sizeof(DTE_T);
    26782682    RTGCPHYS const GCPhysDte    = GCPhysDevTab + offDte;
    26792683
    2680     Assert(!(GCPhysDevTab & X86_PAGE_4K_OFFSET_MASK));
    2681     int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysDte, pDte, sizeof(*pDte));
    2682     if (RT_FAILURE(rc))
    2683     {
     2684    /* Ensure the DTE falls completely within the device table segment. */
     2685    uint32_t const cbDevTabSeg  = (pThis->aDevTabBaseAddrs[idxSeg].n.u9Size + 1) << X86_PAGE_4K_SHIFT;
     2686    if (offDte + sizeof(DTE_T) <= cbDevTabSeg)
     2687    {
     2688        /* Read the device table entry from guest memory. */
     2689        Assert(!(GCPhysDevTab & X86_PAGE_4K_OFFSET_MASK));
     2690        int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysDte, pDte, sizeof(*pDte));
     2691        if (RT_SUCCESS(rc))
     2692            return rc;
     2693
     2694        /* Raise a device table hardware error. */
    26842695        LogFunc(("Failed to read device table entry at %#RGp. rc=%Rrc -> DevTabHwError\n", GCPhysDte, rc));
    26852696
     
    26872698        iommuAmdInitDevTabHwErrorEvent(uDevId, GCPhysDte, enmOp, &EvtDevTabHwErr);
    26882699        iommuAmdRaiseDevTabHwErrorEvent(pDevIns, enmOp, &EvtDevTabHwErr);
    2689         return VERR_IOMMU_IPE_1;
    2690     }
    2691 
    2692     return rc;
     2700        return VERR_IOMMU_DTE_READ_FAILED;
     2701    }
     2702
     2703    /* Raise an I/O page fault for out-of-bounds acccess. */
     2704    EVT_IO_PAGE_FAULT_T EvtIoPageFault;
     2705    iommuAmdInitIoPageFaultEvent(uDevId, 0 /* uDomainId */, 0 /* uIova */, false /* fPresent */, false /* fRsvdNotZero */,
     2706                                 false /* fPermDenied */, enmOp, &EvtIoPageFault);
     2707    iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault, kIoPageFaultType_DevId_Invalid);
     2708    return VERR_IOMMU_DTE_BAD_OFFSET;
    26932709}
    26942710
     
    32443260        iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, GCPhysIn, false /* fPresent */, false /* fRsvdNotZero */,
    32453261                                     false /* fPermDenied */, enmOp, &EvtIoPageFault);
    3246         iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault,
    3247                                       kIoPageFaultType_IrteAddrInvalid);
     3262        iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault, kIoPageFaultType_IrteAddrInvalid);
    32483263        return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
    32493264    }
     
    33483363{
    33493364    /* Read the device table entry from memory. */
    3350     LogFlowFunc(("uDevId=%#x enmOp=%u\n", uDevId, enmOp));
     3365    LogFlowFunc(("uDevId=%#x (%#x:%#x:%#x) enmOp=%u\n", uDevId,
     3366                 ((uDevId >> VBOX_PCI_BUS_SHIFT) & VBOX_PCI_BUS_MASK),
     3367                 ((uDevId >> VBOX_PCI_DEVFN_DEV_SHIFT) & VBOX_PCI_DEVFN_DEV_MASK), (uDevId & VBOX_PCI_DEVFN_FUN_MASK), enmOp));
    33513368
    33523369    DTE_T Dte;
     
    34043421                    {
    34053422                        uint8_t const uIntrCtrl = Dte.n.u2IntrCtrl;
    3406                         if (uIntrCtrl == IOMMU_INTR_CTRL_TARGET_ABORT)
    3407                         {
    3408                             LogFunc(("IntCtl=0: Target aborting fixed/arbitrated interrupt -> Target abort\n"));
    3409                             iommuAmdSetPciTargetAbort(pDevIns);
    3410                             return VERR_IOMMU_INTR_REMAP_DENIED;
    3411                         }
    3412 
    3413                         if (uIntrCtrl == IOMMU_INTR_CTRL_FWD_UNMAPPED)
    3414                         {
    3415                             fPassThru = true;
    3416                             break;
    3417                         }
    3418 
    34193423                        if (uIntrCtrl == IOMMU_INTR_CTRL_REMAP)
    34203424                        {
     
    34443448                        }
    34453449
     3450                        if (uIntrCtrl == IOMMU_INTR_CTRL_FWD_UNMAPPED)
     3451                        {
     3452                            fPassThru = true;
     3453                            break;
     3454                        }
     3455
     3456                        if (uIntrCtrl == IOMMU_INTR_CTRL_TARGET_ABORT)
     3457                        {
     3458                            LogFunc(("IntCtl=0: Remapping disallowed for fixed/arbitrated interrupt (%#x) -> Target abort\n",
     3459                                     pMsiIn->Data.n.u8Vector));
     3460                            iommuAmdSetPciTargetAbort(pDevIns);
     3461                            return VERR_IOMMU_INTR_REMAP_DENIED;
     3462                        }
     3463
    34463464                        /* Paranoia. */
    34473465                        Assert(uIntrCtrl == IOMMU_INTR_CTRL_RSVD);
    34483466
    34493467                        LogFunc(("IntCtl mode invalid %#x -> Illegal DTE\n", uIntrCtrl));
    3450 
    34513468                        EVT_ILLEGAL_DTE_T Event;
    34523469                        iommuAmdInitIllegalDteEvent(uDevId, pMsiIn->Addr.u64, true /* fRsvdNotZero */, enmOp, &Event);
     
    34743491                }
    34753492
     3493                LogFunc(("Remapping/passthru disallowed for interrupt (%#x) -> Target abort\n", pMsiIn->Data.n.u8Vector));
    34763494                iommuAmdSetPciTargetAbort(pDevIns);
    34773495                return VERR_IOMMU_INTR_REMAP_DENIED;
Note: See TracChangeset for help on using the changeset viewer.

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