VirtualBox

Changeset 23830 in vbox


Ignore:
Timestamp:
Oct 16, 2009 7:48:17 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
53587
Message:

#3987: Virtio: Reset, feature negotiation, notification control.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevVirtioNet.cpp

    r23578 r23830  
    5252//- TODO: Move to Virtio.h ----------------------------------------------------
    5353
    54 #define VPCI_F_NOTIFY_ON_EMPTY 0x1000000
     54#define VPCI_F_NOTIFY_ON_EMPTY 0x01000000
     55#define VPCI_F_BAD_FEATURE     0x40000000
    5556
    5657#define VRINGDESC_MAX_SIZE (2 * 1024 * 1024)
     
    6869typedef VRINGDESC *PVRINGDESC;
    6970
    70 #define VRINGAVAIL_F_NO_NOTIFY 0x01
     71#define VRINGAVAIL_F_NO_INTERRUPT 0x01
    7172
    7273struct VRingAvail
     
    8586typedef struct VRingUsedElem VRINGUSEDELEM;
    8687
    87 #define VRINGUSED_F_NO_INTERRUPT 0x01
     88#define VRINGUSED_F_NO_NOTIFY 0x01
    8889
    8990struct VRingUsed
     
    191192RT_C_DECLS_BEGIN
    192193PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pState);
     194PDMBOTHCBDECL(uint32_t) vnetGetHostMinimalFeatures(void *pState);
     195PDMBOTHCBDECL(void)     vnetSetHostFeatures(void *pState, uint32_t uFeatures);
    193196PDMBOTHCBDECL(int)      vnetGetConfig(void *pState, uint32_t port, uint32_t cb, void *data);
    194197PDMBOTHCBDECL(int)      vnetSetConfig(void *pState, uint32_t port, uint32_t cb, void *data);
     
    212215    const char *pcszNameFmt;
    213216    uint32_t  (*pfnGetHostFeatures)(void *pvState);
     217    uint32_t  (*pfnGetHostMinimalFeatures)(void *pvState);
     218    void      (*pfnSetHostFeatures)(void *pvState, uint32_t uFeatures);
    214219    int       (*pfnGetConfig)(void *pvState, uint32_t port, uint32_t cb, void *data);
    215220    int       (*pfnSetConfig)(void *pvState, uint32_t port, uint32_t cb, void *data);
     
    223228    { /* Virtio Network Device */
    224229        0x1AF4, 0x1000, 0x1AF4, 1 + VIRTIO_NET_ID, 0x0200, 3, "virtio-net", "vnet%d",
    225         vnetGetHostFeatures, vnetGetConfig, vnetSetConfig, vnetReset
     230        vnetGetHostFeatures, vnetGetHostMinimalFeatures, vnetSetHostFeatures,
     231        vnetGetConfig, vnetSetConfig, vnetReset
    226232#ifdef DEBUG
    227233        , vnetGetQueueName
     
    230236    { /* Virtio Block Device */
    231237        0x1AF4, 0x1001, 0x1AF4, 1 + VIRTIO_BLK_ID, 0x0180, 2, "virtio-blk", "vblk%d",
    232         NULL, NULL, NULL, NULL
     238        NULL, NULL, NULL, NULL, NULL, NULL
    233239#ifdef DEBUG
    234240        , NULL
     
    278284    pQueue->uNextAvailIndex       = 0;
    279285    pQueue->uNextUsedIndex        = 0;
     286    pQueue->uPageNumber           = 0;
    280287}
    281288
     
    324331}
    325332
    326 static uint16_t vringReadAvail(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex)
     333uint16_t vringReadAvail(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex)
    327334{
    328335    uint16_t tmp;
     
    332339                      &tmp, sizeof(tmp));
    333340    return tmp;
     341}
     342
     343uint16_t vringReadAvailFlags(PVPCISTATE pState, PVRING pVRing)
     344{
     345    uint16_t tmp;
     346   
     347    PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns),
     348                      pVRing->addrAvail + RT_OFFSETOF(VRINGAVAIL, uFlags),
     349                      &tmp, sizeof(tmp));
     350    return tmp;
     351}
     352
     353DECLINLINE(void) vringSetNotification(PVPCISTATE pState, PVRING pVRing, bool fEnabled)
     354{
     355    uint16_t tmp;
     356   
     357    PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns),
     358                      pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, uFlags),
     359                      &tmp, sizeof(tmp));
     360
     361    if (fEnabled)
     362        tmp &= ~ VRINGUSED_F_NO_NOTIFY;
     363    else
     364        tmp |= VRINGUSED_F_NO_NOTIFY;
     365
     366    PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns),
     367                       pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, uFlags),
     368                       &tmp, sizeof(tmp));
    334369}
    335370
     
    430465void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue)
    431466{
    432     int rc = vpciRaiseInterrupt(pState, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE);
    433     if (RT_FAILURE(rc))
    434         Log(("%s vqueueNotify: Failed to raise an interrupt (%Vrc).\n", INSTANCE(pState), rc));
     467    LogFlow(("%s vqueueNotify: %s availFlags=%x guestFeatures=%x vqueue is %sempty\n",
     468             INSTANCE(pState), QUEUENAME(pState, pQueue),
     469             vringReadAvailFlags(pState, &pQueue->VRing),
     470             pState->uGuestFeatures, vqueueIsEmpty(pState, pQueue)?"":"not "));
     471    if (!(vringReadAvailFlags(pState, &pQueue->VRing) & VRINGAVAIL_F_NO_INTERRUPT)
     472        || ((pState->uGuestFeatures & VPCI_F_NOTIFY_ON_EMPTY) && vqueueIsEmpty(pState, pQueue)))
     473    {
     474        int rc = vpciRaiseInterrupt(pState, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE);
     475        if (RT_FAILURE(rc))
     476            Log(("%s vqueueNotify: Failed to raise an interrupt (%Vrc).\n", INSTANCE(pState), rc));
     477    }
    435478}
    436479
     
    493536        return rc;
    494537
     538    LogFlow(("%s vpciRaiseInterrupt: u8IntCause=%x\n",
     539             INSTANCE(pState), u8IntCause));
     540
    495541    pState->uISR |= u8IntCause;
    496542    PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 1);
     
    506552PDMBOTHCBDECL(void) vpciLowerInterrupt(VPCISTATE *pState)
    507553{
     554    LogFlow(("%s vpciLowerInterrupt\n", INSTANCE(pState)));
    508555    PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 0);
     556}
     557
     558DECLINLINE(uint32_t) vpciGetHostFeatures(PVPCISTATE pState)
     559{
     560    return g_VPCIDevices[pState->enmDevType].pfnGetHostFeatures(pState)
     561        | VPCI_F_NOTIFY_ON_EMPTY;
    509562}
    510563
     
    534587        case VPCI_HOST_FEATURES:
    535588            /* Tell the guest what features we support. */
    536             *pu32 = g_VPCIDevices[pState->enmDevType].pfnGetHostFeatures(pState);
     589            *pu32 = vpciGetHostFeatures(pState) | VPCI_F_BAD_FEATURE;
    537590            break;
    538591
     
    609662    {
    610663        case VPCI_GUEST_FEATURES:
    611             // TODO: Feature negotiation code goes here.
    612             // The guest may potentially desire features we don't support!
    613             pState->uGuestFeatures = u32;
     664            /* Check if the guest negotiates properly, fall back to basics if it does not. */
     665            if (VPCI_F_BAD_FEATURE & u32)
     666            {
     667                Log(("%s Guest failed to negotiate properly! (guest=%x)\n",
     668                     INSTANCE(pState), u32));
     669                pState->uGuestFeatures = g_VPCIDevices[pState->enmDevType].pfnGetHostMinimalFeatures(pState);
     670            }
     671            /* The guest may potentially desire features we don't support! */
     672            else if (~vpciGetHostFeatures(pState) & u32)
     673            {
     674                Log(("%s Guest asked for features host does not support! (host=%x guest=%x)\n",
     675                     INSTANCE(pState), vpciGetHostFeatures(pState), u32));
     676                pState->uGuestFeatures = vpciGetHostFeatures(pState);
     677            }
     678            else
     679                pState->uGuestFeatures = u32;
     680            g_VPCIDevices[pState->enmDevType].pfnSetHostFeatures(pState, pState->uGuestFeatures);
    614681            break;
    615682
     
    11271194}
    11281195
     1196PDMBOTHCBDECL(uint32_t) vnetGetHostMinimalFeatures(void *pvState)
     1197{
     1198    return VNET_F_MAC;
     1199}
     1200
     1201PDMBOTHCBDECL(void) vnetSetHostFeatures(void *pvState, uint32_t uFeatures)
     1202{
     1203    // TODO: Nothing to do here yet
     1204    VNETSTATE *pState = (VNETSTATE *)pvState;
     1205    LogFlow(("%s vnetSetHostFeatures: uFeatures=%x\n", INSTANCE(pState), uFeatures));
     1206}
     1207
    11291208PDMBOTHCBDECL(int) vnetGetConfig(void *pvState, uint32_t port, uint32_t cb, void *data)
    11301209{
     
    12171296 * This must be called before the pfnRecieve() method is called.
    12181297 *
     1298 * @remarks As a side effect this function enables queue notification
     1299 *          if it cannot receive because the queue is empty.
     1300 *          It disables notification if it can receive.
     1301 *
    12191302 * @returns VERR_NET_NO_BUFFER_SPACE if it cannot.
    12201303 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     
    12231306static int vnetCanReceive(VNETSTATE *pState)
    12241307{
     1308    int rc;
    12251309    LogFlow(("%s vnetCanReceive\n", INSTANCE(pState)));
    1226     int rc = (vqueueIsReady(&pState->VPCI, pState->pRxQueue)
    1227             && !vqueueIsEmpty(&pState->VPCI, pState->pRxQueue))
    1228         ? VINF_SUCCESS : VERR_NET_NO_BUFFER_SPACE;
    1229     LogFlow(("%s vnetCanReceive -> %d\n", INSTANCE(pState), rc));
     1310    if (!(pState->VPCI.uStatus & VPCI_STATUS_DRV_OK))
     1311        rc = VERR_NET_NO_BUFFER_SPACE;
     1312    else if (!vqueueIsReady(&pState->VPCI, pState->pRxQueue))
     1313        rc = VERR_NET_NO_BUFFER_SPACE;
     1314    else if (vqueueIsEmpty(&pState->VPCI, pState->pRxQueue))
     1315    {
     1316        vringSetNotification(&pState->VPCI, &pState->pRxQueue->VRing, true);
     1317        rc = VERR_NET_NO_BUFFER_SPACE;
     1318    }
     1319    else
     1320    {
     1321        vringSetNotification(&pState->VPCI, &pState->pRxQueue->VRing, false);
     1322        rc = VINF_SUCCESS;
     1323    }
     1324
     1325    LogFlow(("%s vnetCanReceive -> %Vrc\n", INSTANCE(pState), rc));
    12301326    return rc;
    12311327}
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