VirtualBox

Changeset 58390 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Oct 23, 2015 12:35:35 PM (9 years ago)
Author:
vboxsync
Message:

VMM/GIM: Implement Hyper-V debug receive thread optimization. Added a few statistics to GIM.
Fixed a bug in Windows guests' debug DHCP handling.

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GIM.cpp

    r58283 r58390  
    5959
    6060#include <iprt/err.h>
     61#include <iprt/semaphore.h>
    6162#include <iprt/string.h>
    6263
     
    167168            rc = VMR3SetError(pVM->pUVM, VERR_GIM_INVALID_PROVIDER, RT_SRC_POS, "Provider '%s' unknown.", szProvider);
    168169    }
     170
     171    /*
     172     * Statistics.
     173     */
     174    STAM_REL_REG_USED(pVM, &pVM->gim.s.StatDbgXmit,      STAMTYPE_COUNTER, "/GIM/Debug/Transmit",      STAMUNIT_OCCURENCES, "Debug packets sent.");
     175    STAM_REL_REG_USED(pVM, &pVM->gim.s.StatDbgXmitBytes, STAMTYPE_COUNTER, "/GIM/Debug/TransmitBytes", STAMUNIT_OCCURENCES, "Debug bytes sent.");
     176    STAM_REL_REG_USED(pVM, &pVM->gim.s.StatDbgRecv,      STAMTYPE_COUNTER, "/GIM/Debug/Receive",       STAMUNIT_OCCURENCES, "Debug packets received.");
     177    STAM_REL_REG_USED(pVM, &pVM->gim.s.StatDbgRecvBytes, STAMTYPE_COUNTER, "/GIM/Debug/ReceiveBytes",  STAMUNIT_OCCURENCES, "Debug bytes received.");
     178
     179    STAM_REL_REG_USED(pVM, &pVM->gim.s.StatHypercalls,   STAMTYPE_COUNTER, "/GIM/Hypercalls",          STAMUNIT_OCCURENCES, "Number of hypercalls performed.");
    169180    return rc;
    170181}
     
    415426 * @param   pVM             The cross context VM structure.
    416427 * @param   pDevIns         Pointer to the GIM device instance.
    417  * @param   pDebugStream    Pointer to the GIM device debug connection, can be
     428 * @param   pDbg            Pointer to the GIM device debug structure, can be
    418429 *                          NULL.
    419430 */
    420 VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns, PPDMISTREAM pDebugStream)
     431VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns, PGIMDEBUG pDbg)
    421432{
    422433    pVM->gim.s.pDevInsR3 = pDevIns;
    423     pVM->gim.s.pDebugStreamR3 = pDebugStream;
     434    pVM->gim.s.pDbgR3    = pDbg;
     435}
     436
     437
     438/**
     439 * Gets debug setup specified by the provider.
     440 *
     441 * @returns VBox status code.
     442 * @param   pVM             The cross context VM structure.
     443 * @param   pDevIns         Where to store the debug setup details.
     444 */
     445VMMR3DECL(int) GIMR3GetDebugSetup(PVM pVM, PGIMDEBUGSETUP pDbgSetup)
     446{
     447    AssertReturn(pVM, VERR_INVALID_PARAMETER);
     448    AssertReturn(pDbgSetup, VERR_INVALID_PARAMETER);
     449
     450    switch (pVM->gim.s.enmProviderId)
     451    {
     452        case GIMPROVIDERID_HYPERV:
     453            return gimR3HvGetDebugSetup(pVM, pDbgSetup);
     454        default:
     455            break;
     456    }
     457    return VERR_GIM_NO_DEBUG_CONNECTION;
    424458}
    425459
     
    430464 * @returns VBox status code.
    431465 *
    432  * @param   pVM         The cross context VM structure.
    433  * @param   pvRead      The read buffer.
    434  * @param   pcbRead     The size of the read buffer as well as where to store
    435  *                      the number of bytes read.
     466 * @param   pVM                 The cross context VM structure.
     467 * @param   pvRead              The read buffer.
     468 * @param   pcbRead             The size of the read buffer as well as where to store
     469 *                              the number of bytes read.
     470 * @param   pfnReadComplete     Callback when the buffer has been read and
     471 *                              before signaling reading of the next buffer.
     472 *                              Optional, can be NULL.
    436473 * @thread  EMT.
    437474 */
    438 VMMR3_INT_DECL(int) GIMR3DebugRead(PVM pVM, void *pvRead, size_t *pcbRead)
    439 {
    440     PPDMISTREAM pDebugStream = pVM->gim.s.pDebugStreamR3;
    441     if (pDebugStream)
    442         return pDebugStream->pfnRead(pDebugStream, pvRead, pcbRead);
     475VMMR3_INT_DECL(int) GIMR3DebugRead(PVM pVM, void *pvRead, size_t *pcbRead, PFNGIMDEBUGBUFREADCOMPLETED pfnReadComplete)
     476{
     477    PGIMDEBUG pDbg = pVM->gim.s.pDbgR3;
     478    if (pDbg)
     479    {
     480        if (ASMAtomicReadBool(&pDbg->fDbgRecvBufRead) == true)
     481        {
     482            STAM_COUNTER_INC(&pVM->gim.s.StatDbgRecv);
     483            STAM_COUNTER_ADD(&pVM->gim.s.StatDbgRecvBytes, pDbg->cbDbgRecvBufRead);
     484
     485            memcpy(pvRead, pDbg->pvDbgRecvBuf, pDbg->cbDbgRecvBufRead);
     486            *pcbRead = pDbg->cbDbgRecvBufRead;
     487            if (pfnReadComplete)
     488                pfnReadComplete(pVM);
     489            RTSemEventMultiSignal(pDbg->hDbgRecvThreadSem);
     490            ASMAtomicWriteBool(&pDbg->fDbgRecvBufRead, false);
     491            return VINF_SUCCESS;
     492        }
     493        else
     494            *pcbRead = 0;
     495        return VERR_NO_DATA;
     496    }
    443497    return VERR_GIM_NO_DEBUG_CONNECTION;
    444498}
     
    458512VMMR3_INT_DECL(int) GIMR3DebugWrite(PVM pVM, void *pvWrite, size_t *pcbWrite)
    459513{
    460     PPDMISTREAM pDebugStream = pVM->gim.s.pDebugStreamR3;
    461     if (pDebugStream)
    462         return pDebugStream->pfnWrite(pDebugStream, pvWrite, pcbWrite);
     514    PGIMDEBUG pDbg = pVM->gim.s.pDbgR3;
     515    if (pDbg)
     516    {
     517        PPDMISTREAM pDbgStream = pDbg->pDbgDrvStream;
     518        if (pDbgStream)
     519        {
     520            size_t cbWrite = *pcbWrite;
     521            int rc = pDbgStream->pfnWrite(pDbgStream, pvWrite, pcbWrite);
     522            if (   RT_SUCCESS(rc)
     523                && *pcbWrite == cbWrite)
     524            {
     525                STAM_COUNTER_INC(&pVM->gim.s.StatDbgXmit);
     526                STAM_COUNTER_ADD(&pVM->gim.s.StatDbgXmitBytes, *pcbWrite);
     527            }
     528            return rc;
     529        }
     530    }
    463531    return VERR_GIM_NO_DEBUG_CONNECTION;
    464532}
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r58337 r58390  
    3737#include <VBox/vmm/pdmapi.h>
    3838#include <VBox/version.h>
     39#ifdef DEBUG_ramshankar
     40# include <iprt/udp.h>
     41#endif
    3942
    4043
     
    175178static int    gimR3HvInitHypercallSupport(PVM pVM);
    176179static void   gimR3HvTermHypercallSupport(PVM pVM);
     180static int    gimR3HvInitDebugSupport(PVM pVM);
     181static void   gimR3HvTermDebugSupport(PVM pVM);
    177182
    178183
     
    203208        rc = CFGMR3ValidateConfig(pCfgHv, "/HyperV/",
    204209                                  "VendorID"
    205                                   "|VSInterface",
     210                                  "|VSInterface"
     211                                  "|HypercallDebugInterface",
    206212                                  "" /* pszValidNodes */, "GIM/HyperV" /* pszWho */, 0 /* uInstance */);
    207213        if (RT_FAILURE(rc))
     
    218224    if (!RTStrNCmp(szVendor, GIM_HV_VENDOR_MICROSOFT, sizeof(GIM_HV_VENDOR_MICROSOFT) - 1))
    219225    {
    220         LogRel(("GIM: HyperV: Warning! Posing as the Microsoft vendor, guest behavior may be altered!\n"));
     226        LogRel(("GIM: HyperV: Warning! Posing as the Microsoft vendor may alter guest behaviour!\n"));
    221227        pHv->fIsVendorMsHv = true;
    222228    }
     
    227233         * The Microsoft virtualization service interface (debugging). */
    228234        rc = CFGMR3QueryBoolDef(pCfgHv, "VSInterface", &pHv->fIsInterfaceVs, true);
     235        AssertLogRelRCReturn(rc, rc);
     236
     237        /** @cfgm{/GIM/HyperV/HypercallDebugInterface, bool, true}
     238         * Whether we specify the guest to use hypercalls for debugging rather than MSRs. */
     239        rc = CFGMR3QueryBoolDef(pCfgHv, "HypercallDebugInterface", &pHv->fDbgHypercallInterface, true);
    229240        AssertLogRelRCReturn(rc, rc);
    230241    }
     
    438449    AssertLogRelRCReturn(rc, rc);
    439450
     451    /*
     452     * Setup debug support.
     453     */
     454    rc = gimR3HvInitDebugSupport(pVM);
     455    AssertLogRelRCReturn(rc, rc);
     456
    440457    return VINF_SUCCESS;
    441458}
     
    559576     * Reset MSRs.
    560577     */
    561     pHv->u64GuestOsIdMsr        = 0;
    562     pHv->u64HypercallMsr        = 0;
    563     pHv->u64TscPageMsr          = 0;
    564     pHv->uCrashP0Msr            = 0;
    565     pHv->uCrashP1Msr            = 0;
    566     pHv->uCrashP2Msr            = 0;
    567     pHv->uCrashP3Msr            = 0;
    568     pHv->uCrashP4Msr            = 0;
    569     pHv->uDebugStatusMsr        = 0;
    570     pHv->uDebugPendingBufferMsr = 0;
    571     pHv->uDebugSendBufferMsr    = 0;
    572     pHv->uDebugRecvBufferMsr    = 0;
     578    pHv->u64GuestOsIdMsr      = 0;
     579    pHv->u64HypercallMsr      = 0;
     580    pHv->u64TscPageMsr        = 0;
     581    pHv->uCrashP0Msr          = 0;
     582    pHv->uCrashP1Msr          = 0;
     583    pHv->uCrashP2Msr          = 0;
     584    pHv->uCrashP3Msr          = 0;
     585    pHv->uCrashP4Msr          = 0;
     586    pHv->uDbgStatusMsr        = 0;
     587    pHv->uDbgPendingBufferMsr = 0;
     588    pHv->uDbgSendBufferMsr    = 0;
     589    pHv->uDbgRecvBufferMsr    = 0;
    573590    for (VMCPUID i = 0; i < pVM->cCpus; i++)
    574591    {
     
    595612    Assert(*pcRegions <= UINT8_MAX);    /* See PGMR3PhysMMIO2Register(). */
    596613    return pHv->aMmio2Regions;
     614}
     615
     616
     617/**
     618 * Callback for when debug data is available over the debugger connection.
     619 *
     620 * @param pVM       The cross context VM structure.
     621 */
     622static DECLCALLBACK(void) gimR3HvDebugBufAvail(PVM pVM)
     623{
     624    PGIMHV   pHv = &pVM->gim.s.u.Hv;
     625    RTGCPHYS GCPhysPendingBuffer = pHv->uDbgPendingBufferMsr;
     626    if (   GCPhysPendingBuffer
     627        && PGMPhysIsGCPhysNormal(pVM, GCPhysPendingBuffer))
     628    {
     629        uint8_t bPendingData = 1;
     630        int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysPendingBuffer, &bPendingData, sizeof(bPendingData));
     631        if (RT_FAILURE(rc))
     632        {
     633            LogRelMax(5, ("GIM: HyperV: Failed to set pending debug receive buffer at %#RGp, rc=%Rrc\n", GCPhysPendingBuffer,
     634                          rc));
     635        }
     636    }
     637}
     638
     639
     640/**
     641 * Callback for when debug data has been read from the debugger connection.
     642 *
     643 * This will be invoked before signalling read of the next debug buffer.
     644 *
     645 * @param pVM       The cross context VM structure.
     646 */
     647static DECLCALLBACK(void) gimR3HvDebugBufReadCompleted(PVM pVM)
     648{
     649    PGIMHV   pHv = &pVM->gim.s.u.Hv;
     650    RTGCPHYS GCPhysPendingBuffer = pHv->uDbgPendingBufferMsr;
     651    if (   GCPhysPendingBuffer
     652        && PGMPhysIsGCPhysNormal(pVM, GCPhysPendingBuffer))
     653    {
     654        uint8_t bPendingData = 0;
     655        int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysPendingBuffer, &bPendingData, sizeof(bPendingData));
     656        if (RT_FAILURE(rc))
     657        {
     658            LogRelMax(5, ("GIM: HyperV: Failed to clear pending debug receive buffer at %#RGp, rc=%Rrc\n", GCPhysPendingBuffer,
     659                          rc));
     660        }
     661    }
     662}
     663
     664
     665/**
     666 * Get Hyper-V debug setup parameters.
     667 *
     668 * @returns VBox status code.
     669 * @param   pVM         The cross context VM structure.
     670 * @param   pDbgSetup   Where to store the debug setup details.
     671 */
     672VMMR3_INT_DECL(int) gimR3HvGetDebugSetup(PVM pVM, PGIMDEBUGSETUP pDbgSetup)
     673{
     674    Assert(pDbgSetup);
     675    PGIMHV pHv = &pVM->gim.s.u.Hv;
     676    if (pHv->fDbgEnabled)
     677    {
     678        pDbgSetup->pfnDbgRecvBufAvail = gimR3HvDebugBufAvail;
     679        pDbgSetup->cbDbgRecvBuf       = GIM_HV_PAGE_SIZE;
     680        return VINF_SUCCESS;
     681    }
     682    return VERR_GIM_NO_DEBUG_CONNECTION;
    597683}
    598684
     
    663749     * Save debug support data.
    664750     */
    665     SSMR3PutU64(pSSM, pcHv->uDebugPendingBufferMsr);
    666     SSMR3PutU64(pSSM, pcHv->uDebugSendBufferMsr);
    667     SSMR3PutU64(pSSM, pcHv->uDebugRecvBufferMsr);
    668     SSMR3PutU64(pSSM, pcHv->uDebugStatusMsr);
    669     SSMR3PutU32(pSSM, pcHv->enmDebugReply);
    670     SSMR3PutU32(pSSM, pcHv->uBootpXId);
     751    SSMR3PutU64(pSSM, pcHv->uDbgPendingBufferMsr);
     752    SSMR3PutU64(pSSM, pcHv->uDbgSendBufferMsr);
     753    SSMR3PutU64(pSSM, pcHv->uDbgRecvBufferMsr);
     754    SSMR3PutU64(pSSM, pcHv->uDbgStatusMsr);
     755    SSMR3PutU32(pSSM, pcHv->enmDbgReply);
     756    SSMR3PutU32(pSSM, pcHv->uDbgBootpXId);
    671757    SSMR3PutU32(pSSM, pcHv->DbgGuestIp4Addr.u);
    672758
     
    792878    if (uHvSavedStatVersion > GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG)
    793879    {
    794         SSMR3GetU64(pSSM, &pHv->uDebugPendingBufferMsr);
    795         SSMR3GetU64(pSSM, &pHv->uDebugSendBufferMsr);
    796         SSMR3GetU64(pSSM, &pHv->uDebugRecvBufferMsr);
    797         SSMR3GetU64(pSSM, &pHv->uDebugStatusMsr);
    798         SSMR3GetU32(pSSM, (uint32_t *)&pHv->enmDebugReply);
    799         SSMR3GetU32(pSSM, &pHv->uBootpXId);
     880        SSMR3GetU64(pSSM, &pHv->uDbgPendingBufferMsr);
     881        SSMR3GetU64(pSSM, &pHv->uDbgSendBufferMsr);
     882        SSMR3GetU64(pSSM, &pHv->uDbgRecvBufferMsr);
     883        SSMR3GetU64(pSSM, &pHv->uDbgStatusMsr);
     884        SSMR3GetU32(pSSM, (uint32_t *)&pHv->enmDbgReply);
     885        SSMR3GetU32(pSSM, &pHv->uDbgBootpXId);
    800886        rc = SSMR3GetU32(pSSM, &pHv->DbgGuestIp4Addr.u);
    801887        AssertRCReturn(rc, rc);
     
    11371223
    11381224/**
     1225 * Initializes Hyper-V guest debug support.
     1226 *
     1227 * @returns VBox status code.
     1228 * @param   pVM     The cross context VM structure.
     1229 */
     1230static int gimR3HvInitDebugSupport(PVM pVM)
     1231{
     1232    PGIMHV pHv = &pVM->gim.s.u.Hv;
     1233    if (   (pHv->uPartFlags & GIM_HV_PART_FLAGS_DEBUGGING)
     1234        || pHv->fIsInterfaceVs)
     1235    {
     1236        pHv->fDbgEnabled = true;
     1237        pHv->pvDbgBuffer = RTMemAllocZ(PAGE_SIZE);
     1238        if (!pHv->pvDbgBuffer)
     1239            return VERR_NO_MEMORY;
     1240    }
     1241    return VINF_SUCCESS;
     1242}
     1243
     1244
     1245/**
     1246 * Terminates Hyper-V guest debug support.
     1247 *
     1248 * @param   pVM     The cross context VM structure.
     1249 */
     1250static void gimR3HvTermDebugSupport(PVM pVM)
     1251{
     1252    PGIMHV pHv = &pVM->gim.s.u.Hv;
     1253    if (pHv->pvDbgBuffer)
     1254    {
     1255        RTMemFree(pHv->pvDbgBuffer);
     1256        pHv->pvDbgBuffer = NULL;
     1257    }
     1258}
     1259
     1260
     1261/**
    11391262 * Reads data from a debugger connection, asynchronous.
    11401263 *
     
    11651288         */
    11661289        size_t cbReallyRead = cbRead;
    1167         rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead);
     1290        rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead, gimR3HvDebugBufReadCompleted);
    11681291        *pcbRead = (uint32_t)cbReallyRead;
    11691292    }
     
    11751298        PGIMHV pHv = &pVM->gim.s.u.Hv;
    11761299        rc = VERR_GIM_IPE_1;
    1177         switch (pHv->enmDebugReply)
     1300        switch (pHv->enmDbgReply)
    11781301        {
    11791302            case GIMHVDEBUGREPLY_UDP:
    11801303            {
    11811304                size_t cbReallyRead = cbRead;
    1182                 rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead);
     1305                rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead, gimR3HvDebugBufReadCompleted);
    11831306                if (   RT_SUCCESS(rc)
    11841307                    && cbReallyRead > 0)
     
    12171340                        pIpHdr->ip_sum     = RTNetIPv4HdrChecksum(pIpHdr);
    12181341                        /* UDP */
     1342                        pUdpHdr->uh_dport  = pHv->uUdpGuestSrcPort;
     1343                        pUdpHdr->uh_sport  = pHv->uUdpGuestDstPort;
    12191344                        pUdpHdr->uh_ulen   = RT_H2N_U16_C((uint16_t)cbReallyRead + sizeof(*pUdpHdr));
    12201345
     
    12421367                    rc = VINF_SUCCESS;
    12431368                    *pcbRead = cbArpReplyPkt;
    1244                     pHv->enmDebugReply = GIMHVDEBUGREPLY_ARP_REPLY_SENT;
     1369                    pHv->enmDbgReply = GIMHVDEBUGREPLY_ARP_REPLY_SENT;
    12451370                }
    12461371                else
     
    12621387                    PRTNETUDP      pUdpHdr   = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
    12631388                    PRTNETBOOTP    pBootpHdr = (PRTNETBOOTP)   (pUdpHdr + 1);
    1264                     pBootpHdr->bp_xid = pHv->uBootpXId;
     1389                    pBootpHdr->bp_xid = pHv->uDbgBootpXId;
    12651390
    12661391                    rc = VINF_SUCCESS;
    12671392                    *pcbRead = cbDhcpOfferPkt;
    1268                     pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_OFFER_SENT;
     1393                    pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_OFFER_SENT;
    12691394                    LogRel(("GIM: HyperV: Debug DHCP offered IP address %RTnaipv4, transaction Id %#x\n", pBootpHdr->bp_yiaddr,
    1270                             RT_N2H_U32(pHv->uBootpXId)));
     1395                            RT_N2H_U32(pHv->uDbgBootpXId)));
    12711396                }
    12721397                else
     
    12881413                    PRTNETUDP      pUdpHdr   = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
    12891414                    PRTNETBOOTP    pBootpHdr = (PRTNETBOOTP)   (pUdpHdr + 1);
    1290                     pBootpHdr->bp_xid = pHv->uBootpXId;
     1415                    pBootpHdr->bp_xid = pHv->uDbgBootpXId;
    12911416
    12921417                    rc = VINF_SUCCESS;
    12931418                    *pcbRead = cbDhcpAckPkt;
    1294                     pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_ACK_SENT;
     1419                    pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_ACK_SENT;
    12951420                    LogRel(("GIM: HyperV: Debug DHCP acknowledged IP address %RTnaipv4, transaction Id %#x\n",
    1296                             pBootpHdr->bp_yiaddr, RT_N2H_U32(pHv->uBootpXId)));
     1421                            pBootpHdr->bp_yiaddr, RT_N2H_U32(pHv->uDbgBootpXId)));
    12971422                }
    12981423                else
     
    13151440            default:
    13161441            {
    1317                 AssertMsgFailed(("GIM: HyperV: Invalid/unimplemented debug reply type %u\n", pHv->enmDebugReply));
     1442                AssertMsgFailed(("GIM: HyperV: Invalid/unimplemented debug reply type %u\n", pHv->enmDbgReply));
    13181443                rc = VERR_INTERNAL_ERROR_2;
    13191444            }
    13201445        }
    13211446        Assert(rc != VERR_GIM_IPE_1);
    1322     }
     1447
     1448#ifdef DEBUG_ramshankar
     1449        if (   rc == VINF_SUCCESS
     1450            && *pcbRead > 0)
     1451        {
     1452            RTSOCKET hSocket;
     1453            int rc2 = RTUdpCreateClientSocket("localhost", 52000, NULL, &hSocket);
     1454            if (RT_SUCCESS(rc2))
     1455            {
     1456                size_t cbTmpWrite = *pcbRead;
     1457                RTSocketWriteNB(hSocket, pvBuf, *pcbRead, &cbTmpWrite); NOREF(cbTmpWrite);
     1458                RTSocketClose(hSocket);
     1459            }
     1460        }
     1461#endif
     1462    }
     1463
    13231464    return rc;
    13241465}
     
    13471488    if (fUdpPkt)
    13481489    {
     1490#ifdef DEBUG_ramshankar
     1491        RTSOCKET hSocket;
     1492        int rc2 = RTUdpCreateClientSocket("localhost", 52000, NULL, &hSocket);
     1493        if (RT_SUCCESS(rc2))
     1494        {
     1495            size_t cbTmpWrite = cbWrite;
     1496            RTSocketWriteNB(hSocket, pbData, cbWrite, &cbTmpWrite);  NOREF(cbTmpWrite);
     1497            RTSocketClose(hSocket);
     1498        }
     1499#endif
    13491500        /*
    13501501         * Windows guests sends us ethernet frames over the Hyper-V debug connection.
     
    13881539                             * Check for DHCP.
    13891540                             */
     1541                            bool fBuggyPkt = false;
    13901542                            size_t const cbUdpPkt = cbMaxIpPkt - cbIpHdr;
    13911543                            if (   pUdpHdr->uh_dport == RT_N2H_U16_C(RTNETIPV4_PORT_BOOTPS)
    1392                                 && pUdpHdr->uh_sport == RT_N2H_U16_C(RTNETIPV4_PORT_BOOTPC)
    1393                                 && cbMaxIpPkt >= cbIpHdr + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN)
     1544                                && pUdpHdr->uh_sport == RT_N2H_U16_C(RTNETIPV4_PORT_BOOTPC))
    13941545                            {
    13951546                                PCRTNETBOOTP pDhcpPkt = (PCRTNETBOOTP)(pUdpHdr + 1);
    13961547                                uint8_t bMsgType;
    1397                                 if (RTNetIPv4IsDHCPValid(pUdpHdr, pDhcpPkt, cbUdpPkt - sizeof(*pUdpHdr), &bMsgType))
     1548                                if (   cbMaxIpPkt >= cbIpHdr + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN
     1549                                    && RTNetIPv4IsDHCPValid(pUdpHdr, pDhcpPkt, cbUdpPkt - sizeof(*pUdpHdr), &bMsgType))
    13981550                                {
    13991551                                    switch (bMsgType)
    14001552                                    {
    14011553                                        case RTNET_DHCP_MT_DISCOVER:
    1402                                             pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_OFFER;
    1403                                             pHv->uBootpXId = pDhcpPkt->bp_xid;
     1554                                            pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_OFFER;
     1555                                            pHv->uDbgBootpXId = pDhcpPkt->bp_xid;
    14041556                                            break;
    14051557                                        case RTNET_DHCP_MT_REQUEST:
    1406                                             pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_ACK;
    1407                                             pHv->uBootpXId = pDhcpPkt->bp_xid;
     1558                                            pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_ACK;
     1559                                            pHv->uDbgBootpXId = pDhcpPkt->bp_xid;
    14081560                                            break;
    14091561                                        default:
     
    14121564                                            break;
    14131565                                    }
     1566                                    fIgnorePkt = true;
    14141567                                }
    1415                                 fIgnorePkt = true;
     1568                                else if (   pIp4Hdr->ip_src.u == GIMHV_DEBUGCLIENT_IPV4
     1569                                         && pIp4Hdr->ip_dst.u == 0)
     1570                                {
     1571                                    /*
     1572                                     * Windows 8.1 seems to be sending malformed BOOTP packets at the final stage of the
     1573                                     * debugger sequence. It appears that a previously sent DHCP request buffer wasn't cleared
     1574                                     * in the guest and they re-use it instead of sending a zero destination+source port packet
     1575                                     * as expected below.
     1576                                     *
     1577                                     * We workaround Microsoft's bug here, or at least, I'm classifying it as a bug to
     1578                                     * preserve my own sanity, see @bugref{8006#c54}.
     1579                                     */
     1580                                    fBuggyPkt = true;
     1581                                }
    14161582                            }
    1417                             else if (   !pUdpHdr->uh_dport
    1418                                      && !pUdpHdr->uh_sport)
     1583
     1584                            if (  (   !pUdpHdr->uh_dport
     1585                                   && !pUdpHdr->uh_sport)
     1586                                || fBuggyPkt)
    14191587                            {
    14201588                                /*
    14211589                                 * Extract the UDP payload and pass it to the debugger and record the guest IP address.
    1422                                  * Hyper-V sends UDP debugger packets with source and destination port as 0. If we don't
    1423                                  * filter out the ports here, we would receive BOOTP, NETBIOS and other UDP sub-protocol
    1424                                  * packets which the debugger yells as "Bad packet received from...".
     1590                                 *
     1591                                 * Hyper-V sends UDP debugger packets with source and destination port as 0 except in the
     1592                                 * aformentioned buggy case. The buggy packet case requires us to remember the ports and
     1593                                 * reply to them, otherwise the guest won't receive the replies we sent with port 0.
    14251594                                 */
    14261595                                uint32_t const cbFrameHdr = sizeof(RTNETETHERHDR) + cbIpHdr + sizeof(RTNETUDP);
    14271596                                pbData  += cbFrameHdr;
    14281597                                cbWrite -= cbFrameHdr;
    1429                                 pHv->DbgGuestIp4Addr = pIp4Hdr->ip_src;
    1430                                 pHv->enmDebugReply   = GIMHVDEBUGREPLY_UDP;
     1598                                pHv->DbgGuestIp4Addr.u = pIp4Hdr->ip_src.u;
     1599                                pHv->uUdpGuestDstPort  = pUdpHdr->uh_dport;
     1600                                pHv->uUdpGuestSrcPort  = pUdpHdr->uh_sport;
     1601                                pHv->enmDbgReply       = GIMHVDEBUGREPLY_UDP;
    14311602                            }
    14321603                            else
    14331604                            {
    1434                                 LogFlow(("GIM: HyperV: Ignoring UDP packet not src and dst port 0\n"));
     1605                                LogFlow(("GIM: HyperV: Ignoring UDP packet SourcePort=%u DstPort=%u\n", pUdpHdr->uh_sport,
     1606                                         pUdpHdr->uh_dport));
    14351607                                fIgnorePkt = true;
    14361608                            }
     
    14761648                            &&  pArpPkt->ar_tpa.u == GIMHV_DEBUGSERVER_IPV4)
    14771649                        {
    1478                             pHv->enmDebugReply = GIMHVDEBUGREPLY_ARP_REPLY;
     1650                            pHv->enmDbgReply = GIMHVDEBUGREPLY_ARP_REPLY;
    14791651                        }
    14801652                    }
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