VirtualBox

Changeset 80340 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Aug 19, 2019 7:43:37 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132801
Message:

Fixed error in MMIO handling of cfg gen check/increment. Seem to have resolved stack corruption issue caused by putting structs that allocated 1.5MB on the stack in temporary functions to test notification callback and test de-queing data. See bugref:9440 Comment #53 for more info

File:
1 edited

Legend:

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

    r80308 r80340  
    5454/** @} */
    5555
    56 #define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED \
     56#define VIRTIOSCSI_HOST_SCSI_ALL_FEATURES \
    5757            (VIRTIOSCSI_F_INOUT | VIRTIOSCSI_F_HOTPLUG | VIRTIOSCSI_F_CHANGE | VIRTIOSCSI_F_T10_PI)
    5858
     59#define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED       0            /**< TBD, support at least hotplug & in/out          */
     60
    5961/**
    6062 * TEMPORARY NOTE: following parameter is set to 1 for early development. Will be increased later
    6163 */
    6264#define VIRTIOSCSI_REQ_QUEUE_CNT                    1            /**< Number of req queues exposed by dev.            */
    63 #define VIRTIOSCSI_MAX_TARGETS                      1           /**< Can probably determined from higher layers      */
     65#define VIRTIOSCSI_QUEUE_CNT                        VIRTIOSCSI_REQ_QUEUE_CNT + 2
     66#define VIRTIOSCSI_MAX_TARGETS                      1            /**< Can probably determined from higher layers       */
    6467#define VIRTIOSCSI_MAX_LUN                          16383        /* < VirtIO specification, section 5.6.4             */
    6568#define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             64           /* < T.B.D. What is a good value for this?           */
     
    8386 * of req queues is variable and determined by virtio_scsi_config.num_queues. See VirtIO 1.0 spec section 5.6.4
    8487 */
    85 #define VIRTIOSCSI_CONTROLQ_IDX                     0            /* Index of control queue                            */
    86 #define VIRTIOSCSI_EVENTQ_IDX                       1            /* Index of event queue                              */
    87 #define VIRTIOSCSI_VIRTQ_REQ_BASE                   2            /* Base index of req queues                          */
    88 
    89 #define REQ_NBR_TO_QIDX(uReqQueueNum) (VIRTIOSCSI_VIRTQ_REQ_BASE + uReqQueueNum)
    90 #define REQ_QIDX_TO_NBR(qIdx)         (qIdx - VIRTIOSCSI_VIRTQ_REQ_BASE)
     88#define CONTROLQ_IDX                                0            /**< Spec-defined Index of control queue             */
     89#define EVENTQ_IDX                                  1            /**< Spec-defined Index of event queue               */
     90#define VIRTQ_REQ_BASE                              2            /**< Spec-defined base index of request queues       */
     91#define QUEUENAME(qIdx) (pVirtioScsi->szQueueNames[qIdx])        /**< Macro to get queue name from its index          */
     92
     93#define IS_REQ_QUEUE(qIdx) (   qIdx >= VIRTQ_REQ_BASE \
     94                            && qIdx < VIRTIOSCSI_QUEUE_CNT)
    9195/**
    9296 * The following struct is the VirtIO SCSI Host Device device-specific configuration described in section 5.6.4
     
    331335    VIRTIOSCSITARGET                aTargetInstances[VIRTIOSCSI_MAX_TARGETS];
    332336
     337    /** Instance name */
    333338    const char                      szInstance[16];
     339
     340    /** Device-specific spec-based VirtIO queuenames */
     341    const char                      szQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE];
     342
     343    /** Track which VirtIO queues we've attached to */
     344    bool                            fQueueAttached[VIRTIOSCSI_QUEUE_CNT];
    334345
    335346    /** Device base interface. */
    336347    PDMIBASE                        IBase;
    337 
    338348
    339349    /** Pointer to the device instance. - R3 ptr. */
     
    375385
    376386    VIRTIO_SCSI_CONFIG_T            virtioScsiConfig;
     387
    377388
    378389
     
    420431#define LOG_ACCESSOR(member) \
    421432        virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIO_SCSI_CONFIG_T, member), \
    422             pv, cb, uMemberOffset, fWrite, false, 0);
     433            pv, cb, uIntraOffset, fWrite, false, 0);
    423434
    424435#define SCSI_CONFIG_ACCESSOR(member) \
    425436    { \
    426         uint32_t uMemberOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \
     437        uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \
    427438        if (fWrite) \
    428             memcpy(((char *)&pVirtioScsi->virtioScsiConfig.member) + uMemberOffset, (const char *)pv, cb); \
     439            memcpy(((char *)&pVirtioScsi->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \
    429440        else \
    430             memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + uMemberOffset), cb); \
     441            memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + uIntraOffset), cb); \
    431442        LOG_ACCESSOR(member); \
    432443    }
     
    434445#define SCSI_CONFIG_ACCESSOR_READONLY(member) \
    435446    { \
    436         uint32_t uMemberOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \
     447        uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \
    437448        if (fWrite) \
    438449            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
    439450        else \
    440451        { \
    441             memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + uMemberOffset), cb); \
     452            memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + uIntraOffset), cb); \
    442453            LOG_ACCESSOR(member); \
    443454        } \
     
    468479#endif
    469480
     481
     482
     483static void virtioScsiHandleRequestq(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pszQueueName)
     484{
     485    LogFunc(("\n"));
     486
     487    PVIRTQ_BUF_VECTOR_T pBufVec = virtioQueueGetBuffer(hVirtio, qIdx);
     488    if (pBufVec == NULL)
     489    {
     490        Log(("\"%s\" not initialized\n", pszQueueName));
     491        return;
     492    }
     493
     494    int rc = virtioQueueGet(hVirtio, qIdx, true);
     495    if (rc == VERR_NOT_AVAILABLE)
     496    {
     497        Log2Func(("Request queue %s is empty\n", pszQueueName));
     498        return;
     499    }
     500
     501    AssertReturnVoid(rc == VINF_SUCCESS);
     502
     503    Log2Func(("Read request queue, %d segs in, %d segs out\n",
     504        pBufVec->cSegsIn, pBufVec->cSegsOut));
     505}
     506
     507static void virtioScsiHandleControlq(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pszQueueName)
     508{
     509
     510    LogFunc(    ("\n"));
     511
     512    PVIRTQ_BUF_VECTOR_T pBufVec = virtioQueueGetBuffer(hVirtio, qIdx);
     513    if (pBufVec == NULL)
     514    {
     515        Log(("\"%s\" not initialized\n", pszQueueName));
     516        return;
     517    }
     518
     519    int rc = virtioQueueGet(hVirtio, qIdx, true);
     520    if (rc == VERR_NOT_AVAILABLE)
     521    {
     522        Log2Func(("Control queue %s is empty\n", pszQueueName));
     523        return;
     524    }
     525
     526    AssertReturnVoid(rc == VINF_SUCCESS);
     527
     528    Log2Func(("Read control queue, %d segs in, %d segs out\n",
     529        pBufVec->cSegsIn, pBufVec->cSegsOut));
     530}
     531
     532static void virtioScsiHandleEventq(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pszQueueName)
     533{
     534    LogFunc(("\n"));
     535
     536    PVIRTQ_BUF_VECTOR_T pBufVec = virtioQueueGetBuffer(hVirtio, qIdx);
     537    if (pBufVec == NULL)
     538    {
     539        Log(("\"%s\" not initialized\n", pszQueueName));
     540        return;
     541    }
     542
     543    int rc = virtioQueueGet(hVirtio, qIdx, true);
     544    if (rc == VERR_NOT_AVAILABLE)
     545    {
     546        Log2Func(("Event queue %s is empty\n", pszQueueName));
     547        return;
     548    }
     549
     550    AssertReturnVoid(rc == VINF_SUCCESS);
     551
     552    Log2Func(("Read event queue, %d segs in, %d segs out\n",
     553        pBufVec->cSegsIn, pBufVec->cSegsOut));
     554}
     555
     556static DECLCALLBACK(void) virtioScsiQueueNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
     557{
     558    AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
     559    PVIRTIOSCSI pVirtioScsi = (PVIRTIOSCSI)pClient;
     560
     561    if (!pVirtioScsi->fQueueAttached[qIdx])
     562    {
     563        int rc = virtioQueueAttach(hVirtio, qIdx, QUEUENAME(qIdx));
     564        pVirtioScsi->fQueueAttached[qIdx] = (rc == VINF_SUCCESS);
     565        AssertReturnVoid(pVirtioScsi->fQueueAttached);
     566    }
     567
     568    Log2Func(("%s has available data\n", QUEUENAME(qIdx)));
     569
     570    if (qIdx == CONTROLQ_IDX)
     571        virtioScsiHandleControlq(hVirtio, qIdx, QUEUENAME(qIdx));
     572    else
     573    if (qIdx == EVENTQ_IDX)
     574        virtioScsiHandleEventq(hVirtio, qIdx, QUEUENAME(qIdx));
     575    else
     576    if (IS_REQ_QUEUE(qIdx))
     577        virtioScsiHandleRequestq(hVirtio, qIdx, QUEUENAME(qIdx));
     578}
     579
     580static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  bool fVirtioReady)
     581{
     582    Log2Func(("\n"));
     583    RT_NOREF(hVirtio);
     584    PVIRTIOSCSI pVirtioScsi = (PVIRTIOSCSI)pClient;
     585    if (fVirtioReady)
     586        Log2Func(("VirtIO ready\n"));
     587    else
     588    {
     589        Log2Func(("VirtIO is resetting\n"));
     590        for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
     591            pVirtioScsi->fQueueAttached[i] = false;
     592    }
     593}
     594
    470595/**
    471596 * Implementation invokes this to reset the VirtIO device
     
    476601    pVirtioScsi->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT;
    477602    virtioResetAll(pVirtioScsi->hVirtio);
    478 
    479603}
    480604
     
    540664}
    541665
    542 
    543 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, bool fVirtioReady)
    544 {
    545 #define MAX_QUEUENAME_SIZE 20
    546     Log2Func(("\n"));
    547     char pszQueueName[MAX_QUEUENAME_SIZE];
    548     if (fVirtioReady)
    549     {
    550         Log2Func(("VirtIO reports ready... Initializing queues\n"));
    551         virtioQueueAttach(hVirtio, VIRTIOSCSI_CONTROLQ_IDX, "controlq");
    552         virtioQueueAttach(hVirtio, VIRTIOSCSI_EVENTQ_IDX,   "eventq");
    553         for (uint16_t qIdx = VIRTIOSCSI_VIRTQ_REQ_BASE;
    554                       qIdx < VIRTIOSCSI_VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT;
    555                       qIdx++)
    556         {
    557             RTStrPrintf(pszQueueName, sizeof(pszQueueName), "requestq_%d", qIdx - 2);
    558             bool fEnabled = virtioQueueAttach(hVirtio, qIdx, (const char *)pszQueueName);
    559             if (!fEnabled)
    560                 break;
    561         }
    562     } else
    563         Log2Func(("VirtIO is resetting\n"));
    564 }
     666/**
     667 * virtio-scsi VirtIO Device-specific capabilities read callback
     668 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     669 *
     670 * @param   pDevIns     The device instance.
     671 * @param   uOffset     Offset within device specific capabilities struct
     672 * @param   pv          Buffer in which to save read data
     673 * @param   cb          Number of bytes to read
     674 */
     675static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
     676{
     677    int rc = VINF_SUCCESS;
     678    PVIRTIOSCSI  pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     679
     680//    LogFunc(("Read from Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",
     681//              uOffset, cb));
     682
     683    rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, false);
     684
     685    return rc;
     686}
     687
     688/**
     689 * virtio-scsi VirtIO Device-specific capabilities read callback
     690 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     691 *
     692 * @param   pDevIns     The device instance.
     693 * @param   uOffset     Offset within device specific capabilities struct
     694 * @param   pv          Buffer in which to save read data
     695 * @param   cb          Number of bytes to write
     696 */
     697static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
     698{
     699    int rc = VINF_SUCCESS;
     700    PVIRTIOSCSI  pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     701
     702//    LogFunc(("Write to Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",
     703//              uOffset, cb));
     704
     705    rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, true);
     706
     707    return rc;
     708}
     709
    565710
    566711/**
     
    9131058
    9141059
    915 static DECLCALLBACK(void) virtioScsiQueueNotified(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    916 {
    917     Log2Func(("virtio callback: %s has avail data\n", virtioQueueGetName(hVirtio, qIdx)));
    918 }
    919 
    920 /**
    921  * virtio-scsi VirtIO Device-specific capabilities read callback
    922  * (other VirtIO capabilities and features are handled in VirtIO implementation)
    923  *
    924  * @param   pDevIns     The device instance.
    925  * @param   uOffset     Offset within device specific capabilities struct
    926  * @param   pv          Buffer in which to save read data
    927  * @param   cb          Number of bytes to read
    928  */
    929 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
    930 {
    931     int rc = VINF_SUCCESS;
    932     PVIRTIOSCSI  pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    933 
    934 //    LogFunc(("Read from Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",
    935 //              uOffset, cb));
    936 
    937     rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, false);
    938 
    939     return rc;
    940 }
    941 
    942 /**
    943  * virtio-scsi VirtIO Device-specific capabilities read callback
    944  * (other VirtIO capabilities and features are handled in VirtIO implementation)
    945  *
    946  * @param   pDevIns     The device instance.
    947  * @param   uOffset     Offset within device specific capabilities struct
    948  * @param   pv          Buffer in which to save read data
    949  * @param   cb          Number of bytes to write
    950  */
    951 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
    952 {
    953     int rc = VINF_SUCCESS;
    954     PVIRTIOSCSI  pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    955 
    956 //    LogFunc(("Write to Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",
    957 //              uOffset, cb));
    958 
    959     rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, true);
    960 
    961     return rc;
    962 }
    963 
    964 
    9651060/**
    9661061 * Memory mapped I/O Handler for read operations.
     
    12031298    pThis->virtioScsiConfig.uMaxLun         = VIRTIOSCSI_MAX_LUN;
    12041299
    1205     rc = virtioConstruct(pDevIns, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,
     1300    rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,
    12061301                         VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED,
    12071302                         virtioScsiR3DevCapRead,
     
    12191314        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO"));
    12201315
     1316    RTStrCopy((char *)pThis->szQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
     1317    RTStrCopy((char *)pThis->szQueueNames[EVENTQ_IDX],   VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");
     1318    for (uint32_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
     1319        RTStrPrintf((char *)pThis->szQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE, "requestq_%d", qIdx);
    12211320
    12221321    rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_MEM_IO, 32,
     
    12741373        LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName));
    12751374
    1276         /* Attach this SCSI driver (upstream driver pre-determined statically outside this module) */
    12771375        AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
    12781376        rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszLunName);
     
    12811379            pTarget->fPresent = true;
    12821380
     1381            /* DrvSCSI.cpp currently implements the IMedia and IMediaEx interfaces, so those
     1382             * are the interfaces that will be used to pass SCSI requests down to the
     1383             * DrvSCSI driver to eventually make it down to the VD layer */
    12831384            pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA);
    12841385            AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
     
    13941495    PDM_DEVREG_VERSION
    13951496};
    1396 
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