Changeset 17586 in vbox for trunk/src/VBox/VMM/VMMAll/PGMAllGst.h
- Timestamp:
- Mar 9, 2009 3:28:25 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 44039
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/PGMAllGst.h
r17215 r17586 28 28 PGM_GST_DECL(int, ModifyPage)(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask); 29 29 PGM_GST_DECL(int, GetPDE)(PVM pVM, RTGCPTR GCPtr, PX86PDEPAE pPDE); 30 #ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY31 PGM_GST_DECL(int, MonitorCR3)(PVM pVM, RTGCPHYS GCPhysCR3);32 PGM_GST_DECL(int, UnmonitorCR3)(PVM pVM);33 #endif34 30 PGM_GST_DECL(bool, HandlerVirtualUpdate)(PVM pVM, uint32_t cr4); 35 #ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY36 # ifndef IN_RING337 PGM_GST_DECL(int, WriteHandlerCR3)(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);38 # if PGM_GST_TYPE == PGM_TYPE_PAE \39 || PGM_GST_TYPE == PGM_TYPE_AMD6440 PGM_GST_DECL(int, PAEWriteHandlerPD)(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);41 # endif42 # endif43 #endif44 31 __END_DECLS 45 32 … … 311 298 #endif 312 299 } 313 314 315 #ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY316 317 #undef LOG_GROUP318 #define LOG_GROUP LOG_GROUP_PGM_POOL319 320 /**321 * Registers physical page monitors for the necessary paging322 * structures to detect conflicts with our guest mappings.323 *324 * This is always called after mapping CR3.325 * This is never called with fixed mappings.326 *327 * @returns VBox status, no specials.328 * @param pVM VM handle.329 * @param GCPhysCR3 The physical address in the CR3 register.330 */331 PGM_GST_DECL(int, MonitorCR3)(PVM pVM, RTGCPHYS GCPhysCR3)332 {333 Assert(!pVM->pgm.s.fMappingsFixed);334 int rc = VINF_SUCCESS;335 336 /*337 * Register/Modify write phys handler for guest's CR3 if it changed.338 */339 #if PGM_GST_TYPE == PGM_TYPE_32BIT340 341 if (pVM->pgm.s.GCPhysGstCR3Monitored != GCPhysCR3)342 {343 # ifndef PGMPOOL_WITH_MIXED_PT_CR3344 const unsigned cbCR3Stuff = PGM_GST_TYPE == PGM_TYPE_PAE ? 32 : PAGE_SIZE;345 if (pVM->pgm.s.GCPhysGstCR3Monitored != NIL_RTGCPHYS)346 rc = PGMHandlerPhysicalModify(pVM, pVM->pgm.s.GCPhysGstCR3Monitored, GCPhysCR3, GCPhysCR3 + cbCR3Stuff - 1);347 else348 rc = PGMHandlerPhysicalRegisterEx(pVM, PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, GCPhysCR3, GCPhysCR3 + cbCR3Stuff - 1,349 pVM->pgm.s.pfnR3GstWriteHandlerCR3, 0,350 pVM->pgm.s.pfnR0GstWriteHandlerCR3, 0,351 pVM->pgm.s.pfnRCGstWriteHandlerCR3, 0,352 pVM->pgm.s.pszR3GstWriteHandlerCR3);353 # else /* PGMPOOL_WITH_MIXED_PT_CR3 */354 rc = pgmPoolMonitorMonitorCR3(pVM->pgm.s.CTX_SUFF(pPool),355 pVM->pgm.s.enmShadowMode == PGMMODE_PAE356 || pVM->pgm.s.enmShadowMode == PGMMODE_PAE_NX357 ? PGMPOOL_IDX_PAE_PD358 : PGMPOOL_IDX_PD,359 GCPhysCR3);360 # endif /* PGMPOOL_WITH_MIXED_PT_CR3 */361 if (RT_FAILURE(rc))362 {363 AssertMsgFailed(("PGMHandlerPhysicalModify/PGMR3HandlerPhysicalRegister failed, rc=%Rrc GCPhysGstCR3Monitored=%RGp GCPhysCR3=%RGp\n",364 rc, pVM->pgm.s.GCPhysGstCR3Monitored, GCPhysCR3));365 return rc;366 }367 pVM->pgm.s.GCPhysGstCR3Monitored = GCPhysCR3;368 }369 370 #elif PGM_GST_TYPE == PGM_TYPE_PAE371 /* Monitor the PDPT page */372 /*373 * Register/Modify write phys handler for guest's CR3 if it changed.374 */375 # ifndef PGMPOOL_WITH_MIXED_PT_CR3376 AssertFailed();377 # endif378 if (pVM->pgm.s.GCPhysGstCR3Monitored != GCPhysCR3)379 {380 rc = pgmPoolMonitorMonitorCR3(pVM->pgm.s.CTX_SUFF(pPool), PGMPOOL_IDX_PDPT, GCPhysCR3);381 if (RT_FAILURE(rc))382 {383 AssertMsgFailed(("PGMHandlerPhysicalModify/PGMR3HandlerPhysicalRegister failed, rc=%Rrc GCPhysGstCR3Monitored=%RGp GCPhysCR3=%RGp\n",384 rc, pVM->pgm.s.GCPhysGstCR3Monitored, GCPhysCR3));385 return rc;386 }387 pVM->pgm.s.GCPhysGstCR3Monitored = GCPhysCR3;388 }389 390 /*391 * Do the 4 PDs.392 */393 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);394 for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)395 {396 if (pGuestPDPT->a[i].n.u1Present)397 {398 RTGCPHYS GCPhys = pGuestPDPT->a[i].u & X86_PDPE_PG_MASK;399 if (pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] != GCPhys)400 {401 Assert(pVM->pgm.s.enmShadowMode == PGMMODE_PAE || pVM->pgm.s.enmShadowMode == PGMMODE_PAE_NX);402 403 rc = pgmPoolMonitorMonitorCR3(pVM->pgm.s.CTX_SUFF(pPool), PGMPOOL_IDX_PAE_PD_0 + i, GCPhys);404 }405 406 if (RT_FAILURE(rc))407 {408 AssertMsgFailed(("PGMHandlerPhysicalModify/PGMR3HandlerPhysicalRegister failed, rc=%Rrc GCPhysGstCR3Monitored=%RGp GCPhysCR3=%RGp\n",409 rc, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i], GCPhys));410 return rc;411 }412 pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] = GCPhys;413 }414 else if (pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] != NIL_RTGCPHYS)415 {416 rc = pgmPoolMonitorUnmonitorCR3(pVM->pgm.s.CTX_SUFF(pPool), PGMPOOL_IDX_PAE_PD_0 + i);417 AssertRC(rc);418 pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] = NIL_RTGCPHYS;419 }420 }421 422 #else423 /* prot/real/amd64 mode stub */424 425 #endif426 return rc;427 }428 429 /**430 * Deregisters any physical page monitors installed by MonitorCR3.431 *432 * @returns VBox status code, no specials.433 * @param pVM The VM handle.434 */435 PGM_GST_DECL(int, UnmonitorCR3)(PVM pVM)436 {437 int rc = VINF_SUCCESS;438 439 /*440 * Deregister the access handlers.441 *442 * PGMSyncCR3 will reinstall it if required and PGMSyncCR3 will be executed443 * before we enter GC again.444 */445 #if PGM_GST_TYPE == PGM_TYPE_32BIT446 if (pVM->pgm.s.GCPhysGstCR3Monitored != NIL_RTGCPHYS)447 {448 # ifndef PGMPOOL_WITH_MIXED_PT_CR3449 rc = PGMHandlerPhysicalDeregister(pVM, pVM->pgm.s.GCPhysGstCR3Monitored);450 AssertRCReturn(rc, rc);451 # else /* PGMPOOL_WITH_MIXED_PT_CR3 */452 rc = pgmPoolMonitorUnmonitorCR3(pVM->pgm.s.CTX_SUFF(pPool),453 pVM->pgm.s.enmShadowMode == PGMMODE_PAE454 || pVM->pgm.s.enmShadowMode == PGMMODE_PAE_NX455 ? PGMPOOL_IDX_PAE_PD456 : PGMPOOL_IDX_PD);457 AssertRCReturn(rc, rc);458 # endif /* PGMPOOL_WITH_MIXED_PT_CR3 */459 pVM->pgm.s.GCPhysGstCR3Monitored = NIL_RTGCPHYS;460 }461 462 #elif PGM_GST_TYPE == PGM_TYPE_PAE463 /* The PDPT page */464 # ifndef PGMPOOL_WITH_MIXED_PT_CR3465 AssertFailed();466 # endif467 468 if (pVM->pgm.s.GCPhysGstCR3Monitored != NIL_RTGCPHYS)469 {470 rc = pgmPoolMonitorUnmonitorCR3(pVM->pgm.s.CTX_SUFF(pPool), PGMPOOL_IDX_PDPT);471 AssertRC(rc);472 }473 474 /* The 4 PDs. */475 for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)476 {477 if (pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] != NIL_RTGCPHYS)478 {479 Assert(pVM->pgm.s.enmShadowMode == PGMMODE_PAE || pVM->pgm.s.enmShadowMode == PGMMODE_PAE_NX);480 int rc2 = pgmPoolMonitorUnmonitorCR3(pVM->pgm.s.CTX_SUFF(pPool), PGMPOOL_IDX_PAE_PD_0 + i);481 AssertRC(rc2);482 if (RT_FAILURE(rc2))483 rc = rc2;484 pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] = NIL_RTGCPHYS;485 }486 }487 #else488 /* prot/real/amd64 mode stub */489 #endif490 return rc;491 492 }493 494 #undef LOG_GROUP495 #define LOG_GROUP LOG_GROUP_PGM496 497 #endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY */498 300 499 301 … … 704 506 } 705 507 706 #ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY707 708 #if PGM_GST_TYPE == PGM_TYPE_32BIT && !defined(IN_RING3)709 710 /**711 * Write access handler for the Guest CR3 page in 32-bit mode.712 *713 * This will try interpret the instruction, if failure fail back to the recompiler.714 * Check if the changed PDEs are marked present and conflicts with our715 * mappings. If conflict, we'll switch to the host context and resolve it there716 *717 * @returns VBox status code (appropritate for trap handling and GC return).718 * @param pVM VM Handle.719 * @param uErrorCode CPU Error code.720 * @param pRegFrame Trap register frame.721 * @param pvFault The fault address (cr2).722 * @param GCPhysFault The GC physical address corresponding to pvFault.723 * @param pvUser User argument.724 */725 PGM_GST_DECL(int, WriteHandlerCR3)(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)726 {727 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));728 729 /*730 * Try interpret the instruction.731 */732 uint32_t cb;733 int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);734 if (RT_SUCCESS(rc) && cb)735 {736 /*737 * Check if the modified PDEs are present and mappings.738 */739 const RTGCPTR offPD = GCPhysFault & PAGE_OFFSET_MASK;740 const unsigned iPD1 = offPD / sizeof(X86PDE);741 const unsigned iPD2 = (offPD + cb - 1) / sizeof(X86PDE);742 743 Assert(cb > 0 && cb <= 8);744 Assert(iPD1 < X86_PG_ENTRIES);745 Assert(iPD2 < X86_PG_ENTRIES);746 747 #ifdef DEBUG748 Log(("pgmXXGst32BitWriteHandlerCR3: emulated change to PD %#x addr=%x\n", iPD1, iPD1 << X86_PD_SHIFT));749 if (iPD1 != iPD2)750 Log(("pgmXXGst32BitWriteHandlerCR3: emulated change to PD %#x addr=%x\n", iPD2, iPD2 << X86_PD_SHIFT));751 #endif752 753 if (!pVM->pgm.s.fMappingsFixed)754 {755 PX86PD pPDSrc = pgmGstGet32bitPDPtr(&pVM->pgm.s);756 if ( ( pPDSrc->a[iPD1].n.u1Present757 && pgmGetMapping(pVM, (RTGCPTR)(iPD1 << X86_PD_SHIFT)) )758 || ( iPD1 != iPD2759 && pPDSrc->a[iPD2].n.u1Present760 && pgmGetMapping(pVM, (RTGCPTR)(iPD2 << X86_PD_SHIFT)) )761 )762 {763 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteConflict);764 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);765 if (rc == VINF_SUCCESS)766 rc = VINF_PGM_SYNC_CR3;767 Log(("pgmXXGst32BitWriteHandlerCR3: detected conflict iPD1=%#x iPD2=%#x - returns %Rrc\n", iPD1, iPD2, rc));768 return rc;769 }770 }771 772 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteHandled);773 }774 else775 {776 Assert(RT_FAILURE(rc));777 if (rc == VERR_EM_INTERPRETER)778 rc = VINF_EM_RAW_EMULATE_INSTR_PD_FAULT;779 Log(("pgmXXGst32BitWriteHandlerCR3: returns %Rrc\n", rc));780 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteUnhandled);781 }782 return rc;783 }784 785 #endif /* PGM_TYPE_32BIT && !IN_RING3 */786 #if PGM_GST_TYPE == PGM_TYPE_PAE && !defined(IN_RING3)787 788 /**789 * Write access handler for the Guest CR3 page in PAE mode.790 *791 * This will try interpret the instruction, if failure fail back to the recompiler.792 * Check if the changed PDEs are marked present and conflicts with our793 * mappings. If conflict, we'll switch to the host context and resolve it there794 *795 * @returns VBox status code (appropritate for trap handling and GC return).796 * @param pVM VM Handle.797 * @param uErrorCode CPU Error code.798 * @param pRegFrame Trap register frame.799 * @param pvFault The fault address (cr2).800 * @param GCPhysFault The GC physical address corresponding to pvFault.801 * @param pvUser User argument.802 */803 PGM_GST_DECL(int, WriteHandlerCR3)(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)804 {805 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));806 807 /*808 * Try interpret the instruction.809 */810 uint32_t cb;811 int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);812 if (RT_SUCCESS(rc) && cb)813 {814 /*815 * Check if any of the PDs have changed.816 * We'll simply check all of them instead of figuring out which one/two to check.817 */818 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);819 for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)820 {821 if ( pGuestPDPT->a[i].n.u1Present822 && (pGuestPDPT->a[i].u & X86_PDPE_PG_MASK)823 != pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])824 {825 /*826 * The PDPE has changed.827 * We will schedule a monitoring update for the next TLB Flush,828 * InvalidatePage or SyncCR3.829 *830 * This isn't perfect, because a lazy page sync might be dealing with an half831 * updated PDPE. However, we assume that the guest OS is disabling interrupts832 * and being extremely careful (cmpxchg8b) when updating a PDPE where it's833 * executing.834 */835 pVM->pgm.s.fSyncFlags |= PGM_SYNC_MONITOR_CR3;836 Log(("pgmXXGstPaeWriteHandlerCR3: detected updated PDPE; [%d] = %#llx, Old GCPhys=%RGp\n",837 i, pGuestPDPT->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));838 }839 }840 841 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteHandled);842 }843 else844 {845 Assert(RT_FAILURE(rc));846 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteUnhandled);847 if (rc == VERR_EM_INTERPRETER)848 rc = VINF_EM_RAW_EMULATE_INSTR_PD_FAULT;849 }850 Log(("pgmXXGstPaeWriteHandlerCR3: returns %Rrc\n", rc));851 return rc;852 }853 854 855 /**856 * Write access handler for the Guest PDs in PAE mode.857 *858 * This will try interpret the instruction, if failure fail back to the recompiler.859 * Check if the changed PDEs are marked present and conflicts with our860 * mappings. If conflict, we'll switch to the host context and resolve it there861 *862 * @returns VBox status code (appropritate for trap handling and GC return).863 * @param pVM VM Handle.864 * @param uErrorCode CPU Error code.865 * @param pRegFrame Trap register frame.866 * @param pvFault The fault address (cr2).867 * @param GCPhysFault The GC physical address corresponding to pvFault.868 * @param pvUser User argument.869 */870 PGM_GST_DECL(int, WriteHandlerPD)(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)871 {872 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));873 874 /*875 * Try interpret the instruction.876 */877 uint32_t cb;878 int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);879 if (RT_SUCCESS(rc) && cb)880 {881 /*882 * Figure out which of the 4 PDs this is.883 */884 RTGCPTR i;885 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);886 for (i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)887 if (pGuestPDPT->a[i].u == (GCPhysFault & X86_PTE_PAE_PG_MASK))888 {889 PX86PDPAE pPDSrc = pgmGstGetPaePD(&pVM->pgm.s, i << X86_PDPT_SHIFT);890 const RTGCPTR offPD = GCPhysFault & PAGE_OFFSET_MASK;891 const unsigned iPD1 = offPD / sizeof(X86PDEPAE);892 const unsigned iPD2 = (offPD + cb - 1) / sizeof(X86PDEPAE);893 894 Assert(cb > 0 && cb <= 8);895 Assert(iPD1 < X86_PG_PAE_ENTRIES);896 Assert(iPD2 < X86_PG_PAE_ENTRIES);897 898 # ifdef LOG_ENABLED899 Log(("pgmXXGstPaeWriteHandlerPD: emulated change to i=%d iPD1=%#05x (%x)\n",900 i, iPD1, (i << X86_PDPT_SHIFT) | (iPD1 << X86_PD_PAE_SHIFT)));901 if (iPD1 != iPD2)902 Log(("pgmXXGstPaeWriteHandlerPD: emulated change to i=%d iPD2=%#05x (%x)\n",903 i, iPD2, (i << X86_PDPT_SHIFT) | (iPD2 << X86_PD_PAE_SHIFT)));904 # endif905 906 if (!pVM->pgm.s.fMappingsFixed)907 {908 if ( ( pPDSrc->a[iPD1].n.u1Present909 && pgmGetMapping(pVM, (RTGCPTR)((i << X86_PDPT_SHIFT) | (iPD1 << X86_PD_PAE_SHIFT))) )910 || ( iPD1 != iPD2911 && pPDSrc->a[iPD2].n.u1Present912 && pgmGetMapping(pVM, (RTGCPTR)((i << X86_PDPT_SHIFT) | (iPD2 << X86_PD_PAE_SHIFT))) )913 )914 {915 Log(("pgmXXGstPaeWriteHandlerPD: detected conflict iPD1=%#x iPD2=%#x\n", iPD1, iPD2));916 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteConflict);917 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);918 return VINF_PGM_SYNC_CR3;919 }920 }921 break; /* ASSUMES no duplicate entries... */922 }923 Assert(i < 4);924 925 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteHandled);926 }927 else928 {929 Assert(RT_FAILURE(rc));930 if (rc == VERR_EM_INTERPRETER)931 rc = VINF_EM_RAW_EMULATE_INSTR_PD_FAULT;932 else933 Log(("pgmXXGst32BitWriteHandlerCR3: returns %Rrc\n", rc));934 STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestCR3WriteUnhandled);935 }936 return rc;937 }938 939 #endif /* PGM_TYPE_PAE && !IN_RING3 */940 941 #endif /* !VBOX_WITH_PGMPOOL_PAGING_ONLY */
Note:
See TracChangeset
for help on using the changeset viewer.