Changeset 14528 in vbox for trunk/src/VBox
- Timestamp:
- Nov 24, 2008 4:04:48 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/PGMR0DynMap.cpp
r14519 r14528 206 206 static int pgmR0DynMapExpand(PPGMR0DYNMAP pThis); 207 207 static void pgmR0DynMapTearDown(PPGMR0DYNMAP pThis); 208 #ifdef DEBUG 209 static int pgmR0DynMapTest(PVM pVM); 210 #endif 208 211 209 212 … … 353 356 RTSemFastMutexRelease(pThis->hInitLock); 354 357 358 #ifdef DEBUG 359 /* 360 * Run some tests. 361 */ 362 if (RT_SUCCESS(rc)) 363 pgmR0DynMapTest(pVM); 364 #endif 355 365 return rc; 356 366 } … … 1040 1050 * already has made sure they aren't matching. 1041 1051 */ 1042 uint32_t const cPages = cPages;1052 uint32_t const cPages = pThis->cPages; 1043 1053 PPGMR0DYNMAPENTRY paPages = pThis->paPages; 1044 1054 uint32_t iFreePage; … … 1124 1134 * to a helper function. 1125 1135 */ 1126 uint32_t const cPages = cPages;1136 uint32_t const cPages = pThis->cPages; 1127 1137 uint32_t iPage = (HCPhys >> PAGE_SHIFT) % cPages; 1128 1138 PPGMR0DYNMAPENTRY paPages = pThis->paPages; … … 1164 1174 * Reference it, update statistics and get the return address. 1165 1175 */ 1166 if (ASMAtomicIncS32(&paPages[iPage].cRefs) == 1) 1176 int32_t cRefs = ASMAtomicIncS32(&paPages[iPage].cRefs); 1177 if (cRefs == 1) 1167 1178 { 1168 1179 pThis->cLoad++; … … 1170 1181 pThis->cMaxLoad = pThis->cLoad; 1171 1182 Assert(pThis->cLoad <= pThis->cPages); 1183 } 1184 else if (RT_UNLIKELY(cRefs <= 0)) 1185 { 1186 ASMAtomicDecS32(&paPages[iPage].cRefs); 1187 RTSpinlockRelease(pThis->hSpinlock, &Tmp); 1188 AssertLogRelMsgFailedReturn(("cRefs=%d iPage=%p HCPhys=%RHp\n", cRefs, iPage, HCPhys), NULL); 1172 1189 } 1173 1190 void *pvPage = paPages[iPage].pvPage; … … 1300 1317 if (pSet->aEntries[j].iPage != iPage) 1301 1318 j++; 1302 else 1319 else if ((uint32_t)pSet->aEntries[i].cRefs + (uint32_t)pSet->aEntries[j].cRefs < UINT16_MAX) 1303 1320 { 1304 /* merge j withi removing j. */1321 /* merge j into i removing j. */ 1305 1322 pSet->aEntries[i].cRefs += pSet->aEntries[j].cRefs; 1306 1323 pSet->cEntries--; … … 1317 1334 } 1318 1335 } 1336 else 1337 { 1338 /* migrate the max number of refs from j into i and quit the inner loop. */ 1339 uint32_t cMigrate = UINT16_MAX - 1 - pSet->aEntries[i].cRefs; 1340 Assert(pSet->aEntries[j].cRefs > cMigrate); 1341 pSet->aEntries[j].cRefs -= cMigrate; 1342 pSet->aEntries[i].cRefs = UINT16_MAX - 1; 1343 break; 1344 } 1319 1345 } 1320 1346 } … … 1328 1354 * Validate state. 1329 1355 */ 1356 AssertPtr(ppv); 1357 *ppv = NULL; 1330 1358 AssertMsgReturn(pVM->pgm.s.pvR0DynMapUsed == g_pPGMR0DynMap, 1331 1359 ("%p != %p\n", pVM->pgm.s.pvR0DynMapUsed, g_pPGMR0DynMap), … … 1335 1363 PPGMMAPSET pSet = &pVCpu->pgm.s.AutoSet; 1336 1364 AssertPtrReturn(pVCpu, VERR_INTERNAL_ERROR); 1337 AssertMsgReturn(pSet->cEntries >RT_ELEMENTS(pSet->aEntries),1365 AssertMsgReturn(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries), 1338 1366 ("%#x (%u)\n", pSet->cEntries, pSet->cEntries), VERR_WRONG_ORDER); 1339 1367 … … 1351 1379 return VERR_PGM_DYNMAP_FAILED; 1352 1380 } 1381 *ppv = pvPage; 1353 1382 1354 1383 /* … … 1360 1389 pSet->aEntries[pSet->cEntries].cRefs = 1; 1361 1390 pSet->aEntries[pSet->cEntries].iPage = iPage; 1391 pSet->cEntries++; 1362 1392 } 1363 1393 else … … 1366 1396 int32_t i = pSet->cEntries; 1367 1397 while (i-- > 0) 1368 if (pSet->aEntries[i].iPage) 1398 if ( pSet->aEntries[i].iPage == iPage 1399 && pSet->aEntries[i].cRefs < UINT16_MAX - 1) 1369 1400 { 1370 1401 pSet->aEntries[i].cRefs++; … … 1379 1410 pSet->aEntries[pSet->cEntries].cRefs = 1; 1380 1411 pSet->aEntries[pSet->cEntries].iPage = iPage; 1412 pSet->cEntries++; 1381 1413 } 1382 1414 else … … 1388 1420 if (++s_cBitched < 10) 1389 1421 LogRel(("PGMDynMapHCPage: set is full!\n")); 1422 *ppv = NULL; 1390 1423 return VERR_PGM_DYNMAP_FULL_SET; 1391 1424 } … … 1396 1429 } 1397 1430 1431 1432 #ifdef DEBUG 1433 /** 1434 * Performs some basic tests in debug builds. 1435 */ 1436 static int pgmR0DynMapTest(PVM pVM) 1437 { 1438 PPGMR0DYNMAP pThis = g_pPGMR0DynMap; 1439 PPGMMAPSET pSet = &pVM->aCpus[0].pgm.s.AutoSet; 1440 1441 /* 1442 * Simple test, map CR3 twice and check that we're getting the 1443 * same mapping address back. 1444 */ 1445 LogRel(("pgmR0DynMapTest: 1\n")); 1446 ASMIntDisable(); 1447 PGMDynMapStartAutoSet(&pVM->aCpus[0]); 1448 1449 uint64_t cr3 = ASMGetCR3() & ~(uint64_t)PAGE_OFFSET_MASK; 1450 void *pv = (void *)(intptr_t)-1; 1451 void *pv2 = (void *)(intptr_t)-2; 1452 int rc = PGMDynMapHCPage(pVM, cr3, &pv); 1453 int rc2 = PGMDynMapHCPage(pVM, cr3, &pv2); 1454 ASMIntEnable(); 1455 if ( RT_SUCCESS(rc2) 1456 && RT_SUCCESS(rc) 1457 && pv == pv2) 1458 { 1459 LogRel(("Load=%u/%u/%u Set=%u/%u\n", pThis->cLoad, pThis->cMaxLoad, pThis->cPages, pSet->cEntries, RT_ELEMENTS(pSet->aEntries))); 1460 1461 /* 1462 * Check that the simple set overflow code works by filling it 1463 * with more CR3 mappings. 1464 */ 1465 LogRel(("pgmR0DynMapTest: 2\n")); 1466 ASMIntDisable(); 1467 for (uint32_t i = 0 ; i < UINT16_MAX*2 + RT_ELEMENTS(pSet->aEntries) / 2 && RT_SUCCESS(rc) && pv2 == pv; i++) 1468 { 1469 pv2 = (void *)(intptr_t)-4; 1470 rc = PGMDynMapHCPage(pVM, cr3, &pv2); 1471 } 1472 ASMIntEnable(); 1473 if (RT_FAILURE(rc) || pv != pv2) 1474 { 1475 LogRel(("failed(%d): rc=%Rrc; pv=%p pv2=%p\n", __LINE__, rc, pv, pv2)); 1476 if (RT_SUCCESS(rc2)) rc2 = VERR_INTERNAL_ERROR; 1477 } 1478 else if (pSet->cEntries != RT_ELEMENTS(pSet->aEntries) / 2) 1479 { 1480 LogRel(("failed(%d): cEntries=%d expected %d\n", __LINE__, pSet->cEntries, RT_ELEMENTS(pSet->aEntries) / 2)); 1481 rc = VERR_INTERNAL_ERROR; 1482 } 1483 else if ( pSet->aEntries[(RT_ELEMENTS(pSet->aEntries) / 2) - 1].cRefs != UINT16_MAX - 1 1484 || pSet->aEntries[(RT_ELEMENTS(pSet->aEntries) / 2) - 2].cRefs != UINT16_MAX - 1 1485 || pSet->aEntries[(RT_ELEMENTS(pSet->aEntries) / 2) - 3].cRefs != 2+2+3 1486 || pSet->aEntries[(RT_ELEMENTS(pSet->aEntries) / 2) - 4].cRefs != 1) 1487 { 1488 LogRel(("failed(%d): bad set dist: ", __LINE__)); 1489 for (uint32_t i = 0; i < pSet->cEntries; i++) 1490 LogRel(("[%d]=%d, ", i, pSet->aEntries[i].cRefs)); 1491 LogRel(("\n")); 1492 rc = VERR_INTERNAL_ERROR; 1493 } 1494 if (RT_SUCCESS(rc)) 1495 { 1496 /* 1497 * Trigger an set optimization run (exactly). 1498 */ 1499 LogRel(("pgmR0DynMapTest: 2\n")); 1500 ASMIntDisable(); 1501 for (uint32_t i = 0 ; i < RT_ELEMENTS(pSet->aEntries) / 2 && RT_SUCCESS(rc) && pv2 != pv; i++) 1502 { 1503 pv2 = (void *)(intptr_t)(-5 - i); 1504 rc = PGMDynMapHCPage(pVM, cr3 + (PAGE_SIZE * i), &pv2); 1505 } 1506 ASMIntEnable(); 1507 if (RT_FAILURE(rc) || pv == pv2) 1508 { 1509 LogRel(("failed(%d): rc=%Rrc; pv=%p pv2=%p\n", __LINE__, rc, pv, pv2)); 1510 if (RT_SUCCESS(rc2)) rc2 = VERR_INTERNAL_ERROR; 1511 } 1512 else if (pSet->cEntries != RT_ELEMENTS(pSet->aEntries) / 2 + 3) 1513 { 1514 LogRel(("failed(%d): cEntries=%d expected %d\n", __LINE__, pSet->cEntries, RT_ELEMENTS(pSet->aEntries) / 2 + 3)); 1515 rc = VERR_INTERNAL_ERROR; 1516 } 1517 } 1518 LogRel(("Load=%u/%u/%u Set=%u/%u\n", pThis->cLoad, pThis->cMaxLoad, pThis->cPages, pSet->cEntries, RT_ELEMENTS(pSet->aEntries))); 1519 } 1520 else 1521 { 1522 LogRel(("failed(%d): rc=%Rrc rc2=%Rrc; pv=%p pv2=%p\n", __LINE__, rc, rc2, pv, pv2)); 1523 if (RT_SUCCESS(rc)) 1524 rc = rc2; 1525 } 1526 1527 /* clean up */ 1528 LogRel(("pgmR0DynMapTest: cleanup\n")); 1529 ASMIntDisable(); 1530 PGMDynMapMigrateAutoSet(&pVM->aCpus[0]); 1531 PGMDynMapReleaseAutoSet(&pVM->aCpus[0]); 1532 ASMIntEnable(); 1533 1534 LogRel(("Load=%u/%u/%u Set=%#x/%u\n", pThis->cLoad, pThis->cMaxLoad, pThis->cPages, pSet->cEntries, RT_ELEMENTS(pSet->aEntries))); 1535 return rc; 1536 } 1537 #endif /* DEBUG */
Note:
See TracChangeset
for help on using the changeset viewer.