Changeset 91728 in vbox
- Timestamp:
- Oct 14, 2021 2:22:24 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevPCNet.cpp
r91022 r91728 78 78 * Defined Constants And Macros * 79 79 *********************************************************************************************************************************/ 80 /* Enable this to catch writes to the ring descriptors instead of using excessive polling */81 /* #define PCNET_NO_POLLING */82 80 83 81 /* Enable to handle frequent io reads in the guest context (recommended) */ … … 310 308 /** Software Interrupt timer - R3. */ 311 309 TMTIMERHANDLE hTimerSoftInt; 312 #ifndef PCNET_NO_POLLING313 310 /** Poll timer - R3. */ 314 311 TMTIMERHANDLE hTimerPoll; 315 #endif316 312 /** Restore timer. 317 313 * This is used to disconnect and reconnect the link after a restore. */ … … 383 379 /** Alignment padding. */ 384 380 uint8_t Alignment4[HC_ARCH_BITS == 64 ? 2 : 6]; 385 386 #ifdef PCNET_NO_POLLING387 PGMPHYSHANDLERTYPE hNoPollingHandlerType;388 RTGCPHYS32 TDRAPhysOld;389 uint32_t cbTDRAOld;390 391 RTGCPHYS32 RDRAPhysOld;392 uint32_t cbRDRAOld;393 #endif394 381 395 382 /** Error counter for bad receive descriptors. */ … … 460 447 STAMPROFILEADV StatPollTimer; 461 448 STAMCOUNTER StatMIIReads; 462 # ifdef PCNET_NO_POLLING463 STAMCOUNTER StatRCVRingWrite;464 STAMCOUNTER StatTXRingWrite;465 STAMCOUNTER StatRingWriteR3;466 STAMCOUNTER StatRingWriteR0;467 STAMCOUNTER StatRingWriteRC;468 469 STAMCOUNTER StatRingWriteFailedR3;470 STAMCOUNTER StatRingWriteFailedR0;471 STAMCOUNTER StatRingWriteFailedRC;472 473 STAMCOUNTER StatRingWriteOutsideR3;474 STAMCOUNTER StatRingWriteOutsideR0;475 STAMCOUNTER StatRingWriteOutsideRC;476 # endif477 449 #endif /* VBOX_WITH_STATISTICS */ 478 450 } PCNETSTATE; … … 520 492 /** Pointer to the connector of the attached network driver. */ 521 493 PPDMINETWORKUPR0 pDrv; 522 #ifdef PCNET_NO_POLLING523 DECLR0CALLBACKMEMBER(int, pfnEMInterpretInstructionR0, (PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize));524 #endif525 494 } PCNETSTATER0; 526 495 /** Pointer to a PCnet state structure for ring-0. */ … … 535 504 /** Pointer to the connector of the attached network driver. */ 536 505 PPDMINETWORKUPRC pDrv; 537 #ifdef PCNET_NO_POLLING538 DECLRCCALLBACKMEMBER(int, pfnEMInterpretInstructionRC, (PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize));539 #endif540 506 } PCNETSTATERC; 541 507 /** Pointer to a PCnet state structure for raw-mode. */ … … 685 651 static uint32_t pcnetBCRReadU16(PPCNETSTATE pThis, uint32_t u32RAP); 686 652 static VBOXSTRICTRC pcnetBCRWriteU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, uint32_t u32RAP, uint32_t val); 687 #ifndef PCNET_NO_POLLING688 653 static void pcnetPollTimerStart(PPDMDEVINS pDevIns, PPCNETSTATE pThis); 689 #endif690 654 static int pcnetXmitPending(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, bool fOnWorkerThread); 691 #ifdef PCNET_NO_POLLING692 # ifndef IN_RING3693 RT_C_DECLS_BEGIN694 DECLEXPORT(FNPGMRZPHYSPFHANDLER) pcnetHandleRingWritePf;695 RT_C_DECLS_END696 # endif697 #endif698 655 699 656 #define PRINT_TMD(T) Log10(( \ … … 1254 1211 1255 1212 1256 1257 #ifdef PCNET_NO_POLLING1258 1259 # ifndef IN_RING31260 /**1261 * @callback_method_impl{FNPGMRZPHYSPFHANDLER,1262 * \#PF write access handler for a PCNET ring.}1263 *1264 * @remarks The @a pvUser argument points to the PCNETSTATE.1265 */1266 DECLEXPORT(int) pcnetHandleRingWritePf(PVM pVM, PVMCPU pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame,1267 RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)1268 {1269 PPCNETSTATE pThis = (PPCNETSTATE)pvUser;1270 1271 Log(("#%d pcnetHandleRingWritePf: write to %#010x\n", PCNET_INST_NR, GCPhysFault));1272 1273 uint32_t cb;1274 int rc = pThis->CTX_SUFF(pfnEMInterpretInstruction)(pVM, pRegFrame, pvFault, &cb);1275 if (RT_SUCCESS(rc) && cb)1276 {1277 if ( (GCPhysFault >= pThis->GCTDRA && GCPhysFault + cb < pcnetTdraAddr(pThis, 0))1278 # ifdef PCNET_MONITOR_RECEIVE_RING1279 || (GCPhysFault >= pThis->GCRDRA && GCPhysFault + cb < pcnetRdraAddr(pThis, 0))1280 # endif1281 )1282 {1283 uint32_t offsetTDRA = (GCPhysFault - pThis->GCTDRA);1284 1285 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY);1286 if (RT_SUCCESS(rc))1287 {1288 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatRingWrite));1289 1290 /* Check if we can do something now */1291 pcnetPollRxTx(pDevIns, pThis, pThisCC);1292 pcnetUpdateIrq(pDevIns, pThis);1293 1294 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);1295 return VINF_SUCCESS;1296 }1297 }1298 else1299 {1300 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatRingWriteOutside));1301 return VINF_SUCCESS; /* outside of the ring range */1302 }1303 }1304 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatRingWriteFailed)); ;1305 return VINF_IOM_R3_MMIO_WRITE; /* handle in ring3 */1306 }1307 # endif /* !IN_RING3 */1308 1309 /**1310 * @callback_method_impl{FNPGMPHYSHANDLER,1311 * Write access handler for a PCNET ring.}1312 */1313 PGM_ALL_CB_DECL(VBOXSTRICTRC)1314 pcnetHandleRingWrite(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,1315 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)1316 {1317 PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser;1318 PPCNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPCNETSTATE);1319 1320 Log(("#%d pcnetHandleRingWrite: write to %#010x\n", PCNET_INST_NR, GCPhys));1321 # ifdef VBOX_WITH_STATISTICS1322 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatRingWrite));1323 if (GCPhys >= pThis->GCRDRA && GCPhys < pcnetRdraAddr(pThis, 0))1324 STAM_COUNTER_INC(&pThis->StatRCVRingWrite);1325 else if (GCPhys >= pThis->GCTDRA && GCPhys < pcnetTdraAddr(pThis, 0))1326 STAM_COUNTER_INC(&pThis->StatTXRingWrite);1327 # endif1328 /* Perform the actual write */1329 memcpy((char *)pvPhys, pvBuf, cbBuf);1330 1331 /* Writes done by our code don't require polling of course */1332 if (PDMDevHlpCritSectIsOwner(pDevIns, &pThis->CritSect) == false)1333 {1334 if ( (GCPhys >= pThis->GCTDRA && GCPhys + cbBuf < pcnetTdraAddr(pThis, 0))1335 # ifdef PCNET_MONITOR_RECEIVE_RING1336 || (GCPhys >= pThis->GCRDRA && GCPhys + cbBuf < pcnetRdraAddr(pThis, 0))1337 # endif1338 )1339 {1340 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY);1341 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock);1342 1343 /* Check if we can do something now */1344 pcnetPollRxTx(pDevIns, pThis, pThisCC);1345 pcnetUpdateIrq(pDevIns, pThis);1346 1347 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);1348 }1349 }1350 return VINF_SUCCESS;1351 }1352 1353 #endif /* PCNET_NO_POLLING */1354 1355 1213 static void pcnetSoftReset(PPCNETSTATE pThis) 1356 1214 { … … 1508 1366 #ifdef IN_RING3 1509 1367 1510 # ifdef PCNET_NO_POLLING1511 static void pcnetR3UpdateRingHandlers(PPCNETSTATE pThis)1512 {1513 PPDMDEVINS pDevIns = pDevIns;1514 int rc;1515 1516 Log(("pcnetR3UpdateRingHandlers TD %RX32 size %#x -> %RX32 ?size? %#x\n", pThis->TDRAPhysOld, pThis->cbTDRAOld, pThis->GCTDRA, pcnetTdraAddr(pThis, 0)));1517 Log(("pcnetR3UpdateRingHandlers RX %RX32 size %#x -> %RX32 ?size? %#x\n", pThis->RDRAPhysOld, pThis->cbRDRAOld, pThis->GCRDRA, pcnetRdraAddr(pThis, 0)));1518 1519 /** @todo unregister order not correct! */1520 1521 # ifdef PCNET_MONITOR_RECEIVE_RING1522 if (pThis->GCRDRA != pThis->RDRAPhysOld || CSR_RCVRL(pThis) != pThis->cbRDRAOld)1523 {1524 if (pThis->RDRAPhysOld != 0)1525 PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns),1526 pThis->RDRAPhysOld & ~PAGE_OFFSET_MASK);1527 1528 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),1529 pThis->GCRDRA & ~PAGE_OFFSET_MASK,1530 RT_ALIGN(pcnetRdraAddr(pThis, 0), PAGE_SIZE) - 1,1531 pThis->hNoPollingHandlerType, pDevIns,1532 pThis->pDevInsHC->pvInstanceDataHC,1533 pThis->pDevInsHC->pvInstanceDataRC,1534 "PCnet receive ring write access handler");1535 AssertRC(rc);1536 1537 pThis->RDRAPhysOld = pThis->GCRDRA;1538 pThis->cbRDRAOld = pcnetRdraAddr(pThis, 0);1539 }1540 # endif /* PCNET_MONITOR_RECEIVE_RING */1541 1542 # ifdef PCNET_MONITOR_RECEIVE_RING1543 /* 3 possibilities:1544 * 1) TDRA on different physical page as RDRA1545 * 2) TDRA completely on same physical page as RDRA1546 * 3) TDRA & RDRA overlap partly with different physical pages1547 */1548 RTGCPHYS32 RDRAPageStart = pThis->GCRDRA & ~PAGE_OFFSET_MASK;1549 RTGCPHYS32 RDRAPageEnd = (pcnetRdraAddr(pThis, 0) - 1) & ~PAGE_OFFSET_MASK;1550 RTGCPHYS32 TDRAPageStart = pThis->GCTDRA & ~PAGE_OFFSET_MASK;1551 RTGCPHYS32 TDRAPageEnd = (pcnetTdraAddr(pThis, 0) - 1) & ~PAGE_OFFSET_MASK;1552 1553 if ( RDRAPageStart > TDRAPageEnd1554 || TDRAPageStart > RDRAPageEnd)1555 {1556 # endif /* PCNET_MONITOR_RECEIVE_RING */1557 /* 1) */1558 if (pThis->GCTDRA != pThis->TDRAPhysOld || CSR_XMTRL(pThis) != pThis->cbTDRAOld)1559 {1560 if (pThis->TDRAPhysOld != 0)1561 PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns),1562 pThis->TDRAPhysOld & ~PAGE_OFFSET_MASK);1563 1564 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),1565 pThis->GCTDRA & ~PAGE_OFFSET_MASK,1566 RT_ALIGN(pcnetTdraAddr(pThis, 0), PAGE_SIZE) - 1,1567 pThis->hNoPollingHandlerType,1568 pDevIns->pvInstanceDataR3,1569 pDevIns->pvInstanceDataR0,1570 pDevIns->pvInstanceDataRC,1571 "PCnet transmit ring write access handler");1572 AssertRC(rc);1573 1574 pThis->TDRAPhysOld = pThis->GCTDRA;1575 pThis->cbTDRAOld = pcnetTdraAddr(pThis, 0);1576 }1577 # ifdef PCNET_MONITOR_RECEIVE_RING1578 }1579 else1580 if ( RDRAPageStart != TDRAPageStart1581 && ( TDRAPageStart == RDRAPageEnd1582 || TDRAPageEnd == RDRAPageStart1583 )1584 )1585 {1586 /* 3) */1587 AssertFailed();1588 }1589 /* else 2) */1590 # endif1591 }1592 # endif /* PCNET_NO_POLLING */1593 1594 1368 static void pcnetR3Init(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC) 1595 1369 { … … 1689 1463 CSR_XMTRC(pThis) = CSR_XMTRL(pThis); 1690 1464 1691 # ifdef PCNET_NO_POLLING1692 pcnetR3UpdateRingHandlers(pThis);1693 # endif1694 1695 1465 /* Reset cached RX and TX states */ 1696 1466 CSR_CRST(pThis) = CSR_CRBC(pThis) = CSR_NRST(pThis) = CSR_NRBC(pThis) = 0; … … 1730 1500 pThis->aCSR[0] &= ~0x0004; /* clear STOP bit */ 1731 1501 pThis->aCSR[0] |= 0x0002; /* STRT */ 1732 #ifndef PCNET_NO_POLLING 1502 1733 1503 pcnetPollTimerStart(pDevIns, pThis); /* start timer if it was stopped */ 1734 #endif1735 1504 } 1736 1505 … … 2857 2626 2858 2627 2859 #ifndef PCNET_NO_POLLING2860 2628 /** 2861 2629 * Start the poller timer. … … 2867 2635 PDMDevHlpTimerSetMillies(pDevIns, pThis->hTimerPoll, 2); 2868 2636 } 2869 #endif2870 2637 2871 2638 … … 2918 2685 * but so far I have not seen any guest depending on these values. The 2ms 2919 2686 * interval is the default polling interval of the PCnet card (65536/33MHz). */ 2920 #ifdef PCNET_NO_POLLING2921 pcnetPollRxTx(pDevIns, pThis, pThisCC);2922 #else2923 2687 uint64_t u64Now = PDMDevHlpTimerGet(pDevIns, pThis->hTimerPoll); 2924 2688 if (RT_UNLIKELY(u64Now - pThis->u64LastPoll > 200000)) … … 2929 2693 if (!PDMDevHlpTimerIsActive(pDevIns, pThis->hTimerPoll)) 2930 2694 pcnetPollTimerStart(pDevIns, pThis); 2931 #endif2932 2695 } 2933 2696 STAM_PROFILE_ADV_STOP(&pThis->StatPollTimer, a); … … 4593 4356 4594 4357 int rc = VINF_SUCCESS; 4595 #ifndef PCNET_NO_POLLING4596 4358 rc = PDMDevHlpTimerSave(pDevIns, pThis->hTimerPoll, pSSM); 4597 4359 if (RT_FAILURE(rc)) 4598 4360 return rc; 4599 #endif4600 4361 if (pThis->uDevType == DEV_AM79C973) 4601 4362 rc = PDMDevHlpTimerSave(pDevIns, pThis->hTimerSoftInt, pSSM); … … 4705 4466 { 4706 4467 /* restore timers and stuff */ 4707 #ifndef PCNET_NO_POLLING4708 4468 PDMDevHlpTimerLoad(pDevIns, pThis->hTimerPoll, pSSM); 4709 #endif4710 4469 if (pThis->uDevType == DEV_AM79C973) 4711 4470 { … … 4726 4485 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, CSR_PROM(pThis)); 4727 4486 4728 #ifdef PCNET_NO_POLLING4729 /* Enable physical monitoring again (!) */4730 pcnetR3UpdateRingHandlers(pThis);4731 #endif4732 4487 /* Indicate link down to the guest OS that all network connections have 4733 4488 been lost, unless we've been teleported here. */ … … 4829 4584 rc2 = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); 4830 4585 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rc2); 4831 #ifndef PCNET_NO_POLLING4832 4586 pcnetPollTimerStart(pDevIns, pThis); 4833 #endif4834 4587 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); 4835 4588 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEventOutOfRxSpace, cMillies); … … 5166 4919 PPCNETSTATERC pThisRC = PDMINS_2_DATA_RC(pDevIns, PPCNETSTATERC); 5167 4920 pThisRC->pDrv += offDelta; 5168 #ifdef PCNET_NO_POLLING5169 pThisRC->pfnEMInterpretInstructionRC += offDelta;5170 #endif5171 4921 } 5172 4922 … … 5407 5157 5408 5158 5409 #ifdef PCNET_NO_POLLING 5410 /* 5411 * Resolve the R0 and RC handlers. 5412 */ 5413 rc = PDMR3LdrGetSymbolR0Lazy(PDMDevHlpGetVM(pDevIns), NULL, NULL, "EMInterpretInstruction", &pThis->pfnEMInterpretInstructionR0); 5414 if (RT_SUCCESS(rc)) 5415 rc = PDMR3LdrGetSymbolRCLazy(PDMDevHlpGetVM(pDevIns), NULL, NULL, "EMInterpretInstruction", &pThis->pfnEMInterpretInstructionRC); 5416 AssertLogRelMsgRCReturn(rc, ("PDMR3LdrGetSymbolRCLazy(EMInterpretInstruction) -> %Rrc\n", rc), rc); 5417 5418 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns), PGMPHYSHANDLERKIND_WRITE, 5419 pcnetHandleRingWrite, 5420 g_DevicePCNet.szR0Mod, NULL, "pcnetHandleRingWritePf", 5421 g_DevicePCNet.szRCMod, NULL, "pcnetHandleRingWritePf", 5422 "PCnet ring write access handler", 5423 &pThis->hNoPollingHandlerType); 5424 AssertRCReturn(rc, rc); 5425 5426 #else 5159 /* Transmit descriptor polling timer */ 5427 5160 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetR3Timer, NULL, TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_RING0, 5428 5161 "PCnet Poll", &pThis->hTimerPoll); … … 5430 5163 rc = PDMDevHlpTimerSetCritSect(pDevIns, pThis->hTimerPoll, &pThis->CritSect); 5431 5164 AssertRCReturn(rc, rc); 5432 #endif 5165 5433 5166 if (pThis->uDevType == DEV_AM79C973) 5434 5167 { … … 5556 5289 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPollTimer, STAMTYPE_PROFILE, "PollTimer", STAMUNIT_TICKS_PER_CALL, "Profiling poll timer"); 5557 5290 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMIIReads, STAMTYPE_COUNTER, "MIIReads", STAMUNIT_OCCURENCES, "Number of MII reads"); 5558 # ifdef PCNET_NO_POLLING5559 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRCVRingWrite, STAMTYPE_COUNTER, "Ring/RCVWrites", STAMUNIT_OCCURENCES, "Nr of receive ring writes");5560 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTXRingWrite, STAMTYPE_COUNTER, "Ring/TXWrites", STAMUNIT_OCCURENCES, "Nr of transmit ring writes");5561 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteR3, STAMTYPE_COUNTER, "Ring/R3/Writes", STAMUNIT_OCCURENCES, "Nr of monitored ring page writes");5562 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteR0, STAMTYPE_COUNTER, "Ring/R0/Writes", STAMUNIT_OCCURENCES, "Nr of monitored ring page writes");5563 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteRC, STAMTYPE_COUNTER, "Ring/RC/Writes", STAMUNIT_OCCURENCES, "Nr of monitored ring page writes");5564 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteFailedR3, STAMTYPE_COUNTER, "Ring/R3/Failed", STAMUNIT_OCCURENCES, "Nr of failed ring page writes");5565 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteFailedR0, STAMTYPE_COUNTER, "Ring/R0/Failed", STAMUNIT_OCCURENCES, "Nr of failed ring page writes");5566 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteFailedRC, STAMTYPE_COUNTER, "Ring/RC/Failed", STAMUNIT_OCCURENCES, "Nr of failed ring page writes");5567 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteOutsideR3, STAMTYPE_COUNTER, "Ring/R3/Outside", STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring");5568 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteOutsideR0, STAMTYPE_COUNTER, "Ring/R0/Outside", STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring");5569 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRingWriteOutsideRC, STAMTYPE_COUNTER, "Ring/RC/Outside", STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring");5570 # endif /* PCNET_NO_POLLING */5571 5291 unsigned i; 5572 5292 for (i = 0; i < RT_ELEMENTS(pThis->aStatXmitFlush) - 1; i++)
Note:
See TracChangeset
for help on using the changeset viewer.