- Timestamp:
- Apr 4, 2008 5:10:17 PM (17 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/IOM.cpp
r7749 r7751 165 165 * Caching of port and statistics (saves some time in rep outs/ins instruction emulation) 166 166 */ 167 pVM->iom.s.pRangeLastReadGC = 0; 168 pVM->iom.s.pRangeLastWriteGC = 0; 169 pVM->iom.s.pStatsLastReadGC = 0; 170 pVM->iom.s.pStatsLastWriteGC = 0; 171 172 pVM->iom.s.pRangeLastReadR3 = 0; 173 pVM->iom.s.pRangeLastWriteR3 = 0; 174 pVM->iom.s.pStatsLastReadR3 = 0; 175 pVM->iom.s.pStatsLastWriteR3 = 0; 176 177 pVM->iom.s.pRangeLastReadR0 = 0; 178 pVM->iom.s.pRangeLastWriteR0 = 0; 179 pVM->iom.s.pStatsLastReadR0 = 0; 180 pVM->iom.s.pStatsLastWriteR0 = 0; 167 pVM->iom.s.pRangeLastReadR0 = NIL_RTR0PTR; 168 pVM->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR; 169 pVM->iom.s.pStatsLastReadR0 = NIL_RTR0PTR; 170 pVM->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR; 171 pVM->iom.s.pMMIORangeLastR0 = NIL_RTR0PTR; 172 pVM->iom.s.pMMIOStatsLastR0 = NIL_RTR0PTR; 173 174 pVM->iom.s.pRangeLastReadR3 = NULL; 175 pVM->iom.s.pRangeLastWriteR3 = NULL; 176 pVM->iom.s.pStatsLastReadR3 = NULL; 177 pVM->iom.s.pStatsLastWriteR3 = NULL; 178 pVM->iom.s.pMMIORangeLastR3 = NULL; 179 pVM->iom.s.pMMIOStatsLastR3 = NULL; 180 181 pVM->iom.s.pRangeLastReadGC = NIL_RTGCPTR; 182 pVM->iom.s.pRangeLastWriteGC = NIL_RTGCPTR; 183 pVM->iom.s.pStatsLastReadGC = NIL_RTGCPTR; 184 pVM->iom.s.pStatsLastWriteGC = NIL_RTGCPTR; 185 pVM->iom.s.pMMIORangeLastGC = NIL_RTGCPTR; 186 pVM->iom.s.pMMIOStatsLastGC = NIL_RTGCPTR; 181 187 } 182 188 … … 212 218 pVM->iom.s.pTreesGC = MMHyperHC2GC(pVM, pVM->iom.s.pTreesHC); 213 219 RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesHC->IOPortTreeGC, true, iomr3RelocateIOPortCallback, &offDelta); 214 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTree GC, true, iomr3RelocateMMIOCallback, &offDelta);220 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTree, true, iomr3RelocateMMIOCallback, &offDelta); 215 221 216 222 if (pVM->iom.s.pfnMMIOHandlerGC) … … 228 234 if (pVM->iom.s.pStatsLastWriteGC) 229 235 pVM->iom.s.pStatsLastWriteGC += offDelta; 236 if (pVM->iom.s.pMMIORangeLastGC) 237 pVM->iom.s.pMMIORangeLastGC += offDelta; 238 if (pVM->iom.s.pMMIOStatsLastGC) 239 pVM->iom.s.pMMIOStatsLastGC += offDelta; 230 240 } 231 241 … … 245 255 246 256 Assert(pRange->pDevIns); 247 pRange->pDevIns += offDelta;257 pRange->pDevIns += offDelta; 248 258 if (pRange->pfnOutCallback) 249 pRange->pfnOutCallback += offDelta;259 pRange->pfnOutCallback += offDelta; 250 260 if (pRange->pfnInCallback) 251 pRange->pfnInCallback += offDelta;261 pRange->pfnInCallback += offDelta; 252 262 if (pRange->pfnOutStrCallback) 253 pRange->pfnOutStrCallback += offDelta;263 pRange->pfnOutStrCallback += offDelta; 254 264 if (pRange->pfnInStrCallback) 255 pRange->pfnInStrCallback += offDelta; 256 /** @todo IOMIOPORTRANGEGC::pvUser hack - relocate if 64KB or higher. This hack should be removed! */ 265 pRange->pfnInStrCallback += offDelta; 257 266 if (pRange->pvUser > _64K) 258 pRange->pvUser += offDelta;267 pRange->pvUser += offDelta; 259 268 return 0; 260 269 } … … 265 274 * 266 275 * @returns 0 (continue enum) 267 * @param pNode Pointer to a IOMMMIORANGE GCnode.276 * @param pNode Pointer to a IOMMMIORANGE node. 268 277 * @param pvUser Pointer to the offDelta. This is a pointer to the delta since we're 269 278 * not certain the delta will fit in a void pointer for all possible configs. … … 271 280 static DECLCALLBACK(int) iomr3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser) 272 281 { 273 PIOMMMIORANGE GC pRange = (PIOMMMIORANGEGC)pNode;282 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode; 274 283 RTGCINTPTR offDelta = *(PRTGCINTPTR)pvUser; 275 284 276 Assert(pRange->pDevIns); 277 pRange->pDevIns += offDelta; 278 279 if (pRange->pfnWriteCallback) 280 pRange->pfnWriteCallback += offDelta; 281 if (pRange->pfnReadCallback) 282 pRange->pfnReadCallback += offDelta; 283 if (pRange->pfnFillCallback) 284 pRange->pfnFillCallback += offDelta; 285 /** @todo IOMMMIORANGEGC::pvUser hack - relocate if 64KB or higher. This hack should be removed! */ 286 if (pRange->pvUser > _64K) 287 pRange->pvUser += offDelta; 285 if (pRange->pDevInsGC) 286 pRange->pDevInsGC += offDelta; 287 if (pRange->pfnWriteCallbackGC) 288 pRange->pfnWriteCallbackGC += offDelta; 289 if (pRange->pfnReadCallbackGC) 290 pRange->pfnReadCallbackGC += offDelta; 291 if (pRange->pfnFillCallbackGC) 292 pRange->pfnFillCallbackGC += offDelta; 293 if (pRange->pvUserGC > _64K) 294 pRange->pvUserGC += offDelta; 295 288 296 return 0; 289 297 } … … 433 441 if (pStats) 434 442 return pStats; 435 #if 1 443 436 444 /* allocate stats node. */ 437 445 int rc = MMHyperAlloc(pVM, sizeof(*pStats), 0, MM_TAG_IOM_STATS, (void **)&pStats); … … 444 452 { 445 453 /* register the statistics counters. */ 446 char szName[64]; 447 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R3", GCPhys); 448 rc = STAMR3Register(pVM, &pStats->ReadR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 449 AssertRC(rc); 450 451 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R3", GCPhys); 452 rc = STAMR3Register(pVM, &pStats->WriteR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 453 AssertRC(rc); 454 455 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-GC", GCPhys); 456 rc = STAMR3Register(pVM, &pStats->ReadGC, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 457 AssertRC(rc); 458 459 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-GC", GCPhys); 460 rc = STAMR3Register(pVM, &pStats->WriteGC, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 461 AssertRC(rc); 462 463 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-GC-2-R3", GCPhys); 464 rc = STAMR3Register(pVM, &pStats->ReadGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 465 AssertRC(rc); 466 467 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-GC-2-R3", GCPhys); 468 rc = STAMR3Register(pVM, &pStats->WriteGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 469 AssertRC(rc); 470 471 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R0", GCPhys); 472 rc = STAMR3Register(pVM, &pStats->ReadR0, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 473 AssertRC(rc); 474 475 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R0", GCPhys); 476 rc = STAMR3Register(pVM, &pStats->WriteR0, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 477 AssertRC(rc); 478 479 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R0-2-R3", GCPhys); 480 rc = STAMR3Register(pVM, &pStats->ReadR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 481 AssertRC(rc); 482 483 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R0-2-R3", GCPhys); 484 rc = STAMR3Register(pVM, &pStats->WriteR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); 454 rc = STAMR3RegisterF(pVM, &pStats->ReadR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-R3", GCPhys); 455 AssertRC(rc); 456 rc = STAMR3RegisterF(pVM, &pStats->WriteR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-R3", GCPhys); 457 AssertRC(rc); 458 rc = STAMR3RegisterF(pVM, &pStats->ReadGC, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-GC", GCPhys); 459 AssertRC(rc); 460 rc = STAMR3RegisterF(pVM, &pStats->WriteGC, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-GC", GCPhys); 461 AssertRC(rc); 462 rc = STAMR3RegisterF(pVM, &pStats->ReadGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-GC-2-R3", GCPhys); 463 AssertRC(rc); 464 rc = STAMR3RegisterF(pVM, &pStats->WriteGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-GC-2-R3", GCPhys); 465 AssertRC(rc); 466 rc = STAMR3RegisterF(pVM, &pStats->ReadR0, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-R0", GCPhys); 467 AssertRC(rc); 468 rc = STAMR3RegisterF(pVM, &pStats->WriteR0, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-R0", GCPhys); 469 AssertRC(rc); 470 rc = STAMR3RegisterF(pVM, &pStats->ReadR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-R0-2-R3", GCPhys); 471 AssertRC(rc); 472 rc = STAMR3RegisterF(pVM, &pStats->WriteR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-R0-2-R3", GCPhys); 485 473 AssertRC(rc); 486 474 487 475 /* Profiling */ 488 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R3/Prof", GCPhys); 489 rc = STAMR3Register(pVM, &pStats->ProfReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc); 490 AssertRC(rc); 491 492 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R3/Prof", GCPhys); 493 rc = STAMR3Register(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc); 494 AssertRC(rc); 495 496 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-GC/Prof", GCPhys); 497 rc = STAMR3Register(pVM, &pStats->ProfReadGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc); 498 AssertRC(rc); 499 500 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-GC/Prof", GCPhys); 501 rc = STAMR3Register(pVM, &pStats->ProfWriteGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc); 502 AssertRC(rc); 503 504 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R0/Prof", GCPhys); 505 rc = STAMR3Register(pVM, &pStats->ProfReadR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc); 506 AssertRC(rc); 507 508 RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R0/Prof", GCPhys); 509 rc = STAMR3Register(pVM, &pStats->ProfWriteR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc); 476 rc = STAMR3RegisterF(pVM, &pStats->ProfReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Read-R3/Prof", GCPhys); 477 AssertRC(rc); 478 rc = STAMR3RegisterF(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Write-R3/Prof", GCPhys); 479 AssertRC(rc); 480 rc = STAMR3RegisterF(pVM, &pStats->ProfReadGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Read-GC/Prof", GCPhys); 481 AssertRC(rc); 482 rc = STAMR3RegisterF(pVM, &pStats->ProfWriteGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Write-GC/Prof", GCPhys); 483 AssertRC(rc); 484 rc = STAMR3RegisterF(pVM, &pStats->ProfReadR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Read-R0/Prof", GCPhys); 485 AssertRC(rc); 486 rc = STAMR3RegisterF(pVM, &pStats->ProfWriteR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Write-R0/Prof", GCPhys); 510 487 AssertRC(rc); 511 488 … … 515 492 MMHyperFree(pVM, pStats); 516 493 } 517 #endif518 494 return NULL; 519 495 } … … 1368 1344 if (pVM->iom.s.pRangeLastReadR0) 1369 1345 { 1370 PIOMIOPORTRANGER0 pRange = pVM->iom.s.pRangeLastReadR0;1346 PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastReadR0); 1371 1347 pHlp->pfnPrintf(pHlp, "R0 Read Ports: %#04x-%#04x %VGv %s\n", 1372 1348 pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc); … … 1374 1350 if (pVM->iom.s.pStatsLastReadR0) 1375 1351 { 1376 PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastReadR0;1352 PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastReadR0); 1377 1353 pHlp->pfnPrintf(pHlp, "R0 Read Stats: %#04x %VGv\n", 1378 1354 pRange->Core.Key, pRange); … … 1381 1357 if (pVM->iom.s.pRangeLastWriteR0) 1382 1358 { 1383 PIOMIOPORTRANGER0 pRange = pVM->iom.s.pRangeLastWriteR0;1359 PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastWriteR0); 1384 1360 pHlp->pfnPrintf(pHlp, "R0 Write Ports: %#04x-%#04x %VGv %s\n", 1385 1361 pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc); … … 1387 1363 if (pVM->iom.s.pStatsLastWriteR0) 1388 1364 { 1389 PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastWriteR0;1365 PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastWriteR0); 1390 1366 pHlp->pfnPrintf(pHlp, "R0 Write Stats: %#04x %VGv\n", 1391 1367 pRange->Core.Key, pRange); … … 1443 1419 * Allocate new range record and initialize it. 1444 1420 */ 1445 PIOMMMIORANGE R3pRange;1421 PIOMMMIORANGE pRange; 1446 1422 rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 1447 1423 if (VBOX_SUCCESS(rc)) 1448 1424 { 1449 pRange->Core.Key = GCPhysStart; 1450 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1); 1451 pRange->GCPhys = GCPhysStart; 1452 pRange->cb = cbRange; 1453 pRange->pvUser = pvUser; 1454 pRange->pDevIns = pDevIns; 1455 pRange->pfnReadCallback = pfnReadCallback; 1456 pRange->pfnWriteCallback= pfnWriteCallback; 1457 pRange->pfnFillCallback = pfnFillCallback; 1458 pRange->pszDesc = pszDesc; 1425 pRange->Core.Key = GCPhysStart; 1426 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1); 1427 pRange->GCPhys = GCPhysStart; 1428 pRange->cb = cbRange; 1429 pRange->pszDesc = pszDesc; 1430 1431 pRange->pvUserR3 = pvUser; 1432 pRange->pDevInsR3 = pDevIns; 1433 pRange->pfnReadCallbackR3 = pfnReadCallback; 1434 pRange->pfnWriteCallbackR3 = pfnWriteCallback; 1435 pRange->pfnFillCallbackR3 = pfnFillCallback; 1436 1437 //pRange->pvUserR0 = NIL_RTR0PTR; 1438 //pRange->pDevInsR0 = NIL_RTR0PTR; 1439 //pRange->pfnReadCallbackR0 = NIL_RTR0PTR; 1440 //pRange->pfnWriteCallbackR0 = NIL_RTR0PTR; 1441 //pRange->pfnFillCallbackR0 = NIL_RTR0PTR; 1442 1443 //pRange->pvUserGC = NIL_RTGCPTR; 1444 //pRange->pDevInsGC = NIL_RTGCPTR; 1445 //pRange->pfnReadCallbackGC = NIL_RTGCPTR; 1446 //pRange->pfnWriteCallbackGC = NIL_RTGCPTR; 1447 //pRange->pfnFillCallbackGC = NIL_RTGCPTR; 1459 1448 1460 1449 /* … … 1467 1456 if (RT_SUCCESS(rc)) 1468 1457 { 1469 if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesHC->MMIOTree R3, &pRange->Core))1458 if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesHC->MMIOTree, &pRange->Core)) 1470 1459 return VINF_SUCCESS; 1471 1460 … … 1515 1504 return VERR_INVALID_PARAMETER; 1516 1505 } 1517 RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1); 1518 if (GCPhysLast < GCPhysStart) 1519 { 1520 AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1521 return VERR_IOM_INVALID_MMIO_RANGE; 1522 } 1523 1524 /* 1525 * Check that a ring-3 MMIO range exists. 1526 */ 1527 RTGCPHYS GCPhys = GCPhysStart; 1528 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1529 { 1530 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys); 1531 if (!pRange) 1532 { 1533 AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc)); 1534 return VERR_IOM_NO_HC_MMIO_RANGE; 1535 } 1536 #ifndef IOM_NO_PDMINS_CHECKS 1537 # ifndef IN_GC 1538 if (pRange->pDevIns != pDevIns) 1539 # else 1540 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns)) 1541 # endif 1542 { 1543 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc, 1544 pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc))); 1545 return VERR_IOM_NOT_MMIO_RANGE_OWNER; 1546 } 1547 #endif /* !IOM_NO_PDMINS_CHECKS */ 1548 /* next */ 1549 Assert(GCPhys <= pRange->Core.KeyLast); 1550 GCPhys = pRange->Core.KeyLast + 1; 1551 } 1552 1553 1554 /* 1555 * Allocate new range record and initialize it. 1556 */ 1557 PIOMMMIORANGEGC pRange; 1558 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 1559 if (VBOX_SUCCESS(rc)) 1560 { 1561 pRange->Core.Key = GCPhysStart; 1562 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1); 1563 pRange->GCPhys = GCPhysStart; 1564 pRange->cb = cbRange; 1565 pRange->pvUser = pvUser; 1566 pRange->pfnReadCallback = pfnReadCallback; 1567 pRange->pfnWriteCallback= pfnWriteCallback; 1568 pRange->pfnFillCallback = pfnFillCallback; 1569 #ifdef IN_GC 1570 pRange->pDevIns = pDevIns; 1571 pRange->pszDesc = MMHyperGC2HC(pVM, (void *)pszDesc); 1572 #else 1573 pRange->pDevIns = MMHyperHC2GC(pVM, pDevIns); 1574 pRange->pszDesc = pszDesc; 1575 #endif 1576 1577 /* 1578 * Try insert it. 1579 */ 1580 if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeGC, &pRange->Core)) 1581 return VINF_SUCCESS; 1582 1583 AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1584 MMHyperFree(pVM, pRange); 1585 rc = VERR_IOM_MMIO_RANGE_CONFLICT; 1586 } 1587 1588 return rc; 1506 1507 /* 1508 * Find the MMIO range and check that the input matches. 1509 */ 1510 PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhysStart); 1511 AssertReturn(pRange, VERR_IOM_MMIO_RANGE_NOT_FOUND); 1512 AssertReturn(pRange->pDevInsR3 == pDevIns, VERR_IOM_NOT_MMIO_RANGE_OWNER); 1513 AssertReturn(pRange->GCPhys == GCPhysStart, VERR_IOM_INVALID_MMIO_RANGE); 1514 AssertReturn(pRange->cb == cbRange, VERR_IOM_INVALID_MMIO_RANGE); 1515 1516 pRange->pvUserGC = pvUser; 1517 pRange->pfnReadCallbackGC = pfnReadCallback; 1518 pRange->pfnWriteCallbackGC= pfnWriteCallback; 1519 pRange->pfnFillCallbackGC = pfnFillCallback; 1520 pRange->pDevInsGC = MMHyperCCToGC(pVM, pDevIns); 1521 1522 return VINF_SUCCESS; 1589 1523 } 1590 1524 … … 1624 1558 return VERR_INVALID_PARAMETER; 1625 1559 } 1626 RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1); 1627 if (GCPhysLast < GCPhysStart) 1628 { 1629 AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1630 return VERR_IOM_INVALID_MMIO_RANGE; 1631 } 1632 1633 /* 1634 * Check that a ring-3 MMIO range exists. 1635 */ 1636 RTGCPHYS GCPhys = GCPhysStart; 1637 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1638 { 1639 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys); 1640 if (!pRange) 1641 { 1642 AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc)); 1643 return VERR_IOM_NO_HC_MMIO_RANGE; 1644 } 1645 #ifndef IOM_NO_PDMINS_CHECKS 1646 # ifndef IN_GC 1647 if (pRange->pDevIns != pDevIns) 1648 # else 1649 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns)) 1650 # endif 1651 { 1652 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc, 1653 pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc))); 1654 return VERR_IOM_NOT_MMIO_RANGE_OWNER; 1655 } 1656 #endif /* !IOM_NO_PDMINS_CHECKS */ 1657 /* next */ 1658 Assert(GCPhys <= pRange->Core.KeyLast); 1659 GCPhys = pRange->Core.KeyLast + 1; 1660 } 1661 1662 1663 /* 1664 * Allocate new range record and initialize it. 1665 */ 1666 PIOMMMIORANGER0 pRange; 1667 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 1668 if (VBOX_SUCCESS(rc)) 1669 { 1670 pRange->Core.Key = GCPhysStart; 1671 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1); 1672 pRange->GCPhys = GCPhysStart; 1673 pRange->cb = cbRange; 1674 pRange->pvUser = pvUser; 1675 pRange->pfnReadCallback = pfnReadCallback; 1676 pRange->pfnWriteCallback= pfnWriteCallback; 1677 pRange->pfnFillCallback = pfnFillCallback; 1678 #ifdef IN_GC 1679 pRange->pDevIns = MMHyperGCToR0(pVM, pDevIns); 1680 pRange->pszDesc = MMHyperGCToR3(pVM, (void *)pszDesc); 1681 #elif defined(IN_RING3) 1682 pRange->pDevIns = MMHyperR3ToR0(pVM, pDevIns); 1683 pRange->pszDesc = pszDesc; 1684 #else 1685 pRange->pDevIns = pDevIns; 1686 pRange->pszDesc = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc); 1687 #endif 1688 1689 /* 1690 * Try insert it. 1691 */ 1692 if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR0, &pRange->Core)) 1693 return VINF_SUCCESS; 1694 1695 AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1696 MMHyperFree(pVM, pRange); 1697 rc = VERR_IOM_MMIO_RANGE_CONFLICT; 1698 } 1699 1700 return rc; 1560 1561 /* 1562 * Find the MMIO range and check that the input matches. 1563 */ 1564 PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhysStart); 1565 AssertReturn(pRange, VERR_IOM_MMIO_RANGE_NOT_FOUND); 1566 AssertReturn(pRange->pDevInsR3 == pDevIns, VERR_IOM_NOT_MMIO_RANGE_OWNER); 1567 AssertReturn(pRange->GCPhys == GCPhysStart, VERR_IOM_INVALID_MMIO_RANGE); 1568 AssertReturn(pRange->cb == cbRange, VERR_IOM_INVALID_MMIO_RANGE); 1569 1570 pRange->pvUserR0 = pvUser; 1571 pRange->pfnReadCallbackR0 = pfnReadCallback; 1572 pRange->pfnWriteCallbackR0= pfnWriteCallback; 1573 pRange->pfnFillCallbackR0 = pfnFillCallback; 1574 pRange->pDevInsR0 = MMHyperCCToR0(pVM, pDevIns); 1575 1576 return VINF_SUCCESS; 1701 1577 } 1702 1578 … … 1732 1608 1733 1609 /* 1734 * Check ownership and such .1610 * Check ownership and such for the entire area. 1735 1611 */ 1736 1612 RTGCPHYS GCPhys = GCPhysStart; 1737 1613 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1738 1614 { 1739 PIOMMMIORANGE R3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysGet(&pVM->iom.s.pTreesHC->MMIOTreeR3, GCPhys);1615 PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys); 1740 1616 if (!pRange) 1741 1617 return VERR_IOM_MMIO_RANGE_NOT_FOUND; 1742 #ifndef IOM_NO_PDMINS_CHECKS 1743 if (pRange->pDevIns != pDevIns) 1744 { 1745 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc)); 1746 return VERR_IOM_NOT_MMIO_RANGE_OWNER; 1747 } 1748 #endif /* !IOM_NO_PDMINS_CHECKS */ 1749 if (pRange->Core.KeyLast > GCPhysLast) 1750 { 1751 AssertMsgFailed(("Incomplete R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc)); 1752 return VERR_IOM_INCOMPLETE_MMIO_RANGE; 1753 } 1618 AssertMsgReturn(pRange->pDevInsR3 == pDevIns, 1619 ("Not owner! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc), 1620 VERR_IOM_NOT_MMIO_RANGE_OWNER); 1621 AssertMsgReturn(pRange->Core.KeyLast <= GCPhysLast, 1622 ("Incomplete R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc), 1623 VERR_IOM_INCOMPLETE_MMIO_RANGE); 1624 1754 1625 /* next */ 1755 1626 Assert(GCPhys <= pRange->Core.KeyLast); … … 1758 1629 1759 1630 /* 1760 * Remove GCranges.1631 * Do the actual removing of the MMIO ranges. 1761 1632 */ 1762 1633 GCPhys = GCPhysStart; 1763 1634 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1764 1635 { 1765 PIOMMMIORANGEGC pRange = (PIOMMMIORANGEGC)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTreeGC, GCPhys); 1766 if (pRange) 1767 { 1768 Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast); 1769 1770 /* next and delete. */ 1771 GCPhys = pRange->Core.KeyLast + 1; 1772 MMHyperFree(pVM, pRange); 1773 } 1774 else /* next - this'll be damned slow! */ 1775 GCPhys++; 1776 } 1777 1778 /* 1779 * Remove R0 ranges. 1780 */ 1781 GCPhys = GCPhysStart; 1782 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1783 { 1784 PIOMMMIORANGER0 pRange = (PIOMMMIORANGER0)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTreeR0, GCPhys); 1785 if (pRange) 1786 { 1787 Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast); 1788 1789 /* next and delete. */ 1790 GCPhys = pRange->Core.KeyLast + 1; 1791 MMHyperFree(pVM, pRange); 1792 } 1793 else /* next - this'll be damned slow! */ 1794 GCPhys++; 1795 } 1796 1797 /* 1798 * Remove R3 ranges. 1799 */ 1800 GCPhys = GCPhysStart; 1801 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1802 { 1803 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTreeR3, GCPhys); 1636 PIOMMMIORANGE pRange = (PIOMMMIORANGE)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTree, GCPhys); 1804 1637 Assert(pRange); 1805 1638 Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast); … … 1809 1642 AssertRC(rc); 1810 1643 1811 /* next and delete. */1644 /* advance and free. */ 1812 1645 GCPhys = pRange->Core.KeyLast + 1; 1813 1646 MMHyperFree(pVM, pRange); 1814 1647 } 1815 1648 1649 iomR3FlushCache(pVM); 1816 1650 return VINF_SUCCESS; 1817 1651 } … … 1819 1653 1820 1654 /** 1821 * Display a single MMIO R3range.1655 * Display a single MMIO range. 1822 1656 * 1823 1657 * @returns 0 … … 1825 1659 * @param pvUser Pointer to info output callback structure. 1826 1660 */ 1827 static DECLCALLBACK(int) iomR3MMIOInfoOne R3(PAVLROGCPHYSNODECORE pNode, void *pvUser)1828 { 1829 PIOMMMIORANGE R3 pRange = (PIOMMMIORANGER3)pNode;1661 static DECLCALLBACK(int) iomR3MMIOInfoOne(PAVLROGCPHYSNODECORE pNode, void *pvUser) 1662 { 1663 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode; 1830 1664 PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser; 1831 1665 pHlp->pfnPrintf(pHlp, … … 1833 1667 pRange->Core.Key, 1834 1668 pRange->Core.KeyLast, 1835 pRange->pDevIns ,1836 pRange->pfnReadCallback ,1837 pRange->pfnWriteCallback ,1838 pRange->pfnFillCallback ,1839 pRange->pvUser ,1669 pRange->pDevInsR3, 1670 pRange->pfnReadCallbackR3, 1671 pRange->pfnWriteCallbackR3, 1672 pRange->pfnFillCallbackR3, 1673 pRange->pvUserR3, 1840 1674 pRange->pszDesc); 1841 return 0;1842 }1843 1844 1845 /**1846 * Display a single MMIO GC range.1847 *1848 * @returns 01849 * @param pNode Pointer to MMIO GC range.1850 * @param pvUser Pointer to info output callback structure.1851 */1852 static DECLCALLBACK(int) iomR3MMIOInfoOneGC(PAVLROGCPHYSNODECORE pNode, void *pvUser)1853 {1854 PIOMMMIORANGEGC pRange = (PIOMMMIORANGEGC)pNode;1855 PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;1856 1675 pHlp->pfnPrintf(pHlp, 1857 "%VGp-%VGp %VGv %VGv %VGv %VGv %VGv %s\n", 1858 pRange->Core.Key, 1859 pRange->Core.KeyLast, 1860 pRange->pDevIns, 1861 pRange->pfnReadCallback, 1862 pRange->pfnWriteCallback, 1863 pRange->pfnFillCallback, 1864 pRange->pvUser, 1865 pRange->pszDesc); 1676 "%*s %VHv %VHv %VHv %VHv %VHv\n", 1677 sizeof(RTGCPHYS) * 2 * 2 + 1, "R0", 1678 pRange->pDevInsR0, 1679 pRange->pfnReadCallbackR0, 1680 pRange->pfnWriteCallbackR0, 1681 pRange->pfnFillCallbackR0, 1682 pRange->pvUserR0); 1683 pHlp->pfnPrintf(pHlp, 1684 "%*s %VGv %VGv %VGv %VGv %VGv\n", 1685 sizeof(RTGCPHYS) * 2 * 2 + 1, "GC", 1686 pRange->pDevInsGC, 1687 pRange->pfnReadCallbackGC, 1688 pRange->pfnWriteCallbackGC, 1689 pRange->pfnFillCallbackGC, 1690 pRange->pvUserGC); 1866 1691 return 0; 1867 1692 } … … 1879 1704 NOREF(pszArgs); 1880 1705 pHlp->pfnPrintf(pHlp, 1881 "MMIO R3ranges (pVM=%p)\n"1706 "MMIO ranges (pVM=%p)\n" 1882 1707 "%.*s %.*s %.*s %.*s %.*s %.*s %s\n", 1883 1708 pVM, … … 1888 1713 sizeof(RTHCPTR) * 2, "Fill ", 1889 1714 sizeof(RTHCPTR) * 2, "pvUser ", 1890 "Description"); 1891 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeR3, true, iomR3MMIOInfoOneR3, (void *)pHlp); 1892 1893 pHlp->pfnPrintf(pHlp, 1894 "MMIO R0 ranges (pVM=%p)\n" 1895 "%.*s %.*s %.*s %.*s %.*s %.*s %s\n", 1896 pVM, 1897 sizeof(RTGCPHYS) * 4 + 1, "GC Phys Range ", 1898 sizeof(RTGCPTR) * 2, "pDevIns ", 1899 sizeof(RTGCPTR) * 2, "Read ", 1900 sizeof(RTGCPTR) * 2, "Write ", 1901 sizeof(RTGCPTR) * 2, "Fill ", 1902 sizeof(RTGCPTR) * 2, "pvUser ", 1903 "Description"); 1904 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeR0, true, iomR3MMIOInfoOneR3, (void *)pHlp); 1905 1906 pHlp->pfnPrintf(pHlp, 1907 "MMIO GC ranges (pVM=%p)\n" 1908 "%.*s %.*s %.*s %.*s %.*s %.*s %s\n", 1909 pVM, 1910 sizeof(RTGCPHYS) * 4 + 1, "GC Phys Range ", 1911 sizeof(RTGCPTR) * 2, "pDevIns ", 1912 sizeof(RTGCPTR) * 2, "Read ", 1913 sizeof(RTGCPTR) * 2, "Write ", 1914 sizeof(RTGCPTR) * 2, "Fill ", 1915 sizeof(RTGCPTR) * 2, "pvUser ", 1916 "Description"); 1917 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeGC, true, iomR3MMIOInfoOneGC, (void *)pHlp); 1715 "Description"); 1716 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTree, true, iomR3MMIOInfoOne, (void *)pHlp); 1918 1717 } 1919 1718 -
trunk/src/VBox/VMM/IOMInternal.h
r7731 r7751 24 24 #include <VBox/stam.h> 25 25 #include <VBox/pgm.h> 26 #include <VBox/param.h> 26 27 #include <iprt/avl.h> 27 28 … … 38 39 39 40 /** 40 * MMIO range descriptor, R3 version. 41 */ 42 typedef struct IOMMMIORANGER3 43 { 44 /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */ 45 AVLROGCPHYSNODECORE Core; 46 #if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32 && !defined(RT_OS_WINDOWS) 47 uint32_t u32Alignment; /**< The sizeof(Core) differs. */ 48 #endif 49 /** Start physical address. */ 50 RTGCPHYS GCPhys; 51 /** Size of the range. */ 52 RTUINT cb; 53 /** Pointer to user argument. */ 54 RTR3PTR pvUser; 55 /** Pointer to device instance. */ 56 R3PTRTYPE(PPDMDEVINS) pDevIns; 57 /** Pointer to write callback function. */ 58 R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback; 59 /** Pointer to read callback function. */ 60 R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback; 61 /** Pointer to fill (memset) callback function. */ 62 R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback; 63 /** Description / Name. For easing debugging. */ 64 R3PTRTYPE(const char *) pszDesc; 65 } IOMMMIORANGER3; 66 /** Pointer to a MMIO range descriptor, R3 version. */ 67 typedef struct IOMMMIORANGER3 *PIOMMMIORANGER3; 68 69 /** 70 * MMIO range descriptor, R0 version. 71 */ 72 typedef struct IOMMMIORANGER0 73 { 74 /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */ 75 AVLROGCPHYSNODECORE Core; 76 /** Start physical address. */ 77 RTGCPHYS GCPhys; 78 #if HC_ARCH_BITS == 64 79 uint32_t u32Alignment; 80 #endif 81 /** Size of the range. */ 82 RTUINT cb; 83 /** Pointer to user argument. */ 84 RTR0PTR pvUser; 85 /** Pointer to device instance. */ 86 R0PTRTYPE(PPDMDEVINS) pDevIns; 87 /** Pointer to write callback function. */ 88 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback; 89 /** Pointer to read callback function. */ 90 R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback; 91 /** Pointer to fill (memset) callback function. */ 92 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback; 93 /** Description / Name. For easing debugging. */ 94 R3PTRTYPE(const char *) pszDesc; 95 } IOMMMIORANGER0; 96 /** Pointer to a MMIO range descriptor, R0 version. */ 97 typedef struct IOMMMIORANGER0 *PIOMMMIORANGER0; 98 99 /** 100 * MMIO range descriptor, GC version. 101 */ 102 typedef struct IOMMMIORANGEGC 41 * MMIO range descriptor. 42 */ 43 typedef struct IOMMMIORANGE 103 44 { 104 45 /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */ … … 107 48 RTGCPHYS GCPhys; 108 49 /** Size of the range. */ 109 RTUINT cb; 110 #if HC_ARCH_BITS == 64 111 uint32_t u32Alignment; 112 #endif 50 uint32_t cb; 51 uint32_t u32Alignment; /**< Alignment padding. */ 52 113 53 /** Pointer to user argument. */ 114 RT GCPTR pvUser;54 RTR3PTR pvUserR3; 115 55 /** Pointer to device instance. */ 116 GCPTRTYPE(PPDMDEVINS) pDevIns;56 PPDMDEVINSR3 pDevInsR3; 117 57 /** Pointer to write callback function. */ 118 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback;58 R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR3; 119 59 /** Pointer to read callback function. */ 120 GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback;60 R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR3; 121 61 /** Pointer to fill (memset) callback function. */ 122 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback; 123 #if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32 124 RTGCPTR GCPtrAlignment; /**< pszDesc is 8 byte aligned. */ 125 #endif 62 R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR3; 63 64 /** Pointer to user argument. */ 65 RTR0PTR pvUserR0; 66 /** Pointer to device instance. */ 67 PPDMDEVINSR0 pDevInsR0; 68 /** Pointer to write callback function. */ 69 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR0; 70 /** Pointer to read callback function. */ 71 R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR0; 72 /** Pointer to fill (memset) callback function. */ 73 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR0; 74 75 /** Pointer to user argument. */ 76 RTGCPTR pvUserGC; 77 /** Pointer to device instance. */ 78 PPDMDEVINSGC pDevInsGC; 79 /** Pointer to write callback function. */ 80 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackGC; 81 /** Pointer to read callback function. */ 82 GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackGC; 83 /** Pointer to fill (memset) callback function. */ 84 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackGC; 85 RTGCPTR GCPtrAlignment; /**< Alignment padding */ 86 126 87 /** Description / Name. For easing debugging. */ 127 88 R3PTRTYPE(const char *) pszDesc; 128 } IOMMMIORANGE GC;129 /** Pointer to a MMIO range descriptor, GCversion. */130 typedef struct IOMMMIORANGE GC *PIOMMMIORANGEGC;89 } IOMMMIORANGE; 90 /** Pointer to a MMIO range descriptor, R3 version. */ 91 typedef struct IOMMMIORANGE *PIOMMMIORANGE; 131 92 132 93 … … 340 301 AVLROIOPORTTREE IOPortTreeGC; 341 302 342 /** Tree containing MMIO range descriptors registered for HC (IOMMMIORANGEHC). */ 343 AVLROGCPHYSTREE MMIOTreeR3; 344 /** Tree containing MMIO range descriptors registered for R0 (IOMMMIORANGER0). */ 345 AVLROGCPHYSTREE MMIOTreeR0; 346 /** Tree containing MMIO range descriptors registered for GC (IOMMMIORANGEGC). */ 347 AVLROGCPHYSTREE MMIOTreeGC; 303 /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */ 304 AVLROGCPHYSTREE MMIOTree; 348 305 349 306 /** Tree containing I/O port statistics (IOMIOPORTSTATS). */ … … 382 339 RTGCPTR Alignment; 383 340 384 /** @name Caching of I/O Port ranges and statistics.341 /** @name Caching of I/O Port and MMIO ranges and statistics. 385 342 * (Saves quite some time in rep outs/ins instruction emulation.) 386 343 * @{ */ … … 389 346 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3; 390 347 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3; 391 392 R3R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0; 393 R3R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0; 394 R3R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0; 395 R3R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0; 348 R3PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR3; 349 R3PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR3; 350 351 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0; 352 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0; 353 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0; 354 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0; 355 R0PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR0; 356 R0PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR0; 396 357 397 358 GCPTRTYPE(PIOMIOPORTRANGEGC) pRangeLastReadGC; … … 399 360 GCPTRTYPE(PIOMIOPORTSTATS) pStatsLastReadGC; 400 361 GCPTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteGC; 362 GCPTRTYPE(PIOMMMIORANGE) pMMIORangeLastGC; 363 GCPTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastGC; 401 364 /** @} */ 402 365 … … 472 435 * @param Port Port to lookup. 473 436 */ 474 inline CTXALLSUFF(PIOMIOPORTRANGE) iomIOPortGetRange(PIOM pIOM, RTIOPORT Port)437 DECLINLINE(CTXALLSUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PIOM pIOM, RTIOPORT Port) 475 438 { 476 439 CTXALLSUFF(PIOMIOPORTRANGE) pRange = (CTXALLSUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(IOPortTree), Port); … … 487 450 * @param Port Port to lookup. 488 451 */ 489 inline PIOMIOPORTRANGER3iomIOPortGetRangeHC(PIOM pIOM, RTIOPORT Port)452 DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeHC(PIOM pIOM, RTIOPORT Port) 490 453 { 491 454 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->IOPortTreeR3, Port); … … 503 466 * @param GCPhys Physical address to lookup. 504 467 */ 505 inline CTXALLSUFF(PIOMMMIORANGE) iomMMIOGetRange(PIOM pIOM, RTGCPHYS GCPhys) 506 { 507 CTXALLSUFF(PIOMMMIORANGE) pRange = (CTXALLSUFF(PIOMMMIORANGE))RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(MMIOTree), GCPhys); 468 DECLINLINE(PIOMMMIORANGE) iomMMIOGetRange(PIOM pIOM, RTGCPHYS GCPhys) 469 { 470 PIOMMMIORANGE pRange = CTXALLSUFF(pIOM->pMMIORangeLast); 471 if ( !pRange 472 || GCPhys - pRange->GCPhys >= pRange->cb) 473 CTXALLSUFF(pIOM->pMMIORangeLast) = pRange = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->MMIOTree, GCPhys); 508 474 return pRange; 509 475 } 510 476 511 477 512 /**513 * Gets the MMIO range for the specified physical address in the current context.514 *515 * @returns Pointer to MMIO range.516 * @returns NULL if address not in a MMIO range.517 *518 * @param pIOM IOM instance data.519 * @param GCPhys Physical address to lookup.520 */521 inline PIOMMMIORANGER3 iomMMIOGetRangeHC(PIOM pIOM, RTGCPHYS GCPhys)522 {523 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);524 return pRange;525 }526 527 478 #ifdef VBOX_WITH_STATISTICS 528 479 /** 529 480 * Gets the MMIO statistics record. 481 * 482 * In ring-3 this will lazily create missing records, while in GC/R0 the caller has to 483 * return the appropriate status to defer the operation to ring-3. 484 * 530 485 * @returns Pointer to MMIO stats. 531 * @returns NULL if not found. 532 * 533 * @param pIOM IOM instance data. 534 * @param GCPhys Physical address to lookup. 535 */ 536 inline PIOMMMIOSTATS iomMMIOGetStats(PIOM pIOM, RTGCPHYS GCPhys) 537 { 538 PIOMMMIOSTATS pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pIOM->CTXSUFF(pTrees)->MMIOStatTree, GCPhys); 486 * @returns NULL if not found (R0/GC), or out of memory (R3). 487 * 488 * @param pIOM IOM instance data. 489 * @param GCPhys Physical address to lookup. 490 * @param pRange The MMIO range. 491 */ 492 DECLINLINE(PIOMMMIOSTATS) iomMMIOGetStats(PIOM pIOM, RTGCPHYS GCPhys, PIOMMMIORANGE pRange) 493 { 494 /* For large ranges, we'll put everything on the first byte. */ 495 if (pRange->cb > PAGE_SIZE) 496 GCPhys = pRange->GCPhys; 497 498 PIOMMMIOSTATS pStats = CTXALLSUFF(pIOM->pMMIOStatsLast); 499 if ( !pStats 500 || pStats->Core.Key != GCPhys) 501 { 502 pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pIOM->CTXSUFF(pTrees)->MMIOStatTree, GCPhys); 503 # ifdef IN_RING3 504 if (!pStats) 505 pStats = iomR3MMIOStatsCreate(IOM2VM(pIOM), GCPhys, pRange->pszDesc); 506 # endif 507 } 539 508 return pStats; 540 509 } -
trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
r7731 r7751 159 159 * @warning VBOX_SUCCESS(rc=VINF_IOM_HC_MMIO_WRITE) is TRUE! 160 160 */ 161 DECLINLINE(int) iomMMIODoWrite(PVM pVM, CTXALLSUFF(PIOMMMIORANGE)pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)161 DECLINLINE(int) iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb) 162 162 { 163 163 #ifdef VBOX_WITH_STATISTICS 164 if (pRange->cb <= PAGE_SIZE) 165 { 166 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault); 167 if (!pStats) 168 return VINF_IOM_HC_MMIO_WRITE; 169 170 int rc = pRange->pfnWriteCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */ 171 if (rc != VINF_IOM_HC_MMIO_WRITE) 172 STAM_COUNTER_INC(&pStats->WriteGC); 173 return rc; 174 } 175 #endif 176 return pRange->pfnWriteCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, (void *)pvData, cb); 164 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange); 165 Assert(pStats); 166 #endif 167 168 int rc; 169 if (RT_LIKELY(pRange->CTXALLSUFF(pfnWriteCallback))) 170 rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */ 171 else 172 rc = VINF_SUCCESS; 173 if (rc != VINF_IOM_HC_MMIO_WRITE) 174 STAM_COUNTER_INC(&pStats->CTXALLSUFF(Write)); 175 return rc; 177 176 } 178 177 … … 180 179 * Wrapper which does the read and updates range statistics when such are enabled. 181 180 */ 182 DECLINLINE(int) iomMMIODoRead(PVM pVM, CTXALLSUFF(PIOMMMIORANGE)pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb)181 DECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb) 183 182 { 184 183 #ifdef VBOX_WITH_STATISTICS 185 if (pRange->cb <= PAGE_SIZE) 186 { 187 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault); 188 if (!pStats) 189 return VINF_IOM_HC_MMIO_READ; 190 191 int rc = pRange->pfnReadCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, pvData, cb); 192 if (rc != VINF_IOM_HC_MMIO_READ) 193 STAM_COUNTER_INC(&pStats->ReadGC); 194 return rc; 195 } 196 #endif 197 return pRange->pfnReadCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, pvData, cb); 184 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange); 185 Assert(pStats); 186 #endif 187 188 int rc; 189 if (RT_LIKELY(pRange->CTXALLSUFF(pfnReadCallback))) 190 rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, pvData, cb); 191 else 192 { 193 switch (cb) 194 { 195 case 1: *(uint8_t *)pvData = 0; break; 196 case 2: *(uint16_t *)pvData = 0; break; 197 case 4: *(uint32_t *)pvData = 0; break; 198 case 8: *(uint64_t *)pvData = 0; break; 199 default: 200 memset(pvData, 0, cb); 201 break; 202 } 203 rc = VINF_SUCCESS; 204 } 205 if (rc != VINF_IOM_HC_MMIO_READ) 206 STAM_COUNTER_INC(&pStats->CTXALLSUFF(Read)); 207 return rc; 198 208 } 199 209 … … 323 333 * Internal - statistics only. 324 334 */ 325 inline voidiomMMIOStatLength(PVM pVM, unsigned cb)335 DECLINLINE(void) iomMMIOStatLength(PVM pVM, unsigned cb) 326 336 { 327 337 #ifdef VBOX_WITH_STATISTICS … … 361 371 * @param GCPhysFault The GC physical address corresponding to pvFault. 362 372 */ 363 static int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange, RTGCPHYS GCPhysFault) 364 { 365 /* 366 * If no read handler then go to ring-3 and handle it there. 367 */ 368 if (!pRange->pfnReadCallback) 369 return VINF_IOM_HC_MMIO_READ; 373 static int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault) 374 { 375 Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3); 370 376 371 377 /* … … 424 430 * @param GCPhysFault The GC physical address corresponding to pvFault. 425 431 */ 426 static int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange, RTGCPHYS GCPhysFault) 427 { 428 /* 429 * If no write handler then go to ring-3 and handle it there. 430 */ 431 if (!pRange->pfnWriteCallback) 432 return VINF_IOM_HC_MMIO_WRITE; 432 static int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault) 433 { 434 Assert(pRange->CTXALLSUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3); 433 435 434 436 /* … … 448 450 449 451 450 /** @todo All the string MMIO stuff can do terrible things since physical contiguous mappings are 451 * assumed all over the place! This must be addressed in a general way, like for example let EM do 452 * all the interpretation and checking of selectors and addresses. 453 * 454 * -> I don't see the problem here. MMIO ranges are by definition linear ranges. The virtual source or destination is read/written properly. 455 */ 456 457 452 /** Wrapper for reading virtual memory. */ 458 453 DECLINLINE(int) iomRamRead(PVM pVM, void *pDest, RTGCPTR GCSrc, uint32_t cb) 459 454 { … … 465 460 } 466 461 462 463 /** Wrapper for writing virtual memory. */ 467 464 DECLINLINE(int) iomRamWrite(PVM pVM, RTGCPTR GCDest, void *pSrc, uint32_t cb) 468 465 { … … 474 471 } 475 472 473 474 #ifdef iom_MOVS_SUPPORT 476 475 /** 477 476 * [REP] MOVSB … … 491 490 * @param pRange Pointer MMIO range. 492 491 */ 493 #ifdef iom_MOVS_SUPPORT 494 static int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange) 495 { 496 STAM_PROFILE_START(&pVM->iom.s.StatGCInstMovs, a); 497 492 static int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 493 { 498 494 /* 499 495 * We do not support segment prefixes or REPNE. 500 496 */ 501 497 if (pCpu->prefix & (PREFIX_SEG | PREFIX_REPNE)) 502 return VINF_IOM_HC_MMIO_READ_WRITE; 498 return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> interpret whatever. */ 503 499 504 500 … … 531 527 pVM->iom.s.cMovsMaxBytes = cTransfers << SIZE_2_SHIFT(cb); 532 528 #endif 529 530 /** @todo re-evaluate on page boundraries. */ 533 531 534 532 RTGCPHYS Phys = GCPhysFault; … … 543 541 544 542 /* Check callback. */ 545 if (!pRange-> pfnWriteCallback)543 if (!pRange->CTXALLSUFF(pfnWriteCallback)) 546 544 { 547 545 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovsToMMIO, a2); … … 552 550 RTGCUINTPTR pu8Virt; 553 551 rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid, 554 555 552 SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL, 553 (PRTGCPTR)&pu8Virt, NULL); 556 554 if (VBOX_SUCCESS(rc)) 557 555 { … … 617 615 618 616 /* Check if destination address is MMIO. */ 617 PIOMMMIORANGE pMMIODst; 619 618 RTGCPHYS PhysDst; 620 619 rc = PGMGstGetPage(pVM, (RTGCPTR)pu8Virt, NULL, &PhysDst); 620 PhysDst |= (RTGCUINTPTR)pu8Virt & PAGE_OFFSET_MASK; 621 621 if ( VBOX_SUCCESS(rc) 622 && iomMMIOGetRangeHC(&pVM->iom.s, PhysDst))622 && (pMMIODst = iomMMIOGetRange(&pVM->iom.s, PhysDst))) 623 623 { 624 624 /* … … 628 628 STAM_PROFILE_START(&pVM->iom.s.StatGCInstMovsFromMMIO, c); 629 629 630 PhysDst |= (RTGCUINTPTR)pu8Virt & PAGE_OFFSET_MASK; 631 CTXALLSUFF(PIOMMMIORANGE) pMMIODst = iomMMIOGetRange(&pVM->iom.s, PhysDst); 632 if ( !pMMIODst 633 || !pMMIODst->pfnWriteCallback) 630 if (!pMMIODst->CTXALLSUFF(pfnWriteCallback) && pMMIODst->pfnWriteCallbackR3) 634 631 { 635 632 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovsMMIO, d); … … 711 708 if (rc == VINF_SUCCESS) 712 709 { 713 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovs, a);714 710 iomMMIOStatLength(pVM, cb); 715 711 } … … 736 732 * @param pRange Pointer MMIO range. 737 733 */ 738 static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange) 739 { 740 STAM_PROFILE_START(&pVM->iom.s.StatGCInstStos, a); 741 734 static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 735 { 742 736 /* 743 737 * We do not support segment prefixes or REPNE.. 744 738 */ 745 739 if (pCpu->prefix & (PREFIX_SEG | PREFIX_REPNE)) 746 return VINF_IOM_HC_MMIO_READ_WRITE; 740 return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> REM instead of HC */ 747 741 748 742 /* … … 776 770 uint32_t u32Data = pRegFrame->eax; 777 771 int rc; 778 if (pRange-> pfnFillCallback)772 if (pRange->CTXALLSUFF(pfnFillCallback)) 779 773 { 780 774 /* … … 785 779 { 786 780 /* addr++ variant. */ 787 rc = pRange-> pfnFillCallback(pRange->pDevIns, pRange->pvUser, Phys, u32Data, cb, cTransfers);781 rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), Phys, u32Data, cb, cTransfers); 788 782 if (rc == VINF_SUCCESS) 789 783 { … … 797 791 { 798 792 /* addr-- variant. */ 799 rc = pRange-> pfnFillCallback(pRange->pDevIns, pRange->pvUser, (Phys - (cTransfers - 1)) << SIZE_2_SHIFT(cb), u32Data, cb, cTransfers);793 rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), (Phys - (cTransfers - 1)) << SIZE_2_SHIFT(cb), u32Data, cb, cTransfers); 800 794 if (rc == VINF_SUCCESS) 801 795 { … … 812 806 * Use the write callback. 813 807 */ 814 /* Check write callback. */ 815 if (!pRange->pfnWriteCallback) 816 return VINF_IOM_HC_MMIO_WRITE; 808 Assert(pRange->CTXALLSUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3); 817 809 818 810 /* fill loop. */ … … 837 829 */ 838 830 if (rc == VINF_SUCCESS) 839 {840 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstStos, a);841 831 iomMMIOStatLength(pVM, cb); 842 }843 832 return rc; 844 833 } … … 861 850 * @param pRange Pointer MMIO range. 862 851 */ 863 static int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE)pRange)864 { 865 STAM_PROFILE_START(&pVM->iom.s.StatGCInstLods, a1);852 static int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 853 { 854 Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3); 866 855 867 856 /* … … 869 858 */ 870 859 if (pCpu->prefix & (PREFIX_SEG | PREFIX_REP | PREFIX_REPNE)) 871 return VINF_IOM_HC_MMIO_READ_WRITE; 872 873 /* Check that we can handle it. */ 874 if (!pRange->pfnReadCallback) 875 return VINF_IOM_HC_MMIO_READ; 860 return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> REM instead of HC */ 876 861 877 862 /* … … 893 878 */ 894 879 if (rc == VINF_SUCCESS) 895 {896 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstLods, a1);897 880 iomMMIOStatLength(pVM, cb); 898 }899 881 return rc; 900 882 } … … 916 898 * @param pRange Pointer MMIO range. 917 899 */ 918 static int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange) 919 { 920 STAM_PROFILE_START(&pVM->iom.s.StatGCInstCmp, a1); 921 922 /* Check read callback. */ 923 if (!pRange->pfnReadCallback) 924 return VINF_EM_RAW_GUEST_TRAP; 900 static int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 901 { 902 Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3); 925 903 926 904 /* … … 949 927 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)) 950 928 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)); 951 952 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstCmp, a1);953 929 iomMMIOStatLength(pVM, cb); 954 930 } … … 973 949 * @param pRange Pointer MMIO range. 974 950 */ 975 static int iomInterpretAND(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange) 976 { 977 STAM_PROFILE_START(&pVM->iom.s.StatGCInstAnd, a1); 978 979 /* Check read callback. */ 980 951 static int iomInterpretAND(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 952 { 981 953 unsigned cb = 0; 982 954 uint32_t uData1; … … 987 959 { 988 960 /* and reg, [MMIO]. */ 961 Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3); 989 962 fAndWrite = false; 990 if (pRange->pfnReadCallback) 991 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb); 992 else 993 rc = VINF_IOM_HC_MMIO_READ; 963 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb); 994 964 } 995 965 else if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb)) … … 997 967 /* and [MMIO], reg|imm. */ 998 968 fAndWrite = true; 999 if (pRange->pfnReadCallback && pRange->pfnWriteCallback) 969 if ( (pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3) 970 && (pRange->CTXALLSUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3)) 1000 971 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb); 1001 972 else … … 1026 997 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)) 1027 998 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)); 1028 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstAnd, a1);1029 999 iomMMIOStatLength(pVM, cb); 1030 1000 } … … 1051 1021 * @param pRange Pointer MMIO range. 1052 1022 */ 1053 static int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange) 1054 { 1055 STAM_PROFILE_START(&pVM->iom.s.StatGCInstTest, a1); 1056 1057 /* Check read callback. */ 1023 static int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 1024 { 1025 Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3); 1058 1026 1059 1027 unsigned cb = 0; … … 1065 1033 { 1066 1034 /* and test, [MMIO]. */ 1067 if (pRange->pfnReadCallback) 1068 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb); 1069 else 1070 rc = VINF_IOM_HC_MMIO_READ; 1035 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb); 1071 1036 } 1072 1037 else if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb)) 1073 1038 { 1074 1039 /* test [MMIO], reg|imm. */ 1075 if (pRange->pfnReadCallback) 1076 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb); 1077 else 1078 rc = VINF_IOM_HC_MMIO_READ; 1040 rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb); 1079 1041 } 1080 1042 else … … 1090 1052 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)) 1091 1053 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)); 1092 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstTest, a1);1093 1054 iomMMIOStatLength(pVM, cb); 1094 1055 } … … 1112 1073 * @param pRange Pointer MMIO range. 1113 1074 */ 1114 static int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange) 1115 { 1116 STAM_PROFILE_START(&pVM->iom.s.StatGCInstTest, a1); 1117 1118 /* Check read callback. */ 1075 static int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange) 1076 { 1077 /* Check for read & write handlers since IOMMMIOHandler doesn't cover this. */ 1078 if ( (!pRange->CTXALLSUFF(pfnReadCallback) && pRange->pfnReadCallbackR3) 1079 || (!pRange->CTXALLSUFF(pfnWriteCallback) && pRange->pfnWriteCallbackR3)) 1080 return VINF_IOM_HC_MMIO_READ_WRITE; 1081 1082 int rc; 1119 1083 unsigned cb = 0; 1120 1084 uint32_t uData1; 1121 1085 uint32_t uData2; 1122 int rc;1123 1124 if (!pRange->pfnReadCallback || !pRange->pfnWriteCallback)1125 {1126 rc = VINF_IOM_HC_MMIO_READ;1127 goto end;1128 }1129 1130 1086 if (iomGetRegImmData(pCpu, &pCpu->param1, pRegFrame, &uData1, &cb)) 1131 1087 { … … 1149 1105 Assert(rc == VINF_IOM_HC_MMIO_READ || rc == VINF_PATM_HC_MMIO_PATCH_READ); 1150 1106 } 1151 else 1152 if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb)) 1107 else if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb)) 1153 1108 { 1154 1109 /* xchg [MMIO], reg. */ … … 1158 1113 /* Store result to MMIO. */ 1159 1114 rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &uData2, cb); 1160 1161 1115 if (rc == VINF_SUCCESS) 1162 1116 { … … 1175 1129 AssertMsgFailed(("Disassember XCHG problem..\n")); 1176 1130 rc = VERR_IOM_MMIO_HANDLER_DISASM_ERROR; 1177 goto end; 1178 } 1179 1180 end: 1181 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstTest, a1); 1131 } 1182 1132 return rc; 1183 1133 } 1184 1134 1185 1186 #ifdef IN_RING01187 1188 /**1189 * Read callback for disassembly function; supports reading bytes that cross a page boundary1190 *1191 * @returns VBox status code.1192 * @param pSrc GC source pointer1193 * @param pDest HC destination pointer1194 * @param size Number of bytes to read1195 * @param pvUserdata Callback specific user data (pCpu)1196 *1197 */1198 DECLCALLBACK(int) iomReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata)1199 {1200 DISCPUSTATE *pCpu = (DISCPUSTATE *)pvUserdata;1201 PVM pVM = (PVM)pCpu->apvUserData[0];1202 1203 int rc = PGMPhysReadGCPtr(pVM, pDest, pSrc, size);1204 AssertRC(rc);1205 return rc;1206 }1207 1208 inline bool iomDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)1209 {1210 return VBOX_SUCCESS(DISCoreOneEx(InstrGC, pCpu->mode, iomReadBytes, pVM, pCpu, pOpsize));1211 }1212 #else1213 inline bool iomDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)1214 {1215 return VBOX_SUCCESS(DISCoreOne(pCpu, InstrGC, pOpsize));1216 }1217 1218 #endif1219 1135 1220 1136 /** … … 1225 1141 * @param pVM VM Handle. 1226 1142 * @param uErrorCode CPU Error code. 1227 * @param p RegFrameTrap register frame.1143 * @param pCtxCore Trap register frame. 1228 1144 * @param pvFault The fault address (cr2). 1229 1145 * @param GCPhysFault The GC physical address corresponding to pvFault. 1230 1146 * @param pvUser Pointer to the MMIO ring-3 range entry. 1231 1147 */ 1232 IOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE p RegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)1148 IOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser) 1233 1149 { 1234 1150 STAM_PROFILE_START(&pVM->iom.s.StatGCMMIOHandler, a); 1235 NOREF(pvUser); /** @todo implement pvUser usage! */1236 1151 Log3(("IOMMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%p eip=%RGv\n", 1237 GCPhysFault, uErrorCode, pvFault, pRegFrame->eip)); 1238 1239 /* 1240 * Find the corresponding MMIO range. 1241 */ 1242 CTXALLSUFF(PIOMMMIORANGE) pRange = iomMMIOGetRange(&pVM->iom.s, GCPhysFault); 1243 if (!pRange) 1244 { 1152 GCPhysFault, uErrorCode, pvFault, pCtxCore->eip)); 1153 1154 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser; 1155 Assert(pRange); 1156 Assert(pRange == iomMMIOGetRange(&pVM->iom.s, GCPhysFault)); 1157 1245 1158 #ifdef VBOX_WITH_STATISTICS 1246 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault); 1247 if (pStats) 1159 /* 1160 * Locate the statistics, if > PAGE_SIZE we'll use the first byte for everything. 1161 */ 1162 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange); 1163 if (!pStats) 1164 { 1165 # ifdef IN_RING3 1166 return VERR_NO_MEMORY; 1167 # else 1168 STAM_PROFILE_STOP(&pVM->iom.s.StatGCMMIOHandler, a); 1169 STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures); 1170 return uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ; 1171 # endif 1172 } 1173 #endif 1174 1175 #ifndef IN_RING3 1176 /* 1177 * Should we defer the request right away? 1178 */ 1179 if (uErrorCode & X86_TRAP_PF_RW 1180 ? !pRange->CTXALLSUFF(pfnWriteCallback) && !pRange->pfnWriteCallbackR3 1181 : !pRange->CTXALLSUFF(pfnReadCallback) && !pRange->pfnReadCallbackR3) 1182 { 1183 # ifdef VBOX_WITH_STATISTICS 1184 if (uErrorCode & X86_TRAP_PF_RW) 1185 STAM_COUNTER_INC(&pStats->CTXALLMID(Write,ToR3)); 1186 else 1187 STAM_COUNTER_INC(&pStats->CTXALLMID(Read,ToR3)); 1188 # endif 1189 1190 STAM_PROFILE_STOP(&pVM->iom.s.StatGCMMIOHandler, a); 1191 STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures); 1192 return uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ; 1193 } 1194 #endif /* !IN_RING3 */ 1195 1196 /* 1197 * Disassemble the instruction and interprete it. 1198 */ 1199 DISCPUSTATE Cpu; 1200 unsigned cbOp; 1201 int rc = EMInterpretDisasOne(pVM, pCtxCore, &Cpu, &cbOp); 1202 AssertRCReturn(rc, rc); 1203 switch (Cpu.pCurInstr->opcode) 1204 { 1205 case OP_MOV: 1206 case OP_MOVZX: 1207 case OP_MOVSX: 1248 1208 { 1209 STAM_PROFILE_START(&pVM->iom.s.StatGCInstMov, b); 1249 1210 if (uErrorCode & X86_TRAP_PF_RW) 1250 STAM_COUNTER_INC(&pStats->WriteGCToR3);1211 rc = iomInterpretMOVxXWrite(pVM, pCtxCore, &Cpu, pRange, GCPhysFault); 1251 1212 else 1252 STAM_COUNTER_INC(&pStats->ReadGCToR3); 1213 rc = iomInterpretMOVxXRead(pVM, pCtxCore, &Cpu, pRange, GCPhysFault); 1214 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMov, b); 1215 break; 1253 1216 } 1254 #endif 1255 PIOMMMIORANGER3 pRangeR3 = iomMMIOGetRangeHC(&pVM->iom.s, GCPhysFault); 1256 if (pRangeR3) 1257 { 1258 STAM_PROFILE_START(&pVM->iom.s.StatGCMMIOHandler, a); 1259 STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures); 1260 return (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ; 1261 } 1217 1218 1219 #ifdef iom_MOVS_SUPPORT 1220 case OP_MOVSB: 1221 case OP_MOVSWD: 1222 STAM_PROFILE_START(&pVM->iom.s.StatGCInstMovs, c); 1223 rc = iomInterpretMOVS(pVM, uErrorCode, pCtxCore, GCPhysFault, &Cpu, pRange); 1224 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovs, c); 1225 break; 1226 #endif 1227 1228 case OP_STOSB: 1229 case OP_STOSWD: 1230 Assert(uErrorCode & X86_TRAP_PF_RW); 1231 STAM_PROFILE_START(&pVM->iom.s.StatGCInstStos, d); 1232 rc = iomInterpretSTOS(pVM, pCtxCore, GCPhysFault, &Cpu, pRange); 1233 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstStos, d); 1234 break; 1235 1236 case OP_LODSB: 1237 case OP_LODSWD: 1238 Assert(!(uErrorCode & X86_TRAP_PF_RW)); 1239 STAM_PROFILE_START(&pVM->iom.s.StatGCInstLods, e); 1240 rc = iomInterpretLODS(pVM, pCtxCore, GCPhysFault, &Cpu, pRange); 1241 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstLods, e); 1242 break; 1243 1244 case OP_CMP: 1245 Assert(!(uErrorCode & X86_TRAP_PF_RW)); 1246 STAM_PROFILE_START(&pVM->iom.s.StatGCInstCmp, f); 1247 rc = iomInterpretCMP(pVM, pCtxCore, GCPhysFault, &Cpu, pRange); 1248 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstCmp, f); 1249 break; 1250 1251 case OP_AND: 1252 STAM_PROFILE_START(&pVM->iom.s.StatGCInstAnd, g); 1253 rc = iomInterpretAND(pVM, pCtxCore, GCPhysFault, &Cpu, pRange); 1254 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstAnd, g); 1255 break; 1256 1257 case OP_TEST: 1258 Assert(!(uErrorCode & X86_TRAP_PF_RW)); 1259 STAM_PROFILE_START(&pVM->iom.s.StatGCInstTest, h); 1260 rc = iomInterpretTEST(pVM, pCtxCore, GCPhysFault, &Cpu, pRange); 1261 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstTest, h); 1262 break; 1263 1264 case OP_XCHG: 1265 STAM_PROFILE_START(&pVM->iom.s.StatGCInstXchg, i); 1266 rc = iomInterpretXCHG(pVM, pCtxCore, GCPhysFault, &Cpu, pRange); 1267 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstXchg, i); 1268 break; 1269 1262 1270 1263 1271 /* 1264 * Now, why are we here...1272 * The instruction isn't supported. Hand it on to ring-3. 1265 1273 */ 1266 AssertMsgFailed(("Internal error! GCPhysFault=%x\n", GCPhysFault)); 1267 return VERR_IOM_MMIO_HANDLER_BOGUS_CALL; 1268 } 1269 1270 /* 1271 * Convert CS:EIP to linear address and initialize the disassembler. 1272 */ 1273 DISCPUSTATE cpu; 1274 cpu.mode = SELMIsSelector32Bit(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) ? CPUMODE_32BIT : CPUMODE_16BIT; 1275 1276 RTGCPTR pvCode; 1277 int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)(cpu.mode == CPUMODE_32BIT ? pRegFrame->eip : pRegFrame->eip & 0xffff), &pvCode); 1278 if (VBOX_FAILURE(rc)) 1279 { 1280 AssertMsgFailed(("Internal error! cs:eip=%04x:%08x rc=%Vrc\n", pRegFrame->cs, pRegFrame->eip, rc)); 1281 return VERR_IOM_MMIO_HANDLER_BOGUS_CALL; 1282 } 1283 1284 /* 1285 * Disassemble the instruction and interprete it. 1286 */ 1287 unsigned cbOp; 1288 if (iomDisCoreOne(pVM, &cpu, (RTGCUINTPTR)pvCode, &cbOp)) 1289 { 1290 switch (cpu.pCurInstr->opcode) 1291 { 1292 case OP_MOV: 1293 case OP_MOVZX: 1294 case OP_MOVSX: 1295 { 1296 STAM_PROFILE_START(&pVM->iom.s.StatGCInstMov, b); 1297 if (uErrorCode & X86_TRAP_PF_RW) 1298 rc = iomInterpretMOVxXWrite(pVM, pRegFrame, &cpu, pRange, GCPhysFault); 1299 else 1300 rc = iomInterpretMOVxXRead(pVM, pRegFrame, &cpu, pRange, GCPhysFault); 1301 if (rc == VINF_SUCCESS) 1302 STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMov, b); 1303 break; 1304 } 1305 1306 1307 #ifdef iom_MOVS_SUPPORT 1308 case OP_MOVSB: 1309 case OP_MOVSWD: 1310 rc = iomInterpretMOVS(pVM, uErrorCode, pRegFrame, GCPhysFault, &cpu, pRange); 1311 break; 1312 #endif 1313 1314 case OP_STOSB: 1315 case OP_STOSWD: 1316 Assert(uErrorCode & X86_TRAP_PF_RW); 1317 rc = iomInterpretSTOS(pVM, pRegFrame, GCPhysFault, &cpu, pRange); 1318 break; 1319 1320 case OP_LODSB: 1321 case OP_LODSWD: 1322 Assert(!(uErrorCode & X86_TRAP_PF_RW)); 1323 rc = iomInterpretLODS(pVM, pRegFrame, GCPhysFault, &cpu, pRange); 1324 break; 1325 1326 1327 case OP_CMP: 1328 Assert(!(uErrorCode & X86_TRAP_PF_RW)); 1329 rc = iomInterpretCMP(pVM, pRegFrame, GCPhysFault, &cpu, pRange); 1330 break; 1331 1332 case OP_AND: 1333 rc = iomInterpretAND(pVM, pRegFrame, GCPhysFault, &cpu, pRange); 1334 break; 1335 1336 case OP_TEST: 1337 Assert(!(uErrorCode & X86_TRAP_PF_RW)); 1338 rc = iomInterpretTEST(pVM, pRegFrame, GCPhysFault, &cpu, pRange); 1339 break; 1340 1341 case OP_XCHG: 1342 rc = iomInterpretXCHG(pVM, pRegFrame, GCPhysFault, &cpu, pRange); 1343 break; 1344 1345 1346 /* 1347 * The instruction isn't supported. Hand it on to ring-3. 1348 */ 1349 default: 1350 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOther); 1351 rc = (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ; 1352 break; 1353 } 1354 } 1274 default: 1275 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOther); 1276 rc = (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ; 1277 break; 1278 } 1279 1280 /* 1281 * On success advance EIP. 1282 */ 1283 if (rc == VINF_SUCCESS) 1284 pCtxCore->eip += cbOp; 1355 1285 else 1356 1286 { 1357 AssertMsgFailed(("Disassembler freaked out!\n"));1358 rc = VERR_IOM_MMIO_HANDLER_DISASM_ERROR;1359 }1360 1361 /*1362 * On success advance EIP.1363 */1364 if (rc == VINF_SUCCESS)1365 pRegFrame->eip += cbOp;1366 else1367 {1368 1287 STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures); 1369 #if def VBOX_WITH_STATISTICS1288 #if defined(VBOX_WITH_STATISTICS) && !defined(IN_RING3) 1370 1289 switch (rc) 1371 1290 { 1372 1291 case VINF_IOM_HC_MMIO_READ: 1292 case VINF_IOM_HC_MMIO_READ_WRITE: 1293 STAM_COUNTER_INC(&pStats->CTXALLMID(Read,ToR3)); 1294 break; 1373 1295 case VINF_IOM_HC_MMIO_WRITE: 1374 case VINF_IOM_HC_MMIO_READ_WRITE: 1375 { 1376 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault); 1377 if (pStats) 1378 { 1379 if (uErrorCode & X86_TRAP_PF_RW) 1380 STAM_COUNTER_INC(&pStats->WriteGCToR3); 1381 else 1382 STAM_COUNTER_INC(&pStats->ReadGCToR3); 1383 } 1384 } 1385 break; 1296 STAM_COUNTER_INC(&pStats->CTXALLMID(Write,ToR3)); 1297 break; 1386 1298 } 1387 1299 #endif 1388 1300 } 1301 1389 1302 STAM_PROFILE_STOP(&pVM->iom.s.StatGCMMIOHandler, a); 1390 1303 return rc; … … 1404 1317 IOMDECL(int) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue) 1405 1318 { 1406 /** @todo add return to ring-3 statistics when this function is used in GC! */1407 1408 1319 /* 1409 1320 * Lookup the current context range node and statistics. 1410 1321 */ 1411 CTXALLSUFF(PIOMMMIORANGE) pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys); 1322 PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys); 1323 AssertMsgReturn(pRange, 1324 ("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue), 1325 VERR_INTERNAL_ERROR); 1412 1326 #ifdef VBOX_WITH_STATISTICS 1413 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys );1414 if (!pStats && (!pRange || pRange->cb <= PAGE_SIZE))1327 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange); 1328 if (!pStats) 1415 1329 # ifdef IN_RING3 1416 pStats = iomR3MMIOStatsCreate(pVM, GCPhys, pRange ? pRange->pszDesc : NULL);1330 return VERR_NO_MEMORY; 1417 1331 # else 1418 1332 return VINF_IOM_HC_MMIO_READ; 1419 1333 # endif 1420 1334 #endif /* VBOX_WITH_STATISTICS */ 1421 #ifdef IN_RING3 1422 if (pRange) 1423 #else /* !IN_RING3 */ 1424 if (pRange && pRange->pfnReadCallback) 1425 #endif /* !IN_RING3 */ 1335 if (pRange->CTXALLSUFF(pfnReadCallback)) 1426 1336 { 1427 1337 /* … … 1432 1342 STAM_PROFILE_ADV_START(&pStats->CTXALLSUFF(ProfRead), a); 1433 1343 #endif 1434 int rc = pRange-> pfnReadCallback(pRange->pDevIns, pRange->pvUser, GCPhys, pu32Value, cbValue);1344 int rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, pu32Value, cbValue); 1435 1345 #ifdef VBOX_WITH_STATISTICS 1436 1346 if (pStats) … … 1469 1379 } 1470 1380 } 1471 1472 1381 #ifndef IN_RING3 1382 if (pRange->pfnReadCallbackR3) 1383 { 1384 STAM_COUNTER_INC(&pStats->CTXALLMID(Read,ToR3)); 1385 return VINF_IOM_HC_MMIO_READ; 1386 } 1387 #endif 1388 1473 1389 /* 1474 1390 * Lookup the ring-3 range. 1475 1391 */ 1476 PIOMMMIORANGER3 pRangeR3 = iomMMIOGetRangeHC(&pVM->iom.s, GCPhys); 1477 if (pRangeR3) 1478 { 1479 if (pRangeR3->pfnReadCallback) 1480 return VINF_IOM_HC_MMIO_READ; 1481 # ifdef VBOX_WITH_STATISTICS 1482 if (pStats) 1483 STAM_COUNTER_INC(&pStats->CTXALLSUFF(Read)); 1484 # endif 1485 *pu32Value = 0; 1486 Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue)); 1487 return VINF_SUCCESS; 1488 } 1489 #endif 1490 1491 AssertMsgFailed(("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue)); 1492 return VERR_INTERNAL_ERROR; 1392 #ifdef VBOX_WITH_STATISTICS 1393 if (pStats) 1394 STAM_COUNTER_INC(&pStats->CTXALLSUFF(Read)); 1395 #endif 1396 *pu32Value = 0; 1397 Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue)); 1398 return VINF_SUCCESS; 1493 1399 } 1494 1400 … … 1506 1412 IOMDECL(int) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue) 1507 1413 { 1508 /** @todo add return to ring-3 statistics when this function is used in GC! */1509 1414 /* 1510 1415 * Lookup the current context range node. 1511 1416 */ 1512 CTXALLSUFF(PIOMMMIORANGE) pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys); 1417 PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys); 1418 AssertMsgReturn(pRange, 1419 ("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue), 1420 VERR_INTERNAL_ERROR); 1513 1421 #ifdef VBOX_WITH_STATISTICS 1514 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys );1515 if (!pStats && (!pRange || pRange->cb <= PAGE_SIZE))1422 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange); 1423 if (!pStats) 1516 1424 # ifdef IN_RING3 1517 pStats = iomR3MMIOStatsCreate(pVM, GCPhys, pRange ? pRange->pszDesc : NULL);1425 return VERR_NO_MEMORY; 1518 1426 # else 1519 1427 return VINF_IOM_HC_MMIO_WRITE; … … 1522 1430 1523 1431 /* 1524 * Perform the write if we found a range. 1525 */ 1526 #ifdef IN_RING3 1527 if (pRange) 1528 #else /* !IN_RING3 */ 1529 if (pRange && pRange->pfnWriteCallback) 1530 #endif /* !IN_RING3 */ 1432 * Perform the write if there's a write handler. R0/GC may have 1433 * to defer it to ring-3. 1434 */ 1435 if (pRange->CTXALLSUFF(pfnWriteCallback)) 1531 1436 { 1532 1437 #ifdef VBOX_WITH_STATISTICS … … 1534 1439 STAM_PROFILE_ADV_START(&pStats->CTXALLSUFF(ProfWrite), a); 1535 1440 #endif 1536 int rc = pRange-> pfnWriteCallback(pRange->pDevIns, pRange->pvUser, GCPhys, &u32Value, cbValue);1441 int rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, &u32Value, cbValue); 1537 1442 #ifdef VBOX_WITH_STATISTICS 1538 1443 if (pStats) … … 1544 1449 return rc; 1545 1450 } 1546 1547 1451 #ifndef IN_RING3 1548 /* 1549 * Lookup the ring-3 range. 1550 */ 1551 PIOMMMIORANGER3 pRangeR3 = iomMMIOGetRangeHC(&pVM->iom.s, GCPhys); 1552 if (pRangeR3) 1553 { 1554 if (pRangeR3->pfnWriteCallback) 1555 return VINF_IOM_HC_MMIO_WRITE; 1556 # ifdef VBOX_WITH_STATISTICS 1557 if (pStats) 1558 STAM_COUNTER_INC(&pStats->CTXALLSUFF(Write)); 1559 # endif 1560 Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, u32Value, cbValue)); 1561 return VINF_SUCCESS; 1562 } 1563 #endif 1564 1565 AssertMsgFailed(("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue)); 1566 return VERR_INTERNAL_ERROR; 1452 if (pRange->pfnWriteCallbackR3) 1453 { 1454 STAM_COUNTER_INC(&pStats->CTXALLMID(Write,ToR3)); 1455 return VINF_IOM_HC_MMIO_WRITE; 1456 } 1457 #endif 1458 1459 /* 1460 * No write handler, nothing to do. 1461 */ 1462 #ifdef VBOX_WITH_STATISTICS 1463 if (pStats) 1464 STAM_COUNTER_INC(&pStats->CTXALLSUFF(Write)); 1465 #endif 1466 Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, u32Value, cbValue, VINF_SUCCESS)); 1467 return VINF_SUCCESS; 1567 1468 } 1568 1469 -
trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
r7731 r7751 122 122 123 123 GEN_CHECK_SIZE(IOM); 124 125 GEN_CHECK_SIZE(IOMMMIORANGER0); 126 GEN_CHECK_OFF(IOMMMIORANGER0, GCPhys); 127 GEN_CHECK_OFF(IOMMMIORANGER0, cb); 128 GEN_CHECK_OFF(IOMMMIORANGER0, pvUser); 129 GEN_CHECK_OFF(IOMMMIORANGER0, pDevIns); 130 GEN_CHECK_OFF(IOMMMIORANGER0, pfnWriteCallback); 131 GEN_CHECK_OFF(IOMMMIORANGER0, pszDesc); 132 133 GEN_CHECK_SIZE(IOMMMIORANGEGC); 134 GEN_CHECK_OFF(IOMMMIORANGEGC, GCPhys); 135 GEN_CHECK_OFF(IOMMMIORANGEGC, cb); 136 GEN_CHECK_OFF(IOMMMIORANGEGC, pvUser); 137 GEN_CHECK_OFF(IOMMMIORANGEGC, pDevIns); 138 GEN_CHECK_OFF(IOMMMIORANGEGC, pfnWriteCallback); 139 GEN_CHECK_OFF(IOMMMIORANGEGC, pszDesc); 124 GEN_CHECK_OFF(IOM, pMMIORangeLastR3); 125 GEN_CHECK_OFF(IOM, pMMIOStatsLastR3); 126 GEN_CHECK_OFF(IOM, pMMIORangeLastR0); 127 GEN_CHECK_OFF(IOM, pMMIOStatsLastR0); 128 GEN_CHECK_OFF(IOM, pMMIORangeLastGC); 129 GEN_CHECK_OFF(IOM, pMMIOStatsLastGC); 130 GEN_CHECK_OFF(IOM, pRangeLastReadR0); 131 GEN_CHECK_OFF(IOM, pRangeLastReadGC); 132 133 GEN_CHECK_SIZE(IOMMMIORANGE); 134 GEN_CHECK_OFF(IOMMMIORANGE, GCPhys); 135 GEN_CHECK_OFF(IOMMMIORANGE, cb); 136 GEN_CHECK_OFF(IOMMMIORANGE, pszDesc); 137 GEN_CHECK_OFF(IOMMMIORANGE, pvUserR3); 138 GEN_CHECK_OFF(IOMMMIORANGE, pDevInsR3); 139 GEN_CHECK_OFF(IOMMMIORANGE, pfnWriteCallbackR3); 140 GEN_CHECK_OFF(IOMMMIORANGE, pfnReadCallbackR3); 141 GEN_CHECK_OFF(IOMMMIORANGE, pfnFillCallbackR3); 142 GEN_CHECK_OFF(IOMMMIORANGE, pvUserR0); 143 GEN_CHECK_OFF(IOMMMIORANGE, pDevInsR0); 144 GEN_CHECK_OFF(IOMMMIORANGE, pfnWriteCallbackR0); 145 GEN_CHECK_OFF(IOMMMIORANGE, pfnReadCallbackR0); 146 GEN_CHECK_OFF(IOMMMIORANGE, pfnFillCallbackR0); 147 GEN_CHECK_OFF(IOMMMIORANGE, pvUserGC); 148 GEN_CHECK_OFF(IOMMMIORANGE, pDevInsGC); 149 GEN_CHECK_OFF(IOMMMIORANGE, pfnWriteCallbackGC); 150 GEN_CHECK_OFF(IOMMMIORANGE, pfnReadCallbackGC); 151 GEN_CHECK_OFF(IOMMMIORANGE, pfnFillCallbackGC); 140 152 141 153 GEN_CHECK_SIZE(IOMMMIOSTATS); … … 163 175 GEN_CHECK_OFF(IOMTREES, IOPortTreeR0); 164 176 GEN_CHECK_OFF(IOMTREES, IOPortTreeGC); 165 GEN_CHECK_OFF(IOMTREES, MMIOTreeR3); 166 GEN_CHECK_OFF(IOMTREES, MMIOTreeR0); 167 GEN_CHECK_OFF(IOMTREES, MMIOTreeGC); 177 GEN_CHECK_OFF(IOMTREES, MMIOTree); 168 178 GEN_CHECK_OFF(IOMTREES, IOPortStatTree); 169 179 GEN_CHECK_OFF(IOMTREES, MMIOStatTree);
Note:
See TracChangeset
for help on using the changeset viewer.