/** * Register a access handler for a physical range. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param enmType Handler type. Any of the PGMPHYSHANDLERTYPE_PHYSICAL* enums. * @param GCPhys Start physical address. * @param GCPhysLast Last physical address. (inclusive) * @param pfnHandlerR3 The R3 handler. * @param pvUserR3 User argument to the R3 handler. * @param pszModR0 The R0 handler module. NULL means the default R0 module. * @param pszHandlerR0 The R0 handler symbol name. * @param pvUserR0 User argument to the R0 handler. * @param pszModRC The RC handler module. NULL means the default RC * module. * @param pszHandlerRC The RC handler symbol name. * @param pvUserRC User argument to the RC handler. Values less than * 0x10000 will not be relocated. * @param pszDesc Pointer to description string. This must not be freed. */ VMMR3DECL(int) PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3, const char *pszModR0, const char *pszHandlerR0, RTR0PTR pvUserR0, const char *pszModRC, const char *pszHandlerRC, RTRCPTR pvUserRC, const char *pszDesc) { LogFlow(("PGMR3HandlerPhysicalRegister: enmType=%d GCPhys=%RGp GCPhysLast=%RGp pfnHandlerR3=%RHv pvUserHC=%RHv pszModR0=%s pszHandlerR0=%s pvUserR0=%RHv pszModRC=%s pszHandlerRC=%s pvUser=%RRv pszDesc=%s\n", enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pszModR0, pszHandlerR0, pvUserR0, pszHandlerRC, pszModRC, pvUserRC, pszDesc)); /* * Validate input. */ if (!pszModRC) pszModRC = VMMGC_MAIN_MODULE_NAME; if (!pszModR0) pszModR0 = VMMR0_MAIN_MODULE_NAME; if (!pszHandlerR0) pszHandlerR0 = "pgmPhysHandlerRedirectToHC"; if (!pszHandlerRC) pszHandlerRC = "pgmPhysHandlerRedirectToHC"; AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER); AssertPtrReturn(pszHandlerR0, VERR_INVALID_POINTER); AssertPtrReturn(pszHandlerRC, VERR_INVALID_POINTER); /* * Resolve the R0 handler. */ R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0 = NIL_RTR0PTR; int rc = VINF_SUCCESS; rc = PDMR3LdrGetSymbolR0Lazy(pVM, pszModR0, NULL /*pszSearchPath*/, pszHandlerR0, &pfnHandlerR0); if (RT_SUCCESS(rc)) { /* * Resolve the GC handler. */ RTRCPTR pfnHandlerRC = NIL_RTRCPTR; if (!HMIsEnabled(pVM)) rc = PDMR3LdrGetSymbolRCLazy(pVM, pszModRC, NULL /*pszSearchPath*/, pszHandlerRC, &pfnHandlerRC); if (RT_SUCCESS(rc)) return PGMHandlerPhysicalRegisterEx(pVM, enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pfnHandlerR0, pvUserR0, pfnHandlerRC, pvUserRC, pszDesc); AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszModRC, pszHandlerRC, rc)); } else AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszModR0, pszHandlerR0, rc)); return rc; }
VMCPU_ASSERT_EMT(pVCpu); Assert(pVCpu->vmm.s.cCallRing3Disabled <= 16); return pVCpu->vmm.s.cCallRing3Disabled == 0; } /** * Sets the ring-0 callback before doing the ring-3 call. * * @param pVCpu The cross context virtual CPU structure. * @param pfnCallback Pointer to the callback. * @param pvUser The user argument. * * @return VBox status code. */ VMMRZDECL(int) VMMRZCallRing3SetNotification(PVMCPU pVCpu, R0PTRTYPE(PFNVMMR0CALLRING3NOTIFICATION) pfnCallback, RTR0PTR pvUser) { AssertPtrReturn(pVCpu, VERR_INVALID_POINTER); AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); if (pVCpu->vmm.s.pfnCallRing3CallbackR0) return VERR_ALREADY_EXISTS; pVCpu->vmm.s.pfnCallRing3CallbackR0 = pfnCallback; pVCpu->vmm.s.pvCallRing3CallbackUserR0 = pvUser; return VINF_SUCCESS; } /** * Removes the ring-0 callback.
* @returns VBox status code. * @param pVM Pointer to the cross context VM structure. * @param enmKind The kind of access handler. * @param pfnHandlerR3 Pointer to the ring-3 handler callback. * @param pfnHandlerR0 Pointer to the ring-0 handler callback. * @param pfnPfHandlerR0 Pointer to the ring-0 \#PF handler callback. * @param pfnHandlerRC Pointer to the raw-mode context handler callback. * @param pfnPfHandlerRC Pointer to the raw-mode context \#PF handler * callback. * @param pszDesc The type description. * @param phType Where to return the type handle (cross context * safe). */ VMMR3_INT_DECL(int) PGMR3HandlerPhysicalTypeRegisterEx(PVM pVM, PGMPHYSHANDLERKIND enmKind, PFNPGMPHYSHANDLER pfnHandlerR3, R0PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR0, R0PTRTYPE(PFNPGMRZPHYSPFHANDLER) pfnPfHandlerR0, RCPTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerRC, RCPTRTYPE(PFNPGMRZPHYSPFHANDLER) pfnPfHandlerRC, const char *pszDesc, PPGMPHYSHANDLERTYPE phType) { AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER); AssertReturn(pfnHandlerR0 != NIL_RTR0PTR, VERR_INVALID_POINTER); AssertReturn(pfnPfHandlerR0 != NIL_RTR0PTR, VERR_INVALID_POINTER); AssertReturn(pfnHandlerRC != NIL_RTRCPTR || HMIsEnabled(pVM), VERR_INVALID_POINTER); AssertReturn(pfnPfHandlerRC != NIL_RTRCPTR || HMIsEnabled(pVM), VERR_INVALID_POINTER); AssertPtrReturn(pszDesc, VERR_INVALID_POINTER); AssertReturn( enmKind == PGMPHYSHANDLERKIND_WRITE || enmKind == PGMPHYSHANDLERKIND_ALL || enmKind == PGMPHYSHANDLERKIND_MMIO, VERR_INVALID_PARAMETER);