VirtualBox

Changeset 78073 in vbox for trunk/src/VBox/Devices/USB


Ignore:
Timestamp:
Apr 10, 2019 10:09:05 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129929
Message:

Devices/USB/DevOHCI.cpp: Remove a few todos and raise unrecoverable errors when the HC encounters an invalid state bugref:9429

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/USB/DevOHCI.cpp

    r76553 r78073  
    906906 */
    907907# define ohciR3SetInterrupt(ohci, intr) ohciR3SetInterruptInt(ohci, VERR_IGNORED, intr, #intr)
     908
     909
     910/**
     911 * Sets the HC in the unrecoverable error state and raises the appropriate interrupt.
     912 *
     913 * @returns nothing.
     914 * @param   pThis               The OHCI instance.
     915 */
     916DECLINLINE(void) ohciR3RaiseUnrecoverableError(POHCI pThis)
     917{
     918    ohciR3SetInterrupt(pThis, OHCI_INTR_UNRECOVERABLE_ERROR);
     919}
    908920
    909921
     
    20812093 * Sets up a OHCI transport buffer.
    20822094 *
     2095 * @returns Flags whether the buffer could be initialised successfully.
    20832096 * @param   pBuf    Ohci buffer.
    20842097 * @param   cbp     Current buffer pointer. 32-bit physical address.
    20852098 * @param   be      Last byte in buffer (BufferEnd). 32-bit physical address.
    20862099 */
    2087 static void ohciR3BufInit(POHCIBUF pBuf, uint32_t cbp, uint32_t be)
    2088 {
     2100static bool ohciR3BufInit(POHCIBUF pBuf, uint32_t cbp, uint32_t be)
     2101{
     2102    if (RT_UNLIKELY(be < cbp))
     2103        return false;
     2104
    20892105    if (!cbp || !be)
    20902106    {
     
    21112127        Log2(("ohci: cbp=%#010x be=%#010x cbTotal=%u PAGE FLIP\n", cbp, be, pBuf->cbTotal));
    21122128    }
     2129
     2130    return true;
    21132131}
    21142132
     
    26602678         */
    26612679        OHCIBUF Buf;
    2662         ohciR3BufInit(&Buf, pTd->cbp, pTd->be);
     2680        if (!ohciR3BufInit(&Buf, pTd->cbp, pTd->be))
     2681        {
     2682            ohciR3RaiseUnrecoverableError(pThis);
     2683            return;
     2684        }
    26632685        uint32_t NewCbp;
    26642686        if (cbLeft >= Buf.cbTotal)
     
    26832705        {
    26842706            Assert(Buf.cVecs > 0);
     2707
     2708            /* Be paranoid */
     2709            if (   Buf.aVecs[0].cb > cbLeft
     2710                || (   Buf.cVecs > 1
     2711                    && Buf.aVecs[1].cb > (cbLeft - Buf.aVecs[0].cb)))
     2712            {
     2713                ohciR3RaiseUnrecoverableError(pThis);
     2714                return;
     2715            }
     2716
    26852717            ohciR3PhysWrite(pThis, Buf.aVecs[0].Addr, pb, Buf.aVecs[0].cb);
    26862718            if (Buf.cVecs > 1)
     
    27902822
    27912823    ohciR3Lock(pThis);
    2792     pThis->fIdle = false;   /* Mark as active */
    2793 
    2794     /* get the current end point descriptor. */
    2795     OHCIED Ed;
    2796     ohciR3ReadEd(pThis, pUrb->pHci->EdAddr, &Ed);
    2797 
    2798     /*
    2799      * Check that the URB hasn't been canceled and then try unlink the TDs.
    2800      *
    2801      * We drop the URB if the ED is marked halted/skip ASSUMING that this
    2802      * means the HCD has canceled the URB.
    2803      *
    2804      * If we succeed here (i.e. not dropping the URB), the TdCopy members will
    2805      * be updated but not yet written. We will delay the writing till we're done
    2806      * with the data copying, buffer pointer advancing and error handling.
    2807      */
    2808     int cFmAge = ohciR3InFlightRemoveUrb(pThis, pUrb);
    2809     if (pUrb->enmStatus == VUSBSTATUS_UNDO)
    2810     {
    2811         /* Leave the TD alone - the HCD doesn't want us talking to the device. */
    2812         Log(("%s: ohciR3RhXferCompletion: CANCELED {ED=%#010x cTds=%d TD0=%#010x age %d}\n",
    2813              pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge));
    2814         STAM_COUNTER_INC(&pThis->StatDroppedUrbs);
    2815         ohciR3Unlock(pThis);
    2816         return;
    2817     }
    2818     bool fHasBeenCanceled = false;
    2819     if (    (Ed.HeadP & ED_HEAD_HALTED)
    2820         ||  (Ed.hwinfo & ED_HWINFO_SKIP)
    2821         ||  cFmAge < 0
    2822         ||  (fHasBeenCanceled = ohciR3HasUrbBeenCanceled(pThis, pUrb, &Ed))
    2823         ||  !ohciR3UnlinkTds(pThis, pUrb, &Ed)
    2824        )
    2825     {
    2826         Log(("%s: ohciR3RhXferCompletion: DROPPED {ED=%#010x cTds=%d TD0=%#010x age %d} because:%s%s%s%s%s!!!\n",
    2827              pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge,
    2828              (Ed.HeadP & ED_HEAD_HALTED)                            ? " ep halted" : "",
    2829              (Ed.hwinfo & ED_HWINFO_SKIP)                           ? " ep skip" : "",
    2830              (Ed.HeadP & ED_PTR_MASK) != pUrb->paTds[0].TdAddr      ? " ep head-changed" : "",
    2831              cFmAge < 0                                             ? " td not-in-flight" : "",
    2832              fHasBeenCanceled                                       ? " td canceled" : ""));
    2833         NOREF(fHasBeenCanceled);
    2834         STAM_COUNTER_INC(&pThis->StatDroppedUrbs);
    2835         ohciR3Unlock(pThis);
    2836         return;
    2837     }
    2838 
    2839     /*
    2840      * Complete the TD updating and write the back.
    2841      * When appropriate also copy data back to the guest memory.
    2842      */
    2843     if (pUrb->enmType == VUSBXFERTYPE_ISOC)
    2844         ohciR3RhXferCompleteIsochronousURB(pThis, pUrb /*, &Ed , cFmAge*/);
    2845     else
    2846         ohciR3RhXferCompleteGeneralURB(pThis, pUrb, &Ed, cFmAge);
    2847 
    2848     /* finally write back the endpoint descriptor. */
    2849     ohciR3WriteEd(pThis, pUrb->pHci->EdAddr, &Ed);
     2824
     2825    /* Do nothing if the HC encountered an unrecoverable error. */
     2826    if (!(pThis->intr_status & OHCI_INTR_UNRECOVERABLE_ERROR))
     2827    {
     2828        pThis->fIdle = false;   /* Mark as active */
     2829
     2830        /* get the current end point descriptor. */
     2831        OHCIED Ed;
     2832        ohciR3ReadEd(pThis, pUrb->pHci->EdAddr, &Ed);
     2833
     2834        /*
     2835         * Check that the URB hasn't been canceled and then try unlink the TDs.
     2836         *
     2837         * We drop the URB if the ED is marked halted/skip ASSUMING that this
     2838         * means the HCD has canceled the URB.
     2839         *
     2840         * If we succeed here (i.e. not dropping the URB), the TdCopy members will
     2841         * be updated but not yet written. We will delay the writing till we're done
     2842         * with the data copying, buffer pointer advancing and error handling.
     2843         */
     2844        int cFmAge = ohciR3InFlightRemoveUrb(pThis, pUrb);
     2845        if (pUrb->enmStatus == VUSBSTATUS_UNDO)
     2846        {
     2847            /* Leave the TD alone - the HCD doesn't want us talking to the device. */
     2848            Log(("%s: ohciR3RhXferCompletion: CANCELED {ED=%#010x cTds=%d TD0=%#010x age %d}\n",
     2849                 pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge));
     2850            STAM_COUNTER_INC(&pThis->StatDroppedUrbs);
     2851            ohciR3Unlock(pThis);
     2852            return;
     2853        }
     2854        bool fHasBeenCanceled = false;
     2855        if (    (Ed.HeadP & ED_HEAD_HALTED)
     2856            ||  (Ed.hwinfo & ED_HWINFO_SKIP)
     2857            ||  cFmAge < 0
     2858            ||  (fHasBeenCanceled = ohciR3HasUrbBeenCanceled(pThis, pUrb, &Ed))
     2859            ||  !ohciR3UnlinkTds(pThis, pUrb, &Ed)
     2860           )
     2861        {
     2862            Log(("%s: ohciR3RhXferCompletion: DROPPED {ED=%#010x cTds=%d TD0=%#010x age %d} because:%s%s%s%s%s!!!\n",
     2863                 pUrb->pszDesc, pUrb->pHci->EdAddr, pUrb->pHci->cTds, pUrb->paTds[0].TdAddr, cFmAge,
     2864                 (Ed.HeadP & ED_HEAD_HALTED)                            ? " ep halted" : "",
     2865                 (Ed.hwinfo & ED_HWINFO_SKIP)                           ? " ep skip" : "",
     2866                 (Ed.HeadP & ED_PTR_MASK) != pUrb->paTds[0].TdAddr      ? " ep head-changed" : "",
     2867                 cFmAge < 0                                             ? " td not-in-flight" : "",
     2868                 fHasBeenCanceled                                       ? " td canceled" : ""));
     2869            NOREF(fHasBeenCanceled);
     2870            STAM_COUNTER_INC(&pThis->StatDroppedUrbs);
     2871            ohciR3Unlock(pThis);
     2872            return;
     2873        }
     2874
     2875        /*
     2876         * Complete the TD updating and write the back.
     2877         * When appropriate also copy data back to the guest memory.
     2878         */
     2879        if (pUrb->enmType == VUSBXFERTYPE_ISOC)
     2880            ohciR3RhXferCompleteIsochronousURB(pThis, pUrb /*, &Ed , cFmAge*/);
     2881        else
     2882            ohciR3RhXferCompleteGeneralURB(pThis, pUrb, &Ed, cFmAge);
     2883
     2884        /* finally write back the endpoint descriptor. */
     2885        ohciR3WriteEd(pThis, pUrb->pHci->EdAddr, &Ed);
     2886    }
     2887
    28502888    ohciR3Unlock(pThis);
    28512889}
     
    29352973    ohciR3ReadTd(pThis, TdAddr, &Td);
    29362974    OHCIBUF Buf;
    2937     ohciR3BufInit(&Buf, Td.cbp, Td.be);
     2975    if (!ohciR3BufInit(&Buf, Td.cbp, Td.be))
     2976    {
     2977        ohciR3RaiseUnrecoverableError(pThis);
     2978        return false;
     2979    }
    29382980
    29392981    *pNextTdAddr = Td.NextTD & ED_PTR_MASK;
     
    29552997                default:
    29562998                    Log(("ohciR3ServiceTd: Invalid direction!!!! Td.hwinfo=%#x Ed.hwdinfo=%#x\n", Td.hwinfo, pEd->hwinfo));
    2957                     /** @todo Do the correct thing here */
     2999                    ohciR3RaiseUnrecoverableError(pThis);
    29583000                    return false;
    29593001            }
     
    29883030        &&  enmDir != VUSBDIRECTION_IN)
    29893031    {
     3032        /* Be paranoid. */
     3033        if (   Buf.aVecs[0].cb > pUrb->cbData
     3034            || (   Buf.cVecs > 1
     3035                && Buf.aVecs[1].cb > (pUrb->cbData - Buf.aVecs[0].cb)))
     3036        {
     3037            ohciR3RaiseUnrecoverableError(pThis);
     3038            VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb);
     3039            return false;
     3040        }
     3041
    29903042        ohciR3PhysRead(pThis, Buf.aVecs[0].Addr, pUrb->abData, Buf.aVecs[0].cb);
    29913043        if (Buf.cVecs > 1)
     
    30093061    Log(("ohciR3ServiceTd: failed submitting TdAddr=%#010x EdAddr=%#010x pUrb=%p!!\n",
    30103062         TdAddr, EdAddr, pUrb));
     3063    VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb);
    30113064    ohciR3InFlightRemove(pThis, TdAddr);
    30123065    return false;
     
    30613114    /* read the head */
    30623115    ohciR3ReadTd(pThis, TdAddr, &Head.Td);
    3063     ohciR3BufInit(&Head.Buf, Head.Td.cbp, Head.Td.be);
     3116    if (!ohciR3BufInit(&Head.Buf, Head.Td.cbp, Head.Td.be))
     3117    {
     3118        ohciR3RaiseUnrecoverableError(pThis);
     3119        return false;
     3120    }
    30643121    Head.TdAddr = TdAddr;
    30653122    Head.pNext = NULL;
     
    30793136        pCur->TdAddr = pTail->Td.NextTD & ED_PTR_MASK;
    30803137        ohciR3ReadTd(pThis, pCur->TdAddr, &pCur->Td);
    3081         ohciR3BufInit(&pCur->Buf, pCur->Td.cbp, pCur->Td.be);
     3138        if (!ohciR3BufInit(&pCur->Buf, pCur->Td.cbp, pCur->Td.be))
     3139        {
     3140            ohciR3RaiseUnrecoverableError(pThis);
     3141            return false;
     3142        }
    30823143
    30833144        /* Don't combine if the direction doesn't match up. There can't actually be
     
    31133174                default:
    31143175                    Log(("ohciR3ServiceTdMultiple: Invalid direction!!!! Head.Td.hwinfo=%#x Ed.hwdinfo=%#x\n", Head.Td.hwinfo, pEd->hwinfo));
    3115                     /** @todo Do the correct thing here */
     3176                    ohciR3RaiseUnrecoverableError(pThis);
    31163177                    return false;
    31173178            }
     
    31803241    for (struct OHCITDENTRY *pCur = &Head; pCur; pCur = pCur->pNext, iTd++)
    31813242        ohciR3InFlightRemove(pThis, pCur->TdAddr);
     3243    VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb);
    31823244    return false;
    31833245}
     
    32913353        default:
    32923354            Log(("ohciR3ServiceIsochronousTd: Invalid direction!!!! Ed.hwdinfo=%#x\n", pEd->hwinfo));
    3293             /* Should probably raise an unrecoverable HC error here */
     3355            ohciR3RaiseUnrecoverableError(pThis);
    32943356            return false;
    32953357    }
     
    33073369    uint32_t cbTotal = 0;
    33083370    if (((uint32_t)pITd->aPSW[R] >> ITD_PSW_CC_SHIFT) < (OHCI_CC_NOT_ACCESSED_0 >> TD_HWINFO_CC_SHIFT))
     3371    {
    33093372        Log(("ITdAddr=%RX32 PSW%d.CC=%#x < 'Not Accessed'!\n", ITdAddr, R, pITd->aPSW[R] >> ITD_PSW_CC_SHIFT)); /* => Unrecoverable Error*/
     3373        pThis->intr_status |= OHCI_INTR_UNRECOVERABLE_ERROR;
     3374        return false;
     3375    }
    33103376    uint16_t offPrev = aPkts[0].off = (pITd->aPSW[R] & ITD_PSW_OFFSET);
    33113377
     
    33183384        cbTotal += aPkts[iR - R - 1].cb = off - offPrev;
    33193385        if (off < offPrev)
     3386        {
    33203387            Log(("ITdAddr=%RX32 PSW%d.offset=%#x < offPrev=%#x!\n", ITdAddr, iR, off, offPrev)); /* => Unrecoverable Error*/
     3388            ohciR3RaiseUnrecoverableError(pThis);
     3389            return false;
     3390        }
    33213391        if (((uint32_t)PSW >> ITD_PSW_CC_SHIFT) < (OHCI_CC_NOT_ACCESSED_0 >> TD_HWINFO_CC_SHIFT))
     3392        {
    33223393            Log(("ITdAddr=%RX32 PSW%d.CC=%#x < 'Not Accessed'!\n", ITdAddr, iR, PSW >> ITD_PSW_CC_SHIFT)); /* => Unrecoverable Error*/
     3394            ohciR3RaiseUnrecoverableError(pThis);
     3395            return false;
     3396        }
    33233397        offPrev = off;
    33243398    }
     
    33293403                          + 1 /* BE is inclusive */;
    33303404    if (offEnd < offPrev)
     3405    {
    33313406        Log(("ITdAddr=%RX32 offEnd=%#x < offPrev=%#x!\n", ITdAddr, offEnd, offPrev)); /* => Unrecoverable Error*/
     3407        ohciR3RaiseUnrecoverableError(pThis);
     3408        return false;
     3409    }
    33323410    cbTotal += aPkts[cFrames - 1 - R].cb = offEnd - offPrev;
    33333411    Assert(cbTotal <= 0x2000);
     
    34063484         pUrb, cbTotal, EdAddr, 1, ITdAddr, rc));
    34073485    ohciR3InFlightRemove(pThis, ITdAddr);
     3486    VUSBIRhFreeUrb(pThis->RootHub.pIRhConn, pUrb);
    34083487    return false;
    34093488}
     
    41454224# endif
    41464225
    4147     /* Frame boundary, so do EOF stuff here. */
    4148     ohciR3BumpFrameNumber(pThis);
    4149     if ( (pThis->dqic != 0x7) && (pThis->dqic != 0))
    4150         pThis->dqic--;
    4151 
    4152     /* Clean up any URBs that have been removed. */
    4153     ohciR3CancelOrphanedURBs(pThis);
    4154 
    4155     /* Start the next frame. */
    4156     ohciR3StartOfFrame(pThis);
     4226    if (!(pThis->intr_status & OHCI_INTR_UNRECOVERABLE_ERROR))
     4227    {
     4228        /* Frame boundary, so do EOF stuff here. */
     4229        ohciR3BumpFrameNumber(pThis);
     4230        if ( (pThis->dqic != 0x7) && (pThis->dqic != 0))
     4231            pThis->dqic--;
     4232
     4233        /* Clean up any URBs that have been removed. */
     4234        ohciR3CancelOrphanedURBs(pThis);
     4235
     4236        /* Start the next frame. */
     4237        ohciR3StartOfFrame(pThis);
     4238    }
    41574239
    41584240# ifdef VBOX_WITH_OHCI_PHYS_READ_STATS
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