Index: /trunk/include/VBox/vmm/gvm.h
===================================================================
--- /trunk/include/VBox/vmm/gvm.h	(revision 90828)
+++ /trunk/include/VBox/vmm/gvm.h	(revision 90829)
@@ -120,12 +120,12 @@
         struct VMMR0PERVCPU s;
 #endif
-        uint8_t             padding[64];
+        uint8_t             padding[256];
     } vmmr0;
 
     /** Padding the structure size to page boundrary. */
 #ifdef VBOX_WITH_NEM_R0
-    uint8_t                 abPadding3[4096 - 64*2 - 64 - 1024 - 64 - 64];
+    uint8_t                 abPadding3[4096 - 64*2 - 64 - 1024 - 64 - 256];
 #else
-    uint8_t                 abPadding3[4096 - 64*2 - 64 - 1024 - 64];
+    uint8_t                 abPadding3[4096 - 64*2 - 64 - 1024 - 256];
 #endif
 } GVMCPU;
@@ -282,9 +282,17 @@
     } tmr0;
 
+    union
+    {
+#if defined(VMM_INCLUDED_SRC_include_VMMInternal_h) && defined(IN_RING0)
+        VMMR0PERVM          s;
+#endif
+        uint8_t             padding[64];
+    } vmmr0;
+
     /** Padding so aCpus starts on a page boundrary.  */
 #ifdef VBOX_WITH_NEM_R0
-    uint8_t         abPadding2[4096*2 - 64 - 256 - 256 - 1024 - 256 - 64 - 2176 - 640 - 512 - 64 - 1024 - 128 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];
+    uint8_t         abPadding2[4096*2 - 64 - 256 - 256 - 1024 - 256 - 64 - 2176 - 640 - 512 - 64 - 1024 - 128 - 64 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];
 #else
-    uint8_t         abPadding2[4096*2 - 64 - 256 - 256 - 1024       - 64 - 2176 - 640 - 512 - 64 - 1024 - 128 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];
+    uint8_t         abPadding2[4096*2 - 64 - 256 - 256 - 1024       - 64 - 2176 - 640 - 512 - 64 - 1024 - 128 - 64 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];
 #endif
 
Index: /trunk/include/VBox/vmm/vmm.h
===================================================================
--- /trunk/include/VBox/vmm/vmm.h	(revision 90828)
+++ /trunk/include/VBox/vmm/vmm.h	(revision 90829)
@@ -297,4 +297,6 @@
     /** Call VMMR0 Per VM Termination. */
     VMMR0_DO_VMMR0_TERM,
+    /** Copy logger settings from userland, VMMR0UpdateLoggersReq(). */
+    VMMR0_DO_VMMR0_UPDATE_LOGGERS,
 
     /** Setup hardware-assisted VM session. */
@@ -472,4 +474,28 @@
 typedef GCFGMVALUEREQ *PGCFGMVALUEREQ;
 
+
+/**
+ * Request package for VMMR0_DO_VMMR0_UPDATE_LOGGERS.
+ *
+ * In addition the u64Arg selects the logger sets: @c false for debug, @c true
+ * for release.
+ */
+typedef struct VMMR0UPDATELOGGERSREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR      Hdr;
+    /** The current logger flags (RTLOGFLAGS). */
+    uint64_t            fFlags;
+    /** Groups, assuming same group layout as ring-3. */
+    uint32_t            cGroups;
+    /** CRC32 of the group names. */
+    uint32_t            uGroupCrc32;
+    /** Per-group settings, variable size. */
+    RT_FLEXIBLE_ARRAY_EXTENSION
+    uint32_t            afGroups[RT_FLEXIBLE_ARRAY];
+} VMMR0UPDATELOGGERSREQ;
+/** Pointer to a VMMR0_DO_VMMR0_UPDATE_LOGGERS request. */
+typedef VMMR0UPDATELOGGERSREQ *PVMMR0UPDATELOGGERSREQ;
+
 #if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
 
@@ -497,4 +523,5 @@
 VMMR0_INT_DECL(void) VMMR0InitPerVMData(PGVM pGVM);
 VMMR0_INT_DECL(int)  VMMR0TermVM(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(void) VMMR0CleanupVM(PGVM pGVM);
 VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPUCC pVCpu);
 VMMR0_INT_DECL(bool) VMMR0IsInRing3LongJump(PVMCPUCC pVCpu);
Index: /trunk/include/iprt/err.h
===================================================================
--- /trunk/include/iprt/err.h	(revision 90828)
+++ /trunk/include/iprt/err.h	(revision 90829)
@@ -128,4 +128,6 @@
 /** Already initialized. */
 #define VINF_ALREADY_INITIALIZED            28
+/** Already initialized. */
+#define VERR_ALREADY_INITIALIZED            (-28)
 /** The specified thread is dead. */
 #define VERR_THREAD_IS_DEAD                 (-29)
Index: /trunk/include/iprt/log.h
===================================================================
--- /trunk/include/iprt/log.h	(revision 90828)
+++ /trunk/include/iprt/log.h	(revision 90829)
@@ -172,4 +172,8 @@
 
 
+/** Pointer to a log buffer descriptor. */
+typedef struct RTLOGBUFFERDESC *PRTLOGBUFFERDESC;
+
+
 /**
  * Logger phase.
@@ -203,20 +207,16 @@
 
 /**
- * Flush function.
- *
+ * Custom buffer flushing function.
+ *
+ * @retval  true if flushed.
+ * @retval  false if flushing pending on other thread and the logger should
+ *          switch to the next buffer.  The other thread will call
+ *          RTLogFlushDone when finished.
  * @param   pLogger     Pointer to the logger instance which is to be flushed.
- */
-typedef DECLCALLBACKTYPE(void, FNRTLOGFLUSH,(PRTLOGGER pLogger));
+ * @param   pBufDesc    The descriptor of the buffer to be flushed.
+ */
+typedef DECLCALLBACKTYPE(bool, FNRTLOGFLUSH,(PRTLOGGER pLogger, PRTLOGBUFFERDESC pBufDesc));
 /** Pointer to flush function. */
 typedef FNRTLOGFLUSH *PFNRTLOGFLUSH;
-
-/**
- * Flush function.
- *
- * @param   pLogger     Pointer to the logger instance which is to be flushed.
- */
-typedef DECLCALLBACKTYPE(void, FNRTLOGFLUSHGC,(PRTLOGGERRC pLogger));
-/** Pointer to logger function. */
-typedef RCPTRTYPE(FNRTLOGFLUSHGC *) PFNRTLOGFLUSHGC;
 
 /**
@@ -262,85 +262,76 @@
 
 /**
- * Logger instance structure for raw-mode context (RC).
- */
-struct RTLOGGERRC
+ * Auxiliary buffer descriptor.
+ *
+ * This is what we share we ring-3 and use for flushing ring-0 EMT loggers when
+ * we return to ring-3.
+ */
+typedef struct RTLOGBUFFERAUXDESC
 {
-    /** Pointer to temporary scratch buffer.
-     * This is used to format the log messages. */
-    char                    achScratch[32768];
-    /** Current scratch buffer position. */
-    uint32_t                offScratch;
-    /** This is set if a prefix is pending. */
-    bool                    fPendingPrefix;
-    bool                    afAlignment[3];
-    /** Pointer to the logger function.
-     * This is actually pointer to a wrapper which will push a pointer to the
-     * instance pointer onto the stack before jumping to the real logger function.
-     * A very unfortunate hack to work around the missing variadic macro support in C++. */
-    RCPTRTYPE(PFNRTLOGGER)  pfnLogger;
-    /** Pointer to the flush function. */
-    PFNRTLOGFLUSHGC         pfnFlush;
-    /** Magic number (RTLOGGERRC_MAGIC). */
+    /** Flush indicator.
+     * Ring-3 sets this if it flushed the buffer, ring-0 clears it again after
+     * writing. */
+    bool volatile           fFlushedIndicator;
+    bool                    afPadding[3];
+    /** Copy of RTLOGBUFFERDESC::offBuf. */
+    uint32_t                offBuf;
+} RTLOGBUFFERAUXDESC;
+/** Pointer to auxiliary buffer descriptor. */
+typedef RTLOGBUFFERAUXDESC *PRTLOGBUFFERAUXDESC;
+
+/**
+ * Log buffer desciptor.
+ */
+typedef struct RTLOGBUFFERDESC
+{
+    /** Magic value / eye catcher (RTLOGBUFFERDESC_MAGIC). */
     uint32_t                u32Magic;
-    /** Logger instance flags - RTLOGFLAGS. */
-    uint32_t                fFlags;
-    /** Number of groups in the afGroups member. */
-    uint32_t                cGroups;
-    /** Group flags array - RTLOGGRPFLAGS.
-     * This member have variable length and may extend way beyond
-     * the declared size of 1 entry. */
-    uint32_t                afGroups[1];
-};
-
-/** RTLOGGERRC::u32Magic value. (John Rogers Searle) */
-#define RTLOGGERRC_MAGIC    0x19320731
-
-
-
-#if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
-
-/** Pointer to internal logger bits. */
-typedef struct RTLOGGERINTERNAL *PRTLOGGERINTERNAL;
-
-/**
- * Logger instance structure.
+    /** Padding. */
+    uint32_t                uReserved;
+    /** The buffer size. */
+    uint32_t                cbBuf;
+    /** The current buffer offset. */
+    uint32_t                offBuf;
+    /** Pointer to the buffer. */
+    char                   *pchBuf;
+    /** Pointer to auxiliary desciptor, NULL if not used. */
+    PRTLOGBUFFERAUXDESC     pAux;
+} RTLOGBUFFERDESC;
+
+/** RTLOGBUFFERDESC::u32Magic value. (Avram Noam Chomsky) */
+# define RTLOGBUFFERDESC_MAGIC   UINT32_C(0x19281207)
+
+/**
+ * The public logger instance part.
+ *
+ * The logger instance is mostly abstract and kept as RTLOGGERINTERNAL within
+ * log.cpp.  This public part is at the start of RTLOGGERINTERNAL.
  */
 struct RTLOGGER
 {
-    /** Pointer to temporary scratch buffer.
-     * This is used to format the log messages. */
-    char                    achScratch[49152];
-    /** Current scratch buffer position. */
-    uint32_t                offScratch;
-    /** Magic number. */
+    /** Magic number (RTLOGGER_MAGIC). */
     uint32_t                u32Magic;
-    /** Logger instance flags - RTLOGFLAGS. */
-    uint32_t                fFlags;
-    /** Destination flags - RTLOGDEST. */
-    uint32_t                fDestFlags;
-    /** Pointer to the internal bits of the logger.
-     * (The memory is allocated in the same block as RTLOGGER.) */
-    PRTLOGGERINTERNAL       pInt;
+    /** User value \#1, initialized to zero. */
+    uint32_t                u32UserValue1;
+    /** User value \#2, initialized to zero. */
+    uint64_t                u64UserValue2;
+    /** User value \#3, initialized to zero. */
+    uint64_t                u64UserValue3;
     /** Pointer to the logger function (used in non-C99 mode only).
      *
-     * This is actually pointer to a wrapper which will push a pointer to the
-     * instance pointer onto the stack before jumping to the real logger function.
-     * A very unfortunate hack to work around the missing variadic macro
+     * This is actually pointer to a wrapper/stub function which will push a pointer
+     * to the instance pointer onto the stack before jumping to the real logger
+     * function.  A very unfortunate hack to work around the missing variadic macro
      * support in older C++/C standards.  (The memory is allocated using
      * RTMemExecAlloc(), except for agnostic R0 code.) */
     PFNRTLOGGER             pfnLogger;
-    /** Number of groups in the afGroups and papszGroups members. */
-    uint32_t                cGroups;
-    /** Group flags array - RTLOGGRPFLAGS.
-     * This member have variable length and may extend way beyond
-     * the declared size of 1 entry. */
-    uint32_t                afGroups[1];
+#if ARCH_BITS == 32
+    /** Explicit padding. */
+    uint32_t                uReserved1;
+#endif
 };
 
-/** RTLOGGER::u32Magic value. (Avram Noam Chomsky) */
-# define RTLOGGER_MAGIC     UINT32_C(0x19281207)
-
-#endif /* !IN_RC || DOXYGEN_RUNNING */
-
+/** RTLOGGER::u32Magic value. (John Rogers Searle) */
+#define RTLOGGER_MAGIC      UINT32_C(0x19320731)
 
 /**
@@ -400,4 +391,8 @@
     RTLOGFLAGS_PREFIX_MASK          = 0x7dff8000
 } RTLOGFLAGS;
+/** Don't use locking. */
+#define RTLOG_F_NO_LOCKING          RT_BIT_64(63)
+/** Mask with all valid log flags (for validation). */
+#define RTLOG_F_VALID_MASK          UINT64_C(0x800000007fff87f3)
 
 /**
@@ -478,4 +473,8 @@
     RTLOGDEST_USER          = 0x40000000
 } RTLOGDEST;
+/** Valid log destinations. */
+#define RTLOG_DST_VALID_MASK    UINT32_C(0x6303003f)
+/** Log destinations that can be changed via RTLogChangeDestinations. */
+#define RTLOG_DST_CHANGE_MASK   UINT32_C(0x4000001e)
 
 
@@ -1973,5 +1972,4 @@
 
 #if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
-
 /**
  * Creates the default logger instance for a iprt users.
@@ -1983,4 +1981,20 @@
  */
 RTDECL(PRTLOGGER) RTLogDefaultInit(void);
+#endif
+
+/**
+ *
+ * This is the 2nd half of what RTLogGetDefaultInstanceEx() and
+ * RTLogRelGetDefaultInstanceEx() does.
+ *
+ * @returns If the group has the specified flags enabled @a pLogger will be
+ *          returned returned.  Otherwise NULL is returned.
+ * @param   pLogger         The logger.  NULL is NULL.
+ * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
+ *                          the high 16 bits.
+ */
+RTDECL(PRTLOGGER)   RTLogCheckGroupFlags(PRTLOGGER pLogger, uint32_t fFlagsAndGroup);
+
+#if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
 
 /**
@@ -2004,5 +2018,5 @@
  * @param   ...                 Format arguments.
  */
-RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint64_t fFlags, const char *pszGroupSettings,
                         const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
                         uint32_t fDestFlags, const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(8, 9);
@@ -2014,9 +2028,9 @@
  *
  * @param   ppLogger            Where to store the logger instance.
+ * @param   pszEnvVarBase       Base name for the environment variables for
+ *                              this instance (ring-3 only).
  * @param   fFlags              Logger instance flags, a combination of the
  *                              RTLOGFLAGS_* values.
  * @param   pszGroupSettings    The initial group settings.
- * @param   pszEnvVarBase       Base name for the environment variables for
- *                              this instance.
  * @param   cGroups             Number of groups in the array.
  * @param   papszGroups         Pointer to array of groups.  This must stick
@@ -2024,4 +2038,8 @@
  * @param   cMaxEntriesPerGroup The max number of entries per group.  UINT32_MAX
  *                              or zero for unlimited.
+ * @param   pfnFlush            Custom flush callback. Optional.
+ * @param   cBufDescs           Number of buffer descriptors that @a paBufDescs
+ *                              points to. Zero for defaults.
+ * @param   paBufDesc           Buffer descriptors, optional.
  * @param   fDestFlags          The destination flags.  RTLOGDEST_FILE is ORed
  *                              if pszFilenameFmt specified.
@@ -2041,9 +2059,9 @@
  * @param   ...                 Format arguments.
  */
-RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, const char *pszEnvVarBase,
-                          unsigned cGroups, const char * const * papszGroups, uint32_t cMaxEntriesPerGroup,
-                          uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
-                          uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot, PRTERRINFO pErrInfo,
-                          const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(14, 15);
+RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
+                          unsigned cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
+                          PFNRTLOGFLUSH pfnFlush, uint32_t cBufDescs, PRTLOGBUFFERDESC paBufDescs, uint32_t fDestFlags,
+                          PFNRTLOGPHASE pfnPhase, uint32_t cHistory, uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+                          PRTERRINFO pErrInfo, const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(17, 18);
 
 /**
@@ -2053,9 +2071,9 @@
  *
  * @param   ppLogger            Where to store the logger instance.
+ * @param   pszEnvVarBase       Base name for the environment variables for
+ *                              this instance (ring-3 only).
  * @param   fFlags              Logger instance flags, a combination of the
  *                              RTLOGFLAGS_* values.
  * @param   pszGroupSettings    The initial group settings.
- * @param   pszEnvVarBase       Base name for the environment variables for
- *                              this instance.
  * @param   cGroups             Number of groups in the array.
  * @param   papszGroups         Pointer to array of groups.  This must stick
@@ -2063,4 +2081,8 @@
  * @param   cMaxEntriesPerGroup The max number of entries per group.  UINT32_MAX
  *                              or zero for unlimited.
+ * @param   pfnFlush            Custom flush callback. Optional.
+ * @param   cBufDescs           Number of buffer descriptors that @a paBufDescs
+ *                              points to. Zero for defaults.
+ * @param   paBufDesc           Buffer descriptors, optional.
  * @param   fDestFlags          The destination flags.  RTLOGDEST_FILE is ORed
  *                              if pszFilenameFmt specified.
@@ -2079,11 +2101,11 @@
  * @param   pszFilenameFmt      Log filename format string.  Standard
  *                              RTStrFormat().
- * @param   args                Format arguments.
- */
-RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, const char *pszEnvVarBase,
-                           unsigned cGroups, const char * const * papszGroups, uint32_t cMaxEntriesPerGroup,
-                           uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
-                           uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot, PRTERRINFO pErrInfo,
-                           const char *pszFilenameFmt, va_list args) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(14, 0);
+ * @param   va                  Format arguments.
+ */
+RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
+                           uint32_t cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
+                           PFNRTLOGFLUSH pfnFlush, uint32_t cBufDescs, PRTLOGBUFFERDESC paBufDescs, uint32_t fDestFlags,
+                           PFNRTLOGPHASE pfnPhase, uint32_t cHistory, uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+                           PRTERRINFO pErrInfo, const char *pszFilenameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(17, 0);
 
 /**
@@ -2210,4 +2232,14 @@
 
 /**
+ * Set the thread name for a thread specific ring-0 logger.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger         The logger. NULL is not allowed.
+ * @param   pszNameFmt      The format string for the thread name.
+ * @param   ...             Format arguments.
+ */
+RTR0DECL(int) RTLogSetR0ThreadNameF(PRTLOGGER pLogger, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
  * Get the current log group settings as a string.
  *
@@ -2234,4 +2266,42 @@
 
 /**
+ * Sets the max number of entries per group.
+ *
+ * @returns Old restriction.
+ *
+ * @param   pLogger             The logger instance (NULL is an alias for the
+ *                              default logger).
+ * @param   cMaxEntriesPerGroup The max number of entries per group.
+ *
+ * @remarks Lowering the limit of an active logger may quietly mute groups.
+ *          Raising it may reactive already muted groups.
+ */
+RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup);
+
+#if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
+
+/**
+ * Gets the current flag settings for the given logger.
+ *
+ * @returns Logger flags, UINT64_MAX if no logger.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ */
+RTDECL(uint64_t) RTLogGetFlags(PRTLOGGER pLogger);
+
+/**
+ * Modifies the flag settings for the given logger.
+ *
+ * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
+ *          pLogger is NULL.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ * @param   fSet                Mask of flags to set (OR).
+ * @param   fClear              Mask of flags to clear (NAND).  This is allowed to
+ *                              include invalid flags - e.g. UINT64_MAX is okay.
+ */
+RTDECL(int) RTLogChangeFlags(PRTLOGGER pLogger, uint64_t fSet, uint64_t fClear);
+
+#endif
+
+/**
  * Updates the flags for the logger instance using the specified
  * specification string.
@@ -2256,27 +2326,5 @@
 RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered);
 
-/**
- * Sets the max number of entries per group.
- *
- * @returns Old restriction.
- *
- * @param   pLogger             The logger instance (NULL is an alias for the
- *                              default logger).
- * @param   cMaxEntriesPerGroup The max number of entries per group.
- *
- * @remarks Lowering the limit of an active logger may quietly mute groups.
- *          Raising it may reactive already muted groups.
- */
-RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup);
-
 #if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
-
-/**
- * Gets the current flag settings for the given logger.
- *
- * @returns Logger flags, UINT64_MAX if no logger.
- * @param   pLogger             Logger instance (NULL for default logger).
- */
-RTDECL(uint64_t) RTLogGetFlags(PRTLOGGER pLogger);
 
 /**
@@ -2292,4 +2340,26 @@
 
 /**
+ * Gets the current destinations flags for the given logger.
+ *
+ * @returns Logger destination flags, UINT32_MAX if no logger.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ */
+RTDECL(uint32_t) RTLogGetDestinations(PRTLOGGER pLogger);
+
+/**
+ * Modifies the log destinations settings for the given logger.
+ *
+ * This is only suitable for simple destination settings that doesn't take
+ * additional arguments, like RTLOGDEST_FILE.
+ *
+ * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
+ *          pLogger is NULL.
+ * @param   pLogger            Logger instance (NULL for default logger).
+ * @param   fSet               Mask of destinations to set (OR).
+ * @param   fClear             Mask of destinations to clear (NAND).
+ */
+RTDECL(int) RTLogChangeDestinations(PRTLOGGER pLogger, uint32_t fSet, uint32_t fClear);
+
+/**
  * Updates the logger destination using the specified string.
  *
@@ -2319,4 +2389,53 @@
  */
 RTDECL(int) RTLogQueryDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf);
+
+/**
+ * Performs a bulk update of logger flags and group flags.
+ *
+ * This is for instanced used for copying settings from ring-3 to ring-0
+ * loggers.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger             The logger instance (NULL for default logger).
+ * @param   fFlags              The new logger flags.
+ * @param   uGroupCrc32         The CRC32 of the group name strings.
+ * @param   cGroups             Number of groups.
+ * @param   pafGroups           Array of group flags.
+ * @sa      RTLogQueryBulk
+ */
+RTDECL(int) RTLogBulkUpdate(PRTLOGGER pLogger, uint64_t fFlags, uint32_t uGroupCrc32, uint32_t cGroups, uint32_t const *pafGroups);
+
+/**
+ * Queries data for a bulk update of logger flags and group flags.
+ *
+ * This is for instanced used for copying settings from ring-3 to ring-0
+ * loggers.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_BUFFER_OVERFLOW if pafGroups is too small, @a pcGroups will be
+ *          set to the actual number of groups.
+ * @param   pLogger             The logger instance (NULL for default logger).
+ * @param   pfFlags             Where to return the logger flags.
+ * @param   puGroupCrc32        Where to return the CRC32 of the group names.
+ * @param   pcGroups            Input: Size of the @a pafGroups allocation.
+ *                              Output: Actual number of groups returned.
+ * @param   pafGroups           Where to return the flags for each group.
+ * @sa      RTLogBulkUpdate
+ */
+RTDECL(int) RTLogQueryBulk(PRTLOGGER pLogger, uint64_t *pfFlags, uint32_t *puGroupCrc32, uint32_t *pcGroups, uint32_t *pafGroups);
+
+/**
+ * Write/copy bulk log data from another logger.
+ *
+ * This is used for transferring stuff from the ring-0 loggers and into the
+ * ring-3 one.  The text goes in as-is w/o any processing (i.e. prefixing or
+ * newline fun).
+ *
+ * @returns IRPT status code.
+ * @param   pLogger             The logger instance (NULL for default logger).
+ * @param   pch                 Pointer to the block of bulk log text to write.
+ * @param   cch                 Size of the block of bulk log text to write.
+ */
+RTDECL(int) RTLogBulkWrite(PRTLOGGER pLogger, const char *pch, size_t cch);
 
 #endif /* !IN_RC || DOXYGEN_RUNNING */
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 90828)
+++ /trunk/include/iprt/mangling.h	(revision 90829)
@@ -1430,5 +1430,10 @@
 # define RTLogBackdoorPrintf                            RT_MANGLER(RTLogBackdoorPrintf) /* r0drv-guest */
 # define RTLogBackdoorPrintfV                           RT_MANGLER(RTLogBackdoorPrintfV) /* r0drv-guest */
+# define RTLogBulkUpdate                                RT_MANGLER(RTLogBulkUpdate)
+# define RTLogBulkWrite                                 RT_MANGLER(RTLogBulkWrite)
 # define RTLogCalcSizeForR0                             RT_MANGLER(RTLogCalcSizeForR0)
+# define RTLogChangeDestinations                        RT_MANGLER(RTLogChangeDestinations)
+# define RTLogChangeFlags                               RT_MANGLER(RTLogChangeFlags)
+# define RTLogCheckGroupFlags                           RT_MANGLER(RTLogCheckGroupFlags)
 # define RTLogClearFileDelayFlag                        RT_MANGLER(RTLogClearFileDelayFlag)
 # define RTLogCloneRC                                   RT_MANGLER(RTLogCloneRC)
@@ -1453,4 +1458,5 @@
 # define RTLogGetDefaultInstance                        RT_MANGLER(RTLogGetDefaultInstance)
 # define RTLogGetDefaultInstanceEx                      RT_MANGLER(RTLogGetDefaultInstanceEx)
+# define RTLogGetDestinations                           RT_MANGLER(RTLogGetDestinations)
 # define RTLogGetFlags                                  RT_MANGLER(RTLogGetFlags)
 # define RTLogGroupSettings                             RT_MANGLER(RTLogGroupSettings)
@@ -1462,4 +1468,5 @@
 # define RTLogPrintfV                                   RT_MANGLER(RTLogPrintfV)
 # define RTLogDumpPrintfV                               RT_MANGLER(RTLogDumpPrintfV)
+# define RTLogQueryBulk                                 RT_MANGLER(RTLogQueryBulk)
 # define RTLogQueryDestinations                         RT_MANGLER(RTLogQueryDestinations)
 # define RTLogQueryFlags                                RT_MANGLER(RTLogQueryFlags)
@@ -1478,5 +1485,5 @@
 # define RTLogSetDefaultInstanceThread                  RT_MANGLER(RTLogSetDefaultInstanceThread) /* r0drv */
 # define RTLogSetGroupLimit                             RT_MANGLER(RTLogSetGroupLimit)
-# define RTLogWriteCom                                  RT_MANGLER(RTLogWriteCom)
+# define RTLogSetR0ThreadNameF                          RT_MANGLER(RTLogSetR0ThreadNameF)
 # define RTLogWriteCom                                  RT_MANGLER(RTLogWriteCom)
 # define RTLogWriteDebugger                             RT_MANGLER(RTLogWriteDebugger)
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp	(revision 90828)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp	(revision 90829)
@@ -567,14 +567,16 @@
     /* Create release (or debug) logger (stdout + file). */
     static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
+#ifdef DEBUG /* See below, debug logger not release. */
+    static const char s_szEnvVarPfx[] = "VBOXTRAY_LOG";
+    static const char s_szGroupSettings[] = "all.e.l.f";
+#else
+    static const char s_szEnvVarPfx[] = "VBOXTRAY_RELEASE_LOG";
+    static const char s_szGroupSettings[] = "all";
+#endif
     RTERRINFOSTATIC ErrInfo;
-    int rc = RTLogCreateEx(&g_pLoggerRelease, RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_USECRLF,
-#ifdef DEBUG /* See below, debug logger not release. */
-                           "all.e.l.f",
-                           "VBOXTRAY_LOG",
-#else
-                           "all",
-                           "VBOXTRAY_RELEASE_LOG",
-#endif
-                           RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX, RTLOGDEST_STDOUT,
+    int rc = RTLogCreateEx(&g_pLoggerRelease, s_szEnvVarPfx,
+                           RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_USECRLF,
+                           s_szGroupSettings, RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX,
+                           NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT,
                            vboxTrayLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
                            RTErrInfoInitStatic(&ErrInfo), NULL /*pszFilenameFmt*/);
Index: /trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile	(revision 90828)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile	(revision 90829)
@@ -101,4 +101,5 @@
 	strformattype.c \
 	strprintf.c \
+	strprintf2.c \
 	strtonum.c \
 	memchr.c \
Index: /trunk/src/VBox/Additions/common/VBoxGuest/freebsd/files_vboxguest
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/freebsd/files_vboxguest	(revision 90828)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/freebsd/files_vboxguest	(revision 90829)
@@ -137,4 +137,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strformattype.cpp=>common/string/strformattype.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf.cpp=>common/string/strprintf.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf2.cpp=>common/string/strprintf2.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strtonum.cpp=>common/string/strtonum.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/memchr.cpp=>common/string/memchr.c \
Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 90828)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 90829)
@@ -73,4 +73,5 @@
 	r0drv/generic/semspinmutex-r0drv-generic.o \
 	common/alloc/alloc.o \
+	common/checksum/crc32.o \
 	common/err/RTErrConvertFromErrno.o \
 	common/err/RTErrConvertToErrno.o \
@@ -107,4 +108,5 @@
 	common/string/strformattype.o \
 	common/string/strprintf.o \
+	common/string/strprintf2.o \
 	common/string/strtonum.o \
 	common/string/utf-8.o \
Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/combined-agnostic.c
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/combined-agnostic.c	(revision 90828)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/combined-agnostic.c	(revision 90829)
@@ -53,4 +53,6 @@
 #undef LOG_GROUP
 #include "common/alloc/alloc.c"
+#undef LOG_GROUP
+#include "common/checksum/crc32.c"
 #undef LOG_GROUP
 #include "common/err/errinfo.c"
@@ -116,4 +118,6 @@
 #include "common/string/strprintf.c"
 #undef LOG_GROUP
+#include "common/string/strprintf2.c"
+#undef LOG_GROUP
 #include "common/string/strtonum.c"
 #undef LOG_GROUP
Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 90828)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 90829)
@@ -38,4 +38,5 @@
     ${PATH_ROOT}/include/iprt/cdefs.h=>include/iprt/cdefs.h \
     ${PATH_ROOT}/include/iprt/cpuset.h=>include/iprt/cpuset.h \
+    ${PATH_ROOT}/include/iprt/crc.h=>include/iprt/crc.h \
     ${PATH_ROOT}/include/iprt/ctype.h=>include/iprt/ctype.h \
     ${PATH_ROOT}/include/iprt/err.h=>include/iprt/err.h \
@@ -113,4 +114,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/alloc/alloc.cpp=>common/alloc/alloc.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/alloc/heapsimple.cpp=>common/alloc/heapsimple.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/checksum/crc32.cpp=>common/checksum/crc32.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertFromErrno.cpp=>common/err/RTErrConvertFromErrno.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertToErrno.cpp=>common/err/RTErrConvertToErrno.c \
@@ -155,4 +157,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strformattype.cpp=>common/string/strformattype.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf.cpp=>common/string/strprintf.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf2.cpp=>common/string/strprintf2.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strtonum.cpp=>common/string/strtonum.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/utf-8.cpp=>common/string/utf-8.c \
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 90828)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 90829)
@@ -314,7 +314,7 @@
     fFlags |= RTLOGFLAGS_USECRLF;
 #endif
-    int rc = RTLogCreateEx(&g_pLoggerRelease, fFlags, "all", "VBOXSERVICE_RELEASE_LOG",
+    int rc = RTLogCreateEx(&g_pLoggerRelease, "VBOXSERVICE_RELEASE_LOG", fFlags, "all",
                            RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/,
-                           RTLOGDEST_STDOUT | RTLOGDEST_USER,
+                           NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT | RTLOGDEST_USER,
                            vgsvcLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
                            NULL /*pErrInfo*/, "%s", pszLogFile ? pszLogFile : "");
Index: /trunk/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp
===================================================================
--- /trunk/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp	(revision 90828)
+++ /trunk/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp	(revision 90829)
@@ -59,7 +59,7 @@
 {
     static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
-    int rc = RTLogCreateEx(&g_pLogger, RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG, "all", "VBOXCLIENT_RELEASE_LOG",
+    int rc = RTLogCreateEx(&g_pLogger, "VBOXCLIENT_RELEASE_LOG", RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG, "all",
                            RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/,
-                           RTLOGDEST_STDOUT,
+                           NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT,
                            NULL /*pfnPhase*/,
                            pszLogFileName ? 10 : 0 /*cHistory*/,
@@ -67,5 +67,4 @@
                            pszLogFileName ? RT_SEC_1DAY : 0 /*cSecsHistoryTimeSlot*/,
                            NULL /*pErrInfo*/, "%s", pszLogFileName ? pszLogFileName : "");
-
     AssertRCReturn(rc, rc);
 
Index: /trunk/src/VBox/Additions/linux/lightdm-greeter/vbox-greeter.cpp
===================================================================
--- /trunk/src/VBox/Additions/linux/lightdm-greeter/vbox-greeter.cpp	(revision 90828)
+++ /trunk/src/VBox/Additions/linux/lightdm-greeter/vbox-greeter.cpp	(revision 90829)
@@ -935,6 +935,7 @@
     fFlags |= RTLOGFLAGS_USECRLF;
 #endif
-    int rc = RTLogCreateEx(&g_pLoggerRelease, fFlags, "all", "VBOXGREETER_RELEASE_LOG",
-                           RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/, RTLOGDEST_STDOUT,
+    int rc = RTLogCreateEx(&g_pLoggerRelease, "VBOXGREETER_RELEASE_LOG", fFlags, "all",
+                           RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/,
+                           NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT,
                            vboxGreeterLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
                            NULL /*pErrInfo*/, pszLogFile);
Index: /trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp	(revision 90828)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp	(revision 90829)
@@ -263,7 +263,7 @@
     fFlags |= RTLOGFLAGS_USECRLF;
 #endif
-    int rc = RTLogCreateEx(&g_pLoggerRelease, fFlags, "all", "VBOXCLIENT_RELEASE_LOG",
+    int rc = RTLogCreateEx(&g_pLoggerRelease, "VBOXCLIENT_RELEASE_LOG", fFlags, "all",
                            RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/,
-                           RTLOGDEST_STDOUT | RTLOGDEST_USER,
+                           NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT | RTLOGDEST_USER,
                            vbClLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
                            NULL /*pErrInfo*/, "%s", pszLogFile ? pszLogFile : "");
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 90829)
@@ -284,4 +284,8 @@
     { "RTHandleTableFreeWithCtx",               (void *)(uintptr_t)RTHandleTableFreeWithCtx },
     { "RTHandleTableLookupWithCtx",             (void *)(uintptr_t)RTHandleTableLookupWithCtx },
+    { "RTLogBulkUpdate",                        (void *)(uintptr_t)RTLogBulkUpdate},
+    { "RTLogCheckGroupFlags",                   (void *)(uintptr_t)RTLogCheckGroupFlags },
+    { "RTLogCreateEx",                          (void *)(uintptr_t)RTLogCreateEx },
+    { "RTLogDestroy",                           (void *)(uintptr_t)RTLogDestroy },
     { "RTLogDefaultInstance",                   (void *)(uintptr_t)RTLogDefaultInstance },
     { "RTLogDefaultInstanceEx",                 (void *)(uintptr_t)RTLogDefaultInstanceEx },
@@ -295,4 +299,5 @@
     { "SUPR0GetDefaultLogRelInstanceEx",        (void *)(uintptr_t)SUPR0GetDefaultLogRelInstanceEx },
     { "RTLogSetDefaultInstanceThread",          (void *)(uintptr_t)RTLogSetDefaultInstanceThread },
+    { "RTLogSetR0ThreadNameF",                  (void *)(uintptr_t)RTLogSetR0ThreadNameF },
     { "RTMemAllocExTag",                        (void *)(uintptr_t)RTMemAllocExTag },
     { "RTMemAllocTag",                          (void *)(uintptr_t)RTMemAllocTag },
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 90829)
@@ -223,5 +223,5 @@
  *          - Remove pvVMMR0 from SUPLDRLOAD.
  */
-#define SUPDRV_IOC_VERSION                              0x00300003
+#define SUPDRV_IOC_VERSION                              0x00300004
 
 /** SUP_IOCTL_COOKIE. */
Index: /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 90829)
@@ -279,5 +279,5 @@
         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
         const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00300000
-                                   ? 0x00300003
+                                   ? 0x00300004
                                    : SUPDRV_IOC_VERSION & 0xffff0000;
         CookieReq.u.In.u32MinVersion = uMinVersion;
Index: /trunk/src/VBox/HostDrivers/Support/freebsd/Makefile
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/freebsd/Makefile	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/freebsd/Makefile	(revision 90829)
@@ -101,4 +101,5 @@
 	strformattype.c \
 	strprintf.c \
+	strprintf2.c \
 	strtonum.c \
 	memchr.c \
Index: /trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv	(revision 90829)
@@ -135,4 +135,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strformattype.cpp=>common/string/strformattype.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf.cpp=>common/string/strprintf.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf2.cpp=>common/string/strprintf2.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strtonum.cpp=>common/string/strtonum.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/memchr.cpp=>common/string/memchr.c \
Index: /trunk/src/VBox/HostDrivers/Support/linux/Makefile
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 90829)
@@ -108,4 +108,5 @@
 	common/string/strformattype.o \
 	common/string/strprintf.o \
+	common/string/strprintf2.o \
 	common/string/strtonum.o \
 	common/table/avlpv.o \
Index: /trunk/src/VBox/HostDrivers/Support/linux/combined-agnostic2.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/combined-agnostic2.c	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/linux/combined-agnostic2.c	(revision 90829)
@@ -54,4 +54,6 @@
 #include "common/string/strprintf.c"
 #undef LOG_GROUP
+#include "common/string/strprintf2.c"
+#undef LOG_GROUP
 #include "common/string/strtonum.c"
 #undef LOG_GROUP
Index: /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 90828)
+++ /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 90829)
@@ -147,4 +147,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strformattype.cpp=>common/string/strformattype.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf.cpp=>common/string/strprintf.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf2.cpp=>common/string/strprintf2.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/strtonum.cpp=>common/string/strtonum.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/table/avlpv.cpp=>common/table/avlpv.c \
Index: /trunk/src/VBox/Main/glue/VBoxLogRelCreate.cpp
===================================================================
--- /trunk/src/VBox/Main/glue/VBoxLogRelCreate.cpp	(revision 90828)
+++ /trunk/src/VBox/Main/glue/VBoxLogRelCreate.cpp	(revision 90829)
@@ -169,6 +169,6 @@
 #endif
     g_pszLogEntity = pcszEntity;
-    int vrc = RTLogCreateEx(&pReleaseLogger, fFlags, pcszGroupSettings, pcszEnvVarBase,
-                            RT_ELEMENTS(s_apszGroups), s_apszGroups, cMaxEntriesPerGroup, fDestFlags,
+    int vrc = RTLogCreateEx(&pReleaseLogger, pcszEnvVarBase, fFlags, pcszGroupSettings, RT_ELEMENTS(s_apszGroups), s_apszGroups,
+                            cMaxEntriesPerGroup,  NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, fDestFlags,
                             vboxHeaderFooter, cHistory, uHistoryFileSize, uHistoryFileTime,
                             pErrInfo, pcszLogFile ? "%s" : NULL, pcszLogFile);
Index: /trunk/src/VBox/Main/src-helper-apps/OpenGLTest/OpenGLTestApp.cpp
===================================================================
--- /trunk/src/VBox/Main/src-helper-apps/OpenGLTest/OpenGLTestApp.cpp	(revision 90828)
+++ /trunk/src/VBox/Main/src-helper-apps/OpenGLTest/OpenGLTestApp.cpp	(revision 90829)
@@ -296,8 +296,9 @@
     }
 
-    int vrc = RTLogCreateEx(&loggerRelease, fFlags, "all",
-                            "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX, enmLogDest,
-                            NULL /* pfnBeginEnd */, 0 /* cHistory */, 0 /* cbHistoryFileMax */, 0 /* uHistoryTimeMax */,
-                            NULL /* pErrInfo */, pszFilenameFmt, pszFilename, RTTimeMilliTS());
+
+    int vrc = RTLogCreateEx(&loggerRelease, "VBOX_RELEASE_LOG", fFlags, "all", RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX,
+                            NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, enmLogDest,
+                            NULL /*pfnBeginEnd*/, 0 /*cHistory*/, 0 /*cbHistoryFileMax*/, 0 /*uHistoryTimeMax*/,
+                            NULL /*pErrInfo*/, pszFilenameFmt, pszFilename, RTTimeMilliTS());
     if (RT_SUCCESS(vrc))
     {
Index: /trunk/src/VBox/Runtime/VBox/VBoxRTImp.def
===================================================================
--- /trunk/src/VBox/Runtime/VBox/VBoxRTImp.def	(revision 90828)
+++ /trunk/src/VBox/Runtime/VBox/VBoxRTImp.def	(revision 90829)
@@ -1257,12 +1257,10 @@
     RTLockValidatorWriteLockGetCount
     RTLockValidatorWriteLockInc
-    RTLogCloneRC
     RTLogComPrintf
     RTLogComPrintfV
-    RTLogCopyGroupsAndFlagsForR0
+    ;RTLogCopyGroupsAndFlagsForR0
     RTLogCreate
     RTLogCreateEx
     RTLogCreateExV
-    RTLogCreateForR0
     RTLogDefaultInit
     RTLogDefaultInstance
@@ -1272,6 +1270,5 @@
     RTLogFlags
     RTLogFlush
-    RTLogFlushRC
-    RTLogFlushToLogger
+    ;RTLogFlushToLogger
     RTLogFormatV
     RTLogGetDefaultInstance
Index: /trunk/src/VBox/Runtime/VBox/log-vbox.cpp
===================================================================
--- /trunk/src/VBox/Runtime/VBox/log-vbox.cpp	(revision 90828)
+++ /trunk/src/VBox/Runtime/VBox/log-vbox.cpp	(revision 90829)
@@ -668,7 +668,6 @@
         /*RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");*/
         RTLogFlags(pLogger, "enabled unbuffered pid tid");
-#  ifndef IN_GUEST
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
-#  else
+        RTLogDestinations(pLogger, "debugger stdout");
+#  ifdef IN_GUEST
         /*RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");*/
         RTLogGroupSettings(pLogger, "all=~0");
@@ -678,34 +677,34 @@
         RTLogGroupSettings(pLogger, "+all");
         RTLogFlags(pLogger, "enabled unbuffered");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+        RTLogDestinations(pLogger, "debugger");
 # endif
 # if defined(DEBUG_ramshankar)  /* Guest ring-0 as well */
         RTLogGroupSettings(pLogger, "+all.e.l.f");
         RTLogFlags(pLogger, "enabled unbuffered");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+        RTLogDestinations(pLogger, "debugger");
 # endif
 # if defined(DEBUG_aleksey)  /* Guest ring-0 as well */
         RTLogGroupSettings(pLogger, "net_flt_drv.e.l.f.l3.l4.l5.l6 +net_adp_drv.e.l.f.l3.l4.l5.l6");
         RTLogFlags(pLogger, "enabled unbuffered");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+        RTLogDestinations(pLogger, "debugger stdout");
 # endif
 # if defined(DEBUG_andy)  /* Guest ring-0 as well */
         RTLogGroupSettings(pLogger, "+all.e.l.f");
         RTLogFlags(pLogger, "enabled unbuffered pid tid");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+        RTLogDestinations(pLogger, "debugger stdout");
 # endif
 # if defined(DEBUG_misha) /* Guest ring-0 as well */
         RTLogFlags(pLogger, "enabled unbuffered");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+        RTLogDestinations(pLogger, "debugger");
 # endif
 # if defined(DEBUG_michael) && defined(IN_GUEST)
         RTLogGroupSettings(pLogger, "+vga.e.l.f");
         RTLogFlags(pLogger, "enabled unbuffered");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+        RTLogDestinations(pLogger, "debugger stdout");
 # endif
 # if 0 /* vboxdrv logging - ATTENTION: this is what we're referring to guys! Change to '# if 1'. */
         RTLogGroupSettings(pLogger, "all=~0 -default.l6.l5.l4.l3");
         RTLogFlags(pLogger, "enabled unbuffered tid");
-        pLogger->fDestFlags |= RTLOGDEST_DEBUGGER | RTLOGDEST_STDOUT;
+        RTLogDestinations(pLogger, "debugger stdout");
 # endif
     }
Index: /trunk/src/VBox/Runtime/common/log/log.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/log/log.cpp	(revision 90828)
+++ /trunk/src/VBox/Runtime/common/log/log.cpp	(revision 90829)
@@ -34,4 +34,5 @@
 #ifndef IN_RC
 # include <iprt/alloc.h>
+# include <iprt/crc.h>
 # include <iprt/process.h>
 # include <iprt/semaphore.h>
@@ -89,4 +90,9 @@
 AssertCompile(sizeof(RTLOG_RINGBUF_EYE_CATCHER_END) == 16);
 
+/** The default buffer size. */
+#define RTLOG_BUFFER_DEFAULT_SIZE       _64K
+/** Buffer alignment used RTLogCreateExV.   */
+#define RTLOG_BUFFER_ALIGN              64
+
 
 /*********************************************************************************************************************************
@@ -94,19 +100,4 @@
 *********************************************************************************************************************************/
 /**
- * Arguments passed to the output function.
- */
-typedef struct RTLOGOUTPUTPREFIXEDARGS
-{
-    /** The logger instance. */
-    PRTLOGGER               pLogger;
-    /** The flags. (used for prefixing.) */
-    unsigned                fFlags;
-    /** The group. (used for prefixing.) */
-    unsigned                iGroup;
-} RTLOGOUTPUTPREFIXEDARGS, *PRTLOGOUTPUTPREFIXEDARGS;
-
-#ifndef IN_RC
-
-/**
  * Internal logger data.
  *
@@ -115,8 +106,25 @@
 typedef struct RTLOGGERINTERNAL
 {
+    /** The public logger core. */
+    RTLOGGER                Core;
+
     /** The structure revision (RTLOGGERINTERNAL_REV). */
     uint32_t                uRevision;
     /** The size of the internal logger structure. */
     uint32_t                cbSelf;
+
+    /** Logger instance flags - RTLOGFLAGS. */
+    uint64_t                fFlags;
+    /** Destination flags - RTLOGDEST. */
+    uint32_t                fDestFlags;
+
+    /** Number of buffer descriptors. */
+    uint8_t                 cBufDescs;
+    /** Index of the current buffer descriptor. */
+    uint8_t                 idxBufDesc;
+    /** Pointer to buffer the descriptors. */
+    PRTLOGBUFFERDESC        paBufDescs;
+    /** Pointer to the current buffer the descriptor. */
+    PRTLOGBUFFERDESC        pBufDesc;
 
     /** Spinning mutex semaphore.  Can be NIL. */
@@ -181,5 +189,5 @@
     char                    szR0ThreadName[16];
 
-# ifdef IN_RING3 /* Note! Must be at the end! */
+#ifdef IN_RING3 /* Note! Must be at the end! */ /** @todo r=bird: figure out why it must be at the end... */
     /** @name File logging bits for the logger.
      * @{ */
@@ -205,19 +213,41 @@
     char                    szFilename[RTPATH_MAX];
     /** @} */
-# endif /* IN_RING3 */
+#endif /* IN_RING3 */
+
+    /** Number of groups in the afGroups and papszGroups members. */
+    uint32_t                cGroups;
+    /** Group flags array - RTLOGGRPFLAGS.
+     * This member have variable length and may extend way beyond
+     * the declared size of 1 entry. */
+    RT_FLEXIBLE_ARRAY_EXTENSION
+    uint32_t                afGroups[RT_FLEXIBLE_ARRAY];
 } RTLOGGERINTERNAL;
 
 /** The revision of the internal logger structure. */
-# define RTLOGGERINTERNAL_REV    UINT32_C(11)
-
-# ifdef IN_RING3
+# define RTLOGGERINTERNAL_REV    UINT32_C(12)
+
+AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbRingBufUnflushed, sizeof(uint64_t));
+#ifdef IN_RING3
 /** The size of the RTLOGGERINTERNAL structure in ring-0.  */
-#  define RTLOGGERINTERNAL_R0_SIZE       RT_UOFFSETOF(RTLOGGERINTERNAL, pfnPhase)
+# define RTLOGGERINTERNAL_R0_SIZE       RT_UOFFSETOF(RTLOGGERINTERNAL, pfnPhase)
 AssertCompileMemberAlignment(RTLOGGERINTERNAL, hFile, sizeof(void *));
 AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbHistoryFileMax, sizeof(uint64_t));
-# endif
-AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbRingBufUnflushed, sizeof(uint64_t));
-
-#endif /* !IN_RC */
+#endif
+
+
+/** Pointer to internal logger bits. */
+typedef struct RTLOGGERINTERNAL *PRTLOGGERINTERNAL;
+/**
+ * Arguments passed to the output function.
+ */
+typedef struct RTLOGOUTPUTPREFIXEDARGS
+{
+    /** The logger instance. */
+    PRTLOGGERINTERNAL       pLoggerInt;
+    /** The flags. (used for prefixing.) */
+    unsigned                fFlags;
+    /** The group. (used for prefixing.) */
+    unsigned                iGroup;
+} RTLOGOUTPUTPREFIXEDARGS, *PRTLOGOUTPUTPREFIXEDARGS;
 
 
@@ -233,15 +263,15 @@
 #endif
 #ifdef IN_RING3
-static int  rtR3LogOpenFileDestination(PRTLOGGER pLogger, PRTERRINFO pErrInfo);
+static int  rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo);
 #endif
 #ifndef IN_RC
-static void rtLogRingBufFlush(PRTLOGGER pLogger);
+static void rtLogRingBufFlush(PRTLOGGERINTERNAL pLoggerInt);
 #endif
-static void rtlogFlush(PRTLOGGER pLogger, bool fNeedSpace);
+static void rtlogFlush(PRTLOGGERINTERNAL pLoggerInt, bool fNeedSpace);
 static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars);
-static DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars);
-static void rtlogLoggerExVLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args);
+static void rtlogLoggerExVLocked(PRTLOGGERINTERNAL pLoggerInt, unsigned fFlags, unsigned iGroup,
+                                 const char *pszFormat, va_list args);
 #ifndef IN_RC
-static void rtlogLoggerExFLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...);
+static void rtlogLoggerExFLocked(PRTLOGGERINTERNAL pLoggerInt, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...);
 #endif
 
@@ -250,5 +280,10 @@
 *   Global Variables                                                                                                             *
 *********************************************************************************************************************************/
-#ifdef IN_RC
+#ifndef IN_RC
+/** Default logger instance. */
+static PRTLOGGER                    g_pLogger;
+/** Default release logger instance. */
+static PRTLOGGER                    g_pRelLogger;
+#else
 /** Default logger instance. Make it weak because our RC module loader does not
  *  necessarily resolve this symbol and the compiler _must_ check if this is
@@ -256,12 +291,13 @@
  *  .weak_reference (must specify "-dynamic" to be used'') */
 # ifdef RT_OS_DARWIN
-extern "C" DECLIMPORT(RTLOGGERRC) g_Logger;
+extern "C" DECLIMPORT(RTLOGGERRC)   g_Logger;
+/** Default release logger instance. */
+extern "C" DECLIMPORT(RTLOGGERRC)   g_RelLogger;
 # else
 extern "C" DECLWEAK(DECLIMPORT(RTLOGGERRC)) g_Logger;
+/** Default release logger instance. */
+extern "C" DECLWEAK(DECLIMPORT(RTLOGGERRC)) g_RelLogger;
 # endif
-#else /* !IN_RC */
-/** Default logger instance. */
-static PRTLOGGER                    g_pLogger;
-#endif /* !IN_RC */
+#endif /* IN_RC */
 #ifdef IN_RING3
 /** The RTThreadGetWriteLockCount() change caused by the logger mutex semaphore. */
@@ -303,5 +339,5 @@
     const char *pszInstr;               /**< The name  */
     size_t      cchInstr;               /**< The size of the name. */
-    uint32_t    fFlag;                  /**< The flag value. */
+    uint64_t    fFlag;                  /**< The flag value. */
     bool        fInverted;              /**< Inverse meaning? */
     uint32_t    fFixedDest;             /**< RTLOGDEST_FIXED_XXX flags blocking this. */
@@ -381,22 +417,23 @@
  *
  * @returns See RTSemSpinMutexRequest().
- * @param   pLogger     The logger instance.
- */
-DECLINLINE(int) rtlogLock(PRTLOGGER pLogger)
+ * @param   pLoggerInt  The logger instance.
+ */
+DECLINLINE(int) rtlogLock(PRTLOGGERINTERNAL pLoggerInt)
 {
 #ifndef IN_RC
-    PRTLOGGERINTERNAL pInt = pLogger->pInt;
-    AssertMsgReturn(pInt->uRevision == RTLOGGERINTERNAL_REV, ("%#x != %#x\n", pInt->uRevision, RTLOGGERINTERNAL_REV),
+    AssertMsgReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, ("%#x != %#x\n", pLoggerInt->Core.u32Magic, RTLOGGER_MAGIC),
+                    VERR_INVALID_MAGIC);
+    AssertMsgReturn(pLoggerInt->uRevision == RTLOGGERINTERNAL_REV, ("%#x != %#x\n", pLoggerInt->uRevision, RTLOGGERINTERNAL_REV),
                     VERR_LOG_REVISION_MISMATCH);
-    AssertMsgReturn(pInt->cbSelf == sizeof(*pInt), ("%#x != %#x\n", pInt->cbSelf, sizeof(*pInt)),
+    AssertMsgReturn(pLoggerInt->cbSelf == sizeof(*pLoggerInt), ("%#x != %#x\n", pLoggerInt->cbSelf, sizeof(*pLoggerInt)),
                     VERR_LOG_REVISION_MISMATCH);
-    if (pInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
-    {
-        int rc = RTSemSpinMutexRequest(pInt->hSpinMtx);
+    if (pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
+    {
+        int rc = RTSemSpinMutexRequest(pLoggerInt->hSpinMtx);
         if (RT_FAILURE(rc))
             return rc;
     }
 #else
-    NOREF(pLogger);
+    NOREF(pLoggerInt);
 #endif
     return VINF_SUCCESS;
@@ -406,13 +443,13 @@
 /**
  * Unlocks the logger instance.
- * @param   pLogger     The logger instance.
- */
-DECLINLINE(void) rtlogUnlock(PRTLOGGER pLogger)
+ * @param   pLoggerInt  The logger instance.
+ */
+DECLINLINE(void) rtlogUnlock(PRTLOGGERINTERNAL pLoggerInt)
 {
 #ifndef IN_RC
-    if (pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
-        RTSemSpinMutexRelease(pLogger->pInt->hSpinMtx);
+    if (pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
+        RTSemSpinMutexRelease(pLoggerInt->hSpinMtx);
 #else
-    NOREF(pLogger);
+    NOREF(pLoggerInt);
 #endif
     return;
@@ -432,6 +469,6 @@
 static DECLCALLBACK(size_t) rtlogPhaseWrite(void *pvArg, const char *pachChars, size_t cbChars)
 {
-    PRTLOGGER pLogger = (PRTLOGGER)pvArg;
-    RTFileWrite(pLogger->pInt->hFile, pachChars, cbChars, NULL);
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pvArg;
+    RTFileWrite(pLoggerInt->hFile, pachChars, cbChars, NULL);
     return cbChars;
 }
@@ -477,11 +514,11 @@
 static DECLCALLBACK(void) rtlogPhaseMsgLocked(PRTLOGGER pLogger, const char *pszFormat, ...)
 {
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    AssertPtrReturnVoid(pLoggerInt);
+    Assert(pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
+
     va_list args;
-    AssertPtrReturnVoid(pLogger);
-    AssertPtrReturnVoid(pLogger->pInt);
-    Assert(pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
-
     va_start(args, pszFormat);
-    rtlogLoggerExVLocked(pLogger, 0, ~0U, pszFormat, args);
+    rtlogLoggerExVLocked(pLoggerInt, 0, ~0U, pszFormat, args);
     va_end(args);
 }
@@ -497,11 +534,11 @@
 static DECLCALLBACK(void) rtlogPhaseMsgNormal(PRTLOGGER pLogger, const char *pszFormat, ...)
 {
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    AssertPtrReturnVoid(pLoggerInt);
+    Assert(pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
+
     va_list args;
-    AssertPtrReturnVoid(pLogger);
-    AssertPtrReturnVoid(pLogger->pInt);
-    Assert(pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
-
     va_start(args, pszFormat);
-    RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
+    RTLogLoggerExV(&pLoggerInt->Core, 0, ~0U, pszFormat, args);
     va_end(args);
 }
@@ -513,15 +550,15 @@
  *
  * @returns IPRT status code.
- * @param   pLogger     The logger instance.
+ * @param   pLoggerInt  The logger instance.
  * @param   cbNewSize   The new ring buffer size (0 == default).
  * @param   fForce      Whether to do this even if the logger instance hasn't
  *                      really been fully created yet (i.e. during RTLogCreate).
  */
-static int rtLogRingBufAdjust(PRTLOGGER pLogger, uint32_t cbNewSize, bool fForce)
+static int rtLogRingBufAdjust(PRTLOGGERINTERNAL pLoggerInt, uint32_t cbNewSize, bool fForce)
 {
     /*
      * If this is early logger init, don't do anything.
      */
-    if (!pLogger->pInt->fCreated && !fForce)
+    if (!pLoggerInt->fCreated && !fForce)
         return VINF_SUCCESS;
 
@@ -529,27 +566,27 @@
      * Lock the logger and make the necessary changes.
      */
-    int rc = rtlogLock(pLogger);
+    int rc = rtlogLock(pLoggerInt);
     if (RT_SUCCESS(rc))
     {
         if (cbNewSize == 0)
             cbNewSize = RTLOG_RINGBUF_DEFAULT_SIZE;
-        if (   pLogger->pInt->cbRingBuf != cbNewSize
-            || !pLogger->pInt->pchRingBufCur)
-        {
-            uintptr_t offOld = pLogger->pInt->pchRingBufCur - pLogger->pInt->pszRingBuf;
+        if (   pLoggerInt->cbRingBuf != cbNewSize
+            || !pLoggerInt->pchRingBufCur)
+        {
+            uintptr_t offOld = pLoggerInt->pchRingBufCur - pLoggerInt->pszRingBuf;
             if (offOld < sizeof(RTLOG_RINGBUF_EYE_CATCHER))
                 offOld = sizeof(RTLOG_RINGBUF_EYE_CATCHER);
             else if (offOld >= cbNewSize)
             {
-                memmove(pLogger->pInt->pszRingBuf, &pLogger->pInt->pszRingBuf[offOld - cbNewSize], cbNewSize);
+                memmove(pLoggerInt->pszRingBuf, &pLoggerInt->pszRingBuf[offOld - cbNewSize], cbNewSize);
                 offOld = sizeof(RTLOG_RINGBUF_EYE_CATCHER);
             }
 
-            void *pvNew = RTMemRealloc(pLogger->pInt->pchRingBufCur, cbNewSize);
+            void *pvNew = RTMemRealloc(pLoggerInt->pchRingBufCur, cbNewSize);
             if (pvNew)
             {
-                pLogger->pInt->pszRingBuf    = (char *)pvNew;
-                pLogger->pInt->pchRingBufCur = (char *)pvNew + offOld;
-                pLogger->pInt->cbRingBuf     = cbNewSize;
+                pLoggerInt->pszRingBuf    = (char *)pvNew;
+                pLoggerInt->pchRingBufCur = (char *)pvNew + offOld;
+                pLoggerInt->cbRingBuf     = cbNewSize;
                 memcpy(pvNew, RTLOG_RINGBUF_EYE_CATCHER, sizeof(RTLOG_RINGBUF_EYE_CATCHER));
                 memcpy((char *)pvNew + cbNewSize - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END),
@@ -560,5 +597,5 @@
                 rc = VERR_NO_MEMORY;
         }
-        rtlogUnlock(pLogger);
+        rtlogUnlock(pLoggerInt);
     }
 
@@ -642,7 +679,7 @@
  * Flushes the ring buffer to all the other log destinations.
  *
- * @param   pLogger     The logger instance which ring buffer should be flushed.
- */
-static void rtLogRingBufFlush(PRTLOGGER pLogger)
+ * @param   pLoggerInt  The logger instance which ring buffer should be flushed.
+ */
+static void rtLogRingBufFlush(PRTLOGGERINTERNAL pLoggerInt)
 {
     const char  *pszPreamble;
@@ -657,8 +694,8 @@
      * part of the buffer.
      */
-    uint64_t     cchUnflushed = pLogger->pInt->cbRingBufUnflushed;
-    char * const pszBuf   = &pLogger->pInt->pszRingBuf[sizeof(RTLOG_RINGBUF_EYE_CATCHER)];
-    size_t const cchBuf   = pLogger->pInt->cbRingBuf - sizeof(RTLOG_RINGBUF_EYE_CATCHER) - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END);
-    size_t       offCur   = pLogger->pInt->pchRingBufCur - pszBuf;
+    uint64_t     cchUnflushed = pLoggerInt->cbRingBufUnflushed;
+    char * const pszBuf   = &pLoggerInt->pszRingBuf[sizeof(RTLOG_RINGBUF_EYE_CATCHER)];
+    size_t const cchBuf   = pLoggerInt->cbRingBuf - sizeof(RTLOG_RINGBUF_EYE_CATCHER) - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END);
+    size_t       offCur   = pLoggerInt->pchRingBufCur - pszBuf;
     size_t       cchAfter;
     if (RT_LIKELY(offCur < cchBuf))
@@ -670,5 +707,5 @@
     }
 
-    pLogger->pInt->cbRingBufUnflushed = 0;
+    pLoggerInt->cbRingBufUnflushed = 0;
 
     /*
@@ -711,5 +748,5 @@
      * Write the ring buffer to all other destiations.
      */
-    if (pLogger->fDestFlags & RTLOGDEST_USER)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_USER)
     {
         if (cchPreamble)
@@ -721,5 +758,5 @@
     }
 
-    if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_DEBUGGER)
     {
         if (cchPreamble)
@@ -732,23 +769,23 @@
 
 # ifdef IN_RING3
-    if (pLogger->fDestFlags & RTLOGDEST_FILE)
-    {
-        if (pLogger->pInt->hFile != NIL_RTFILE)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_FILE)
+    {
+        if (pLoggerInt->hFile != NIL_RTFILE)
         {
             if (cchPreamble)
-                RTFileWrite(pLogger->pInt->hFile, pszPreamble, cchPreamble, NULL);
+                RTFileWrite(pLoggerInt->hFile, pszPreamble, cchPreamble, NULL);
             if (cchFirst)
-                RTFileWrite(pLogger->pInt->hFile, pszFirst, cchFirst, NULL);
+                RTFileWrite(pLoggerInt->hFile, pszFirst, cchFirst, NULL);
             if (cchSecond)
-                RTFileWrite(pLogger->pInt->hFile, pszSecond, cchSecond, NULL);
-            if (pLogger->fFlags & RTLOGFLAGS_FLUSH)
-                RTFileFlush(pLogger->pInt->hFile);
-        }
-        if (pLogger->pInt->cHistory)
-            pLogger->pInt->cbHistoryFileWritten += cchFirst + cchSecond;
+                RTFileWrite(pLoggerInt->hFile, pszSecond, cchSecond, NULL);
+            if (pLoggerInt->fFlags & RTLOGFLAGS_FLUSH)
+                RTFileFlush(pLoggerInt->hFile);
+        }
+        if (pLoggerInt->cHistory)
+            pLoggerInt->cbHistoryFileWritten += cchFirst + cchSecond;
     }
 # endif
 
-    if (pLogger->fDestFlags & RTLOGDEST_STDOUT)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_STDOUT)
     {
         if (cchPreamble)
@@ -760,5 +797,5 @@
     }
 
-    if (pLogger->fDestFlags & RTLOGDEST_STDERR)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_STDERR)
     {
         if (cchPreamble)
@@ -771,5 +808,5 @@
 
 # if defined(IN_RING0) && !defined(LOG_NO_COM)
-    if (pLogger->fDestFlags & RTLOGDEST_COM)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_COM)
     {
         if (cchPreamble)
@@ -784,81 +821,165 @@
 
 
-RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, const char *pszEnvVarBase,
-                           unsigned cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
-                           uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
-                           uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
+                           uint32_t cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
+                           PFNRTLOGFLUSH pfnFlush, uint32_t cBufDescs, PRTLOGBUFFERDESC paBufDescs, uint32_t fDestFlags,
+                           PFNRTLOGPHASE pfnPhase, uint32_t cHistory, uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
                            PRTERRINFO pErrInfo, const char *pszFilenameFmt, va_list args)
 {
-    int         rc;
-    size_t      offInternal;
-    size_t      cbLogger;
-    PRTLOGGER   pLogger;
+    int                 rc;
+    size_t              cbLogger;
+    size_t              offBuffers;
+    PRTLOGGERINTERNAL   pLoggerInt;
+    uint32_t            i;
 
     /*
      * Validate input.
      */
-    if (   (cGroups && !papszGroups)
-        || !RT_VALID_PTR(ppLogger) )
-    {
-        AssertMsgFailed(("Invalid parameters!\n"));
-        return VERR_INVALID_PARAMETER;
-    }
+    AssertPtrReturn(ppLogger, VERR_INVALID_POINTER);
     *ppLogger = NULL;
-
+    if (cGroups)
+    {
+        AssertPtrReturn(papszGroups, VERR_INVALID_POINTER);
+        AssertReturn(cGroups < _8K, VERR_OUT_OF_RANGE);
+    }
     AssertMsgReturn(cHistory < _1M, ("%#x", cHistory), VERR_OUT_OF_RANGE);
-
-    /*
-     * Allocate a logger instance.
-     */
-    offInternal = RT_UOFFSETOF_DYN(RTLOGGER, afGroups[cGroups]);
-    offInternal = RT_ALIGN_Z(offInternal, sizeof(uint64_t));
-    cbLogger = offInternal + sizeof(RTLOGGERINTERNAL);
+    AssertReturn(cBufDescs <= 128, VERR_OUT_OF_RANGE);
+
+    /*
+     * Calculate the logger size.
+     */
+    AssertCompileSize(RTLOGGER, 32);
+    cbLogger = RT_UOFFSETOF_DYN(RTLOGGERINTERNAL, afGroups[cGroups]);
     if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
         cbLogger += cGroups * sizeof(uint32_t);
-    pLogger = (PRTLOGGER)RTMemAllocZVarTag(cbLogger, "may-leak:log-instance");
-    if (pLogger)
+    if (cBufDescs == 0)
+    {
+        /* Allocate one buffer descriptor and a default sized buffer. */
+        cbLogger   = RT_ALIGN_Z(cbLogger, RTLOG_BUFFER_ALIGN);
+        offBuffers = cbLogger;
+        cbLogger  += RT_ALIGN_Z(sizeof(paBufDescs[0]), RTLOG_BUFFER_ALIGN) + RTLOG_BUFFER_DEFAULT_SIZE;
+    }
+    else
+    {
+        /* Caller-supplied buffer descriptors.  If pchBuf is NULL, we have to allocate the buffers. */
+        AssertPtrReturn(paBufDescs, VERR_INVALID_POINTER);
+        if (paBufDescs[0].pchBuf != NULL)
+            offBuffers = 0;
+        else
+        {
+            cbLogger = RT_ALIGN_Z(cbLogger, RTLOG_BUFFER_ALIGN);
+            offBuffers = cbLogger;
+        }
+
+        for (i = 0; i < cBufDescs; i++)
+        {
+            AssertReturn(paBufDescs[i].u32Magic == RTLOGBUFFERDESC_MAGIC, VERR_INVALID_MAGIC);
+            AssertReturn(paBufDescs[i].uReserved == 0, VERR_INVALID_PARAMETER);
+            AssertMsgReturn(paBufDescs[i].cbBuf >= _1K && paBufDescs[i].cbBuf <= _64M,
+                            ("paBufDesc[%u].cbBuf=%#x\n", i, paBufDescs[i].cbBuf), VERR_OUT_OF_RANGE);
+            AssertReturn(paBufDescs[i].offBuf == 0, VERR_INVALID_PARAMETER);
+            if (offBuffers != 0)
+            {
+                cbLogger += RT_ALIGN_Z(paBufDescs[i].cbBuf, RTLOG_BUFFER_ALIGN);
+                AssertReturn(paBufDescs[i].pchBuf == NULL, VERR_INVALID_PARAMETER);
+                AssertReturn(paBufDescs[i].pAux == NULL, VERR_INVALID_PARAMETER);
+            }
+            else
+            {
+                AssertPtrReturn(paBufDescs[i].pchBuf, VERR_INVALID_POINTER);
+                AssertPtrNullReturn(paBufDescs[i].pAux, VERR_INVALID_POINTER);
+            }
+        }
+    }
+
+    /*
+     * Allocate a logger instance.
+     */
+    pLoggerInt = (PRTLOGGERINTERNAL)RTMemAllocZVarTag(cbLogger, "may-leak:log-instance");
+    if (pLoggerInt)
     {
 # if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
         uint8_t *pu8Code;
 # endif
-        pLogger->u32Magic       = RTLOGGER_MAGIC;
-        pLogger->cGroups        = cGroups;
-        pLogger->fFlags         = fFlags;
-        pLogger->fDestFlags     = fDestFlags;
-        pLogger->pInt           = (PRTLOGGERINTERNAL)((uintptr_t)pLogger + offInternal);
-        pLogger->pInt->uRevision                = RTLOGGERINTERNAL_REV;
-        pLogger->pInt->cbSelf                   = sizeof(RTLOGGERINTERNAL);
-        pLogger->pInt->hSpinMtx                 = NIL_RTSEMSPINMUTEX;
-        pLogger->pInt->pfnFlush                 = NULL;
-        pLogger->pInt->pfnPrefix                = NULL;
-        pLogger->pInt->pvPrefixUserArg          = NULL;
-        pLogger->pInt->fPendingPrefix           = true;
-        pLogger->pInt->fCreated                 = false;
-        pLogger->pInt->nsR0ProgramStart         = 0;
-        RT_ZERO(pLogger->pInt->szR0ThreadName);
-        pLogger->pInt->cMaxGroups               = cGroups;
-        pLogger->pInt->papszGroups              = papszGroups;
+        pLoggerInt->Core.u32Magic               = RTLOGGER_MAGIC;
+        pLoggerInt->cGroups                     = cGroups;
+        pLoggerInt->fFlags                      = fFlags;
+        pLoggerInt->fDestFlags                  = fDestFlags;
+        pLoggerInt->uRevision                   = RTLOGGERINTERNAL_REV;
+        pLoggerInt->cbSelf                      = sizeof(RTLOGGERINTERNAL);
+        pLoggerInt->hSpinMtx                    = NIL_RTSEMSPINMUTEX;
+        pLoggerInt->pfnFlush                    = pfnFlush;
+        pLoggerInt->pfnPrefix                   = NULL;
+        pLoggerInt->pvPrefixUserArg             = NULL;
+        pLoggerInt->fPendingPrefix              = true;
+        pLoggerInt->fCreated                    = false;
+        pLoggerInt->nsR0ProgramStart            = 0;
+        RT_ZERO(pLoggerInt->szR0ThreadName);
+        pLoggerInt->cMaxGroups                  = cGroups;
+        pLoggerInt->papszGroups                 = papszGroups;
         if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
-            pLogger->pInt->pacEntriesPerGroup   = (uint32_t *)(pLogger->pInt + 1);
+            pLoggerInt->pacEntriesPerGroup      = (uint32_t *)(pLoggerInt + 1);
         else
-            pLogger->pInt->pacEntriesPerGroup   = NULL;
-        pLogger->pInt->cMaxEntriesPerGroup      = cMaxEntriesPerGroup ? cMaxEntriesPerGroup : UINT32_MAX;
+            pLoggerInt->pacEntriesPerGroup      = NULL;
+        pLoggerInt->cMaxEntriesPerGroup         = cMaxEntriesPerGroup ? cMaxEntriesPerGroup : UINT32_MAX;
 # ifdef IN_RING3
-        pLogger->pInt->pfnPhase                 = pfnPhase;
-        pLogger->pInt->hFile                    = NIL_RTFILE;
-        pLogger->pInt->cHistory                 = cHistory;
+        pLoggerInt->pfnPhase                    = pfnPhase;
+        pLoggerInt->hFile                       = NIL_RTFILE;
+        pLoggerInt->cHistory                    = cHistory;
         if (cbHistoryFileMax == 0)
-            pLogger->pInt->cbHistoryFileMax     = UINT64_MAX;
+            pLoggerInt->cbHistoryFileMax        = UINT64_MAX;
         else
-            pLogger->pInt->cbHistoryFileMax     = cbHistoryFileMax;
+            pLoggerInt->cbHistoryFileMax        = cbHistoryFileMax;
         if (cSecsHistoryTimeSlot == 0)
-            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
+            pLoggerInt->cSecsHistoryTimeSlot    = UINT32_MAX;
         else
-            pLogger->pInt->cSecsHistoryTimeSlot = cSecsHistoryTimeSlot;
+            pLoggerInt->cSecsHistoryTimeSlot    = cSecsHistoryTimeSlot;
 # else   /* !IN_RING3 */
         RT_NOREF_PV(pfnPhase); RT_NOREF_PV(cHistory); RT_NOREF_PV(cbHistoryFileMax); RT_NOREF_PV(cSecsHistoryTimeSlot);
 # endif  /* !IN_RING3 */
         if (pszGroupSettings)
-            RTLogGroupSettings(pLogger, pszGroupSettings);
+            RTLogGroupSettings(&pLoggerInt->Core, pszGroupSettings);
+
+        /*
+         * Buffer descriptors.
+         */
+        if (!offBuffers)
+        {
+            /* Caller-supplied descriptors: */
+            pLoggerInt->cBufDescs  = cBufDescs;
+            pLoggerInt->paBufDescs = paBufDescs;
+        }
+        else if (cBufDescs)
+        {
+            /* Caller-supplied descriptors, but we allocate the actual buffers: */
+            pLoggerInt->cBufDescs  = cBufDescs;
+            pLoggerInt->paBufDescs = paBufDescs;
+            for (i = 0; i < cBufDescs; i++)
+            {
+                paBufDescs[i].pchBuf = (char *)pLoggerInt + offBuffers;
+                offBuffers = RT_ALIGN_Z(offBuffers + paBufDescs[i].cbBuf, RTLOG_BUFFER_ALIGN);
+            }
+            Assert(offBuffers == cbLogger);
+        }
+        else
+        {
+            /* One descriptor with a default sized buffer. */
+            pLoggerInt->cBufDescs  = cBufDescs  = 1;
+            pLoggerInt->paBufDescs = paBufDescs = (PRTLOGBUFFERDESC)((char *)(char *)pLoggerInt + offBuffers);
+            offBuffers = RT_ALIGN_Z(offBuffers + sizeof(paBufDescs[0]) * cBufDescs, RTLOG_BUFFER_ALIGN);
+            for (i = 0; i < cBufDescs; i++)
+            {
+                paBufDescs[i].u32Magic  = RTLOGBUFFERDESC_MAGIC;
+                paBufDescs[i].uReserved = 0;
+                paBufDescs[i].cbBuf     = RTLOG_BUFFER_DEFAULT_SIZE;
+                paBufDescs[i].offBuf    = 0;
+                paBufDescs[i].pAux      = NULL;
+                paBufDescs[i].pchBuf    = (char *)pLoggerInt + offBuffers;
+                offBuffers = RT_ALIGN_Z(offBuffers + RTLOG_BUFFER_DEFAULT_SIZE, RTLOG_BUFFER_ALIGN);
+            }
+            Assert(offBuffers == cbLogger);
+        }
+        pLoggerInt->pBufDesc   = paBufDescs;
+        pLoggerInt->idxBufDesc = 0;
 
 # if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
@@ -869,7 +990,7 @@
         if (pu8Code)
         {
-            pLogger->pfnLogger = *(PFNRTLOGGER*)&pu8Code;
+            pLoggerInt->Core.pfnLogger = *(PFNRTLOGGER *)&pu8Code;
             *pu8Code++ = 0x68;          /* push imm32 */
-            *(void **)pu8Code = pLogger;
+            *(void **)pu8Code = &pLoggerInt->Core;
             pu8Code += sizeof(void *);
             *pu8Code++ = 0xe8;          /* call rel32 */
@@ -881,6 +1002,6 @@
             *pu8Code++ = 0x04;
             *pu8Code++ = 0xc3;          /* ret near */
-            AssertMsg((uintptr_t)pu8Code - (uintptr_t)pLogger->pfnLogger <= 64,
-                      ("Wrapper assembly is too big! %d bytes\n", (uintptr_t)pu8Code - (uintptr_t)pLogger->pfnLogger));
+            AssertMsg((uintptr_t)pu8Code - (uintptr_t)pLoggerInt->Core.pfnLogger <= 64,
+                      ("Wrapper assembly is too big! %d bytes\n", (uintptr_t)pu8Code - (uintptr_t)pLoggerInt->Core.pfnLogger));
             rc = VINF_SUCCESS;
         }
@@ -889,5 +1010,5 @@
             rc = VERR_NO_MEMORY;
 #  ifdef RT_OS_LINUX
-                /* Most probably SELinux causing trouble since the larger RTMemAlloc succeeded. */
+            /* Most probably SELinux causing trouble since the larger RTMemAlloc succeeded. */
             RTErrInfoSet(pErrInfo, rc, N_("mmap(PROT_WRITE | PROT_EXEC) failed -- SELinux?"));
 #  endif
@@ -903,7 +1024,7 @@
             {
                 /** @todo validate the length, fail on overflow. */
-                RTStrPrintfV(pLogger->pInt->szFilename, sizeof(pLogger->pInt->szFilename), pszFilenameFmt, args);
-                if (pLogger->pInt->szFilename[0])
-                    pLogger->fDestFlags |= RTLOGDEST_FILE;
+                RTStrPrintfV(pLoggerInt->szFilename, sizeof(pLoggerInt->szFilename), pszFilenameFmt, args);
+                if (pLoggerInt->szFilename[0])
+                    pLoggerInt->fDestFlags |= RTLOGDEST_FILE;
             }
 
@@ -924,5 +1045,5 @@
                 const char *pszValue = RTEnvGet(pszEnvVar);
                 if (pszValue)
-                    RTLogDestinations(pLogger, pszValue);
+                    RTLogDestinations(&pLoggerInt->Core, pszValue);
 
                 /*
@@ -932,5 +1053,5 @@
                 pszValue = RTEnvGet(pszEnvVar);
                 if (pszValue)
-                    RTLogFlags(pLogger, pszValue);
+                    RTLogFlags(&pLoggerInt->Core, pszValue);
 
                 /*
@@ -940,5 +1061,5 @@
                 pszValue = RTEnvGet(pszEnvVar);
                 if (pszValue)
-                    RTLogGroupSettings(pLogger, pszValue);
+                    RTLogGroupSettings(&pLoggerInt->Core, pszValue);
 
                 /*
@@ -952,5 +1073,5 @@
                     rc = RTStrToUInt32Full(pszValue, 0, &cMax);
                     if (RT_SUCCESS(rc))
-                        pLogger->pInt->cMaxEntriesPerGroup = cMax ? cMax : UINT32_MAX;
+                        pLoggerInt->cMaxEntriesPerGroup = cMax ? cMax : UINT32_MAX;
                     else
                         AssertMsgFailed(("Invalid group limit! %s=%s\n", pszEnvVar, pszValue));
@@ -966,13 +1087,13 @@
              */
             rc = VINF_SUCCESS;
-            if ((pLogger->fDestFlags & (RTLOGDEST_F_DELAY_FILE | RTLOGDEST_FILE)) == RTLOGDEST_F_DELAY_FILE)
-                pLogger->fDestFlags &= ~RTLOGDEST_F_DELAY_FILE;
+            if ((pLoggerInt->fDestFlags & (RTLOGDEST_F_DELAY_FILE | RTLOGDEST_FILE)) == RTLOGDEST_F_DELAY_FILE)
+                pLoggerInt->fDestFlags &= ~RTLOGDEST_F_DELAY_FILE;
 # ifdef IN_RING3
-            if ((pLogger->fDestFlags & (RTLOGDEST_FILE | RTLOGDEST_F_DELAY_FILE)) == RTLOGDEST_FILE)
-                rc = rtR3LogOpenFileDestination(pLogger, pErrInfo);
+            if ((pLoggerInt->fDestFlags & (RTLOGDEST_FILE | RTLOGDEST_F_DELAY_FILE)) == RTLOGDEST_FILE)
+                rc = rtR3LogOpenFileDestination(pLoggerInt, pErrInfo);
 # endif
 
-            if ((pLogger->fDestFlags & RTLOGDEST_RINGBUF) && RT_SUCCESS(rc))
-                rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, true /*fForce*/);
+            if ((pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF) && RT_SUCCESS(rc))
+                rc = rtLogRingBufAdjust(pLoggerInt, pLoggerInt->cbRingBuf, true /*fForce*/);
 
             /*
@@ -982,5 +1103,6 @@
             if (RT_SUCCESS(rc))
             {
-                rc = RTSemSpinMutexCreate(&pLogger->pInt->hSpinMtx, RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
+                if (!(fFlags & RTLOG_F_NO_LOCKING))
+                    rc = RTSemSpinMutexCreate(&pLoggerInt->hSpinMtx, RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
                 if (RT_SUCCESS(rc))
                 {
@@ -990,17 +1112,17 @@
                     {
                         int32_t c = RTLockValidatorWriteLockGetCount(Thread);
-                        RTSemSpinMutexRequest(pLogger->pInt->hSpinMtx);
+                        RTSemSpinMutexRequest(pLoggerInt->hSpinMtx);
                         c = RTLockValidatorWriteLockGetCount(Thread) - c;
-                        RTSemSpinMutexRelease(pLogger->pInt->hSpinMtx);
+                        RTSemSpinMutexRelease(pLoggerInt->hSpinMtx);
                         ASMAtomicWriteU32(&g_cLoggerLockCount, c);
                     }
 
                     /* Use the callback to generate some initial log contents. */
-                    Assert(RT_VALID_PTR(pLogger->pInt->pfnPhase) || pLogger->pInt->pfnPhase == NULL);
-                    if (pLogger->pInt->pfnPhase)
-                        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal);
+                    AssertPtrNull(pLoggerInt->pfnPhase);
+                    if (pLoggerInt->pfnPhase)
+                        pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal);
 # endif
-                    pLogger->pInt->fCreated = true;
-                    *ppLogger = pLogger;
+                    pLoggerInt->fCreated = true;
+                    *ppLogger = &pLoggerInt->Core;
                     return VINF_SUCCESS;
                 }
@@ -1009,13 +1131,13 @@
             }
 # ifdef IN_RING3
-            RTFileClose(pLogger->pInt->hFile);
+            RTFileClose(pLoggerInt->hFile);
 # endif
 # if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
-            RTMemFree(*(void **)&pLogger->pfnLogger);
+            RTMemFree(*(void **)&pLoggerInt->Core.pfnLogger);
 # else
-            RTMemExecFree(*(void **)&pLogger->pfnLogger, 64);
+            RTMemExecFree(*(void **)&pLoggerInt->Core.pfnLogger, 64);
 # endif
         }
-        RTMemFree(pLogger);
+        RTMemFree(pLoggerInt);
     }
     else
@@ -1027,17 +1149,18 @@
 
 
-RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
+RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint64_t fFlags, const char *pszGroupSettings,
                         const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
                         uint32_t fDestFlags, const char *pszFilenameFmt, ...)
 {
-    va_list args;
-    int rc;
-
-    va_start(args, pszFilenameFmt);
-    rc = RTLogCreateExV(ppLogger, fFlags, pszGroupSettings, pszEnvVarBase,
-                        cGroups, papszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/, fDestFlags,
+    va_list va;
+    int     rc;
+
+    va_start(va, pszFilenameFmt);
+    rc = RTLogCreateExV(ppLogger, pszEnvVarBase, fFlags, pszGroupSettings, cGroups, papszGroups,
+                        UINT32_MAX /*cMaxEntriesPerGroup*/,
+                        NULL /*pfnFlush*/, 0 /*cBufDescs*/, NULL /*paBufDescs*/, fDestFlags,
                         NULL /*pfnPhase*/, 0 /*cHistory*/, 0 /*cbHistoryFileMax*/, 0 /*cSecsHistoryTimeSlot*/,
-                        NULL /*pErrInfo*/, pszFilenameFmt, args);
-    va_end(args);
+                        NULL /*pErrInfo*/, pszFilenameFmt, va);
+    va_end(va);
     return rc;
 }
@@ -1045,18 +1168,19 @@
 
 
-RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, const char *pszEnvVarBase,
+RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
                           unsigned cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
-                          uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
-                          uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+                          PFNRTLOGFLUSH pfnFlush, uint32_t cBufDescs, PRTLOGBUFFERDESC paBufDescs, uint32_t fDestFlags,
+                          PFNRTLOGPHASE pfnPhase, uint32_t cHistory, uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
                           PRTERRINFO pErrInfo, const char *pszFilenameFmt, ...)
 {
-    va_list args;
-    int rc;
-
-    va_start(args, pszFilenameFmt);
-    rc = RTLogCreateExV(ppLogger, fFlags, pszGroupSettings, pszEnvVarBase, cGroups, papszGroups, cMaxEntriesPerGroup,
-                        fDestFlags, pfnPhase, cHistory, cbHistoryFileMax, cSecsHistoryTimeSlot,
-                        pErrInfo, pszFilenameFmt, args);
-    va_end(args);
+    va_list va;
+    int     rc;
+
+    va_start(va, pszFilenameFmt);
+    rc = RTLogCreateExV(ppLogger, pszEnvVarBase, fFlags, pszGroupSettings, cGroups, papszGroups, cMaxEntriesPerGroup,
+                        pfnFlush, cBufDescs, paBufDescs, fDestFlags,
+                        pfnPhase, cHistory, cbHistoryFileMax, cSecsHistoryTimeSlot,
+                        pErrInfo, pszFilenameFmt, va);
+    va_end(va);
     return rc;
 }
@@ -1074,32 +1198,32 @@
 RTDECL(int) RTLogDestroy(PRTLOGGER pLogger)
 {
-    int             rc;
-    uint32_t        iGroup;
-    RTSEMSPINMUTEX  hSpinMtx;
+    int                 rc;
+    uint32_t            iGroup;
+    RTSEMSPINMUTEX      hSpinMtx;
+    PRTLOGGERINTERNAL   pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
 
     /*
      * Validate input.
      */
-    if (!pLogger)
+    if (!pLoggerInt)
         return VINF_SUCCESS;
-    AssertPtrReturn(pLogger, VERR_INVALID_POINTER);
-    AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
-    AssertPtrReturn(pLogger->pInt, VERR_INVALID_POINTER);
+    AssertPtrReturn(pLoggerInt, VERR_INVALID_POINTER);
+    AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
 
     /*
      * Acquire logger instance sem and disable all logging. (paranoia)
      */
-    rc = rtlogLock(pLogger);
+    rc = rtlogLock(pLoggerInt);
     AssertMsgRCReturn(rc, ("%Rrc\n", rc), rc);
 
-    pLogger->fFlags |= RTLOGFLAGS_DISABLED;
-    iGroup = pLogger->cGroups;
+    pLoggerInt->fFlags |= RTLOGFLAGS_DISABLED;
+    iGroup = pLoggerInt->cGroups;
     while (iGroup-- > 0)
-        pLogger->afGroups[iGroup] = 0;
+        pLoggerInt->afGroups[iGroup] = 0;
 
     /*
      * Flush it.
      */
-    rtlogFlush(pLogger, false /*fNeedSpace*/);
+    rtlogFlush(pLoggerInt, false /*fNeedSpace*/);
 
 # ifdef IN_RING3
@@ -1107,18 +1231,18 @@
      * Add end of logging message.
      */
-    if (   (pLogger->fDestFlags & RTLOGDEST_FILE)
-        && pLogger->pInt->hFile != NIL_RTFILE)
-        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_END, rtlogPhaseMsgLocked);
+    if (   (pLoggerInt->fDestFlags & RTLOGDEST_FILE)
+        && pLoggerInt->hFile != NIL_RTFILE)
+        pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_END, rtlogPhaseMsgLocked);
 
     /*
      * Close output stuffs.
      */
-    if (pLogger->pInt->hFile != NIL_RTFILE)
-    {
-        int rc2 = RTFileClose(pLogger->pInt->hFile);
+    if (pLoggerInt->hFile != NIL_RTFILE)
+    {
+        int rc2 = RTFileClose(pLoggerInt->hFile);
         AssertRC(rc2);
         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
             rc = rc2;
-        pLogger->pInt->hFile = NIL_RTFILE;
+        pLoggerInt->hFile = NIL_RTFILE;
     }
 # endif
@@ -1127,6 +1251,6 @@
      * Free the mutex, the wrapper and the instance memory.
      */
-    hSpinMtx = pLogger->pInt->hSpinMtx;
-    pLogger->pInt->hSpinMtx = NIL_RTSEMSPINMUTEX;
+    hSpinMtx = pLoggerInt->hSpinMtx;
+    pLoggerInt->hSpinMtx = NIL_RTSEMSPINMUTEX;
     if (hSpinMtx != NIL_RTSEMSPINMUTEX)
     {
@@ -1139,14 +1263,14 @@
     }
 
-    if (pLogger->pfnLogger)
+    if (pLoggerInt->Core.pfnLogger)
     {
 # if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
-        RTMemFree(*(void **)&pLogger->pfnLogger);
+        RTMemFree(*(void **)&pLoggerInt->Core.pfnLogger);
 # else
-        RTMemExecFree(*(void **)&pLogger->pfnLogger, 64);
+        RTMemExecFree(*(void **)&pLoggerInt->Core.pfnLogger, 64);
 # endif
-        pLogger->pfnLogger = NULL;
-    }
-    RTMemFree(pLogger);
+        pLoggerInt->Core.pfnLogger = NULL;
+    }
+    RTMemFree(pLoggerInt);
 
     return rc;
@@ -1155,4 +1279,5 @@
 
 
+# if 0 /* obsolete */
 /**
  * Create a logger instance clone for RC usage.
@@ -1237,6 +1362,8 @@
 }
 RT_EXPORT_SYMBOL(RTLogCloneRC);
-
-
+# endif
+
+
+# if 0 /* obsolete */
 /**
  * Flushes a RC logger instance to a R3 logger.
@@ -1294,7 +1421,8 @@
 }
 RT_EXPORT_SYMBOL(RTLogFlushRC);
+# endif
 
 # ifdef IN_RING3
-
+#  if 0 /* obsolete */
 RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger,
                              RTR0PTR pLoggerR0Ptr, RTR0PTR pfnLoggerR0Ptr, RTR0PTR pfnFlushR0Ptr,
@@ -1472,7 +1600,9 @@
 RT_EXPORT_SYMBOL(RTLogFlushR0);
 
+#  endif /* obsolete */
 # endif /* IN_RING3 */
 
 
+#if 0
 /**
  * Flushes the buffer in one logger instance onto another logger.
@@ -1486,20 +1616,23 @@
 RTDECL(void) RTLogFlushToLogger(PRTLOGGER pSrcLogger, PRTLOGGER pDstLogger)
 {
+    PRTLOGGERINTERNAL pSrcLoggerInt = (PRTLOGGERINTERNAL)pSrcLogger;
+    PRTLOGGERINTERNAL pDstLoggerInt = (PRTLOGGERINTERNAL)pDstLogger;
+
     /*
      * Resolve defaults.
      */
-    if (!pDstLogger)
-    {
-        pDstLogger = RTLogDefaultInstance();
-        if (!pDstLogger)
+    if (!pDstLoggerInt)
+    {
+        pDstLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pDstLoggerInt)
         {
             /* flushing to "/dev/null". */
-            if (pSrcLogger->offScratch)
+            if (pSrcLoggerInt->offScratch)
             {
-                int rc = rtlogLock(pSrcLogger);
+                int rc = rtlogLock(pSrcLoggerInt);
                 if (RT_SUCCESS(rc))
                 {
-                    pSrcLogger->offScratch = 0;
-                    rtlogUnlock(pSrcLogger);
+                    pSrcLoggerInt->offScratch = 0;
+                    rtlogUnlock(pSrcLoggerInt);
                 }
             }
@@ -1511,14 +1644,14 @@
      * Any thing to flush?
      */
-    if (    pSrcLogger->offScratch
-        ||  pDstLogger->offScratch)
+    if (    pSrcLoggerInt->offScratch
+        ||  pDstLoggerInt->offScratch)
     {
         /*
          * Acquire logger semaphores.
          */
-        int rc = rtlogLock(pDstLogger);
+        int rc = rtlogLock(pDstLoggerInt);
         if (RT_FAILURE(rc))
             return;
-        rc = rtlogLock(pSrcLogger);
+        rc = rtlogLock(pSrcLoggerInt);
         if (RT_SUCCESS(rc))
         {
@@ -1527,9 +1660,9 @@
              * flush the HC instance.
              */
-            if (pSrcLogger->offScratch)
+            if (pSrcLoggerInt->offScratch)
             {
-                rtLogOutput(pDstLogger, pSrcLogger->achScratch, pSrcLogger->offScratch);
-                rtLogOutput(pDstLogger, NULL, 0);
-                pSrcLogger->offScratch = 0;
+                rtLogOutput(pDstLoggerInt, pSrcLoggerInt->achScratch, pSrcLoggerInt->offScratch);
+                rtLogOutput(pDstLoggerInt, NULL, 0);
+                pSrcLoggerInt->offScratch = 0;
             }
 
@@ -1537,10 +1670,11 @@
              * Release the semaphores.
              */
-            rtlogUnlock(pSrcLogger);
-        }
-        rtlogUnlock(pDstLogger);
+            rtlogUnlock(pSrcLoggerInt);
+        }
+        rtlogUnlock(pDstLoggerInt);
     }
 }
 RT_EXPORT_SYMBOL(RTLogFlushToLogger);
+#endif
 
 
@@ -1558,19 +1692,20 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return VINF_SUCCESS;
     }
-    AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
 
     /*
      * Do the work.
      */
-    rtlogLock(pLogger);
-    pLogger->pInt->pvPrefixUserArg = pvUser;
-    pLogger->pInt->pfnPrefix       = pfnCallback;
-    rtlogUnlock(pLogger);
+    rtlogLock(pLoggerInt);
+    pLoggerInt->pvPrefixUserArg = pvUser;
+    pLoggerInt->pfnPrefix       = pfnCallback;
+    rtlogUnlock(pLoggerInt);
 
     return VINF_SUCCESS;
@@ -1666,13 +1801,16 @@
 RTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszValue)
 {
+
     /*
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return VINF_SUCCESS;
     }
+    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
 
     /*
@@ -1723,10 +1861,10 @@
                             ? RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1
                             : rtlogGroupFlags(&pszStart[3]);
-            for (i = 0; i < pLogger->cGroups; i++)
+            for (i = 0; i < pLoggerInt->cGroups; i++)
             {
                 if (fEnabled)
-                    pLogger->afGroups[i] |= fFlags;
+                    pLoggerInt->afGroups[i] |= fFlags;
                 else
-                    pLogger->afGroups[i] &= ~fFlags;
+                    pLoggerInt->afGroups[i] &= ~fFlags;
             }
         }
@@ -1736,8 +1874,8 @@
              * Specific group(s).
              */
-            for (i = 0; i < pLogger->cGroups; i++)
+            for (i = 0; i < pLoggerInt->cGroups; i++)
             {
                 const char *psz2 = (const char*)pszStart;
-                if (rtlogIsGroupMatching(pLogger->pInt->papszGroups[i], &psz2, cch))
+                if (rtlogIsGroupMatching(pLoggerInt->papszGroups[i], &psz2, cch))
                 {
                     unsigned fFlags = RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1;
@@ -1745,7 +1883,7 @@
                         fFlags = rtlogGroupFlags(psz2);
                     if (fEnabled)
-                        pLogger->afGroups[i] |= fFlags;
+                        pLoggerInt->afGroups[i] |= fFlags;
                     else
-                        pLogger->afGroups[i] &= ~fFlags;
+                        pLoggerInt->afGroups[i] &= ~fFlags;
                 }
             } /* for each group */
@@ -1920,9 +2058,10 @@
 RTDECL(int) RTLogQueryGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
 {
-    bool        fNotFirst = false;
-    int         rc        = VINF_SUCCESS;
-    uint32_t    cGroups;
-    uint32_t    fGroup;
-    uint32_t    i;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    bool              fNotFirst  = false;
+    int               rc         = VINF_SUCCESS;
+    uint32_t          cGroups;
+    uint32_t          fGroup;
+    uint32_t          i;
 
     Assert(cchBuf);
@@ -1931,8 +2070,8 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
         {
             *pszBuf = '\0';
@@ -1940,13 +2079,14 @@
         }
     }
-
-    cGroups = pLogger->cGroups;
+    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
+
+    cGroups = pLoggerInt->cGroups;
 
     /*
      * Check if all are the same.
      */
-    fGroup = pLogger->afGroups[0];
+    fGroup = pLoggerInt->afGroups[0];
     for (i = 1; i < cGroups; i++)
-        if (pLogger->afGroups[i] != fGroup)
+        if (pLoggerInt->afGroups[i] != fGroup)
             break;
     if (i >= cGroups)
@@ -1960,8 +2100,8 @@
         for (i = 0; i < cGroups; i++)
         {
-            fGroup = pLogger->afGroups[i];
+            fGroup = pLoggerInt->afGroups[i];
             if (fGroup)
             {
-                const char *pszName = pLogger->pInt->papszGroups[i];
+                const char *pszName = pLoggerInt->papszGroups[i];
                 if (pszName)
                 {
@@ -1992,13 +2132,14 @@
 RTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszValue)
 {
-    int rc = VINF_SUCCESS;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    int               rc         = VINF_SUCCESS;
 
     /*
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return VINF_SUCCESS;
     }
@@ -2046,10 +2187,10 @@
             if (!strncmp(pszValue, g_aLogFlags[i].pszInstr, g_aLogFlags[i].cchInstr))
             {
-                if (!(g_aLogFlags[i].fFixedDest & pLogger->fDestFlags))
+                if (!(g_aLogFlags[i].fFixedDest & pLoggerInt->fDestFlags))
                 {
                     if (fNo == g_aLogFlags[i].fInverted)
-                        pLogger->fFlags |= g_aLogFlags[i].fFlag;
+                        pLoggerInt->fFlags |= g_aLogFlags[i].fFlag;
                     else
-                        pLogger->fFlags &= ~g_aLogFlags[i].fFlag;
+                        pLoggerInt->fFlags &= ~g_aLogFlags[i].fFlag;
                 }
                 pszValue += g_aLogFlags[i].cchInstr;
@@ -2087,23 +2228,24 @@
 RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered)
 {
-    bool fOld;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    bool              fOld;
 
     /*
      * Resolve the logger instance.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return false;
     }
 
-    rtlogLock(pLogger);
-    fOld  = !!(pLogger->fFlags & RTLOGFLAGS_BUFFERED);
+    rtlogLock(pLoggerInt);
+    fOld  = !!(pLoggerInt->fFlags & RTLOGFLAGS_BUFFERED);
     if (fBuffered)
-        pLogger->fFlags |= RTLOGFLAGS_BUFFERED;
+        pLoggerInt->fFlags |= RTLOGFLAGS_BUFFERED;
     else
-        pLogger->fFlags &= ~RTLOGFLAGS_BUFFERED;
-    rtlogUnlock(pLogger);
+        pLoggerInt->fFlags &= ~RTLOGFLAGS_BUFFERED;
+    rtlogUnlock(pLoggerInt);
 
     return fOld;
@@ -2115,21 +2257,51 @@
 RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup)
 {
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+
     /*
      * Resolve the logger instance.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return UINT32_MAX;
     }
 
-    rtlogLock(pLogger);
-    uint32_t cOld = pLogger->pInt->cMaxEntriesPerGroup;
-    pLogger->pInt->cMaxEntriesPerGroup = cMaxEntriesPerGroup;
-    rtlogUnlock(pLogger);
+    rtlogLock(pLoggerInt);
+    uint32_t cOld = pLoggerInt->cMaxEntriesPerGroup;
+    pLoggerInt->cMaxEntriesPerGroup = cMaxEntriesPerGroup;
+    rtlogUnlock(pLoggerInt);
 
     return cOld;
 }
+#endif
+
+
+#ifdef IN_RING0
+RTR0DECL(int) RTLogSetR0ThreadNameF(PRTLOGGER pLogger, const char *pszNameFmt, ...)
+{
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    int               rc;
+    if (pLoggerInt)
+    {
+        va_list va;
+        va_start(va, pszNameFmt);
+
+        rc = rtlogLock(pLoggerInt);
+        if (RT_SUCCESS(rc))
+        {
+            ssize_t cch = RTStrPrintf2V(pLoggerInt->szR0ThreadName, sizeof(pLoggerInt->szR0ThreadName), pszNameFmt, va);
+            rtlogUnlock(pLoggerInt);
+            rc = cch > 0 ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW;
+        }
+
+        va_end(va);
+    }
+    else
+        rc = VERR_INVALID_PARAMETER;
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogSetR0ThreadNameF);
 #endif
 
@@ -2144,13 +2316,49 @@
 RTDECL(uint64_t) RTLogGetFlags(PRTLOGGER pLogger)
 {
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return UINT64_MAX;
     }
-    return pLogger->fFlags;
+    return pLoggerInt->fFlags;
 }
 RT_EXPORT_SYMBOL(RTLogGetFlags);
+
+
+/**
+ * Modifies the flag settings for the given logger.
+ *
+ * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
+ *          pLogger is NULL.
+ * @param   pLogger         Logger instance (NULL for default logger).
+ * @param   fSet            Mask of flags to set (OR).
+ * @param   fClear          Mask of flags to clear (NAND).  This is allowed to
+ *                          include invalid flags - e.g. UINT64_MAX is okay.
+ */
+RTDECL(int) RTLogChangeFlags(PRTLOGGER pLogger, uint64_t fSet, uint64_t fClear)
+{
+    AssertReturn(!(fSet & ~RTLOG_F_VALID_MASK), VERR_INVALID_FLAGS);
+
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
+            return VINF_SUCCESS;
+    }
+    AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pLoggerInt->uRevision == RTLOGGERINTERNAL_REV, VERR_LOG_REVISION_MISMATCH);
+
+    /*
+     * Make the changes.
+     */
+    pLoggerInt->fFlags &= ~fClear;
+    pLoggerInt->fFlags |= fSet;
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogChangeFlags);
 
 
@@ -2166,8 +2374,9 @@
 RTDECL(int) RTLogQueryFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
 {
-    bool        fNotFirst = false;
-    int         rc        = VINF_SUCCESS;
-    uint32_t    fFlags;
-    unsigned    i;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    bool              fNotFirst  = false;
+    int               rc         = VINF_SUCCESS;
+    uint32_t          fFlags;
+    unsigned          i;
 
     Assert(cchBuf);
@@ -2176,8 +2385,8 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
         {
             *pszBuf = '\0';
@@ -2189,5 +2398,5 @@
      * Add the flags in the list.
      */
-    fFlags = pLogger->fFlags;
+    fFlags = pLoggerInt->fFlags;
     for (i = 0; i < RT_ELEMENTS(g_aLogFlags); i++)
         if (    !g_aLogFlags[i].fInverted
@@ -2272,8 +2481,9 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return VINF_SUCCESS;
     }
@@ -2313,7 +2523,7 @@
             {
                 if (!fNo)
-                    pLogger->fDestFlags |= g_aLogDst[i].fFlag;
+                    pLoggerInt->fDestFlags |= g_aLogDst[i].fFlag;
                 else
-                    pLogger->fDestFlags &= ~g_aLogDst[i].fFlag;
+                    pLoggerInt->fDestFlags &= ~g_aLogDst[i].fFlag;
                 pszValue += cchInstr;
 
@@ -2328,5 +2538,5 @@
 
 # ifdef IN_RING3
-                    char szTmp[sizeof(pLogger->pInt->szFilename)];
+                    char szTmp[sizeof(pLoggerInt->szFilename)];
 # else
                     char szTmp[32];
@@ -2334,15 +2544,15 @@
                     if (0)
                     { /* nothing */ }
-#ifdef IN_RING3
+# ifdef IN_RING3
 
                     /* log file name */
                     else if (i == 0 /* file */ && !fNo)
                     {
-                        if (!(pLogger->fDestFlags & RTLOGDEST_FIXED_FILE))
+                        if (!(pLoggerInt->fDestFlags & RTLOGDEST_FIXED_FILE))
                         {
-                            AssertReturn(cch < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
-                            memcpy(pLogger->pInt->szFilename, pszValue, cch);
-                            pLogger->pInt->szFilename[cch] = '\0';
-                            /** @todo reopen log file if pLogger->pInt->fCreated is true ... */
+                            AssertReturn(cch < sizeof(pLoggerInt->szFilename), VERR_OUT_OF_RANGE);
+                            memcpy(pLoggerInt->szFilename, pszValue, cch);
+                            pLoggerInt->szFilename[cch] = '\0';
+                            /** @todo reopen log file if pLoggerInt->fCreated is true ... */
                         }
                     }
@@ -2350,20 +2560,20 @@
                     else if (i == 1 /* dir */ && !fNo)
                     {
-                        if (!(pLogger->fDestFlags & RTLOGDEST_FIXED_DIR))
+                        if (!(pLoggerInt->fDestFlags & RTLOGDEST_FIXED_DIR))
                         {
-                            const char *pszFile = RTPathFilename(pLogger->pInt->szFilename);
+                            const char *pszFile = RTPathFilename(pLoggerInt->szFilename);
                             size_t      cchFile = pszFile ? strlen(pszFile) : 0;
-                            AssertReturn(cchFile + cch + 1 < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
+                            AssertReturn(cchFile + cch + 1 < sizeof(pLoggerInt->szFilename), VERR_OUT_OF_RANGE);
                             memcpy(szTmp, cchFile ? pszFile : "", cchFile + 1);
 
-                            memcpy(pLogger->pInt->szFilename, pszValue, cch);
-                            pLogger->pInt->szFilename[cch] = '\0';
-                            RTPathStripTrailingSlash(pLogger->pInt->szFilename);
-
-                            cch = strlen(pLogger->pInt->szFilename);
-                            pLogger->pInt->szFilename[cch++] = '/';
-                            memcpy(&pLogger->pInt->szFilename[cch], szTmp, cchFile);
-                            pLogger->pInt->szFilename[cch + cchFile] = '\0';
-                            /** @todo reopen log file if pLogger->pInt->fCreated is true ... */
+                            memcpy(pLoggerInt->szFilename, pszValue, cch);
+                            pLoggerInt->szFilename[cch] = '\0';
+                            RTPathStripTrailingSlash(pLoggerInt->szFilename);
+
+                            cch = strlen(pLoggerInt->szFilename);
+                            pLoggerInt->szFilename[cch++] = '/';
+                            memcpy(&pLoggerInt->szFilename[cch], szTmp, cchFile);
+                            pLoggerInt->szFilename[cch + cchFile] = '\0';
+                            /** @todo reopen log file if pLoggerInt->fCreated is true ... */
                         }
                     }
@@ -2377,8 +2587,8 @@
                                 rc = RTStrToUInt32Full(szTmp, 0, &cHistory);
                             AssertMsgReturn(RT_SUCCESS(rc) && cHistory < _1M, ("Invalid history value %s (%Rrc)!\n", szTmp, rc), rc);
-                            pLogger->pInt->cHistory = cHistory;
+                            pLoggerInt->cHistory = cHistory;
                         }
                         else
-                            pLogger->pInt->cHistory = 0;
+                            pLoggerInt->cHistory = 0;
                     }
                     else if (i == 3 /* histsize */)
@@ -2388,11 +2598,11 @@
                             int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
                             if (RT_SUCCESS(rc))
-                                rc = RTStrToUInt64Full(szTmp, 0, &pLogger->pInt->cbHistoryFileMax);
+                                rc = RTStrToUInt64Full(szTmp, 0, &pLoggerInt->cbHistoryFileMax);
                             AssertMsgRCReturn(rc, ("Invalid history file size value %s (%Rrc)!\n", szTmp, rc), rc);
-                            if (pLogger->pInt->cbHistoryFileMax == 0)
-                                pLogger->pInt->cbHistoryFileMax = UINT64_MAX;
+                            if (pLoggerInt->cbHistoryFileMax == 0)
+                                pLoggerInt->cbHistoryFileMax = UINT64_MAX;
                         }
                         else
-                            pLogger->pInt->cbHistoryFileMax = UINT64_MAX;
+                            pLoggerInt->cbHistoryFileMax = UINT64_MAX;
                     }
                     else if (i == 4 /* histtime */)
@@ -2402,11 +2612,11 @@
                             int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
                             if (RT_SUCCESS(rc))
-                                rc = RTStrToUInt32Full(szTmp, 0, &pLogger->pInt->cSecsHistoryTimeSlot);
+                                rc = RTStrToUInt32Full(szTmp, 0, &pLoggerInt->cSecsHistoryTimeSlot);
                             AssertMsgRCReturn(rc, ("Invalid history time slot value %s (%Rrc)!\n", szTmp, rc), rc);
-                            if (pLogger->pInt->cSecsHistoryTimeSlot == 0)
-                                pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
+                            if (pLoggerInt->cSecsHistoryTimeSlot == 0)
+                                pLoggerInt->cSecsHistoryTimeSlot = UINT32_MAX;
                         }
                         else
-                            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
+                            pLoggerInt->cSecsHistoryTimeSlot = UINT32_MAX;
                     }
 # endif /* IN_RING3 */
@@ -2427,5 +2637,5 @@
                         else
                             cbRingBuf = RT_ALIGN_32(cbRingBuf, 64);
-                        rc = rtLogRingBufAdjust(pLogger, cbRingBuf, false /*fForce*/);
+                        rc = rtLogRingBufAdjust(pLoggerInt, cbRingBuf, false /*fForce*/);
                         if (RT_FAILURE(rc))
                             return rc;
@@ -2438,7 +2648,7 @@
                     pszValue = pszEnd + (*pszEnd != '\0');
                 }
-                else if (i == 5 /* ringbuf */ && !fNo && !pLogger->pInt->pszRingBuf)
+                else if (i == 5 /* ringbuf */ && !fNo && !pLoggerInt->pszRingBuf)
                 {
-                    int rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, false /*fForce*/);
+                    int rc = rtLogRingBufAdjust(pLoggerInt, pLoggerInt->cbRingBuf, false /*fForce*/);
                     if (RT_FAILURE(rc))
                         return rc;
@@ -2476,8 +2686,9 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return VINF_SUCCESS;
     }
@@ -2486,26 +2697,88 @@
      * Do the work.
      */
-    int rc = rtlogLock(pLogger);
+    int rc = rtlogLock(pLoggerInt);
     if (RT_SUCCESS(rc))
     {
-        if (pLogger->fDestFlags & RTLOGDEST_F_DELAY_FILE)
-        {
-            pLogger->fDestFlags &= ~RTLOGDEST_F_DELAY_FILE;
+        if (pLoggerInt->fDestFlags & RTLOGDEST_F_DELAY_FILE)
+        {
+            pLoggerInt->fDestFlags &= ~RTLOGDEST_F_DELAY_FILE;
 # ifdef IN_RING3
-            if (   pLogger->fDestFlags & RTLOGDEST_FILE
-                && pLogger->pInt->hFile == NIL_RTFILE)
+            if (   pLoggerInt->fDestFlags & RTLOGDEST_FILE
+                && pLoggerInt->hFile == NIL_RTFILE)
             {
-                rc = rtR3LogOpenFileDestination(pLogger, pErrInfo);
+                rc = rtR3LogOpenFileDestination(pLoggerInt, pErrInfo);
                 if (RT_SUCCESS(rc))
-                    rtlogFlush(pLogger, false /*fNeedSpace*/);
+                    rtlogFlush(pLoggerInt, false /*fNeedSpace*/);
             }
 # endif
             RT_NOREF(pErrInfo); /** @todo fix create API to use RTErrInfo */
         }
-        rtlogUnlock(pLogger);
+        rtlogUnlock(pLoggerInt);
     }
     return VINF_SUCCESS;
 }
 RT_EXPORT_SYMBOL(RTLogClearFileDelayFlag);
+
+
+/**
+ * Modifies the log destinations settings for the given logger.
+ *
+ * This is only suitable for simple destination settings that doesn't take
+ * additional arguments, like RTLOGDEST_FILE.
+ *
+ * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
+ *          pLogger is NULL.
+ * @param   pLogger            Logger instance (NULL for default logger).
+ * @param   fSet               Mask of destinations to set (OR).
+ * @param   fClear             Mask of destinations to clear (NAND).
+ */
+RTDECL(int) RTLogChangeDestinations(PRTLOGGER pLogger, uint32_t fSet, uint32_t fClear)
+{
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    AssertCompile((RTLOG_DST_VALID_MASK & RTLOG_DST_CHANGE_MASK) == RTLOG_DST_CHANGE_MASK);
+    AssertReturn(!(fSet & ~RTLOG_DST_CHANGE_MASK), VERR_INVALID_FLAGS);
+    AssertReturn(!(fClear & ~RTLOG_DST_CHANGE_MASK), VERR_INVALID_FLAGS);
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
+            return VINF_SUCCESS;
+    }
+    AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pLoggerInt->uRevision == RTLOGGERINTERNAL_REV, VERR_LOG_REVISION_MISMATCH);
+
+    /*
+     * Make the changes.
+     */
+    pLoggerInt->fDestFlags &= ~fClear;
+    pLoggerInt->fDestFlags |= fSet;
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogChangeDestinations);
+
+
+/**
+ * Gets the current destinations flags for the given logger.
+ *
+ * @returns Logger destination flags, UINT32_MAX if no logger.
+ * @param   pLogger             Logger instance (NULL for default logger).
+ */
+RTDECL(uint32_t) RTLogGetDestinations(PRTLOGGER pLogger)
+{
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
+            return UINT32_MAX;
+    }
+    return pLoggerInt->fFlags;
+}
+RT_EXPORT_SYMBOL(RTLogGetDestinations);
 
 
@@ -2521,8 +2794,9 @@
 RTDECL(int) RTLogQueryDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
 {
-    bool        fNotFirst = false;
-    int         rc        = VINF_SUCCESS;
-    uint32_t    fDestFlags;
-    unsigned    i;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    bool              fNotFirst  = false;
+    int               rc         = VINF_SUCCESS;
+    uint32_t          fDestFlags;
+    unsigned          i;
 
     AssertReturn(cchBuf, VERR_INVALID_PARAMETER);
@@ -2532,8 +2806,8 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return VINF_SUCCESS;
     }
@@ -2542,5 +2816,5 @@
      * Add the flags in the list.
      */
-    fDestFlags = pLogger->fDestFlags;
+    fDestFlags = pLoggerInt->fDestFlags;
     for (i = 6; i < RT_ELEMENTS(g_aLogDst); i++)
         if (g_aLogDst[i].fFlag & fDestFlags)
@@ -2569,12 +2843,12 @@
         if (RT_FAILURE(rc))
             return rc;
-        rc = RTStrCopyP(&pszBuf, &cchBuf, pLogger->pInt->szFilename);
+        rc = RTStrCopyP(&pszBuf, &cchBuf, pLoggerInt->szFilename);
         if (RT_FAILURE(rc))
             return rc;
         fNotFirst = true;
 
-        if (pLogger->pInt->cHistory)
-        {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " history=%u" : "history=%u", pLogger->pInt->cHistory);
+        if (pLoggerInt->cHistory)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " history=%u" : "history=%u", pLoggerInt->cHistory);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
             if (RT_FAILURE(rc))
@@ -2582,7 +2856,7 @@
             fNotFirst = true;
         }
-        if (pLogger->pInt->cbHistoryFileMax != UINT64_MAX)
-        {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " histsize=%llu" : "histsize=%llu", pLogger->pInt->cbHistoryFileMax);
+        if (pLoggerInt->cbHistoryFileMax != UINT64_MAX)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " histsize=%llu" : "histsize=%llu", pLoggerInt->cbHistoryFileMax);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
             if (RT_FAILURE(rc))
@@ -2590,7 +2864,7 @@
             fNotFirst = true;
         }
-        if (pLogger->pInt->cSecsHistoryTimeSlot != UINT32_MAX)
-        {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " histtime=%llu" : "histtime=%llu", pLogger->pInt->cSecsHistoryTimeSlot);
+        if (pLoggerInt->cSecsHistoryTimeSlot != UINT32_MAX)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " histtime=%llu" : "histtime=%llu", pLoggerInt->cSecsHistoryTimeSlot);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
             if (RT_FAILURE(rc))
@@ -2606,9 +2880,9 @@
     if (fDestFlags & RTLOGDEST_RINGBUF)
     {
-        if (pLogger->pInt->cbRingBuf == RTLOG_RINGBUF_DEFAULT_SIZE)
+        if (pLoggerInt->cbRingBuf == RTLOG_RINGBUF_DEFAULT_SIZE)
             rc = RTStrCopyP(&pszBuf, &cchBuf, fNotFirst ? " ringbuf" : "ringbuf");
         else
         {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " ringbuf=%#x" : "ringbuf=%#x", pLogger->pInt->cbRingBuf);
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " ringbuf=%#x" : "ringbuf=%#x", pLoggerInt->cbRingBuf);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
         }
@@ -2622,4 +2896,205 @@
 RT_EXPORT_SYMBOL(RTLogQueryDestinations);
 
+
+/**
+ * Helper for calculating the CRC32 of all the group names.
+ */
+static uint32_t rtLogCalcGroupNameCrc32(PRTLOGGERINTERNAL pLoggerInt)
+{
+    const char * const * const  papszGroups = pLoggerInt->papszGroups;
+    uint32_t                    iGroup      = pLoggerInt->cGroups;
+    uint32_t                    uCrc32      = RTCrc32Start();
+    while (iGroup-- > 0)
+    {
+        const char *pszGroup = papszGroups[iGroup];
+        uCrc32 = RTCrc32Process(uCrc32, pszGroup, strlen(pszGroup) + 1);
+    }
+    return RTCrc32Finish(uCrc32);
+}
+
+
+/**
+ * Performs a bulk update of logger flags and group flags.
+ *
+ * This is for instanced used for copying settings from ring-3 to ring-0
+ * loggers.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger             The logger instance (NULL for default logger).
+ * @param   fFlags              The new logger flags.
+ * @param   uGroupCrc32         The CRC32 of the group name strings.
+ * @param   cGroups             Number of groups.
+ * @param   pafGroups           Array of group flags.
+ * @sa      RTLogQueryBulk
+ */
+RTDECL(int) RTLogBulkUpdate(PRTLOGGER pLogger, uint64_t fFlags, uint32_t uGroupCrc32, uint32_t cGroups, uint32_t const *pafGroups)
+{
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    int               rc;
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
+        if (!pLoggerInt)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Do the updating.
+     */
+    rc = rtlogLock(pLoggerInt);
+    if (RT_SUCCESS(rc))
+    {
+        pLoggerInt->fFlags = fFlags;
+        if (   uGroupCrc32 == rtLogCalcGroupNameCrc32(pLoggerInt)
+            && pLoggerInt->cGroups == cGroups)
+        {
+            memcpy(pLoggerInt->afGroups, pafGroups, sizeof(pLoggerInt->afGroups[0]) * cGroups);
+            rc = VINF_SUCCESS;
+        }
+        else
+            rc = VERR_MISMATCH;
+
+        rtlogUnlock(pLoggerInt);
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogBulkUpdate);
+
+
+/**
+ * Queries data for a bulk update of logger flags and group flags.
+ *
+ * This is for instanced used for copying settings from ring-3 to ring-0
+ * loggers.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_BUFFER_OVERFLOW if pafGroups is too small, @a pcGroups will be
+ *          set to the actual number of groups.
+ * @param   pLogger             The logger instance (NULL for default logger).
+ * @param   pfFlags             Where to return the logger flags.
+ * @param   puGroupCrc32        Where to return the CRC32 of the group names.
+ * @param   pcGroups            Input: Size of the @a pafGroups allocation.
+ *                              Output: Actual number of groups returned.
+ * @param   pafGroups           Where to return the flags for each group.
+ * @sa      RTLogBulkUpdate
+ */
+RTDECL(int) RTLogQueryBulk(PRTLOGGER pLogger, uint64_t *pfFlags, uint32_t *puGroupCrc32, uint32_t *pcGroups, uint32_t *pafGroups)
+{
+    PRTLOGGERINTERNAL pLoggerInt   = (PRTLOGGERINTERNAL)pLogger;
+    uint32_t const    cGroupsAlloc = *pcGroups;
+
+    /*
+     * Resolve defaults.
+     */
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
+        if (!pLoggerInt)
+        {
+            *pfFlags      = 0;
+            *puGroupCrc32 = 0;
+            *pcGroups     = 0;
+            return VINF_SUCCESS;
+        }
+    }
+    AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+
+    /*
+     * Get the data.
+     */
+    *pfFlags  = pLoggerInt->fFlags;
+    *pcGroups = pLoggerInt->cGroups;
+    if (cGroupsAlloc >= pLoggerInt->cGroups)
+    {
+        memcpy(pafGroups, pLoggerInt->afGroups, sizeof(pLoggerInt->afGroups[0]) * pLoggerInt->cGroups);
+        *puGroupCrc32 = rtLogCalcGroupNameCrc32(pLoggerInt);
+        return VINF_SUCCESS;
+    }
+    *puGroupCrc32 = 0;
+    return VERR_BUFFER_OVERFLOW;
+}
+RT_EXPORT_SYMBOL(RTLogQueryBulk);
+
+
+/**
+ * Write/copy bulk log data from another logger.
+ *
+ * This is used for transferring stuff from the ring-0 loggers and into the
+ * ring-3 one.  The text goes in as-is w/o any processing (i.e. prefixing or
+ * newline fun).
+ *
+ * @returns IRPT status code.
+ * @param   pLogger             The logger instance (NULL for default logger).
+ * @param   pch                 Pointer to the block of bulk log text to write.
+ * @param   cch                 Size of the block of bulk log text to write.
+ */
+RTDECL(int) RTLogBulkWrite(PRTLOGGER pLogger, const char *pch, size_t cch)
+{
+    /*
+     * Resolve defaults.
+     */
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
+        if (!pLoggerInt)
+            return VINF_SUCCESS;
+    }
+
+    /*
+     * Lock and validate it.
+     */
+    int rc = rtlogLock(pLoggerInt);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Do the copying.
+         */
+        while (cch > 0)
+        {
+            PRTLOGBUFFERDESC const  pBufDesc = pLoggerInt->pBufDesc;
+            char * const            pchBuf   = pBufDesc->pchBuf;
+            uint32_t const          cbBuf    = pBufDesc->cbBuf;
+            uint32_t                offBuf   = pBufDesc->offBuf;
+            if (cch + 1 < cbBuf - offBuf)
+            {
+                memcpy(&pchBuf[offBuf], pch, cch);
+                offBuf += (uint32_t)cch;
+                pchBuf[offBuf] = '\0';
+                pBufDesc->offBuf = offBuf;
+                if (pBufDesc->pAux)
+                    pBufDesc->pAux->offBuf = offBuf;
+                if (!(pLoggerInt->fDestFlags & RTLOGFLAGS_BUFFERED))
+                    rtlogFlush(pLoggerInt, false /*fNeedSpace*/);
+                break;
+            }
+
+            /* Not enough space. */
+            if (offBuf + 1 < cbBuf)
+            {
+                uint32_t cbToCopy = cbBuf - offBuf - 1;
+                memcpy(&pchBuf[offBuf], pch, cbToCopy);
+                offBuf += cbToCopy;
+                pchBuf[offBuf] = '\0';
+                pBufDesc->offBuf = offBuf;
+                if (pBufDesc->pAux)
+                    pBufDesc->pAux->offBuf = offBuf;
+                pch += cbToCopy;
+                cch -= cbToCopy;
+            }
+
+            rtlogFlush(pLoggerInt, false /*fNeedSpace*/);
+        }
+
+        rtlogUnlock(pLoggerInt);
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTLogBulkWrite);
+
 #endif /* !IN_RC */
 
@@ -2636,51 +3111,45 @@
      * Resolve defaults.
      */
-    if (!pLogger)
-    {
-#ifdef IN_RC
-        pLogger = &g_Logger;
-#else
-        pLogger = g_pLogger;
-#endif
-        if (!pLogger)
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
+        if (!pLoggerInt)
             return;
     }
+    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
+    AssertPtr(pLoggerInt->pBufDesc);
+    Assert(pLoggerInt->pBufDesc->u32Magic == RTLOGBUFFERDESC_MAGIC);
 
     /*
      * Any thing to flush?
      */
-    if (   pLogger->offScratch
-#ifndef IN_RC
-        || (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
-#endif
-       )
-    {
-#ifndef IN_RC
+    if (   pLoggerInt->pBufDesc->offBuf > 0
+        || (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF))
+    {
         /*
          * Acquire logger instance sem.
          */
-        int rc = rtlogLock(pLogger);
-        if (RT_FAILURE(rc))
-            return;
-#endif
-        /*
-         * Call worker.
-         */
-        rtlogFlush(pLogger, false /*fNeedSpace*/);
-
-#ifndef IN_RC
-        /*
-         * Since this is an explicit flush call, the ring buffer content should
-         * be flushed to the other destinations if active.
-         */
-        if (   (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
-            && pLogger->pInt->pszRingBuf /* paranoia */)
-            rtLogRingBufFlush(pLogger);
-
-        /*
-         * Release the semaphore.
-         */
-        rtlogUnlock(pLogger);
-#endif
+        int rc = rtlogLock(pLoggerInt);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Call worker.
+             */
+            rtlogFlush(pLoggerInt, false /*fNeedSpace*/);
+
+            /*
+             * Since this is an explicit flush call, the ring buffer content should
+             * be flushed to the other destinations if active.
+             */
+            if (   (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF)
+                && pLoggerInt->pszRingBuf /* paranoia */)
+                rtLogRingBufFlush(pLoggerInt);
+
+            /*
+             * Release the semaphore.
+             */
+            rtlogUnlock(pLoggerInt);
+        }
     }
 }
@@ -2728,22 +3197,32 @@
 
 
+/**
+ * Worker for RTLogDefaultInstanceEx, RTLogGetDefaultInstanceEx,
+ * RTLogRelGetDefaultInstanceEx and RTLogCheckGroupFlags.
+ */
+DECL_FORCE_INLINE(PRTLOGGERINTERNAL) rtLogCheckGroupFlagsWorker(PRTLOGGERINTERNAL pLoggerInt, uint32_t fFlagsAndGroup)
+{
+    if (pLoggerInt->fFlags & RTLOGFLAGS_DISABLED)
+        pLoggerInt = NULL;
+    else
+    {
+        uint32_t const fFlags = RT_LO_U16(fFlagsAndGroup);
+        uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
+        if (   iGroup != UINT16_MAX
+             && (   (pLoggerInt->afGroups[iGroup < pLoggerInt->cGroups ? iGroup : 0] & (fFlags | RTLOGGRPFLAGS_ENABLED))
+                 != (fFlags | RTLOGGRPFLAGS_ENABLED)))
+            pLoggerInt = NULL;
+    }
+    return pLoggerInt;
+}
+
+
 RTDECL(PRTLOGGER)   RTLogDefaultInstanceEx(uint32_t fFlagsAndGroup)
 {
-    PRTLOGGER pLogger = rtLogDefaultInstanceCommon();
-    if (pLogger)
-    {
-        if (pLogger->fFlags & RTLOGFLAGS_DISABLED)
-            pLogger = NULL;
-        else
-        {
-            uint16_t const fFlags = RT_LO_U16(fFlagsAndGroup);
-            uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
-            if (   iGroup != UINT16_MAX
-                 && (   (pLogger->afGroups[iGroup < pLogger->cGroups ? iGroup : 0] & (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED))
-                     != (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED)))
-                pLogger = NULL;
-        }
-    }
-    return pLogger;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)rtLogDefaultInstanceCommon();
+    if (pLoggerInt)
+        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
+    AssertCompileMemberOffset(RTLOGGERINTERNAL, Core, 0);
+    return (PRTLOGGER)pLoggerInt;
 }
 RT_EXPORT_SYMBOL(RTLogDefaultInstanceEx);
@@ -2786,20 +3265,9 @@
 RTDECL(PRTLOGGER) RTLogGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
 {
-    PRTLOGGER pLogger = rtLogGetDefaultInstanceCommon();
-    if (pLogger)
-    {
-        if (pLogger->fFlags & RTLOGFLAGS_DISABLED)
-            pLogger = NULL;
-        else
-        {
-            uint32_t const fFlags = RT_LO_U16(fFlagsAndGroup);
-            uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
-            if (   iGroup != UINT16_MAX
-                 && (   (pLogger->afGroups[iGroup < pLogger->cGroups ? iGroup : 0] & (fFlags | RTLOGGRPFLAGS_ENABLED))
-                     != (fFlags | RTLOGGRPFLAGS_ENABLED)))
-                pLogger = NULL;
-        }
-    }
-    return pLogger;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)rtLogGetDefaultInstanceCommon();
+    if (pLoggerInt)
+        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
+    AssertCompileMemberOffset(RTLOGGERINTERNAL, Core, 0);
+    return (PRTLOGGER)pLoggerInt;
 }
 RT_EXPORT_SYMBOL(RTLogGetDefaultInstanceEx);
@@ -2908,4 +3376,65 @@
 
 
+RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstance(void)
+{
+#ifdef IN_RC
+    return &g_RelLogger;
+#else /* !IN_RC */
+    return g_pRelLogger;
+#endif /* !IN_RC */
+}
+RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstance);
+
+
+RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
+{
+#ifdef IN_RC
+    PRTLOGGERINTERNAL pLoggerInt = &g_RelLogger;
+#else
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)g_pRelLogger;
+#endif
+    if (pLoggerInt)
+        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
+    return (PRTLOGGER)pLoggerInt;
+}
+RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstanceEx);
+
+
+#ifndef IN_RC
+/**
+ * Sets the default logger instance.
+ *
+ * @returns iprt status code.
+ * @param   pLogger     The new default release logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger)
+{
+    return ASMAtomicXchgPtrT(&g_pRelLogger, pLogger, PRTLOGGER);
+}
+RT_EXPORT_SYMBOL(RTLogRelSetDefaultInstance);
+#endif /* !IN_RC */
+
+
+/**
+ *
+ * This is the 2nd half of what RTLogGetDefaultInstanceEx() and
+ * RTLogRelGetDefaultInstanceEx() does.
+ *
+ * @returns If the group has the specified flags enabled @a pLogger will be
+ *          returned returned.  Otherwise NULL is returned.
+ * @param   pLogger         The logger.  NULL is NULL.
+ * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
+ *                          the high 16 bits.
+ */
+RTDECL(PRTLOGGER)   RTLogCheckGroupFlags(PRTLOGGER pLogger, uint32_t fFlagsAndGroup)
+{
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    if (pLoggerInt)
+        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
+    return (PRTLOGGER)pLoggerInt;
+}
+RT_EXPORT_SYMBOL(RTLogCheckGroupFlags);
+
+
 /**
  * Write to a logger instance.
@@ -2938,13 +3467,14 @@
 RTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
 {
-    int rc;
+    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
+    int               rc;
 
     /*
      * A NULL logger means default instance.
      */
-    if (!pLogger)
-    {
-        pLogger = RTLogDefaultInstance();
-        if (!pLogger)
+    if (!pLoggerInt)
+    {
+        pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
+        if (!pLoggerInt)
             return;
     }
@@ -2953,5 +3483,5 @@
      * Validate and correct iGroup.
      */
-    if (iGroup != ~0U && iGroup >= pLogger->cGroups)
+    if (iGroup != ~0U && iGroup >= pLoggerInt->cGroups)
         iGroup = 0;
 
@@ -2959,12 +3489,12 @@
      * If no output, then just skip it.
      */
-    if (    (pLogger->fFlags & RTLOGFLAGS_DISABLED)
+    if (    (pLoggerInt->fFlags & RTLOGFLAGS_DISABLED)
 #ifndef IN_RC
-        || !pLogger->fDestFlags
+        || !pLoggerInt->fDestFlags
 #endif
         || !pszFormat || !*pszFormat)
         return;
     if (    iGroup != ~0U
-        &&  (pLogger->afGroups[iGroup] & (fFlags | RTLOGGRPFLAGS_ENABLED)) != (fFlags | RTLOGGRPFLAGS_ENABLED))
+        &&  (pLoggerInt->afGroups[iGroup] & (fFlags | RTLOGGRPFLAGS_ENABLED)) != (fFlags | RTLOGGRPFLAGS_ENABLED))
         return;
 
@@ -2972,10 +3502,10 @@
      * Acquire logger instance sem.
      */
-    rc = rtlogLock(pLogger);
+    rc = rtlogLock(pLoggerInt);
     if (RT_FAILURE(rc))
     {
 #ifdef IN_RING0
-        if (pLogger->fDestFlags & ~RTLOGDEST_FILE)
-            rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, pLogger->pInt, pszFormat, args);
+        if (pLoggerInt->fDestFlags & ~RTLOGDEST_FILE)
+            rtR0LogLoggerExFallback(pLoggerInt->fDestFlags, pLoggerInt->fFlags, pLoggerInt, pszFormat, args);
 #endif
         return;
@@ -2986,32 +3516,31 @@
      */
 #ifndef IN_RC
-    if (RT_UNLIKELY(   (pLogger->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
-                    && iGroup < pLogger->cGroups
-                    && (pLogger->afGroups[iGroup] & RTLOGGRPFLAGS_RESTRICT)
-                    && ++pLogger->pInt->pacEntriesPerGroup[iGroup] >= pLogger->pInt->cMaxEntriesPerGroup ))
-    {
-        uint32_t cEntries = pLogger->pInt->pacEntriesPerGroup[iGroup];
-        if (cEntries > pLogger->pInt->cMaxEntriesPerGroup)
-            pLogger->pInt->pacEntriesPerGroup[iGroup] = cEntries - 1;
+    if (RT_UNLIKELY(   (pLoggerInt->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+                    && iGroup < pLoggerInt->cGroups
+                    && (pLoggerInt->afGroups[iGroup] & RTLOGGRPFLAGS_RESTRICT)
+                    && ++pLoggerInt->pacEntriesPerGroup[iGroup] >= pLoggerInt->cMaxEntriesPerGroup ))
+    {
+        uint32_t cEntries = pLoggerInt->pacEntriesPerGroup[iGroup];
+        if (cEntries > pLoggerInt->cMaxEntriesPerGroup)
+            pLoggerInt->pacEntriesPerGroup[iGroup] = cEntries - 1;
         else
         {
-            rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
-            if (   pLogger->pInt->papszGroups
-                && pLogger->pInt->papszGroups[iGroup])
-                rtlogLoggerExFLocked(pLogger, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",
-                                     cEntries, pLogger->pInt->papszGroups[iGroup], iGroup);
+            rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);
+            if (   pLoggerInt->papszGroups
+                && pLoggerInt->papszGroups[iGroup])
+                rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",
+                                     cEntries, pLoggerInt->papszGroups[iGroup], iGroup);
             else
-                rtlogLoggerExFLocked(pLogger, fFlags, iGroup, "%u messages from group #%u, muting it.\n",
-                                     cEntries, iGroup);
+                rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group #%u, muting it.\n", cEntries, iGroup);
         }
     }
     else
 #endif
-        rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
+        rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);
 
     /*
      * Release the semaphore.
      */
-    rtlogUnlock(pLogger);
+    rtlogUnlock(pLoggerInt);
 }
 RT_EXPORT_SYMBOL(RTLogLoggerExV);
@@ -3211,41 +3740,41 @@
  * Opens/creates the log file.
  *
- * @param   pLogger         The logger instance to update. NULL is not allowed!
+ * @param   pLoggerInt      The logger instance to update. NULL is not allowed!
  * @param   pErrInfo        Where to return extended error information.
  *                          Optional.
  */
-static int rtlogFileOpen(PRTLOGGER pLogger, PRTERRINFO pErrInfo)
+static int rtlogFileOpen(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
 {
     uint32_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_NONE;
-    if (pLogger->fFlags & RTLOGFLAGS_APPEND)
+    if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
         fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND;
     else
     {
-        RTFileDelete(pLogger->pInt->szFilename);
+        RTFileDelete(pLoggerInt->szFilename);
         fOpen |= RTFILE_O_CREATE;
     }
-    if (pLogger->fFlags & RTLOGFLAGS_WRITE_THROUGH)
+    if (pLoggerInt->fFlags & RTLOGFLAGS_WRITE_THROUGH)
         fOpen |= RTFILE_O_WRITE_THROUGH;
-    if (pLogger->fDestFlags & RTLOGDEST_F_NO_DENY)
+    if (pLoggerInt->fDestFlags & RTLOGDEST_F_NO_DENY)
         fOpen = (fOpen & ~RTFILE_O_DENY_NONE) | RTFILE_O_DENY_NOT_DELETE;
 
     unsigned cBackoff = 0;
-    int rc = RTFileOpen(&pLogger->pInt->hFile, pLogger->pInt->szFilename, fOpen);
+    int rc = RTFileOpen(&pLoggerInt->hFile, pLoggerInt->szFilename, fOpen);
     while (   (   rc == VERR_SHARING_VIOLATION
-               || (rc == VERR_ALREADY_EXISTS && !(pLogger->fFlags & RTLOGFLAGS_APPEND)))
+               || (rc == VERR_ALREADY_EXISTS && !(pLoggerInt->fFlags & RTLOGFLAGS_APPEND)))
            && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
     {
         RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
-        if (!(pLogger->fFlags & RTLOGFLAGS_APPEND))
-            RTFileDelete(pLogger->pInt->szFilename);
-        rc = RTFileOpen(&pLogger->pInt->hFile, pLogger->pInt->szFilename, fOpen);
+        if (!(pLoggerInt->fFlags & RTLOGFLAGS_APPEND))
+            RTFileDelete(pLoggerInt->szFilename);
+        rc = RTFileOpen(&pLoggerInt->hFile, pLoggerInt->szFilename, fOpen);
     }
     if (RT_SUCCESS(rc))
     {
-        rc = RTFileQuerySize(pLogger->pInt->hFile, &pLogger->pInt->cbHistoryFileWritten);
+        rc = RTFileQuerySize(pLoggerInt->hFile, &pLoggerInt->cbHistoryFileWritten);
         if (RT_FAILURE(rc))
         {
             /* Don't complain if this fails, assume the file is empty. */
-            pLogger->pInt->cbHistoryFileWritten = 0;
+            pLoggerInt->cbHistoryFileWritten = 0;
             rc = VINF_SUCCESS;
         }
@@ -3253,6 +3782,6 @@
     else
     {
-        pLogger->pInt->hFile = NIL_RTFILE;
-        RTErrInfoSetF(pErrInfo, rc, N_("could not open file '%s' (fOpen=%#x)"), pLogger->pInt->szFilename, fOpen);
+        pLoggerInt->hFile = NIL_RTFILE;
+        RTErrInfoSetF(pErrInfo, rc, N_("could not open file '%s' (fOpen=%#x)"), pLoggerInt->szFilename, fOpen);
     }
     return rc;
@@ -3265,5 +3794,5 @@
  * Used by the rtlogFlush() function as well as RTLogCreateExV.
  *
- * @param   pLogger     The logger instance to update. NULL is not allowed!
+ * @param   pLoggerInt  The logger instance to update. NULL is not allowed!
  * @param   uTimeSlot   Current time slot (for tikme based rotation).
  * @param   fFirst      Flag whether this is the beginning of logging, i.e.
@@ -3272,13 +3801,13 @@
  * @param   pErrInfo    Where to return extended error information. Optional.
  */
-static void rtlogRotate(PRTLOGGER pLogger, uint32_t uTimeSlot, bool fFirst, PRTERRINFO pErrInfo)
+static void rtlogRotate(PRTLOGGERINTERNAL pLoggerInt, uint32_t uTimeSlot, bool fFirst, PRTERRINFO pErrInfo)
 {
     /* Suppress rotating empty log files simply because the time elapsed. */
-    if (RT_UNLIKELY(!pLogger->pInt->cbHistoryFileWritten))
-        pLogger->pInt->uHistoryTimeSlotStart = uTimeSlot;
+    if (RT_UNLIKELY(!pLoggerInt->cbHistoryFileWritten))
+        pLoggerInt->uHistoryTimeSlotStart = uTimeSlot;
 
     /* Check rotation condition: file still small enough and not too old? */
-    if (RT_LIKELY(   pLogger->pInt->cbHistoryFileWritten < pLogger->pInt->cbHistoryFileMax
-                  && uTimeSlot == pLogger->pInt->uHistoryTimeSlotStart))
+    if (RT_LIKELY(   pLoggerInt->cbHistoryFileWritten < pLoggerInt->cbHistoryFileMax
+                  && uTimeSlot == pLoggerInt->uHistoryTimeSlotStart))
         return;
 
@@ -3288,6 +3817,6 @@
      * rotation would cause severe trouble otherwise.
      */
-    uint32_t const fSavedFlags = pLogger->fFlags;
-    pLogger->fFlags |= RTLOGFLAGS_DISABLED;
+    uint32_t const fSavedFlags = pLoggerInt->fFlags;
+    pLoggerInt->fFlags |= RTLOGFLAGS_DISABLED;
 
     /*
@@ -3295,24 +3824,24 @@
      * chatty phase logging we could run into endless rotation.
      */
-    uint32_t const cSavedHistory = pLogger->pInt->cHistory;
-    pLogger->pInt->cHistory = 0;
+    uint32_t const cSavedHistory = pLoggerInt->cHistory;
+    pLoggerInt->cHistory = 0;
 
     /*
      * Close the old log file.
      */
-    if (pLogger->pInt->hFile != NIL_RTFILE)
+    if (pLoggerInt->hFile != NIL_RTFILE)
     {
         /* Use the callback to generate some final log contents, but only if
          * this is a rotation with a fully set up logger. Leave the other case
          * to the RTLogCreateExV function. */
-        if (pLogger->pInt->pfnPhase && !fFirst)
-        {
-            uint32_t fODestFlags = pLogger->fDestFlags;
-            pLogger->fDestFlags &= RTLOGDEST_FILE;
-            pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
-            pLogger->fDestFlags = fODestFlags;
-        }
-        RTFileClose(pLogger->pInt->hFile);
-        pLogger->pInt->hFile = NIL_RTFILE;
+        if (pLoggerInt->pfnPhase && !fFirst)
+        {
+            uint32_t fODestFlags = pLoggerInt->fDestFlags;
+            pLoggerInt->fDestFlags &= RTLOGDEST_FILE;
+            pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
+            pLoggerInt->fDestFlags = fODestFlags;
+        }
+        RTFileClose(pLoggerInt->hFile);
+        pLoggerInt->hFile = NIL_RTFILE;
     }
 
@@ -3324,12 +3853,12 @@
         for (uint32_t i = cSavedHistory - 1; i + 1 > 0; i--)
         {
-            char szOldName[sizeof(pLogger->pInt->szFilename) + 32];
+            char szOldName[sizeof(pLoggerInt->szFilename) + 32];
             if (i > 0)
-                RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLogger->pInt->szFilename, i);
+                RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLoggerInt->szFilename, i);
             else
-                RTStrCopy(szOldName, sizeof(szOldName), pLogger->pInt->szFilename);
-
-            char szNewName[sizeof(pLogger->pInt->szFilename) + 32];
-            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLogger->pInt->szFilename, i + 1);
+                RTStrCopy(szOldName, sizeof(szOldName), pLoggerInt->szFilename);
+
+            char szNewName[sizeof(pLoggerInt->szFilename) + 32];
+            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLoggerInt->szFilename, i + 1);
 
             unsigned cBackoff = 0;
@@ -3351,6 +3880,6 @@
         for (uint32_t i = cSavedHistory + 1; ; i++)
         {
-            char szExcessName[sizeof(pLogger->pInt->szFilename) + 32];
-            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLogger->pInt->szFilename, i);
+            char szExcessName[sizeof(pLoggerInt->szFilename) + 32];
+            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLoggerInt->szFilename, i);
             int rc = RTFileDelete(szExcessName);
             if (RT_FAILURE(rc))
@@ -3362,7 +3891,7 @@
      * Update logger state and create new log file.
      */
-    pLogger->pInt->cbHistoryFileWritten = 0;
-    pLogger->pInt->uHistoryTimeSlotStart = uTimeSlot;
-    rtlogFileOpen(pLogger, pErrInfo);
+    pLoggerInt->cbHistoryFileWritten = 0;
+    pLoggerInt->uHistoryTimeSlotStart = uTimeSlot;
+    rtlogFileOpen(pLoggerInt, pErrInfo);
 
     /*
@@ -3371,15 +3900,15 @@
      * RTLogCreateExV function.
      */
-    if (pLogger->pInt->pfnPhase && !fFirst)
-    {
-        uint32_t const fSavedDestFlags = pLogger->fDestFlags;
-        pLogger->fDestFlags &= RTLOGDEST_FILE;
-        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
-        pLogger->fDestFlags = fSavedDestFlags;
+    if (pLoggerInt->pfnPhase && !fFirst)
+    {
+        uint32_t const fSavedDestFlags = pLoggerInt->fDestFlags;
+        pLoggerInt->fDestFlags &= RTLOGDEST_FILE;
+        pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
+        pLoggerInt->fDestFlags = fSavedDestFlags;
     }
 
     /* Restore saved values. */
-    pLogger->pInt->cHistory = cSavedHistory;
-    pLogger->fFlags         = fSavedFlags;
+    pLoggerInt->cHistory = cSavedHistory;
+    pLoggerInt->fFlags   = fSavedFlags;
 }
 
@@ -3391,30 +3920,30 @@
  *
  * @returns IPRT status code.
- * @param   pLogger             The logger.
+ * @param   pLoggerInt          The logger.
  * @param   pErrInfo            Where to return extended error information.
  *                              Optional.
  */
-static int rtR3LogOpenFileDestination(PRTLOGGER pLogger, PRTERRINFO pErrInfo)
+static int rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
 {
     int rc;
-    if (pLogger->fFlags & RTLOGFLAGS_APPEND)
-    {
-        rc = rtlogFileOpen(pLogger, pErrInfo);
+    if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
+    {
+        rc = rtlogFileOpen(pLoggerInt, pErrInfo);
 
         /* Rotate in case of appending to a too big log file,
            otherwise this simply doesn't do anything. */
-        rtlogRotate(pLogger, 0, true /* fFirst */, pErrInfo);
+        rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
     }
     else
     {
         /* Force rotation if it is configured. */
-        pLogger->pInt->cbHistoryFileWritten = UINT64_MAX;
-        rtlogRotate(pLogger, 0, true /* fFirst */, pErrInfo);
+        pLoggerInt->cbHistoryFileWritten = UINT64_MAX;
+        rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
 
         /* If the file is not open then rotation is not set up. */
-        if (pLogger->pInt->hFile == NIL_RTFILE)
-        {
-            pLogger->pInt->cbHistoryFileWritten = 0;
-            rc = rtlogFileOpen(pLogger, pErrInfo);
+        if (pLoggerInt->hFile == NIL_RTFILE)
+        {
+            pLoggerInt->cbHistoryFileWritten = 0;
+            rc = rtlogFileOpen(pLoggerInt, pErrInfo);
         }
         else
@@ -3433,25 +3962,35 @@
  * Used by the RTLogFlush() function.
  *
- * @param   pLogger     The logger instance to write to. NULL is not allowed!
+ * @param   pLoggerInt  The logger instance to write to. NULL is not allowed!
  * @param   fNeedSpace  Set if the caller assumes space will be made available.
  */
-static void rtlogFlush(PRTLOGGER pLogger, bool fNeedSpace)
-{
-    uint32_t const cchScratch = pLogger->offScratch;
-    if (cchScratch == 0)
+static void rtlogFlush(PRTLOGGERINTERNAL pLoggerInt, bool fNeedSpace)
+{
+    PRTLOGBUFFERDESC const pBufDesc   = pLoggerInt->pBufDesc;
+    uint32_t               cchToFlush = pBufDesc->offBuf;
+    char * const           pchToFlush = pBufDesc->pchBuf;
+    uint32_t const         cbBuf      = pBufDesc->cbBuf;
+    Assert(pBufDesc->u32Magic == RTLOGBUFFERDESC_MAGIC);
+
+    NOREF(fNeedSpace);
+    if (cchToFlush == 0)
         return; /* nothing to flush. */
-    NOREF(fNeedSpace);
-
-#ifndef IN_RC
+
+    AssertPtrReturnVoid(pchToFlush);
+    AssertReturnVoid(cbBuf > 0);
+    AssertMsgStmt(cchToFlush < cbBuf, ("%#x vs %#x\n", cchToFlush, cbBuf), cchToFlush = cbBuf - 1);
+
     /*
      * If the ring buffer is active, the other destinations are only written
      * to when the ring buffer is flushed by RTLogFlush().
      */
-    if (   (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
-        && pLogger->pInt
-        && pLogger->pInt->pszRingBuf /* paraoia */)
-    {
-        rtLogRingBufWrite(pLogger->pInt, pLogger->achScratch, pLogger->offScratch);
-        pLogger->offScratch = 0; /* empty the buffer. */
+    if (   (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF)
+        && pLoggerInt->pszRingBuf /* paranoia */)
+    {
+        rtLogRingBufWrite(pLoggerInt, pchToFlush, cchToFlush);
+
+        /* empty the buffer. */
+        pBufDesc->offBuf = 0;
+        *pchToFlush      = '\0';
     }
     /*
@@ -3460,59 +3999,58 @@
      */
     else
-# ifdef IN_RING3
-        if (!(pLogger->fDestFlags & RTLOGDEST_F_DELAY_FILE))
-# endif
+#ifdef IN_RING3
+         if (!(pLoggerInt->fDestFlags & RTLOGDEST_F_DELAY_FILE))
 #endif
     {
         /* Make sure the string is terminated.  On Windows, RTLogWriteDebugger
            will get upset if it isn't. */
-        if (RT_LIKELY(cchScratch < sizeof(pLogger->achScratch)))
-            pLogger->achScratch[cchScratch] = '\0';
-        else
-            AssertFailed();
-
-#ifndef IN_RC
-        if (pLogger->fDestFlags & RTLOGDEST_USER)
-            RTLogWriteUser(pLogger->achScratch, cchScratch);
-
-        if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER)
-            RTLogWriteDebugger(pLogger->achScratch, cchScratch);
-
-# ifdef IN_RING3
-        if ((pLogger->fDestFlags & (RTLOGDEST_FILE | RTLOGDEST_RINGBUF)) == RTLOGDEST_FILE)
-        {
-            if (pLogger->pInt->hFile != NIL_RTFILE)
+        pchToFlush[cchToFlush] = '\0';
+
+        if (pLoggerInt->fDestFlags & RTLOGDEST_USER)
+            RTLogWriteUser(pchToFlush, cchToFlush);
+
+        if (pLoggerInt->fDestFlags & RTLOGDEST_DEBUGGER)
+            RTLogWriteDebugger(pchToFlush, cchToFlush);
+
+#ifdef IN_RING3
+        if ((pLoggerInt->fDestFlags & (RTLOGDEST_FILE | RTLOGDEST_RINGBUF)) == RTLOGDEST_FILE)
+        {
+            if (pLoggerInt->hFile != NIL_RTFILE)
             {
-                RTFileWrite(pLogger->pInt->hFile, pLogger->achScratch, cchScratch, NULL);
-                if (pLogger->fFlags & RTLOGFLAGS_FLUSH)
-                    RTFileFlush(pLogger->pInt->hFile);
+                RTFileWrite(pLoggerInt->hFile, pchToFlush, cchToFlush, NULL);
+                if (pLoggerInt->fFlags & RTLOGFLAGS_FLUSH)
+                    RTFileFlush(pLoggerInt->hFile);
             }
-            if (pLogger->pInt->cHistory)
-                pLogger->pInt->cbHistoryFileWritten += cchScratch;
-        }
-# endif
-
-        if (pLogger->fDestFlags & RTLOGDEST_STDOUT)
-            RTLogWriteStdOut(pLogger->achScratch, cchScratch);
-
-        if (pLogger->fDestFlags & RTLOGDEST_STDERR)
-            RTLogWriteStdErr(pLogger->achScratch, cchScratch);
-
-# if (defined(IN_RING0) || defined(IN_RC)) && !defined(LOG_NO_COM)
-        if (pLogger->fDestFlags & RTLOGDEST_COM)
-            RTLogWriteCom(pLogger->achScratch, cchScratch);
-# endif
-#endif /* !IN_RC */
-
-#ifdef IN_RC
-        if (pLogger->pfnFlush)
-            pLogger->pfnFlush(pLogger);
-#else
-        if (pLogger->pInt->pfnFlush)
-            pLogger->pInt->pfnFlush(pLogger);
+            if (pLoggerInt->cHistory)
+                pLoggerInt->cbHistoryFileWritten += cchToFlush;
+        }
 #endif
 
+        if (pLoggerInt->fDestFlags & RTLOGDEST_STDOUT)
+            RTLogWriteStdOut(pchToFlush, cchToFlush);
+
+        if (pLoggerInt->fDestFlags & RTLOGDEST_STDERR)
+            RTLogWriteStdErr(pchToFlush, cchToFlush);
+
+#if (defined(IN_RING0) || defined(IN_RC)) && !defined(LOG_NO_COM)
+        if (pLoggerInt->fDestFlags & RTLOGDEST_COM)
+            RTLogWriteCom(pchToFlush, cchToFlush);
+#endif
+
+        if (pLoggerInt->pfnFlush)
+        {
+            /** @todo implement asynchronous buffer switching protocol. */
+            bool fDone;
+            if (pBufDesc->pAux)
+                pBufDesc->pAux->offBuf = cchToFlush;
+            fDone = pLoggerInt->pfnFlush(&pLoggerInt->Core, pBufDesc);
+            Assert(fDone == true); RT_NOREF(fDone);
+        }
+
         /* empty the buffer. */
-        pLogger->offScratch = 0;
+        pBufDesc->offBuf = 0;
+        if (pBufDesc->pAux)
+            pBufDesc->pAux->offBuf = 0;
+        *pchToFlush      = '\0';
 
 #ifdef IN_RING3
@@ -3522,7 +4060,7 @@
          * and footer messages.
          */
-        if (   (pLogger->fDestFlags & RTLOGDEST_FILE)
-            && pLogger->pInt->cHistory)
-            rtlogRotate(pLogger, RTTimeProgramSecTS() / pLogger->pInt->cSecsHistoryTimeSlot, false /*fFirst*/, NULL /*pErrInfo*/);
+        if (   pLoggerInt->cHistory > 0
+            && (pLoggerInt->fDestFlags & RTLOGDEST_FILE))
+            rtlogRotate(pLoggerInt, RTTimeProgramSecTS() / pLoggerInt->cSecsHistoryTimeSlot, false /*fFirst*/, NULL /*pErrInfo*/);
 #endif
     }
@@ -3534,17 +4072,20 @@
          * buffer and insert a message indicating that we've dropped output.
          */
-        uint32_t offHalf = sizeof(pLogger->achScratch) / 2;
-        if (cchScratch > offHalf)
-        {
-            if (pLogger->fFlags & RTLOGFLAGS_USECRLF)
-                pLogger->achScratch[offHalf++] = '\r';
-            static const char s_szDropMsg[] = "\n[DROP DROP DROP]";
-            memcpy(&pLogger->achScratch[offHalf], RT_STR_TUPLE(s_szDropMsg));
-            offHalf += sizeof(s_szDropMsg) - 1;
-            if (pLogger->fFlags & RTLOGFLAGS_USECRLF)
-                pLogger->achScratch[offHalf++] = '\r';
-            pLogger->achScratch[offHalf++] = '\n';
-
-            pLogger->offScratch = offHalf;
+        uint32_t offHalf = cbBuf / 2;
+        if (cchToFlush > offHalf)
+        {
+            static const char s_szDropMsgLf[]   = "\n[DROP DROP DROP]\n";
+            static const char s_szDropMsgCrLf[] = "\r\n[DROP DROP DROP]\r\n";
+            if (!(pLoggerInt->fFlags & RTLOGFLAGS_USECRLF))
+            {
+                memcpy(&pchToFlush[offHalf], RT_STR_TUPLE(s_szDropMsgLf));
+                offHalf += sizeof(s_szDropMsgLf) - 1;
+            }
+            else
+            {
+                memcpy(&pchToFlush[offHalf], RT_STR_TUPLE(s_szDropMsgCrLf));
+                offHalf += sizeof(s_szDropMsgCrLf) - 1;
+            }
+            pBufDesc->offBuf = offHalf;
         }
     }
@@ -3559,5 +4100,5 @@
 static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars)
 {
-    PRTLOGGER pLogger = (PRTLOGGER)pv;
+    PRTLOGGERINTERNAL pLoggerInt  = (PRTLOGGERINTERNAL)pv;
     if (cbChars)
     {
@@ -3565,35 +4106,68 @@
         for (;;)
         {
-#if defined(DEBUG) && defined(IN_RING3)
-            /* sanity */
-            if (pLogger->offScratch >= sizeof(pLogger->achScratch))
+            PRTLOGBUFFERDESC const pBufDesc = pLoggerInt->pBufDesc;
+            if (pBufDesc->offBuf < pBufDesc->cbBuf)
             {
-                fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
-                        pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
+                /* how much */
+                char    *pchBuf = pBufDesc->pchBuf;
+                uint32_t offBuf = pBufDesc->offBuf;
+                size_t   cb     = pBufDesc->cbBuf - offBuf - 1;
+                if (cb > cbChars)
+                    cb = cbChars;
+
+                switch (cb)
+                {
+                    default:
+                        memcpy(&pchBuf[offBuf], pachChars, cb);
+                        pBufDesc->offBuf   = offBuf + (uint32_t)cb;
+                        cbRet             += cb;
+                        cbChars           -= cb;
+                        if (cbChars <= 0)
+                            return cbRet;
+                        pachChars += cb;
+                        break;
+
+                    case 1:
+                        pchBuf[offBuf]     = pachChars[0];
+                        pBufDesc->offBuf   = offBuf + 1;
+                        if (cbChars == 1)
+                            return cbRet + 1;
+                        cbChars   -= 1;
+                        pachChars += 1;
+                        break;
+
+                    case 2:
+                        pchBuf[offBuf]     = pachChars[0];
+                        pchBuf[offBuf + 1] = pachChars[1];
+                        pBufDesc->offBuf   = offBuf + 2;
+                        if (cbChars == 2)
+                            return cbRet + 2;
+                        cbChars   -= 2;
+                        pachChars += 2;
+                        break;
+
+                    case 3:
+                        pchBuf[offBuf]     = pachChars[0];
+                        pchBuf[offBuf + 1] = pachChars[1];
+                        pchBuf[offBuf + 2] = pachChars[2];
+                        pBufDesc->offBuf   = offBuf + 3;
+                        if (cbChars == 3)
+                            return cbRet + 3;
+                        cbChars   -= 3;
+                        pachChars += 3;
+                        break;
+                }
+
+            }
+#if defined(RT_STRICT) && defined(IN_RING3)
+            else
+            {
+                fprintf(stderr, "pBufDesc->offBuf >= pBufDesc->cbBuf (%#x >= %#x)\n", pBufDesc->offBuf, pBufDesc->cbBuf);
                 AssertBreakpoint(); AssertBreakpoint();
             }
 #endif
 
-            /* how much */
-            size_t cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
-            if (cb > cbChars)
-                cb = cbChars;
-
-            /* copy */
-            memcpy(&pLogger->achScratch[pLogger->offScratch], pachChars, cb);
-
-            /* advance */
-            pLogger->offScratch += (uint32_t)cb;
-            cbRet += cb;
-            cbChars -= cb;
-
-            /* done? */
-            if (cbChars <= 0)
-                return cbRet;
-
-            pachChars += cb;
-
             /* flush */
-            rtlogFlush(pLogger, true /*fNeedSpace*/);
+            rtlogFlush(pLoggerInt, true /*fNeedSpace*/);
         }
 
@@ -3606,5 +4180,6 @@
          * There's always space for a terminator, and it's not counted.
          */
-        pLogger->achScratch[pLogger->offScratch] = '\0';
+        PRTLOGBUFFERDESC const pBufDesc = pLoggerInt->pBufDesc;
+        pBufDesc->pchBuf[RT_MIN(pBufDesc->offBuf, pBufDesc->cbBuf - 1)] = '\0';
         return 0;
     }
@@ -3678,6 +4253,6 @@
 static DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars)
 {
-    PRTLOGOUTPUTPREFIXEDARGS    pArgs = (PRTLOGOUTPUTPREFIXEDARGS)pv;
-    PRTLOGGER                   pLogger = pArgs->pLogger;
+    PRTLOGOUTPUTPREFIXEDARGS    pArgs      = (PRTLOGOUTPUTPREFIXEDARGS)pv;
+    PRTLOGGERINTERNAL           pLoggerInt = pArgs->pLoggerInt;
     if (cbChars)
     {
@@ -3685,12 +4260,21 @@
         for (;;)
         {
-            uint32_t    offScratch = pLogger->offScratch;
-            size_t      cb         = sizeof(pLogger->achScratch) - offScratch - 1;
-            const char *pszNewLine;
-            char       *psz;
-#ifdef IN_RC
-            bool       *pfPendingPrefix = &pLogger->fPendingPrefix;
-#else
-            bool       *pfPendingPrefix = &pLogger->pInt->fPendingPrefix;
+            PRTLOGBUFFERDESC const  pBufDesc = pLoggerInt->pBufDesc;
+            char * const            pchBuf   = pBufDesc->pchBuf;
+            uint32_t const          cbBuf    = pBufDesc->cbBuf;
+            uint32_t                offBuf   = pBufDesc->offBuf;
+            size_t                  cb       = cbBuf - offBuf - 1;
+            const char             *pszNewLine;
+            char                   *psz;
+
+#if defined(RT_STRICT) && defined(IN_RING3)
+            /* sanity */
+            if (offBuf < cbBuf)
+            { /* likely */ }
+            else
+            {
+                fprintf(stderr, "offBuf >= cbBuf (%#x >= %#x)\n", offBuf, cbBuf);
+                AssertBreakpoint(); AssertBreakpoint();
+            }
 #endif
 
@@ -3698,27 +4282,16 @@
              * Pending prefix?
              */
-            if (*pfPendingPrefix)
+            if (pLoggerInt->fPendingPrefix)
             {
-                *pfPendingPrefix = false;
-
-#if defined(DEBUG) && defined(IN_RING3)
-                /* sanity */
-                if (offScratch >= sizeof(pLogger->achScratch))
-                {
-                    fprintf(stderr, "offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
-                            offScratch, (unsigned)sizeof(pLogger->achScratch));
-                    AssertBreakpoint(); AssertBreakpoint();
-                }
-#endif
-
                 /*
                  * Flush the buffer if there isn't enough room for the maximum prefix config.
                  * Max is 256, add a couple of extra bytes.  See CCH_PREFIX check way below.
                  */
-                if (cb < 256 + 16)
+                if (cb >= 256 + 16)
+                    pLoggerInt->fPendingPrefix = false;
+                else
                 {
-                    rtlogFlush(pLogger, true /*fNeedSpace*/);
-                    offScratch = pLogger->offScratch;
-                    cb = sizeof(pLogger->achScratch) - offScratch - 1;
+                    rtlogFlush(pLoggerInt, true /*fNeedSpace*/);
+                    continue;
                 }
 
@@ -3727,16 +4300,16 @@
                  * psz is pointing to the current position.
                  */
-                psz = &pLogger->achScratch[offScratch];
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TS)
+                psz = &pchBuf[offBuf];
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_TS)
                 {
                     uint64_t     u64    = RTTimeNanoTS();
                     int          iBase  = 16;
                     unsigned int fFlags = RTSTR_F_ZEROPAD;
-                    if (pLogger->fFlags & RTLOGFLAGS_DECIMAL_TS)
+                    if (pLoggerInt->fFlags & RTLOGFLAGS_DECIMAL_TS)
                     {
                         iBase = 10;
                         fFlags = 0;
                     }
-                    if (pLogger->fFlags & RTLOGFLAGS_REL_TS)
+                    if (pLoggerInt->fFlags & RTLOGFLAGS_REL_TS)
                     {
                         static volatile uint64_t s_u64LastTs;
@@ -3754,5 +4327,5 @@
 #define CCH_PREFIX_01   0 + 17
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TSC)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_TSC)
                 {
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
@@ -3763,10 +4336,10 @@
                     int          iBase  = 16;
                     unsigned int fFlags = RTSTR_F_ZEROPAD;
-                    if (pLogger->fFlags & RTLOGFLAGS_DECIMAL_TS)
+                    if (pLoggerInt->fFlags & RTLOGFLAGS_DECIMAL_TS)
                     {
                         iBase = 10;
                         fFlags = 0;
                     }
-                    if (pLogger->fFlags & RTLOGFLAGS_REL_TS)
+                    if (pLoggerInt->fFlags & RTLOGFLAGS_REL_TS)
                     {
                         static volatile uint64_t s_u64LastTsc;
@@ -3784,10 +4357,10 @@
 #define CCH_PREFIX_02   CCH_PREFIX_01 + 17
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_MS_PROG)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_MS_PROG)
                 {
 #if defined(IN_RING3) || defined(IN_RC)
                     uint64_t u64 = RTTimeProgramMilliTS();
 #else
-                    uint64_t u64 = (RTTimeNanoTS() - pLogger->pInt->nsR0ProgramStart) / RT_NS_1MS;
+                    uint64_t u64 = (RTTimeNanoTS() - pLoggerInt->nsR0ProgramStart) / RT_NS_1MS;
 #endif
                     /* 1E8 milliseconds = 27 hours */
@@ -3797,5 +4370,5 @@
 #define CCH_PREFIX_03   CCH_PREFIX_02 + 21
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TIME)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_TIME)
                 {
 #if defined(IN_RING3) || defined(IN_RING0)
@@ -3818,5 +4391,5 @@
 #define CCH_PREFIX_04   CCH_PREFIX_03 + (3+1+3+1+3+1+7+1)
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TIME_PROG)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_TIME_PROG)
                 {
 
@@ -3824,5 +4397,5 @@
                     uint64_t u64 = RTTimeProgramMicroTS();
 #else
-                    uint64_t u64 = (RTTimeNanoTS() - pLogger->pInt->nsR0ProgramStart) / RT_NS_1US;
+                    uint64_t u64 = (RTTimeNanoTS() - pLoggerInt->nsR0ProgramStart) / RT_NS_1US;
 
 #endif
@@ -3842,5 +4415,5 @@
 
 # if 0
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_DATETIME)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_DATETIME)
                 {
                     char szDate[32];
@@ -3857,5 +4430,5 @@
 # endif
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_PID)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_PID)
                 {
 #ifndef IN_RC
@@ -3869,5 +4442,5 @@
 #define CCH_PREFIX_07   CCH_PREFIX_06 + 9
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_TID)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_TID)
                 {
 #ifndef IN_RC
@@ -3881,5 +4454,5 @@
 #define CCH_PREFIX_08   CCH_PREFIX_07 + 17
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_THREAD)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_THREAD)
                 {
 #ifdef IN_RING3
@@ -3888,5 +4461,5 @@
                     const char *pszName = "EMT-RC";
 #else
-                    const char *pszName = pLogger->pInt->szR0ThreadName[0] ? pLogger->pInt->szR0ThreadName : "R0";
+                    const char *pszName = pLoggerInt->szR0ThreadName[0] ? pLoggerInt->szR0ThreadName : "R0";
 #endif
                     psz = rtLogStPNCpyPad(psz, pszName, 16, 8);
@@ -3894,5 +4467,5 @@
 #define CCH_PREFIX_09   CCH_PREFIX_08 + 17
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_CPUID)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_CPUID)
                 {
 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
@@ -3907,8 +4480,8 @@
 
 #ifndef IN_RC
-                if (    (pLogger->fFlags & RTLOGFLAGS_PREFIX_CUSTOM)
-                    &&  pLogger->pInt->pfnPrefix)
+                if (    (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_CUSTOM)
+                    &&  pLoggerInt->pfnPrefix)
                 {
-                    psz += pLogger->pInt->pfnPrefix(pLogger, psz, 31, pLogger->pInt->pvPrefixUserArg);
+                    psz += pLoggerInt->pfnPrefix(&pLoggerInt->Core, psz, 31, pLoggerInt->pvPrefixUserArg);
                     *psz++ = ' ';                                                               /* +32 */
                 }
@@ -3916,5 +4489,5 @@
 #define CCH_PREFIX_11   CCH_PREFIX_10 + 32
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_LOCK_COUNTS)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_LOCK_COUNTS)
                 {
 #ifdef IN_RING3 /** @todo implement these counters in ring-0 too? */
@@ -3941,5 +4514,5 @@
 #define CCH_PREFIX_12   CCH_PREFIX_11 + 8
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_FLAG_NO)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_FLAG_NO)
                 {
                     psz += RTStrFormatNumber(psz, pArgs->fFlags, 16, 8, 0, RTSTR_F_ZEROPAD);
@@ -3948,8 +4521,8 @@
 #define CCH_PREFIX_13   CCH_PREFIX_12 + 9
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_FLAG)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_FLAG)
                 {
 #ifdef IN_RING3
-                    const char *pszGroup = pArgs->iGroup != ~0U ? pLogger->pInt->papszGroups[pArgs->iGroup] : NULL;
+                    const char *pszGroup = pArgs->iGroup != ~0U ? pLoggerInt->papszGroups[pArgs->iGroup] : NULL;
 #else
                     const char *pszGroup = NULL;
@@ -3959,5 +4532,5 @@
 #define CCH_PREFIX_14   CCH_PREFIX_13 + 17
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_GROUP_NO)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_GROUP_NO)
                 {
                     if (pArgs->iGroup != ~0U)
@@ -3974,7 +4547,7 @@
 #define CCH_PREFIX_15   CCH_PREFIX_14 + 9
 
-                if (pLogger->fFlags & RTLOGFLAGS_PREFIX_GROUP)
+                if (pLoggerInt->fFlags & RTLOGFLAGS_PREFIX_GROUP)
                 {
-                    const unsigned fGrp = pLogger->afGroups[pArgs->iGroup != ~0U ? pArgs->iGroup : 0];
+                    const unsigned fGrp = pLoggerInt->afGroups[pArgs->iGroup != ~0U ? pArgs->iGroup : 0];
                     const char *pszGroup;
                     size_t cchGroup;
@@ -4009,25 +4582,14 @@
                  * Done, figure what we've used and advance the buffer and free size.
                  */
-                cb = psz - &pLogger->achScratch[offScratch];
-                AssertMsg(cb <= 223, ("%#zx (%zd) - fFlags=%#x\n", cb, cb, pLogger->fFlags));
-                pLogger->offScratch = offScratch += (uint32_t)cb;
-                cb = sizeof(pLogger->achScratch) - offScratch - 1;
+                AssertMsg(psz - &pchBuf[offBuf] <= 223,
+                          ("%#zx (%zd) - fFlags=%#x\n", psz - &pchBuf[offBuf], psz - &pchBuf[offBuf], pLoggerInt->fFlags));
+                pBufDesc->offBuf = offBuf = (uint32_t)(psz - pchBuf);
+                cb = cbBuf - offBuf - 1;
             }
             else if (cb <= 0)
             {
-                rtlogFlush(pLogger, true /*fNeedSpace*/);
-                offScratch = pLogger->offScratch;
-                cb = sizeof(pLogger->achScratch) - offScratch - 1;
+                rtlogFlush(pLoggerInt, true /*fNeedSpace*/);
+                continue;
             }
-
-#if defined(DEBUG) && defined(IN_RING3)
-            /* sanity */
-            if (offScratch >= sizeof(pLogger->achScratch))
-            {
-                fprintf(stderr, "offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
-                        offScratch, (unsigned)sizeof(pLogger->achScratch));
-                AssertBreakpoint(); AssertBreakpoint();
-            }
-#endif
 
             /* how much */
@@ -4039,32 +4601,35 @@
             if (pszNewLine)
             {
-                if (pLogger->fFlags & RTLOGFLAGS_USECRLF)
+                if (!(pLoggerInt->fFlags & RTLOGFLAGS_USECRLF))
+                {
+                    cb = pszNewLine - pachChars + 1;
+                    memcpy(&pchBuf[offBuf], pachChars, cb);
+                    pLoggerInt->fPendingPrefix = true;
+                }
+                else if (cbBuf - offBuf < (uintptr_t)(pszNewLine - pachChars + 2))
+                {
                     cb = pszNewLine - pachChars;
+                    memcpy(&pchBuf[offBuf], pachChars, cb);
+                    pchBuf[offBuf + cb++] = '\r';
+                    pchBuf[offBuf + cb++] = '\n';
+                    pachChars--;    /* Discount the extra '\r'. */
+                    cbChars++;      /* Discount the extra '\r'. */
+                    cbRet--;        /* Ditto. */
+                    pLoggerInt->fPendingPrefix = true;
+                }
                 else
                 {
-                    cb = pszNewLine - pachChars + 1;
-                    *pfPendingPrefix = true;
+                    /* Insufficient buffer space, leave the '\n' for the next iteration. */
+                    cb = pszNewLine - pachChars;
+                    memcpy(&pchBuf[offBuf], pachChars, cb);
                 }
             }
-
-            /* copy */
-            memcpy(&pLogger->achScratch[offScratch], pachChars, cb);
+            else
+                memcpy(&pchBuf[offBuf], pachChars, cb);
 
             /* advance */
-            pLogger->offScratch = offScratch += (uint32_t)cb;
-            cbRet += cb;
+            pBufDesc->offBuf = offBuf += (uint32_t)cb;
+            cbRet   += cb;
             cbChars -= cb;
-
-            if (    pszNewLine
-                &&  (pLogger->fFlags & RTLOGFLAGS_USECRLF)
-                &&  offScratch + 2 < sizeof(pLogger->achScratch))
-            {
-                memcpy(&pLogger->achScratch[offScratch], "\r\n", 2);
-                pLogger->offScratch = offScratch += 2;
-                cbRet++;
-                cbChars--;
-                cb++;
-                *pfPendingPrefix = true;
-            }
 
             /* done? */
@@ -4082,5 +4647,6 @@
          * There's always space for a terminator, and it's not counted.
          */
-        pLogger->achScratch[pLogger->offScratch] = '\0';
+        PRTLOGBUFFERDESC const pBufDesc = pLoggerInt->pBufDesc;
+        pBufDesc->pchBuf[RT_MIN(pBufDesc->offBuf, pBufDesc->cbBuf - 1)] = '\0';
         return 0;
     }
@@ -4094,5 +4660,5 @@
  * logging kind which is currently enabled before writing anything to the log.
  *
- * @param   pLogger     Pointer to logger instance. Must be non-NULL.
+ * @param   pLoggerInt  Pointer to logger instance. Must be non-NULL.
  * @param   fFlags      The logging flags.
  * @param   iGroup      The group.
@@ -4102,22 +4668,47 @@
  * @param   args        Format arguments.
  */
-static void rtlogLoggerExVLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
-{
-    /*
-     * Format the message and perhaps flush it.
-     */
-    if (pLogger->fFlags & (RTLOGFLAGS_PREFIX_MASK | RTLOGFLAGS_USECRLF))
+static void rtlogLoggerExVLocked(PRTLOGGERINTERNAL pLoggerInt, unsigned fFlags, unsigned iGroup,
+                                 const char *pszFormat, va_list args)
+{
+    /*
+     * If we've got an auxilary descriptor, check if the buffer was flushed.
+     */
+    PRTLOGBUFFERDESC    pBufDesc = pLoggerInt->pBufDesc;
+    PRTLOGBUFFERAUXDESC pAuxDesc = pBufDesc->pAux;
+    if (!pAuxDesc || !pAuxDesc->fFlushedIndicator)
+    { /* likely, except maybe for ring-0 */ }
+    else
+    {
+        pAuxDesc->fFlushedIndicator = false;
+        pBufDesc->offBuf        = 0;
+    }
+
+    /*
+     * Format the message.
+     */
+    if (pLoggerInt->fFlags & (RTLOGFLAGS_PREFIX_MASK | RTLOGFLAGS_USECRLF))
     {
         RTLOGOUTPUTPREFIXEDARGS OutputArgs;
-        OutputArgs.pLogger = pLogger;
-        OutputArgs.iGroup  = iGroup;
-        OutputArgs.fFlags  = fFlags;
+        OutputArgs.pLoggerInt = pLoggerInt;
+        OutputArgs.iGroup     = iGroup;
+        OutputArgs.fFlags     = fFlags;
         RTLogFormatV(rtLogOutputPrefixed, &OutputArgs, pszFormat, args);
     }
     else
-        RTLogFormatV(rtLogOutput, pLogger, pszFormat, args);
-    if (    !(pLogger->fFlags & RTLOGFLAGS_BUFFERED)
-        &&  pLogger->offScratch)
-        rtlogFlush(pLogger, false /*fNeedSpace*/);
+        RTLogFormatV(rtLogOutput, pLoggerInt, pszFormat, args);
+
+    /*
+     * Maybe flush the buffer and update the auxiliary descriptor if there is one.
+     */
+    pBufDesc = pLoggerInt->pBufDesc;  /* (the descriptor may have changed) */
+    if (    !(pLoggerInt->fFlags & RTLOGFLAGS_BUFFERED)
+        &&  pBufDesc->offBuf)
+        rtlogFlush(pLoggerInt, false /*fNeedSpace*/);
+    else
+    {
+        pAuxDesc = pBufDesc->pAux;
+        if (pAuxDesc)
+            pAuxDesc->offBuf = pBufDesc->offBuf;
+    }
 }
 
@@ -4127,5 +4718,5 @@
  * For calling rtlogLoggerExVLocked.
  *
- * @param   pLogger     The logger.
+ * @param   pLoggerInt  The logger.
  * @param   fFlags      The logging flags.
  * @param   iGroup      The group.
@@ -4135,9 +4726,9 @@
  * @param   ...         Format arguments.
  */
-static void rtlogLoggerExFLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...)
+static void rtlogLoggerExFLocked(PRTLOGGERINTERNAL pLoggerInt, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...)
 {
     va_list va;
     va_start(va, pszFormat);
-    rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, va);
+    rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, va);
     va_end(va);
 }
Index: /trunk/src/VBox/Runtime/common/log/logrel.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/log/logrel.cpp	(revision 90828)
+++ /trunk/src/VBox/Runtime/common/log/logrel.cpp	(revision 90829)
@@ -56,68 +56,4 @@
 # include <stdio.h>
 #endif
-
-
-/*********************************************************************************************************************************
-*   Global Variables                                                                                                             *
-*********************************************************************************************************************************/
-#ifdef IN_RC
-/** Default release logger instance. */
-extern "C" DECLIMPORT(RTLOGGERRC)   g_RelLogger;
-#else /* !IN_RC */
-/** Default release logger instance. */
-static PRTLOGGER                    g_pRelLogger;
-#endif /* !IN_RC */
-
-
-RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstance(void)
-{
-#ifdef IN_RC
-    return &g_RelLogger;
-#else /* !IN_RC */
-    return g_pRelLogger;
-#endif /* !IN_RC */
-}
-RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstance);
-
-
-RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
-{
-#ifdef IN_RC
-    PRTLOGGER pLogger = &g_RelLogger;
-#else /* !IN_RC */
-    PRTLOGGER pLogger = g_pRelLogger;
-#endif /* !IN_RC */
-    if (pLogger)
-    {
-        if (pLogger->fFlags & RTLOGFLAGS_DISABLED)
-            pLogger = NULL;
-        else
-        {
-            uint16_t const fFlags = RT_LO_U16(fFlagsAndGroup);
-            uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
-            if (   iGroup != UINT16_MAX
-                 && (   (pLogger->afGroups[iGroup < pLogger->cGroups ? iGroup : 0] & (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED))
-                     != (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED)))
-            pLogger = NULL;
-        }
-    }
-    return pLogger;
-}
-RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstanceEx);
-
-
-#ifndef IN_RC
-/**
- * Sets the default logger instance.
- *
- * @returns iprt status code.
- * @param   pLogger     The new default release logger instance.
- */
-RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger)
-{
-    return ASMAtomicXchgPtrT(&g_pRelLogger, pLogger, PRTLOGGER);
-}
-RT_EXPORT_SYMBOL(RTLogRelSetDefaultInstance);
-#endif /* !IN_RC */
 
 
Index: /trunk/src/VBox/Runtime/testcase/tstLog.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstLog.cpp	(revision 90828)
+++ /trunk/src/VBox/Runtime/testcase/tstLog.cpp	(revision 90829)
@@ -69,5 +69,5 @@
     {
 #if 0   /* Old tests: */
-        printf("tstLog: Requires manual inspection of the log output!\n");
+        RTTestIPrintf(RTTESTLVL_ALWAYS, "Requires manual inspection of the log output!\n");
         RTLogPrintf("%%Rrc %d: %Rrc\n", VERR_INVALID_PARAMETER, VERR_INVALID_PARAMETER);
         RTLogPrintf("%%Rrs %d: %Rrs\n", VERR_INVALID_PARAMETER, VERR_INVALID_PARAMETER);
Index: /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp	(revision 90829)
@@ -1325,14 +1325,5 @@
     PGMR0CleanupVM(pGVM);
     TMR0CleanupVM(pGVM);
-
-    AssertCompile(NIL_RTTHREADCTXHOOK == (RTTHREADCTXHOOK)0); /* Depends on zero initialized memory working for NIL at the moment. */
-    for (VMCPUID idCpu = 0; idCpu < pGVM->cCpus; idCpu++)
-    {
-        /** @todo Can we busy wait here for all thread-context hooks to be
-         *        deregistered before releasing (destroying) it? Only until we find a
-         *        solution for not deregistering hooks everytime we're leaving HMR0
-         *        context. */
-        VMMR0ThreadCtxHookDestroyForEmt(&pGVM->aCpus[idCpu]);
-    }
+    VMMR0CleanupVM(pGVM);
 }
 
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 90829)
@@ -55,4 +55,6 @@
 #include <iprt/assert.h>
 #include <iprt/crc.h>
+#include <iprt/mem.h>
+#include <iprt/memobj.h>
 #include <iprt/mp.h>
 #include <iprt/once.h>
@@ -141,4 +143,7 @@
 #endif
 RT_C_DECLS_END
+static int vmmR0UpdateLoggers(PGVM pGVM, VMCPUID idCpu, PVMMR0UPDATELOGGERSREQ pReq, bool fRelease);
+static FNRTLOGFLUSH vmmR0LogFlush;
+static FNRTLOGFLUSH vmmR0LogRelFlush;
 
 
@@ -365,4 +370,10 @@
 VMMR0_INT_DECL(void) VMMR0InitPerVMData(PGVM pGVM)
 {
+    pGVM->vmmr0.s.hMemObjLogger         = NIL_RTR0MEMOBJ;
+    pGVM->vmmr0.s.hMapObjLogger         = NIL_RTR0MEMOBJ;
+    pGVM->vmmr0.s.hMemObjReleaseLogger  = NIL_RTR0MEMOBJ;
+    pGVM->vmmr0.s.hMapObjReleaseLogger  = NIL_RTR0MEMOBJ;
+    pGVM->vmmr0.s.fCalledInitVm         = false;
+
     for (VMCPUID idCpu = 0; idCpu < pGVM->cCpus; idCpu++)
     {
@@ -378,4 +389,102 @@
 
 /**
+ * Helper for vmmR0InitLoggers
+ */
+static int vmmR0InitLoggerOne(PGVMCPU pGVCpu, bool fRelease, PVMMR0PERVCPULOGGER pR0Log, PVMMR3CPULOGGER pShared,
+                              uint32_t cbBuf, char *pchBuf, RTR3PTR pchBufR3)
+{
+    pR0Log->BufDesc.u32Magic    = RTLOGBUFFERDESC_MAGIC;
+    pR0Log->BufDesc.uReserved   = 0;
+    pR0Log->BufDesc.cbBuf       = cbBuf;
+    pR0Log->BufDesc.offBuf      = 0;
+    pR0Log->BufDesc.pchBuf      = pchBuf;
+    pR0Log->BufDesc.pAux        = &pShared->AuxDesc;
+
+    pShared->AuxDesc.fFlushedIndicator   = false;
+    pShared->AuxDesc.afPadding[0]        = 0;
+    pShared->AuxDesc.afPadding[1]        = 0;
+    pShared->AuxDesc.afPadding[2]        = 0;
+    pShared->AuxDesc.offBuf              = 0;
+    pShared->pchBufR3                    = pchBufR3;
+    pShared->cbBuf                       = cbBuf;
+
+    static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
+    int rc = RTLogCreateEx(&pR0Log->pLogger, fRelease ? "VBOX_RELEASE_LOG" : "VBOX_LOG", RTLOG_F_NO_LOCKING | RTLOGFLAGS_BUFFERED,
+                           "all", RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX,
+                           fRelease ? vmmR0LogRelFlush : vmmR0LogFlush, 1 /*cBufDescs*/, &pR0Log->BufDesc,
+                           RTLOGDEST_DUMMY,
+                           NULL /*pfnPhase*/, 0 /*cHistory*/, 0 /*cbHistoryFileMax*/, 0 /*cSecsHistoryTimeSlot*/,
+                           NULL /*pErrInfo*/, NULL /*pszFilenameFmt*/);
+    if (RT_SUCCESS(rc))
+    {
+        PRTLOGGER pLogger = pR0Log->pLogger;
+        pLogger->u32UserValue1 = VMMR0_LOGGER_FLAGS_MAGIC_VALUE;
+        pLogger->u64UserValue2 = (uintptr_t)pGVCpu;
+        pLogger->u64UserValue3 = (uintptr_t)pGVCpu;
+
+        RTLogSetR0ThreadNameF(pLogger, "EMT-%u-R0", pGVCpu->idCpu);
+    }
+    else
+        pR0Log->pLogger = NULL;
+    return rc;
+}
+
+
+/**
+ * Initializes one type of loggers for each EMT.
+ */
+static int vmmR0InitLoggers(PGVM pGVM, bool fRelease, uint32_t cbBuf, PRTR0MEMOBJ phMemObj, PRTR0MEMOBJ phMapObj)
+{
+    /* Allocate buffers first. */
+    int rc = RTR0MemObjAllocPage(phMemObj, cbBuf * pGVM->cCpus, false /*fExecutable*/);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTR0MemObjMapUser(phMapObj, *phMemObj, (RTR3PTR)-1, 0 /*uAlignment*/, RTMEM_PROT_READ, NIL_RTR0PROCESS);
+        if (RT_SUCCESS(rc))
+        {
+            char  * const pchBuf   = (char *)RTR0MemObjAddress(*phMemObj);
+            AssertPtrReturn(pchBuf, VERR_INTERNAL_ERROR_2);
+
+            RTR3PTR const pchBufR3 = RTR0MemObjAddressR3(*phMapObj);
+            AssertReturn(pchBufR3 != NIL_RTR3PTR, VERR_INTERNAL_ERROR_3);
+
+            /* Initialize the per-CPU loggers. */
+            for (uint32_t i = 0; i < pGVM->cCpus; i++)
+            {
+                PGVMCPU             pGVCpu  = &pGVM->aCpus[i];
+                PVMMR0PERVCPULOGGER pR0Log  = fRelease ? &pGVCpu->vmmr0.s.RelLogger : &pGVCpu->vmmr0.s.Logger;
+                PVMMR3CPULOGGER     pShared = fRelease ? &pGVCpu->vmm.s.RelLogger   : &pGVCpu->vmm.s.Logger;
+                rc = vmmR0InitLoggerOne(pGVCpu, fRelease, pR0Log, pShared, cbBuf, pchBuf + i * cbBuf, pchBufR3 + i * cbBuf);
+                if (RT_FAILURE(rc))
+                {
+                    pR0Log->pLogger   = NULL;
+                    pShared->pchBufR3 = NIL_RTR3PTR;
+                    while (i-- > 0)
+                    {
+                        pGVCpu  = &pGVM->aCpus[i];
+                        pR0Log  = fRelease ? &pGVCpu->vmmr0.s.RelLogger : &pGVCpu->vmmr0.s.Logger;
+                        pShared = fRelease ? &pGVCpu->vmm.s.RelLogger   : &pGVCpu->vmm.s.Logger;
+                        RTLogDestroy(pR0Log->pLogger);
+                        pR0Log->pLogger   = NULL;
+                        pShared->pchBufR3 = NIL_RTR3PTR;
+                    }
+                    break;
+                }
+            }
+            if (RT_SUCCESS(rc))
+                return VINF_SUCCESS;
+
+            /* Bail out. */
+            RTR0MemObjFree(*phMapObj, false /*fFreeMappings*/);
+            *phMapObj = NIL_RTR0MEMOBJ;
+        }
+        RTR0MemObjFree(*phMemObj, true /*fFreeMappings*/);
+        *phMemObj = NIL_RTR0MEMOBJ;
+    }
+    return rc;
+}
+
+
+/**
  * Initiates the R0 driver for a particular VM instance.
  *
@@ -412,12 +521,30 @@
         return rc;
 
+    /* Don't allow this to be called more than once. */
+    if (!pGVM->vmmr0.s.fCalledInitVm)
+        pGVM->vmmr0.s.fCalledInitVm = true;
+    else
+        return VERR_ALREADY_INITIALIZED;
+
+    /*
+     * Create the ring-0 release loggers.
+     */
+    rc = vmmR0InitLoggers(pGVM, true /*fRelease*/, _8K, &pGVM->vmmr0.s.hMemObjReleaseLogger, &pGVM->vmmr0.s.hMapObjReleaseLogger);
+    if (RT_FAILURE(rc))
+        return rc;
+
 #ifdef LOG_ENABLED
     /*
+     * Create debug loggers.
+     */
+    rc = vmmR0InitLoggers(pGVM, false /*fRelease*/, _64K, &pGVM->vmmr0.s.hMemObjLogger, &pGVM->vmmr0.s.hMapObjLogger);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
      * Register the EMT R0 logger instance for VCPU 0.
      */
     PVMCPUCC pVCpu = VMCC_GET_CPU_0(pGVM);
-
-    PVMMR0LOGGER pR0Logger = pVCpu->vmm.s.pR0LoggerR0;
-    if (pR0Logger)
+    if (pVCpu->vmmr0.s.Logger.pLogger)
     {
 # if 0 /* testing of the logger. */
@@ -451,7 +578,9 @@
         LogCom(("vmmR0InitVM: RTLogPrintf returned fine offScratch=%d\n", pR0Logger->Logger.offScratch));
 # endif
-        Log(("Switching to per-thread logging instance %p (key=%p)\n", &pR0Logger->Logger, pGVM->pSession));
-        RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pGVM->pSession);
-        pR0Logger->fRegistered = true;
+# ifdef VBOX_WITH_R0_LOGGING
+        Log(("Switching to per-thread logging instance %p (key=%p)\n", pVCpu->vmmr0.s.Logger.pLogger, pGVM->pSession));
+        RTLogSetDefaultInstanceThread(pVCpu->vmmr0.s.Logger.pLogger, (uintptr_t)pGVM->pSession);
+        pVCpu->vmmr0.s.Logger.fRegistered = true;
+# endif
     }
 #endif /* LOG_ENABLED */
@@ -548,15 +677,14 @@
     AssertReturn(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf(), VERR_INVALID_CPU_ID);
 
-#ifdef LOG_ENABLED
+#if defined(LOG_ENABLED) && defined(VBOX_WITH_R0_LOGGING)
     /*
      * Registration of ring 0 loggers.
      */
-    PVMCPUCC       pVCpu     = &pGVM->aCpus[idCpu];
-    PVMMR0LOGGER pR0Logger = pVCpu->vmm.s.pR0LoggerR0;
-    if (   pR0Logger
-        && !pR0Logger->fRegistered)
-    {
-        RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pGVM->pSession);
-        pR0Logger->fRegistered = true;
+    PVMCPUCC pVCpu = &pGVM->aCpus[idCpu];
+    if (   pVCpu->vmmr0.s.Logger.pLogger
+        && !pVCpu->vmmr0.s.Logger.fRegistered)
+    {
+        RTLogSetDefaultInstanceThread(pVCpu->vmmr0.s.Logger.pLogger, (uintptr_t)pGVM->pSession);
+        pVCpu->vmmr0.s.Logger.fRegistered = true;
     }
 #endif
@@ -614,8 +742,52 @@
 
     /*
-     * Deregister the logger.
+     * Deregister the logger for this EMT.
      */
     RTLogSetDefaultInstanceThread(NULL, (uintptr_t)pGVM->pSession);
     return VINF_SUCCESS;
+}
+
+
+/**
+ * This is called at the end of gvmmR0CleanupVM().
+ *
+ * @param   pGVM        The global (ring-0) VM structure.
+ */
+VMMR0_INT_DECL(void) VMMR0CleanupVM(PGVM pGVM)
+{
+    AssertCompile(NIL_RTTHREADCTXHOOK == (RTTHREADCTXHOOK)0); /* Depends on zero initialized memory working for NIL at the moment. */
+    for (VMCPUID idCpu = 0; idCpu < pGVM->cCpus; idCpu++)
+    {
+        PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
+
+        /** @todo Can we busy wait here for all thread-context hooks to be
+         *        deregistered before releasing (destroying) it? Only until we find a
+         *        solution for not deregistering hooks everytime we're leaving HMR0
+         *        context. */
+        VMMR0ThreadCtxHookDestroyForEmt(pGVCpu);
+
+        /* Destroy the release logger. */
+        RTLogDestroy(pGVCpu->vmmr0.s.RelLogger.pLogger);
+        pGVCpu->vmmr0.s.RelLogger.pLogger = NULL;
+        pGVCpu->vmm.s.RelLogger.pchBufR3  = NIL_RTR3PTR;
+
+        /* Destroy the regular logger. */
+        RTLogDestroy(pGVCpu->vmmr0.s.Logger.pLogger);
+        pGVCpu->vmmr0.s.Logger.pLogger = NULL;
+        pGVCpu->vmm.s.Logger.pchBufR3  = NIL_RTR3PTR;
+    }
+
+    /*
+     * Free logger buffer memory.
+     */
+    RTR0MemObjFree(pGVM->vmmr0.s.hMapObjReleaseLogger, false /*fFreeMappings*/);
+    pGVM->vmmr0.s.hMapObjReleaseLogger = NIL_RTR0MEMOBJ;
+    RTR0MemObjFree(pGVM->vmmr0.s.hMemObjReleaseLogger, true /*fFreeMappings*/);
+    pGVM->vmmr0.s.hMemObjReleaseLogger = NIL_RTR0MEMOBJ;
+
+    RTR0MemObjFree(pGVM->vmmr0.s.hMapObjLogger, false /*fFreeMappings*/);
+    pGVM->vmmr0.s.hMapObjLogger = NIL_RTR0MEMOBJ;
+    RTR0MemObjFree(pGVM->vmmr0.s.hMemObjLogger, true /*fFreeMappings*/);
+    pGVM->vmmr0.s.hMemObjLogger = NIL_RTR0MEMOBJ;
 }
 
@@ -1171,8 +1343,5 @@
 VMMR0_INT_DECL(PRTLOGGER) VMMR0GetReleaseLogger(PVMCPUCC pVCpu)
 {
-    PVMMR0LOGGER pLogger = pVCpu->vmm.s.pR0RelLoggerR0;
-    if (pLogger)
-        return &pLogger->Logger;
-    return NULL;
+    return pVCpu->vmmr0.s.RelLogger.pLogger;
 }
 
@@ -1880,4 +2049,17 @@
 
         /*
+         * Update release or debug logger instances.
+         */
+        case VMMR0_DO_VMMR0_UPDATE_LOGGERS:
+            if (idCpu == NIL_VMCPUID)
+                return VERR_INVALID_CPU_ID;
+            if (u64Arg <= 1 && pReqHdr != NULL)
+                rc = vmmR0UpdateLoggers(pGVM, idCpu /*idCpu*/, (PVMMR0UPDATELOGGERSREQ)pReqHdr, u64Arg != 0);
+            else
+                return VERR_INVALID_PARAMETER;
+            VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING);
+            break;
+
+        /*
          * Attempt to enable hm mode and check the current setting.
          */
@@ -2688,67 +2870,139 @@
 
 /**
- * Internal R0 logger worker: Flush logger.
- *
- * @param   pLogger     The logger instance to flush.
- * @remark  This function must be exported!
- */
-VMMR0DECL(void) vmmR0LoggerFlush(PRTLOGGER pLogger)
+ * Updates the EMT loggers for the VM.
+ *
+ * @returns VBox status code.
+ * @param   pGVM            The global (ring-0) VM structure.
+ * @param   idCpu           The ID of the calling EMT.
+ * @param   pReq            The request data.
+ * @param   fRelease        Which logger set to update.
+ * @thread  EMT(idCpu)
+ */
+static int vmmR0UpdateLoggers(PGVM pGVM, VMCPUID idCpu, PVMMR0UPDATELOGGERSREQ pReq, bool fRelease)
+{
+    /*
+     * Check sanity.  First we require EMT to be calling us.
+     */
+    AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID);
+    AssertReturn(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf(), VERR_INVALID_CPU_ID);
+
+    AssertReturn(pReq->Hdr.cbReq >= RT_UOFFSETOF_DYN(VMMR0UPDATELOGGERSREQ, afGroups[0]), VERR_INVALID_PARAMETER);
+    AssertReturn(pReq->cGroups < _8K, VERR_INVALID_PARAMETER);
+    AssertReturn(pReq->Hdr.cbReq == RT_UOFFSETOF_DYN(VMMR0UPDATELOGGERSREQ, afGroups[pReq->cGroups]), VERR_INVALID_PARAMETER);
+
+    /*
+     * Adjust flags.
+     */
+    /* Always buffered: */
+    pReq->fFlags |= RTLOGFLAGS_BUFFERED;
+    /* These doesn't make sense at present: */
+    pReq->fFlags &= ~(RTLOGFLAGS_FLUSH | RTLOGFLAGS_WRITE_THROUGH);
+    /* We've traditionally skipped the group restrictions. */
+    pReq->fFlags &= ~RTLOGFLAGS_RESTRICT_GROUPS;
+
+    /*
+     * Do the updating.
+     */
+    int rc = VINF_SUCCESS;
+    for (idCpu = 0; idCpu < pGVM->cCpus; idCpu++)
+    {
+        PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
+        PRTLOGGER pLogger = fRelease ? pGVCpu->vmmr0.s.RelLogger.pLogger : pGVCpu->vmmr0.s.Logger.pLogger;
+        if (pLogger)
+            rc = RTLogBulkUpdate(pLogger, pReq->fFlags, pReq->uGroupCrc32, pReq->cGroups, pReq->afGroups);
+    }
+
+    return rc;
+}
+
+
+/**
+ * Common worker for vmmR0LogFlush and vmmR0LogRelFlush.
+ */
+static bool vmmR0LoggerFlushCommon(PRTLOGGER pLogger, PRTLOGBUFFERDESC pBufDesc, bool fRelease)
+{
+    RT_NOREF(pBufDesc, fRelease);
+
+    /*
+     * Convert the pLogger into a GVMCPU handle and 'call' back to Ring-3.
+     * (This is a bit paranoid code.)
+     */
+    if (RT_VALID_PTR(pLogger))
+    {
+        if (   pLogger->u32Magic == RTLOGGER_MAGIC
+            && (pLogger->u32UserValue1 & VMMR0_LOGGER_FLAGS_MAGIC_MASK) == VMMR0_LOGGER_FLAGS_MAGIC_VALUE
+            && pLogger->u64UserValue2 == pLogger->u64UserValue3)
+        {
+            if (!(pLogger->u32UserValue1 & VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED))
+            {
+                PGVMCPU const pGVCpu = (PGVMCPU)(uintptr_t)pLogger->u64UserValue2;
+                if (   RT_VALID_PTR(pGVCpu)
+                    && ((uintptr_t)pGVCpu & PAGE_OFFSET_MASK) == 0)
+                {
+                    RTNATIVETHREAD const hNativeSelf = RTThreadNativeSelf();
+                    if (   hNativeSelf == pGVCpu->hEMT
+                        && RT_VALID_PTR(pGVCpu->pGVM))
+                    {
+                        /*
+                         * Check that the jump buffer is armed.
+                         */
+#ifdef RT_ARCH_X86
+                        if (   pGVCpu->vmm.s.CallRing3JmpBufR0.eip != 0
+                            && !pGVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call)
+#else
+                        if (   pGVCpu->vmm.s.CallRing3JmpBufR0.rip != 0
+                            && !pGVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call)
+#endif
+                        {
+                            VMMRZCallRing3(pGVCpu->pGVM, pGVCpu, VMMCALLRING3_VMM_LOGGER_FLUSH, fRelease);
+                        }
+#ifdef DEBUG
+                        else SUPR0Printf("vmmR0LoggerFlush: Jump buffer isn't armed!\n");
+#endif
+                    }
+#ifdef DEBUG
+                    else SUPR0Printf("vmmR0LoggerFlush: pLogger=%p pGVCpu=%p hEMT=%p hNativeSelf=%p!\n",
+                                     pLogger, pGVCpu, pGVCpu->hEMT, hNativeSelf);
+#endif
+
+                }
+#ifdef DEBUG
+                else SUPR0Printf("vmmR0LoggerFlush: pLogger=%p pGVCpu=%p!\n", pLogger, pGVCpu);
+#endif
+            }
+            /* else: quiet */
+        }
+#ifdef DEBUG
+        else SUPR0Printf("vmmR0LoggerFlush: pLogger=%p u32Magic=%#x u32UserValue1=%#x u64UserValue2=%#RX64 u64UserValue3=%#RX64!\n",
+                        pLogger, pLogger->u32Magic, pLogger->u32UserValue1, pLogger->u64UserValue2, pLogger->u64UserValue3);
+#endif
+    }
+#ifdef DEBUG
+    else SUPR0Printf("vmmR0LoggerFlush: pLogger=%p!\n", pLogger);
+#endif
+    return true;
+}
+
+
+/**
+ * @callback_method_impl{FNRTLOGFLUSH, Release logger buffer flush callback.}
+ */
+static DECLCALLBACK(bool) vmmR0LogRelFlush(PRTLOGGER pLogger, PRTLOGBUFFERDESC pBufDesc)
+{
+    return vmmR0LoggerFlushCommon(pLogger, pBufDesc, true /*fRelease*/);
+}
+
+
+/**
+ * @callback_method_impl{FNRTLOGFLUSH, Logger (debug) buffer flush callback.}
+ */
+static DECLCALLBACK(bool) vmmR0LogFlush(PRTLOGGER pLogger, PRTLOGBUFFERDESC pBufDesc)
 {
 #ifdef LOG_ENABLED
-    /*
-     * Convert the pLogger into a VM handle and 'call' back to Ring-3.
-     * (This is a bit paranoid code.)
-     */
-    PVMMR0LOGGER pR0Logger = (PVMMR0LOGGER)((uintptr_t)pLogger - RT_UOFFSETOF(VMMR0LOGGER, Logger));
-    if (    !RT_VALID_PTR(pR0Logger)
-        ||  !RT_VALID_PTR(pR0Logger + 1)
-        ||  pLogger->u32Magic != RTLOGGER_MAGIC)
-    {
-# ifdef DEBUG
-        SUPR0Printf("vmmR0LoggerFlush: pLogger=%p!\n", pLogger);
-# endif
-        return;
-    }
-    if (pR0Logger->fFlushingDisabled)
-        return; /* quietly */
-
-    PVMCC pVM = pR0Logger->pVM;
-    if (   !RT_VALID_PTR(pVM)
-        || pVM->pSelf != pVM)
-    {
-# ifdef DEBUG
-        SUPR0Printf("vmmR0LoggerFlush: pVM=%p! pSelf=%p! pLogger=%p\n", pVM, pVM->pSelf, pLogger);
-# endif
-        return;
-    }
-
-    PVMCPUCC pVCpu = VMMGetCpu(pVM);
-    if (pVCpu)
-    {
-        /*
-         * Check that the jump buffer is armed.
-         */
-# ifdef RT_ARCH_X86
-        if (    !pVCpu->vmm.s.CallRing3JmpBufR0.eip
-            ||  pVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call)
-# else
-        if (    !pVCpu->vmm.s.CallRing3JmpBufR0.rip
-            ||  pVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call)
-# endif
-        {
-# ifdef DEBUG
-            SUPR0Printf("vmmR0LoggerFlush: Jump buffer isn't armed!\n");
-# endif
-            return;
-        }
-        VMMRZCallRing3(pVM, pVCpu, VMMCALLRING3_VMM_LOGGER_FLUSH, 0);
-    }
-# ifdef DEBUG
-    else
-        SUPR0Printf("vmmR0LoggerFlush: invalid VCPU context!\n");
-# endif
+    return vmmR0LoggerFlushCommon(pLogger, pBufDesc, false /*fRelease*/);
 #else
-    NOREF(pLogger);
-#endif  /* LOG_ENABLED */
+    RT_NOREF(pLogger, pBufDesc);
+    return true;
+#endif
 }
 
@@ -2762,8 +3016,9 @@
 VMMR0_INT_DECL(void) VMMR0LogFlushDisable(PVMCPUCC pVCpu)
 {
-    if (pVCpu->vmm.s.pR0LoggerR0)
-        pVCpu->vmm.s.pR0LoggerR0->fFlushingDisabled = true;
-    if (pVCpu->vmm.s.pR0RelLoggerR0)
-        pVCpu->vmm.s.pR0RelLoggerR0->fFlushingDisabled = true;
+    pVCpu->vmmr0.s.fLogFlushingDisabled = true;
+    if (pVCpu->vmmr0.s.Logger.pLogger)
+        pVCpu->vmmr0.s.Logger.pLogger->u32UserValue1 |= VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
+    if (pVCpu->vmmr0.s.RelLogger.pLogger)
+        pVCpu->vmmr0.s.RelLogger.pLogger->u32UserValue1 |= VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
 }
 
@@ -2776,8 +3031,9 @@
 VMMR0_INT_DECL(void) VMMR0LogFlushEnable(PVMCPUCC pVCpu)
 {
-    if (pVCpu->vmm.s.pR0LoggerR0)
-        pVCpu->vmm.s.pR0LoggerR0->fFlushingDisabled = false;
-    if (pVCpu->vmm.s.pR0RelLoggerR0)
-        pVCpu->vmm.s.pR0RelLoggerR0->fFlushingDisabled = false;
+    pVCpu->vmmr0.s.fLogFlushingDisabled = false;
+    if (pVCpu->vmmr0.s.Logger.pLogger)
+        pVCpu->vmmr0.s.Logger.pLogger->u32UserValue1 &= ~VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
+    if (pVCpu->vmmr0.s.RelLogger.pLogger)
+        pVCpu->vmmr0.s.RelLogger.pLogger->u32UserValue1 &= ~VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
 }
 
@@ -2790,12 +3046,34 @@
 VMMR0_INT_DECL(bool) VMMR0IsLogFlushDisabled(PVMCPUCC pVCpu)
 {
-    if (pVCpu->vmm.s.pR0LoggerR0)
-        return pVCpu->vmm.s.pR0LoggerR0->fFlushingDisabled;
-    if (pVCpu->vmm.s.pR0RelLoggerR0)
-        return pVCpu->vmm.s.pR0RelLoggerR0->fFlushingDisabled;
-    return true;
+    return pVCpu->vmmr0.s.fLogFlushingDisabled;
 }
 
 #endif /* LOG_ENABLED */
+
+/*
+ * Override RTLogGetDefaultInstanceEx so we can do logging from EMTs in ring-0.
+ */
+DECLEXPORT(PRTLOGGER) RTLogGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
+{
+#ifdef LOG_ENABLED
+    PGVMCPU pGVCpu = GVMMR0GetGVCpuByEMT(NIL_RTNATIVETHREAD);
+    if (pGVCpu)
+    {
+        PRTLOGGER pLogger = pGVCpu->vmmr0.s.Logger.pLogger;
+        if (RT_VALID_PTR(pLogger))
+        {
+            if (   pLogger->u64UserValue2 == (uintptr_t)pGVCpu
+                && pLogger->u64UserValue3 == (uintptr_t)pGVCpu)
+            {
+                if (!(pGVCpu->vmmr0.s.fLogFlushingDisabled))
+                    return RTLogCheckGroupFlags(pLogger, fFlagsAndGroup);
+                return NULL;
+            }
+        }
+    }
+#endif
+    return SUPR0GetDefaultLogInstanceEx(fFlagsAndGroup);
+}
+
 
 /*
@@ -2807,24 +3085,13 @@
     if (pGVCpu)
     {
-        PVMCPUCC pVCpu = pGVCpu;
-        if (RT_VALID_PTR(pVCpu))
-        {
-            PVMMR0LOGGER pVmmLogger = pVCpu->vmm.s.pR0RelLoggerR0;
-            if (RT_VALID_PTR(pVmmLogger))
+        PRTLOGGER pLogger = pGVCpu->vmmr0.s.RelLogger.pLogger;
+        if (RT_VALID_PTR(pLogger))
+        {
+            if (   pLogger->u64UserValue2 == (uintptr_t)pGVCpu
+                && pLogger->u64UserValue3 == (uintptr_t)pGVCpu)
             {
-                if (   pVmmLogger->fCreated
-                    && pVmmLogger->pVM == pGVCpu->pGVM)
-                {
-                    if (pVmmLogger->Logger.fFlags & RTLOGFLAGS_DISABLED)
-                        return NULL;
-                    uint16_t const fFlags = RT_LO_U16(fFlagsAndGroup);
-                    uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
-                    if (   iGroup != UINT16_MAX
-                        && (   (  pVmmLogger->Logger.afGroups[iGroup < pVmmLogger->Logger.cGroups ? iGroup : 0]
-                                & (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED))
-                            != (fFlags | (uint32_t)RTLOGGRPFLAGS_ENABLED)))
-                        return NULL;
-                    return &pVmmLogger->Logger;
-                }
+                if (!(pGVCpu->vmmr0.s.fLogFlushingDisabled))
+                    return RTLogCheckGroupFlags(pLogger, fFlagsAndGroup);
+                return NULL;
             }
         }
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.def
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.def	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.def	(revision 90829)
@@ -37,4 +37,5 @@
     RTLogDefaultInstance
     RTLogDefaultInstanceEx
+    RTLogGetDefaultInstanceEx
     RTLogRelGetDefaultInstance
     RTLogRelGetDefaultInstanceEx
@@ -63,6 +64,4 @@
     TMTimerUnlock
     VMMGetSvnRev
-    vmmR0LoggerFlush
-    vmmR0LoggerWrapper
     VMSetError
     VMSetErrorV
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm	(revision 90829)
@@ -505,16 +505,2 @@
 ENDPROC vmmR0CallRing3LongJmp
 
-
-;;
-; Internal R0 logger worker: Logger wrapper.
-;
-; @cproto VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...)
-;
-BEGINPROC_EXPORTED vmmR0LoggerWrapper
-SEH64_END_PROLOGUE
-    int3
-    int3
-    int3
-    ret
-ENDPROC vmmR0LoggerWrapper
-
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-x86.asm
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-x86.asm	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-x86.asm	(revision 90829)
@@ -31,7 +31,4 @@
 %define STACK_PADDING   0eeeeeeeeh
 
-
-; For vmmR0LoggerWrapper. (The other architecture(s) use(s) C99 variadic macros.)
-extern NAME(RTLogLogger)
 
 
@@ -387,15 +384,2 @@
 ENDPROC vmmR0CallRing3LongJmp
 
-
-;;
-; Internal R0 logger worker: Logger wrapper.
-;
-; @cproto VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...)
-;
-EXPORTEDNAME vmmR0LoggerWrapper
-    push    0                           ; assumes we're the wrapper for a default instance.
-    call    NAME(RTLogLogger)
-    add     esp, byte 4
-    ret
-ENDPROC vmmR0LoggerWrapper
-
Index: /trunk/src/VBox/VMM/VMMR3/VMM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 90829)
@@ -151,11 +151,13 @@
 
 /** Macro for flushing the ring-0 logging. */
-#define VMM_FLUSH_R0_LOG(a_pR0Logger, a_pR3Logger) \
+#define VMM_FLUSH_R0_LOG(a_pLogger, a_pR3Logger) \
     do { \
-        PVMMR0LOGGER pVmmLogger = (a_pR0Logger); \
-        if (!pVmmLogger || pVmmLogger->Logger.offScratch == 0) \
+        if ((a_pLogger)->AuxDesc.offBuf == 0 || (a_pLogger)->AuxDesc.fFlushedIndicator) \
         { /* likely? */ } \
         else \
-            RTLogFlushR0(a_pR3Logger, &pVmmLogger->Logger); \
+        { \
+            RTLogBulkWrite(a_pR3Logger, (a_pLogger)->pchBufR3, (a_pLogger)->AuxDesc.offBuf); \
+            (a_pLogger)->AuxDesc.fFlushedIndicator = true; \
+        } \
     } while (0)
 
@@ -165,5 +167,4 @@
 *********************************************************************************************************************************/
 static int                  vmmR3InitStacks(PVM pVM);
-static int                  vmmR3InitLoggers(PVM pVM);
 static void                 vmmR3InitRegisterStats(PVM pVM);
 static DECLCALLBACK(int)    vmmR3Save(PVM pVM, PSSMHANDLE pSSM);
@@ -281,15 +282,10 @@
     if (RT_SUCCESS(rc))
     {
-        rc = vmmR3InitLoggers(pVM);
-
 #ifdef VBOX_WITH_NMI
         /*
          * Allocate mapping for the host APIC.
          */
-        if (RT_SUCCESS(rc))
-        {
-            rc = MMR3HyperReserve(pVM, PAGE_SIZE, "Host APIC", &pVM->vmm.s.GCPtrApicBase);
-            AssertRC(rc);
-        }
+        rc = MMR3HyperReserve(pVM, PAGE_SIZE, "Host APIC", &pVM->vmm.s.GCPtrApicBase);
+        AssertRC(rc);
 #endif
         if (RT_SUCCESS(rc))
@@ -352,94 +348,4 @@
 
     return rc;
-}
-
-
-/**
- * Initialize the loggers.
- *
- * @returns VBox status code.
- * @param   pVM         The cross context VM structure.
- */
-static int vmmR3InitLoggers(PVM pVM)
-{
-    int rc;
-#define RTLogCalcSizeForR0(cGroups, fFlags) (RT_UOFFSETOF_DYN(VMMR0LOGGER, Logger.afGroups[cGroups]) + PAGE_SIZE)
-
-    /*
-     * Allocate R0 Logger instance (finalized in the relocator).
-     */
-#if defined(LOG_ENABLED) && defined(VBOX_WITH_R0_LOGGING)
-    PRTLOGGER pLogger = RTLogDefaultInstance();
-    if (pLogger)
-    {
-        size_t const cbLogger = RTLogCalcSizeForR0(pLogger->cGroups, 0);
-        for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
-        {
-            PVMCPU pVCpu = pVM->apCpusR3[idCpu];
-            rc = MMR3HyperAllocOnceNoRelEx(pVM, cbLogger, PAGE_SIZE, MM_TAG_VMM, MMHYPER_AONR_FLAGS_KERNEL_MAPPING,
-                                           (void **)&pVCpu->vmm.s.pR0LoggerR3);
-            if (RT_FAILURE(rc))
-                return rc;
-            pVCpu->vmm.s.pR0LoggerR3->pVM        = VMCC_GET_VMR0_FOR_CALL(pVM);
-            //pVCpu->vmm.s.pR0LoggerR3->fCreated = false;
-            pVCpu->vmm.s.pR0LoggerR3->cbLogger   = (uint32_t)cbLogger;
-            pVCpu->vmm.s.pR0LoggerR0 = MMHyperR3ToR0(pVM, pVCpu->vmm.s.pR0LoggerR3);
-        }
-    }
-#endif /* LOG_ENABLED && VBOX_WITH_R0_LOGGING */
-
-    /*
-     * Release logging.
-     */
-    PRTLOGGER pRelLogger = RTLogRelGetDefaultInstance();
-    if (pRelLogger)
-    {
-        /*
-         * Ring-0 release logger.
-         */
-        RTR0PTR pfnLoggerWrapper = NIL_RTR0PTR;
-        rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerWrapper", &pfnLoggerWrapper);
-        AssertReleaseMsgRCReturn(rc, ("vmmR0LoggerWrapper not found! rc=%Rra\n", rc), rc);
-
-        RTR0PTR pfnLoggerFlush = NIL_RTR0PTR;
-        rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerFlush", &pfnLoggerFlush);
-        AssertReleaseMsgRCReturn(rc, ("vmmR0LoggerFlush not found! rc=%Rra\n", rc), rc);
-
-        size_t const cbLogger = RTLogCalcSizeForR0(pRelLogger->cGroups, 0);
-
-        for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
-        {
-            PVMCPU pVCpu = pVM->apCpusR3[idCpu];
-            rc = MMR3HyperAllocOnceNoRelEx(pVM, cbLogger, PAGE_SIZE, MM_TAG_VMM, MMHYPER_AONR_FLAGS_KERNEL_MAPPING,
-                                           (void **)&pVCpu->vmm.s.pR0RelLoggerR3);
-            if (RT_FAILURE(rc))
-                return rc;
-            PVMMR0LOGGER pVmmLogger = pVCpu->vmm.s.pR0RelLoggerR3;
-            RTR0PTR      R0PtrVmmLogger = MMHyperR3ToR0(pVM, pVmmLogger);
-            pVCpu->vmm.s.pR0RelLoggerR0     = R0PtrVmmLogger;
-            pVmmLogger->pVM                 = VMCC_GET_VMR0_FOR_CALL(pVM);
-            pVmmLogger->cbLogger            = (uint32_t)cbLogger;
-            pVmmLogger->fCreated            = false;
-            pVmmLogger->fFlushingDisabled   = false;
-            pVmmLogger->fRegistered         = false;
-            pVmmLogger->idCpu               = idCpu;
-
-            char szR0ThreadName[16];
-            RTStrPrintf(szR0ThreadName, sizeof(szR0ThreadName), "EMT-%u-R0", idCpu);
-            rc = RTLogCreateForR0(&pVmmLogger->Logger, pVmmLogger->cbLogger, R0PtrVmmLogger + RT_UOFFSETOF(VMMR0LOGGER, Logger),
-                                  pfnLoggerWrapper, pfnLoggerFlush,
-                                  RTLOGFLAGS_BUFFERED, RTLOGDEST_DUMMY, szR0ThreadName);
-            AssertReleaseMsgRCReturn(rc, ("RTLogCreateForR0 failed! rc=%Rra\n", rc), rc);
-
-            /* We only update the release log instance here. */
-            rc = RTLogCopyGroupsAndFlagsForR0(&pVmmLogger->Logger, R0PtrVmmLogger + RT_UOFFSETOF(VMMR0LOGGER, Logger),
-                                              pRelLogger, RTLOGFLAGS_BUFFERED, UINT32_MAX);
-            AssertReleaseMsgRCReturn(rc, ("RTLogCopyGroupsAndFlagsForR0 failed! rc=%Rra\n", rc), rc);
-
-            pVmmLogger->fCreated = true;
-        }
-    }
-
-    return VINF_SUCCESS;
 }
 
@@ -582,16 +488,10 @@
     Assert(pVCpu && pVCpu->idCpu == 0);
 
-#ifdef LOG_ENABLED
-    /*
-     * Initialize the ring-0 logger if we haven't done so yet.
-     */
-    if (    pVCpu->vmm.s.pR0LoggerR3
-        &&  !pVCpu->vmm.s.pR0LoggerR3->fCreated)
-    {
-        rc = VMMR3UpdateLoggers(pVM);
-        if (RT_FAILURE(rc))
-            return rc;
-    }
-#endif
+    /*
+     * Make sure the ring-0 loggers are up to date.
+     */
+    rc = VMMR3UpdateLoggers(pVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     /*
@@ -610,7 +510,7 @@
          */
 #ifdef LOG_ENABLED
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0LoggerR3, NULL);
-#endif
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0RelLoggerR3, RTLogRelGetDefaultInstance());
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.Logger, NULL);
+#endif
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.RelLogger, RTLogRelGetDefaultInstance());
         if (rc != VINF_VMM_CALL_HOST)
             break;
@@ -743,7 +643,7 @@
          */
 #ifdef LOG_ENABLED
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0LoggerR3, NULL);
-#endif
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0RelLoggerR3, RTLogRelGetDefaultInstance());
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.Logger, NULL);
+#endif
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.RelLogger, RTLogRelGetDefaultInstance());
         if (rc != VINF_VMM_CALL_HOST)
             break;
@@ -810,58 +710,73 @@
 
 /**
+ * Worker for VMMR3UpdateLoggers.
+ */
+static int vmmR3UpdateLoggersWorker(PVM pVM, PVMCPU pVCpu, PRTLOGGER pSrcLogger, bool fReleaseLogger)
+{
+    /*
+     * Get the group count.
+     */
+    uint32_t uGroupsCrc32 = 0;
+    uint32_t cGroups      = 0;
+    uint64_t fFlags       = 0;
+    int rc = RTLogQueryBulk(pSrcLogger, &fFlags, &uGroupsCrc32, &cGroups, NULL);
+    Assert(rc == VERR_BUFFER_OVERFLOW);
+
+    /*
+     * Allocate the request of the right size.
+     */
+    uint32_t const         cbReq = RT_UOFFSETOF_DYN(VMMR0UPDATELOGGERSREQ, afGroups[cGroups]);
+    PVMMR0UPDATELOGGERSREQ pReq  = (PVMMR0UPDATELOGGERSREQ)RTMemAllocZVar(cbReq);
+    if (pReq)
+    {
+        pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+        pReq->Hdr.cbReq    = cbReq;
+        pReq->cGroups      = cGroups;
+        rc = RTLogQueryBulk(pSrcLogger, &pReq->fFlags, &pReq->uGroupCrc32, &pReq->cGroups, pReq->afGroups);
+        AssertRC(rc);
+        if (RT_SUCCESS(rc))
+            rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_VMMR0_UPDATE_LOGGERS, fReleaseLogger, &pReq->Hdr);
+
+        RTMemFree(pReq);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    return rc;
+}
+
+
+/**
  * Updates the settings for the RC and R0 loggers.
  *
  * @returns VBox status code.
  * @param   pVM     The cross context VM structure.
+ * @param   EMT
  */
 VMMR3_INT_DECL(int) VMMR3UpdateLoggers(PVM pVM)
 {
-    int rc = VINF_SUCCESS;
-
+    VM_ASSERT_EMT(pVM);
+    PVMCPU pVCpu = VMMGetCpu(pVM);
+    AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT);
+
+    /*
+     * Each EMT has each own logger instance.
+     */
+    /* Debug logging.*/
+    int rcDebug = VINF_SUCCESS;
 #ifdef LOG_ENABLED
-    /*
-     * For the ring-0 EMT logger, we use a per-thread logger instance
-     * in ring-0. Only initialize it once.
-     */
     PRTLOGGER const pDefault = RTLogDefaultInstance();
-    for (VMCPUID i = 0; i < pVM->cCpus; i++)
-    {
-        PVMCPU       pVCpu = pVM->apCpusR3[i];
-        PVMMR0LOGGER pR0LoggerR3 = pVCpu->vmm.s.pR0LoggerR3;
-        if (pR0LoggerR3)
-        {
-            if (!pR0LoggerR3->fCreated)
-            {
-                RTR0PTR pfnLoggerWrapper = NIL_RTR0PTR;
-                rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerWrapper", &pfnLoggerWrapper);
-                AssertReleaseMsgRCReturn(rc, ("vmmR0LoggerWrapper not found! rc=%Rra\n", rc), rc);
-
-                RTR0PTR pfnLoggerFlush = NIL_RTR0PTR;
-                rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerFlush", &pfnLoggerFlush);
-                AssertReleaseMsgRCReturn(rc, ("vmmR0LoggerFlush not found! rc=%Rra\n", rc), rc);
-
-                char szR0ThreadName[16];
-                RTStrPrintf(szR0ThreadName, sizeof(szR0ThreadName), "EMT-%u-R0", i);
-                rc = RTLogCreateForR0(&pR0LoggerR3->Logger, pR0LoggerR3->cbLogger,
-                                      pVCpu->vmm.s.pR0LoggerR0 + RT_UOFFSETOF(VMMR0LOGGER, Logger),
-                                      pfnLoggerWrapper, pfnLoggerFlush,
-                                      RTLOGFLAGS_BUFFERED, RTLOGDEST_DUMMY, szR0ThreadName);
-                AssertReleaseMsgRCReturn(rc, ("RTLogCreateForR0 failed! rc=%Rra\n", rc), rc);
-
-                pR0LoggerR3->idCpu = i;
-                pR0LoggerR3->fCreated = true;
-                pR0LoggerR3->fFlushingDisabled = false;
-            }
-
-            rc = RTLogCopyGroupsAndFlagsForR0(&pR0LoggerR3->Logger, pVCpu->vmm.s.pR0LoggerR0 + RT_UOFFSETOF(VMMR0LOGGER, Logger),
-                                              pDefault, RTLOGFLAGS_BUFFERED, UINT32_MAX);
-            AssertRC(rc);
-        }
-    }
+    if (pDefault)
+        rcDebug = vmmR3UpdateLoggersWorker(pVM, pVCpu, pDefault, false /*fReleaseLogger*/);
 #else
     RT_NOREF(pVM);
 #endif
 
-    return rc;
+    /* Release logging. */
+    int rcRelease = VINF_SUCCESS;
+    PRTLOGGER const pRelease = RTLogRelGetDefaultInstance();
+    if (pRelease)
+        rcRelease = vmmR3UpdateLoggersWorker(pVM, pVCpu, pRelease, true /*fReleaseLogger*/);
+
+    return RT_SUCCESS(rcDebug) ? rcRelease : rcDebug;
 }
 
@@ -1139,7 +1054,7 @@
          */
 #ifdef LOG_ENABLED
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0LoggerR3, NULL);
-#endif
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0RelLoggerR3, RTLogRelGetDefaultInstance());
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.Logger, NULL);
+#endif
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.RelLogger, RTLogRelGetDefaultInstance());
         if (rc != VINF_VMM_CALL_HOST)
         {
@@ -1183,7 +1098,7 @@
          */
 #ifdef LOG_ENABLED
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0LoggerR3, NULL);
-#endif
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0RelLoggerR3, RTLogRelGetDefaultInstance());
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.Logger, NULL);
+#endif
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.RelLogger, RTLogRelGetDefaultInstance());
         if (rcStrict != VINF_VMM_CALL_HOST)
             return rcStrict;
@@ -2340,7 +2255,7 @@
          */
 #ifdef LOG_ENABLED
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0LoggerR3, NULL);
-#endif
-        VMM_FLUSH_R0_LOG(pVCpu->vmm.s.pR0RelLoggerR3, RTLogRelGetDefaultInstance());
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.Logger, NULL);
+#endif
+        VMM_FLUSH_R0_LOG(&pVCpu->vmm.s.RelLogger, RTLogRelGetDefaultInstance());
         if (rc != VINF_VMM_CALL_HOST)
             break;
Index: /trunk/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp	(revision 90829)
@@ -218,17 +218,15 @@
     if (pHlp->pRelLogger)
     {
-        pHlp->fRelLoggerFlags = pHlp->pRelLogger->fFlags;
-        pHlp->pRelLogger->fFlags &= ~RTLOGFLAGS_DISABLED;
-        pHlp->pRelLogger->fFlags |= RTLOGFLAGS_BUFFERED;
+        pHlp->fRelLoggerFlags = RTLogGetFlags(pHlp->pRelLogger);
+        RTLogChangeFlags(pHlp->pRelLogger, RTLOGFLAGS_BUFFERED, RTLOGFLAGS_DISABLED);
     }
 
     if (pHlp->pLogger)
     {
-        pHlp->fLoggerFlags     = pHlp->pLogger->fFlags;
-        pHlp->fLoggerDestFlags = pHlp->pLogger->fDestFlags;
-        pHlp->pLogger->fFlags     &= ~RTLOGFLAGS_DISABLED;
-        pHlp->pLogger->fFlags     |= RTLOGFLAGS_BUFFERED;
+        pHlp->fLoggerFlags     = RTLogGetFlags(pHlp->pLogger);
+        pHlp->fLoggerDestFlags = RTLogGetDestinations(pHlp->pLogger);
+        RTLogChangeFlags(pHlp->pLogger, RTLOGFLAGS_BUFFERED, RTLOGFLAGS_DISABLED);
 #ifndef DEBUG_sandervl
-        pHlp->pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
+        RTLogChangeDestinations(pHlp->pLogger, RTLOGDEST_DEBUGGER, 0);
 #endif
     }
@@ -237,6 +235,6 @@
      * Check if we need write to stderr.
      */
-    pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
-                 && (!pHlp->pLogger    || !(pHlp->pLogger->fDestFlags    & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
+    pHlp->fStdErr = (!pHlp->pRelLogger || !(RTLogGetDestinations(pHlp->pRelLogger) & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
+                 && (!pHlp->pLogger    || !(RTLogGetDestinations(pHlp->pLogger)    & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
 #ifdef DEBUG_sandervl
     pHlp->fStdErr = false; /* takes too long to display here */
@@ -263,5 +261,7 @@
     {
         RTLogFlush(pHlp->pRelLogger);
-        pHlp->pRelLogger->fFlags = pHlp->fRelLoggerFlags;
+        RTLogChangeFlags(pHlp->pRelLogger,
+                         pHlp->fRelLoggerFlags & RTLOGFLAGS_DISABLED,
+                         pHlp->fRelLoggerFlags & RTLOGFLAGS_BUFFERED);
     }
 
@@ -269,6 +269,8 @@
     {
         RTLogFlush(pHlp->pLogger);
-        pHlp->pLogger->fFlags     = pHlp->fLoggerFlags;
-        pHlp->pLogger->fDestFlags = pHlp->fLoggerDestFlags;
+        RTLogChangeFlags(pHlp->pLogger,
+                         pHlp->fLoggerFlags & RTLOGFLAGS_DISABLED,
+                         pHlp->fLoggerFlags & RTLOGFLAGS_BUFFERED);
+        RTLogChangeDestinations(pHlp->pLogger, 0, pHlp->fLoggerDestFlags & RTLOGDEST_DEBUGGER);
     }
 
Index: /trunk/src/VBox/VMM/VMMRZ/VMMRZ.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRZ/VMMRZ.cpp	(revision 90828)
+++ /trunk/src/VBox/VMM/VMMRZ/VMMRZ.cpp	(revision 90829)
@@ -144,10 +144,9 @@
         pVCpu->pVMRC->vmm.s.fRCLoggerFlushingDisabled = true;
 #else
-# ifdef LOG_ENABLED
-        if (pVCpu->vmm.s.pR0LoggerR0)
-            pVCpu->vmm.s.pR0LoggerR0->fFlushingDisabled = true;
-# endif
-        if (pVCpu->vmm.s.pR0RelLoggerR0)
-            pVCpu->vmm.s.pR0RelLoggerR0->fFlushingDisabled = true;
+        pVCpu->vmmr0.s.fLogFlushingDisabled = true;
+        if (pVCpu->vmmr0.s.Logger.pLogger)
+            pVCpu->vmmr0.s.Logger.pLogger->u32UserValue1 |= VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
+        if (pVCpu->vmmr0.s.RelLogger.pLogger)
+            pVCpu->vmmr0.s.RelLogger.pLogger->u32UserValue1 |= VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
 #endif
     }
@@ -178,10 +177,9 @@
         pVCpu->pVMRC->vmm.s.fRCLoggerFlushingDisabled = false;
 #else
-# ifdef LOG_ENABLED
-        if (pVCpu->vmm.s.pR0LoggerR0)
-            pVCpu->vmm.s.pR0LoggerR0->fFlushingDisabled = false;
-# endif
-        if (pVCpu->vmm.s.pR0RelLoggerR0)
-            pVCpu->vmm.s.pR0RelLoggerR0->fFlushingDisabled = false;
+        pVCpu->vmmr0.s.fLogFlushingDisabled = false;
+        if (pVCpu->vmmr0.s.Logger.pLogger)
+            pVCpu->vmmr0.s.Logger.pLogger->u32UserValue1 &= ~VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
+        if (pVCpu->vmmr0.s.RelLogger.pLogger)
+            pVCpu->vmmr0.s.RelLogger.pLogger->u32UserValue1 &= ~VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED;
 #endif
     }
Index: /trunk/src/VBox/VMM/include/VMMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/VMMInternal.h	(revision 90828)
+++ /trunk/src/VBox/VMM/include/VMMInternal.h	(revision 90829)
@@ -67,32 +67,39 @@
 
 /**
- * The ring-0 logger instance wrapper.
- *
- * We need to be able to find the VM handle from the logger instance, so we wrap
- * it in this structure.
- */
-typedef struct VMMR0LOGGER
+ * R0 logger data (ring-0 only data).
+ */
+typedef struct VMMR0PERVCPULOGGER
 {
-    /** Pointer to Pointer to the VM. */
-    R0PTRTYPE(PVMCC)            pVM;
-    /** Size of the allocated logger instance (Logger). */
-    uint32_t                    cbLogger;
-    /** Flag indicating whether we've create the logger Ring-0 instance yet. */
-    bool                        fCreated;
-    /** Flag indicating whether we've disabled flushing (world switch) or not. */
-    bool                        fFlushingDisabled;
+    /** Pointer to the logger instance.
+     * The RTLOGGER::u32UserValue1 member is used for flags and magic, while the
+     * RTLOGGER::u64UserValue2 member is the corresponding PGVMCPU value.
+     * RTLOGGER::u64UserValue3 is currently and set to the PGVMCPU value too. */
+    R0PTRTYPE(PRTLOGGER)    pLogger;
+    /** Log buffer descriptor.
+     * The buffer is allocated in a common block for all VCpus, see VMMR0PERVM.  */
+    RTLOGBUFFERDESC         BufDesc;
     /** Flag indicating whether we've registered the instance already. */
-    bool                        fRegistered;
-    bool                        a8Alignment;
-    /** The CPU ID. */
-    VMCPUID                     idCpu;
-#if HC_ARCH_BITS == 64
-    uint32_t                    u32Alignment;
-#endif
-    /** The ring-0 logger instance. This extends beyond the size.  */
-    RTLOGGER                    Logger;
-} VMMR0LOGGER;
-/** Pointer to a ring-0 logger instance wrapper. */
-typedef VMMR0LOGGER *PVMMR0LOGGER;
+    bool                    fRegistered;
+    bool                    afPadding[7];
+} VMMR0PERVCPULOGGER;
+/** Pointer to the R0 logger data (ring-0 only). */
+typedef VMMR0PERVCPULOGGER *PVMMR0PERVCPULOGGER;
+
+
+/**
+ * R0 logger data shared with ring-3 (per CPU).
+ */
+typedef struct VMMR3CPULOGGER
+{
+    /** Auxiliary buffer descriptor. */
+    RTLOGBUFFERAUXDESC      AuxDesc;
+    /** Ring-3 mapping of the logging buffer. */
+    R3PTRTYPE(char *)       pchBufR3;
+    /** The buffer size. */
+    uint32_t                cbBuf;
+    uint32_t                uReserved;
+} VMMR3CPULOGGER;
+/** Pointer to r0 logger data shared with ring-3. */
+typedef VMMR3CPULOGGER *PVMMR3CPULOGGER;
 
 
@@ -367,18 +374,4 @@
     R3PTRTYPE(uint8_t *)        pbEMTStackR3;
 
-    /** Pointer to the R0 logger instance - R3 Ptr.
-     * This is NULL if logging is disabled. */
-    R3PTRTYPE(PVMMR0LOGGER)     pR0LoggerR3;
-    /** Pointer to the R0 logger instance - R0 Ptr.
-     * This is NULL if logging is disabled. */
-    R0PTRTYPE(PVMMR0LOGGER)     pR0LoggerR0;
-
-    /** Pointer to the R0 release logger instance - R3 Ptr.
-     * This is NULL if logging is disabled. */
-    R3PTRTYPE(PVMMR0LOGGER)     pR0RelLoggerR3;
-    /** Pointer to the R0 release instance - R0 Ptr.
-     * This is NULL if logging is disabled. */
-    R0PTRTYPE(PVMMR0LOGGER)     pR0RelLoggerR0;
-
     /** @name Rendezvous
      * @{ */
@@ -435,4 +428,12 @@
     VMMR0JMPBUF                 CallRing3JmpBufR0;
     /** @} */
+
+    /** @name Logging
+     * @{ */
+    /** The R0 logger data shared with ring-3. */
+    VMMR3CPULOGGER              Logger;
+    /** The R0 release logger data shared with ring-3. */
+    VMMR3CPULOGGER              RelLogger;
+    /** @}  */
 
     STAMPROFILE                 StatR0HaltBlock;
@@ -462,6 +463,6 @@
     /** Set if we've entered HM context. */
     bool volatile                       fInHmContext;
-
-    bool                                afPadding[5];
+    /** Flag indicating whether we've disabled flushing (world switch) or not. */
+    bool                                fLogFlushingDisabled;
     /** The EMT hash table index. */
     uint16_t                            idxEmtHash;
@@ -483,8 +484,47 @@
     PSUPDRVSESSION                      pSession;
     /** @} */
+
+    /** @name Loggers
+     * @{ */
+    /** The R0 logger data. */
+    VMMR0PERVCPULOGGER                  Logger;
+    /** The R0 release logger data. */
+    VMMR0PERVCPULOGGER                  RelLogger;
+    /** @} */
 } VMMR0PERVCPU;
 /** Pointer to VMM ring-0 VMCPU instance data. */
 typedef VMMR0PERVCPU *PVMMR0PERVCPU;
 
+/** @name RTLOGGER::u32UserValue1 Flags
+ * @{ */
+/** The magic value. */
+#define VMMR0_LOGGER_FLAGS_MAGIC_VALUE          UINT32_C(0x7d297f05)
+/** Part of the flags value used for the magic. */
+#define VMMR0_LOGGER_FLAGS_MAGIC_MASK           UINT32_C(0xffffff0f)
+/** Set if flushing is disabled (copy of fLogFlushingDisabled). */
+#define VMMR0_LOGGER_FLAGS_FLUSHING_DISABLED    UINT32_C(0x00000010)
+/** @} */
+
+
+/**
+ * VMM data kept in the ring-0 GVM.
+ */
+typedef struct VMMR0PERVM
+{
+    /** Logger (debug) buffer allocation.
+     * This covers all CPUs.  */
+    RTR0MEMOBJ          hMemObjLogger;
+    /** The ring-3 mapping object for hMemObjLogger. */
+    RTR0MEMOBJ          hMapObjLogger;
+
+    /** Release logger buffer allocation.
+     * This covers all CPUs.  */
+    RTR0MEMOBJ          hMemObjReleaseLogger;
+    /** The ring-3 mapping object for hMemObjReleaseLogger. */
+    RTR0MEMOBJ          hMapObjReleaseLogger;
+
+    /** Set if vmmR0InitVM has been called. */
+    bool                fCalledInitVm;
+} VMMR0PERVM;
 
 RT_C_DECLS_BEGIN
@@ -593,29 +633,4 @@
 DECLASM(int)    vmmR0CallRing3LongJmp(PVMMR0JMPBUF pJmpBuf, int rc);
 
-/**
- * Internal R0 logger worker: Logger wrapper.
- */
-VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...);
-
-/**
- * Internal R0 logger worker: Flush logger.
- *
- * @param   pLogger     The logger instance to flush.
- * @remark  This function must be exported!
- */
-VMMR0DECL(void) vmmR0LoggerFlush(PRTLOGGER pLogger);
-
-/**
- * Internal R0 logger worker: Custom prefix.
- *
- * @returns Number of chars written.
- *
- * @param   pLogger     The logger instance.
- * @param   pchBuf      The output buffer.
- * @param   cchBuf      The size of the buffer.
- * @param   pvUser      User argument (ignored).
- */
-VMMR0DECL(size_t) vmmR0LoggerPrefix(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser);
-
 # ifdef VBOX_WITH_TRIPLE_FAULT_HACK
 int  vmmR0TripleFaultHackInit(void);
Index: /trunk/src/VBox/VMM/include/VMMInternal.mac
===================================================================
--- /trunk/src/VBox/VMM/include/VMMInternal.mac	(revision 90828)
+++ /trunk/src/VBox/VMM/include/VMMInternal.mac	(revision 90829)
@@ -116,9 +116,4 @@
         .pbEMTStackR3           RTR3PTR_RES 1
 
-        .pR0LoggerR3            RTR3PTR_RES 1
-        .pR0LoggerR0            RTR0PTR_RES 1
-        .pR0RelLoggerR3         RTR3PTR_RES 1
-        .pR0RelLoggerR0         RTR0PTR_RES 1
-
         .fInRendezvous          resb 1
         .afPadding1             resb 2
