Index: trunk/include/VBox/vmm/vmm.h
===================================================================
--- trunk/include/VBox/vmm/vmm.h	(revision 96924)
+++ trunk/include/VBox/vmm/vmm.h	(revision 96925)
@@ -454,6 +454,6 @@
  * Request package for VMMR0_DO_VMMR0_UPDATE_LOGGERS.
  *
- * In addition the u64Arg selects the logger sets: @c false for debug, @c true
- * for release.
+ * In addition the u64Arg is selects the logger and indicates whether we're only
+ * outputting to the parent VMM. See VMMR0UPDATELOGGER_F_XXX.
  */
 typedef struct VMMR0UPDATELOGGERSREQ
@@ -473,4 +473,16 @@
 /** Pointer to a VMMR0_DO_VMMR0_UPDATE_LOGGERS request. */
 typedef VMMR0UPDATELOGGERSREQ *PVMMR0UPDATELOGGERSREQ;
+
+/** @name VMMR0UPDATELOGGER_F_XXX - u64Arg definitions for VMMR0_DO_VMMR0_UPDATE_LOGGERS.
+ * @{ */
+/** Logger index mask. */
+#define VMMR0UPDATELOGGER_F_LOGGER_MASK         UINT64_C(0x0001)
+/** Only flush to the parent VMM's debug log, don't return to ring-3. */
+#define VMMR0UPDATELOGGER_F_TO_PARENT_VMM_DBG   UINT64_C(0x0002)
+/** Only flush to the parent VMM's debug log, don't return to ring-3. */
+#define VMMR0UPDATELOGGER_F_TO_PARENT_VMM_REL   UINT64_C(0x0004)
+/** Valid flag mask. */
+#define VMMR0UPDATELOGGER_F_VALID_MASK          UINT64_C(0x0007)
+/** @} */
 
 #if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
Index: trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- trunk/src/VBox/Runtime/Makefile.kmk	(revision 96924)
+++ trunk/src/VBox/Runtime/Makefile.kmk	(revision 96925)
@@ -3405,5 +3405,6 @@
 	common/asm/ASMRdMsrEx.asm \
 	common/asm/ASMWrMsrEx.asm \
-	common/string/RTStrEnd.asm
+	common/string/RTStrEnd.asm \
+	VBox/RTLogWriteVmm-amd64-x86.asm
 RuntimeR0_SOURCES.amd64 += \
 	common/asm/ASMCpuIdExSlow.asm \
@@ -3425,5 +3426,6 @@
 	common/asm/ASMWrMsrEx.asm \
 	common/math/RTUInt128MulByU64Ex.asm \
-	common/string/RTStrEnd.asm
+	common/string/RTStrEnd.asm \
+	VBox/RTLogWriteVmm-amd64-x86.asm
 RuntimeR0_SOURCES.arm32 += \
 	common/string/RTStrEnd.cpp
Index: trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 96924)
+++ trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 96925)
@@ -100,5 +100,5 @@
 #endif
 RT_C_DECLS_END
-static int  vmmR0UpdateLoggers(PGVM pGVM, VMCPUID idCpu, PVMMR0UPDATELOGGERSREQ pReq, size_t idxLogger);
+static int  vmmR0UpdateLoggers(PGVM pGVM, VMCPUID idCpu, PVMMR0UPDATELOGGERSREQ pReq, uint64_t fFlags);
 static int  vmmR0LogFlusher(PGVM pGVM);
 static int  vmmR0LogWaitFlushed(PGVM pGVM, VMCPUID idCpu, size_t idxLogger);
@@ -1837,6 +1837,6 @@
             if (idCpu == NIL_VMCPUID)
                 return VERR_INVALID_CPU_ID;
-            if (u64Arg < VMMLOGGER_IDX_MAX  && pReqHdr != NULL)
-                rc = vmmR0UpdateLoggers(pGVM, idCpu /*idCpu*/, (PVMMR0UPDATELOGGERSREQ)pReqHdr, (size_t)u64Arg);
+            if (!(u64Arg & ~VMMR0UPDATELOGGER_F_VALID_MASK) && pReqHdr != NULL)
+                rc = vmmR0UpdateLoggers(pGVM, idCpu /*idCpu*/, (PVMMR0UPDATELOGGERSREQ)pReqHdr, u64Arg);
             else
                 return VERR_INVALID_PARAMETER;
@@ -2738,8 +2738,8 @@
  * @param   idCpu           The ID of the calling EMT.
  * @param   pReq            The request data.
- * @param   idxLogger       Which logger set to update.
+ * @param   fFlags          Flags, see VMMR0UPDATELOGGER_F_XXX.
  * @thread  EMT(idCpu)
  */
-static int vmmR0UpdateLoggers(PGVM pGVM, VMCPUID idCpu, PVMMR0UPDATELOGGERSREQ pReq, size_t idxLogger)
+static int vmmR0UpdateLoggers(PGVM pGVM, VMCPUID idCpu, PVMMR0UPDATELOGGERSREQ pReq, uint64_t fFlags)
 {
     /*
@@ -2753,4 +2753,5 @@
     AssertReturn(pReq->Hdr.cbReq == RT_UOFFSETOF_DYN(VMMR0UPDATELOGGERSREQ, afGroups[pReq->cGroups]), VERR_INVALID_PARAMETER);
 
+    size_t const idxLogger = (size_t)(fFlags & VMMR0UPDATELOGGER_F_LOGGER_MASK);
     AssertReturn(idxLogger < VMMLOGGER_IDX_MAX, VERR_OUT_OF_RANGE);
 
@@ -2758,6 +2759,7 @@
      * Adjust flags.
      */
-    /* Always buffered: */
-    pReq->fFlags |= RTLOGFLAGS_BUFFERED;
+    /* Always buffered, unless logging directly to parent VMM: */
+    if (!(fFlags & (VMMR0UPDATELOGGER_F_TO_PARENT_VMM_DBG | VMMR0UPDATELOGGER_F_TO_PARENT_VMM_REL)))
+        pReq->fFlags |= RTLOGFLAGS_BUFFERED;
     /* These doesn't make sense at present: */
     pReq->fFlags &= ~(RTLOGFLAGS_FLUSH | RTLOGFLAGS_WRITE_THROUGH);
@@ -2775,4 +2777,7 @@
         if (pLogger)
         {
+            pGVCpu->vmmr0.s.u.aLoggers[idxLogger].fFlushToParentVmmDbg = RT_BOOL(fFlags & VMMR0UPDATELOGGER_F_TO_PARENT_VMM_DBG);
+            pGVCpu->vmmr0.s.u.aLoggers[idxLogger].fFlushToParentVmmRel = RT_BOOL(fFlags & VMMR0UPDATELOGGER_F_TO_PARENT_VMM_REL);
+
             RTLogSetR0ProgramStart(pLogger, pGVM->vmm.s.nsProgramStart);
             rc = RTLogBulkUpdate(pLogger, pReq->fFlags, pReq->uGroupCrc32, pReq->cGroups, pReq->afGroups);
@@ -2998,7 +3003,7 @@
 
 /**
- * Inner worker for vmmR0LoggerFlushCommon.
- */
-static bool   vmmR0LoggerFlushInner(PGVM pGVM, PGVMCPU pGVCpu, uint32_t idxLogger, size_t idxBuffer, uint32_t cbToFlush)
+ * Inner worker for vmmR0LoggerFlushCommon for flushing to ring-3.
+ */
+static bool   vmmR0LoggerFlushInnerToRing3(PGVM pGVM, PGVMCPU pGVCpu, uint32_t idxLogger, size_t idxBuffer, uint32_t cbToFlush)
 {
     PVMMR0PERVCPULOGGER const pR0Log    = &pGVCpu->vmmr0.s.u.aLoggers[idxLogger];
@@ -3048,5 +3053,5 @@
     if (enmAction != kJustSignal)
     {
-        int rc = VMMR0EmtPrepareToBlock(pGVCpu, VINF_SUCCESS, "vmmR0LoggerFlushInner", pR0Log->hEventFlushWait, &Ctx);
+        int rc = VMMR0EmtPrepareToBlock(pGVCpu, VINF_SUCCESS, "vmmR0LoggerFlushInnerToRing3", pR0Log->hEventFlushWait, &Ctx);
         if (RT_SUCCESS(rc))
         { /* likely */ }
@@ -3154,4 +3159,20 @@
     return fFlushedBuffer;
 }
+
+
+/**
+ * Inner worker for vmmR0LoggerFlushCommon when only flushing to the parent
+ * VMM's logs.
+ */
+static bool vmmR0LoggerFlushInnerToParent(PGVM pGVM, PGVMCPU pGVCpu, PVMMR0PERVCPULOGGER pR0Log, PRTLOGBUFFERDESC pBufDesc)
+{
+    uint32_t const cbToFlush = pBufDesc->offBuf;
+    if (pR0Log->fFlushToParentVmmDbg)
+        RTLogWriteVmm(pBufDesc->pchBuf, cbToFlush, false /*fRelease*/);
+    if (pR0Log->fFlushToParentVmmRel)
+        RTLogWriteVmm(pBufDesc->pchBuf, cbToFlush, true /*fRelease*/);
+    return true;
+}
+
 
 
@@ -3192,5 +3213,10 @@
                         {
                             pR0Log->fFlushing = true;
-                            bool fFlushed = vmmR0LoggerFlushInner(pGVM, pGVCpu, idxLogger, idxBuffer, pBufDesc->offBuf);
+                            bool fFlushed;
+                            if (   !pR0Log->fFlushToParentVmmDbg
+                                && !pR0Log->fFlushToParentVmmRel)
+                                fFlushed = vmmR0LoggerFlushInnerToRing3(pGVM, pGVCpu, idxLogger, idxBuffer, pBufDesc->offBuf);
+                            else
+                                fFlushed = vmmR0LoggerFlushInnerToParent(pGVM, pGVCpu, pR0Log, pBufDesc);
                             pR0Log->fFlushing = false;
                             return fFlushed;
Index: trunk/src/VBox/VMM/VMMR3/VMM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 96924)
+++ trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 96925)
@@ -731,5 +731,20 @@
         AssertRC(rc);
         if (RT_SUCCESS(rc))
-            rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_VMMR0_UPDATE_LOGGERS, fReleaseLogger, &pReq->Hdr);
+        {
+            /*
+             * The 64-bit value argument.
+             */
+            uint64_t fExtraArg = fReleaseLogger;
+
+            /* Only outputting to the parent VMM's logs? Enable ring-0 to flush directly. */
+            uint32_t fDst = RTLogGetDestinations(pSrcLogger);
+            fDst &= ~(RTLOGDEST_DUMMY | RTLOGDEST_F_NO_DENY | RTLOGDEST_F_DELAY_FILE | RTLOGDEST_FIXED_FILE | RTLOGDEST_FIXED_DIR);
+            if (   (fDst & (RTLOGDEST_VMM | RTLOGDEST_VMM_REL))
+                && !(fDst & ~(RTLOGDEST_VMM | RTLOGDEST_VMM_REL)))
+                fExtraArg |= (fDst & RTLOGDEST_VMM     ? VMMR0UPDATELOGGER_F_TO_PARENT_VMM_DBG : 0)
+                          |  (fDst & RTLOGDEST_VMM_REL ? VMMR0UPDATELOGGER_F_TO_PARENT_VMM_REL : 0);
+
+            rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_VMMR0_UPDATE_LOGGERS, fExtraArg, &pReq->Hdr);
+        }
 
         RTMemFree(pReq);
Index: trunk/src/VBox/VMM/include/VMMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/VMMInternal.h	(revision 96924)
+++ trunk/src/VBox/VMM/include/VMMInternal.h	(revision 96925)
@@ -99,5 +99,8 @@
     /** Set while we're inside vmmR0LoggerFlushCommon to prevent recursion. */
     bool                    fFlushing;
-    bool                    afPadding[1];
+    /** Flush to parent VMM's debug log instead of ring-3. */
+    bool                    fFlushToParentVmmDbg : 1;
+    /** Flush to parent VMM's debug log instead of ring-3. */
+    bool                    fFlushToParentVmmRel : 1;
     /** Number of buffers currently queued for flushing. */
     uint32_t volatile       cFlushing;
