diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
|---|---|---|
| committer | <> | 2014-05-08 15:03:54 +0000 |
| commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
| tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/VMM/VMMRZ/VMMRZ.cpp | |
| parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
| download | VirtualBox-master.tar.gz | |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/VMM/VMMRZ/VMMRZ.cpp')
| -rw-r--r-- | src/VBox/VMM/VMMRZ/VMMRZ.cpp | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/src/VBox/VMM/VMMRZ/VMMRZ.cpp b/src/VBox/VMM/VMMRZ/VMMRZ.cpp index 9a86cfb6..e78f41fb 100644 --- a/src/VBox/VMM/VMMRZ/VMMRZ.cpp +++ b/src/VBox/VMM/VMMRZ/VMMRZ.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -25,6 +25,7 @@ #include <VBox/err.h> #include <iprt/assert.h> +#include <iprt/asm-amd64-x86.h> #include <iprt/string.h> @@ -52,6 +53,7 @@ VMMRZDECL(int) VMMRZCallRing3(PVM pVM, PVMCPU pVCpu, VMMCALLRING3 enmOperation, if (RT_UNLIKELY( pVCpu->vmm.s.cCallRing3Disabled != 0 && enmOperation != VMMCALLRING3_VM_R0_ASSERTION)) { +#ifndef IN_RING0 /* * In most cases, it's sufficient to return a status code which * will then be propagated up the code usually encountering several @@ -64,6 +66,7 @@ VMMRZDECL(int) VMMRZCallRing3(PVM pVM, PVMCPU pVCpu, VMMCALLRING3 enmOperation, */ if (enmOperation != VMMCALLRING3_REM_REPLAY_HANDLER_NOTIFICATIONS) return VERR_VMM_RING3_CALL_DISABLED; +#endif #ifdef IN_RC RTStrPrintf(g_szRTAssertMsg1, sizeof(pVM->vmm.s.szRing0AssertMsg1), "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x\n", enmOperation, uArg, pVCpu->idCpu); @@ -83,7 +86,14 @@ VMMRZDECL(int) VMMRZCallRing3(PVM pVM, PVMCPU pVCpu, VMMCALLRING3 enmOperation, #ifdef IN_RC pVM->vmm.s.pfnRCToHost(VINF_VMM_CALL_HOST); #else - int rc = vmmR0CallRing3LongJmp(&pVCpu->vmm.s.CallRing3JmpBufR0, VINF_VMM_CALL_HOST); + int rc; + if (pVCpu->vmm.s.pfnCallRing3CallbackR0) + { + rc = pVCpu->vmm.s.pfnCallRing3CallbackR0(pVCpu, enmOperation, pVCpu->vmm.s.pvCallRing3CallbackUserR0); + if (RT_FAILURE(rc)) + return rc; + } + rc = vmmR0CallRing3LongJmp(&pVCpu->vmm.s.CallRing3JmpBufR0, VINF_VMM_CALL_HOST); if (RT_FAILURE(rc)) return rc; #endif @@ -118,8 +128,12 @@ VMMRZDECL(int) VMMRZCallRing3NoCpu(PVM pVM, VMMCALLRING3 enmOperation, uint64_t VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu) { VMCPU_ASSERT_EMT(pVCpu); +#if defined(LOG_ENABLED) && defined(IN_RING0) + RTCCUINTREG fFlags = ASMIntDisableFlags(); /* preemption consistency. */ +#endif + Assert(pVCpu->vmm.s.cCallRing3Disabled < 16); - if (++pVCpu->vmm.s.cCallRing3Disabled == 1) + if (ASMAtomicIncU32(&pVCpu->vmm.s.cCallRing3Disabled) == 1) /** @todo replace with unordered variant (ASMAtomicUoIncU32). */ { /** @todo it might make more sense to just disable logging here, then we * won't flush away important bits... but that goes both ways really. */ @@ -132,6 +146,10 @@ VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu) # endif #endif } + +#if defined(LOG_ENABLED) && defined(IN_RING0) + ASMSetFlags(fFlags); +#endif } @@ -144,8 +162,12 @@ VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu) VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPU pVCpu) { VMCPU_ASSERT_EMT(pVCpu); +#if defined(LOG_ENABLED) && defined(IN_RING0) + RTCCUINTREG fFlags = ASMIntDisableFlags(); /* preemption consistency. */ +#endif + Assert(pVCpu->vmm.s.cCallRing3Disabled > 0); - if (--pVCpu->vmm.s.cCallRing3Disabled == 0) + if (ASMAtomicDecU32(&pVCpu->vmm.s.cCallRing3Disabled) == 0) /** @todo replace with unordered variant (ASMAtomicUoDecU32). */ { #ifdef IN_RC pVCpu->pVMRC->vmm.s.fRCLoggerFlushingDisabled = false; @@ -156,6 +178,10 @@ VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPU pVCpu) # endif #endif } + +#if defined(LOG_ENABLED) && defined(IN_RING0) + ASMSetFlags(fFlags); +#endif } @@ -172,3 +198,49 @@ VMMRZDECL(bool) VMMRZCallRing3IsEnabled(PVMCPU pVCpu) return pVCpu->vmm.s.cCallRing3Disabled == 0; } + +/** + * Sets the ring-0 callback before doing the ring-3 call. + * + * @param pVCpu Pointer to the VMCPU. + * @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. + * + * @param pVCpu Pointer to the VMCPU. + */ +VMMRZDECL(void) VMMRZCallRing3RemoveNotification(PVMCPU pVCpu) +{ + pVCpu->vmm.s.pfnCallRing3CallbackR0 = NULL; +} + + +/** + * Checks whether there is a ring-0 callback notification active. + * + * @param pVCpu Pointer to the VMCPU. + * @returns true if there the notification is active, false otherwise. + */ +VMMRZDECL(bool) VMMRZCallRing3IsNotificationSet(PVMCPU pVCpu) +{ + return pVCpu->vmm.s.pfnCallRing3CallbackR0 != NULL; +} + |
