669
668
if (pvSharedPage)
671
670
/* Get the virtual address of the new page. */
673
rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvNewPage);
675
if (rc == VINF_SUCCESS)
671
PGMPAGEMAPLOCK PgMpLck;
673
rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvNewPage, &PgMpLck); AssertRC(rc);
677
/** @todo todo write ASMMemCopyPage */
678
memcpy(pvNewPage, pvSharedPage, PAGE_SIZE);
676
memcpy(pvNewPage, pvSharedPage, PAGE_SIZE); /** @todo todo write ASMMemCopyPage */
677
pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
1025
1025
const uint32_t idChunk = PGM_PAGE_GET_CHUNKID(pPage);
1026
1026
if (idChunk == NIL_GMM_CHUNKID)
1028
AssertMsgReturn(PGM_PAGE_GET_PAGEID(pPage) == NIL_GMM_PAGEID, ("pPage=%R[pgmpage]\n", pPage), VERR_INTERNAL_ERROR_2);
1028
AssertMsgReturn(PGM_PAGE_GET_PAGEID(pPage) == NIL_GMM_PAGEID, ("pPage=%R[pgmpage]\n", pPage), VERR_PGM_PHYS_PAGE_MAP_IPE_1);
1029
1029
if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2)
1031
1031
/* Lookup the MMIO2 range and use pvR3 to calc the address. */
1032
1032
PPGMRAMRANGE pRam = pgmPhysGetRange(pVM, GCPhys);
1033
AssertMsgReturn(pRam || !pRam->pvR3, ("pRam=%p pPage=%R[pgmpage]\n", pRam, pPage), VERR_INTERNAL_ERROR_2);
1033
AssertMsgReturn(pRam || !pRam->pvR3, ("pRam=%p pPage=%R[pgmpage]\n", pRam, pPage), VERR_PGM_PHYS_PAGE_MAP_IPE_2);
1034
1034
*ppv = (void *)((uintptr_t)pRam->pvR3 + (uintptr_t)((GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK) - pRam->GCPhys));
1036
1036
else if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2_ALIAS_MMIO)
1039
1039
* One solution would be to seed MMIO2 pages to GMM and get unique Page IDs for
1040
1040
* them, that would also avoid this mess. It would actually be kind of
1041
1041
* elegant... */
1042
AssertLogRelMsgFailedReturn(("%RGp\n", GCPhys), VERR_INTERNAL_ERROR_3);
1042
AssertLogRelMsgFailedReturn(("%RGp\n", GCPhys), VERR_PGM_MAP_MMIO2_ALIAS_MMIO);
1046
1046
/** @todo handle MMIO2 */
1047
AssertMsgReturn(PGM_PAGE_IS_ZERO(pPage), ("pPage=%R[pgmpage]\n", pPage), VERR_INTERNAL_ERROR_2);
1047
AssertMsgReturn(PGM_PAGE_IS_ZERO(pPage), ("pPage=%R[pgmpage]\n", pPage), VERR_PGM_PHYS_PAGE_MAP_IPE_3);
1048
1048
AssertMsgReturn(PGM_PAGE_GET_HCPHYS(pPage) == pVM->pgm.s.HCPhysZeroPg,
1049
1049
("pPage=%R[pgmpage]\n", pPage),
1050
VERR_INTERNAL_ERROR_2);
1050
VERR_PGM_PHYS_PAGE_MAP_IPE_4);
1051
1051
*ppv = pVM->pgm.s.CTXALLSUFF(pvZeroPg);
1291
1297
* @param ppv Where to store the address corresponding to GCPhys.
1300
* @deprecated Use pgmPhysGCPhys2CCPtrInternalEx.
1295
int pgmPhysGCPhys2CCPtrInternal(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void **ppv)
1302
int pgmPhysGCPhys2CCPtrInternalDepr(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void **ppv)
1298
AssertReturn(pPage, VERR_INTERNAL_ERROR);
1305
AssertReturn(pPage, VERR_PGM_PHYS_NULL_PAGE_PARAM);
1299
1306
PGM_LOCK_ASSERT_OWNER(pVM);
1307
pVM->pgm.s.cDeprecatedPageLocks++;
1302
1310
* Make sure the page is writable.
1332
1340
return VINF_SUCCESS;
1343
#if !defined(IN_RC) && !defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
1346
* Locks a page mapping for writing.
1348
* @param pVM The VM handle.
1349
* @param pPage The page.
1350
* @param pTlbe The mapping TLB entry for the page.
1351
* @param pLock The lock structure (output).
1353
DECLINLINE(void) pgmPhysPageMapLockForWriting(PVM pVM, PPGMPAGE pPage, PPGMPAGEMAPTLBE pTlbe, PPGMPAGEMAPLOCK pLock)
1355
PPGMPAGEMAP pMap = pTlbe->pMap;
1359
unsigned cLocks = PGM_PAGE_GET_WRITE_LOCKS(pPage);
1360
if (RT_LIKELY(cLocks < PGM_PAGE_MAX_LOCKS - 1))
1363
pVM->pgm.s.cWriteLockedPages++;
1364
PGM_PAGE_INC_WRITE_LOCKS(pPage);
1366
else if (cLocks != PGM_PAGE_MAX_LOCKS)
1368
PGM_PAGE_INC_WRITE_LOCKS(pPage);
1369
AssertMsgFailed(("%R[pgmpage] is entering permanent write locked state!\n", pPage));
1371
pMap->cRefs++; /* Extra ref to prevent it from going away. */
1374
pLock->uPageAndType = (uintptr_t)pPage | PGMPAGEMAPLOCK_TYPE_WRITE;
1375
pLock->pvMap = pMap;
1379
* Locks a page mapping for reading.
1381
* @param pVM The VM handle.
1382
* @param pPage The page.
1383
* @param pTlbe The mapping TLB entry for the page.
1384
* @param pLock The lock structure (output).
1386
DECLINLINE(void) pgmPhysPageMapLockForReading(PVM pVM, PPGMPAGE pPage, PPGMPAGEMAPTLBE pTlbe, PPGMPAGEMAPLOCK pLock)
1388
PPGMPAGEMAP pMap = pTlbe->pMap;
1392
unsigned cLocks = PGM_PAGE_GET_READ_LOCKS(pPage);
1393
if (RT_LIKELY(cLocks < PGM_PAGE_MAX_LOCKS - 1))
1396
pVM->pgm.s.cReadLockedPages++;
1397
PGM_PAGE_INC_READ_LOCKS(pPage);
1399
else if (cLocks != PGM_PAGE_MAX_LOCKS)
1401
PGM_PAGE_INC_READ_LOCKS(pPage);
1402
AssertMsgFailed(("%R[pgmpage] is entering permanent read locked state!\n", pPage));
1404
pMap->cRefs++; /* Extra ref to prevent it from going away. */
1407
pLock->uPageAndType = (uintptr_t)pPage | PGMPAGEMAPLOCK_TYPE_READ;
1408
pLock->pvMap = pMap;
1411
#endif /* !IN_RC && !VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 */
1415
* Internal version of PGMPhysGCPhys2CCPtr that expects the caller to
1416
* own the PGM lock and have access to the page structure.
1418
* @returns VBox status code.
1419
* @retval VINF_SUCCESS on success.
1420
* @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical backing.
1421
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
1423
* @param pVM The VM handle.
1424
* @param GCPhys The guest physical address of the page that should be mapped.
1425
* @param pPage Pointer to the PGMPAGE structure for the page.
1426
* @param ppv Where to store the address corresponding to GCPhys.
1427
* @param pLock Where to store the lock information that
1428
* pgmPhysReleaseInternalPageMappingLock needs.
1432
int pgmPhysGCPhys2CCPtrInternal(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock)
1435
AssertReturn(pPage, VERR_PGM_PHYS_NULL_PAGE_PARAM);
1436
PGM_LOCK_ASSERT_OWNER(pVM);
1439
* Make sure the page is writable.
1441
if (RT_UNLIKELY(PGM_PAGE_GET_STATE(pPage) != PGM_PAGE_STATE_ALLOCATED))
1443
rc = pgmPhysPageMakeWritable(pVM, pPage, GCPhys);
1446
AssertMsg(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3 /* not returned */, ("%Rrc\n", rc));
1448
Assert(PGM_PAGE_GET_HCPHYS(pPage) != 0);
1453
#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
1455
PVMCPU pVCpu = VMMGetCpu(pVM);
1456
rc = pgmRZDynMapHCPageInlined(pVCpu,
1457
PGM_PAGE_GET_HCPHYS(pPage),
1459
RTLOG_COMMA_SRC_POS);
1462
*ppv = (void *)((uintptr_t)pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
1464
pLock->pVCpu = pVCpu;
1467
PPGMPAGEMAPTLBE pTlbe;
1468
rc = pgmPhysPageQueryTlbeWithPage(pVM, pPage, GCPhys, &pTlbe);
1471
pgmPhysPageMapLockForWriting(pVM, pPage, pTlbe, pLock);
1472
*ppv = (void *)((uintptr_t)pTlbe->pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
1474
return VINF_SUCCESS;
1337
1479
* Internal version of PGMPhysGCPhys2CCPtrReadOnly that expects the caller to
1338
* own the PGM lock and therefore not need to lock the mapped page.
1480
* own the PGM lock and have access to the page structure.
1340
1482
* @returns VBox status code.
1341
1483
* @retval VINF_SUCCESS on success.
1346
1488
* @param GCPhys The guest physical address of the page that should be mapped.
1347
1489
* @param pPage Pointer to the PGMPAGE structure for the page.
1348
1490
* @param ppv Where to store the address corresponding to GCPhys.
1491
* @param pLock Where to store the lock information that
1492
* pgmPhysReleaseInternalPageMappingLock needs.
1352
int pgmPhysGCPhys2CCPtrInternalReadOnly(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, const void **ppv)
1496
int pgmPhysGCPhys2CCPtrInternalReadOnly(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, const void **ppv, PPGMPAGEMAPLOCK pLock)
1354
AssertReturn(pPage, VERR_INTERNAL_ERROR);
1498
AssertReturn(pPage, VERR_PGM_PHYS_NULL_PAGE_PARAM);
1355
1499
PGM_LOCK_ASSERT_OWNER(pVM);
1356
1500
Assert(PGM_PAGE_GET_HCPHYS(pPage) != 0);
1359
* Get the mapping address.
1361
1505
#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
1363
int rc = pgmRZDynMapHCPageInlined(VMMGetCpu(pVM),
1507
PVMCPU pVCpu = VMMGetCpu(pVM);
1508
int rc = pgmRZDynMapHCPageInlined(pVCpu,
1364
1509
PGM_PAGE_GET_HCPHYS(pPage),
1366
1511
RTLOG_COMMA_SRC_POS); /** @todo add a read only flag? */
1367
1512
if (RT_FAILURE(rc))
1369
1514
*ppv = (void *)((uintptr_t)pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
1516
pLock->pVCpu = pVCpu;
1371
1519
PPGMPAGEMAPTLBE pTlbe;
1372
1520
int rc = pgmPhysPageQueryTlbeWithPage(pVM, pPage, GCPhys, &pTlbe);
1373
1521
if (RT_FAILURE(rc))
1523
pgmPhysPageMapLockForReading(pVM, pPage, pTlbe, pLock);
1375
1524
*ppv = (void *)((uintptr_t)pTlbe->pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
1377
1526
return VINF_SUCCESS;
1395
1544
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
1397
1546
* @param pVM The VM handle.
1398
* @param GCPhys The guest physical address of the page that should be mapped.
1547
* @param GCPhys The guest physical address of the page that should be
1399
1549
* @param ppv Where to store the address corresponding to GCPhys.
1400
* @param pLock Where to store the lock information that PGMPhysReleasePageMappingLock needs.
1550
* @param pLock Where to store the lock information that
1551
* PGMPhysReleasePageMappingLock needs.
1402
1553
* @remarks The caller is responsible for dealing with access handlers.
1403
1554
* @todo Add an informational return code for pages with access handlers?
1405
* @remark Avoid calling this API from within critical sections (other than the
1406
* PGM one) because of the deadlock risk. External threads may need to
1407
* delegate jobs to the EMTs.
1556
* @remark Avoid calling this API from within critical sections (other than
1557
* the PGM one) because of the deadlock risk. External threads may
1558
* need to delegate jobs to the EMTs.
1559
* @remarks Only one page is mapped! Make no assumption about what's after or
1560
* before the returned page!
1408
1561
* @thread Any thread.
1410
1563
VMMDECL(int) PGMPhysGCPhys2CCPtr(PVM pVM, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock)
1476
1625
* Now, just perform the locking and calculate the return address.
1478
PPGMPAGEMAP pMap = pTlbe->pMap;
1482
unsigned cLocks = PGM_PAGE_GET_WRITE_LOCKS(pPage);
1483
if (RT_LIKELY(cLocks < PGM_PAGE_MAX_LOCKS - 1))
1486
pVM->pgm.s.cWriteLockedPages++;
1487
PGM_PAGE_INC_WRITE_LOCKS(pPage);
1489
else if (cLocks != PGM_PAGE_GET_WRITE_LOCKS(pPage))
1491
PGM_PAGE_INC_WRITE_LOCKS(pPage);
1492
AssertMsgFailed(("%RGp / %R[pgmpage] is entering permanent write locked state!\n", GCPhys, pPage));
1494
pMap->cRefs++; /* Extra ref to prevent it from going away. */
1627
pgmPhysPageMapLockForWriting(pVM, pPage, pTlbe, pLock);
1497
1628
*ppv = (void *)((uintptr_t)pTlbe->pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
1498
pLock->uPageAndType = (uintptr_t)pPage | PGMPAGEMAPLOCK_TYPE_WRITE;
1499
pLock->pvMap = pMap;
1519
1648
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
1521
1650
* @param pVM The VM handle.
1522
* @param GCPhys The guest physical address of the page that should be mapped.
1651
* @param GCPhys The guest physical address of the page that should be
1523
1653
* @param ppv Where to store the address corresponding to GCPhys.
1524
* @param pLock Where to store the lock information that PGMPhysReleasePageMappingLock needs.
1654
* @param pLock Where to store the lock information that
1655
* PGMPhysReleasePageMappingLock needs.
1526
1657
* @remarks The caller is responsible for dealing with access handlers.
1527
1658
* @todo Add an informational return code for pages with access handlers?
1529
* @remark Avoid calling this API from within critical sections (other than
1660
* @remarks Avoid calling this API from within critical sections (other than
1530
1661
* the PGM one) because of the deadlock risk.
1662
* @remarks Only one page is mapped! Make no assumption about what's after or
1663
* before the returned page!
1531
1664
* @thread Any thread.
1533
1666
VMMDECL(int) PGMPhysGCPhys2CCPtrReadOnly(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock)
1588
1716
* Now, just perform the locking and calculate the return address.
1590
PPGMPAGEMAP pMap = pTlbe->pMap;
1594
unsigned cLocks = PGM_PAGE_GET_READ_LOCKS(pPage);
1595
if (RT_LIKELY(cLocks < PGM_PAGE_MAX_LOCKS - 1))
1598
pVM->pgm.s.cReadLockedPages++;
1599
PGM_PAGE_INC_READ_LOCKS(pPage);
1601
else if (cLocks != PGM_PAGE_GET_READ_LOCKS(pPage))
1603
PGM_PAGE_INC_READ_LOCKS(pPage);
1604
AssertMsgFailed(("%RGp / %R[pgmpage] is entering permanent readonly locked state!\n", GCPhys, pPage));
1606
pMap->cRefs++; /* Extra ref to prevent it from going away. */
1718
pgmPhysPageMapLockForReading(pVM, pPage, pTlbe, pLock);
1609
1719
*ppv = (void *)((uintptr_t)pTlbe->pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
1610
pLock->uPageAndType = (uintptr_t)pPage | PGMPAGEMAPLOCK_TYPE_READ;
1611
pLock->pvMap = pMap;
1780
1905
* @param pVM The VM handle.
1781
1906
* @param GCPhys The GC physical address to convert.
1782
* @param cbRange Physical range
1783
1907
* @param pR3Ptr Where to store the R3 pointer on success.
1785
1909
* @deprecated Avoid when possible!
1787
VMMDECL(int) PGMPhysGCPhys2R3Ptr(PVM pVM, RTGCPHYS GCPhys, RTUINT cbRange, PRTR3PTR pR3Ptr)
1911
int pgmPhysGCPhys2R3Ptr(PVM pVM, RTGCPHYS GCPhys, PRTR3PTR pR3Ptr)
1789
1913
/** @todo this is kind of hacky and needs some more work. */
1790
1914
#ifndef DEBUG_sandervl
1791
1915
VM_ASSERT_EMT(pVM); /* no longer safe for use outside the EMT thread! */
1794
Log(("PGMPhysGCPhys2R3Ptr(,%RGp,%#x,): dont use this API!\n", GCPhys, cbRange)); /** @todo eliminate this API! */
1918
Log(("pgmPhysGCPhys2R3Ptr(,%RGp,): dont use this API!\n", GCPhys)); /** @todo eliminate this API! */
1795
1919
#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
1796
1920
AssertFailedReturn(VERR_NOT_IMPLEMENTED);
2608
2735
* Get the pointer to the page.
2611
int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, pRam->GCPhys + off, &pvDst);
2737
PGMPAGEMAPLOCK PgMpLck;
2739
int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, pRam->GCPhys + off, &pvDst, &PgMpLck);
2612
2740
if (RT_SUCCESS(rc))
2614
2742
Assert(!PGM_PAGE_IS_BALLOONED(pPage));
2615
2743
memcpy(pvDst, pvBuf, cb);
2744
pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
2618
2746
/* Ignore writes to ballooned pages. */
2619
if (!PGM_PAGE_IS_BALLOONED(pPage))
2747
else if (!PGM_PAGE_IS_BALLOONED(pPage))
2620
2748
AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
2621
2749
pRam->GCPhys + off, pPage, rc));
3278
3406
if (RT_SUCCESS(rc))
3280
3408
/** @todo we should check reserved bits ... */
3282
rc = PGM_GCPHYS_2_PTR_V2(pVM, pVCpu, GCPhys, &pvSrc);
3409
PGMPAGEMAPLOCK PgMpLck;
3411
rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvSrc, &PgMpLck);
3285
3414
case VINF_SUCCESS:
3286
3415
Log(("PGMPhysInterpretedRead: pvDst=%p pvSrc=%p cb=%d\n", pvDst, (uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), cb));
3287
3416
memcpy(pvDst, (uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), cb);
3417
PGMPhysReleasePageMappingLock(pVM, &PgMpLck);
3289
3419
case VERR_PGM_PHYS_PAGE_RESERVED:
3290
3420
case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
3291
memset(pvDst, 0, cb); /** @todo this is wrong, it should be 0xff */
3421
memset(pvDst, 0xff, cb);
3424
Assert(RT_FAILURE_NP(rc));
3321
3452
/** @todo we should check reserved bits ... */
3322
3453
AssertMsgFailed(("cb=%d cb1=%d cb2=%d GCPtrSrc=%RGv\n", cb, cb1, cb2, GCPtrSrc));
3324
rc = PGM_GCPHYS_2_PTR_V2(pVM, pVCpu, GCPhys1, &pvSrc1);
3454
PGMPAGEMAPLOCK PgMpLck;
3456
rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys1, &pvSrc1, &PgMpLck);
3327
3459
case VINF_SUCCESS:
3328
3460
memcpy(pvDst, (uint8_t *)pvSrc1 + (GCPtrSrc & PAGE_OFFSET_MASK), cb1);
3461
PGMPhysReleasePageMappingLock(pVM, &PgMpLck);
3330
3463
case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
3331
memset(pvDst, 0, cb1); /** @todo this is wrong, it should be 0xff */
3464
memset(pvDst, 0xff, cb1);
3467
Assert(RT_FAILURE_NP(rc));
3338
rc = PGM_GCPHYS_2_PTR_V2(pVM, pVCpu, GCPhys2, &pvSrc2);
3472
rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys2, &pvSrc2, &PgMpLck);
3341
3475
case VINF_SUCCESS:
3342
3476
memcpy((uint8_t *)pvDst + cb1, pvSrc2, cb2);
3477
PGMPhysReleasePageMappingLock(pVM, &PgMpLck);
3344
3479
case VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:
3345
memset((uint8_t *)pvDst + cb1, 0, cb2); /** @todo this is wrong, it should be 0xff */
3480
memset((uint8_t *)pvDst + cb1, 0xff, cb2);
3483
Assert(RT_FAILURE_NP(rc));