Changeset 58390 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Oct 23, 2015 12:35:35 PM (9 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/GIM.cpp
r58283 r58390 59 59 60 60 #include <iprt/err.h> 61 #include <iprt/semaphore.h> 61 62 #include <iprt/string.h> 62 63 … … 167 168 rc = VMR3SetError(pVM->pUVM, VERR_GIM_INVALID_PROVIDER, RT_SRC_POS, "Provider '%s' unknown.", szProvider); 168 169 } 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."); 169 180 return rc; 170 181 } … … 415 426 * @param pVM The cross context VM structure. 416 427 * @param pDevIns Pointer to the GIM device instance. 417 * @param pD ebugStream Pointer to the GIM device debug connection, can be428 * @param pDbg Pointer to the GIM device debug structure, can be 418 429 * NULL. 419 430 */ 420 VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns, P PDMISTREAM pDebugStream)431 VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns, PGIMDEBUG pDbg) 421 432 { 422 433 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 */ 445 VMMR3DECL(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; 424 458 } 425 459 … … 430 464 * @returns VBox status code. 431 465 * 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. 436 473 * @thread EMT. 437 474 */ 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); 475 VMMR3_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 } 443 497 return VERR_GIM_NO_DEBUG_CONNECTION; 444 498 } … … 458 512 VMMR3_INT_DECL(int) GIMR3DebugWrite(PVM pVM, void *pvWrite, size_t *pcbWrite) 459 513 { 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 } 463 531 return VERR_GIM_NO_DEBUG_CONNECTION; 464 532 } -
trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
r58337 r58390 37 37 #include <VBox/vmm/pdmapi.h> 38 38 #include <VBox/version.h> 39 #ifdef DEBUG_ramshankar 40 # include <iprt/udp.h> 41 #endif 39 42 40 43 … … 175 178 static int gimR3HvInitHypercallSupport(PVM pVM); 176 179 static void gimR3HvTermHypercallSupport(PVM pVM); 180 static int gimR3HvInitDebugSupport(PVM pVM); 181 static void gimR3HvTermDebugSupport(PVM pVM); 177 182 178 183 … … 203 208 rc = CFGMR3ValidateConfig(pCfgHv, "/HyperV/", 204 209 "VendorID" 205 "|VSInterface", 210 "|VSInterface" 211 "|HypercallDebugInterface", 206 212 "" /* pszValidNodes */, "GIM/HyperV" /* pszWho */, 0 /* uInstance */); 207 213 if (RT_FAILURE(rc)) … … 218 224 if (!RTStrNCmp(szVendor, GIM_HV_VENDOR_MICROSOFT, sizeof(GIM_HV_VENDOR_MICROSOFT) - 1)) 219 225 { 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")); 221 227 pHv->fIsVendorMsHv = true; 222 228 } … … 227 233 * The Microsoft virtualization service interface (debugging). */ 228 234 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); 229 240 AssertLogRelRCReturn(rc, rc); 230 241 } … … 438 449 AssertLogRelRCReturn(rc, rc); 439 450 451 /* 452 * Setup debug support. 453 */ 454 rc = gimR3HvInitDebugSupport(pVM); 455 AssertLogRelRCReturn(rc, rc); 456 440 457 return VINF_SUCCESS; 441 458 } … … 559 576 * Reset MSRs. 560 577 */ 561 pHv->u64GuestOsIdMsr 562 pHv->u64HypercallMsr 563 pHv->u64TscPageMsr 564 pHv->uCrashP0Msr 565 pHv->uCrashP1Msr 566 pHv->uCrashP2Msr 567 pHv->uCrashP3Msr 568 pHv->uCrashP4Msr 569 pHv->uD ebugStatusMsr = 0;570 pHv->uD ebugPendingBufferMsr = 0;571 pHv->uD ebugSendBufferMsr = 0;572 pHv->uD ebugRecvBufferMsr = 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; 573 590 for (VMCPUID i = 0; i < pVM->cCpus; i++) 574 591 { … … 595 612 Assert(*pcRegions <= UINT8_MAX); /* See PGMR3PhysMMIO2Register(). */ 596 613 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 */ 622 static 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 */ 647 static 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 */ 672 VMMR3_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; 597 683 } 598 684 … … 663 749 * Save debug support data. 664 750 */ 665 SSMR3PutU64(pSSM, pcHv->uD ebugPendingBufferMsr);666 SSMR3PutU64(pSSM, pcHv->uD ebugSendBufferMsr);667 SSMR3PutU64(pSSM, pcHv->uD ebugRecvBufferMsr);668 SSMR3PutU64(pSSM, pcHv->uD ebugStatusMsr);669 SSMR3PutU32(pSSM, pcHv->enmD ebugReply);670 SSMR3PutU32(pSSM, pcHv->u BootpXId);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); 671 757 SSMR3PutU32(pSSM, pcHv->DbgGuestIp4Addr.u); 672 758 … … 792 878 if (uHvSavedStatVersion > GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG) 793 879 { 794 SSMR3GetU64(pSSM, &pHv->uD ebugPendingBufferMsr);795 SSMR3GetU64(pSSM, &pHv->uD ebugSendBufferMsr);796 SSMR3GetU64(pSSM, &pHv->uD ebugRecvBufferMsr);797 SSMR3GetU64(pSSM, &pHv->uD ebugStatusMsr);798 SSMR3GetU32(pSSM, (uint32_t *)&pHv->enmD ebugReply);799 SSMR3GetU32(pSSM, &pHv->u BootpXId);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); 800 886 rc = SSMR3GetU32(pSSM, &pHv->DbgGuestIp4Addr.u); 801 887 AssertRCReturn(rc, rc); … … 1137 1223 1138 1224 /** 1225 * Initializes Hyper-V guest debug support. 1226 * 1227 * @returns VBox status code. 1228 * @param pVM The cross context VM structure. 1229 */ 1230 static 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 */ 1250 static 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 /** 1139 1262 * Reads data from a debugger connection, asynchronous. 1140 1263 * … … 1165 1288 */ 1166 1289 size_t cbReallyRead = cbRead; 1167 rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead );1290 rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead, gimR3HvDebugBufReadCompleted); 1168 1291 *pcbRead = (uint32_t)cbReallyRead; 1169 1292 } … … 1175 1298 PGIMHV pHv = &pVM->gim.s.u.Hv; 1176 1299 rc = VERR_GIM_IPE_1; 1177 switch (pHv->enmD ebugReply)1300 switch (pHv->enmDbgReply) 1178 1301 { 1179 1302 case GIMHVDEBUGREPLY_UDP: 1180 1303 { 1181 1304 size_t cbReallyRead = cbRead; 1182 rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead );1305 rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead, gimR3HvDebugBufReadCompleted); 1183 1306 if ( RT_SUCCESS(rc) 1184 1307 && cbReallyRead > 0) … … 1217 1340 pIpHdr->ip_sum = RTNetIPv4HdrChecksum(pIpHdr); 1218 1341 /* UDP */ 1342 pUdpHdr->uh_dport = pHv->uUdpGuestSrcPort; 1343 pUdpHdr->uh_sport = pHv->uUdpGuestDstPort; 1219 1344 pUdpHdr->uh_ulen = RT_H2N_U16_C((uint16_t)cbReallyRead + sizeof(*pUdpHdr)); 1220 1345 … … 1242 1367 rc = VINF_SUCCESS; 1243 1368 *pcbRead = cbArpReplyPkt; 1244 pHv->enmD ebugReply = GIMHVDEBUGREPLY_ARP_REPLY_SENT;1369 pHv->enmDbgReply = GIMHVDEBUGREPLY_ARP_REPLY_SENT; 1245 1370 } 1246 1371 else … … 1262 1387 PRTNETUDP pUdpHdr = (PRTNETUDP) ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN); 1263 1388 PRTNETBOOTP pBootpHdr = (PRTNETBOOTP) (pUdpHdr + 1); 1264 pBootpHdr->bp_xid = pHv->u BootpXId;1389 pBootpHdr->bp_xid = pHv->uDbgBootpXId; 1265 1390 1266 1391 rc = VINF_SUCCESS; 1267 1392 *pcbRead = cbDhcpOfferPkt; 1268 pHv->enmD ebugReply = GIMHVDEBUGREPLY_DHCP_OFFER_SENT;1393 pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_OFFER_SENT; 1269 1394 LogRel(("GIM: HyperV: Debug DHCP offered IP address %RTnaipv4, transaction Id %#x\n", pBootpHdr->bp_yiaddr, 1270 RT_N2H_U32(pHv->u BootpXId)));1395 RT_N2H_U32(pHv->uDbgBootpXId))); 1271 1396 } 1272 1397 else … … 1288 1413 PRTNETUDP pUdpHdr = (PRTNETUDP) ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN); 1289 1414 PRTNETBOOTP pBootpHdr = (PRTNETBOOTP) (pUdpHdr + 1); 1290 pBootpHdr->bp_xid = pHv->u BootpXId;1415 pBootpHdr->bp_xid = pHv->uDbgBootpXId; 1291 1416 1292 1417 rc = VINF_SUCCESS; 1293 1418 *pcbRead = cbDhcpAckPkt; 1294 pHv->enmD ebugReply = GIMHVDEBUGREPLY_DHCP_ACK_SENT;1419 pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_ACK_SENT; 1295 1420 LogRel(("GIM: HyperV: Debug DHCP acknowledged IP address %RTnaipv4, transaction Id %#x\n", 1296 pBootpHdr->bp_yiaddr, RT_N2H_U32(pHv->u BootpXId)));1421 pBootpHdr->bp_yiaddr, RT_N2H_U32(pHv->uDbgBootpXId))); 1297 1422 } 1298 1423 else … … 1315 1440 default: 1316 1441 { 1317 AssertMsgFailed(("GIM: HyperV: Invalid/unimplemented debug reply type %u\n", pHv->enmD ebugReply));1442 AssertMsgFailed(("GIM: HyperV: Invalid/unimplemented debug reply type %u\n", pHv->enmDbgReply)); 1318 1443 rc = VERR_INTERNAL_ERROR_2; 1319 1444 } 1320 1445 } 1321 1446 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 1323 1464 return rc; 1324 1465 } … … 1347 1488 if (fUdpPkt) 1348 1489 { 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 1349 1500 /* 1350 1501 * Windows guests sends us ethernet frames over the Hyper-V debug connection. … … 1388 1539 * Check for DHCP. 1389 1540 */ 1541 bool fBuggyPkt = false; 1390 1542 size_t const cbUdpPkt = cbMaxIpPkt - cbIpHdr; 1391 1543 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)) 1394 1545 { 1395 1546 PCRTNETBOOTP pDhcpPkt = (PCRTNETBOOTP)(pUdpHdr + 1); 1396 1547 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)) 1398 1550 { 1399 1551 switch (bMsgType) 1400 1552 { 1401 1553 case RTNET_DHCP_MT_DISCOVER: 1402 pHv->enmD ebugReply = GIMHVDEBUGREPLY_DHCP_OFFER;1403 pHv->u BootpXId = pDhcpPkt->bp_xid;1554 pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_OFFER; 1555 pHv->uDbgBootpXId = pDhcpPkt->bp_xid; 1404 1556 break; 1405 1557 case RTNET_DHCP_MT_REQUEST: 1406 pHv->enmD ebugReply = GIMHVDEBUGREPLY_DHCP_ACK;1407 pHv->u BootpXId = pDhcpPkt->bp_xid;1558 pHv->enmDbgReply = GIMHVDEBUGREPLY_DHCP_ACK; 1559 pHv->uDbgBootpXId = pDhcpPkt->bp_xid; 1408 1560 break; 1409 1561 default: … … 1412 1564 break; 1413 1565 } 1566 fIgnorePkt = true; 1414 1567 } 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 } 1416 1582 } 1417 else if ( !pUdpHdr->uh_dport 1418 && !pUdpHdr->uh_sport) 1583 1584 if ( ( !pUdpHdr->uh_dport 1585 && !pUdpHdr->uh_sport) 1586 || fBuggyPkt) 1419 1587 { 1420 1588 /* 1421 1589 * 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. 1425 1594 */ 1426 1595 uint32_t const cbFrameHdr = sizeof(RTNETETHERHDR) + cbIpHdr + sizeof(RTNETUDP); 1427 1596 pbData += cbFrameHdr; 1428 1597 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; 1431 1602 } 1432 1603 else 1433 1604 { 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)); 1435 1607 fIgnorePkt = true; 1436 1608 } … … 1476 1648 && pArpPkt->ar_tpa.u == GIMHV_DEBUGSERVER_IPV4) 1477 1649 { 1478 pHv->enmD ebugReply = GIMHVDEBUGREPLY_ARP_REPLY;1650 pHv->enmDbgReply = GIMHVDEBUGREPLY_ARP_REPLY; 1479 1651 } 1480 1652 }
Note:
See TracChangeset
for help on using the changeset viewer.