Changeset 6854 in vbox
- Timestamp:
- Feb 7, 2008 7:24:14 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/pgm.h
r6837 r6854 289 289 PGMROMPROT_READ_RAM_WRITE_IGNORE, 290 290 /** Read from the shadow ROM page, ignore writes. 291 * Map the shadow page read-write, noaccess handler. */291 * Map the shadow page read-write, disabled write access handler. */ 292 292 PGMROMPROT_READ_RAM_WRITE_RAM, 293 293 /** The end of valid values. */ … … 296 296 PGMROMPROT_32BIT_HACK = 0x7fffffff 297 297 } PGMROMPROT; 298 299 /** 300 * Is the ROM mapped (true) or is the shadow RAM mapped (false). 301 * 302 * @returns boolean. 303 * @param enmProt The PGMROMPROT value, must be valid. 304 */ 305 #define PGMROMPROT_IS_ROM(enmProt) \ 306 ( (enmProt) == PGMROMPROT_READ_ROM_WRITE_IGNORE \ 307 || (enmProt) == PGMROMPROT_READ_ROM_WRITE_RAM ) 298 308 299 309 -
trunk/src/VBox/VMM/PGM.cpp
r6829 r6854 1711 1711 } 1712 1712 } 1713 1714 #ifdef VBOX_WITH_NEW_PHYS_CODE 1715 /* 1716 * Zero shadow ROM pages. 1717 */ 1718 rc = pgmR3PhysRomReset(pVM); 1719 #endif 1713 1720 1714 1721 /* -
trunk/src/VBox/VMM/PGMHandler.cpp
r5999 r6854 70 70 * @param pfnHandlerR3 The R3 handler. 71 71 * @param pvUserR3 User argument to the R3 handler. 72 * @param pszModR0 The R0 handler module. NULL means default R0 module.72 * @param pszModR0 The R0 handler module. NULL means the default R0 module. 73 73 * @param pszHandlerR0 The R0 handler symbol name. 74 74 * @param pvUserR0 User argument to the R0 handler. 75 * @param pszModGC The GC handler module. NULL means default GC module.75 * @param pszModGC The GC handler module. NULL means the default GC module. 76 76 * @param pszHandlerGC The GC handler symbol name. 77 77 * @param pvUserGC User argument to the GC handler. -
trunk/src/VBox/VMM/PGMInternal.h
r6837 r6854 481 481 /** MMIO2 page. (RWX) */ 482 482 PGMPAGETYPE_MMIO2, 483 /** Shadowed ROM in PGMROMPROT_READ_RAM_WRITE_RAM mode. (RWX) */484 PGMPAGETYPE_ROM_ RAM,483 /** Shadowed ROM. (RWX) */ 484 PGMPAGETYPE_ROM_SHADOW, 485 485 /** ROM page. (R-X) */ 486 486 PGMPAGETYPE_ROM, … … 495 495 * @{ */ 496 496 #define PGMPAGETYPE_IS_READABLE(type) ( (type) <= PGMPAGETYPE_ROM ) 497 #define PGMPAGETYPE_IS_WRITEABLE(type) ( (type) <= PGMPAGETYPE_ROM_ RAM)498 #define PGMPAGETYPE_IS_RWX(type) ( (type) <= PGMPAGETYPE_ROM_ RAM)497 #define PGMPAGETYPE_IS_WRITEABLE(type) ( (type) <= PGMPAGETYPE_ROM_SHADOW ) 498 #define PGMPAGETYPE_IS_RWX(type) ( (type) <= PGMPAGETYPE_ROM_SHADOW ) 499 499 #define PGMPAGETYPE_IS_ROX(type) ( (type) == PGMPAGETYPE_ROM ) 500 500 #define PGMPAGETYPE_IS_NP(type) ( (type) == PGMPAGETYPE_MMIO ) … … 634 634 * @param pPage Pointer to the physical guest page tracking structure. 635 635 */ 636 #define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (pPage)->idPage & (RT_BIT_32(GMM_CHUNKID_SHIFT) - 1))636 #define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (pPage)->idPage & GMM_PAGEID_IDX_MASK ) 637 637 /* later: 638 638 #if GMM_CHUNKID_SHIFT <= 12 639 # define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (uint32_t)((pPage)->HCPhys & (RT_BIT_32(GMM_CHUNKID_SHIFT) - 1)) )639 # define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (uint32_t)((pPage)->HCPhys & GMM_PAGEID_IDX_MASK) ) 640 640 #else 641 641 # define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (uint32_t)((pPage)->HCPhys & 0xfff) \ … … 751 751 * Per page tracking structure for ROM image. 752 752 * 753 * This is in addition to PGMPAGE, which will be set up with one 754 * of the two pages described here. 753 * A ROM image may have a shadow page, in which case we may have 754 * two pages backing it. This structure contains the PGMPAGE for 755 * both while PGMRAMRANGE have a copy of the active one. It is 756 * important that these aren't out of sync in any regard other 757 * than page pool tracking data. 755 758 */ 756 759 typedef struct PGMROMPAGE 757 760 { 758 /** The virgin page (read-only). */ 759 RTHCPHYS HCPhysVirgin; 760 /** The shadow page (read-write). */ 761 RTHCPHYS HCPhysShadow; 762 /** The page id of the virgin page. NIL_GMM_PAGEID if it's the zero page. */ 763 uint32_t idPageVirgin; 764 /** The page id of the shadow page. NIL_GMM_PAGEID if it's the zero page. */ 765 uint32_t idPageShadow; 766 /** The current protection status. */ 761 /** The page structure for the virgin ROM page. */ 762 PGMPAGE Virgin; 763 /** The page structure for the shadow RAM page. */ 764 PGMPAGE Shadow; 765 /** The current protection setting. */ 767 766 PGMROMPROT enmProt; 768 uint32_t u32Padding; /**< Structure size padding.*/ 767 /** Pad the structure size to a multiple of 8. */ 768 uint32_t u32Padding; 769 769 } PGMROMPAGE; 770 /** Pointer to a ROM page tracking structure. */ 771 typedef PGMROMPAGE *PPGMROMPAGE; 770 772 771 773 … … 2330 2332 2331 2333 int pgmPhysPageLoadIntoTlb(PPGM pPGM, RTGCPHYS GCPhys); 2334 int pgmPhysPageMakeWritable(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys); 2335 int pgmPhysPageMap(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPPGMPAGEMAP ppMap, void **ppv); 2332 2336 #ifdef IN_RING3 2333 2337 int pgmR3PhysChunkMap(PVM pVM, uint32_t idChunk, PPPGMCHUNKR3MAP ppChunk); 2338 int pgmR3PhysRomReset(PVM pVM); 2334 2339 #ifndef VBOX_WITH_NEW_PHYS_CODE 2335 2340 int pgmr3PhysGrowRange(PVM pVM, RTGCPHYS GCPhys); -
trunk/src/VBox/VMM/PGMPhys.cpp
r6840 r6854 42 42 43 43 44 /******************************************************************************* 45 * Internal Functions * 46 *******************************************************************************/ 47 /*static - shut up warning */ 48 DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser); 49 50 44 51 45 52 /* … … 407 414 */ 408 415 PPGMROMRANGE pRomNew; 409 rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMROMRANGE, aPages[cPages]), sizeof(PGMROMPAGE), MM_TAG_PGM_PHYS, (void **)pRomNew);416 rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)pRomNew); 410 417 if (RT_SUCCESS(rc)) 411 418 { … … 415 422 if (RT_SUCCESS(rc)) 416 423 { 424 pgmLock(pVM); 425 417 426 /* 418 427 * Initialize and insert the RAM range (if required). 419 428 */ 429 PPGMROMPAGE pRomPage = &pRomNew->aPages[0]; 420 430 if (!fRamExists) 421 431 { … … 428 438 429 439 PPGMPAGE pPage = &pRamNew->aPages[0]; 430 for (uint32_t iPage = 0; iPage < cPages; iPage++ )440 for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++) 431 441 { 432 442 pPage->fWrittenTo = 0; … … 437 447 PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_ALLOCATED); 438 448 PGM_PAGE_SET_PAGEID(pPage, pReq->aPages[iPage].idPage); 449 450 pRomPage->Virgin = *pPage; 439 451 } 440 452 … … 444 456 { 445 457 PPGMPAGE pPage = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT]; 446 for (uint32_t iPage = 0; iPage < cPages; iPage++ )458 for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++) 447 459 { 448 460 PGM_PAGE_SET_TYPE(pPage, PGMPAGETYPE_ROM); … … 450 462 PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_ALLOCATED); 451 463 PGM_PAGE_SET_PAGEID(pPage, pReq->aPages[iPage].idPage); 464 465 pRomPage->Virgin = *pPage; 452 466 } 453 467 454 468 pRamNew = pRam; 455 469 } 470 pgmUnlock(pVM); 471 456 472 457 473 /* … … 459 475 */ 460 476 rc = PGMR3HandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, GCPhys, GCPhysLast, 461 NULL, NULL, /** @todo we actually need a ring-3 write handler here for shadowed ROMs, so hack REM! */ 462 NULL, "pgmGuestROMWriteHandler", 0, 463 NULL, "pgmGuestROMWriteHandler", 0, pszDesc); 477 #if 0 /** @todo we actually need a ring-3 write handler here for shadowed ROMs, so hack REM! */ 478 pgmR3PhysRomWriteHandler, pRomNew, 479 #else 480 NULL, NULL, 481 #endif 482 NULL, "pgmGuestROMWriteHandler", MMHyperCCToR0(pVM, pRomNew), 483 NULL, "pgmGuestROMWriteHandler", MMHyperCCToGC(pVM, pRomNew), pszDesc); 464 484 if (RT_SUCCESS(rc)) 465 485 { 486 pgmLock(pVM); 487 466 488 /* 467 489 * Copy the image over to the virgin pages. 468 490 * This must be done after linking in the RAM range. 469 491 */ 470 for (uint32_t iPage = 0; iPage < cPages; iPage++) 492 PPGMPAGE pRamPage = &pRamNew->aPages[(GCPhys - pRamNew->GCPhys) >> PAGE_SHIFT]; 493 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++) 471 494 { 472 void *pvDst ;473 P GMPAGEMAPLOCK Lock;474 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhys + (iPage << PAGE_SHIFT), &pvDst, &Lock);495 void *pvDstPage; 496 PPGMPAGEMAP pMapIgnored; 497 rc = pgmPhysPageMap(pVM, pRamPage, GCPhys + (iPage << PAGE_SHIFT), &pMapIgnored, &pvDstPage); 475 498 if (RT_FAILURE(rc)) 476 499 { … … 478 501 break; 479 502 } 480 memcpy(pvDst, (const uint8_t *)pvBinary + (iPage << PAGE_SHIFT), PAGE_SIZE); 481 PGMPhysReleasePageMappingLock(pVM, &Lock); 503 memcpy(pvDstPage, (const uint8_t *)pvBinary + (iPage << PAGE_SHIFT), PAGE_SIZE); 482 504 } 483 505 if (RT_SUCCESS(rc)) … … 485 507 /* 486 508 * Initialize the ROM range. 509 * Note that the Virgin member of the pages has already been initialized above. 487 510 */ 488 511 pRomNew->GCPhys = GCPhys; … … 495 518 for (unsigned iPage = 0; iPage < cPages; iPage++) 496 519 { 497 pRomNew->aPages[iPage].HCPhysVirgin = pReq->aPages[iPage].HCPhysGCPhys; 498 pRomNew->aPages[iPage].HCPhysShadow = NIL_RTHCPHYS; 499 pRomNew->aPages[iPage].idPageVirgin = pReq->aPages[iPage].idPage; 500 pRomNew->aPages[iPage].idPageShadow = NIL_GMM_PAGEID; 520 PPGMROMPAGE pPage = &pRomNew->aPages[iPage]; 521 522 pPage->Shadow.HCPhys = 0; 523 pPage->Shadow.fWrittenTo = 0; 524 pPage->Shadow.fSomethingElse = 0; 525 pPage->Shadow.u29B = 0; 526 PGM_PAGE_SET_TYPE( &pPage->Shadow, PGMPAGETYPE_ROM_SHADOW); 527 PGM_PAGE_SET_STATE( &pPage->Shadow, PGM_PAGE_STATE_ZERO); 528 PGM_PAGE_SET_PAGEID(&pPage->Shadow, pReq->aPages[iPage].idPage); 529 501 530 pRomNew->aPages[iPage].enmProt = PGMROMPROT_READ_ROM_WRITE_IGNORE; 502 531 } … … 525 554 526 555 GMMR3AllocatePagesCleanup(pReq); 556 pgmUnlock(pVM); 527 557 return VINF_SUCCESS; 528 558 } … … 530 560 /* bail out */ 531 561 562 pgmUnlock(pVM); 532 563 int rc2 = PGMHandlerPhysicalDeregister(pVM, GCPhys); 533 564 AssertRC(rc2); 565 pgmLock(pVM); 534 566 } 535 567 … … 544 576 GMMR3FreeAllocatedPages(pVM, pReq); 545 577 GMMR3AllocatePagesCleanup(pReq); 578 pgmUnlock(pVM); 546 579 return rc; 580 } 581 582 583 /** 584 * \#PF Handler callback for ROM write accesses. 585 * 586 * @returns VINF_SUCCESS if the handler have carried out the operation. 587 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation. 588 * @param pVM VM Handle. 589 * @param GCPhys The physical address the guest is writing to. 590 * @param pvPhys The HC mapping of that address. 591 * @param pvBuf What the guest is reading/writing. 592 * @param cbBuf How much it's reading/writing. 593 * @param enmAccessType The access type. 594 * @param pvUser User argument. 595 */ 596 /*static - shut up warning */ 597 DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser) 598 { 599 PPGMROMRANGE pRom = (PPGMROMRANGE)pvUser; 600 const uint32_t iPage = GCPhys - pRom->GCPhys; 601 Assert(iPage < (pRom->cb >> PAGE_SHIFT)); 602 PPGMROMPAGE pRomPage = &pRom->aPages[iPage]; 603 switch (pRomPage->enmProt) 604 { 605 /* 606 * Ignore. 607 */ 608 case PGMROMPROT_READ_ROM_WRITE_IGNORE: 609 case PGMROMPROT_READ_RAM_WRITE_IGNORE: 610 return VINF_SUCCESS; 611 612 /* 613 * Write to the ram page. 614 */ 615 case PGMROMPROT_READ_ROM_WRITE_RAM: 616 case PGMROMPROT_READ_RAM_WRITE_RAM: /* yes this will get here too, it's *way* simpler that way. */ 617 { 618 /* This should be impossible now, pvPhys doesn't work cross page anylonger. */ 619 Assert(((GCPhys - pRom->GCPhys + cbBuf - 1) >> PAGE_SHIFT) == iPage); 620 621 /* 622 * Take the lock, do lazy allocation, map the page and copy the data. 623 * 624 * Note that we have to bypass the mapping TLB since it works on 625 * guest physical addresses and entering the shadow page would 626 * kind of screw things up... 627 */ 628 int rc = pgmLock(pVM); 629 AssertRC(rc); 630 631 if (RT_UNLIKELY(PGM_PAGE_GET_STATE(&pRomPage->Shadow) != PGM_PAGE_STATE_ALLOCATED)) 632 { 633 rc = pgmPhysPageMakeWritable(pVM, &pRomPage->Shadow, GCPhys); 634 if (RT_FAILURE(rc)) 635 { 636 pgmUnlock(pVM); 637 return rc; 638 } 639 } 640 641 void *pvDstPage; 642 PPGMPAGEMAP pMapIgnored; 643 rc = pgmPhysPageMap(pVM, &pRomPage->Shadow, GCPhys & X86_PTE_PG_MASK, &pMapIgnored, &pvDstPage); 644 if (RT_SUCCESS(rc)) 645 memcpy((uint8_t *)pvDstPage + (GCPhys & PAGE_OFFSET_MASK), pvBuf, cbBuf); 646 647 pgmUnlock(pVM); 648 return rc; 649 } 650 651 default: 652 AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhys=%RGp\n", 653 pRom->aPages[iPage].enmProt, iPage, GCPhys), 654 VERR_INTERNAL_ERROR); 655 } 656 } 657 658 659 660 /** 661 * Called by PGMR3Reset to reset the shadow, switch to the virgin, 662 * and verify that the virgin part is untouched. 663 * 664 * This is done after the normal memory has been cleared. 665 * 666 * @param pVM The VM handle. 667 */ 668 int pgmR3PhysRomReset(PVM pVM) 669 { 670 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3) 671 { 672 const uint32_t cPages = pRom->cb >> PAGE_SHIFT; 673 674 if (pRom->fFlags & PGMPHYS_ROM_FLAG_SHADOWED) 675 { 676 /* 677 * Reset the physical handler. 678 */ 679 int rc = PGMR3PhysRomProtect(pVM, pRom->GCPhys, pRom->cb, PGMROMPROT_READ_ROM_WRITE_IGNORE); 680 AssertRCReturn(rc, rc); 681 682 /* 683 * What we do with the shadow pages depends on the memory 684 * preallocation option. If not enabled, we'll just throw 685 * out all the dirty pages and replace them by the zero page. 686 */ 687 if (1)///@todo !pVM->pgm.f.fRamPreAlloc) 688 { 689 /* Count dirty shadow pages. */ 690 uint32_t cDirty = 0; 691 uint32_t iPage = cPages; 692 while (iPage-- > 0) 693 if (PGM_PAGE_GET_STATE(&pRom->aPages[iPage].Shadow) != PGM_PAGE_STATE_ZERO) 694 cDirty++; 695 if (cDirty) 696 { 697 /* Free the dirty pages. */ 698 PGMMFREEPAGESREQ pReq; 699 rc = GMMR3FreePagesPrepare(pVM, &pReq, cDirty, GMMACCOUNT_BASE); 700 AssertRCReturn(rc, rc); 701 702 uint32_t iReqPage = 0; 703 for (iPage = 0; iPage < cPages; iPage++) 704 if (PGM_PAGE_GET_STATE(&pRom->aPages[iPage].Shadow) != PGM_PAGE_STATE_ZERO) 705 { 706 pReq->aPages[iReqPage].idPage = PGM_PAGE_GET_PAGEID(&pRom->aPages[iPage].Shadow); 707 iReqPage++; 708 } 709 710 rc = GMMR3FreePagesPerform(pVM, pReq); 711 GMMR3FreePagesCleanup(pReq); 712 AssertRCReturn(rc, rc); 713 714 /* setup the zero page. */ 715 for (iPage = 0; iPage < cPages; iPage++) 716 if (PGM_PAGE_GET_STATE(&pRom->aPages[iPage].Shadow) != PGM_PAGE_STATE_ZERO) 717 { 718 PGM_PAGE_SET_STATE( &pRom->aPages[iPage].Shadow, PGM_PAGE_STATE_ZERO); 719 PGM_PAGE_SET_HCPHYS(&pRom->aPages[iPage].Shadow, pVM->pgm.s.HCPhysZeroPg); 720 PGM_PAGE_SET_PAGEID(&pRom->aPages[iPage].Shadow, NIL_GMM_PAGEID); 721 pRom->aPages[iPage].Shadow.fWrittenTo = false; 722 iReqPage++; 723 } 724 } 725 } 726 else 727 { 728 /* clear all the pages. */ 729 pgmLock(pVM); 730 for (uint32_t iPage = 0; iPage < cPages; iPage++) 731 { 732 const RTGCPHYS GCPhys = pRom->GCPhys + (iPage << PAGE_SHIFT); 733 rc = pgmPhysPageMakeWritable(pVM, &pRom->aPages[iPage].Shadow, GCPhys); 734 if (RT_FAILURE(rc)) 735 break; 736 737 void *pvDstPage; 738 PPGMPAGEMAP pMapIgnored; 739 rc = pgmPhysPageMap(pVM, &pRom->aPages[iPage].Shadow, GCPhys, &pMapIgnored, &pvDstPage); 740 if (RT_FAILURE(rc)) 741 break; 742 memset(pvDstPage, 0, PAGE_SIZE); 743 } 744 pgmUnlock(pVM); 745 AssertRCReturn(rc, rc); 746 } 747 } 748 749 #ifdef VBOX_STRICT 750 /* 751 * Verify that the virgin page is unchanged if possible. 752 */ 753 if (pRom->pvOriginal) 754 { 755 uint8_t const *pbSrcPage = (uint8_t const *)pRom->pvOriginal; 756 for (uint32_t iPage = 0; iPage < cPages; iPage++, pbSrcPage += PAGE_SIZE) 757 { 758 const RTGCPHYS GCPhys = pRom->GCPhys + (iPage << PAGE_SHIFT); 759 PPGMPAGEMAP pMapIgnored; 760 void *pvDstPage; 761 int rc = pgmPhysPageMap(pVM, &pRom->aPages[iPage].Virgin, GCPhys, &pMapIgnored, &pvDstPage); 762 if (RT_FAILURE(rc)) 763 break; 764 if (memcmp(pvDstPage, pbSrcPage, PAGE_SIZE)) 765 LogRel(("pgmR3PhysRomReset: %RGp rom page changed (%s) - loaded saved state?\n", 766 GCPhys, pRom->pszDesc)); 767 } 768 } 769 #endif 770 } 771 772 return VINF_SUCCESS; 773 } 774 775 776 /** 777 * Change the shadowing of a range of ROM pages. 778 * 779 * This is intended for implementing chipset specific memory registers 780 * and will not be very strict about the input. It will silently ignore 781 * any pages that are not the part of a shadowed ROM. 782 * 783 * @returns VBox status code. 784 * @param pVM Pointer to the shared VM structure. 785 * @param GCPhys Where to start. Page aligned. 786 * @param cb How much to change. Page aligned. 787 * @param enmProt The new ROM protection. 788 */ 789 PGMR3DECL(int) PGMR3PhysRomProtect(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, PGMROMPROT enmProt) 790 { 791 /* 792 * Check input 793 */ 794 if (!cb) 795 return VINF_SUCCESS; 796 AssertReturn(!(GCPhys & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER); 797 AssertReturn(!(cb & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER); 798 RTGCPHYS GCPhysLast = GCPhys + (cb - 1); 799 AssertReturn(GCPhysLast > GCPhys, VERR_INVALID_PARAMETER); 800 AssertReturn(enmProt >= PGMROMPROT_INVALID && enmProt <= PGMROMPROT_END, VERR_INVALID_PARAMETER); 801 802 /* 803 * Process the request. 804 */ 805 bool fFlushedPool = false; 806 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3) 807 if ( GCPhys <= pRom->GCPhysLast 808 && GCPhysLast >= pRom->GCPhys) 809 { 810 /* 811 * Iterate the relevant pages and the ncessary make changes. 812 */ 813 bool fChanges = false; 814 uint32_t const cPages = pRom->GCPhysLast > GCPhysLast 815 ? pRom->cb >> PAGE_SHIFT 816 : (GCPhysLast - pRom->GCPhys) >> PAGE_SHIFT; 817 for (uint32_t iPage = (GCPhys - pRom->GCPhys) >> PAGE_SHIFT; 818 iPage < cPages; 819 iPage++) 820 { 821 PPGMROMPAGE pRomPage = &pRom->aPages[iPage]; 822 if (PGMROMPROT_IS_ROM(pRomPage->enmProt) != PGMROMPROT_IS_ROM(enmProt)) 823 { 824 fChanges = true; 825 826 /* flush the page pool first so we don't leave any usage references dangling. */ 827 if (!fFlushedPool) 828 { 829 pgmPoolFlushAll(pVM); 830 fFlushedPool = true; 831 } 832 833 PPGMPAGE pOld = PGMROMPROT_IS_ROM(pRomPage->enmProt) ? &pRomPage->Virgin : &pRomPage->Shadow; 834 PPGMPAGE pNew = PGMROMPROT_IS_ROM(pRomPage->enmProt) ? &pRomPage->Shadow : &pRomPage->Virgin; 835 PPGMPAGE pRamPage = pgmPhysGetPage(&pVM->pgm.s, pRom->GCPhys + (iPage << PAGE_SHIFT)); 836 837 *pOld = *pRamPage; 838 *pRamPage = *pNew; 839 /** @todo sync the volatile flags (handlers) when these have been moved out of HCPhys. */ 840 } 841 } 842 843 /* 844 * Reset the access handler if we made changes, no need 845 * to optimize this. 846 */ 847 if (fChanges) 848 { 849 int rc = PGMHandlerPhysicalReset(pVM, pRom->GCPhys); 850 AssertRCReturn(rc, rc); 851 } 852 853 /* Advance - cb isn't updated. */ 854 GCPhys = pRom->GCPhys + (cPages << PAGE_SHIFT); 855 } 856 857 return VINF_SUCCESS; 547 858 } 548 859 -
trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp
r6829 r6854 993 993 } 994 994 995 996 995 #ifndef IN_RING3 997 998 # ifdef IN_RING0999 /** @todo try combine this with iom and em. */1000 1001 /**1002 * Read callback for disassembly function; supports reading bytes that cross a page boundary1003 *1004 * @returns VBox status code.1005 * @param pSrc GC source pointer1006 * @param pDest HC destination pointer1007 * @param size Number of bytes to read1008 * @param pvUserdata Callback specific user data (pCpu)1009 *1010 */1011 DECLCALLBACK(int) pgmReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata)1012 {1013 DISCPUSTATE *pCpu = (DISCPUSTATE *)pvUserdata;1014 PVM pVM = (PVM)pCpu->apvUserData[0];1015 1016 int rc = PGMPhysReadGCPtr(pVM, pDest, pSrc, size);1017 AssertRC(rc);1018 return rc;1019 }1020 1021 inline int pgmDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)1022 {1023 return DISCoreOneEx(InstrGC, pCpu->mode, pgmReadBytes, pVM, pCpu, pOpsize);1024 }1025 1026 # else /* !IN_RING0 (i.e. in IN_GC) */1027 inline int pgmDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)1028 {1029 return DISCoreOne(pCpu, InstrGC, pOpsize);1030 }1031 1032 #endif /* !IN_RING0 (i.e. in IN_GC) */1033 1034 996 1035 997 /** … … 1043 1005 * @param pvFault The fault address (cr2). 1044 1006 * @param GCPhysFault The GC physical address corresponding to pvFault. 1045 * @param pvUser User argument. 1007 * @param pvUser User argument. Pointer to the ROM range structure. 1046 1008 */ 1047 1009 PGMDECL(int) pgmGuestROMWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser) 1048 1010 { 1049 DISCPUSTATE Cpu; 1050 Cpu.mode = SELMIsSelector32Bit(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) ? CPUMODE_32BIT : CPUMODE_16BIT; 1051 if (Cpu.mode == CPUMODE_32BIT) 1052 { 1053 RTGCPTR GCPtrCode; 1054 int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &GCPtrCode); 1055 if (VBOX_SUCCESS(rc)) 1056 { 1011 int rc; 1012 #ifdef VBOX_WITH_NEW_PHYS_CODE 1013 PPGMROMRANGE pRom = (PPGMROMRANGE)pvUser; 1014 uint32_t iPage = GCPhysFault - pRom->GCPhys; 1015 Assert(iPage < (pRom->cb >> PAGE_SHIFT)); 1016 switch (pRom->aPages[iPage].enmProt) 1017 { 1018 case PGMROMPROT_READ_ROM_WRITE_IGNORE: 1019 case PGMROMPROT_READ_RAM_WRITE_IGNORE: 1020 { 1021 #endif 1022 /* 1023 * If it's a simple instruction which doesn't change the cpu state 1024 * we will simply skip it. Otherwise we'll have to defer it to REM. 1025 */ 1057 1026 uint32_t cbOp; 1058 rc = pgmDisCoreOne(pVM, &Cpu, (RTGCUINTPTR)GCPtrCode, &cbOp); 1059 if (VBOX_SUCCESS(rc)) 1027 DISCPUSTATE Cpu; 1028 rc = EMInterpretDisasOne(pVM, pRegFrame, &Cpu, &cbOp); 1029 if ( RT_SUCCESS(rc) 1030 && Cpu.mode == CPUMODE_32BIT 1031 && !(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG))) 1060 1032 { 1061 /* ASSUMES simple instructions. 1062 * For instance 'pop [ROM_ADDRESS]' or 'and [ROM_ADDRESS], eax' better 1063 * not occure or we'll screw up the cpu state. 1064 */ 1065 /** @todo We're assuming too much here I think. */ 1066 if (!(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG))) 1033 switch (Cpu.opcode) 1067 1034 { 1068 /* 1069 * Move on to the next instruction.1070 */1071 pRegFrame->eip += cbOp;1072 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestROMWriteHandled);1073 return VINF_SUCCESS;1035 /** @todo Find other instructions we can safely skip, possibly 1036 * adding this kind of detection to DIS or EM. */ 1037 case OP_MOV: 1038 pRegFrame->eip += cbOp; 1039 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestROMWriteHandled); 1040 return VINF_SUCCESS; 1074 1041 } 1075 LogFlow(("pgmGuestROMWriteHandler: wrong prefix!!\n"));1076 1042 } 1077 } 1078 } 1043 else if (RT_UNLIKELY(rc == VERR_INTERNAL_ERROR)) 1044 return rc; 1045 #ifdef VBOX_WITH_NEW_PHYS_CODE 1046 break; 1047 } 1048 1049 case PGMROMPROT_READ_RAM_WRITE_RAM: 1050 rc = PGMHandlerPhysicalPageTempOff(pVM, pRom->GCPhys, GCPhysFault & X86_PTE_PG_MASK); 1051 AssertRC(rc); 1052 case PGMROMPROT_READ_ROM_WRITE_RAM: 1053 /* Handle it in ring-3 because it's *way* easier there. */ 1054 break; 1055 1056 default: 1057 AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhysFault=%RGp\n", 1058 pRom->aPages[iPage].enmProt, iPage, GCPhysFault), 1059 VERR_INTERNAL_ERROR); 1060 } 1061 #endif 1079 1062 1080 1063 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestROMWriteUnhandled); 1081 1064 return VINF_EM_RAW_EMULATE_INSTR; 1082 1065 } 1083 #endif /* !IN_RING3 */ 1066 1067 #endif /* IN_RING3 */ -
trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp
r6829 r6854 313 313 STAM_COUNTER_INC(&pVM->pgm.s.StatPageReplaceShared); 314 314 pVM->pgm.s.cSharedPages--; 315 /** @todo err.. what about copying the page content? */ 315 316 } 316 317 else … … 319 320 STAM_COUNTER_INC(&pVM->pgm.s.StatPageReplaceZero); 320 321 pVM->pgm.s.cZeroPages--; 322 /** @todo verify that the handy page is zero! */ 321 323 } 322 324 … … 565 567 PPGMPAGE pPage = pTlbe->pPage; 566 568 if (RT_UNLIKELY(pPage->u2State != PGM_PAGE_STATE_ALLOCATED)) 569 { 567 570 rc = pgmPhysPageMakeWritable(pVM, pPage, GCPhys); 571 /** @todo stuff is missing here! */ 572 } 568 573 if (RT_SUCCESS(rc)) 569 574 { -
trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
r6837 r6854 547 547 GEN_CHECK_OFF(PGMRAMRANGE, aPages[1]); 548 548 GEN_CHECK_SIZE(PGMROMPAGE); 549 GEN_CHECK_OFF(PGMROMPAGE, HCPhysVirgin); 550 GEN_CHECK_OFF(PGMROMPAGE, HCPhysShadow); 551 GEN_CHECK_OFF(PGMROMPAGE, idPageVirgin); 552 GEN_CHECK_OFF(PGMROMPAGE, idPageShadow); 549 GEN_CHECK_OFF(PGMROMPAGE, Virgin); 550 GEN_CHECK_OFF(PGMROMPAGE, Shadow); 553 551 GEN_CHECK_OFF(PGMROMPAGE, enmProt); 554 552 GEN_CHECK_SIZE(PGMROMRANGE); -
trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp
r6837 r6854 212 212 CHECK_SIZE(PGMPAGE, 16); 213 213 CHECK_MEMBER_ALIGNMENT(PGMRAMRANGE, aPages, 16); 214 CHECK_SIZE(PGMROMPAGE, 32);215 CHECK_MEMBER_ALIGNMENT(PGMROMRANGE, aPages, 32);216 214 217 215 /* misc */
Note:
See TracChangeset
for help on using the changeset viewer.