VirtualBox

Changeset 80615 in vbox for trunk/src


Ignore:
Timestamp:
Sep 6, 2019 4:24:53 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Now disk operations are working on Linux such as fdisk, mkfs, and mounting the disk and accessing files. See bugref:9440, Comment #73

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r80596 r80615  
    108108
    109109#define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT)
     110
     111/**
     112 * This macro resolves to boolean true if uOffset matches a field offset and size exactly,
     113 * (or if it is a 64-bit field, if it accesses either 32-bit part as a 32-bit access)
     114 * ASSUMED this critereon is mandated by section 4.1.3.1 of the VirtIO 1.0 specification)
     115 * This MACRO can be re-written to allow unaligned access to a field (within bounds).
     116 *
     117 * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
     118 * @result           - true or false
     119 */
     120#define MATCH_SCSI_CONFIG(member) \
     121            (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
     122             && (   uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
     123                 || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
     124             && cb == sizeof(uint32_t)) \
     125         || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
     126               && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member))
     127
     128#define LOG_ACCESSOR(member) \
     129        virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
     130            pv, cb, uIntraOffset, fWrite, false, 0);
     131
     132#define SCSI_CONFIG_ACCESSOR(member) \
     133    { \
     134        uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
     135        if (fWrite) \
     136            memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \
     137        else \
     138            memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
     139        LOG_ACCESSOR(member); \
     140    }
     141
     142#define SCSI_CONFIG_ACCESSOR_READONLY(member) \
     143    { \
     144        uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
     145        if (fWrite) \
     146            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
     147        else \
     148        { \
     149            memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
     150            LOG_ACCESSOR(member); \
     151        } \
     152    }
     153
     154#define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \
     155            pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE
     156
     157#define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \
     158            pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE
    110159/**
    111160 * The following struct is the VirtIO SCSI Host Device   device-specific configuration described in section 5.6.4
     
    493542
    494543#define SET_LUN_BUF(target, lun, out) \
    495      out[0] = 0x01;  out[1] = target; out[2] = (lun >> 8) & 0x40;  out[3] = lun & 0xff;  *((uint16_t *)out + 4) = 0;
    496 
     544     out[0] = 0x01;  \
     545     out[1] = target; \
     546     out[2] = (lun >> 8) & 0x40; \
     547     out[3] = lun & 0xff;  \
     548     *((uint16_t *)out + 4) = 0;
    497549
    498550DECLINLINE(bool) isBufZero(uint8_t *pv, size_t cb)
     
    595647}
    596648
    597 /**
    598  * This macro resolves to boolean true if uOffset matches a field offset and size exactly,
    599  * (or if it is a 64-bit field, if it accesses either 32-bit part as a 32-bit access)
    600  * ASSUMED this critereon is mandated by section 4.1.3.1 of the VirtIO 1.0 specification)
    601  * This MACRO can be re-written to allow unaligned access to a field (within bounds).
    602  *
    603  * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
    604  * @result           - true or false
    605  */
    606 #define MATCH_SCSI_CONFIG(member) \
    607             (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
    608              && (   uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
    609                  || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
    610              && cb == sizeof(uint32_t)) \
    611          || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
    612                && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member))
    613 
    614 #define LOG_ACCESSOR(member) \
    615         virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
    616             pv, cb, uIntraOffset, fWrite, false, 0);
    617 
    618 #define SCSI_CONFIG_ACCESSOR(member) \
    619     { \
    620         uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
    621         if (fWrite) \
    622             memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \
    623         else \
    624             memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
    625         LOG_ACCESSOR(member); \
    626     }
    627 
    628 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \
    629     { \
    630         uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
    631         if (fWrite) \
    632             LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
    633         else \
    634         { \
    635             memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
    636             LOG_ACCESSOR(member); \
    637         } \
    638     }
    639 
    640 #define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \
    641             pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE
    642 
    643 #define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \
    644             pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE
    645 
    646649typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
    647650
     
    667670}
    668671#endif
     672
     673DECLINLINE(void) virtioScsiVirtToSgPhys(PVIRTIOSCSI pThis, PRTSGBUF pSgDst, void *pvSrc, size_t cb)
     674{
     675    while (cb)
     676    {
     677        size_t cbSeg = cb;
     678        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgDst, &cbSeg);
     679        PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSrc, cbSeg);
     680        pvSrc = ((uint8_t *)pvSrc) + cbSeg;
     681        cb -= cbSeg;
     682    }
     683}
     684
     685DECLINLINE(void) virtioScsiSgPhysTogVirt(PVIRTIOSCSI pThis, PRTSGBUF pSgSrc, void *pvDst, size_t cb)
     686{
     687    while (cb)
     688    {
     689        size_t cbSeg = cb;
     690        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgSrc, &cbSeg);
     691        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvDst, cbSeg);
     692        pvDst = ((uint8_t *)pvDst) + cbSeg;
     693        cb -= cbSeg;
     694    }
     695}
    669696
    670697/**
     
    701728 */
    702729static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    703                                                     void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
    704                                                     size_t cbCopy)
    705 {
    706     RT_NOREF(hIoReq);
    707     RT_NOREF(pInterface);
    708 
     730                                                      void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy)
     731{
     732    RT_NOREF2(hIoReq, pInterface);
    709733    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    710 
    711     /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */
    712     memcpy(pReq->pbDataIn + offDst, pSgBuf->paSegs[0].pvSeg, cbCopy);
     734    if (pReq->pbDataIn)
     735        RTSgBufCopyToBuf(pSgBuf, pReq->pbDataIn + offDst, cbCopy);
    713736    return VINF_SUCCESS;
    714737}
    715738
    716 
    717739/**
    718740 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
    719741 */
    720742static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    721                                                   void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
    722                                                   size_t cbCopy)
    723 {
    724     RT_NOREF(hIoReq);
    725     RT_NOREF(pInterface);
    726 
     743                                                    void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy)
     744{
     745    RT_NOREF2(hIoReq, pInterface);
    727746    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    728     /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */
    729 
    730     memcpy(pSgBuf->paSegs[0].pvSeg, pReq->pbDataOut + offSrc, cbCopy);
     747    if (pReq->pbDataOut)
     748        RTSgBufCopyFromBuf(pSgBuf, pReq->pbDataOut + offSrc, cbCopy);
    731749
    732750    return VINF_SUCCESS;
     
    799817}
    800818
     819static void virtioScsiFreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq)
     820{
     821    RTMemFree(pReq->pbSense);
     822    RTMemFree(pReq->pbPiIn);
     823    RTMemFree(pReq->pbDataIn);
     824    RTMemFree(pReq->pVirtqReq);
     825    pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq);
     826}
     827
    801828/**
    802829 * This is called to complete a request immediately
     
    848875 *       and return the failure code for any-and-all until that's done before
    849876 *       allowing a reset to continue.
    850  *
    851  *       In the absence of active I/O farmed out to VSCSI
    852  *       the device handles a guest driver unload/reload gracefully and has
    853  *       been tested.
    854877 */
    855878static int virtioScsiReqFinish(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq)
     
    10121035
    10131036        Log(("-----------------------------------------------------------------------------------------\n"));
    1014 
    1015     }
    1016     RTMemFree(pReq->pbSense);
    1017     RTMemFree(pReq->pbDataIn);
    1018     RTMemFree(pReq->pbPiIn);
    1019     RTMemFree(pReq->pVirtqReq);
    1020 
    1021     pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
     1037    }
     1038
     1039    virtioScsiFreeReq(pTarget, pReq);
    10221040
    10231041    if (pTarget->cReqsInProgress == 0 && pThis->fSignalIdle)
     
    10261044    return VINF_SUCCESS;
    10271045}
     1046
    10281047
    10291048static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf)
     
    10381057    AssertReturn(pVirtqReq, VERR_NO_MEMORY);
    10391058
    1040     off_t cbOff = 0;
    1041     size_t cbCopy = cbOut;
    1042     while (cbCopy)
    1043     {
    1044         size_t cbSeg = cbCopy;
    1045         RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg);
    1046         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, ((uint8_t *)pVirtqReq) + cbOff, cbSeg);
    1047         cbCopy -= cbSeg;
    1048         cbOff += cbSeg;
    1049     }
    1050 
    1051 //    VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, (uint8_t *)pVirtqReq,  cbOut,  0, "\npVirtqReq");
     1059    virtioScsiSgPhysTogVirt(pThis, pOutSgBuf, pVirtqReq, cbOut);
    10521060
    10531061    uint8_t  uTarget =  pVirtqReq->cmdHdr.uLUN[1];
     
    10931101        respHdr.uResidual = cbDataOut + cbDataIn;
    10941102        virtioScsiReqErr(pThis, qIdx, &respHdr, abSense);
     1103        RTMemFree(pVirtqReq);
    10951104        return VINF_SUCCESS;
    10961105    }
     
    11361145    pReq->cbIn      = cbIn;
    11371146    pReq->cbOut     = cbOut;
    1138     pReq->pbDataOut = pbDataOut;
    11391147    pReq->cbDataOut = cbDataOut;
     1148    pReq->pbDataOut = cbDataOut ? pbDataOut : 0;
    11401149    pReq->pVirtqReq = pVirtqReq;
    11411150    pReq->pInSgBuf  = pInSgBuf;
     
    11551164    rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN,
    11561165                                        pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize,
    1157                                         PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, cbDataIn,
     1166                                        PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir,
     1167                                        RT_MAX(cbDataIn, cbDataOut),
    11581168                                        pReq->pbSense, pReq->cbSense, &pReq->uSenseLen,
    11591169                                        &pReq->uStatus, 30 * RT_MS_1SEC);
     
    11881198        respHdr.uResidual = cbDataIn + cbDataOut;
    11891199        virtioScsiReqErr(pThis, qIdx, &respHdr, abSense);
    1190         RTMemFree(pReq->pbSense);
    1191         RTMemFree(pReq->pbDataIn);
    1192         RTMemFree(pReq->pbPiIn);
    1193         RTMemFree(pVirtqReq);
    1194         pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
     1200        virtioScsiFreeReq(pTarget, pReq);
    11951201        return VINF_SUCCESS;
    11961202    }
     
    12131219static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf)
    12141220{
    1215     RT_NOREF(pThis);
    1216     RT_NOREF(qIdx);
    1217     RT_NOREF(pInSgBuf);
     1221    RT_NOREF3(pThis, qIdx, pInSgBuf);
    12181222
    12191223    /**
     
    12271231    AssertMsgReturn(pScsiCtrl, ("Out of memory"), VERR_NO_MEMORY);
    12281232
    1229      /**
    1230       * Get control command into virtual memory
    1231       */
    1232     off_t cbOff = 0;
    1233     size_t cbSeg = 0;
    1234     while (cbOut)
    1235     {
    1236         RTGCPHYS pvSeg = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg);
    1237         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pvSeg, pScsiCtrl + cbOff, cbSeg);
    1238         cbOut -= cbSeg;
    1239         cbOff += cbSeg;
    1240     }
     1233    virtioScsiSgPhysTogVirt(pThis, pOutSgBuf, pScsiCtrl, cbOut);
    12411234
    12421235    uint8_t  uResponse = VIRTIOSCSI_S_OK;
     
    14141407        if (rc == VERR_NOT_AVAILABLE)
    14151408        {
    1416             Log3Func(("Nothing found in %s\n", QUEUENAME(qIdx)));
     1409            Log6Func(("Nothing found in %s\n", QUEUENAME(qIdx)));
    14171410            continue;
    14181411        }
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r80596 r80615  
    14631463
    14641464 /**
    1465   * Do a hex dump of a buffer.
     1465  * Do a hex dump of a buffer
    14661466  *
    14671467  * @param   pv       Pointer to array to dump
     
    14751475     if (pszTitle)
    14761476         Log(("%s [%d bytes]:\n", pszTitle, cb));
    1477      for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1); row++)
     1477     for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1) && row * 16 < cb; row++)
    14781478     {
    1479          uint32_t uAddr = row * 16 + uBase;
    1480          Log(("%x%x%x%x: ", (uAddr >> 12) & 0xf, (uAddr >> 8) & 0xf, (uAddr >> 4) & 0xf, uAddr & 0xf));
    1481          for (int col = 0; col < 16; col++)
     1479         Log(("%04x: ", row * 16 + uBase)); /* line address */
     1480         for (uint8_t col = 0; col < 16; col++)
    14821481         {
    14831482            uint32_t idx = row * 16 + col;
    1484             uint8_t u8 = pv[idx];
    14851483            if (idx >= cb)
    14861484                Log(("-- %s", (col + 1) % 8 ? "" : "  "));
    14871485            else
    1488                 Log(("%x%x %s", u8 >> 4 & 0xf, u8 & 0xf, (col + 1) % 8 ? "" : "  "));
     1486                Log(("%02x %s", pv[idx], (col + 1) % 8 ? "" : "  "));
    14891487         }
    1490          for (int col = 0; col < 16; col++)
    1491          {
    1492             uint32_t idx = row * 16 + col;
    1493             uint8_t u8 = pv[idx];
    1494             if (idx >= cb)
    1495                 Log((" "));
    1496             else
    1497                 Log(("%c", u8 >= 0x20 && u8 <= 0x7e ? u8 : '.'));
    1498          }
     1488         for (uint32_t idx = row * 16; idx < row * 16 + 16; idx++)
     1489            Log(("%c", (idx >= cb) ? ' ' : (pv[idx] >= 0x20 && pv[idx] <= 0x7e ? pv[idx] : '.')));
    14991490         Log(("\n"));
    15001491    }
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