- Timestamp:
- Jul 4, 2016 12:07:24 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/DevOHCI.cpp
r59875 r62001 93 93 #include <iprt/semaphore.h> 94 94 #include <iprt/critsect.h> 95 #include <iprt/param.h> 95 96 #ifdef IN_RING3 96 97 # include <iprt/alloca.h> … … 102 103 #include "VBoxDD.h" 103 104 105 106 #define VBOX_WITH_OHCI_PHYS_READ_CACHE 107 //#define VBOX_WITH_OHCI_PHYS_READ_STATS 104 108 105 109 /********************************************************************************************************************************* … … 243 247 typedef OHCILOAD *POHCILOAD; 244 248 249 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 250 typedef struct OHCIPAGECACHE 251 { 252 /** Last read physical page address. */ 253 RTGCPHYS GCPhysReadCacheAddr; 254 /** Copy of last read physical page. */ 255 uint8_t au8PhysReadCache[PAGE_SIZE]; 256 } OHCIPAGECACHE, *POHCIPAGECACHE; 257 #endif 245 258 246 259 /** … … 398 411 /** Critical section to synchronize the framer and URB completion handler. */ 399 412 RTCRITSECT CritSect; 413 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 414 /** Last read physical page for caching ED reads in the framer thread. */ 415 R3PTRTYPE(POHCIPAGECACHE) pCacheED; 416 /** Last read physical page for caching TD reads in the framer thread. */ 417 R3PTRTYPE(POHCIPAGECACHE) pCacheTD; 418 #endif 400 419 401 420 } OHCI; … … 815 834 static void ohciBusResume(POHCI ohci, bool fHardware); 816 835 static void ohciBusStop(POHCI pThis); 836 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 837 static void ohciPhysReadCacheClear(POHCIPAGECACHE pPageCache); 838 #endif 817 839 818 840 static DECLCALLBACK(void) ohciRhXferCompletion(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb); … … 1178 1200 pThis->fno = 0; 1179 1201 1202 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 1203 ohciPhysReadCacheClear(pThis->pCacheED); 1204 ohciPhysReadCacheClear(pThis->pCacheTD); 1205 #endif 1206 1180 1207 /* 1181 1208 * If this is a hardware reset, we will initialize the root hub too. … … 1238 1265 #ifdef IN_RING3 1239 1266 1267 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 1268 struct DescReadStats 1269 { 1270 uint32_t cReads; 1271 uint32_t cPageChange; 1272 uint32_t cMinReadsPerPage; 1273 uint32_t cMaxReadsPerPage; 1274 1275 uint32_t cReadsLastPage; 1276 uint32_t u32LastPageAddr; 1277 }; 1278 1279 struct PhysReadStats 1280 { 1281 struct DescReadStats ed; 1282 struct DescReadStats td; 1283 struct DescReadStats all; 1284 1285 uint32_t cCrossReads; 1286 uint32_t cCacheReads; 1287 uint32_t cPageReads; 1288 }; 1289 1290 static struct PhysReadStats physReadStats; 1291 1292 static void descReadStatsReset(struct DescReadStats *p) 1293 { 1294 p->cReads = 0; 1295 p->cPageChange = 0; 1296 p->cMinReadsPerPage = UINT32_MAX; 1297 p->cMaxReadsPerPage = 0; 1298 1299 p->cReadsLastPage = 0; 1300 p->u32LastPageAddr = 0; 1301 } 1302 1303 static void physReadStatsReset(struct PhysReadStats *p) 1304 { 1305 descReadStatsReset(&p->ed); 1306 descReadStatsReset(&p->td); 1307 descReadStatsReset(&p->all); 1308 1309 p->cCrossReads = 0; 1310 p->cCacheReads = 0; 1311 p->cPageReads = 0; 1312 } 1313 1314 static void physReadStatsUpdateDesc(struct DescReadStats *p, uint32_t u32Addr) 1315 { 1316 const uint32_t u32PageAddr = u32Addr & ~UINT32_C(0xFFF); 1317 1318 ++p->cReads; 1319 1320 if (p->u32LastPageAddr == 0) 1321 { 1322 /* First call. */ 1323 ++p->cReadsLastPage; 1324 p->u32LastPageAddr = u32PageAddr; 1325 } 1326 else if (u32PageAddr != p->u32LastPageAddr) 1327 { 1328 /* New page. */ 1329 ++p->cPageChange; 1330 1331 p->cMinReadsPerPage = RT_MIN(p->cMinReadsPerPage, p->cReadsLastPage); 1332 p->cMaxReadsPerPage = RT_MAX(p->cMaxReadsPerPage, p->cReadsLastPage);; 1333 1334 p->cReadsLastPage = 1; 1335 p->u32LastPageAddr = u32PageAddr; 1336 } 1337 else 1338 { 1339 /* Read on the same page. */ 1340 ++p->cReadsLastPage; 1341 } 1342 } 1343 1344 static void physReadStatsPrint(struct PhysReadStats *p) 1345 { 1346 p->ed.cMinReadsPerPage = RT_MIN(p->ed.cMinReadsPerPage, p->ed.cReadsLastPage); 1347 p->ed.cMaxReadsPerPage = RT_MAX(p->ed.cMaxReadsPerPage, p->ed.cReadsLastPage);; 1348 1349 p->td.cMinReadsPerPage = RT_MIN(p->td.cMinReadsPerPage, p->td.cReadsLastPage); 1350 p->td.cMaxReadsPerPage = RT_MAX(p->td.cMaxReadsPerPage, p->td.cReadsLastPage);; 1351 1352 p->all.cMinReadsPerPage = RT_MIN(p->all.cMinReadsPerPage, p->all.cReadsLastPage); 1353 p->all.cMaxReadsPerPage = RT_MAX(p->all.cMaxReadsPerPage, p->all.cReadsLastPage);; 1354 1355 LogRel(("PHYSREAD:\n" 1356 " ED: %d, %d, %d/%d\n" 1357 " TD: %d, %d, %d/%d\n" 1358 " ALL: %d, %d, %d/%d\n" 1359 " C: %d, %d, %d\n" 1360 "", 1361 p->ed.cReads, p->ed.cPageChange, p->ed.cMinReadsPerPage, p->ed.cMaxReadsPerPage, 1362 p->td.cReads, p->td.cPageChange, p->td.cMinReadsPerPage, p->td.cMaxReadsPerPage, 1363 p->all.cReads, p->all.cPageChange, p->all.cMinReadsPerPage, p->all.cMaxReadsPerPage, 1364 p->cCrossReads, p->cCacheReads, p->cPageReads 1365 )); 1366 1367 physReadStatsReset(p); 1368 } 1369 #endif /* VBOX_WITH_OHCI_PHYS_READ_STATS */ 1370 1371 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 1372 static POHCIPAGECACHE ohciPhysReadCacheAlloc(void) 1373 { 1374 return (POHCIPAGECACHE)RTMemAlloc(sizeof(OHCIPAGECACHE)); 1375 } 1376 1377 static void ohciPhysReadCacheFree(POHCIPAGECACHE pPageCache) 1378 { 1379 RTMemFree(pPageCache); 1380 } 1381 1382 static void ohciPhysReadCacheClear(POHCIPAGECACHE pPageCache) 1383 { 1384 pPageCache->GCPhysReadCacheAddr = NIL_RTGCPHYS; 1385 } 1386 1387 static void ohciPhysReadCacheRead(POHCI pThis, POHCIPAGECACHE pPageCache, RTGCPHYS GCPhys, void *pvBuf, size_t cbBuf) 1388 { 1389 const RTGCPHYS PageAddr = PAGE_ADDRESS(GCPhys); 1390 1391 if (PageAddr == PAGE_ADDRESS(GCPhys + cbBuf)) 1392 { 1393 if (PageAddr != pPageCache->GCPhysReadCacheAddr) 1394 { 1395 PDMDevHlpPhysRead(pThis->pDevInsR3, PageAddr, 1396 pPageCache->au8PhysReadCache, sizeof(pPageCache->au8PhysReadCache)); 1397 pPageCache->GCPhysReadCacheAddr = PageAddr; 1398 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 1399 ++physReadStats.cPageReads; 1400 #endif 1401 } 1402 1403 memcpy(pvBuf, &pPageCache->au8PhysReadCache[GCPhys & PAGE_OFFSET_MASK], cbBuf); 1404 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 1405 ++physReadStats.cCacheReads; 1406 #endif 1407 } 1408 else 1409 { 1410 PDMDevHlpPhysRead(pThis->pDevInsR3, GCPhys, pvBuf, cbBuf); 1411 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 1412 ++physReadStats.cCrossReads; 1413 #endif 1414 } 1415 } 1416 1417 static void ohciReadEdCached(POHCI pThis, uint32_t EdAddr, POHCIED pEd) 1418 { 1419 ohciPhysReadCacheRead(pThis, pThis->pCacheED, EdAddr, pEd, sizeof(*pEd)); 1420 } 1421 1422 static void ohciReadTdCached(POHCI pThis, uint32_t TdAddr, POHCITD pTd) 1423 { 1424 ohciPhysReadCacheRead(pThis, pThis->pCacheTD, TdAddr, pTd, sizeof(*pTd)); 1425 } 1426 #endif /* VBOX_WITH_OHCI_PHYS_READ_CACHE */ 1427 1240 1428 /** 1241 1429 * Reads an OHCIED. … … 1243 1431 DECLINLINE(void) ohciReadEd(POHCI pThis, uint32_t EdAddr, POHCIED pEd) 1244 1432 { 1433 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 1434 physReadStatsUpdateDesc(&physReadStats.ed, EdAddr); 1435 physReadStatsUpdateDesc(&physReadStats.all, EdAddr); 1436 #endif 1245 1437 ohciGetDWords(pThis, EdAddr, (uint32_t *)pEd, sizeof(*pEd) >> 2); 1246 1438 } … … 1251 1443 DECLINLINE(void) ohciReadTd(POHCI pThis, uint32_t TdAddr, POHCITD pTd) 1252 1444 { 1445 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 1446 physReadStatsUpdateDesc(&physReadStats.td, TdAddr); 1447 physReadStatsUpdateDesc(&physReadStats.all, TdAddr); 1448 #endif 1253 1449 ohciGetDWords(pThis, TdAddr, (uint32_t *)pTd, sizeof(*pTd) >> 2); 1254 1450 #ifdef LOG_ENABLED … … 2761 2957 } Head; 2762 2958 2959 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 2960 ohciPhysReadCacheClear(pThis->pCacheTD); 2961 #endif 2962 2763 2963 /* read the head */ 2964 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 2965 ohciReadTdCached(pThis, TdAddr, &Head.Td); 2966 #else 2764 2967 ohciReadTd(pThis, TdAddr, &Head.Td); 2968 #endif 2765 2969 ohciBufInit(&Head.Buf, Head.Td.cbp, Head.Td.be); 2766 2970 Head.TdAddr = TdAddr; … … 2780 2984 pCur->pNext = NULL; 2781 2985 pCur->TdAddr = pTail->Td.NextTD & ED_PTR_MASK; 2986 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 2987 ohciReadTdCached(pThis, pCur->TdAddr, &pCur->Td); 2988 #else 2782 2989 ohciReadTd(pThis, pCur->TdAddr, &pCur->Td); 2990 #endif 2783 2991 ohciBufInit(&pCur->Buf, pCur->Td.cbp, pCur->Td.be); 2784 2992 … … 3280 3488 { 3281 3489 OHCIED Ed; 3490 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3491 ohciReadEdCached(pThis, EdAddr, &Ed); 3492 #else 3282 3493 ohciReadEd(pThis, EdAddr, &Ed); 3494 #endif 3283 3495 Assert(!(Ed.hwinfo & ED_HWINFO_ISO)); /* the guest is screwing us */ 3284 3496 if (ohciIsEdReady(&Ed)) … … 3374 3586 { 3375 3587 OHCIED Ed; 3588 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3589 ohciReadEdCached(pThis, EdAddr, &Ed); 3590 #else 3376 3591 ohciReadEd(pThis, EdAddr, &Ed); 3592 #endif 3377 3593 Assert(!(Ed.hwinfo & ED_HWINFO_ISO)); /* the guest is screwing us */ 3378 3594 if (ohciIsEdPresent(&Ed)) … … 3491 3707 { 3492 3708 OHCIED Ed; 3709 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3710 ohciReadEdCached(pThis, EdAddr, &Ed); 3711 #else 3493 3712 ohciReadEd(pThis, EdAddr, &Ed); 3713 #endif 3494 3714 3495 3715 if (ohciIsEdReady(&Ed)) … … 3623 3843 Assert(cLeft == 0); 3624 3844 3845 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3846 /* Get hcca data to minimize calls to ohciGetDWords/PDMDevHlpPhysRead. */ 3847 uint32_t au32HCCA[OHCI_HCCA_NUM_INTR]; 3848 ohciGetDWords(pThis, pThis->hcca, au32HCCA, OHCI_HCCA_NUM_INTR); 3849 #endif 3850 3625 3851 /* Go over all bulk/control/interrupt endpoint lists; any URB found in these lists 3626 3852 * is marked as active again. … … 3637 3863 break; 3638 3864 default: 3865 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3866 EdAddr = au32HCCA[i]; 3867 #else 3639 3868 ohciGetDWords(pThis, pThis->hcca + i * sizeof(EdAddr), &EdAddr, 1); 3869 #endif 3640 3870 break; 3641 3871 } … … 3644 3874 OHCIED Ed; 3645 3875 OHCITD Td; 3876 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3877 ohciReadEdCached(pThis, EdAddr, &Ed); 3878 #else 3646 3879 ohciReadEd(pThis, EdAddr, &Ed); 3880 #endif 3647 3881 uint32_t TdAddr = Ed.HeadP & ED_PTR_MASK; 3648 3882 uint32_t TailP = Ed.TailP & ED_PTR_MASK; … … 3651 3885 && (TdAddr != TailP)) 3652 3886 { 3887 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3888 ohciPhysReadCacheClear(pThis->pCacheTD); 3889 #endif 3653 3890 do 3654 3891 { 3892 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 3893 ohciReadTdCached(pThis, TdAddr, &Td); 3894 #else 3655 3895 ohciReadTd(pThis, TdAddr, &Td); 3896 #endif 3656 3897 j = ohci_in_flight_find(pThis, TdAddr); 3657 3898 if (j > -1) 3658 3899 pThis->aInFlight[j].fInactive = false; 3659 3900 TdAddr = Td.NextTD & ED_PTR_MASK; 3901 /* See #8125. 3902 * Sometimes the ED is changed by the guest between ohciReadEd above and here. 3903 * Then the code reads TD pointed by the new TailP, which is not allowed. 3904 * Luckily Windows guests have Td.NextTD = 0 in the tail TD. 3905 * Also having a real TD at 0 is very unlikely. 3906 * So do not continue. 3907 */ 3908 if (TdAddr == 0) 3909 break; 3660 3910 /* Failsafe for temporarily looped lists. */ 3661 3911 if (++k == 128) … … 3811 4061 pThis->fIdle = true; 3812 4062 4063 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 4064 physReadStatsReset(&physReadStats); 4065 #endif 4066 4067 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 4068 ohciPhysReadCacheClear(pThis->pCacheED); 4069 ohciPhysReadCacheClear(pThis->pCacheTD); 4070 #endif 4071 3813 4072 /* Frame boundary, so do EOF stuff here. */ 3814 4073 bump_frame_number(pThis); … … 3821 4080 /* Start the next frame. */ 3822 4081 ohciStartOfFrame(pThis); 4082 4083 #ifdef VBOX_WITH_OHCI_PHYS_READ_STATS 4084 physReadStatsPrint(&physReadStats); 4085 #endif 3823 4086 3824 4087 RTCritSectLeave(&pThis->CritSect); … … 5592 5855 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 5593 5856 5857 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 5858 ohciPhysReadCacheFree(pThis->pCacheED); 5859 pThis->pCacheED = NULL; 5860 ohciPhysReadCacheFree(pThis->pCacheTD); 5861 pThis->pCacheTD = NULL; 5862 #endif 5863 5594 5864 if (RTCritSectIsInitialized(&pThis->CritSect)) 5595 5865 RTCritSectDelete(&pThis->CritSect); … … 5767 6037 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 5768 6038 N_("OHCI: Failed to create critical section")); 6039 6040 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE 6041 pThis->pCacheED = ohciPhysReadCacheAlloc(); 6042 pThis->pCacheTD = ohciPhysReadCacheAlloc(); 6043 if (pThis->pCacheED == NULL || pThis->pCacheTD == NULL) 6044 return PDMDevHlpVMSetError(pDevIns, VERR_NO_MEMORY, RT_SRC_POS, 6045 N_("OHCI: Failed to allocate PhysRead cache")); 6046 #endif 5769 6047 5770 6048 /*
Note:
See TracChangeset
for help on using the changeset viewer.