[Pkg-virtualbox-commits] [virtualbox] 01/03: Imported Upstream version 5.1.14-dfsg

Gianfranco Costamagna locutusofborg at moszumanska.debian.org
Tue Jan 17 15:01:29 UTC 2017


This is an automated email from the git hooks/post-receive script.

locutusofborg pushed a commit to branch master
in repository virtualbox.

commit 057939e0d242be672f5c77940088065959aa6fb7
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date:   Tue Jan 17 15:51:45 2017 +0100

    Imported Upstream version 5.1.14-dfsg
---
 Config.kmk                                         |   4 +-
 doc/manual/user_ChangeLogImpl.xml                  |  58 ++
 include/iprt/formats/pecoff.h                      | 130 +++-
 include/iprt/ldr.h                                 |  14 +-
 include/iprt/mangling.h                            |   1 +
 include/iprt/nt/nt.h                               |  24 +-
 src/VBox/Additions/linux/sharedfolders/regops.c    |  33 +-
 src/VBox/Devices/Audio_50/DevHDA.cpp               |  32 +-
 src/VBox/Devices/Audio_50/DevIchAc97.cpp           |  15 +-
 src/VBox/Devices/Audio_50/DevSB16.cpp              |   4 +-
 src/VBox/Devices/Audio_50/DrvAudio.cpp             |  10 +-
 src/VBox/Devices/Audio_50/DrvHostCoreAudio.cpp     | 114 ++-
 src/VBox/Devices/Audio_50/DrvHostDSound.cpp        |  38 +-
 src/VBox/Devices/Audio_50/HDACodec.cpp             |   3 +-
 .../Audio_50/testcase/tstAudioMixBuffer.cpp        |   1 -
 src/VBox/Devices/Bus/DevPciIch9.cpp                | 469 +++++++-----
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd      | Bin 2097152 -> 2097152 bytes
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd      | Bin 2097152 -> 2097152 bytes
 .../Graphics/BIOS/VBoxVgaBiosAlternative286.asm    |   6 +-
 .../Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum |   2 +-
 .../Graphics/BIOS/VBoxVgaBiosAlternative386.asm    |   6 +-
 .../Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum |   2 +-
 .../Graphics/BIOS/VBoxVgaBiosAlternative8086.asm   |   6 +-
 .../BIOS/VBoxVgaBiosAlternative8086.md5sum         |   2 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA.cpp          | 821 ++++++++++++++++-----
 src/VBox/Devices/Graphics/DevVGA-SVGA.h            |   2 +
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m    |  10 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h |   1 +
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp    |   7 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp    |  26 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp        |  15 +-
 src/VBox/Devices/Graphics/DevVGA.cpp               |  13 +-
 src/VBox/Devices/Graphics/DevVGA.h                 |  86 +++
 .../Devices/PC/BIOS/VBoxBiosAlternative286.asm     |   4 +-
 .../Devices/PC/BIOS/VBoxBiosAlternative286.md5sum  |   2 +-
 .../Devices/PC/BIOS/VBoxBiosAlternative386.asm     |   4 +-
 .../Devices/PC/BIOS/VBoxBiosAlternative386.md5sum  |   2 +-
 .../Devices/PC/BIOS/VBoxBiosAlternative8086.asm    |   4 +-
 .../Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum |   2 +-
 src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp   |  23 +
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts |  32 +-
 .../VirtualBox/src/globals/UIMessageCenter.cpp     |  22 +
 .../VirtualBox/src/globals/UIMessageCenter.h       |   2 +
 .../Frontends/VirtualBox/src/net/UIDownloader.cpp  |  40 +-
 .../Frontends/VirtualBox/src/net/UIDownloader.h    |  22 +-
 .../VirtualBox/src/net/UIDownloaderAdditions.cpp   |  73 +-
 .../VirtualBox/src/net/UIDownloaderAdditions.h     |   2 +
 .../src/net/UIDownloaderExtensionPack.cpp          |  82 +-
 .../VirtualBox/src/net/UIDownloaderExtensionPack.h |   2 +
 .../VirtualBox/src/net/UIUpdateManager.cpp         |   4 +-
 .../VirtualBox/src/runtime/UIMultiScreenLayout.cpp |  17 +-
 .../VirtualBox/src/runtime/UIMultiScreenLayout.h   |   1 +
 .../VirtualBox/src/selector/VBoxSnapshotsWgt.cpp   |   2 +-
 .../src/wizards/newvm/UIWizardNewVMPageBasic1.cpp  |  12 +-
 src/VBox/HostServices/SharedFolders/shflhandle.h   |   1 +
 src/VBox/HostServices/SharedFolders/vbsf.cpp       | 387 ++++++----
 src/VBox/Main/include/GuestSessionImpl.h           |   2 -
 src/VBox/Main/include/MachineImpl.h                |  49 +-
 src/VBox/Main/include/ThreadTask.h                 |  10 +-
 src/VBox/Main/include/ovfreader.h                  |   4 +-
 src/VBox/Main/src-all/ThreadTask.cpp               |  34 +-
 src/VBox/Main/src-client/GuestDnDTargetImpl.cpp    |   6 +-
 src/VBox/Main/src-client/GuestSessionImpl.cpp      |  33 -
 src/VBox/Main/src-server/MachineImpl.cpp           |  39 +-
 src/VBox/Main/src-server/SnapshotImpl.cpp          |  47 +-
 src/VBox/Main/src-server/VirtualBoxImpl.cpp        |  67 +-
 src/VBox/Main/src-server/xpcom/server.cpp          |   3 +
 src/VBox/Runtime/common/ldr/ldrFile.cpp            |  31 +-
 src/VBox/Runtime/common/ldr/ldrPE.cpp              |  50 +-
 src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c  |   6 +-
 .../r0drv/linux/mpnotification-r0drv-linux.c       |  55 +-
 src/VBox/Runtime/testcase/tstLdr-2.cpp             |   5 +-
 src/VBox/Runtime/testcase/tstLdr-3.cpp             |   5 +-
 src/VBox/Runtime/testcase/tstLdr-4.cpp             |   4 +-
 src/VBox/VMM/VMMAll/IEMAllAImplC.cpp               |  15 +-
 src/VBox/VMM/VMMR0/HMVMXR0.cpp                     |  53 +-
 src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp           |  49 +-
 src/VBox/VMM/VMMRZ/VMMRZ.cpp                       |   6 +-
 78 files changed, 2303 insertions(+), 967 deletions(-)

diff --git a/Config.kmk b/Config.kmk
index 606b00d..8637671 100644
--- a/Config.kmk
+++ b/Config.kmk
@@ -208,7 +208,7 @@ VBOX_VERSION_MINOR = 1
 # This is the current build number. It should be increased every time we publish a
 # new build. The define is available in every source file. Only even build numbers
 # will be published, odd numbers are set during development.
-VBOX_VERSION_BUILD = 12
+VBOX_VERSION_BUILD = 14
 # The raw version string. This *must not* contain any other information/fields than
 # major, minor and build revision (as it is now) -- also will be used for host/guest version
 # comparison.
@@ -6955,7 +6955,7 @@ endif
 SVN                    ?= svn$(HOSTSUFF_EXE)
 VBOX_SVN_REV_KMK        = $(PATH_OUT)/revision.kmk
 ifndef VBOX_SVN_REV
- VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 112440 $  )
+ VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 112924 $  )
  VBOX_SVN_DEP          := $(firstword $(wildcard $(PATH_ROOT)/.svn/wc.db $(abspath $(PATH_ROOT)/../.svn/wc.db) $(abspath $(PATH_ROOT)/../../.svn/wc.db) $(PATH_ROOT)/.svn/entries))
  ifeq ($(which $(SVN)),)
   VBOX_SVN_DEP         :=
diff --git a/doc/manual/user_ChangeLogImpl.xml b/doc/manual/user_ChangeLogImpl.xml
index 0568c74..4086b34 100644
--- a/doc/manual/user_ChangeLogImpl.xml
+++ b/doc/manual/user_ChangeLogImpl.xml
@@ -3,6 +3,64 @@
 <chapter> <!-- HACK ALERT! Seems we must have a single top level element for xi:include to work.
                            So, we use chapter and xpointer="xpointer(/chapter/)" with xi:include. -->
   <sect1>
+    <title>Version 5.1.14 (2017-01-16)</title>
+
+    <para>This is a maintenance release. The following items were fixed and/or
+      added:</para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>VMM: fixed emulation of certain instructions for 64-bit guests
+          on 32-bit hosts</para>
+      </listitem>
+
+      <listitem>
+        <para>VMM: properly handle certain MSRs for 64-bit guests on ancient
+          CPUs without VT-x support for MSR bitmaps (bug #13886)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: fixed a crash with multimonitor setups under certain
+          conditions</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: allow cloning of snapshots when the VM is running</para>
+      </listitem>
+
+      <listitem>
+        <para>NVMe: fixed compatibility with the Storage Performance Development
+          Kit (SPDK, bug #16368)</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxSVC: fixed a crash under rare circumstances</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxManage: added a sanity check to
+          <emphasis>modifymedium --resize</emphasis> to prevent users from
+          resizing their hard disk from 1GB to 1PB (bug #16311)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows hosts: another fix for recent Windows 10 hosts</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts: Linux 4.10 fixes</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux Additions: fixed protocol error during certain operations on
+          shared folders (bug #8463)</para>
+      </listitem>
+
+    </itemizedlist>
+  </sect1>
+
+  <sect1>
     <title>Version 5.1.12 (2016-12-20)</title>
 
     <para>This is a maintenance release. The following items were fixed and/or
diff --git a/include/iprt/formats/pecoff.h b/include/iprt/formats/pecoff.h
index 46d2f22..e92ce64 100644
--- a/include/iprt/formats/pecoff.h
+++ b/include/iprt/formats/pecoff.h
@@ -789,18 +789,67 @@ typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V7
     uint32_t  GuardLongJumpTargetTable;             /**< 0x70 */
     uint32_t  GuardLongJumpTargetCount;             /**< 0x74 */
     uint32_t  DynamicValueRelocTable;               /**< 0x78 */
-    uint32_t  HybridMetadataPointer;                /**< 0x7c */
-    uint32_t  FailFastIndirectProc;                 /**< 0x80 - temporary name, rename when we get symbols */
-    uint32_t  FailFastPointer;                      /**< 0x84 - temporary name, rename when we get symbols */
-    uint32_t  UnknownZero1;                         /**< 0x88 - temporary name, rename when we get symbols */
+    uint32_t  CHPEMetadataPointer;                  /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+    uint32_t  GuardRFFailureRoutine;                /**< 0x80 */
+    uint32_t  GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+    uint32_t  DynamicValueRelocTableOffset;         /**< 0x88 */
+    uint16_t  DynamicValueRelocTableSection;        /**< 0x8c */
+    uint16_t  Reserved2;                            /**< 0x8e */
 } IMAGE_LOAD_CONFIG_DIRECTORY32_V7;
-AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V7, 0x8c);
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V7, 0x90);
 typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V7 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V7;
 typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V7 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V7;
 
-typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V7   IMAGE_LOAD_CONFIG_DIRECTORY32;
-typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V7  PIMAGE_LOAD_CONFIG_DIRECTORY32;
-typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V7 PCIMAGE_LOAD_CONFIG_DIRECTORY32;
+/** @since  Windows 10 build 15002 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V8
+{
+    uint32_t  Size;                                 /**< 0x00 */
+    uint32_t  TimeDateStamp;                        /**< 0x04 */
+    uint16_t  MajorVersion;                         /**< 0x08 */
+    uint16_t  MinorVersion;                         /**< 0x0a */
+    uint32_t  GlobalFlagsClear;                     /**< 0x0c */
+    uint32_t  GlobalFlagsSet;                       /**< 0x10 */
+    uint32_t  CriticalSectionDefaultTimeout;        /**< 0x14 */
+    uint32_t  DeCommitFreeBlockThreshold;           /**< 0x18 */
+    uint32_t  DeCommitTotalFreeThreshold;           /**< 0x1c */
+    uint32_t  LockPrefixTable;                      /**< 0x20 */
+    uint32_t  MaximumAllocationSize;                /**< 0x24 */
+    uint32_t  VirtualMemoryThreshold;               /**< 0x28 */
+    uint32_t  ProcessHeapFlags;                     /**< 0x2c */
+    uint32_t  ProcessAffinityMask;                  /**< 0x30 */
+    uint16_t  CSDVersion;                           /**< 0x34 */
+    uint16_t  DependentLoadFlags;                   /**< 0x36 */
+    uint32_t  EditList;                             /**< 0x38 */
+    uint32_t  SecurityCookie;                       /**< 0x3c */
+    uint32_t  SEHandlerTable;                       /**< 0x40 */
+    uint32_t  SEHandlerCount;                       /**< 0x44 */
+    uint32_t  GuardCFCCheckFunctionPointer;         /**< 0x48 */
+    uint32_t  GuardCFDispatchFunctionPointer;       /**< 0x4c */
+    uint32_t  GuardCFFunctionTable;                 /**< 0x50 */
+    uint32_t  GuardCFFunctionCount;                 /**< 0x54 */
+    uint32_t  GuardFlags;                           /**< 0x58 */
+    IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+    uint32_t  GuardAddressTakenIatEntryTable;       /**< 0x68 */
+    uint32_t  GuardAddressTakenIatEntryCount;       /**< 0x6c */
+    uint32_t  GuardLongJumpTargetTable;             /**< 0x70 */
+    uint32_t  GuardLongJumpTargetCount;             /**< 0x74 */
+    uint32_t  DynamicValueRelocTable;               /**< 0x78 */
+    uint32_t  CHPEMetadataPointer;                  /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+    uint32_t  GuardRFFailureRoutine;                /**< 0x80 */
+    uint32_t  GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+    uint32_t  DynamicValueRelocTableOffset;         /**< 0x88 */
+    uint16_t  DynamicValueRelocTableSection;        /**< 0x8c */
+    uint16_t  Reserved2;                            /**< 0x8e */
+    uint32_t  GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+    uint32_t  HotPatchTableOffset;                  /**< 0x94 */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V8;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V8, 0x98);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V8;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V8;
+
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8   IMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V8  PIMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V8 PCIMAGE_LOAD_CONFIG_DIRECTORY32;
 
 
 /* No _IMAGE_LOAD_CONFIG_DIRECTORY64_V1 exists. */
@@ -1012,18 +1061,69 @@ typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V7
     uint64_t  GuardLongJumpTargetTable;             /**< 0xb0 */
     uint64_t  GuardLongJumpTargetCount;             /**< 0xb8 */
     uint64_t  DynamicValueRelocTable;               /**< 0xc0 */
-    uint64_t  HybridMetadataPointer;                /**< 0xc8 */
-    uint64_t  FailFastIndirectProc;                 /**< 0xd0 - temporary name, rename when we get symbols */
-    uint64_t  FailFastPointer;                      /**< 0xd8 - temporary name, rename when we get symbols */
-    uint64_t  UnknownZero1;                         /**< 0xe0 - temporary name, rename when we get symbols */
+    uint64_t  CHPEMetadataPointer;                  /**< 0xc8 Not sure when this was renamed from HybridMetadataPointer. */
+    uint64_t  GuardRFFailureRoutine;                /**< 0xd0 */
+    uint64_t  GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+    uint32_t  DynamicValueRelocTableOffset;         /**< 0xe0 */
+    uint16_t  DynamicValueRelocTableSection;        /**< 0xe4 */
+    uint16_t  Reserved2;                            /**< 0xe6 */
 } IMAGE_LOAD_CONFIG_DIRECTORY64_V7;
 AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V7, 0xe8);
 typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V7 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V7;
 typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V7 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V7;
 
-typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V7   IMAGE_LOAD_CONFIG_DIRECTORY64;
-typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V7  PIMAGE_LOAD_CONFIG_DIRECTORY64;
-typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V7 PCIMAGE_LOAD_CONFIG_DIRECTORY64;
+/** @since  Windows 10 build 15002 (or maybe earlier). */
+#pragma pack(4) /* Stupid, stupid microsofties! */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V8
+{
+    uint32_t  Size;                                 /**< 0x00 */
+    uint32_t  TimeDateStamp;                        /**< 0x04 */
+    uint16_t  MajorVersion;                         /**< 0x08 */
+    uint16_t  MinorVersion;                         /**< 0x0a */
+    uint32_t  GlobalFlagsClear;                     /**< 0x0c */
+    uint32_t  GlobalFlagsSet;                       /**< 0x10 */
+    uint32_t  CriticalSectionDefaultTimeout;        /**< 0x14 */
+    uint64_t  DeCommitFreeBlockThreshold;           /**< 0x18 */
+    uint64_t  DeCommitTotalFreeThreshold;           /**< 0x20 */
+    uint64_t  LockPrefixTable;                      /**< 0x28 */
+    uint64_t  MaximumAllocationSize;                /**< 0x30 */
+    uint64_t  VirtualMemoryThreshold;               /**< 0x38 */
+    uint64_t  ProcessAffinityMask;                  /**< 0x40 */
+    uint32_t  ProcessHeapFlags;                     /**< 0x48 */
+    uint16_t  CSDVersion;                           /**< 0x4c */
+    uint16_t  DependentLoadFlags;                   /**< 0x4e */
+    uint64_t  EditList;                             /**< 0x50 */
+    uint64_t  SecurityCookie;                       /**< 0x58 */
+    uint64_t  SEHandlerTable;                       /**< 0x60 */
+    uint64_t  SEHandlerCount;                       /**< 0x68 */
+    uint64_t  GuardCFCCheckFunctionPointer;         /**< 0x70 */
+    uint64_t  GuardCFDispatchFunctionPointer;       /**< 0x78 */
+    uint64_t  GuardCFFunctionTable;                 /**< 0x80 */
+    uint64_t  GuardCFFunctionCount;                 /**< 0x88 */
+    uint32_t  GuardFlags;                           /**< 0x90 */
+    IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+    uint64_t  GuardAddressTakenIatEntryTable;       /**< 0xa0 */
+    uint64_t  GuardAddressTakenIatEntryCount;       /**< 0xa8 */
+    uint64_t  GuardLongJumpTargetTable;             /**< 0xb0 */
+    uint64_t  GuardLongJumpTargetCount;             /**< 0xb8 */
+    uint64_t  DynamicValueRelocTable;               /**< 0xc0 */
+    uint64_t  CHPEMetadataPointer;                  /**< 0xc8 */
+    uint64_t  GuardRFFailureRoutine;                /**< 0xd0 */
+    uint64_t  GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+    uint32_t  DynamicValueRelocTableOffset;         /**< 0xe0 */
+    uint16_t  DynamicValueRelocTableSection;        /**< 0xe4 */
+    uint16_t  Reserved2;                            /**< 0xe6 */
+    uint64_t  GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+    uint32_t  HotPatchTableOffset;                  /**< 0xf0 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V8;
+#pragma pack()
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V8, 0xf4);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V8;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V8;
+
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8   IMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V8  PIMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V8 PCIMAGE_LOAD_CONFIG_DIRECTORY64;
 
 /** @} */
 
diff --git a/include/iprt/ldr.h b/include/iprt/ldr.h
index 9f2c1e0..a9d9349 100644
--- a/include/iprt/ldr.h
+++ b/include/iprt/ldr.h
@@ -375,7 +375,7 @@ typedef RTLDRARCH *PRTLDRARCH;
 /** @} */
 
 /**
- * Open a binary image file, extended version.
+ * Open a binary image file.
  *
  * @returns iprt status code.
  * @param   pszFilename Image filename.
@@ -386,6 +386,18 @@ typedef RTLDRARCH *PRTLDRARCH;
 RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod);
 
 /**
+ * Open a binary image file, extended version.
+ *
+ * @returns iprt status code.
+ * @param   pszFilename Image filename.
+ * @param   fFlags      Valid RTLDR_O_XXX combination.
+ * @param   enmArch     CPU architecture specifier for the image to be loaded.
+ * @param   phLdrMod    Where to store the handle to the loader module.
+ * @param   pErrInfo    Where to return extended error information. Optional.
+ */
+RTDECL(int) RTLdrOpenEx(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
+
+/**
  * Opens a binary image file using kLdr.
  *
  * @returns iprt status code.
diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h
index 52ec21f..465100a 100644
--- a/include/iprt/mangling.h
+++ b/include/iprt/mangling.h
@@ -1003,6 +1003,7 @@
 # define RTLdrLoadEx                                    RT_MANGLER(RTLdrLoadEx)
 # define RTLdrLoadSystem                                RT_MANGLER(RTLdrLoadSystem)
 # define RTLdrOpen                                      RT_MANGLER(RTLdrOpen)
+# define RTLdrOpenEx                                    RT_MANGLER(RTLdrOpenEx)
 # define RTLdrOpenInMemory                              RT_MANGLER(RTLdrOpenInMemory)
 # define RTLdrOpenkLdr                                  RT_MANGLER(RTLdrOpenkLdr)
 # define RTLdrRelocate                                  RT_MANGLER(RTLdrRelocate)
diff --git a/include/iprt/nt/nt.h b/include/iprt/nt/nt.h
index e16cedc..136b5ed 100644
--- a/include/iprt/nt/nt.h
+++ b/include/iprt/nt/nt.h
@@ -985,6 +985,13 @@ typedef struct _PEB_COMMON
     uint32_t Padding6;                                                      /**< 0x37c / NA */
 #endif
     uint64_t CsrServerReadOnlySharedMemoryBase;                             /**< 0x380 / 0x248 */
+    /* End of PEB in W8, W81. */
+    uintptr_t TppWorkerpListLock;                                           /**< 0x388 / 0x250 */
+    LIST_ENTRY TppWorkerpList;                                              /**< 0x390 / 0x254 */
+    PVOID WaitOnAddressHashTable[128];                                      /**< 0x3a0 / 0x25c */
+#if ARCH_BITS == 32
+    uint32_t ExplicitPadding7;                                              /**< NA NA / 0x45c */
+#endif
 } PEB_COMMON;
 typedef PEB_COMMON *PPEB_COMMON;
 
@@ -996,12 +1003,14 @@ AssertCompileMemberOffset(PEB_COMMON, LoaderLock,     ARCH_BITS == 64 ? 0x110 :
 AssertCompileMemberOffset(PEB_COMMON, Diff5.W52.ImageProcessAffinityMask, ARCH_BITS == 64 ? 0x138 :  0xc0);
 AssertCompileMemberOffset(PEB_COMMON, PostProcessInitRoutine,    ARCH_BITS == 64 ? 0x230 : 0x14c);
 AssertCompileMemberOffset(PEB_COMMON, AppCompatFlags, ARCH_BITS == 64 ? 0x2c8 : 0x1d8);
-AssertCompileSize(PEB_COMMON, ARCH_BITS == 64 ? 0x388 : 0x250);
+AssertCompileSize(PEB_COMMON, ARCH_BITS == 64 ? 0x7a0 : 0x460);
 
+/** The size of the windows 10 (build 14393) PEB structure. */
+#define PEB_SIZE_W10    sizeof(PEB_COMMON)
 /** The size of the windows 8.1 PEB structure.  */
-#define PEB_SIZE_W81    sizeof(PEB_COMMON)
+#define PEB_SIZE_W81    RT_UOFFSETOF(PEB_COMMON, TppWorkerpListLock)
 /** The size of the windows 8.0 PEB structure.  */
-#define PEB_SIZE_W80    sizeof(PEB_COMMON)
+#define PEB_SIZE_W80    RT_UOFFSETOF(PEB_COMMON, TppWorkerpListLock)
 /** The size of the windows 7 PEB structure.  */
 #define PEB_SIZE_W7     RT_UOFFSETOF(PEB_COMMON, CsrServerReadOnlySharedMemoryBase)
 /** The size of the windows vista PEB structure.  */
@@ -1373,7 +1382,10 @@ typedef struct _TEB_COMMON
             /* End of TEB in W7 (windows 7)! */
             PVOID ReservedForWdf;                                          /**< 0x1818 / 0xfe4 - New Since W7. */
             /* End of TEB in W8 (windows 8.0 & 8.1)! */
-        } W8, W80, W81;
+            PVOID ReservedForCrt;                                          /**< 0x1820 / 0xfe8 - New Since W10.  */
+            RTUUID EffectiveContainerId;                                   /**< 0x1828 / 0xfec - New Since W10.  */
+            /* End of TEB in W10 14393! */
+        } W8, W80, W81, W10;
         struct
         {
             PVOID ResourceRetValue;                                        /**< 0x1810 / 0xfe0 */
@@ -1400,10 +1412,12 @@ AssertCompileMemberOffset(TEB_COMMON, WinSockData,          ARCH_BITS == 64 ? 0x
 AssertCompileMemberOffset(TEB_COMMON, GuaranteedStackBytes, ARCH_BITS == 64 ? 0x1748 : 0xf78);
 AssertCompileMemberOffset(TEB_COMMON, MuiImpersonation,     ARCH_BITS == 64 ? 0x17e8 : 0xfc4);
 AssertCompileMemberOffset(TEB_COMMON, LockCount,            ARCH_BITS == 64 ? 0x1808 : 0xfd8);
-AssertCompileSize(TEB_COMMON, ARCH_BITS == 64 ? 0x1828 : 0xff8);
+AssertCompileSize(TEB_COMMON, ARCH_BITS == 64 ? 0x1838 : 0x1000);
 
 
 /** The size of the windows 8.1 PEB structure.  */
+#define TEB_SIZE_W10    ( RT_UOFFSETOF(TEB_COMMON, Diff12.W10.EffectiveContainerId) + sizeof(RTUUID) )
+/** The size of the windows 8.1 PEB structure.  */
 #define TEB_SIZE_W81    ( RT_UOFFSETOF(TEB_COMMON, Diff12.W8.ReservedForWdf) + sizeof(PVOID) )
 /** The size of the windows 8.0 PEB structure.  */
 #define TEB_SIZE_W80    ( RT_UOFFSETOF(TEB_COMMON, Diff12.W8.ReservedForWdf) + sizeof(PVOID) )
diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c
index 2a9f5c4..44b1f0f 100644
--- a/src/VBox/Additions/linux/sharedfolders/regops.c
+++ b/src/VBox/Additions/linux/sharedfolders/regops.c
@@ -328,8 +328,7 @@ static int sf_reg_open(struct inode *inode, struct file *file)
         if (file->f_flags & O_TRUNC)
         {
             LogFunc(("O_TRUNC set\n"));
-            params.CreateFlags |= (  SHFL_CF_ACT_OVERWRITE_IF_EXISTS
-                                   | SHFL_CF_ACCESS_WRITE);
+            params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
         }
         else
             params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
@@ -340,30 +339,26 @@ static int sf_reg_open(struct inode *inode, struct file *file)
         if (file->f_flags & O_TRUNC)
         {
             LogFunc(("O_TRUNC set\n"));
-            params.CreateFlags |= (  SHFL_CF_ACT_OVERWRITE_IF_EXISTS
-                    | SHFL_CF_ACCESS_WRITE);
+            params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
         }
     }
 
-    if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE))
+    switch (file->f_flags & O_ACCMODE)
     {
-        switch (file->f_flags & O_ACCMODE)
-        {
-            case O_RDONLY:
-                params.CreateFlags |= SHFL_CF_ACCESS_READ;
-                break;
+        case O_RDONLY:
+            params.CreateFlags |= SHFL_CF_ACCESS_READ;
+            break;
 
-            case O_WRONLY:
-                params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
-                break;
+        case O_WRONLY:
+            params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
+            break;
 
-            case O_RDWR:
-                params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
-                break;
+        case O_RDWR:
+            params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
+            break;
 
-            default:
-                BUG ();
-        }
+        default:
+            BUG ();
     }
 
     if (file->f_flags & O_APPEND)
diff --git a/src/VBox/Devices/Audio_50/DevHDA.cpp b/src/VBox/Devices/Audio_50/DevHDA.cpp
index acc0e34..2c619d6 100644
--- a/src/VBox/Devices/Audio_50/DevHDA.cpp
+++ b/src/VBox/Devices/Audio_50/DevHDA.cpp
@@ -813,7 +813,7 @@ static int  hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value
 static int  hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
 static int  hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
 static int  hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-DECLINLINE(bool) hdaRegWriteSDIsAllowed(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+inline bool hdaRegWriteSDIsAllowed(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
 
 /*
  * Generic register read/write functions.
@@ -1249,10 +1249,13 @@ static int hdaProcessInterrupt(PHDASTATE pThis)
  * Looks up a register at the exact offset given by @a offReg.
  *
  * @returns Register index on success, -1 if not found.
+ * @param   pThis               The HDA device state.
  * @param   offReg              The register offset.
  */
-static int hdaRegLookup(uint32_t offReg)
+static int hdaRegLookup(PHDASTATE pThis, uint32_t offReg)
 {
+    RT_NOREF(pThis);
+
     /*
      * Aliases.
      */
@@ -1300,10 +1303,13 @@ static int hdaRegLookup(uint32_t offReg)
  * Looks up a register covering the offset given by @a offReg.
  *
  * @returns Register index on success, -1 if not found.
+ * @param   pThis               The HDA device state.
  * @param   offReg              The register offset.
  */
-static int hdaRegLookupWithin(uint32_t offReg)
+static int hdaRegLookupWithin(PHDASTATE pThis, uint32_t offReg)
 {
+     RT_NOREF(pThis);
+
     /*
      * Aliases.
      */
@@ -1440,7 +1446,8 @@ static int hdaCORBCmdProcess(PHDASTATE pThis)
             rc = pfn(pThis->pCodec, HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp);
         }
 
-        AssertRCReturn(rc, rc);
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
         (rirbWp)++;
 
         LogFunc(("verb:%08x->%016lx\n", cmd, resp));
@@ -1824,9 +1831,12 @@ static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
 static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
 {
     const uint8_t  u8Strm  = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
-    uint32_t       u32LPIB = HDA_STREAM_REG(pThis, LPIB, u8Strm);
+          uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, u8Strm);
 
-    LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32\n", u8Strm, u32LPIB, HDA_STREAM_REG(pThis, CBL,  u8Strm)));
+#if defined(LOG_ENABLED)
+    const uint32_t u32CBL  = HDA_STREAM_REG(pThis, CBL,  u8Strm);
+    LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32\n", u8Strm, u32LPIB, u32CBL));
+#endif
 
     *pu32Value = u32LPIB;
     return VINF_SUCCESS;
@@ -2308,7 +2318,7 @@ static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
  * @param   iReg                Register to write.
  * @param   u32Value            Value to write.
  */
-DECLINLINE(bool) hdaRegWriteSDIsAllowed(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+inline bool hdaRegWriteSDIsAllowed(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
     RT_NOREF(u32Value);
 
@@ -3369,7 +3379,7 @@ PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhys
      * Look up and log.
      */
     uint32_t        offReg = GCPhysAddr - pThis->MMIOBaseAddr;
-    int             idxRegDsc = hdaRegLookup(offReg);    /* Register descriptor index. */
+    int             idxRegDsc = hdaRegLookup(pThis, offReg);    /* Register descriptor index. */
 #ifdef LOG_ENABLED
     unsigned const  cbLog     = cb;
     uint32_t        offRegLog = offReg;
@@ -3488,7 +3498,7 @@ PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhy
      * Look up and log the access.
      */
     uint32_t    offReg = GCPhysAddr - pThis->MMIOBaseAddr;
-    int         idxRegDsc = hdaRegLookup(offReg);
+    int         idxRegDsc = hdaRegLookup(pThis, offReg);
     uint32_t    idxRegMem = idxRegDsc != -1 ? g_aHdaRegMap[idxRegDsc].mem_idx : UINT32_MAX;
     uint64_t    u64Value;
     if (cb == 4)        u64Value = *(uint32_t const *)pv;
@@ -3537,7 +3547,7 @@ PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhy
          * will only see 1 or 2 byte accesses of this kind, so no risk of
          * shifting out input values.
          */
-        if (idxRegDsc == -1 && (idxRegDsc = hdaRegLookupWithin(offReg)) != -1)
+        if (idxRegDsc == -1 && (idxRegDsc = hdaRegLookupWithin(pThis, offReg)) != -1)
         {
             uint32_t const cbBefore = offReg - g_aHdaRegMap[idxRegDsc].offset; Assert(cbBefore > 0 && cbBefore < 4);
             offReg    -= cbBefore;
@@ -3584,7 +3594,7 @@ PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhy
             cb     -= cbReg;
             u64Value >>= cbReg * 8;
             if (idxRegDsc == -1)
-                idxRegDsc = hdaRegLookup(offReg);
+                idxRegDsc = hdaRegLookup(pThis, offReg);
             else
             {
                 idxRegDsc++;
diff --git a/src/VBox/Devices/Audio_50/DevIchAc97.cpp b/src/VBox/Devices/Audio_50/DevIchAc97.cpp
index 9bd4811..61f231e 100644
--- a/src/VBox/Devices/Audio_50/DevIchAc97.cpp
+++ b/src/VBox/Devices/Audio_50/DevIchAc97.cpp
@@ -995,6 +995,10 @@ static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbM
     PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
     PAC97BMREGS pRegs   = &pStrmSt->Regs;
 
+    uint32_t    addr           = pRegs->bd.addr;
+    uint32_t    cbWrittenTotal = 0;
+    uint32_t    cbToRead       = 0;
+
     uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax);
     if (!cbToWrite)
     {
@@ -1003,10 +1007,7 @@ static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbM
         return VINF_EOF;
     }
 
-    uint32_t addr = pRegs->bd.addr;
-    int      rc = VINF_SUCCESS;
-    uint32_t cbWrittenTotal = 0;
-    uint32_t cbToRead = 0;
+    int rc = VINF_SUCCESS;
 
     LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pRegs, cbMax, cbToWrite));
 
@@ -1024,7 +1025,8 @@ static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbM
         {
             int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
                                                  pThis->pvReadWriteBuf, cbToRead, &cbWritten);
-            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten)); NOREF(rc2);
+            RT_NOREF(rc2);
+            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
         }
 
         LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n",
@@ -1766,7 +1768,8 @@ static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser,
 /**
  * @callback_method_impl{FNIOMIOPORTOUT}
  */
-static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32Val, unsigned cbVal)
+static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
+                                               void *pvUser, RTIOPORT Port, uint32_t u32Val, unsigned cbVal)
 {
     RT_NOREF(pDevIns);
     PAC97STATE pThis = (PAC97STATE)pvUser;
diff --git a/src/VBox/Devices/Audio_50/DevSB16.cpp b/src/VBox/Devices/Audio_50/DevSB16.cpp
index 25658f9..81d0026 100644
--- a/src/VBox/Devices/Audio_50/DevSB16.cpp
+++ b/src/VBox/Devices/Audio_50/DevSB16.cpp
@@ -1639,7 +1639,8 @@ static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos,
         {
             int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
                                                  tmpbuf, cbToRead, &cbWritten);
-            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten)); NOREF(rc2);
+            RT_NOREF(rc2);
+            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
         }
 
         Assert(cbToWrite >= cbToRead);
@@ -2157,6 +2158,7 @@ static DECLCALLBACK(int) sb16Destruct(PPDMDEVINS pDevIns)
     PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
 
     PSB16DRIVER pDrv;
+
     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
         pDrv->Out.phStrmOut = NULL;
 
diff --git a/src/VBox/Devices/Audio_50/DrvAudio.cpp b/src/VBox/Devices/Audio_50/DrvAudio.cpp
index 5385be1..a7b8992 100644
--- a/src/VBox/Devices/Audio_50/DrvAudio.cpp
+++ b/src/VBox/Devices/Audio_50/DrvAudio.cpp
@@ -1748,10 +1748,10 @@ static DECLCALLBACK(int) drvAudioCallback(PPDMIAUDIOCONNECTOR pInterface, PDMAUD
  * @param   pThis               Driver instance to be called.
  * @param   pCfgHandle          CFGM configuration handle to use for this driver.
  */
-static int drvAudioHostInit(PDRVAUDIO pThis, PCFGMNODE pCfgHandle)
+static int drvAudioHostInit(PCFGMNODE pCfgHandle, PDRVAUDIO pThis)
 {
     /* pCfgHandle is optional. */
-    NOREF(pCfgHandle);
+    RT_NOREF(pCfgHandle);
     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
 
     LogFlowFuncEnter();
@@ -1760,7 +1760,7 @@ static int drvAudioHostInit(PDRVAUDIO pThis, PCFGMNODE pCfgHandle)
     int rc = pThis->pHostDrvAudio->pfnInit(pThis->pHostDrvAudio);
     if (RT_FAILURE(rc))
     {
-        LogRel(("Audio: Initialization of host backend failed with %Rrc\n", rc));
+        LogFlowFunc(("Initialization of lower driver failed with rc=%Rrc\n", rc));
         return VERR_AUDIO_BACKEND_INIT_FAILED;
     }
 
@@ -1768,7 +1768,7 @@ static int drvAudioHostInit(PDRVAUDIO pThis, PCFGMNODE pCfgHandle)
     rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg);
     if (RT_FAILURE(rc))
     {
-        LogRel(("Audio: Getting host backend configuration failed with %Rrc\n", rc));
+        LogFlowFunc(("Getting backend configuration failed with rc=%Rrc\n", rc));
         return VERR_AUDIO_BACKEND_INIT_FAILED;
     }
 
@@ -1911,7 +1911,7 @@ static DECLCALLBACK(int) drvAudioInit(PCFGMNODE pCfgHandle, PPDMDRVINS pDrvIns)
      * If everything went well, initialize the lower driver.
      */
     if (RT_SUCCESS(rc))
-        rc = drvAudioHostInit(pThis, pCfgHandle);
+        rc = drvAudioHostInit(pCfgHandle, pThis);
 
     LogFlowFuncLeaveRC(rc);
     return rc;
diff --git a/src/VBox/Devices/Audio_50/DrvHostCoreAudio.cpp b/src/VBox/Devices/Audio_50/DrvHostCoreAudio.cpp
index 1731769..11daedf 100644
--- a/src/VBox/Devices/Audio_50/DrvHostCoreAudio.cpp
+++ b/src/VBox/Devices/Audio_50/DrvHostCoreAudio.cpp
@@ -31,7 +31,6 @@
 
 #include <CoreAudio/CoreAudio.h>
 #include <CoreServices/CoreServices.h>
-#include <AudioUnit/AudioUnit.h>
 #include <AudioToolbox/AudioConverter.h>
 #include <AudioToolbox/AudioToolbox.h>
 
@@ -73,7 +72,6 @@
  * http://developer.apple.com/mac/library/technotes/tn2002/tn2091.html
  * http://developer.apple.com/mac/library/qa/qa2007/qa1533.html
  * http://developer.apple.com/mac/library/qa/qa2001/qa1317.html
- * http://developer.apple.com/mac/library/documentation/AudioUnit/Reference/AUComponentServicesReference/Reference/reference.html
  */
 
 /**
@@ -237,7 +235,7 @@ static AudioDeviceID drvHostCoreAudioDeviceUIDtoID(const char* pszUID)
  *
  ******************************************************************************/
 
-/* Initialization status indicator used for the recreation of the AudioUnits. */
+/* Initialization status indicator used for device (re)initialization. */
 #define CA_STATUS_UNINIT    UINT32_C(0) /* The device is uninitialized */
 #define CA_STATUS_IN_INIT   UINT32_C(1) /* The device is currently initializing */
 #define CA_STATUS_INIT      UINT32_C(2) /* The device is initialized */
@@ -334,8 +332,6 @@ typedef struct COREAUDIOSTREAMOUT
     PDMAUDIOHSTSTRMOUT          streamOut;
     /** The audio device ID of the currently used device. */
     AudioDeviceID               deviceID;
-    /** The AudioUnit being used. */
-    AudioUnit                   audioUnit;
     /** A ring buffer for transferring data to the playback thread. */
     PRTCIRCBUF                  pCircBuf;
     /** Initialization status tracker. Used when some of the device parameters
@@ -360,8 +356,6 @@ typedef struct COREAUDIOSTREAMIN
     PDMAUDIOHSTSTRMIN           streamIn;
     /** The audio device ID of the currently used device. */
     AudioDeviceID               deviceID;
-    /** The AudioUnit used. */
-    AudioUnit                   audioUnit;
     /** A ring buffer for transferring data from the recording thread. */
     PRTCIRCBUF                  pCircBuf;
 #ifdef VBOX_WITH_AUDIO_CA_CONVERTER
@@ -370,8 +364,6 @@ typedef struct COREAUDIOSTREAMIN
     /** Callback context for the audio converter. */
     COREAUDIOCONVCBCTX          convCbCtx;
 #endif
-    /** The ratio between the device & the stream sample rate. */
-    Float64                     sampleRatio;
     /** Initialization status tracker. Used when some of the device parameters
      *  or the device itself is changed during the runtime. */
     volatile uint32_t           status;
@@ -755,15 +747,26 @@ static DECLCALLBACK(int) coreAudioQueueThread(RTTHREAD hThreadSelf, void *pvUser
                                   CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &pCAStream->audioQueue);
 
     if (err != noErr)
+    {
+        LogRel(("CoreAudio: Failed to create audio queue (%RI32)\n", err));
         return VERR_GENERAL_FAILURE; /** @todo Fudge! */
+    }
 
+    ///@todo: The following code may cause subsequent AudioQueueStart to fail
+    // with !dev error (560227702). If we skip it entirely, we end up using the
+    // default device, which is what we're doing anyway. 
+#if 0
     /*
      * Assign device to queue.
      */
     UInt32 uSize = sizeof(pCAStream->UUID);
     err = AudioQueueSetProperty(pCAStream->audioQueue, kAudioQueueProperty_CurrentDevice, &pCAStream->UUID, uSize);
     if (err != noErr)
+    {
+        LogRel(("CoreAudio: Failed to set queue device UUID (%d)\n", err));
         return VERR_GENERAL_FAILURE; /** @todo Fudge! */
+    }
+#endif
 
     const size_t cbBufSize = AQ_BUF_SIZE; /** @todo Make this configurable! */
 
@@ -812,6 +815,7 @@ static DECLCALLBACK(int) coreAudioQueueThread(RTTHREAD hThreadSelf, void *pvUser
     }
 
     AudioQueueDispose(pCAStream->audioQueue, 1);
+    pCAStream->audioQueue = NULL;
 
     LogFunc(("Ended pCAStream=%p\n", pCAStream));
     return VINF_SUCCESS;
@@ -1096,6 +1100,7 @@ static int coreAudioStreamInitQueue(PCOREAUDIOSTREAM pCAStream, bool fIn, PPDMAU
     /*
      * Start the thread.
      */
+    pCAStream->fShutdown = false;
     rc = RTThreadCreate(&pCAStream->hThread, coreAudioQueueThread,
                         pCAStream /* pvUser */, 0 /* Default stack size */,
                         RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "CAQUEUE");
@@ -1172,13 +1177,20 @@ static int drvHostCoreAudioReinitInput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTST
         rc = drvHostCoreAudioASBDToStreamCfg(&pStreamIn->cbCtx.pStream->asbdStream, &CfgAcq);
         if (RT_SUCCESS(rc))
         {
+            int rc2;
+            rc2 = RTCritSectInit(&pStreamIn->cbCtx.pStream->CritSect);
+            AssertRC(rc2);
+                   
             rc = coreAudioStreamInitQueue(pStreamIn->cbCtx.pStream, true /* fInput */, &CfgAcq /* pCfgReq */, NULL /* pCfgAcq */);
             if (RT_SUCCESS(rc))
+            {
+                ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_INIT);
                 rc = drvHostCoreAudioControlIn(pInterface, pHstStrmIn, PDMAUDIOSTREAMCMD_ENABLE);
+            }
 
             if (RT_FAILURE(rc))
             {
-                int rc2 = drvHostCoreAudioFiniIn(pInterface, pHstStrmIn);
+                rc2 = drvHostCoreAudioFiniIn(pInterface, pHstStrmIn);
                 AssertRC(rc2);
             }
         }
@@ -1201,13 +1213,20 @@ static int drvHostCoreAudioReinitOutput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTS
         rc = drvHostCoreAudioASBDToStreamCfg(&pStreamOut->cbCtx.pStream->asbdStream, &CfgAcq);
         if (RT_SUCCESS(rc))
         {
+            int rc2;
+            rc2 = RTCritSectInit(&pStreamOut->cbCtx.pStream->CritSect);
+            AssertRC(rc2);
+
             rc = coreAudioStreamInitQueue(pStreamOut->cbCtx.pStream, false /* fInput */, &CfgAcq /* pCfgReq */, NULL /* pCfgAcq */);
             if (RT_SUCCESS(rc))
+            {
+                ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_INIT);
                 rc = drvHostCoreAudioControlOut(pInterface, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
+            }
 
             if (RT_FAILURE(rc))
             {
-                int rc2 = drvHostCoreAudioFiniOut(pInterface, pHstStrmOut);
+                rc2 = drvHostCoreAudioFiniOut(pInterface, pHstStrmOut);
                 AssertRC(rc2);
             }
         }
@@ -1606,20 +1625,11 @@ static DECLCALLBACK(int) drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, P
         case PDMAUDIOSTREAMCMD_RESUME:
         {
             LogFunc(("Queue enable\n"));
-            if (pCAStream->enmDir == PDMAUDIODIR_IN)
-            {
-                rc = coreAudioStreamInvalidateQueue(pCAStream);
-                if (RT_SUCCESS(rc))
-                {
-                    /* Start the audio queue immediately. */
-                    AudioQueueStart(pCAStream->audioQueue, NULL);
-                }
-            }
-            if (pCAStream->enmDir == PDMAUDIODIR_OUT)
+            rc = coreAudioStreamInvalidateQueue(pCAStream);
+            if (RT_SUCCESS(rc))
             {
-                /* Touch the run flag to start the audio queue as soon as
-                 * we have anough data to actually play something. */
-                ASMAtomicXchgBool(&pCAStream->fRun, true);
+                /* Start the audio queue immediately. */
+                AudioQueueStart(pCAStream->audioQueue, NULL);
             }
             break;
         }
@@ -1677,20 +1687,11 @@ static DECLCALLBACK(int) drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PP
         case PDMAUDIOSTREAMCMD_RESUME:
         {
             LogFunc(("Queue enable\n"));
-            if (pCAStream->enmDir == PDMAUDIODIR_IN)
-            {
-                rc = coreAudioStreamInvalidateQueue(pCAStream);
-                if (RT_SUCCESS(rc))
-                {
-                    /* Start the audio queue immediately. */
-                    AudioQueueStart(pCAStream->audioQueue, NULL);
-                }
-            }
-            if (pCAStream->enmDir == PDMAUDIODIR_OUT)
+            rc = coreAudioStreamInvalidateQueue(pCAStream);
+            if (RT_SUCCESS(rc))
             {
-                /* Touch the run flag to start the audio queue as soon as
-                 * we have anough data to actually play something. */
-                ASMAtomicXchgBool(&pCAStream->fRun, true);
+                /* Start the audio queue immediately. */
+                AudioQueueStart(pCAStream->audioQueue, NULL);
             }
             break;
         }
@@ -1703,6 +1704,7 @@ static DECLCALLBACK(int) drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PP
             ASMAtomicXchgBool(&pCAStream->fIsRunning, false);
             break;
         }
+
         case PDMAUDIOSTREAMCMD_PAUSE:
         {
             LogFunc(("Queue pause\n"));
@@ -1799,7 +1801,10 @@ static DECLCALLBACK(int) drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMA
 
             rc = coreAudioStreamUninitQueue(pCAStream);
             if (RT_FAILURE(rc))
+            {
+                LogRel(("CoreAudio: Failed to uninit stream queue: %Rrc)\n", rc));
                 return rc;
+            }
 
             if (RTCritSectIsInitialized(&pCAStream->CritSect))
                 RTCritSectDelete(&pCAStream->CritSect);
@@ -1812,22 +1817,8 @@ static DECLCALLBACK(int) drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMA
             pStreamIn->ConverterRef = NULL;
         }
 #endif
-        err = AudioUnitUninitialize(pStreamIn->audioUnit);
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        if (err == noErr)
-            err = CloseComponent(pStreamIn->audioUnit);
-#pragma clang diagnostic pop
-
-        if (   err != noErr
-            && err != kAudioHardwareBadObjectError)
-        {
-            LogRel(("CoreAudio: Failed to uninit the recording device (%RI32)\n", err));
-        }
 
         pStreamIn->deviceID      = kAudioDeviceUnknown;
-        pStreamIn->audioUnit     = NULL;
-        pStreamIn->sampleRatio   = 1;
 
 #ifdef VBOX_WITH_AUDIO_CA_CONVERTER
         drvHostCoreAudioUninitConvCbCtx(&pStreamIn->convCbCtx);
@@ -1931,26 +1922,16 @@ static DECLCALLBACK(int) drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDM
 
             rc = coreAudioStreamUninitQueue(pCAStream);
             if (RT_FAILURE(rc))
+            {
+                LogRel(("CoreAudio: Failed to uninit stream queue: %Rrc)\n", rc));
                 return rc;
+            }
 
             if (RTCritSectIsInitialized(&pCAStream->CritSect))
                 RTCritSectDelete(&pCAStream->CritSect);
         }
-        err = AudioUnitUninitialize(pStreamOut->audioUnit);
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        if (err == noErr)
-            err = CloseComponent(pStreamOut->audioUnit);
-#pragma clang diagnostic pop
-
-        if (   err != noErr
-            && err != kAudioHardwareBadObjectError)
-        {
-            LogRel(("CoreAudio: Failed to uninit the playback device (%RI32)\n", err));
-        }
 
         pStreamOut->deviceID  = kAudioDeviceUnknown;
-        pStreamOut->audioUnit = NULL;
         if (pStreamOut->pCircBuf)
         {
             RTCircBufDestroy(pStreamOut->pCircBuf);
@@ -1980,11 +1961,9 @@ static DECLCALLBACK(int) drvHostCoreAudioInitIn(PPDMIHOSTAUDIO pInterface,
     LogFlowFunc(("enmRecSource=%RU32\n", enmRecSource));
 
     pStreamIn->deviceID            = kAudioDeviceUnknown;
-    pStreamIn->audioUnit           = NULL;
 #ifdef VBOX_WITH_AUDIO_CA_CONVERTER
     pStreamIn->ConverterRef        = NULL;
 #endif
-    pStreamIn->sampleRatio         = 1;
     pStreamIn->pCircBuf            = NULL;
     pStreamIn->status              = CA_STATUS_UNINIT;
     pStreamIn->fDefDevChgListReg   = false;
@@ -2009,7 +1988,6 @@ static DECLCALLBACK(int) drvHostCoreAudioInitIn(PPDMIHOSTAUDIO pInterface,
     pCAStream->hThread    = NIL_RTTHREAD;
     pCAStream->fRun       = false;
     pCAStream->fIsRunning = false;
-    pCAStream->fShutdown  = false;
 
     bool fDeviceByUser = false; /* Do we use a device which was set by the user? */
 #if 0
@@ -2089,7 +2067,6 @@ static DECLCALLBACK(int) drvHostCoreAudioInitOut(PPDMIHOSTAUDIO pInterface,
     LogFlowFuncEnter();
 
     pStreamOut->deviceID            = kAudioDeviceUnknown;
-    pStreamOut->audioUnit           = NULL;
     pStreamOut->pCircBuf            = NULL;
     pStreamOut->status              = CA_STATUS_UNINIT;
     pStreamOut->fDefDevChgListReg   = false;
@@ -2112,7 +2089,6 @@ static DECLCALLBACK(int) drvHostCoreAudioInitOut(PPDMIHOSTAUDIO pInterface,
     pCAStream->hThread    = NIL_RTTHREAD;
     pCAStream->fRun       = false;
     pCAStream->fIsRunning = false;
-    pCAStream->fShutdown  = false;
 
     bool fDeviceByUser = false; /* Do we use a device which was set by the user? */
 
diff --git a/src/VBox/Devices/Audio_50/DrvHostDSound.cpp b/src/VBox/Devices/Audio_50/DrvHostDSound.cpp
index 2f8889c..150cccb 100644
--- a/src/VBox/Devices/Audio_50/DrvHostDSound.cpp
+++ b/src/VBox/Devices/Audio_50/DrvHostDSound.cpp
@@ -18,6 +18,7 @@
  */
 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
 #include <VBox/log.h>
+
 #include <iprt/win/windows.h>
 #include <dsound.h>
 
@@ -249,17 +250,21 @@ static int dsoundGetPosOut(PDRVHOSTDSOUND   pThis,
     DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStrmOut->strmOut.MixBuf, pDSoundStrmOut->csPlaybackBufferSize);
 
     /* Get the current play position which is used for calculating the free space in the buffer. */
-    DWORD cbPlayPos = 0;
-
-    HRESULT hr = E_FAIL;
+    DWORD   cbPlayPos = 0;  /* MSC maybe used uninitialized */
+    HRESULT hr = E_FAIL; /* MSC maybe used uninitialized */
     for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
     {
         hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL);
         if (   SUCCEEDED(hr)
             || hr != DSERR_BUFFERLOST) /** @todo: MSDN doesn't state this error for GetCurrentPosition(). */
+        {
             break;
-        LogFlowFunc(("Getting playing position failed due to lost buffer, restoring ...\n"));
-        directSoundPlayRestore(pThis, pDSB);
+        }
+        else
+        {
+            LogFlowFunc(("Getting playing position failed due to lost buffer, restoring ...\n"));
+            directSoundPlayRestore(pThis, pDSB);
+        }
     }
 
     int rc = VINF_SUCCESS;
@@ -372,18 +377,24 @@ static HRESULT directSoundPlayLock(PDRVHOSTDSOUND pThis,
     DWORD cb1 = 0;
     DWORD cb2 = 0;
 
+    HRESULT hr = E_FAIL; /* MSC maybe uninitalized  */
     for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
     {
-        HRESULT hr = IDirectSoundBuffer8_Lock(pDSB, dwOffset, dwBytes, &pv1, &cb1, &pv2, &cb2, dwFlags);
-        if (SUCCEEDED(hr))
+        hr = IDirectSoundBuffer8_Lock(pDSB, dwOffset, dwBytes, &pv1, &cb1, &pv2, &cb2, dwFlags);
+        if (   SUCCEEDED(hr)
+            || hr != DSERR_BUFFERLOST)
             break;
-        if (hr != DSERR_BUFFERLOST)
+        else
         {
-            DSLOGREL(("DSound: Locking playback buffer failed with %Rhrc\n", hr));
-            return hr;
+            LogFlowFunc(("Locking failed due to lost buffer, restoring ...\n"));
+            directSoundPlayRestore(pThis, pDSB);
         }
-        LogFlowFunc(("Locking failed due to lost buffer, restoring ...\n"));
-        directSoundPlayRestore(pThis, pDSB);
+    }
+
+    if (FAILED(hr))
+    {
+        DSLOGREL(("DSound: Locking playback buffer failed with %Rhrc\n", hr));
+        return hr;
     }
 
     if (   (pv1 && (cb1 & pProps->uAlign))
@@ -751,7 +762,7 @@ static HRESULT directSoundPlayGetStatus(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFE
 
     DWORD dwStatus = 0;
 
-    HRESULT hr = E_FAIL;
+    HRESULT hr = E_FAIL; /* MSC maybe used uninitialized */
     for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
     {
         hr = IDirectSoundBuffer8_GetStatus(pDSB, &dwStatus);
@@ -2187,7 +2198,6 @@ static DECLCALLBACK(int) drvHostDSoundConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pC
 
     LogRel(("Audio: Initializing DirectSound audio driver\n"));
 
-
     HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
     if (FAILED(hr))
     {
diff --git a/src/VBox/Devices/Audio_50/HDACodec.cpp b/src/VBox/Devices/Audio_50/HDACodec.cpp
index cc42d62..ba6d027 100644
--- a/src/VBox/Devices/Audio_50/HDACodec.cpp
+++ b/src/VBox/Devices/Audio_50/HDACodec.cpp
@@ -1353,7 +1353,7 @@ static DECLCALLBACK(int) vrbProcUnimplemented(PHDACODEC pThis, uint32_t cmd, uin
 {
     RT_NOREF(pThis, cmd);
     LogFlowFunc(("cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
-                 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
+        CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
     *pResp = 0;
     return VINF_SUCCESS;
 }
@@ -2346,7 +2346,6 @@ static const CODECVERB g_aCodecVerbs[] =
 };
 
 #ifdef DEBUG
-
 typedef struct CODECDBGINFO
 {
     /** DBGF info helpers. */
diff --git a/src/VBox/Devices/Audio_50/testcase/tstAudioMixBuffer.cpp b/src/VBox/Devices/Audio_50/testcase/tstAudioMixBuffer.cpp
index 8a99672..b297c93 100644
--- a/src/VBox/Devices/Audio_50/testcase/tstAudioMixBuffer.cpp
+++ b/src/VBox/Devices/Audio_50/testcase/tstAudioMixBuffer.cpp
@@ -72,7 +72,6 @@ static int tstSingle(RTTEST hTest)
     int8_t  samples8 [2] = { 0x12, 0x34 };
     int16_t samples16[2] = { 0xAA, 0xBB };
     int32_t samples32[2] = { 0xCC, 0xDD };
-    //int64_t samples64[2] = { 0xEE, 0xFF };
 
     RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0, &samples8, sizeof(samples8), &written));
     RTTESTI_CHECK(written == 0 /* Samples */);
diff --git a/src/VBox/Devices/Bus/DevPciIch9.cpp b/src/VBox/Devices/Bus/DevPciIch9.cpp
index d88f61d..6273c3b 100644
--- a/src/VBox/Devices/Bus/DevPciIch9.cpp
+++ b/src/VBox/Devices/Bus/DevPciIch9.cpp
@@ -4,10 +4,20 @@
  *
  * @note    bird: I've cleaned up DevPCI.cpp to some extent, this file has not
  *                be cleaned up and because of pending code merge.
+ *
+ *          DO NOT use the PDMPciDev* or PCIDev* family of functions in this
+ *          file except in the two callbacks for config space access (and the
+ *          functions which are used exclusively by that code) and the two
+ *          device constructors when setting up the config space for the
+ *          bridges.  Everything else need extremely careful review.  Using
+ *          them elsewhere (especially in the init code) causes weird failures
+ *          with PCI passthrough, as it would only update the array of
+ *          (emulated) config space, but not talk to the actual device (needs
+ *          invoking the respective callback).
  */
 
 /*
- * Copyright (C) 2010-2016 Oracle Corporation
+ * Copyright (C) 2010-2017 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -327,7 +337,7 @@ static int ich9pciDataWriteAddr(PICH9PCIGLOBALS pGlobals, PciAddress* pAddr,
     {
         if (pGlobals->aPciBus.cBridges)
         {
-#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
+#ifdef IN_RING3 /** @todo do lookup in R0/RC too! r=klaus don't think that it can work, since the config space access callback only works in R3 */
             PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pAddr->iBus);
             if (pBridgeDevice)
             {
@@ -353,7 +363,7 @@ static int ich9pciDataWriteAddr(PICH9PCIGLOBALS pGlobals, PciAddress* pAddr,
         }
     }
 
-    Log2(("ich9pciDataWriteAddr: %02x:%02x:%02x reg %x(%d) %x %Rrc\n",
+    Log2(("ich9pciDataWriteAddr: %02x:%02x.%d reg %x(%d) %x %Rrc\n",
           pAddr->iBus, pAddr->iDeviceFunc >> 3, pAddr->iDeviceFunc & 0x7, pAddr->iRegister,
           cb, val, rc));
     return rc;
@@ -440,7 +450,7 @@ static int ich9pciDataReadAddr(PICH9PCIGLOBALS pGlobals, PciAddress* pPciAddr, i
     {
         if (pGlobals->aPciBus.cBridges)
         {
-#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
+#ifdef IN_RING3 /** @todo do lookup in R0/RC too! r=klaus don't think that it can work, since the config space access callback only works in R3 */
             PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pPciAddr->iBus);
             if (pBridgeDevice)
             {
@@ -472,7 +482,7 @@ static int ich9pciDataReadAddr(PICH9PCIGLOBALS pGlobals, PciAddress* pPciAddr, i
             ich9pciNoMem(pu32, cb);
     }
 
-    Log3(("ich9pciDataReadAddr: %02x:%02x:%02x reg %x(%d) gave %x %Rrc\n",
+    Log3(("ich9pciDataReadAddr: %02x:%02x.%d reg %x(%d) gave %x %Rrc\n",
           pPciAddr->iBus, pPciAddr->iDeviceFunc >> 3, pPciAddr->iDeviceFunc & 0x7, pPciAddr->iRegister,
           cb, *pu32, rc));
     return rc;
@@ -642,8 +652,9 @@ static void ich9pciSetIrqInternal(PICH9PCIGLOBALS pGlobals, uint8_t uDevFn, PPDM
         return;
     }
 
-    PICH9PCIBUS     pBus      =     &pGlobals->aPciBus;
-    const bool  fIsAcpiDevice = PCIDevGetDeviceId(pPciDev) == 0x7113;
+    PICH9PCIBUS pBus = &pGlobals->aPciBus;
+    /* safe, only needs to go to the config space array */
+    const bool fIsAcpiDevice = PDMPciDevGetDeviceId(pPciDev) == 0x7113;
 
     LogFlowFunc(("PCI Dev %p : IRQ\n", pPciDev));
     /* Check if the state changed. */
@@ -660,7 +671,8 @@ static void ich9pciSetIrqInternal(PICH9PCIGLOBALS pGlobals, uint8_t uDevFn, PPDM
              * kludge (i.e. we fetch the hardwired value from ACPIs
              * PCI device configuration space).
              */
-            ich9pciApicSetIrq(pBus, uDevFn, pPciDev, -1, iLevel, uTagSrc, PCIDevGetInterruptLine(pPciDev));
+            /* safe, only needs to go to the config space array */
+            ich9pciApicSetIrq(pBus, uDevFn, pPciDev, -1, iLevel, uTagSrc, PDMPciDevGetInterruptLine(pPciDev));
         else
             ich9pciApicSetIrq(pBus, uDevFn, pPciDev, iIrq, iLevel, uTagSrc, -1);
     }
@@ -800,8 +812,10 @@ DECLINLINE(PPDMPCIDEV) ich9pciFindBridge(PICH9PCIBUS pBus, uint8_t uBus)
         PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
         AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
                   ("Device is not a PCI bridge but on the list of PCI bridges\n"));
-        uint32_t uSecondary   = PCIDevGetByte(pBridge, VBOX_PCI_SECONDARY_BUS);
-        uint32_t uSubordinate = PCIDevGetByte(pBridge, VBOX_PCI_SUBORDINATE_BUS);
+        /* safe, only needs to go to the config space array */
+        uint32_t uSecondary   = PDMPciDevGetByte(pBridge, VBOX_PCI_SECONDARY_BUS);
+        /* safe, only needs to go to the config space array */
+        uint32_t uSubordinate = PDMPciDevGetByte(pBridge, VBOX_PCI_SUBORDINATE_BUS);
         Log3(("ich9pciFindBridge on bus %p, bridge %d: %d in %d..%d\n", pBus, iBridge, uBus, uSecondary, uSubordinate));
         if (uBus >= uSecondary && uBus <= uSubordinate)
             return pBridge;
@@ -816,17 +830,17 @@ static uint32_t ich9pciGetCfg(PPDMPCIDEV pPciDev, int32_t iRegister, int cb)
     return pPciDev->Int.s.pfnConfigRead(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, iRegister, cb);
 }
 
-static uint8_t ich9pciGetByte(PPDMPCIDEV pPciDev, int32_t iRegister)
+DECLINLINE(uint8_t) ich9pciGetByte(PPDMPCIDEV pPciDev, int32_t iRegister)
 {
     return (uint8_t)ich9pciGetCfg(pPciDev, iRegister, 1);
 }
 
-static uint16_t ich9pciGetWord(PPDMPCIDEV pPciDev, int32_t iRegister)
+DECLINLINE(uint16_t) ich9pciGetWord(PPDMPCIDEV pPciDev, int32_t iRegister)
 {
     return (uint16_t)ich9pciGetCfg(pPciDev, iRegister, 2);
 }
 
-static uint32_t ich9pciGetDWord(PPDMPCIDEV pPciDev, int32_t iRegister)
+DECLINLINE(uint32_t) ich9pciGetDWord(PPDMPCIDEV pPciDev, int32_t iRegister)
 {
     return (uint32_t)ich9pciGetCfg(pPciDev, iRegister, 4);
 }
@@ -837,6 +851,29 @@ DECLINLINE(uint32_t) ich9pciGetRegionReg(int iRegion)
             VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
 }
 
+static void ich9pciSetCfg(PPDMPCIDEV pPciDev, int32_t iRegister, uint32_t u32, int cb)
+{
+    pPciDev->Int.s.pfnConfigWrite(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, iRegister, u32, cb);
+}
+
+DECLINLINE(void) ich9pciSetByte(PPDMPCIDEV pPciDev, int32_t iRegister, uint8_t u8)
+{
+    ich9pciSetCfg(pPciDev, iRegister, u8, 1);
+}
+
+DECLINLINE(void) ich9pciSetWord(PPDMPCIDEV pPciDev, int32_t iRegister, uint16_t u16)
+{
+    ich9pciSetCfg(pPciDev, iRegister, u16, 2);
+}
+
+#if 0
+DECLINLINE(void) ich9pciSetDWord(PPDMPCIDEV pPciDev, int32_t iRegister, uint32_t u32)
+{
+    ich9pciSetCfg(pPciDev, iRegister, u32, 4);
+}
+#endif
+
+
 #define INVALID_PCI_ADDRESS ~0U
 
 static int  ich9pciUnmapRegion(PPDMPCIDEV pDev, int iRegion)
@@ -900,7 +937,7 @@ static void ich9pciUpdateMappings(PDMPCIDEV* pDev, bool fP2PBridge)
         if (pRegion->type & PCI_ADDRESS_SPACE_IO)
         {
             /* port IO region */
-            if (iCmd & PCI_COMMAND_IOACCESS)
+            if (iCmd & VBOX_PCI_COMMAND_IO)
             {
                 /* IO access allowed */
                 uNew = ich9pciGetDWord(pDev, uConfigReg);
@@ -915,7 +952,7 @@ static void ich9pciUpdateMappings(PDMPCIDEV* pDev, bool fP2PBridge)
         else
         {
             /* MMIO region */
-            if (iCmd & PCI_COMMAND_MEMACCESS)
+            if (iCmd & VBOX_PCI_COMMAND_MEMORY)
             {
                 uNew = ich9pciGetDWord(pDev, uConfigReg);
                 if (f64Bit)
@@ -933,7 +970,7 @@ static void ich9pciUpdateMappings(PDMPCIDEV* pDev, bool fP2PBridge)
                        mappings, we handle specific values as invalid
                        mappings. */
                     /* Unconditionally exclude I/O-APIC/HPET/ROM. Pessimistic, but better than causing a mess. */
-                    if (uLast <= uNew || uNew == 0 || (uNew <= UINT32_C(0xffffffff) && uLast >= UINT32_C(0xfec00000)))
+                    if (uLast <= uNew || uNew == 0 || (uNew <= UINT32_C(0xffffffff) && uLast >= UINT32_C(0xfec00000)) || uNew >= UINT64_C(0xffffffff00000000))
                         uNew = INVALID_PCI_ADDRESS;
                 }
             } else
@@ -1033,7 +1070,8 @@ static DECLCALLBACK(int) ich9pciIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV
 
     /* Set type in the PCI config space. */
     uint32_t u32Value   = (uint32_t)enmType & (PCI_ADDRESS_SPACE_IO | PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH);
-    PCIDevSetDWord(pPciDev, ich9pciGetRegionReg(iRegion), u32Value);
+    /* safe, only needs to go to the config space array */
+    PDMPciDevSetDWord(pPciDev, ich9pciGetRegionReg(iRegion), u32Value);
 
     return VINF_SUCCESS;
 }
@@ -1140,7 +1178,8 @@ static DECLCALLBACK(void) ich9pcibridgeConfigWrite(PPDMDEVINSR3 pDevIns, uint8_t
     LogFlowFunc((": pDevIns=%p uBus=%d uDevice=%d u32Address=%u u32Value=%u cb=%d\n", pDevIns, uBus, uDevice, u32Address, u32Value, cb));
 
     /* If the current bus is not the target bus search for the bus which contains the device. */
-    if (uBus != PCIDevGetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS))
+    /* safe, only needs to go to the config space array */
+    if (uBus != PDMPciDevGetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS))
     {
         PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(pBus, uBus);
         if (pBridgeDevice)
@@ -1170,7 +1209,8 @@ static DECLCALLBACK(uint32_t) ich9pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint
     LogFlowFunc((": pDevIns=%p uBus=%d uDevice=%d u32Address=%u cb=%d\n", pDevIns, uBus, uDevice, u32Address, cb));
 
     /* If the current bus is not the target bus search for the bus which contains the device. */
-    if (uBus != PCIDevGetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS))
+    /* safe, only needs to go to the config space array */
+    if (uBus != PDMPciDevGetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS))
     {
         PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(pBus, uBus);
         if (pBridgeDevice)
@@ -1204,9 +1244,8 @@ static DECLCALLBACK(uint32_t) ich9pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint
  *
  * @param   pDev                The PCI device.
  * @param   pbSrcConfig         The configuration register values to be loaded.
- * @param   fIsBridge           Whether this is a bridge device or not.
  */
-static void pciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig, bool fIsBridge)
+static void pciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig)
 {
     /*
      * This table defines the fields for normal devices and bridge devices, and
@@ -1236,35 +1275,35 @@ static void pciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig
         { 0x10, 4, 1, 3, "BASE_ADDRESS_0" },
         { 0x14, 4, 1, 3, "BASE_ADDRESS_1" },
         { 0x18, 4, 1, 1, "BASE_ADDRESS_2" },
-        { 0x18, 1, 1, 2, "PRIMARY_BUS" },       // fWritable = ??
-        { 0x19, 1, 1, 2, "SECONDARY_BUS" },     // fWritable = ??
-        { 0x1a, 1, 1, 2, "SUBORDINATE_BUS" },   // fWritable = ??
-        { 0x1b, 1, 1, 2, "SEC_LATENCY_TIMER" }, // fWritable = ??
+        { 0x18, 1, 1, 2, "PRIMARY_BUS" },
+        { 0x19, 1, 1, 2, "SECONDARY_BUS" },
+        { 0x1a, 1, 1, 2, "SUBORDINATE_BUS" },
+        { 0x1b, 1, 1, 2, "SEC_LATENCY_TIMER" },
         { 0x1c, 4, 1, 1, "BASE_ADDRESS_3" },
-        { 0x1c, 1, 1, 2, "IO_BASE" },           // fWritable = ??
-        { 0x1d, 1, 1, 2, "IO_LIMIT" },          // fWritable = ??
-        { 0x1e, 2, 1, 2, "SEC_STATUS" },        // fWritable = ??
+        { 0x1c, 1, 1, 2, "IO_BASE" },
+        { 0x1d, 1, 1, 2, "IO_LIMIT" },
+        { 0x1e, 2, 1, 2, "SEC_STATUS" },
         { 0x20, 4, 1, 1, "BASE_ADDRESS_4" },
-        { 0x20, 2, 1, 2, "MEMORY_BASE" },       // fWritable = ??
-        { 0x22, 2, 1, 2, "MEMORY_LIMIT" },      // fWritable = ??
+        { 0x20, 2, 1, 2, "MEMORY_BASE" },
+        { 0x22, 2, 1, 2, "MEMORY_LIMIT" },
         { 0x24, 4, 1, 1, "BASE_ADDRESS_5" },
-        { 0x24, 2, 1, 2, "PREF_MEMORY_BASE" },  // fWritable = ??
-        { 0x26, 2, 1, 2, "PREF_MEMORY_LIMIT" }, // fWritable = ??
-        { 0x28, 4, 1, 1, "CARDBUS_CIS" },       // fWritable = ??
-        { 0x28, 4, 1, 2, "PREF_BASE_UPPER32" }, // fWritable = ??
-        { 0x2c, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },// fWritable = !?
-        { 0x2c, 4, 1, 2, "PREF_LIMIT_UPPER32" },// fWritable = ??
-        { 0x2e, 2, 0, 1, "SUBSYSTEM_ID" },      // fWritable = !?
-        { 0x30, 4, 1, 1, "ROM_ADDRESS" },       // fWritable = ?!
-        { 0x30, 2, 1, 2, "IO_BASE_UPPER16" },   // fWritable = ?!
-        { 0x32, 2, 1, 2, "IO_LIMIT_UPPER16" },  // fWritable = ?!
-        { 0x34, 4, 0, 3, "CAPABILITY_LIST" },   // fWritable = !? cb=!?
-        { 0x38, 4, 1, 1, "RESERVED_38" },       // ???
-        { 0x38, 4, 1, 2, "ROM_ADDRESS_BR" },    // fWritable = !? cb=!? fBridge=!?
-        { 0x3c, 1, 1, 3, "INTERRUPT_LINE" },    // fBridge=??
-        { 0x3d, 1, 0, 3, "INTERRUPT_PIN" },     // fBridge=??
+        { 0x24, 2, 1, 2, "PREF_MEMORY_BASE" },
+        { 0x26, 2, 1, 2, "PREF_MEMORY_LIMIT" },
+        { 0x28, 4, 0, 1, "CARDBUS_CIS" },
+        { 0x28, 4, 1, 2, "PREF_BASE_UPPER32" },
+        { 0x2c, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },
+        { 0x2c, 4, 1, 2, "PREF_LIMIT_UPPER32" },
+        { 0x2e, 2, 0, 1, "SUBSYSTEM_ID" },
+        { 0x30, 4, 1, 1, "ROM_ADDRESS" },
+        { 0x30, 2, 1, 2, "IO_BASE_UPPER16" },
+        { 0x32, 2, 1, 2, "IO_LIMIT_UPPER16" },
+        { 0x34, 4, 0, 3, "CAPABILITY_LIST" },
+        { 0x38, 4, 1, 1, "RESERVED_38" },
+        { 0x38, 4, 1, 2, "ROM_ADDRESS_BR" },
+        { 0x3c, 1, 1, 3, "INTERRUPT_LINE" },
+        { 0x3d, 1, 0, 3, "INTERRUPT_PIN" },
         { 0x3e, 1, 0, 1, "MIN_GNT" },
-        { 0x3e, 2, 1, 2, "BRIDGE_CONTROL" },    // fWritable = !?
+        { 0x3e, 2, 1, 2, "BRIDGE_CONTROL" },
         { 0x3f, 1, 0, 1, "MAX_LAT" },
         /* The COMMAND register must come last as it requires the *ADDRESS*
            registers to be restored before we pretent to change it from 0 to
@@ -1302,7 +1341,7 @@ static void pciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig
     /*
      * Loop thru the fields covering the 64 bytes of standard registers.
      */
-    uint8_t const fBridge = fIsBridge ? 2 : 1;
+    uint8_t const fBridge = pciDevIsPci2PciBridge(pDev) ? 2 : 1;
     Assert(!pciDevIsPassthrough(pDev));
     uint8_t *pbDstConfig = &pDev->abConfig[0];
 
@@ -1345,7 +1384,8 @@ static void pciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig
                                 pDev->pszNameR3, pDev->Int.s.CTX_SUFF(pDevIns)->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
                 }
                 if (off == VBOX_PCI_COMMAND)
-                    PCIDevSetCommand(pDev, 0); /* For remapping, see ich9pciR3CommonLoadExec. */
+                    /* safe, only needs to go to the config space array */
+                    PDMPciDevSetCommand(pDev, 0); /* For remapping, see ich9pciR3CommonLoadExec. */
                 pDev->Int.s.pfnConfigWrite(pDev->Int.s.CTX_SUFF(pDevIns), pDev, off, u32Src, cb);
             }
         }
@@ -1398,10 +1438,13 @@ static DECLCALLBACK(int) ich9pciR3CommonLoadExec(PICH9PCIBUS pBus, PSSMHANDLE pS
         PPDMPCIDEV pDev = pBus->apDevices[i];
         if (pDev)
         {
-            uint16_t u16 = PCIDevGetCommand(pDev);
+            /* safe, only needs to go to the config space array */
+            uint16_t u16 = PDMPciDevGetCommand(pDev);
             pDev->Int.s.pfnConfigWrite(pDev->Int.s.CTX_SUFF(pDevIns), pDev, VBOX_PCI_COMMAND, 0, 2);
-            PCIDevSetCommand(pDev, u16);
-            Assert(PCIDevGetCommand(pDev) == u16);
+            /* safe, only needs to go to the config space array */
+            PDMPciDevSetCommand(pDev, u16);
+            /* safe, only needs to go to the config space array */
+            Assert(PDMPciDevGetCommand(pDev) == u16);
         }
     }
 
@@ -1430,12 +1473,14 @@ static DECLCALLBACK(int) ich9pciR3CommonLoadExec(PICH9PCIBUS pBus, PSSMHANDLE pS
             pDev = pBus->apDevices[i];
             if (pDev)
             {
+                /* safe, only needs to go to the config space array */
                 LogRel(("PCI: New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pDev->pszNameR3,
-                        PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev)));
+                        PDMPciDevGetVendorId(pDev), PDMPciDevGetDeviceId(pDev)));
                 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
                 {
+                    /* safe, only needs to go to the config space array */
                     rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("New device in slot %#x, %s (vendor=%#06x device=%#06x)"),
-                                          i, pDev->pszNameR3, PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev));
+                                          i, pDev->pszNameR3, PDMPciDevGetVendorId(pDev), PDMPciDevGetDeviceId(pDev));
                     break;
                 }
             }
@@ -1474,28 +1519,32 @@ static DECLCALLBACK(int) ich9pciR3CommonLoadExec(PICH9PCIBUS pBus, PSSMHANDLE pS
         pDev = pBus->apDevices[i];
         if (!pDev)
         {
+            /* safe, only needs to go to the config space array */
             LogRel(("PCI: Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
-                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
+                    PDMPciDevGetVendorId(&DevTmp), PDMPciDevGetDeviceId(&DevTmp)));
             if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
             {
+                /* safe, only needs to go to the config space array */
                 rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x has been removed! vendor=%#06x device=%#06x"),
-                                      i, PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp));
+                                      i, PDMPciDevGetVendorId(&DevTmp), PDMPciDevGetDeviceId(&DevTmp));
                 break;
             }
             continue;
         }
 
         /* match the vendor id assuming that this will never be changed. */
-        if (PCIDevGetVendorId(&DevTmp) != PCIDevGetVendorId(pDev))
+        /* safe, only needs to go to the config space array */
+        if (PDMPciDevGetVendorId(&DevTmp) != PDMPciDevGetVendorId(pDev))
         {
+            /* safe, only needs to go to the config space array */
             rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
-                                  i, pDev->pszNameR3, PCIDevGetVendorId(&DevTmp), PCIDevGetVendorId(pDev));
+                                  i, pDev->pszNameR3, PDMPciDevGetVendorId(&DevTmp), PDMPciDevGetVendorId(pDev));
             break;
         }
 
         /* commit the loaded device config. */
         Assert(!pciDevIsPassthrough(pDev));
-        pciR3CommonRestoreConfig(pDev, &DevTmp.abConfig[0], false ); /** @todo fix bridge fun! */
+        pciR3CommonRestoreConfig(pDev, &DevTmp.abConfig[0]);
 
         pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
         pDev->Int.s.u8MsiCapOffset  = DevTmp.Int.s.u8MsiCapOffset;
@@ -1558,7 +1607,7 @@ static DECLCALLBACK(int) ich9pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE
 
 
 /*
- * Perform imeediate read of configuration space register.
+ * Perform immediate read of configuration space register.
  * Cannot be rescheduled, as already in R3.
  */
 static uint32_t ich9pciConfigRead(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t len)
@@ -1613,7 +1662,7 @@ static void ich9pciSetRegionAddress(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint
 
 static void ich9pciBiosInitBridge(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn)
 {
-    Log(("BIOS init bridge: %02x::%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
+    Log(("BIOS init bridge: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
 
     /*
      * The I/O range for the bridge must be aligned to a 4KB boundary.
@@ -1644,26 +1693,32 @@ static void ich9pciBiosInitBridge(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint8_
     ich9pciBiosInitAllDevicesOnBus(pGlobals, uBridgeBus);
 
     /*
-     * Set I/O limit register. If there is no device with I/O space behind the bridge
-     * we set a lower value than in the base register.
-     * The result with a real bridge is that no I/O transactions are passed to the secondary
-     * interface. Again this doesn't really matter here but we want to be compliant to the spec.
+     * Set I/O limit register. If there is no device with I/O space behind the
+     * bridge we set a lower value than in the base register.
      */
-    if ((u32IoAddressBase != pGlobals->uPciBiosIo) && ((pGlobals->uPciBiosIo % 4096) != 0))
+    if (u32IoAddressBase != pGlobals->uPciBiosIo)
     {
-        /* The upper boundary must be one byte less than a 4KB boundary. */
+        /* Need again alignment to a 4KB boundary. */
         pGlobals->uPciBiosIo = RT_ALIGN_32(pGlobals->uPciBiosIo, 4*1024);
+        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, ((pGlobals->uPciBiosIo >> 8) & 0xf0) - 1, 1);
+    }
+    else
+    {
+        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_BASE, 0xf0, 1);
+        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, 0x00, 1);
     }
-
-    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, ((pGlobals->uPciBiosIo >> 8) & 0xf0) - 1, 1);
 
     /* Same with the MMIO limit register but with 1MB boundary here. */
     if ((u32MMIOAddressBase != pGlobals->uPciBiosMmio) && ((pGlobals->uPciBiosMmio % (1024 * 1024)) != 0))
     {
-        /* The upper boundary must be one byte less than a 1MB boundary. */
         pGlobals->uPciBiosMmio = RT_ALIGN_32(pGlobals->uPciBiosMmio, 1024*1024);
+        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, ((pGlobals->uPciBiosMmio >> 16) & UINT32_C(0xfff0)) - 1, 2);
+    }
+    else
+    {
+        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_BASE, 0xfff0, 2);
+        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, 0x0000, 2);
     }
-    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, ((pGlobals->uPciBiosMmio >> 16) & UINT32_C(0xfff0)) - 1, 2);
 
     /*
      * Set the prefetch base and limit registers. We currently have no device with a prefetchable region
@@ -1687,6 +1742,7 @@ static void ich9pciBiosInitDeviceBARs(PICH9PCIGLOBALS pGlobals, uint8_t uBus, ui
         /* PCI bridges have 2 BARs. */
         cRegions = 2;
 
+    bool fSuppressMem = false;
     bool fActiveMemRegion = false;
     bool fActiveIORegion = false;
     for (int iRegion = 0; iRegion < cRegions; iRegion++)
@@ -1697,11 +1753,28 @@ static void ich9pciBiosInitDeviceBARs(PICH9PCIGLOBALS pGlobals, uint8_t uBus, ui
            are cleared. */
         uint8_t u8ResourceType = ich9pciConfigRead(pGlobals, uBus, uDevFn, u32Address, 1);
 
+        bool fPrefetch =    (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_IO)))
+                         == PCI_ADDRESS_SPACE_MEM_PREFETCH;
         bool f64Bit =    (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
                       == PCI_ADDRESS_SPACE_BAR64;
-        bool fIsPio = ((u8ResourceType & PCI_COMMAND_IOACCESS) == PCI_COMMAND_IOACCESS);
+        bool fIsPio = ((u8ResourceType & PCI_ADDRESS_SPACE_IO) == PCI_ADDRESS_SPACE_IO);
         uint64_t cbRegSize64 = 0;
 
+        /* Hack: since this PCI init code cannot handle prefetchable BARs on
+         * anything besides the primary bus, it's for now the best solution
+         * to leave such BARs uninitialized and keep memory transactions
+         * disabled. The OS will hopefully be clever enough to fix this.
+         * Prefetchable BARs are the only ones which can be truly big (and
+         * are almost always 64-bit BARs). The non-prefetchable ones will not
+         * cause running out of space in the PCI memory hole. */
+        if (fPrefetch && uBus != 0)
+        {
+            fSuppressMem = true;
+            if (f64Bit)
+                iRegion++; /* skip next region */
+            continue;
+        }
+
         if (f64Bit)
         {
             ich9pciConfigWrite(pGlobals, uBus, uDevFn, u32Address,   UINT32_C(0xffffffff), 4);
@@ -1713,7 +1786,7 @@ static void ich9pciBiosInitDeviceBARs(PICH9PCIGLOBALS pGlobals, uint8_t uBus, ui
 
             /* No 64-bit PIO regions possible. */
 #ifndef DEBUG_bird /* EFI triggers this for DevAHCI. */
-            AssertMsg((u8ResourceType & PCI_COMMAND_IOACCESS) == 0, ("type=%#x rgn=%d\n", u8ResourceType, iRegion));
+            AssertMsg((u8ResourceType & PCI_ADDRESS_SPACE_IO) == 0, ("type=%#x rgn=%d\n", u8ResourceType, iRegion));
 #endif
         }
         else
@@ -1755,7 +1828,10 @@ static void ich9pciBiosInitDeviceBARs(PICH9PCIGLOBALS pGlobals, uint8_t uBus, ui
                 || (uNew <= UINT32_C(0xffffffff) && uNew + cbRegSize64 - 1 >= UINT32_C(0xfec00000))
                 || uNew >= _4G)
             {
-                if (f64Bit)
+                /* Only prefetchable regions can be placed above 4GB, as the
+                 * address decoder for non-prefetchable addresses in bridges
+                 * is limited to 32 bits. */
+                if (f64Bit && fPrefetch)
                 {
                     /* Map a 64-bit region above 4GB. */
                     Assert(!fIsPio);
@@ -1797,10 +1873,10 @@ static void ich9pciBiosInitDeviceBARs(PICH9PCIGLOBALS pGlobals, uint8_t uBus, ui
 
     /* Update the command word appropriately. */
     uint8_t uCmd = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, 2);
-    if (fActiveMemRegion)
-        uCmd |= PCI_COMMAND_MEMACCESS; /* Enable MMIO access. */
+    if (fActiveMemRegion && !fSuppressMem)
+        uCmd |= VBOX_PCI_COMMAND_MEMORY; /* Enable MMIO access. */
     if (fActiveIORegion)
-        uCmd |= PCI_COMMAND_IOACCESS; /* Enable I/O space access. */
+        uCmd |= VBOX_PCI_COMMAND_IO; /* Enable I/O space access. */
     ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, uCmd, 2);
 }
 
@@ -1841,7 +1917,7 @@ static void ich9pciBiosInitAllDevicesOnBus(PICH9PCIGLOBALS pGlobals, uint8_t uBu
                  */
                 uint8_t uCmd = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, 1);
                 ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND,
-                                   uCmd | PCI_COMMAND_IOACCESS,
+                                   uCmd | VBOX_PCI_COMMAND_IO,
                                    1);
                 break;
             }
@@ -1867,6 +1943,7 @@ static void ich9pciBiosInitAllDevicesOnBus(PICH9PCIGLOBALS pGlobals, uint8_t uBu
                         Assert(false);
                         break;
                     }
+                    /* safe, only needs to go to the config space array */
                     if (uBus == PDMPciDevGetByte(pBridge, VBOX_PCI_SECONDARY_BUS))
                     {
                         /* OK, found bus this device attached to. */
@@ -1918,17 +1995,23 @@ static void ich9pciBiosInitAllDevicesOnBus(PICH9PCIGLOBALS pGlobals, uint8_t uBu
  * @param   pGlobals         Global device instance data used to generate unique bus numbers.
  * @param   pBus             The PCI bus to initialize.
  * @param   uBusPrimary      The primary bus number the bus is connected to.
- * @param   uBusSecondary    The secondary bus number, i.e. the bus number behind the bridge.
  */
-static uint8_t ich9pciInitBridgeTopology(PICH9PCIGLOBALS pGlobals, PICH9PCIBUS pBus, unsigned uBusPrimary, uint8_t uBusSecondary)
+static uint8_t ich9pciInitBridgeTopology(PICH9PCIGLOBALS pGlobals, PICH9PCIBUS pBus, unsigned uBusPrimary)
 {
     PPDMPCIDEV pBridgeDev = &pBus->aPciDev;
 
     /* Set only if we are not on the root bus, it has no primary bus attached. */
-    if (uBusSecondary != 0)
-    {
-        PCIDevSetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS, uBusPrimary);
-        PCIDevSetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS, uBusSecondary);
+    if (pBus->iBus != 0)
+    {
+        ich9pciSetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS, uBusPrimary);
+        ich9pciSetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS, pBus->iBus);
+        /* Since the subordinate bus value can only be finalized once we
+         * finished recursing through everything behind the bridge, the only
+         * solution is temporarily configuring the subordinate to the maximum
+         * possible value. This makes sure that the config space accesses work
+         * (for our own sloppy emulation it apparently doesn't matter, but
+         * this is vital for real PCI bridges/devices in passthrough mode). */
+        ich9pciSetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, 0xff);
     }
 
     uint8_t uMaxSubNum = pBus->iBus;
@@ -1938,15 +2021,27 @@ static uint8_t ich9pciInitBridgeTopology(PICH9PCIGLOBALS pGlobals, PICH9PCIBUS p
         AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
                   ("Device is not a PCI bridge but on the list of PCI bridges\n"));
         PICH9PCIBUS pChildBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PICH9PCIBUS);
-        uint8_t uMaxChildSubBus = ich9pciInitBridgeTopology(pGlobals, pChildBus, uBusSecondary, pChildBus->iBus);
+        uint8_t uMaxChildSubBus = ich9pciInitBridgeTopology(pGlobals, pChildBus, pChildBus->iBus);
         uMaxSubNum = RT_MAX(uMaxSubNum, uMaxChildSubBus);
     }
-    PCIDevSetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, uMaxSubNum);
+    if (pBus->iBus != 0)
+        ich9pciSetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, uMaxSubNum);
+
+    /* Make sure that transactions are able to get through the bridge. Not
+     * strictly speaking necessary this early (before any device is set up),
+     * but on the other hand it can't hurt either. */
+    if (pBus->iBus != 0)
+        ich9pciSetWord(pBridgeDev, VBOX_PCI_COMMAND,
+                         VBOX_PCI_COMMAND_IO
+                       | VBOX_PCI_COMMAND_MEMORY
+                       | VBOX_PCI_COMMAND_MASTER);
+
+    /* safe, only needs to go to the config space array */
     Log2(("ich9pciInitBridgeTopology: for bus %p: primary=%d secondary=%d subordinate=%d\n",
           pBus,
-          PCIDevGetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS),
-          PCIDevGetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS),
-          PCIDevGetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS)
+          PDMPciDevGetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS),
+          PDMPciDevGetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS),
+          PDMPciDevGetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS)
           ));
 
     return uMaxSubNum;
@@ -1968,7 +2063,7 @@ static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
     pGlobals->uPciBiosMmio64 = cbAbove4GB + _4G;
     pGlobals->uBus = 0;
 
-    /* NB: Assume that if MMIO range is enabled, it is at the bottom of the memory hole. */
+    /* NB: Assume that if MMIO range is enabled, it is below the beginning of the memory hole. */
     if (pGlobals->u64PciConfigMMioAddress)
     {
         AssertRelease(pGlobals->u64PciConfigMMioAddress >= cbBelow4GB);
@@ -1980,7 +2075,7 @@ static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
      * Assign bridge topology, for further routing to work.
      */
     PICH9PCIBUS pBus = &pGlobals->aPciBus;
-    ich9pciInitBridgeTopology(pGlobals, pBus, 0, 0);
+    ich9pciInitBridgeTopology(pGlobals, pBus, 0);
 
     /*
      * Init all devices on bus 0 (recursing to further buses).
@@ -2028,11 +2123,14 @@ static DECLCALLBACK(uint32_t) ich9pciConfigReadDev(PPDMDEVINS pDevIns, PPDMPCIDE
     switch (len)
     {
         case 1:
-            return PCIDevGetByte(pPciDev,  u32Address);
+            /* safe, only needs to go to the config space array */
+            return PDMPciDevGetByte(pPciDev,  u32Address);
         case 2:
-            return PCIDevGetWord(pPciDev,  u32Address);
+            /* safe, only needs to go to the config space array */
+            return PDMPciDevGetWord(pPciDev,  u32Address);
         case 4:
-            return PCIDevGetDWord(pPciDev, u32Address);
+            /* safe, only needs to go to the config space array */
+            return PDMPciDevGetDWord(pPciDev, u32Address);
         default:
             Assert(false);
             return 0;
@@ -2075,12 +2173,14 @@ DECLINLINE(void) ich9pciWriteBarByte(PPDMPCIDEV pPciDev, int iRegion, int iOffse
 
     }
 
-    uint8_t u8Old = PCIDevGetByte(pPciDev, uAddr) & uMask;
+    /* safe, only needs to go to the config space array */
+    uint8_t u8Old = PDMPciDevGetByte(pPciDev, uAddr) & uMask;
     u8Val = (u8Old & uMask) | (u8Val & ~uMask);
 
     Log3(("ich9pciWriteBarByte: was %x writing %x\n", u8Old, u8Val));
 
-    PCIDevSetByte(pPciDev, uAddr, u8Val);
+    /* safe, only needs to go to the config space array */
+    PDMPciDevSetByte(pPciDev, uAddr, u8Val);
 }
 
 
@@ -2187,7 +2287,7 @@ static DECLCALLBACK(void) ich9pciConfigWriteDev(PPDMDEVINS pDevIns, PPDMPCIDEV p
                 }
                 break;
             default:
-                AssertMsgFailed(("Unknown header type %x\n", PCIDevGetHeaderType(pPciDev)));
+                AssertMsgFailed(("Unknown header type %x\n", PDMPciDevGetHeaderType(pPciDev)));
                 fWritable = false;
                 break;
         }
@@ -2245,7 +2345,8 @@ static DECLCALLBACK(void) ich9pciConfigWriteDev(PPDMDEVINS pDevIns, PPDMPCIDEV p
             default:
             default_case:
                 if (fWritable)
-                    PCIDevSetByte(pPciDev, addr, u8Val);
+                    /* safe, only needs to go to the config space array */
+                    PDMPciDevSetByte(pPciDev, addr, u8Val);
         }
         addr++;
         val >>= 8;
@@ -2267,6 +2368,13 @@ static void printIndent(PCDBGFINFOHLP pHlp, int iIndent)
 
 static void ich9pciBusInfo(PICH9PCIBUS pBus, PCDBGFINFOHLP pHlp, int iIndent, bool fRegisters)
 {
+    /* This has to use the callbacks for accuracy reasons. Otherwise it can get
+     * confusing in the passthrough case or when the callbacks for some device
+     * are doing something non-trivial (like implementing an indirect
+     * passthrough approach), because then the abConfig array is an imprecise
+     * cache needed for efficiency (so that certain reads can be done from
+     * R0/RC), but far from authoritative or what the guest would see. */
+
     for (uint32_t iDev = 0; iDev < RT_ELEMENTS(pBus->apDevices); iDev++)
     {
         PPDMPCIDEV pPciDev = pBus->apDevices[iDev];
@@ -2278,7 +2386,7 @@ static void ich9pciBusInfo(PICH9PCIBUS pBus, PCDBGFINFOHLP pHlp, int iIndent, bo
              * For passthrough devices MSI/MSI-X mostly reflects the way interrupts delivered to the guest,
              * as host driver handles real devices interrupts.
              */
-            pHlp->pfnPrintf(pHlp, "%02x:%02x:%02x %s%s: %04x-%04x",
+            pHlp->pfnPrintf(pHlp, "%02x:%02x.%d %s%s: %04x-%04x",
                             pBus->iBus, (iDev >> 3) & 0xff, iDev & 0x7,
                             pPciDev->pszNameR3,
                             pciDevIsPassthrough(pPciDev) ? " (PASSTHROUGH)" : "",
@@ -2304,58 +2412,60 @@ static void ich9pciBusInfo(PICH9PCIBUS pBus, PCDBGFINFOHLP pHlp, int iIndent, bo
                 pHlp->pfnPrintf(pHlp, "\n");
             }
 
-            uint16_t iCmd = ich9pciGetWord(pPciDev, VBOX_PCI_COMMAND);
-            if ((iCmd & (VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY)) != 0)
+            for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
             {
-                for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
-                {
-                    PCIIORegion* pRegion = &pPciDev->Int.s.aIORegions[iRegion];
-                    uint64_t  iRegionSize = pRegion->size;
+                PCIIORegion* pRegion = &pPciDev->Int.s.aIORegions[iRegion];
+                uint64_t  iRegionSize = pRegion->size;
 
-                    if (iRegionSize == 0)
-                        continue;
+                if (iRegionSize == 0)
+                    continue;
 
-                    uint32_t u32Addr = ich9pciGetDWord(pPciDev, ich9pciGetRegionReg(iRegion));
-                    const char * pszDesc;
-                    char szDescBuf[128];
+                uint32_t u32Addr = ich9pciGetDWord(pPciDev, ich9pciGetRegionReg(iRegion));
+                const char * pszDesc;
+                char szDescBuf[128];
 
-                    bool f64Bit =    (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
-                                  == PCI_ADDRESS_SPACE_BAR64;
-                    if (pRegion->type & PCI_ADDRESS_SPACE_IO)
-                    {
-                        pszDesc = "IO";
-                        u32Addr &= ~0x3;
-                    }
-                    else
-                    {
-                        RTStrPrintf(szDescBuf, sizeof(szDescBuf), "MMIO%s%s",
-                                    f64Bit ? "64" : "32",
-                                    (pRegion->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) ? " PREFETCH" : "");
-                        pszDesc = szDescBuf;
-                        u32Addr &= ~0xf;
-                    }
+                bool f64Bit =    (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
+                              == PCI_ADDRESS_SPACE_BAR64;
+                if (pRegion->type & PCI_ADDRESS_SPACE_IO)
+                {
+                    pszDesc = "IO";
+                    u32Addr &= ~0x3;
+                }
+                else
+                {
+                    RTStrPrintf(szDescBuf, sizeof(szDescBuf), "MMIO%s%s",
+                                f64Bit ? "64" : "32",
+                                (pRegion->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) ? " PREFETCH" : "");
+                    pszDesc = szDescBuf;
+                    u32Addr &= ~0xf;
+                }
 
-                    printIndent(pHlp, iIndent + 2);
-                    pHlp->pfnPrintf(pHlp, "%s region #%d: ",pszDesc, iRegion);
-                    if (f64Bit)
-                    {
-                        uint32_t u32High = ich9pciGetDWord(pPciDev, ich9pciGetRegionReg(iRegion+1));
-                        uint64_t u64Addr = RT_MAKE_U64(u32Addr, u32High);
-                        pHlp->pfnPrintf(pHlp, "%RX64..%RX64\n", u64Addr, u64Addr+iRegionSize-1);
-                        iRegion++;
-                    }
-                    else
-                        pHlp->pfnPrintf(pHlp, "%x..%x\n", u32Addr, u32Addr+iRegionSize-1);
+                printIndent(pHlp, iIndent + 2);
+                pHlp->pfnPrintf(pHlp, "%s region #%d: ",pszDesc, iRegion);
+                if (f64Bit)
+                {
+                    uint32_t u32High = ich9pciGetDWord(pPciDev, ich9pciGetRegionReg(iRegion+1));
+                    uint64_t u64Addr = RT_MAKE_U64(u32Addr, u32High);
+                    pHlp->pfnPrintf(pHlp, "%RX64..%RX64\n", u64Addr, u64Addr+iRegionSize-1);
+                    iRegion++;
                 }
+                else
+                    pHlp->pfnPrintf(pHlp, "%x..%x\n", u32Addr, u32Addr+iRegionSize-1);
             }
 
             printIndent(pHlp, iIndent + 2);
+            uint16_t iCmd = ich9pciGetWord(pPciDev, VBOX_PCI_COMMAND);
             uint16_t iStatus = ich9pciGetWord(pPciDev, VBOX_PCI_STATUS);
-            pHlp->pfnPrintf(pHlp, "Command: %04X, Status: %04X\n",
+            pHlp->pfnPrintf(pHlp, "Command: %04x, Status: %04x\n",
                             iCmd, iStatus);
             printIndent(pHlp, iIndent + 2);
             pHlp->pfnPrintf(pHlp, "Bus master: %s\n",
                             iCmd & VBOX_PCI_COMMAND_MASTER ? "Yes" : "No");
+            if (iCmd != PDMPciDevGetCommand(pPciDev))
+            {
+                printIndent(pHlp, iIndent + 2);
+                pHlp->pfnPrintf(pHlp, "CACHE INCONSISTENCY: Command: %04x\n", PDMPciDevGetCommand(pPciDev));
+            }
 
             if (fRegisters)
             {
@@ -2384,19 +2494,37 @@ static void ich9pciBusInfo(PICH9PCIBUS pBus, PCDBGFINFOHLP pHlp, int iIndent, bo
         for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
         {
             PICH9PCIBUS pBusSub = PDMINS_2_DATA(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns), PICH9PCIBUS);
+            uint8_t uPrimary = ich9pciGetByte(&pBusSub->aPciDev, VBOX_PCI_PRIMARY_BUS);
+            uint8_t uSecondary = ich9pciGetByte(&pBusSub->aPciDev, VBOX_PCI_SECONDARY_BUS);
+            uint8_t uSubordinate = ich9pciGetByte(&pBusSub->aPciDev, VBOX_PCI_SUBORDINATE_BUS);
             printIndent(pHlp, iIndent);
             pHlp->pfnPrintf(pHlp, "bridge topology: primary=%d secondary=%d subordinate=%d\n",
-                            PCIDevGetByte(&pBusSub->aPciDev, VBOX_PCI_PRIMARY_BUS),
-                            PCIDevGetByte(&pBusSub->aPciDev, VBOX_PCI_SECONDARY_BUS),
-                            PCIDevGetByte(&pBusSub->aPciDev, VBOX_PCI_SUBORDINATE_BUS));
+                            uPrimary, uSecondary, uSubordinate);
+            if (   uPrimary != PDMPciDevGetByte(&pBusSub->aPciDev, VBOX_PCI_PRIMARY_BUS)
+                || uSecondary != PDMPciDevGetByte(&pBusSub->aPciDev, VBOX_PCI_SECONDARY_BUS)
+                || uSubordinate != PDMPciDevGetByte(&pBusSub->aPciDev, VBOX_PCI_SUBORDINATE_BUS))
+            {
+                printIndent(pHlp, iIndent);
+                pHlp->pfnPrintf(pHlp, "CACHE INCONSISTENCY: primary=%d secondary=%d subordinate=%d\n",
+                                PDMPciDevGetByte(&pBusSub->aPciDev, VBOX_PCI_PRIMARY_BUS),
+                                PDMPciDevGetByte(&pBusSub->aPciDev, VBOX_PCI_SECONDARY_BUS),
+                                PDMPciDevGetByte(&pBusSub->aPciDev, VBOX_PCI_SUBORDINATE_BUS));
+            }
             printIndent(pHlp, iIndent);
             pHlp->pfnPrintf(pHlp, "behind bridge: I/O %#06x..%#06x\n",
-                            (PCIDevGetByte(&pBusSub->aPciDev, VBOX_PCI_IO_BASE) & 0xf0) << 8,
-                            (PCIDevGetByte(&pBusSub->aPciDev, VBOX_PCI_IO_LIMIT) & 0xf0) << 8 | 0xfff);
+                            (ich9pciGetByte(&pBusSub->aPciDev, VBOX_PCI_IO_BASE) & 0xf0) << 8,
+                            (ich9pciGetByte(&pBusSub->aPciDev, VBOX_PCI_IO_LIMIT) & 0xf0) << 8 | 0xfff);
             printIndent(pHlp, iIndent);
             pHlp->pfnPrintf(pHlp, "behind bridge: memory %#010x..%#010x\n",
-                            PCIDevGetWord(&pBusSub->aPciDev, VBOX_PCI_MEMORY_BASE) << 16,
-                            PCIDevGetWord(&pBusSub->aPciDev, VBOX_PCI_MEMORY_LIMIT) << 16 | 0xffff);
+                            (ich9pciGetWord(&pBusSub->aPciDev, VBOX_PCI_MEMORY_BASE) & 0xfff0) << 16,
+                            (ich9pciGetWord(&pBusSub->aPciDev, VBOX_PCI_MEMORY_LIMIT) & 0xfff0) << 16 | 0xfffff);
+            printIndent(pHlp, iIndent);
+            pHlp->pfnPrintf(pHlp, "behind bridge: prefetch memory %#010x..%#010x\n",
+                            (  ((uint64_t)ich9pciGetDWord(&pBusSub->aPciDev, VBOX_PCI_PREF_BASE_UPPER32) << 32)
+                             | (ich9pciGetWord(&pBusSub->aPciDev, VBOX_PCI_MEMORY_BASE) & 0xfff0) << 16),
+                            (  ((uint64_t)ich9pciGetDWord(&pBusSub->aPciDev, VBOX_PCI_PREF_LIMIT_UPPER32) << 32)
+                             | (ich9pciGetWord(&pBusSub->aPciDev, VBOX_PCI_MEMORY_LIMIT) & 0xfff0) << 16)
+                             | 0xfffff);
             ich9pciBusInfo(pBusSub, pHlp, iIndent + 1, fRegisters);
         }
     }
@@ -2532,14 +2660,14 @@ static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns, int iInstance, PCF
      */
 #if 0
     /* Host bridge device */
-    PCIDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
-    PCIDevSetDeviceId(  &pBus->aPciDev, 0x29e0); /* Desktop */
-    PCIDevSetRevisionId(&pBus->aPciDev,   0x01); /* rev. 01 */
-    PCIDevSetClassBase( &pBus->aPciDev,   0x06); /* bridge */
-    PCIDevSetClassSub(  &pBus->aPciDev,   0x00); /* Host/PCI bridge */
-    PCIDevSetClassProg( &pBus->aPciDev,   0x00); /* Host/PCI bridge */
-    PCIDevSetHeaderType(&pBus->aPciDev,   0x00); /* bridge */
-    PCIDevSetWord(&pBus->aPciDev,  VBOX_PCI_SEC_STATUS, 0x0280);  /* secondary status */
+    PDMPciDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
+    PDMPciDevSetDeviceId(  &pBus->aPciDev, 0x29e0); /* Desktop */
+    PDMPciDevSetRevisionId(&pBus->aPciDev,   0x01); /* rev. 01 */
+    PDMPciDevSetClassBase( &pBus->aPciDev,   0x06); /* bridge */
+    PDMPciDevSetClassSub(  &pBus->aPciDev,   0x00); /* Host/PCI bridge */
+    PDMPciDevSetClassProg( &pBus->aPciDev,   0x00); /* Host/PCI bridge */
+    PDMPciDevSetHeaderType(&pBus->aPciDev,   0x00); /* bridge */
+    PDMPciDevSetWord(&pBus->aPciDev,  VBOX_PCI_SEC_STATUS, 0x0280);  /* secondary status */
 
     pBus->aPciDev.pDevIns               = pDevIns;
     /* We register Host<->PCI controller on the bus */
@@ -2633,10 +2761,9 @@ static void ich9pciResetDevice(PPDMPCIDEV pDev)
     }
     else
     {
-        PCIDevSetCommand(pDev,
-                         PCIDevGetCommand(pDev)
-                         &
-                         ~(VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY |
+        ich9pciSetWord(pDev, VBOX_PCI_COMMAND,
+                         ich9pciGetWord(pDev, VBOX_PCI_COMMAND)
+                       & ~(VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY |
                            VBOX_PCI_COMMAND_MASTER | VBOX_PCI_COMMAND_SPECIAL |
                            VBOX_PCI_COMMAND_PARITY | VBOX_PCI_COMMAND_SERR |
                            VBOX_PCI_COMMAND_FAST_BACK | VBOX_PCI_COMMAND_INTX_DISABLE));
@@ -2644,8 +2771,8 @@ static void ich9pciResetDevice(PPDMPCIDEV pDev)
         /* Bridge device reset handlers processed later */
         if (!pciDevIsPci2PciBridge(pDev))
         {
-            PCIDevSetByte(pDev, VBOX_PCI_CACHE_LINE_SIZE, 0x0);
-            PCIDevSetInterruptLine(pDev, 0x0);
+            ich9pciSetByte(pDev, VBOX_PCI_CACHE_LINE_SIZE, 0x0);
+            ich9pciSetByte(pDev, VBOX_PCI_INTERRUPT_LINE, 0x0);
         }
 
         /* Reset MSI message control. */
@@ -2785,22 +2912,22 @@ static DECLCALLBACK(int)   ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
     /*
      * Fill in PCI configs and add them to the bus.
      */
-    PCIDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
-    PCIDevSetDeviceId(  &pBus->aPciDev, 0x2448); /* 82801 Mobile PCI bridge. */
-    PCIDevSetRevisionId(&pBus->aPciDev,   0xf2);
-    PCIDevSetClassSub(  &pBus->aPciDev,   0x04); /* pci2pci */
-    PCIDevSetClassBase( &pBus->aPciDev,   0x06); /* PCI_bridge */
-    PCIDevSetClassProg( &pBus->aPciDev,   0x01); /* Supports subtractive decoding. */
-    PCIDevSetHeaderType(&pBus->aPciDev,   0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */
-    PCIDevSetCommand(   &pBus->aPciDev,   0x00);
-    PCIDevSetStatus(    &pBus->aPciDev,   0x20); /* 66MHz Capable. */
-    PCIDevSetInterruptLine(&pBus->aPciDev, 0x00); /* This device does not assert interrupts. */
+    PDMPciDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
+    PDMPciDevSetDeviceId(  &pBus->aPciDev, 0x2448); /* 82801 Mobile PCI bridge. */
+    PDMPciDevSetRevisionId(&pBus->aPciDev,   0xf2);
+    PDMPciDevSetClassSub(  &pBus->aPciDev,   0x04); /* pci2pci */
+    PDMPciDevSetClassBase( &pBus->aPciDev,   0x06); /* PCI_bridge */
+    PDMPciDevSetClassProg( &pBus->aPciDev,   0x01); /* Supports subtractive decoding. */
+    PDMPciDevSetHeaderType(&pBus->aPciDev,   0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */
+    PDMPciDevSetCommand(   &pBus->aPciDev,   0x00);
+    PDMPciDevSetStatus(    &pBus->aPciDev,   0x20); /* 66MHz Capable. */
+    PDMPciDevSetInterruptLine(&pBus->aPciDev, 0x00); /* This device does not assert interrupts. */
 
     /*
      * This device does not generate interrupts. Interrupt delivery from
      * devices attached to the bus is unaffected.
      */
-    PCIDevSetInterruptPin (&pBus->aPciDev, 0x00);
+    PDMPciDevSetInterruptPin (&pBus->aPciDev, 0x00);
 
     /*
      * Register this PCI bridge. The called function will take care on which bus we will get registered.
@@ -2847,9 +2974,9 @@ static void ich9pcibridgeReset(PPDMDEVINS pDevIns)
     PICH9PCIBUS pBus = PDMINS_2_DATA(pDevIns, PICH9PCIBUS);
 
     /* Reset config space to default values. */
-    PCIDevSetByte(&pBus->aPciDev, VBOX_PCI_PRIMARY_BUS, 0);
-    PCIDevSetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS, 0);
-    PCIDevSetByte(&pBus->aPciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
+    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_PRIMARY_BUS, 0);
+    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS, 0);
+    ich9pciSetByte(&pBus->aPciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
 
     /* PCI-specific reset for each device. */
     for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd
index a546ca1..d5b9dad 100644
Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd differ
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd
index ad456a1..661492e 100644
Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd differ
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm
index 1e67f1c..bccf268 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm
@@ -7293,7 +7293,7 @@ vesa_pm_end:                                 ; 0xc4514 LB 0x1
 
 section _DATA progbits vstart=0x4600 align=1 ; size=0x371f class=DATA group=DGROUP
 _msg_vga_init:                               ; 0xc4600 LB 0x2f
-    db  'Oracle VM VirtualBox Version 5.1.12 VGA BIOS', 00dh, 00ah, 000h
+    db  'Oracle VM VirtualBox Version 5.1.14 VGA BIOS', 00dh, 00ah, 000h
 _vga_modes:                                  ; 0xc462f LB 0x80
     db  000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
     db  002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
@@ -8188,7 +8188,7 @@ _vbebios_vendor_name:                        ; 0xc7c73 LB 0x13
 _vbebios_product_name:                       ; 0xc7c86 LB 0x21
     db  'Oracle VM VirtualBox VBE Adapter', 000h
 _vbebios_product_revision:                   ; 0xc7ca7 LB 0x24
-    db  'Oracle VM VirtualBox Version 5.1.12', 000h
+    db  'Oracle VM VirtualBox Version 5.1.14', 000h
 _vbebios_info_string:                        ; 0xc7ccb LB 0x2b
     db  'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h
 _no_vbebios_info_string:                     ; 0xc7cf6 LB 0x29
@@ -8247,4 +8247,4 @@ section CONST2 progbits vstart=0x7d20 align=1 ; size=0x0 class=DATA group=DGROUP
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
-    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c4h
+    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c0h
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum
index 64b7476..3a7818a 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum
@@ -1 +1 @@
-3ad4030f75fbc4c4f340896b74bd37fb *VBoxVgaBios286.rom
+66a87d595db40d8be27d3858c116ecfa *VBoxVgaBios286.rom
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm
index d5c4a10..88efd62 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm
@@ -6769,7 +6769,7 @@ vesa_pm_end:                                 ; 0xc4514 LB 0x1
 
 section _DATA progbits vstart=0x4600 align=1 ; size=0x371f class=DATA group=DGROUP
 _msg_vga_init:                               ; 0xc4600 LB 0x2f
-    db  'Oracle VM VirtualBox Version 5.1.12 VGA BIOS', 00dh, 00ah, 000h
+    db  'Oracle VM VirtualBox Version 5.1.14 VGA BIOS', 00dh, 00ah, 000h
 _vga_modes:                                  ; 0xc462f LB 0x80
     db  000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
     db  002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
@@ -7664,7 +7664,7 @@ _vbebios_vendor_name:                        ; 0xc7c73 LB 0x13
 _vbebios_product_name:                       ; 0xc7c86 LB 0x21
     db  'Oracle VM VirtualBox VBE Adapter', 000h
 _vbebios_product_revision:                   ; 0xc7ca7 LB 0x24
-    db  'Oracle VM VirtualBox Version 5.1.12', 000h
+    db  'Oracle VM VirtualBox Version 5.1.14', 000h
 _vbebios_info_string:                        ; 0xc7ccb LB 0x2b
     db  'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h
 _no_vbebios_info_string:                     ; 0xc7cf6 LB 0x29
@@ -7723,4 +7723,4 @@ section CONST2 progbits vstart=0x7d20 align=1 ; size=0x0 class=DATA group=DGROUP
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
-    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0b9h
+    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0b5h
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum
index 25e6338..2bf5306 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum
@@ -1 +1 @@
-ed833c5294df462be2d19a5b2bf6e6cf *VBoxVgaBios386.rom
+309c3495246bb19390b897316241c49f *VBoxVgaBios386.rom
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm
index 84f4ad0..15d836b 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm
@@ -7434,7 +7434,7 @@ vesa_pm_end:                                 ; 0xc4514 LB 0x1
 
 section _DATA progbits vstart=0x4600 align=1 ; size=0x371f class=DATA group=DGROUP
 _msg_vga_init:                               ; 0xc4600 LB 0x2f
-    db  'Oracle VM VirtualBox Version 5.1.12 VGA BIOS', 00dh, 00ah, 000h
+    db  'Oracle VM VirtualBox Version 5.1.14 VGA BIOS', 00dh, 00ah, 000h
 _vga_modes:                                  ; 0xc462f LB 0x80
     db  000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
     db  002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
@@ -8329,7 +8329,7 @@ _vbebios_vendor_name:                        ; 0xc7c73 LB 0x13
 _vbebios_product_name:                       ; 0xc7c86 LB 0x21
     db  'Oracle VM VirtualBox VBE Adapter', 000h
 _vbebios_product_revision:                   ; 0xc7ca7 LB 0x24
-    db  'Oracle VM VirtualBox Version 5.1.12', 000h
+    db  'Oracle VM VirtualBox Version 5.1.14', 000h
 _vbebios_info_string:                        ; 0xc7ccb LB 0x2b
     db  'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h
 _no_vbebios_info_string:                     ; 0xc7cf6 LB 0x29
@@ -8388,4 +8388,4 @@ section CONST2 progbits vstart=0x7d20 align=1 ; size=0x0 class=DATA group=DGROUP
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
-    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04bh
+    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 047h
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum
index 7099855..bdcba9e 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum
@@ -1 +1 @@
-fa53164a127c5e858864ea3d97aaaab4 *VBoxVgaBios8086.rom
+95f66ba7097d50ee351fb0f22651d793 *VBoxVgaBios8086.rom
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
index aa967b0..a576867 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
@@ -54,13 +54,6 @@
 /* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
 #include "DevVGA.h"
 
-#ifdef DEBUG
-/* Enable to log FIFO register accesses. */
-//# define DEBUG_FIFO_ACCESS
-/* Enable to log GMR page accesses. */
-//# define DEBUG_GMR_ACCESS
-#endif
-
 #include "DevVGA-SVGA.h"
 #include "vmsvga/svga_reg.h"
 #include "vmsvga/svga_escape.h"
@@ -152,9 +145,67 @@ typedef struct VMSVGAR3STATE
     /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
     STAMPROFILE             StatBusyDelayEmts;
 
-    STAMPROFILE             StatR3CmdPresent;
-    STAMPROFILE             StatR3CmdDrawPrimitive;
-    STAMPROFILE             StatR3CmdSurfaceDMA;
+    STAMPROFILE             StatR3Cmd3dPresentProf;
+    STAMPROFILE             StatR3Cmd3dDrawPrimitivesProf;
+    STAMPROFILE             StatR3Cmd3dSurfaceDmaProf;
+    STAMCOUNTER             StatR3CmdDefineGmr2;
+    STAMCOUNTER             StatR3CmdDefineGmr2Free;
+    STAMCOUNTER             StatR3CmdDefineGmr2Modify;
+    STAMCOUNTER             StatR3CmdRemapGmr2;
+    STAMCOUNTER             StatR3CmdRemapGmr2Modify;
+    STAMCOUNTER             StatR3CmdInvalidCmd;
+    STAMCOUNTER             StatR3CmdFence;
+    STAMCOUNTER             StatR3CmdUpdate;
+    STAMCOUNTER             StatR3CmdUpdateVerbose;
+    STAMCOUNTER             StatR3CmdDefineCursor;
+    STAMCOUNTER             StatR3CmdDefineAlphaCursor;
+    STAMCOUNTER             StatR3CmdEscape;
+    STAMCOUNTER             StatR3CmdDefineScreen;
+    STAMCOUNTER             StatR3CmdDestroyScreen;
+    STAMCOUNTER             StatR3CmdDefineGmrFb;
+    STAMCOUNTER             StatR3CmdBlitGmrFbToScreen;
+    STAMCOUNTER             StatR3CmdBlitScreentoGmrFb;
+    STAMCOUNTER             StatR3CmdAnnotationFill;
+    STAMCOUNTER             StatR3CmdAnnotationCopy;
+    STAMCOUNTER             StatR3Cmd3dSurfaceDefine;
+    STAMCOUNTER             StatR3Cmd3dSurfaceDefineV2;
+    STAMCOUNTER             StatR3Cmd3dSurfaceDestroy;
+    STAMCOUNTER             StatR3Cmd3dSurfaceCopy;
+    STAMCOUNTER             StatR3Cmd3dSurfaceStretchBlt;
+    STAMCOUNTER             StatR3Cmd3dSurfaceDma;
+    STAMCOUNTER             StatR3Cmd3dSurfaceScreen;
+    STAMCOUNTER             StatR3Cmd3dContextDefine;
+    STAMCOUNTER             StatR3Cmd3dContextDestroy;
+    STAMCOUNTER             StatR3Cmd3dSetTransform;
+    STAMCOUNTER             StatR3Cmd3dSetZRange;
+    STAMCOUNTER             StatR3Cmd3dSetRenderState;
+    STAMCOUNTER             StatR3Cmd3dSetRenderTarget;
+    STAMCOUNTER             StatR3Cmd3dSetTextureState;
+    STAMCOUNTER             StatR3Cmd3dSetMaterial;
+    STAMCOUNTER             StatR3Cmd3dSetLightData;
+    STAMCOUNTER             StatR3Cmd3dSetLightEnable;
+    STAMCOUNTER             StatR3Cmd3dSetViewPort;
+    STAMCOUNTER             StatR3Cmd3dSetClipPlane;
+    STAMCOUNTER             StatR3Cmd3dClear;
+    STAMCOUNTER             StatR3Cmd3dPresent;
+    STAMCOUNTER             StatR3Cmd3dPresentReadBack;
+    STAMCOUNTER             StatR3Cmd3dShaderDefine;
+    STAMCOUNTER             StatR3Cmd3dShaderDestroy;
+    STAMCOUNTER             StatR3Cmd3dSetShader;
+    STAMCOUNTER             StatR3Cmd3dSetShaderConst;
+    STAMCOUNTER             StatR3Cmd3dDrawPrimitives;
+    STAMCOUNTER             StatR3Cmd3dSetScissorRect;
+    STAMCOUNTER             StatR3Cmd3dBeginQuery;
+    STAMCOUNTER             StatR3Cmd3dEndQuery;
+    STAMCOUNTER             StatR3Cmd3dWaitForQuery;
+    STAMCOUNTER             StatR3Cmd3dGenerateMipmaps;
+    STAMCOUNTER             StatR3Cmd3dActivateSurface;
+    STAMCOUNTER             StatR3Cmd3dDeactivateSurface;
+
+    STAMCOUNTER             StatR3RegConfigDoneWr;
+    STAMCOUNTER             StatR3RegGmrDescriptorWr;
+    STAMCOUNTER             StatR3RegGmrDescriptorWrErrors;
+    STAMCOUNTER             StatR3RegGmrDescriptorWrFree;
 
     STAMCOUNTER             StatFifoCommands;
     STAMCOUNTER             StatFifoErrors;
@@ -229,9 +280,68 @@ static SSMFIELD const g_aVMSVGAR3STATEFields[] =
     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, hBusyDelayedEmts),
 #endif
     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatBusyDelayEmts),
-    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdPresent),
-    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDrawPrimitive),
-    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdSurfaceDMA),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentProf),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2Free),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2Modify),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRemapGmr2),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRemapGmr2Modify),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdInvalidCmd),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdFence),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdUpdate),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdUpdateVerbose),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineCursor),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineAlphaCursor),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdEscape),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineScreen),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDestroyScreen),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmrFb),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdAnnotationFill),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdAnnotationCopy),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDma),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dContextDefine),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dContextDestroy),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetTransform),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetZRange),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetRenderState),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetTextureState),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetMaterial),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetLightData),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetLightEnable),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetViewPort),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetClipPlane),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dClear),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresent),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentReadBack),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dShaderDefine),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dShaderDestroy),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetShader),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetShaderConst),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetScissorRect),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dBeginQuery),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dEndQuery),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dWaitForQuery),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dActivateSurface),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface),
+
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegConfigDoneWr),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWr),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree),
+
     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCommands),
     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoErrors),
     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoUnkCmds),
@@ -299,10 +409,11 @@ static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces);
  *
  * @returns Index register string or "UNKNOWN"
  * @param   pThis       VMSVGA State
+ * @param   idxReg      The index register.
  */
-static const char *vmsvgaIndexToString(PVGASTATE pThis)
+static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
 {
-    switch (pThis->svga.u32IndexReg)
+    switch (idxReg)
     {
     case SVGA_REG_ID:
         return "SVGA_REG_ID";
@@ -406,9 +517,9 @@ static const char *vmsvgaIndexToString(PVGASTATE pThis)
         return "SVGA_REG_NUM_DISPLAYS";
 
     default:
-        if (pThis->svga.u32IndexReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
+        if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
             return "SVGA_SCRATCH_BASE reg";
-        if (pThis->svga.u32IndexReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
+        if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
             return "SVGA_PALETTE_BASE reg";
         return "UNKNOWN";
     }
@@ -541,11 +652,11 @@ static const char *vmsvgaFIFOCmdToString(uint32_t u32Cmd)
 /**
  * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
  */
-DECLCALLBACK(void) vmsvgaPortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t uScreenId, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
+DECLCALLBACK(void) vmsvgaPortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
 {
     PVGASTATE pThis = RT_FROM_MEMBER(pInterface, VGASTATE, IPort);
 
-    Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", uScreenId, x, y, cx, cy));
+    Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
     VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
 
     if (x < pThis->svga.uWidth)
@@ -580,9 +691,9 @@ DECLCALLBACK(void) vmsvgaPortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t u
      * Now inform the 3D backend.
      */
     if (pThis->svga.f3DEnabled)
-        vmsvga3dUpdateHostScreenViewport(pThis, uScreenId, &OldViewport);
+        vmsvga3dUpdateHostScreenViewport(pThis, idScreen, &OldViewport);
 # else
-    RT_NOREF(uScreenId, OldViewport);
+    RT_NOREF(idScreen, OldViewport);
 # endif
 }
 #endif /* IN_RING3 */
@@ -597,20 +708,32 @@ DECLCALLBACK(void) vmsvgaPortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t u
 PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
 {
     int rc = VINF_SUCCESS;
-
     *pu32 = 0;
-    switch (pThis->svga.u32IndexReg)
+
+    /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
+    uint32_t idxReg = pThis->svga.u32IndexReg;
+    if (   idxReg >= SVGA_REG_CAPABILITIES
+        && pThis->svga.u32SVGAId == SVGA_ID_0)
+    {
+        idxReg += SVGA_PALETTE_BASE - SVGA_REG_CAPABILITIES;
+        Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
+    }
+
+    switch (idxReg)
     {
     case SVGA_REG_ID:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
         *pu32 = pThis->svga.u32SVGAId;
         break;
 
     case SVGA_REG_ENABLE:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
         *pu32 = pThis->svga.fEnabled;
         break;
 
     case SVGA_REG_WIDTH:
     {
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
         if (    pThis->svga.fEnabled
             &&  pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
         {
@@ -629,6 +752,7 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
 
     case SVGA_REG_HEIGHT:
     {
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
         if (    pThis->svga.fEnabled
             &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
         {
@@ -646,15 +770,18 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
     }
 
     case SVGA_REG_MAX_WIDTH:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
         *pu32 = pThis->svga.u32MaxWidth;
         break;
 
     case SVGA_REG_MAX_HEIGHT:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
         *pu32 = pThis->svga.u32MaxHeight;
         break;
 
     case SVGA_REG_DEPTH:
         /* This returns the color depth of the current mode. */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
         switch (pThis->svga.uBpp)
         {
         case 15:
@@ -671,6 +798,7 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
         break;
 
     case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
         if (    pThis->svga.fEnabled
             &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
         {
@@ -687,6 +815,7 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
         break;
 
     case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
         if (    pThis->svga.fEnabled
             &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
         {
@@ -703,6 +832,7 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
         break;
 
     case SVGA_REG_PSEUDOCOLOR:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
         *pu32 = 0;
         break;
 
@@ -755,17 +885,20 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
             u32BlueMask  = 0x000000ff;
             break;
         }
-        switch (pThis->svga.u32IndexReg)
+        switch (idxReg)
         {
         case SVGA_REG_RED_MASK:
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
             *pu32 = u32RedMask;
             break;
 
         case SVGA_REG_GREEN_MASK:
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
             *pu32 = u32GreenMask;
             break;
 
         case SVGA_REG_BLUE_MASK:
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
             *pu32 = u32BlueMask;
             break;
         }
@@ -774,6 +907,7 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
 
     case SVGA_REG_BYTES_PER_LINE:
     {
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
         if (    pThis->svga.fEnabled
             &&  pThis->svga.cbScanline)
         {
@@ -791,15 +925,18 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
     }
 
     case SVGA_REG_VRAM_SIZE:            /* VRAM size */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
         *pu32 = pThis->vram_size;
         break;
 
     case SVGA_REG_FB_START:             /* Frame buffer physical address. */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
         Assert(pThis->GCPhysVRAM <= 0xffffffff);
         *pu32 = pThis->GCPhysVRAM;
         break;
 
     case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
         /* Always zero in our case. */
         *pu32 = 0;
         break;
@@ -809,6 +946,8 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
 #ifndef IN_RING3
         rc = VINF_IOM_R3_IOPORT_READ;
 #else
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
+
         /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
         if (    pThis->svga.fEnabled
             &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
@@ -826,27 +965,33 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
     }
 
     case SVGA_REG_CAPABILITIES:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
         *pu32 = pThis->svga.u32RegCaps;
         break;
 
     case SVGA_REG_MEM_START:           /* FIFO start */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
         Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
         *pu32 = pThis->svga.GCPhysFIFO;
         break;
 
     case SVGA_REG_MEM_SIZE:            /* FIFO size */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
         *pu32 = pThis->svga.cbFIFO;
         break;
 
     case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
         *pu32 = pThis->svga.fConfigured;
         break;
 
     case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
         *pu32 = 0;
         break;
 
     case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
         if (pThis->svga.fBusy)
         {
 #ifndef IN_RING3
@@ -905,102 +1050,146 @@ PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
         break;
 
     case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
         *pu32 = pThis->svga.u32GuestId;
         break;
 
     case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
         *pu32 = pThis->svga.cScratchRegion;
         break;
 
     case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
         *pu32 = SVGA_FIFO_NUM_REGS;
         break;
 
     case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
         *pu32 = pThis->svga.u32PitchLock;
         break;
 
     case SVGA_REG_IRQMASK:             /* Interrupt mask */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
         *pu32 = pThis->svga.u32IrqMask;
         break;
 
     /* See "Guest memory regions" below. */
     case SVGA_REG_GMR_ID:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
         *pu32 = pThis->svga.u32CurrentGMRId;
         break;
 
     case SVGA_REG_GMR_DESCRIPTOR:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
         /* Write only */
         *pu32 = 0;
         break;
 
     case SVGA_REG_GMR_MAX_IDS:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
         *pu32 = VMSVGA_MAX_GMR_IDS;
         break;
 
     case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
         *pu32 = VMSVGA_MAX_GMR_PAGES;
         break;
 
     case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
         *pu32 = pThis->svga.fTraces;
         break;
 
     case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
         *pu32 = VMSVGA_MAX_GMR_PAGES;
         break;
 
     case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
         *pu32 = VMSVGA_SURFACE_SIZE;
         break;
 
     case SVGA_REG_TOP:               /* Must be 1 more than the last register */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
         break;
 
-    case SVGA_PALETTE_BASE:         /* Base of SVGA color map */
-        break;
-        /* Next 768 (== 256*3) registers exist for colormap */
-
     /* Mouse cursor support. */
     case SVGA_REG_CURSOR_ID:
     case SVGA_REG_CURSOR_X:
     case SVGA_REG_CURSOR_Y:
     case SVGA_REG_CURSOR_ON:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxRd);
         break;
 
     /* Legacy multi-monitor support */
     case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
         *pu32 = 1;
         break;
 
     case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
+        *pu32 = 0;
+        break;
+
     case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
+        *pu32 = 0;
+        break;
+
     case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
+        *pu32 = 0;
+        break;
+
     case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
         *pu32 = 0;
         break;
 
     case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
         *pu32 = pThis->svga.uWidth;
         break;
 
     case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
         *pu32 = pThis->svga.uHeight;
         break;
 
     case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
         *pu32 = 1;  /* Must return something sensible here otherwise the Linux driver will take a legacy code path without 3d support. */
         break;
 
     default:
-        if (    pThis->svga.u32IndexReg >= SVGA_SCRATCH_BASE
-            &&  pThis->svga.u32IndexReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion)
+    {
+        uint32_t offReg;
+        if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
+        {
+            *pu32 = pThis->svga.au32ScratchRegion[offReg];
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
+        }
+        else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
         {
-            *pu32 = pThis->svga.au32ScratchRegion[pThis->svga.u32IndexReg - SVGA_SCRATCH_BASE];
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
+            /* Next 768 (== 256*3) registers exist for colormap */
+        }
+        else
+        {
+#if !defined(IN_RING3) && defined(VBOX_STRICT)
+            rc = VINF_IOM_R3_IOPORT_READ;
+#else
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
+            AssertMsgFailed(("reg=%#x\n", idxReg));
+#endif
         }
         break;
     }
-    Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis), pThis->svga.u32IndexReg, *pu32, rc));
+    }
+    Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
     return rc;
 }
 
@@ -1110,22 +1299,34 @@ DECLINLINE(void) vmsvgaSafeFifoBusyRegUpdate(PVGASTATE pThis, bool fState)
  */
 PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
 {
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA3D)
+#ifdef IN_RING3
     PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
 #endif
     int            rc = VINF_SUCCESS;
 
-    Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis), pThis->svga.u32IndexReg, u32));
-    switch (pThis->svga.u32IndexReg)
+    /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
+    uint32_t idxReg = pThis->svga.u32IndexReg;
+    if (   idxReg >= SVGA_REG_CAPABILITIES
+        && pThis->svga.u32SVGAId == SVGA_ID_0)
+    {
+        idxReg += SVGA_PALETTE_BASE - SVGA_REG_CAPABILITIES;
+        Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
+    }
+    Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
+    switch (idxReg)
     {
     case SVGA_REG_ID:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
         if (    u32 == SVGA_ID_0
             ||  u32 == SVGA_ID_1
             ||  u32 == SVGA_ID_2)
             pThis->svga.u32SVGAId = u32;
+        else
+            AssertMsgFailed(("%#x\n", u32));
         break;
 
     case SVGA_REG_ENABLE:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
         if (    pThis->svga.fEnabled    == u32
             &&  pThis->last_bpp         == (unsigned)pThis->svga.uBpp
             &&  pThis->last_scr_width   == (unsigned)pThis->svga.uWidth
@@ -1193,6 +1394,7 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_WIDTH:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
         if (pThis->svga.uWidth != u32)
         {
             if (pThis->svga.fEnabled)
@@ -1212,6 +1414,7 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_HEIGHT:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
         if (pThis->svga.uHeight != u32)
         {
             if (pThis->svga.fEnabled)
@@ -1231,10 +1434,12 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_DEPTH:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
         /** @todo read-only?? */
         break;
 
     case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
         if (pThis->svga.uBpp != u32)
         {
             if (pThis->svga.fEnabled)
@@ -1254,10 +1459,12 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_PSEUDOCOLOR:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
         break;
 
     case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
 #ifdef IN_RING3
+        STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
         pThis->svga.fConfigured = u32;
         /* Disabling the FIFO enables tracing (dirty page detection) by default. */
         if (!pThis->svga.fConfigured)
@@ -1271,6 +1478,7 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
         if (    pThis->svga.fEnabled
             &&  pThis->svga.fConfigured)
         {
@@ -1293,17 +1501,21 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" (read-only) */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
         break;
 
     case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
         pThis->svga.u32GuestId = u32;
         break;
 
     case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
         pThis->svga.u32PitchLock = u32;
         break;
 
     case SVGA_REG_IRQMASK:             /* Interrupt mask */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
         pThis->svga.u32IrqMask = u32;
 
         /* Irq pending after the above change? */
@@ -1321,26 +1533,35 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
     case SVGA_REG_CURSOR_X:
     case SVGA_REG_CURSOR_Y:
     case SVGA_REG_CURSOR_ON:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxWr);
         break;
 
     /* Legacy multi-monitor support */
     case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
         break;
     case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
         break;
     case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
         break;
     case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
         break;
     case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
         break;
     case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
         break;
     case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
         break;
 #ifdef VBOX_WITH_VMSVGA3D
     /* See "Guest memory regions" below. */
     case SVGA_REG_GMR_ID:
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
         pThis->svga.u32CurrentGMRId = u32;
         break;
 
@@ -1350,76 +1571,90 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 # else /* IN_RING3 */
     {
-        SVGAGuestMemDescriptor desc;
-        RTGCPHYS               GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
-        RTGCPHYS               GCPhysBase = GCPhys;
-        uint32_t               idGMR = pThis->svga.u32CurrentGMRId;
-        uint32_t               cDescriptorsAllocated = 16;
-        uint32_t               iDescriptor = 0;
+        STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
 
         /* Validate current GMR id. */
+        uint32_t idGMR = pThis->svga.u32CurrentGMRId;
         AssertBreak(idGMR < VMSVGA_MAX_GMR_IDS);
 
         /* Free the old GMR if present. */
         vmsvgaGMRFree(pThis, idGMR);
 
         /* Just undefine the GMR? */
+        RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
         if (GCPhys == 0)
+        {
+            STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
             break;
+        }
 
-        pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
-        AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
 
         /* Never cross a page boundary automatically. */
+        const uint32_t          cMaxPages   = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
+        uint32_t                cPagesTotal = 0;
+        uint32_t                iDesc       = 0;
+        PVMSVGAGMRDESCRIPTOR    paDescs     = NULL;
+        uint32_t                cLoops      = 0;
+        RTGCPHYS                GCPhysBase  = GCPhys;
         while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
         {
             /* Read descriptor. */
+            SVGAGuestMemDescriptor desc;
             rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc));
             AssertRCBreak(rc);
 
-            if (    desc.ppn == 0
-                &&  desc.numPages == 0)
-                break;  /* terminator */
-
-            if (    desc.ppn != 0
-                &&  desc.numPages == 0)
+            if (desc.numPages != 0)
             {
-                /* Pointer to the next physical page of descriptors. */
-                GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
-            }
-            else
-            {
-                if (iDescriptor == cDescriptorsAllocated)
+                AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
+                cPagesTotal += desc.numPages;
+                AssertBreakStmt(cPagesTotal   <= cMaxPages, rc = VERR_OUT_OF_RANGE);
+
+                if ((iDesc & 15) == 0)
                 {
-                    cDescriptorsAllocated += 16;
-                    pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemRealloc(pSVGAState->aGMR[idGMR].paDesc, cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
-                    AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
+                    void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
+                    AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
+                    paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
                 }
 
-                pSVGAState->aGMR[idGMR].paDesc[iDescriptor].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
-                pSVGAState->aGMR[idGMR].paDesc[iDescriptor++].numPages = desc.numPages;
-                pSVGAState->aGMR[idGMR].cbTotal += desc.numPages * PAGE_SIZE;
+                paDescs[iDesc].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
+                paDescs[iDesc++].numPages = desc.numPages;
 
                 /* Continue with the next descriptor. */
                 GCPhys += sizeof(desc);
             }
+            else if (desc.ppn == 0)
+                break;  /* terminator */
+            else /* Pointer to the next physical page of descriptors. */
+                GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
+
+            cLoops++;
+            AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
         }
-        pSVGAState->aGMR[idGMR].numDescriptors = iDescriptor;
-        Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x\n", idGMR, iDescriptor, pSVGAState->aGMR[idGMR].cbTotal));
 
-        if (!pSVGAState->aGMR[idGMR].numDescriptors)
+        AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
+        if (RT_SUCCESS(rc))
         {
-            AssertFailed();
-            RTMemFree(pSVGAState->aGMR[idGMR].paDesc);
-            pSVGAState->aGMR[idGMR].paDesc = NULL;
+            /* Commit the GMR. */
+            pSVGAState->aGMR[idGMR].paDesc         = paDescs;
+            pSVGAState->aGMR[idGMR].numDescriptors = iDesc;
+            pSVGAState->aGMR[idGMR].cMaxPages      = cPagesTotal;
+            pSVGAState->aGMR[idGMR].cbTotal        = cPagesTotal * PAGE_SIZE;
+            Assert((pSVGAState->aGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
+            Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
+                 idGMR, iDesc, pSVGAState->aGMR[idGMR].cbTotal, cPagesTotal));
+        }
+        else
+        {
+            RTMemFree(paDescs);
+            STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
         }
-        AssertRC(rc);
         break;
     }
 # endif /* IN_RING3 */
 #endif // VBOX_WITH_VMSVGA3D
 
     case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
         if (pThis->svga.fTraces == u32)
             break; /* nothing to do */
 
@@ -1431,14 +1666,12 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
         break;
 
     case SVGA_REG_TOP:               /* Must be 1 more than the last register */
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
         break;
 
-    case SVGA_PALETTE_BASE:         /* Base of SVGA color map */
-        break;
-        /* Next 768 (== 256*3) registers exist for colormap */
-
     case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
-        Log(("Write to deprecated register %x - val %x ignored\n", pThis->svga.u32IndexReg, u32));
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
+        Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
         break;
 
     case SVGA_REG_FB_START:
@@ -1462,17 +1695,35 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
     case SVGA_REG_GMR_MAX_IDS:
     case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
         /* Read only - ignore. */
-        Log(("Write to R/O register %x - val %x ignored\n", pThis->svga.u32IndexReg, u32));
+        Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
+        STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
         break;
 
     default:
-        if (    pThis->svga.u32IndexReg >= SVGA_SCRATCH_BASE
-            &&  pThis->svga.u32IndexReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion)
+    {
+        uint32_t offReg;
+        if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
+        {
+            pThis->svga.au32ScratchRegion[offReg] = u32;
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
+        }
+        else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
         {
-            pThis->svga.au32ScratchRegion[pThis->svga.u32IndexReg - SVGA_SCRATCH_BASE] = u32;
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
+            /* Next 768 (== 256*3) registers exist for colormap */
+        }
+        else
+        {
+#if !defined(IN_RING3) && defined(VBOX_STRICT)
+            rc = VINF_IOM_R3_IOPORT_WRITE;
+#else
+            STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
+            AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
+#endif
         }
         break;
     }
+    }
     return rc;
 }
 
@@ -1489,7 +1740,7 @@ PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
  *                      variable regardless of what @a cb might say.
  * @param   cb          Number of bytes read.
  */
-PDMBOTHCBDECL(int) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+PDMBOTHCBDECL(int) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
 {
     PVGASTATE   pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
     RT_NOREF_PV(pvUser);
@@ -1497,12 +1748,12 @@ PDMBOTHCBDECL(int) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
     /* Ignore non-dword accesses. */
     if (cb != 4)
     {
-        Log(("Ignoring non-dword read at %x cb=%d\n", Port, cb));
+        Log(("Ignoring non-dword read at %x cb=%d\n", uPort, cb));
         *pu32 = UINT32_MAX;
         return VINF_SUCCESS;
     }
 
-    switch (Port - pThis->svga.BasePort)
+    switch (uPort - pThis->svga.BasePort)
     {
     case SVGA_INDEX_PORT:
         *pu32 = pThis->svga.u32IndexReg;
@@ -1536,7 +1787,7 @@ PDMBOTHCBDECL(int) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
  * @param   u32         The value to output.
  * @param   cb          The value size in bytes.
  */
-PDMBOTHCBDECL(int) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+PDMBOTHCBDECL(int) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
 {
     PVGASTATE   pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
     RT_NOREF_PV(pvUser);
@@ -1544,11 +1795,11 @@ PDMBOTHCBDECL(int) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port
     /* Ignore non-dword accesses. */
     if (cb != 4)
     {
-        Log(("Ignoring non-dword write at %x val=%x cb=%d\n", Port, u32, cb));
+        Log(("Ignoring non-dword write at %x val=%x cb=%d\n", uPort, u32, cb));
         return VINF_SUCCESS;
     }
 
-    switch (Port - pThis->svga.BasePort)
+    switch (uPort - pThis->svga.BasePort)
     {
     case SVGA_INDEX_PORT:
         pThis->svga.u32IndexReg = u32;
@@ -1588,6 +1839,7 @@ PDMBOTHCBDECL(int) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port
  */
 static int vmsvgaFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
 {
+    RT_NOREF(pVM);
     RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
     uint32_t *pFIFO = pThis->svga.pFIFOR3;
 
@@ -1932,13 +2184,13 @@ static int vmsvgaFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWri
  * @param   pvUser          User argument.
  */
 static DECLCALLBACK(VBOXSTRICTRC)
-vmsvgaR3FIFOAccessHandler(PVM pVM, PVMCPU pVCpu RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
+vmsvgaR3FIFOAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
                           PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
 {
     PVGASTATE   pThis = (PVGASTATE)pvUser;
     int         rc;
     Assert(pThis);
-    Assert(GCPhys >= pThis->GCPhysVRAM);
+    Assert(GCPhys >= pThis->svga.GCPhysFIFO);
     NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin);
 
     rc = vmsvgaFIFOAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
@@ -1952,6 +2204,8 @@ vmsvgaR3FIFOAccessHandler(PVM pVM, PVMCPU pVCpu RTGCPHYS GCPhys, void *pvPhys, v
 #endif /* DEBUG_FIFO_ACCESS */
 
 #ifdef DEBUG_GMR_ACCESS
+# ifdef IN_RING3
+
 /**
  * HC access handler for the FIFO.
  *
@@ -1974,7 +2228,7 @@ vmsvgaR3GMRAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, v
     PVGASTATE   pThis = (PVGASTATE)pvUser;
     Assert(pThis);
     PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
-    NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin);
+    NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
 
     Log(("vmsvgaR3GMRAccessHandler: GMR access to page %RGp\n", GCPhys));
 
@@ -1994,6 +2248,7 @@ vmsvgaR3GMRAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, v
                      * Then return telling the caller to restart the guest instruction.
                      */
                     int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
+                    AssertRC(rc);
                     goto end;
                 }
             }
@@ -2003,9 +2258,7 @@ end:
     return VINF_PGM_HANDLER_DO_DEFAULT;
 }
 
-# ifdef IN_RING3
-
-/* Callback handler for VMR3ReqCallWait */
+/* Callback handler for VMR3ReqCallWaitU */
 static DECLCALLBACK(int) vmsvgaRegisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
 {
     PVGASTATE       pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
@@ -2023,7 +2276,7 @@ static DECLCALLBACK(int) vmsvgaRegisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
     return VINF_SUCCESS;
 }
 
-/* Callback handler for VMR3ReqCallWait */
+/* Callback handler for VMR3ReqCallWaitU */
 static DECLCALLBACK(int) vmsvgaDeregisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
 {
     PVGASTATE       pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
@@ -2038,7 +2291,7 @@ static DECLCALLBACK(int) vmsvgaDeregisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
     return VINF_SUCCESS;
 }
 
-/* Callback handler for VMR3ReqCallWait */
+/* Callback handler for VMR3ReqCallWaitU */
 static DECLCALLBACK(int) vmsvgaResetGMRHandlers(PVGASTATE pThis)
 {
     PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
@@ -2661,12 +2914,14 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
             case SVGA_CMD_INVALID_CMD:
                 /* Nothing to do. */
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
                 break;
 
             case SVGA_CMD_FENCE:
             {
                 SVGAFifoCmdFence *pCmdFence;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
                 {
                     Log(("vmsvgaFIFOLoop: SVGA_CMD_FENCE %x\n", pCmdFence->fence));
@@ -2695,6 +2950,10 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
                 SVGAFifoCmdUpdate *pUpdate;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pUpdate, SVGAFifoCmdUpdate, sizeof(*pUpdate));
+                if (enmCmdId == SVGA_CMD_UPDATE)
+                    STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdate);
+                else
+                    STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdateVerbose);
                 Log(("vmsvgaFIFOLoop: UPDATE (%d,%d)(%d,%d)\n", pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height));
                 vgaR3UpdateDisplay(pThis, pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height);
                 break;
@@ -2705,6 +2964,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                 /* Followed by bitmap data. */
                 SVGAFifoCmdDefineCursor *pCursor;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineCursor, sizeof(*pCursor));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineCursor);
                 AssertFailed(); /** @todo implement when necessary. */
                 break;
             }
@@ -2718,6 +2978,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
 
                 SVGAFifoCmdDefineAlphaCursor *pCursor;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCursor));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineAlphaCursor);
 
                 Log(("vmsvgaFIFOLoop: ALPHA_CURSOR id=%d size (%d,%d) hotspot (%d,%d)\n", pCursor->id, pCursor->width, pCursor->height, pCursor->hotspotX, pCursor->hotspotY));
 
@@ -2772,6 +3033,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                 /* Followed by nsize bytes of data. */
                 SVGAFifoCmdEscape *pEscape;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pEscape, SVGAFifoCmdEscape, sizeof(*pEscape));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdEscape);
 
                 /* Refetch the command buffer with the variable data; undo size increase (ugly) */
                 AssertBreak(pEscape->size < VMSVGA_FIFO_SIZE);
@@ -2822,6 +3084,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                 SVGAFifoCmdDefineGMR2 *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_GMR2 id=%x %x pages\n", pCmd->gmrId, pCmd->numPages));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2);
 
                 /* Validate current GMR id. */
                 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
@@ -2829,14 +3092,24 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
 
                 if (!pCmd->numPages)
                 {
+                    STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Free);
                     vmsvgaGMRFree(pThis, pCmd->gmrId);
                 }
                 else
                 {
                     PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
+                    if (pGMR->cMaxPages)
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Modify);
+
+                    /* Not sure if we should always free the descriptor, but for simplicity
+                       we do so if the new size is smaller than the current. */
+                    /** @todo always free the descriptor in SVGA_CMD_DEFINE_GMR2? */
+                    if (pGMR->cbTotal / X86_PAGE_SIZE > pGMR->cMaxPages)
+                        vmsvgaGMRFree(pThis, pCmd->gmrId);
+
                     pGMR->cMaxPages = pCmd->numPages;
+                    /* The rest is done by the REMAP_GMR2 command. */
                 }
-                /* everything done in remap */
                 break;
             }
 
@@ -2845,51 +3118,64 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                 /* Followed by page descriptors or guest ptr. */
                 SVGAFifoCmdRemapGMR2 *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
-                uint32_t cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
-                uint32_t cbCmd;
-                uint64_t *paNewPage64 = NULL;
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_REMAP_GMR2 id=%x flags=%x offset=%x npages=%x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
                 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
 
                 /* Calculate the size of what comes after next and fetch it. */
-                cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
+                uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
                 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
                     cbCmd += sizeof(SVGAGuestPtr);
                 else
-                if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
                 {
-                    cbCmd         += cbPageDesc;
-                    pCmd->numPages = 1;
-                }
-                else
-                {
-                    AssertBreak(pCmd->numPages <= VMSVGA_FIFO_SIZE);
-                    cbCmd += cbPageDesc * pCmd->numPages;
+                    uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
+                    if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
+                    {
+                        cbCmd         += cbPageDesc;
+                        pCmd->numPages = 1;
+                    }
+                    else
+                    {
+                        AssertBreak(pCmd->numPages <= VMSVGA_FIFO_SIZE / cbPageDesc);
+                        cbCmd += cbPageDesc * pCmd->numPages;
+                    }
                 }
                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
 
-                /* Validate current GMR id. */
+                /* Validate current GMR id and size. */
                 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
                 PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
-                AssertBreak(pCmd->offsetPages + pCmd->numPages <= pGMR->cMaxPages);
+                AssertBreak(   (uint64_t)pCmd->offsetPages + pCmd->numPages
+                            <= RT_MIN(pGMR->cMaxPages, RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE)));
                 AssertBreak(!pCmd->offsetPages || pGMR->paDesc); /** @todo */
 
-                /* Save the old page descriptors as an array of page addresses (>> PAGE_SHIFT) */
+                if (pCmd->numPages == 0)
+                    break;
+
+                /* Calc new total page count so we can use it instead of cMaxPages for allocations below. */
+                uint32_t const cNewTotalPages = RT_MAX(pGMR->cbTotal >> X86_PAGE_SHIFT, pCmd->offsetPages + pCmd->numPages);
+
+                /*
+                 * We flatten the existing descriptors into a page array, overwrite the
+                 * pages specified in this command and then recompress the descriptor.
+                 */
+                /** @todo Optimize the GMR remap algorithm! */
+
+                /* Save the old page descriptors as an array of page frame numbers (address >> X86_PAGE_SHIFT) */
+                uint64_t *paNewPage64 = NULL;
                 if (pGMR->paDesc)
                 {
-                    uint32_t idxPage = 0;
-                    paNewPage64 = (uint64_t *)RTMemAllocZ(pGMR->cMaxPages * sizeof(uint64_t));
+                    STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2Modify);
+
+                    paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t));
                     AssertBreak(paNewPage64);
 
+                    uint32_t idxPage = 0;
                     for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
-                    {
                         for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++)
-                        {
-                            paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * PAGE_SIZE) >> PAGE_SHIFT;
-                        }
-                    }
-                    AssertBreak(idxPage == pGMR->cbTotal >> PAGE_SHIFT);
+                            paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * X86_PAGE_SIZE) >> X86_PAGE_SHIFT;
+                    AssertBreakStmt(idxPage == pGMR->cbTotal >> X86_PAGE_SHIFT, RTMemFree(paNewPage64));
                 }
 
                 /* Free the old GMR if present. */
@@ -2897,72 +3183,76 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     RTMemFree(pGMR->paDesc);
 
                 /* Allocate the maximum amount possible (everything non-continuous) */
-                pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->cMaxPages * sizeof(VMSVGAGMRDESCRIPTOR));
-                AssertBreak(pGMR->paDesc);
+                PVMSVGAGMRDESCRIPTOR paDescs;
+                pGMR->paDesc = paDescs = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cNewTotalPages * sizeof(VMSVGAGMRDESCRIPTOR));
+                AssertBreakStmt(paDescs, RTMemFree(paNewPage64));
 
                 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
                 {
                     /** @todo */
                     AssertFailed();
+                    pGMR->numDescriptors = 0;
                 }
                 else
                 {
-                    uint32_t            *pPage32 = (uint32_t *)(pCmd + 1);
-                    uint64_t            *pPage64 = (uint64_t *)(pCmd + 1);
-                    uint32_t             iDescriptor = 0;
-                    RTGCPHYS             GCPhys;
-                    bool                 fGCPhys64 = !!(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
+                    uint32_t  *paPages32 = (uint32_t *)(pCmd + 1);
+                    uint64_t  *paPages64 = (uint64_t *)(pCmd + 1);
+                    bool       fGCPhys64 = RT_BOOL(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
 
                     if (paNewPage64)
                     {
                         /* Overwrite the old page array with the new page values. */
-                        for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
-                        {
-                            if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
-                                paNewPage64[i] = pPage64[i - pCmd->offsetPages];
-                            else
-                                paNewPage64[i] = pPage32[i - pCmd->offsetPages];
-                        }
+                        if (fGCPhys64)
+                            for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
+                                paNewPage64[i] = paPages64[i - pCmd->offsetPages];
+                        else
+                            for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
+                                paNewPage64[i] = paPages32[i - pCmd->offsetPages];
+
                         /* Use the updated page array instead of the command data. */
                         fGCPhys64      = true;
-                        pPage64        = paNewPage64;
-                        pCmd->numPages = pGMR->cbTotal >> PAGE_SHIFT;
+                        paPages64      = paNewPage64;
+                        pCmd->numPages = cNewTotalPages;
                     }
 
+                    /* The first page. */
+                    /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be
+                     *        applied to paNewPage64. */
+                    RTGCPHYS GCPhys;
                     if (fGCPhys64)
-                        GCPhys = (pPage64[0] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL;    /* seeing rubbish in the top bits with certain linux guests*/
+                        GCPhys = (paPages64[0] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
                     else
-                        GCPhys = (RTGCPHYS)pPage32[0] << PAGE_SHIFT;
-
-                    pGMR->paDesc[0].GCPhys    = GCPhys;
-                    pGMR->paDesc[0].numPages  = 1;
-                    pGMR->cbTotal             = PAGE_SIZE;
+                        GCPhys = (RTGCPHYS)paPages32[0] << PAGE_SHIFT;
+                    paDescs[0].GCPhys    = GCPhys;
+                    paDescs[0].numPages  = 1;
 
+                    /* Subsequent pages. */
+                    uint32_t iDescriptor = 0;
                     for (uint32_t i = 1; i < pCmd->numPages; i++)
                     {
                         if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
-                            GCPhys = (pPage64[i] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL;    /* seeing rubbish in the top bits with certain linux guests*/
+                            GCPhys = (paPages64[i] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
                         else
-                            GCPhys = (RTGCPHYS)pPage32[i] << PAGE_SHIFT;
+                            GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT;
 
                         /* Continuous physical memory? */
-                        if (GCPhys == pGMR->paDesc[iDescriptor].GCPhys + pGMR->paDesc[iDescriptor].numPages * PAGE_SIZE)
+                        if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE)
                         {
-                            Assert(pGMR->paDesc[iDescriptor].numPages);
-                            pGMR->paDesc[iDescriptor].numPages++;
+                            Assert(paDescs[iDescriptor].numPages);
+                            paDescs[iDescriptor].numPages++;
                             LogFlow(("Page %x GCPhys=%RGp successor\n", i, GCPhys));
                         }
                         else
                         {
                             iDescriptor++;
-                            pGMR->paDesc[iDescriptor].GCPhys   = GCPhys;
-                            pGMR->paDesc[iDescriptor].numPages = 1;
-                            LogFlow(("Page %x GCPhys=%RGp\n", i, pGMR->paDesc[iDescriptor].GCPhys));
+                            paDescs[iDescriptor].GCPhys   = GCPhys;
+                            paDescs[iDescriptor].numPages = 1;
+                            LogFlow(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys));
                         }
-
-                        pGMR->cbTotal += PAGE_SIZE;
                     }
-                    LogFlow(("Nr of descriptors %x\n", iDescriptor + 1));
+
+                    pGMR->cbTotal = cNewTotalPages << X86_PAGE_SHIFT;
+                    LogFlow(("Nr of descriptors %x; cbTotal=%#x\n", iDescriptor + 1, cNewTotalPages));
                     pGMR->numDescriptors = iDescriptor + 1;
                 }
 
@@ -2970,7 +3260,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     RTMemFree(paNewPage64);
 
 #  ifdef DEBUG_GMR_ACCESS
-                VMR3ReqCallWait(PDMDevHlpGetVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaRegisterGMR, 2, pThis->pDevInsR3, pCmd->gmrId);
+                VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaRegisterGMR, 2, pThis->pDevInsR3, pCmd->gmrId);
 #  endif
                 break;
             }
@@ -2983,6 +3273,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
                 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.structSize));
                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineScreen);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d)\n", pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y));
                 if (pCmd->screen.flags & SVGA_SCREEN_HAS_ROOT)
@@ -3007,6 +3298,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
                 SVGAFifoCmdDestroyScreen *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDestroyScreen);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
                 break;
@@ -3016,6 +3308,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
                 SVGAFifoCmdDefineGMRFB *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmrFb);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_GMRFB gmr=%x offset=%x bytesPerLine=%x bpp=%d color depth=%d\n", pCmd->ptr.gmrId, pCmd->ptr.offset, pCmd->bytesPerLine, pCmd->format.s.bitsPerPixel, pCmd->format.s.colorDepth));
                 pSVGAState->GMRFB.ptr          = pCmd->ptr;
@@ -3029,6 +3322,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                 uint32_t width, height;
                 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitGmrFbToScreen);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n", pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
 
@@ -3074,6 +3368,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
                 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitScreentoGmrFb);
 
                 /* Note! This can fetch 3d render results as well!! */
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_BLIT_SCREEN_TO_GMRFB dest=(%d,%d) src id=%d (%d,%d)(%d,%d)\n", pCmd->destOrigin.x, pCmd->destOrigin.y, pCmd->srcScreenId, pCmd->srcRect.left, pCmd->srcRect.top, pCmd->srcRect.right, pCmd->srcRect.bottom));
@@ -3085,6 +3380,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
                 SVGAFifoCmdAnnotationFill *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdAnnotationFill);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_ANNOTATION_FILL red=%x green=%x blue=%x\n", pCmd->color.s.r, pCmd->color.s.g, pCmd->color.s.b));
                 pSVGAState->colorAnnotation = pCmd->color;
@@ -3095,6 +3391,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             {
                 SVGAFifoCmdAnnotationCopy *pCmd;
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
+                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdAnnotationCopy);
 
                 Log(("vmsvgaFIFOLoop: SVGA_CMD_ANNOTATION_COPY\n"));
                 AssertFailed();
@@ -3128,12 +3425,13 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t                cMipLevels;
                         SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDefine);
 
                         cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
                         rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0,
                                                    SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1));
 #  ifdef DEBUG_GMR_ACCESS
-                        VMR3ReqCallWait(PDMDevHlpGetVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaResetGMRHandlers, 1, pThis);
+                        VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaResetGMRHandlers, 1, pThis);
 #  endif
                         break;
                     }
@@ -3143,6 +3441,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t                   cMipLevels;
                         SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDefineV2);
 
                         cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
                         rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, pCmd->surfaceFlags, pCmd->format, pCmd->face,
@@ -3155,6 +3454,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDestroy);
                         rc = vmsvga3dSurfaceDestroy(pThis, pCmd->sid);
                         break;
                     }
@@ -3164,6 +3464,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t              cCopyBoxes;
                         SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceCopy);
 
                         cCopyBoxes = (pHdr->size - sizeof(pCmd)) / sizeof(SVGA3dCopyBox);
                         rc = vmsvga3dSurfaceCopy(pThis, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
@@ -3174,6 +3475,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt);
 
                         rc = vmsvga3dSurfaceStretchBlt(pThis, &pCmd->dest, &pCmd->boxDest, &pCmd->src, &pCmd->boxSrc, pCmd->mode);
                         break;
@@ -3184,11 +3486,12 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t             cCopyBoxes;
                         SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDma);
 
                         cCopyBoxes = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox);
-                        STAM_PROFILE_START(&pSVGAState->StatR3CmdSurfaceDMA, a);
+                        STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, a);
                         rc = vmsvga3dSurfaceDMA(pThis, pCmd->guest, pCmd->host, pCmd->transfer, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
-                        STAM_PROFILE_STOP(&pSVGAState->StatR3CmdSurfaceDMA, a);
+                        STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, a);
                         break;
                     }
 
@@ -3197,6 +3500,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t                      cRects;
                         SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceScreen);
 
                         cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGASignedRect);
                         rc = vmsvga3dSurfaceBlitToScreen(pThis, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage, pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1));
@@ -3207,6 +3511,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dContextDefine);
 
                         rc = vmsvga3dContextDefine(pThis, pCmd->cid);
                         break;
@@ -3216,6 +3521,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dContextDestroy);
 
                         rc = vmsvga3dContextDestroy(pThis, pCmd->cid);
                         break;
@@ -3225,6 +3531,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetTransform);
 
                         rc = vmsvga3dSetTransform(pThis, pCmd->cid, pCmd->type, pCmd->matrix);
                         break;
@@ -3234,6 +3541,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetZRange);
 
                         rc = vmsvga3dSetZRange(pThis, pCmd->cid, pCmd->zRange);
                         break;
@@ -3244,6 +3552,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t                 cRenderStates;
                         SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetRenderState);
 
                         cRenderStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRenderState);
                         rc = vmsvga3dSetRenderState(pThis, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1));
@@ -3254,6 +3563,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetRenderTarget);
 
                         rc = vmsvga3dSetRenderTarget(pThis, pCmd->cid, pCmd->type, pCmd->target);
                         break;
@@ -3264,6 +3574,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         uint32_t                  cTextureStates;
                         SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetTextureState);
 
                         cTextureStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dTextureState);
                         rc = vmsvga3dSetTextureState(pThis, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1));
@@ -3274,6 +3585,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetMaterial);
 
                         rc = vmsvga3dSetMaterial(pThis, pCmd->cid, pCmd->face, &pCmd->material);
                         break;
@@ -3283,6 +3595,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetLightData);
 
                         rc = vmsvga3dSetLightData(pThis, pCmd->cid, pCmd->index, &pCmd->data);
                         break;
@@ -3292,6 +3605,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetLightEnable);
 
                         rc = vmsvga3dSetLightEnabled(pThis, pCmd->cid, pCmd->index, pCmd->enabled);
                         break;
@@ -3301,6 +3615,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetViewPort);
 
                         rc = vmsvga3dSetViewPort(pThis, pCmd->cid, &pCmd->rect);
                         break;
@@ -3310,6 +3625,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetClipPlane);
 
                         rc = vmsvga3dSetClipPlane(pThis, pCmd->cid, pCmd->index, pCmd->plane);
                         break;
@@ -3319,8 +3635,9 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdClear  *pCmd = (SVGA3dCmdClear *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
-                        uint32_t         cRects;
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dClear);
 
+                        uint32_t         cRects;
                         cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRect);
                         rc = vmsvga3dCommandClear(pThis, pCmd->cid, pCmd->clearFlag, pCmd->color, pCmd->depth, pCmd->stencil, cRects, (SVGA3dRect *)(pCmd + 1));
                         break;
@@ -3331,13 +3648,16 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
-                        uint32_t          cRects;
+                        if ((unsigned)enmCmdId == SVGA_3D_CMD_PRESENT)
+                            STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dPresent);
+                        else
+                            STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dPresentReadBack);
 
-                        cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
+                        uint32_t cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
 
-                        STAM_PROFILE_START(&pSVGAState->StatR3CmdPresent, a);
+                        STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dPresentProf, a);
                         rc = vmsvga3dCommandPresent(pThis, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1));
-                        STAM_PROFILE_STOP(&pSVGAState->StatR3CmdPresent, a);
+                        STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dPresentProf, a);
                         break;
                     }
 
@@ -3345,9 +3665,9 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
-                        uint32_t               cbData;
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dShaderDefine);
 
-                        cbData = (pHdr->size - sizeof(*pCmd));
+                        uint32_t cbData = (pHdr->size - sizeof(*pCmd));
                         rc = vmsvga3dShaderDefine(pThis, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1));
                         break;
                     }
@@ -3356,6 +3676,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dShaderDestroy);
 
                         rc = vmsvga3dShaderDestroy(pThis, pCmd->cid, pCmd->shid, pCmd->type);
                         break;
@@ -3365,6 +3686,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetShader);
 
                         rc = vmsvga3dShaderSet(pThis, NULL, pCmd->cid, pCmd->type, pCmd->shid);
                         break;
@@ -3374,6 +3696,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetShaderConst);
 
                         uint32_t cRegisters = (pHdr->size - sizeof(*pCmd)) / sizeof(pCmd->values) + 1;
                         rc = vmsvga3dShaderSetConst(pThis, pCmd->cid, pCmd->reg, pCmd->type, pCmd->ctype, cRegisters, pCmd->values);
@@ -3384,9 +3707,9 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
-                        uint32_t                 cVertexDivisor;
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dDrawPrimitives);
 
-                        cVertexDivisor = (pHdr->size - sizeof(*pCmd) - sizeof(SVGA3dVertexDecl) * pCmd->numVertexDecls - sizeof(SVGA3dPrimitiveRange) * pCmd->numRanges);
+                        uint32_t cVertexDivisor = (pHdr->size - sizeof(*pCmd) - sizeof(SVGA3dVertexDecl) * pCmd->numVertexDecls - sizeof(SVGA3dPrimitiveRange) * pCmd->numRanges);
                         Assert(pCmd->numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES);
                         Assert(pCmd->numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS);
                         Assert(!cVertexDivisor || cVertexDivisor == pCmd->numVertexDecls);
@@ -3395,9 +3718,9 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                         SVGA3dPrimitiveRange *pNumRange      = (SVGA3dPrimitiveRange *) (&pVertexDecl[pCmd->numVertexDecls]);
                         SVGA3dVertexDivisor  *pVertexDivisor = (cVertexDivisor) ? (SVGA3dVertexDivisor *)(&pNumRange[pCmd->numRanges]) : NULL;
 
-                        STAM_PROFILE_START(&pSVGAState->StatR3CmdDrawPrimitive, a);
+                        STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, a);
                         rc = vmsvga3dDrawPrimitives(pThis, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges, pNumRange, cVertexDivisor, pVertexDivisor);
-                        STAM_PROFILE_STOP(&pSVGAState->StatR3CmdDrawPrimitive, a);
+                        STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, a);
                         break;
                     }
 
@@ -3405,6 +3728,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetScissorRect);
 
                         rc = vmsvga3dSetScissorRect(pThis, pCmd->cid, &pCmd->rect);
                         break;
@@ -3414,6 +3738,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dBeginQuery);
 
                         rc = vmsvga3dQueryBegin(pThis, pCmd->cid, pCmd->type);
                         break;
@@ -3423,6 +3748,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dEndQuery);
 
                         rc = vmsvga3dQueryEnd(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
                         break;
@@ -3432,6 +3758,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dWaitForQuery);
 
                         rc = vmsvga3dQueryWait(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
                         break;
@@ -3441,19 +3768,24 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     {
                         SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)(pHdr + 1);
                         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dGenerateMipmaps);
 
                         rc = vmsvga3dGenerateMipmaps(pThis, pCmd->sid, pCmd->filter);
                         break;
                     }
 
                     case SVGA_3D_CMD_ACTIVATE_SURFACE:
+                        /* context id + surface id? */
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dActivateSurface);
+                        break;
                     case SVGA_3D_CMD_DEACTIVATE_SURFACE:
                         /* context id + surface id? */
+                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dDeactivateSurface);
                         break;
 
                     default:
                         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
-                        AssertFailed();
+                        AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
                         break;
                     }
                 }
@@ -3461,7 +3793,7 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
 # endif // VBOX_WITH_VMSVGA3D
                 {
                     STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
-                    AssertFailed();
+                    AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
                 }
             }
 
@@ -3485,7 +3817,8 @@ static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             if (   u32IrqStatus
                 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
             {
-                PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
+                int rc2 = PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
+                AssertRC(rc2);
 
                 /* FIFO progress might trigger an interrupt. */
                 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
@@ -3533,11 +3866,12 @@ void vmsvgaGMRFree(PVGASTATE pThis, uint32_t idGMR)
     PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
 
     /* Free the old descriptor if present. */
-    if (pSVGAState->aGMR[idGMR].numDescriptors)
+    PGMR pGMR = &pSVGAState->aGMR[idGMR];
+    if (   pGMR->numDescriptors
+        || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */)
     {
-        PGMR pGMR = &pSVGAState->aGMR[idGMR];
 # ifdef DEBUG_GMR_ACCESS
-        VMR3ReqCallWait(PDMDevHlpGetVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaDeregisterGMR, 2, pThis->pDevInsR3, idGMR);
+        VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaDeregisterGMR, 2, pThis->pDevInsR3, idGMR);
 # endif
 
         Assert(pGMR->paDesc);
@@ -3547,7 +3881,8 @@ void vmsvgaGMRFree(PVGASTATE pThis, uint32_t idGMR)
         pGMR->cbTotal        = 0;
         pGMR->cMaxPages      = 0;
     }
-    Assert(!pSVGAState->aGMR[idGMR].cbTotal);
+    Assert(!pGMR->cMaxPages);
+    Assert(!pGMR->cbTotal);
 }
 
 /**
@@ -4006,9 +4341,8 @@ int vmsvgaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint3
 
         if (pGMR->numDescriptors)
         {
-            /* Allocate the maximum amount possible (everything non-continuous) */
             Assert(pGMR->cMaxPages || pGMR->cbTotal);
-            pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ((pGMR->cMaxPages) ? pGMR->cMaxPages : (pGMR->cbTotal >> PAGE_SHIFT) * sizeof(VMSVGAGMRDESCRIPTOR));
+            pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
             AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
 
             for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
@@ -4360,9 +4694,146 @@ int vmsvgaInit(PPDMDEVINS pDevIns)
     /*
      * Statistics.
      */
-    STAM_REG(pVM, &pSVGAState->StatR3CmdPresent,        STAMTYPE_PROFILE, "/Devices/VMSVGA/3d/Cmd/Present",  STAMUNIT_TICKS_PER_CALL, "Profiling of Present.");
-    STAM_REG(pVM, &pSVGAState->StatR3CmdDrawPrimitive,  STAMTYPE_PROFILE, "/Devices/VMSVGA/3d/Cmd/DrawPrimitive",  STAMUNIT_TICKS_PER_CALL, "Profiling of DrawPrimitive.");
-    STAM_REG(pVM, &pSVGAState->StatR3CmdSurfaceDMA,     STAMTYPE_PROFILE, "/Devices/VMSVGA/3d/Cmd/SurfaceDMA",  STAMUNIT_TICKS_PER_CALL, "Profiling of SurfaceDMA.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dActivateSurface,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dActivateSurface",    STAMUNIT_OCCURENCES, "SVGA_3D_CMD_ACTIVATE_SURFACE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dBeginQuery,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dBeginQuery",         STAMUNIT_OCCURENCES, "SVGA_3D_CMD_BEGIN_QUERY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dClear,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dClear",              STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CLEAR");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dContextDefine,        STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dContextDefine",      STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CONTEXT_DEFINE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dContextDestroy,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dContextDestroy",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CONTEXT_DESTROY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dDeactivateSurface,    STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dDeactivateSurface",  STAMUNIT_OCCURENCES, "SVGA_3D_CMD_DEACTIVATE_SURFACE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dDrawPrimitives,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dDrawPrimitives",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_DRAW_PRIMITIVES");
+    STAM_REG(pVM,     &pSVGAState->StatR3Cmd3dDrawPrimitivesProf,   STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dDrawPrimitivesProf", STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dEndQuery,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dEndQuery",           STAMUNIT_OCCURENCES, "SVGA_3D_CMD_END_QUERY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dGenerateMipmaps,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dGenerateMipmaps",    STAMUNIT_OCCURENCES, "SVGA_3D_CMD_GENERATE_MIPMAPS");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dPresent,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dPresent",            STAMUNIT_OCCURENCES, "SVGA_3D_CMD_PRESENT");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dPresentReadBack,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dPresentReadBack",    STAMUNIT_OCCURENCES, "SVGA_3D_CMD_PRESENT_READBACK");
+    STAM_REG(pVM,     &pSVGAState->StatR3Cmd3dPresentProf,          STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dPresentProfBoth",    STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetClipPlane,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetClipPlane",       STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETCLIPPLANE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetLightData,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetLightData",       STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETLIGHTDATA");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetLightEnable,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetLightEnable",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETLIGHTENABLE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetMaterial,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetMaterial",        STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETMATERIAL");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetRenderState,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetRenderState",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETRENDERSTATE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetRenderTarget,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetRenderTarget",    STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETRENDERTARGET");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetScissorRect,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetScissorRect",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETSCISSORRECT");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetShader,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetShader",          STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SET_SHADER");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetShaderConst,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetShaderConst",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SET_SHADER_CONST");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetTextureState,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetTextureState",    STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETTEXTURESTATE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetTransform,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetTransform",       STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETTRANSFORM");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetViewPort,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetViewPort",        STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETVIEWPORT");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetZRange,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetZRange",          STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETZRANGE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dShaderDefine,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dShaderDefine",       STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SHADER_DEFINE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dShaderDestroy,        STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dShaderDestroy",      STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SHADER_DESTROY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceCopy,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceCopy",        STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_COPY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDefine,        STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDefine",      STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DEFINE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDefineV2,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDefineV2",    STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DEFINE_V2");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDestroy,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDestroy",     STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DESTROY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDma,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDma",         STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DMA");
+    STAM_REG(pVM,     &pSVGAState->StatR3Cmd3dSurfaceDmaProf,       STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dSurfaceDmaProf",     STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceScreen,        STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceScreen",      STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_SCREEN");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceStretchBlt,    STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceStretchBlt",  STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_STRETCHBLT");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dWaitForQuery,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dWaitForQuery",       STAMUNIT_OCCURENCES, "SVGA_3D_CMD_WAIT_FOR_QUERY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdAnnotationCopy,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/AnnotationCopy",       STAMUNIT_OCCURENCES, "SVGA_CMD_ANNOTATION_COPY");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdAnnotationFill,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/AnnotationFill",       STAMUNIT_OCCURENCES, "SVGA_CMD_ANNOTATION_FILL");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdBlitGmrFbToScreen,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/BlitGmrFbToScreen",    STAMUNIT_OCCURENCES, "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdBlitScreentoGmrFb,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/BlitScreentoGmrFb",    STAMUNIT_OCCURENCES, "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineAlphaCursor,      STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineAlphaCursor",    STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_ALPHA_CURSOR");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineCursor,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineCursor",         STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_CURSOR");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2",           STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_GMR2");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2Free,         STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2/Free",      STAMUNIT_OCCURENCES, "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2Modify,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2/Modify",    STAMUNIT_OCCURENCES, "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmrFb,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmrFb",          STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_GMRFB");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineScreen,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineScreen",         STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_SCREEN");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDestroyScreen,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DestroyScreen",        STAMUNIT_OCCURENCES, "SVGA_CMD_DESTROY_SCREEN");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdEscape,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Escape",               STAMUNIT_OCCURENCES, "SVGA_CMD_ESCAPE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdFence,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Fence",                STAMUNIT_OCCURENCES, "SVGA_CMD_FENCE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdInvalidCmd,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/InvalidCmd",           STAMUNIT_OCCURENCES, "SVGA_CMD_INVALID_CMD");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdRemapGmr2,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/RemapGmr2",            STAMUNIT_OCCURENCES, "SVGA_CMD_REMAP_GMR2.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdRemapGmr2Modify,        STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/RemapGmr2/Modify",     STAMUNIT_OCCURENCES, "Number of SVGA_CMD_REMAP_GMR2 commands that modifies rather than complete the definition of a GMR.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdUpdate,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Update",               STAMUNIT_OCCURENCES, "SVGA_CMD_UPATE");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3CmdUpdateVerbose,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/UpdateVerbose",        STAMUNIT_OCCURENCES, "SVGA_CMD_UPDATE_VERBOSE");
+
+    STAM_REL_REG(pVM, &pSVGAState->StatR3RegConfigDoneWr,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ConfigDoneWrite",            STAMUNIT_OCCURENCES, "SVGA_REG_CONFIG_DONE writes");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWr,        STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite",         STAMUNIT_OCCURENCES, "SVGA_REG_GMR_DESCRIPTOR writes");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWrErrors,  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite/Errors",  STAMUNIT_OCCURENCES, "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
+    STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWrFree,    STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite/Free",    STAMUNIT_OCCURENCES, "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegBitsPerPixelWr,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BitsPerPixelWrite",          STAMUNIT_OCCURENCES, "SVGA_REG_BITS_PER_PIXEL writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegBusyWr,                   STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BusyWrite",                  STAMUNIT_OCCURENCES, "SVGA_REG_BUSY writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegCursorXxxxWr,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CursorXxxxWrite",            STAMUNIT_OCCURENCES, "SVGA_REG_CURSOR_XXXX writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDepthWr,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DepthWrite",                 STAMUNIT_OCCURENCES, "SVGA_REG_DEPTH writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayHeightWr,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayHeightWrite",         STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_HEIGHT writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIdWr,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIdWrite",             STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_ID writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIsPrimaryWr,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIsPrimaryWrite",      STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionXWr,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionXWrite",      STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_X writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionYWr,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionYWrite",      STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_Y writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayWidthWr,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayWidthWrite",          STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_WIDTH writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegEnableWr,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/EnableWrite",                STAMUNIT_OCCURENCES, "SVGA_REG_ENABLE writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGmrIdWr,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrIdWrite",                 STAMUNIT_OCCURENCES, "SVGA_REG_GMR_ID writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGuestIdWr,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GuestIdWrite",               STAMUNIT_OCCURENCES, "SVGA_REG_GUEST_ID writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegHeightWr,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HeightWrite",                STAMUNIT_OCCURENCES, "SVGA_REG_HEIGHT writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegIdWr,                     STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IdWrite",                    STAMUNIT_OCCURENCES, "SVGA_REG_ID writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegIrqMaskWr,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IrqMaskWrite",               STAMUNIT_OCCURENCES, "SVGA_REG_IRQMASK writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegNumDisplaysWr,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumDisplaysWrite",           STAMUNIT_OCCURENCES, "SVGA_REG_NUM_DISPLAYS writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegNumGuestDisplaysWr,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumGuestDisplaysWrite",      STAMUNIT_OCCURENCES, "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegPaletteWr,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PaletteWrite",               STAMUNIT_OCCURENCES, "SVGA_PALETTE_XXXX writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegPitchLockWr,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PitchLockWrite",             STAMUNIT_OCCURENCES, "SVGA_REG_PITCHLOCK writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegPseudoColorWr,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PseudoColorWrite",           STAMUNIT_OCCURENCES, "SVGA_REG_PSEUDOCOLOR writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegReadOnlyWr,               STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ReadOnlyWrite",              STAMUNIT_OCCURENCES, "Read-only SVGA_REG_XXXX writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegScratchWr,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchWrite",               STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH_XXXX writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegSyncWr,                   STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/SyncWrite",                  STAMUNIT_OCCURENCES, "SVGA_REG_SYNC writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegTopWr,                    STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TopWrite",                   STAMUNIT_OCCURENCES, "SVGA_REG_TOP writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegTracesWr,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TracesWrite",                STAMUNIT_OCCURENCES, "SVGA_REG_TRACES writes.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegUnknownWr,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/UnknownWrite",               STAMUNIT_OCCURENCES, "Writes to unknown register.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegWidthWr,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WidthWrite",                 STAMUNIT_OCCURENCES, "SVGA_REG_WIDTH writes.");
+
+    STAM_REL_REG(pVM, &pThis->svga.StatRegBitsPerPixelRd,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BitsPerPixelRead",           STAMUNIT_OCCURENCES, "SVGA_REG_BITS_PER_PIXEL reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegBlueMaskRd,               STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BlueMaskRead",               STAMUNIT_OCCURENCES, "SVGA_REG_BLUE_MASK reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegBusyRd,                   STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BusyRead",                   STAMUNIT_OCCURENCES, "SVGA_REG_BUSY reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegBytesPerLineRd,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BytesPerLineRead",           STAMUNIT_OCCURENCES, "SVGA_REG_BYTES_PER_LINE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegCapabilitesRd,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CapabilitesRead",            STAMUNIT_OCCURENCES, "SVGA_REG_CAPABILITIES reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegConfigDoneRd,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ConfigDoneRead",             STAMUNIT_OCCURENCES, "SVGA_REG_CONFIG_DONE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegCursorXxxxRd,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CursorXxxxRead",             STAMUNIT_OCCURENCES, "SVGA_REG_CURSOR_XXXX reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDepthRd,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DepthRead",                  STAMUNIT_OCCURENCES, "SVGA_REG_DEPTH reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayHeightRd,          STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayHeightRead",          STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_HEIGHT reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIdRd,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIdRead",              STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_ID reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIsPrimaryRd,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIsPrimaryRead",       STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionXRd,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionXRead",       STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_X reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionYRd,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionYRead",       STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_Y reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayWidthRd,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayWidthRead",           STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_WIDTH reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegEnableRd,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/EnableRead",                 STAMUNIT_OCCURENCES, "SVGA_REG_ENABLE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegFbOffsetRd,               STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbOffsetRead",               STAMUNIT_OCCURENCES, "SVGA_REG_FB_OFFSET reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegFbSizeRd,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbSizeRead",                 STAMUNIT_OCCURENCES, "SVGA_REG_FB_SIZE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegFbStartRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbStartRead",                STAMUNIT_OCCURENCES, "SVGA_REG_FB_START reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGmrIdRd,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrIdRead",                  STAMUNIT_OCCURENCES, "SVGA_REG_GMR_ID reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGmrMaxDescriptorLengthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrMaxDescriptorLengthRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGmrMaxIdsRd,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrMaxIdsRead",              STAMUNIT_OCCURENCES, "SVGA_REG_GMR_MAX_IDS reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGmrsMaxPagesRd,           STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrsMaxPagesRead",           STAMUNIT_OCCURENCES, "SVGA_REG_GMRS_MAX_PAGES reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGreenMaskRd,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GreenMaskRead",              STAMUNIT_OCCURENCES, "SVGA_REG_GREEN_MASK reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegGuestIdRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GuestIdRead",                STAMUNIT_OCCURENCES, "SVGA_REG_GUEST_ID reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegHeightRd,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HeightRead",                 STAMUNIT_OCCURENCES, "SVGA_REG_HEIGHT reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegHostBitsPerPixelRd,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HostBitsPerPixelRead",       STAMUNIT_OCCURENCES, "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegIdRd,                     STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IdRead",                     STAMUNIT_OCCURENCES, "SVGA_REG_ID reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegIrqMaskRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IrqMaskRead",                STAMUNIT_OCCURENCES, "SVGA_REG_IRQ_MASK reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegMaxHeightRd,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MaxHeightRead",              STAMUNIT_OCCURENCES, "SVGA_REG_MAX_HEIGHT reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegMaxWidthRd,               STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MaxWidthRead",               STAMUNIT_OCCURENCES, "SVGA_REG_MAX_WIDTH reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegMemorySizeRd,             STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemorySizeRead",             STAMUNIT_OCCURENCES, "SVGA_REG_MEMORY_SIZE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegMemRegsRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemRegsRead",                STAMUNIT_OCCURENCES, "SVGA_REG_MEM_REGS reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegMemSizeRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemSizeRead",                STAMUNIT_OCCURENCES, "SVGA_REG_MEM_SIZE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegMemStartRd,               STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemStartRead",               STAMUNIT_OCCURENCES, "SVGA_REG_MEM_START reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegNumDisplaysRd,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumDisplaysRead",            STAMUNIT_OCCURENCES, "SVGA_REG_NUM_DISPLAYS reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegNumGuestDisplaysRd,       STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumGuestDisplaysRead",       STAMUNIT_OCCURENCES, "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegPaletteRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PaletteRead",                STAMUNIT_OCCURENCES, "SVGA_REG_PLAETTE_XXXX reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegPitchLockRd,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PitchLockRead",              STAMUNIT_OCCURENCES, "SVGA_REG_PITCHLOCK reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegPsuedoColorRd,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PsuedoColorRead",            STAMUNIT_OCCURENCES, "SVGA_REG_PSEUDOCOLOR reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegRedMaskRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/RedMaskRead",                STAMUNIT_OCCURENCES, "SVGA_REG_RED_MASK reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegScratchRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchRead",                STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegScratchSizeRd,            STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchSizeRead",            STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH_SIZE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegSyncRd,                   STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/SyncRead",                   STAMUNIT_OCCURENCES, "SVGA_REG_SYNC reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegTopRd,                    STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TopRead",                    STAMUNIT_OCCURENCES, "SVGA_REG_TOP reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegTracesRd,                 STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TracesRead",                 STAMUNIT_OCCURENCES, "SVGA_REG_TRACES reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegUnknownRd,                STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/UnknownRead",                STAMUNIT_OCCURENCES, "SVGA_REG_UNKNOWN reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegVramSizeRd,               STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/VramSizeRead",               STAMUNIT_OCCURENCES, "SVGA_REG_VRAM_SIZE reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegWidthRd,                  STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WidthRead",                  STAMUNIT_OCCURENCES, "SVGA_REG_WIDTH reads.");
+    STAM_REL_REG(pVM, &pThis->svga.StatRegWriteOnlyRd,              STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WriteOnlyRead",              STAMUNIT_OCCURENCES, "Write-only SVGA_REG_XXXX reads.");
+
     STAM_REL_REG(pVM, &pSVGAState->StatBusyDelayEmts,   STAMTYPE_PROFILE, "/Devices/VMSVGA/EmtDelayOnBusyFifo",  STAMUNIT_TICKS_PER_CALL, "Time we've delayed EMTs because of busy FIFO thread.");
     STAM_REL_REG(pVM, &pSVGAState->StatFifoCommands,    STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoCommands",  STAMUNIT_OCCURENCES, "FIFO command counter.");
     STAM_REL_REG(pVM, &pSVGAState->StatFifoErrors,      STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoErrors",  STAMUNIT_OCCURENCES, "FIFO error counter.");
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.h b/src/VBox/Devices/Graphics/DevVGA-SVGA.h
index 18351a7..ef25c67 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA.h
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.h
@@ -28,6 +28,8 @@
 #define VMSVGA_MAX_GMR_PAGES            0x100000
 /** Maximum nr of GMR ids. */
 #define VMSVGA_MAX_GMR_IDS              0x100
+/** Maximum number of GMR descriptors.  */
+#define VMSVGA_MAX_GMR_DESC_LOOP_COUNT  VMSVGA_MAX_GMR_PAGES
 
 #define VMSVGA_VAL_UNINITIALIZED        (unsigned)-1
 
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m
index 5b1b557..4d493f8 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m
@@ -41,8 +41,8 @@
  * Define this to experiment with using NSOpenGLView instead
  * of NSView.  There are transparency issues with the former,
  * so for the time being we're using the latter.  */
-#if 0
-#define USE_NSOPENGLVIEW
+#if 0 || DOXYGEN_RUNNING
+# define USE_NSOPENGLVIEW
 #endif
 
 /**@def FLOAT_FMT_STR
@@ -698,8 +698,14 @@ VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaServiceRunLoop(void)
 /**
  * Document me later.
  *
+ * @param   ppView
+ * @param   ppCtx
  * @param   pParentView     The parent view if this is a context we'll be
  *                          presenting to.
+ * @param   cx
+ * @param   cy
+ * @param   pSharedCtx
+ * @param   fOtherProfile
  */
 VMSVGA3DCOCOA_DECL(bool) vmsvga3dCocoaCreateViewAndContext(NativeNSViewRef *ppView, NativeNSOpenGLContextRef *ppCtx,
                                                            NativeNSViewRef pParentView, uint32_t cx, uint32_t cy,
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
index fd605e0..46df775 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
@@ -555,6 +555,7 @@ typedef struct VMSVGA3DSURFACE
     /** AVL tree containing VMSVGA3DSHAREDSURFACE structures. */
     AVLU32TREE              pSharedObjectTree;
     bool                    fStencilAsTexture;
+    uint32_t                fu32ActualUsageFlags;
 #endif
 } VMSVGA3DSURFACE;
 /** Pointer to a 3d surface. */
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
index 94ca2e0..b7d1311 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
@@ -172,7 +172,6 @@ extern "C" int ExplicitlyLoadVBoxSVGA3D(bool fResolveAllImports, PRTERRINFO pErr
  *
  * @returns true if supported, false if not.
  * @param   pState              The VMSVGA3d state.
- * @param   fActualGLVersion    The actual OpenGL version we're working against.
  * @param   rsMinGLVersion      The OpenGL version that introduced this feature
  *                              into the core.
  * @param   pszWantedExtension  The name of the OpenGL extension we want padded
@@ -1847,6 +1846,7 @@ void vmsvga3dBackSurfaceDestroy(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface
         AssertFailed(); /** @todo destroy SVGA3D_SURFACE_CUBEMAP */
         break;
 
+    case SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER:
     case SVGA3D_SURFACE_HINT_INDEXBUFFER:
     case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
         if (pSurface->oglId.buffer != OPENGL_INVALID_ID)
@@ -2455,6 +2455,7 @@ int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVG
         AssertFailed(); /** @todo DMA SVGA3D_SURFACE_HINT_DEPTHSTENCIL */
         break;
 
+    case SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER:
     case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
     case SVGA3D_SURFACE_HINT_INDEXBUFFER:
     {
@@ -2480,7 +2481,9 @@ int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVG
                 if (RT_LIKELY(   offDst + pBox->w * pSurface->cbBlock  + (pBox->h - 1) * pMipLevel->cbSurfacePitch
                               <= pMipLevel->cbSurface))
                 {
-                    Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n", (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" : "index",
+                    Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n",
+                         (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" :
+                           (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_INDEXBUFFER ? "index" : "buffer",
                          pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h));
 
                     rc = vmsvgaGMRTransfer(pThis,
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
index e432a04..f6cc17b 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
@@ -1102,14 +1102,21 @@ void vmsvga3dBackSurfaceDestroy(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface
         AssertFailed(); /** @todo */
         break;
 
+    case SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER:
     case SVGA3D_SURFACE_HINT_INDEXBUFFER:
-        if (pSurface->u.pIndexBuffer)
-            pSurface->u.pIndexBuffer->Release();
-        break;
-
     case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
-        if (pSurface->u.pVertexBuffer)
-            pSurface->u.pVertexBuffer->Release();
+        if (pSurface->fu32ActualUsageFlags == SVGA3D_SURFACE_HINT_VERTEXBUFFER)
+        {
+            if (pSurface->u.pVertexBuffer)
+                pSurface->u.pVertexBuffer->Release();
+        }
+        else if (pSurface->fu32ActualUsageFlags == SVGA3D_SURFACE_HINT_INDEXBUFFER)
+        {
+            if (pSurface->u.pIndexBuffer)
+                pSurface->u.pIndexBuffer->Release();
+        }
+        else
+            AssertMsg(pSurface->u.pVertexBuffer == NULL, ("fu32ActualUsageFlags %x\n", pSurface->fu32ActualUsageFlags));
         break;
 
     case SVGA3D_SURFACE_HINT_TEXTURE:
@@ -1929,8 +1936,9 @@ int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVG
         break;
     }
 
+    case SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER:
     case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
-        fVertex = true;
+        fVertex = RT_BOOL(pSurface->fu32ActualUsageFlags & SVGA3D_SURFACE_HINT_VERTEXBUFFER);
         /* no break */
 
     case SVGA3D_SURFACE_HINT_INDEXBUFFER:
@@ -1972,7 +1980,7 @@ int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVG
     }
 
     default:
-        AssertFailed();
+        AssertMsgFailed(("Unsupported surface hint 0x%08X\n", pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK));
         break;
     }
 
@@ -4832,6 +4840,7 @@ int vmsvga3dDrawPrimitivesProcessVertexDecls(PVMSVGA3DSTATE pState, PVMSVGA3DCON
                 pVertexSurface->fDirty = false;
             }
             pVertexSurface->flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
+            pVertexSurface->fu32ActualUsageFlags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
         }
         else
             Assert(pVertexSurface->fDirty == false);
@@ -5037,6 +5046,7 @@ int vmsvga3dDrawPrimitives(PVGASTATE pThis, uint32_t cid, uint32_t numVertexDecl
                     pIndexSurface->fDirty = false;
                 }
                 pIndexSurface->flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
+                pIndexSurface->fu32ActualUsageFlags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
             }
             else
                 Assert(pIndexSurface->fDirty == false);
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
index c6ef690..22da1ee 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
@@ -216,6 +216,7 @@ int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags,
         pSurface->fUsageD3D |= D3DUSAGE_WRITEONLY;
     if (surfaceFlags & SVGA3D_SURFACE_AUTOGENMIPMAPS)
         pSurface->fUsageD3D |= D3DUSAGE_AUTOGENMIPMAP;
+    pSurface->fu32ActualUsageFlags = 0;
 #else
     vmsvga3dSurfaceFormat2OGL(pSurface, format);
 #endif
@@ -340,7 +341,11 @@ int vmsvga3dSurfaceDestroy(PVGASTATE pThis, uint32_t sid)
  *
  * @returns VBox status code (currently ignored).
  * @param   pThis               The VGA device instance data.
- * @param   sid                 The ID of the surface to destroy.
+ * @param   pDstSfcImg
+ * @param   pDstBox
+ * @param   pSrcSfcImg
+ * @param   pSrcBox
+ * @param   enmMode
  */
 int vmsvga3dSurfaceStretchBlt(PVGASTATE pThis, SVGA3dSurfaceImageId const *pDstSfcImg, SVGA3dBox const *pDstBox,
                               SVGA3dSurfaceImageId const *pSrcSfcImg, SVGA3dBox const *pSrcBox, SVGA3dStretchBltMode enmMode)
@@ -442,15 +447,15 @@ int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceIma
     PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
     AssertReturn(pSurface && pSurface->id == sid, VERR_INVALID_PARAMETER);
 
-    AssertMsg(host.face == 0, ("host.face=%#x\n", host.face));
-    AssertReturn(pSurface->faces[0].numMipLevels > host.mipmap, VERR_INVALID_PARAMETER);
-    PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->pMipmapLevels[host.mipmap];
-
     if (pSurface->flags & SVGA3D_SURFACE_HINT_TEXTURE)
         Log(("vmsvga3dSurfaceDMA TEXTURE guestptr gmr=%x offset=%x pitch=%x host sid=%x face=%d mipmap=%d transfer=%s cCopyBoxes=%d\n", guest.ptr.gmrId, guest.ptr.offset, guest.pitch, host.sid, host.face, host.mipmap, (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", cCopyBoxes));
     else
         Log(("vmsvga3dSurfaceDMA guestptr gmr=%x offset=%x pitch=%x host sid=%x face=%d mipmap=%d transfer=%s cCopyBoxes=%d\n", guest.ptr.gmrId, guest.ptr.offset, guest.pitch, host.sid, host.face, host.mipmap, (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", cCopyBoxes));
 
+    AssertMsg(host.face == 0, ("host.face=%#x\n", host.face));
+    AssertMsgReturn(pSurface->faces[0].numMipLevels > host.mipmap, ("numMipLevels %d, host.mipmap %d", pSurface->faces[0].numMipLevels, host.mipmap), VERR_INVALID_PARAMETER);
+    PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->pMipmapLevels[host.mipmap];
+
     if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
     {
         /*
diff --git a/src/VBox/Devices/Graphics/DevVGA.cpp b/src/VBox/Devices/Graphics/DevVGA.cpp
index bbbe241..530f620 100644
--- a/src/VBox/Devices/Graphics/DevVGA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA.cpp
@@ -2090,9 +2090,10 @@ static void vga_get_resolution(PVGASTATE pThis, int *pwidth, int *pheight)
  * @param   pThis   Pointer to the vga state.
  * @param   cx      The width.
  * @param   cy      The height.
+ * @param   pDrv    The display connector.
  */
 static int vga_resize_graphic(PVGASTATE pThis, int cx, int cy,
-                PDMIDISPLAYCONNECTOR *pDrv)
+                              PDMIDISPLAYCONNECTOR *pDrv)
 {
     const unsigned cBits = pThis->get_bpp(pThis);
 
@@ -3865,7 +3866,7 @@ static int vbeParseBitmap(PVGASTATE pThis)
  *
  * @returns VBox status code.
  *
- * @param   cbDepth     Logo depth.
+ * @param   cBits       Logo depth.
  * @param   xLogo       Logo X position.
  * @param   yLogo       Logo Y position.
  * @param   cxLogo      Logo width.
@@ -4610,6 +4611,9 @@ static DECLCALLBACK(int) vgaPortQueryStatusLed(PPDMILEDPORTS pInterface, unsigne
  * request from the guest os, but may also happen as the result of a reset.
  *
  * @param   pInterface          Pointer to this interface.
+ * @param   bpp                 Bits per pixel.
+ * @param   pvVRAM              VRAM.
+ * @param   cbLine              Number of bytes per line.
  * @param   cx                  New display width.
  * @param   cy                  New display height
  * @thread  The emulation thread.
@@ -4767,6 +4771,7 @@ DECLCALLBACK(int) vgaUpdateDisplayAll(PVGASTATE pThis, bool fFailOnResize)
  * Update the entire display.
  *
  * @param   pInterface          Pointer to this interface.
+ * @param   fFailOnResize       Fail on resize.
  * @see     PDMIKEYBOARDPORT::pfnUpdateDisplayAll() for details.
  */
 static DECLCALLBACK(int) vgaPortUpdateDisplayAll(PPDMIDISPLAYPORT pInterface, bool fFailOnResize)
@@ -5584,7 +5589,7 @@ static DECLCALLBACK(int) vgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 
 
 /**
- * @copydoc FNSSMDEVSAVEEXEC
+ * @copydoc FNSSMDEVLOADEXEC
  */
 static DECLCALLBACK(int) vgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 {
@@ -6971,7 +6976,7 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
             RTTIME T;
             RTTimeLocalExplode(&T, &Now);
             bool fSuppressNewYearSplash = false;
-            rc = CFGMR3QueryBoolDef(pCfg, "SuppressNewYearSplash", &fSuppressNewYearSplash, false);
+            rc = CFGMR3QueryBoolDef(pCfg, "SuppressNewYearSplash", &fSuppressNewYearSplash, true);
             if (   !fSuppressNewYearSplash
                 && (T.u16YearDay > 353 || T.u16YearDay < 10))
             {
diff --git a/src/VBox/Devices/Graphics/DevVGA.h b/src/VBox/Devices/Graphics/DevVGA.h
index ed969c7..87176a8 100644
--- a/src/VBox/Devices/Graphics/DevVGA.h
+++ b/src/VBox/Devices/Graphics/DevVGA.h
@@ -213,6 +213,13 @@ typedef struct _VBOX_VHWA_PENDINGCMD
 
 #ifdef VBOX_WITH_VMSVGA
 
+#ifdef DEBUG
+/* Enable to log FIFO register accesses. */
+//# define DEBUG_FIFO_ACCESS
+/* Enable to log GMR page accesses. */
+//# define DEBUG_GMR_ACCESS
+#endif
+
 #define VMSVGA_FIFO_EXTCMD_NONE                         0
 #define VMSVGA_FIFO_EXTCMD_TERMINATE                    1
 #define VMSVGA_FIFO_EXTCMD_SAVESTATE                    2
@@ -349,6 +356,85 @@ typedef struct VMSVGAState
     /** FIFO debug access handler type handle. */
     PGMPHYSHANDLERTYPE          hFifoAccessHandlerType;
 # endif
+
+    STAMCOUNTER                 StatRegBitsPerPixelWr;
+    STAMCOUNTER                 StatRegBusyWr;
+    STAMCOUNTER                 StatRegCursorXxxxWr;
+    STAMCOUNTER                 StatRegDepthWr;
+    STAMCOUNTER                 StatRegDisplayHeightWr;
+    STAMCOUNTER                 StatRegDisplayIdWr;
+    STAMCOUNTER                 StatRegDisplayIsPrimaryWr;
+    STAMCOUNTER                 StatRegDisplayPositionXWr;
+    STAMCOUNTER                 StatRegDisplayPositionYWr;
+    STAMCOUNTER                 StatRegDisplayWidthWr;
+    STAMCOUNTER                 StatRegEnableWr;
+    STAMCOUNTER                 StatRegGmrIdWr;
+    STAMCOUNTER                 StatRegGuestIdWr;
+    STAMCOUNTER                 StatRegHeightWr;
+    STAMCOUNTER                 StatRegIdWr;
+    STAMCOUNTER                 StatRegIrqMaskWr;
+    STAMCOUNTER                 StatRegNumDisplaysWr;
+    STAMCOUNTER                 StatRegNumGuestDisplaysWr;
+    STAMCOUNTER                 StatRegPaletteWr;
+    STAMCOUNTER                 StatRegPitchLockWr;
+    STAMCOUNTER                 StatRegPseudoColorWr;
+    STAMCOUNTER                 StatRegReadOnlyWr;
+    STAMCOUNTER                 StatRegScratchWr;
+    STAMCOUNTER                 StatRegSyncWr;
+    STAMCOUNTER                 StatRegTopWr;
+    STAMCOUNTER                 StatRegTracesWr;
+    STAMCOUNTER                 StatRegUnknownWr;
+    STAMCOUNTER                 StatRegWidthWr;
+
+    STAMCOUNTER                 StatRegBitsPerPixelRd;
+    STAMCOUNTER                 StatRegBlueMaskRd;
+    STAMCOUNTER                 StatRegBusyRd;
+    STAMCOUNTER                 StatRegBytesPerLineRd;
+    STAMCOUNTER                 StatRegCapabilitesRd;
+    STAMCOUNTER                 StatRegConfigDoneRd;
+    STAMCOUNTER                 StatRegCursorXxxxRd;
+    STAMCOUNTER                 StatRegDepthRd;
+    STAMCOUNTER                 StatRegDisplayHeightRd;
+    STAMCOUNTER                 StatRegDisplayIdRd;
+    STAMCOUNTER                 StatRegDisplayIsPrimaryRd;
+    STAMCOUNTER                 StatRegDisplayPositionXRd;
+    STAMCOUNTER                 StatRegDisplayPositionYRd;
+    STAMCOUNTER                 StatRegDisplayWidthRd;
+    STAMCOUNTER                 StatRegEnableRd;
+    STAMCOUNTER                 StatRegFbOffsetRd;
+    STAMCOUNTER                 StatRegFbSizeRd;
+    STAMCOUNTER                 StatRegFbStartRd;
+    STAMCOUNTER                 StatRegGmrIdRd;
+    STAMCOUNTER                 StatRegGmrMaxDescriptorLengthRd;
+    STAMCOUNTER                 StatRegGmrMaxIdsRd;
+    STAMCOUNTER                 StatRegGmrsMaxPagesRd;
+    STAMCOUNTER                 StatRegGreenMaskRd;
+    STAMCOUNTER                 StatRegGuestIdRd;
+    STAMCOUNTER                 StatRegHeightRd;
+    STAMCOUNTER                 StatRegHostBitsPerPixelRd;
+    STAMCOUNTER                 StatRegIdRd;
+    STAMCOUNTER                 StatRegIrqMaskRd;
+    STAMCOUNTER                 StatRegMaxHeightRd;
+    STAMCOUNTER                 StatRegMaxWidthRd;
+    STAMCOUNTER                 StatRegMemorySizeRd;
+    STAMCOUNTER                 StatRegMemRegsRd;
+    STAMCOUNTER                 StatRegMemSizeRd;
+    STAMCOUNTER                 StatRegMemStartRd;
+    STAMCOUNTER                 StatRegNumDisplaysRd;
+    STAMCOUNTER                 StatRegNumGuestDisplaysRd;
+    STAMCOUNTER                 StatRegPaletteRd;
+    STAMCOUNTER                 StatRegPitchLockRd;
+    STAMCOUNTER                 StatRegPsuedoColorRd;
+    STAMCOUNTER                 StatRegRedMaskRd;
+    STAMCOUNTER                 StatRegScratchRd;
+    STAMCOUNTER                 StatRegScratchSizeRd;
+    STAMCOUNTER                 StatRegSyncRd;
+    STAMCOUNTER                 StatRegTopRd;
+    STAMCOUNTER                 StatRegTracesRd;
+    STAMCOUNTER                 StatRegUnknownRd;
+    STAMCOUNTER                 StatRegVramSizeRd;
+    STAMCOUNTER                 StatRegWidthRd;
+    STAMCOUNTER                 StatRegWriteOnlyRd;
 } VMSVGAState;
 #endif /* VBOX_WITH_VMSVGA */
 
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm
index 3ee2f6d..fd8737f 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm
@@ -1115,7 +1115,7 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xcde class=DATA group=DGROUP
 
 section CONST2 progbits vstart=0xd8e align=1 ; size=0x3fa class=DATA group=DGROUP
 _bios_cvs_version_string:                    ; 0xf0d8e LB 0x12
-    db  'VirtualBox 5.1.12', 000h
+    db  'VirtualBox 5.1.14', 000h
 _bios_prefix_string:                         ; 0xf0da0 LB 0x8
     db  'BIOS: ', 000h, 000h
 _isotag:                                     ; 0xf0da8 LB 0x6
@@ -17798,4 +17798,4 @@ biosorg_check_before_or_at_0FFEEh:           ; 0xfff80 LB 0x70
     db  'XM'
 cpu_reset:                                   ; 0xffff0 LB 0x10
     jmp far 0f000h:0e05bh                     ; ea 5b e0 00 f0
-    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 058h
+    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 056h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum
index 3f2ee6b..5a7c9d9 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum
@@ -1 +1 @@
-4152605718c15bf8f0fb342c6a79f5a2 *VBoxPcBios286.rom
+86778e11757d6e0bf6fcc2ea86562af3 *VBoxPcBios286.rom
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm
index 42b5249..17e39ab 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm
@@ -1078,7 +1078,7 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xcde class=DATA group=DGROUP
 
 section CONST2 progbits vstart=0xd8e align=1 ; size=0x3fa class=DATA group=DGROUP
 _bios_cvs_version_string:                    ; 0xf0d8e LB 0x12
-    db  'VirtualBox 5.1.12', 000h
+    db  'VirtualBox 5.1.14', 000h
 _bios_prefix_string:                         ; 0xf0da0 LB 0x8
     db  'BIOS: ', 000h, 000h
 _isotag:                                     ; 0xf0da8 LB 0x6
@@ -17197,4 +17197,4 @@ biosorg_check_before_or_at_0FFEEh:           ; 0xfff80 LB 0x70
     db  'XM'
 cpu_reset:                                   ; 0xffff0 LB 0x10
     jmp far 0f000h:0e05bh                     ; ea 5b e0 00 f0
-    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 0e9h
+    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 0e7h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum
index 1c14bc1..3451cd0 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum
@@ -1 +1 @@
-6419c66459b0a6857d8aa59da1eb400a *VBoxPcBios386.rom
+463264b1d9ad1b4f0486e4e85cd5b1e5 *VBoxPcBios386.rom
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm
index 77d23bf..f5320c7 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm
@@ -1115,7 +1115,7 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xcde class=DATA group=DGROUP
 
 section CONST2 progbits vstart=0xd8e align=1 ; size=0x3fa class=DATA group=DGROUP
 _bios_cvs_version_string:                    ; 0xf0d8e LB 0x12
-    db  'VirtualBox 5.1.12', 000h
+    db  'VirtualBox 5.1.14', 000h
 _bios_prefix_string:                         ; 0xf0da0 LB 0x8
     db  'BIOS: ', 000h, 000h
 _isotag:                                     ; 0xf0da8 LB 0x6
@@ -18273,4 +18273,4 @@ biosorg_check_before_or_at_0FFEEh:           ; 0xfff80 LB 0x70
     db  'XM'
 cpu_reset:                                   ; 0xffff0 LB 0x10
     jmp far 0f000h:0e05bh                     ; ea 5b e0 00 f0
-    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fbh, 006h
+    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fbh, 004h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum
index da9b927..124bd30 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum
@@ -1 +1 @@
-4043c5dddd3a62bfc262d1f96987a95d *VBoxPcBios8086.rom
+c048f16803d5500df9d2f3edd43147a7 *VBoxPcBios8086.rom
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
index b6f9356..3c92614 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
@@ -502,6 +502,7 @@ RTEXITCODE handleModifyMedium(HandlerArg *a)
     bool fModifyProperties = false;
     bool fModifyCompact = false;
     bool fModifyResize = false;
+    bool fModifyResizeMB = false;
     bool fModifyLocation = false;
     uint64_t cbResize = 0;
     const char *pszFilenameOrUuid = NULL;
@@ -588,6 +589,7 @@ RTEXITCODE handleModifyMedium(HandlerArg *a)
             case 'r':   // --resize
                 cbResize = ValueUnion.u64 * _1M;
                 fModifyResize = true;
+                fModifyResizeMB = true; // do sanity check!
                 break;
 
             case 'R':   // --resizebyte
@@ -657,6 +659,27 @@ RTEXITCODE handleModifyMedium(HandlerArg *a)
         return RTEXITCODE_FAILURE;
     }
 
+    if (   fModifyResize
+        && fModifyResizeMB)
+    {
+        // Sanity check
+        //
+        // In general users should know what they do but in this case users have no
+        // alternative to VBoxManage. If happens that one wants to resize the disk
+        // and uses --resize and does not consider that this parameter expects the
+        // new medium size in MB not Byte. If the operation is started and then
+        // aborted by the user, the result is most likely a medium which doesn't
+        // work anymore.
+        LONG64 logicalSize;
+        pMedium->COMGETTER(LogicalSize)(&logicalSize);
+        if (cbResize > (uint64_t)logicalSize * 1000)
+        {
+            RTMsgError("Error: Attempt to resize the medium from %RU64.%RU64 MB to %RU64.%RU64 MB. Use --resizebyte if this is intended!\n",
+                    logicalSize / _1M, (logicalSize % _1M) / (_1M / 10), cbResize / _1M, (cbResize % _1M) / (_1M / 10));
+            return RTEXITCODE_FAILURE;
+        }
+    }
+
     if (fModifyMediumType)
     {
         MediumType_T enmCurrMediumType;
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
index 8fdeb51..fbf8fb2 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
@@ -1193,6 +1193,10 @@
         <source>Downloading %1...</source>
         <translation>%1 wird heruntergeladen...</translation>
     </message>
+    <message>
+        <source>Verifying %1...</source>
+        <translation>Überprüfe %1...</translation>
+    </message>
 </context>
 <context>
     <name>UIDownloaderAdditions</name>
@@ -4130,7 +4134,7 @@
     </message>
     <message>
         <source>Location:</source>
-        <translation>abgespeichert wo:</translation>
+        <translation>gespeichert wo:</translation>
     </message>
     <message>
         <source>Type (Format):</source>
@@ -4192,7 +4196,7 @@
     </message>
     <message>
         <source>Details:</source>
-        <translation>abgespeichert wie:</translation>
+        <translation>gespeichert wie:</translation>
     </message>
     <message>
         <source>&Port Count:</source>
@@ -5126,7 +5130,7 @@
     </message>
     <message>
         <source>Failed to save the settings of the virtual machine <b>%1</b> to <b><nobr>%2</nobr></b>.</source>
-        <translation>Die Einstellungen der virtuellen Maschine <b>%1</b> konnten nicht nach <b><nobr>%2</nobr></b> abgespeichert werden.</translation>
+        <translation>Die Einstellungen der virtuellen Maschine <b>%1</b> konnten nicht in <b><nobr>%2</nobr></b> gespeichert werden.</translation>
     </message>
     <message>
         <source><p>Could not enter seamless mode due to insufficient guest video memory.</p><p>You should configure the virtual machine to have at least <b>%1</b> of video memory.</p></source>
@@ -5319,7 +5323,7 @@
     </message>
     <message>
         <source>Failed to update Guest Additions. The Guest Additions disk image file will be inserted for user installation.</source>
-        <translation>Die Gasterweiterungen konnten nicht aktualisiert werden. Das ISO-Abbild mit den Erweiterungen wird jetzt für eine manuelle gemountet.</translation>
+        <translation>Die Gasterweiterungen konnten nicht aktualisiert werden. Das Abbild mit den Gasterweiterungen wird jetzt für eine manuelle Installation gemountet.</translation>
     </message>
     <message>
         <source>Failed to install the Extension Pack <b>%1</b>.</source>
@@ -5451,7 +5455,7 @@
     </message>
     <message>
         <source>The virtual machine that you are changing has been started. Only certain settings can be changed while a machine is running. All other changes will be lost if you close this window now.</source>
-        <translation>Der Zustand der virtuellen Maschine hat sich in der Zwischenzeit geändert. Durch Bestätigen werden nur die zur Laufzeit änderbaren Einstellungen abgespeichert. Alle anderen Änderungen gehen verloren.</translation>
+        <translation>Der Zustand der virtuellen Maschine hat sich in der Zwischenzeit geändert. Durch Bestätigen werden nur die zur Laufzeit änderbaren Einstellungen gespeichert. Alle anderen Änderungen gehen verloren.</translation>
     </message>
     <message>
         <source>Can't find snapshot named <b>%1</b>.</source>
@@ -5710,7 +5714,7 @@
     </message>
     <message>
         <source><p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded from <nobr><a href="%1">%1</a></nobr> but can't be saved locally as <nobr><b>%2</b>.</nobr></p><p>Please choose another location for that file.</p></source>
-        <translation><p>Das CD-Abbild mit den <b>VirtualBox-Gasterweiterungen</b> wurde erfolgreich von <nobr><a href="%1">%1</a></nobr> heruntergeladen, konnte aber nicht unter <nobr><b>%2</b></nobr>gespeichert werden.</p><p>Bitte wählen Sie einen anderen Ordner für diese Datei.</p></translation>
+        <translation><p>Das Abbild mit den <b>VirtualBox-Gasterweiterungen</b> wurde erfolgreich von <nobr><a href="%1">%1</a></nobr> heruntergeladen, konnte aber nicht unter <nobr><b>%2</b></nobr>gespeichert werden.</p><p>Bitte wählen Sie einen anderen Ordner für diese Datei.</p></translation>
     </message>
     <message>
         <source><p>Could not find the <b>VirtualBox User Manual</b> <nobr><b>%1</b>.</nobr></p><p>Do you wish to download this file from the Internet?</p></source>
@@ -5823,7 +5827,7 @@
     </message>
     <message>
         <source><p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded from <nobr><a href="%1">%1</a></nobr> and saved locally as <nobr><b>%2</b>.</nobr></p><p>Do you wish to register this disk image file and insert it into the virtual optical drive?</p></source>
-        <translation><p>Das CD-Abbild mit den <b>VirtualBox-Gasterweiterungen</b> wurde erfolgreich von <nobr><a href="%1">%1</a></nobr> heruntergeladen und lokal unter <nobr><b>%2</b></nobr> gespeichert.</p><p>Möchten Sie dieses Abbild in VirtualBox registrieren und in das virtuelle optische Laufwerk einlegen?</p></translation>
+        <translation><p>Das Abbild mit den <b>VirtualBox-Gasterweiterungen</b> wurde erfolgreich von <nobr><a href="%1">%1</a></nobr> heruntergeladen und lokal unter <nobr><b>%2</b></nobr> gespeichert.</p><p>Möchten Sie dieses Abbild in VirtualBox registrieren und in das virtuelle optische Laufwerk einlegen?</p></translation>
     </message>
     <message>
         <source>Bad password or authentication failure.</source>
@@ -5932,7 +5936,15 @@
     </message>
     <message>
         <source><p>The reason for this error are most likely wrong permissions of the IPC daemon socket due to an installation problem. Please check the permissions of <font color=blue>'/tmp'</font> and <font color=blue>'/tmp/.vbox-*-ipc/'</font></p></source>
-        <translation type="unfinished"></translation>
+        <translation><p>Die Ursache für diesen Fehler liegt meist in mangelhaften Zugriffsrechten für den IPC-Daemon-Socket aufgrund eines Installationsproblems. Bitte überprüfen Sie Zugriffsrechte von <font color=blue>'/tmp'</font> und <font color=blue>'/tmp/.vbox-*-ipc/'</font></p></translation>
+    </message>
+    <message>
+        <source><p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded from <nobr><a href="%1">%1</a></nobr> and saved locally as <nobr><b>%2</b>, </nobr>but the SHA-256 checksum verification failed.</p><p>Please do the download, installation and verification manually.</p></source>
+        <translation><p>Das Medium mit den <b>VirtualBox-Gasterweiterungen</b> wurde erfolgreich von <nobr><a href="%1">%1</a></nobr> heruntergeladen und lokal unter <nobr><b>%2</b></nobr> gespeichert. Allerdings schlug die Überprüfung des SHA256-Hashes fehl.</p><p>Bitte laden Sie dieses Medium manuell herunter und überprüfen Sie den SHA256-Hash.</p></translation>
+    </message>
+    <message>
+        <source><p>The <b><nobr>%1</nobr></b> has been successfully downloaded from <nobr><a href="%2">%2</a></nobr> and saved locally as <nobr><b>%3</b>, </nobr>but the SHA-256 checksum verification failed.</p><p>Please do the download, installation and verification manually.</p></source>
+        <translation><p>Das <b><nobr>%1</nobr></b>  wurde erfolgreich von <nobr><a href="%2">%2</a></nobr> heruntergeladen und lokal unter <nobr><b>%3</b></nobr> gespeichert. Allerdings schlug die Überprüfung des SHA256-Hashes fehl.</p><p>Bitte laden Sie dieses Medium manuell herunter und überprüfen Sie den SHA256-Hash.</p></translation>
     </message>
 </context>
 <context>
@@ -7375,11 +7387,11 @@
     </message>
     <message>
         <source><p><nobr>Holds the name or full path to the virtual machine folder you are about to create.</nobr></p></source>
-        <translation><p><nobr>Enthält den Namen oder den Pfad der virtuellen Machine, die erzeugt werden soll.</nobr></p></translation>
+        <translation type="vanished"><p><nobr>Enthält den Namen oder den Pfad der virtuellen Machine, die erzeugt werden soll.</nobr></p></translation>
     </message>
     <message>
         <source><p><nobr>You are about to create the virtual machine in the following folder:</nobr><br><nobr><b>%1</b></nobr></p></source>
-        <translation><p><nobr>Die virtuelle Machine wird im folgenden Ordner erzeugt:</nobr><br><nobr><b>%1</b></nobr></p></translation>
+        <translation type="vanished"><p><nobr>Die virtuelle Machine wird im folgenden Ordner erzeugt:</nobr><br><nobr><b>%1</b></nobr></p></translation>
     </message>
 </context>
 <context>
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp b/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp
index 9a2629f..386d46a 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp
@@ -2165,6 +2165,17 @@ bool UIMessageCenter::proposeMountGuestAdditions(const QString &strUrl, const QS
                           tr("Insert", "additions"));
 }
 
+void UIMessageCenter::cannotValidateGuestAdditionsSHA256Sum(const QString &strUrl, const QString &strSrc) const
+{
+    alert(windowManager().networkManagerOrMainWindowShown(), MessageType_Error,
+          tr("<p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded "
+             "from <nobr><a href=\"%1\">%1</a></nobr> "
+             "and saved locally as <nobr><b>%2</b>, </nobr>"
+             "but the SHA-256 checksum verification failed.</p>"
+             "<p>Please do the download, installation and verification manually.</p>")
+             .arg(strUrl, strSrc));
+}
+
 void UIMessageCenter::cannotUpdateGuestAdditions(const CProgress &progress) const
 {
     error(0, MessageType_Error,
@@ -2254,6 +2265,17 @@ bool UIMessageCenter::proposeInstallExtentionPack(const QString &strExtPackName,
                           tr("Install", "extension pack"));
 }
 
+void UIMessageCenter::cannotValidateExtentionPackSHA256Sum(const QString &strExtPackName, const QString &strFrom, const QString &strTo) const
+{
+    alert(windowManager().networkManagerOrMainWindowShown(), MessageType_Error,
+          tr("<p>The <b><nobr>%1</nobr></b> has been successfully downloaded "
+             "from <nobr><a href=\"%2\">%2</a></nobr> "
+             "and saved locally as <nobr><b>%3</b>, </nobr>"
+             "but the SHA-256 checksum verification failed.</p>"
+             "<p>Please do the download, installation and verification manually.</p>")
+             .arg(strExtPackName, strFrom, strTo));
+}
+
 bool UIMessageCenter::proposeDeleteExtentionPack(const QString &strTo) const
 {
     return questionBinary(windowManager().networkManagerOrMainWindowShown(), MessageType_Question,
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h b/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h
index 2ee014d..624a064 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h
+++ b/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h
@@ -328,6 +328,7 @@ public:
     bool confirmDownloadGuestAdditions(const QString &strUrl, qulonglong uSize) const;
     void cannotSaveGuestAdditions(const QString &strURL, const QString &strTarget) const;
     bool proposeMountGuestAdditions(const QString &strUrl, const QString &strSrc) const;
+    void cannotValidateGuestAdditionsSHA256Sum(const QString &strUrl, const QString &strSrc) const;
     void cannotUpdateGuestAdditions(const CProgress &progress) const;
     bool cannotFindUserManual(const QString &strMissedLocation) const;
     bool confirmDownloadUserManual(const QString &strURL, qulonglong uSize) const;
@@ -337,6 +338,7 @@ public:
     bool confirmDownloadExtensionPack(const QString &strExtPackName, const QString &strURL, qulonglong uSize) const;
     void cannotSaveExtensionPack(const QString &strExtPackName, const QString &strFrom, const QString &strTo) const;
     bool proposeInstallExtentionPack(const QString &strExtPackName, const QString &strFrom, const QString &strTo) const;
+    void cannotValidateExtentionPackSHA256Sum(const QString &strExtPackName, const QString &strFrom, const QString &strTo) const;
     bool proposeDeleteExtentionPack(const QString &strTo) const;
     bool proposeDeleteOldExtentionPacks(const QStringList &strFiles) const;
 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.cpp b/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.cpp
index 43a1f60..4e89bdd 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.cpp
@@ -15,6 +15,9 @@
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
 
+/// This class requires proper doxy.
+/// For now I'm keeping the old style consistent.
+
 #ifdef VBOX_WITH_PRECOMPILED_HEADERS
 # include <precomp.h>
 #else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
@@ -48,13 +51,23 @@ void UIDownloader::sltStartAcknowledging()
 /* Downloading start: */
 void UIDownloader::sltStartDownloading()
 {
-    /* Set state to acknowledging: */
+    /* Set state to downloading: */
     m_state = UIDownloaderState_Downloading;
 
     /* Send GET request: */
     createNetworkRequest(UINetworkRequestType_GET, QList<QUrl>() << m_source);
 }
 
+/* Verifying start: */
+void UIDownloader::sltStartVerifying()
+{
+    /* Set state to verifying: */
+    m_state = UIDownloaderState_Verifying;
+
+    /* Send GET request: */
+    createNetworkRequest(UINetworkRequestType_GET, QList<QUrl>() << m_strPathSHA256SumsFile);
+}
+
 /* Constructor: */
 UIDownloader::UIDownloader()
     : m_state(UIDownloaderState_Null)
@@ -62,6 +75,7 @@ UIDownloader::UIDownloader()
     /* Connect listeners: */
     connect(this, SIGNAL(sigToStartAcknowledging()), this, SLOT(sltStartAcknowledging()), Qt::QueuedConnection);
     connect(this, SIGNAL(sigToStartDownloading()), this, SLOT(sltStartDownloading()), Qt::QueuedConnection);
+    connect(this, SIGNAL(sigToStartVerifying()), this, SLOT(sltStartVerifying()), Qt::QueuedConnection);
 }
 
 /* virtual override */
@@ -72,6 +86,7 @@ const QString UIDownloader::description() const
     {
         case UIDownloaderState_Acknowledging: return tr("Looking for %1...");
         case UIDownloaderState_Downloading:   return tr("Downloading %1...");
+        case UIDownloaderState_Verifying:     return tr("Verifying %1...");
         default:                              break;
     }
     /* Return null-string by default: */
@@ -112,6 +127,11 @@ void UIDownloader::processNetworkReplyFinished(UINetworkReply *pNetworkReply)
             handleDownloadingResult(pNetworkReply);
             break;
         }
+        case UIDownloaderState_Verifying:
+        {
+            handleVerifyingResult(pNetworkReply);
+            break;
+        }
         default:
             break;
     }
@@ -142,6 +162,24 @@ void UIDownloader::handleDownloadingResult(UINetworkReply *pNetworkReply)
     /* Handle downloaded object: */
     handleDownloadedObject(pNetworkReply);
 
+    /* Check whether we should do verification: */
+    if (!m_strPathSHA256SumsFile.isEmpty())
+    {
+        /* Start verifying: */
+        startDelayedVerifying();
+    }
+    else
+    {
+        /* Delete downloader: */
+        deleteLater();
+    }
+}
+
+void UIDownloader::handleVerifyingResult(UINetworkReply *pNetworkReply)
+{
+    /* Handle verified object: */
+    handleVerifiedObject(pNetworkReply);
+
     /* Delete downloader: */
     deleteLater();
 }
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.h b/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.h
index d036c69..b2fa293 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.h
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIDownloader.h
@@ -15,6 +15,9 @@
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
 
+/// This class requires proper doxy.
+/// For now I'm keeping the old style consistent.
+
 #ifndef __UIDownloader_h__
 #define __UIDownloader_h__
 
@@ -41,6 +44,8 @@ signals:
     void sigToStartAcknowledging();
     /* Signal to start downloading: */
     void sigToStartDownloading();
+    /* Signal to start verifying: */
+    void sigToStartVerifying();
 
 public:
 
@@ -53,6 +58,8 @@ protected slots:
     void sltStartAcknowledging();
     /* Downloading part: */
     void sltStartDownloading();
+    /* Verifying part: */
+    void sltStartVerifying();
 
 protected:
 
@@ -61,7 +68,8 @@ protected:
     {
         UIDownloaderState_Null,
         UIDownloaderState_Acknowledging,
-        UIDownloaderState_Downloading
+        UIDownloaderState_Downloading,
+        UIDownloaderState_Verifying,
     };
 
     /* Constructor: */
@@ -79,6 +87,11 @@ protected:
     void setTarget(const QString &strTarget) { m_strTarget = strTarget; }
     const QString& target() const { return m_strTarget; }
 
+    /* SHA-256 stuff,
+     * allows to set/get SHA-256 sum dictionary file for downloaded source. */
+    QString pathSHA256SumsFile() const { return m_strPathSHA256SumsFile; }
+    void setPathSHA256SumsFile(const QString &strPathSHA256SumsFile) { m_strPathSHA256SumsFile = strPathSHA256SumsFile; }
+
     /** Returns description of the current network operation. */
     virtual const QString description() const;
 
@@ -86,6 +99,8 @@ protected:
     void startDelayedAcknowledging() { emit sigToStartAcknowledging(); }
     /* Start delayed downloading: */
     void startDelayedDownloading() { emit sigToStartDownloading(); }
+    /* Start delayed verifying: */
+    void startDelayedVerifying() { emit sigToStartVerifying(); }
 
     /* Network-reply progress handler: */
     void processNetworkReplyProgress(qint64 iReceived, qint64 iTotal);
@@ -98,11 +113,15 @@ protected:
     virtual void handleAcknowledgingResult(UINetworkReply *pNetworkReply);
     /* Handle downloading result: */
     virtual void handleDownloadingResult(UINetworkReply *pNetworkReply);
+    /* Handle verifying result: */
+    virtual void handleVerifyingResult(UINetworkReply *pNetworkReply);
 
     /* Pure virtual function to ask user about downloading confirmation: */
     virtual bool askForDownloadingConfirmation(UINetworkReply *pNetworkReply) = 0;
     /* Pure virtual function to handle downloaded object: */
     virtual void handleDownloadedObject(UINetworkReply *pNetworkReply) = 0;
+    /* Base virtual function to handle verified object: */
+    virtual void handleVerifiedObject(UINetworkReply * /* pNetworkReply */) {}
 
 private:
 
@@ -111,6 +130,7 @@ private:
     QList<QUrl> m_sources;
     QUrl m_source;
     QString m_strTarget;
+    QString m_strPathSHA256SumsFile;
 };
 
 #endif // __UIDownloader_h__
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.cpp b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.cpp
index 1e72736..617dc8f 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.cpp
@@ -33,6 +33,9 @@
 
 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
 
+/* Other VBox includes: */
+#include <iprt/sha.h>
+
 
 /* static */
 UIDownloaderAdditions* UIDownloaderAdditions::m_spInstance = 0;
@@ -80,13 +83,16 @@ UIDownloaderAdditions::UIDownloaderAdditions()
     }
 
     /* Prepare source/target: */
-    const QString &strName = QString("VBoxGuestAdditions_%1.iso").arg(strVersion);
-    const QString &strSource = QString("http://download.virtualbox.org/virtualbox/%1/").arg(strVersion) + strName;
-    const QString &strTarget = QDir(vboxGlobal().homeFolder()).absoluteFilePath(strName);
+    const QString strSourceName = QString("VBoxGuestAdditions_%1.iso").arg(strVersion);
+    const QString strSourceFolder = QString("http://download.virtualbox.org/virtualbox/%1/").arg(strVersion);
+    const QString strSource = strSourceFolder + strSourceName;
+    const QString strPathSHA256SumsFile = QString("https://www.virtualbox.org/download/hashes/%1/SHA256SUMS").arg(strVersion);
+    const QString strTarget = QDir(vboxGlobal().homeFolder()).absoluteFilePath(strSourceName);
 
     /* Set source/target: */
     setSource(strSource);
     setTarget(strTarget);
+    setPathSHA256SumsFile(strPathSHA256SumsFile);
 }
 
 UIDownloaderAdditions::~UIDownloaderAdditions()
@@ -110,7 +116,64 @@ bool UIDownloaderAdditions::askForDownloadingConfirmation(UINetworkReply *pReply
 void UIDownloaderAdditions::handleDownloadedObject(UINetworkReply *pReply)
 {
     /* Read received data into the buffer: */
-    QByteArray receivedData(pReply->readAll());
+    m_receivedData = pReply->readAll();
+}
+
+void UIDownloaderAdditions::handleVerifiedObject(UINetworkReply *pReply)
+{
+    /* Try to verify the SHA-256 checksum: */
+    QString strCalculatedSumm;
+    bool fSuccess = false;
+    do
+    {
+        /* Read received data into the buffer: */
+        const QByteArray receivedData(pReply->readAll());
+        /* Make sure it's not empty: */
+        if (receivedData.isEmpty())
+            break;
+
+        /* Parse buffer contents to dictionary: */
+        const QStringList dictionary(QString(receivedData).split("\n", QString::SkipEmptyParts));
+        /* Make sure it's not empty: */
+        if (dictionary.isEmpty())
+            break;
+
+        /* Parse each record to tags, look for the required one: */
+        foreach (const QString &strRecord, dictionary)
+        {
+            const QString strFileName = strRecord.section(" *", 1);
+            const QString strDownloadedSumm = strRecord.section(" *", 0, 0);
+            if (strFileName == source().fileName())
+            {
+                /* Calc the SHA-256 on the bytes, creating a string: */
+                uint8_t abHash[RTSHA256_HASH_SIZE];
+                RTSha256(m_receivedData.constData(), m_receivedData.length(), abHash);
+                char szDigest[RTSHA256_DIGEST_LEN + 1];
+                int rc = RTSha256ToString(abHash, szDigest, sizeof(szDigest));
+                if (RT_FAILURE(rc))
+                {
+                    AssertRC(rc);
+                    szDigest[0] = '\0';
+                }
+                strCalculatedSumm = szDigest;
+                //printf("Downloaded SHA-256 summ: [%s]\n", strDownloadedSumm.toUtf8().constData());
+                //printf("Calculated SHA-256 summ: [%s]\n", strCalculatedSumm.toUtf8().constData());
+                /* Make sure checksum is valid: */
+                fSuccess = strDownloadedSumm == strCalculatedSumm;
+                break;
+            }
+        }
+    }
+    while (false);
+
+    /* If SHA-256 checksum verification failed: */
+    if (!fSuccess)
+    {
+        /* Warn the user about additions-image was downloaded and saved but checksum is invalid: */
+        msgCenter().cannotValidateGuestAdditionsSHA256Sum(source().toString(), QDir::toNativeSeparators(target()));
+        return;
+    }
+
     /* Serialize that buffer into the file: */
     while (true)
     {
@@ -119,7 +182,7 @@ void UIDownloaderAdditions::handleDownloadedObject(UINetworkReply *pReply)
         if (file.open(QIODevice::WriteOnly))
         {
             /* Write buffer into the file: */
-            file.write(receivedData);
+            file.write(m_receivedData);
             file.close();
 
             /* Warn the user about additions-image loaded and saved, propose to mount it: */
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.h b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.h
index d5e362b..5823c13 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.h
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderAdditions.h
@@ -49,9 +49,11 @@ private:
     /* Virtual stuff reimplementations: */
     bool askForDownloadingConfirmation(UINetworkReply *pReply);
     void handleDownloadedObject(UINetworkReply *pReply);
+    void handleVerifiedObject(UINetworkReply *pReply);
 
     /* Variables: */
     static UIDownloaderAdditions *m_spInstance;
+    QByteArray m_receivedData;
 };
 
 #endif // __UIDownloaderAdditions_h__
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.cpp b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.cpp
index 96e929d..17bb948 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.cpp
@@ -33,6 +33,7 @@
 
 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
 
+/* Other VBox includes: */
 #include <iprt/sha.h>
 
 
@@ -60,12 +61,14 @@ UIDownloaderExtensionPack::UIDownloaderExtensionPack()
         m_spInstance = this;
 
     /* Prepare source/target: */
+    QString strVersion = vboxGlobal().vboxVersionStringNormalized();
     QString strExtPackUnderscoredName(QString(GUI_ExtPackName).replace(' ', '_'));
     QString strTemplateSourcePath("http://download.virtualbox.org/virtualbox/%1/");
     QString strTemplateSourceName(QString("%1-%2.vbox-extpack").arg(strExtPackUnderscoredName));
-    QString strSourcePath(strTemplateSourcePath.arg(vboxGlobal().vboxVersionStringNormalized()));
-    QString strSourceName(strTemplateSourceName.arg(vboxGlobal().vboxVersionStringNormalized()));
+    QString strSourcePath(strTemplateSourcePath.arg(strVersion));
+    QString strSourceName(strTemplateSourceName.arg(strVersion));
     QString strSource(strSourcePath + strSourceName);
+    QString strPathSHA256SumsFile = QString("https://www.virtualbox.org/download/hashes/%1/SHA256SUMS").arg(strVersion);
     QString strTargetPath(vboxGlobal().homeFolder());
     QString strTargetName(strSourceName);
     QString strTarget(QDir(strTargetPath).absoluteFilePath(strTargetName));
@@ -73,6 +76,7 @@ UIDownloaderExtensionPack::UIDownloaderExtensionPack()
     /* Set source/target: */
     setSource(strSource);
     setTarget(strTarget);
+    setPathSHA256SumsFile(strPathSHA256SumsFile);
 }
 
 UIDownloaderExtensionPack::~UIDownloaderExtensionPack()
@@ -96,7 +100,64 @@ bool UIDownloaderExtensionPack::askForDownloadingConfirmation(UINetworkReply *pR
 void UIDownloaderExtensionPack::handleDownloadedObject(UINetworkReply *pReply)
 {
     /* Read received data into the buffer: */
-    QByteArray receivedData(pReply->readAll());
+    m_receivedData = pReply->readAll();
+}
+
+void UIDownloaderExtensionPack::handleVerifiedObject(UINetworkReply *pReply)
+{
+    /* Try to verify the SHA-256 checksum: */
+    QString strCalculatedSumm;
+    bool fSuccess = false;
+    do
+    {
+        /* Read received data into the buffer: */
+        const QByteArray receivedData(pReply->readAll());
+        /* Make sure it's not empty: */
+        if (receivedData.isEmpty())
+            break;
+
+        /* Parse buffer contents to dictionary: */
+        const QStringList dictionary(QString(receivedData).split("\n", QString::SkipEmptyParts));
+        /* Make sure it's not empty: */
+        if (dictionary.isEmpty())
+            break;
+
+        /* Parse each record to tags, look for the required one: */
+        foreach (const QString &strRecord, dictionary)
+        {
+            const QString strFileName = strRecord.section(" *", 1);
+            const QString strDownloadedSumm = strRecord.section(" *", 0, 0);
+            if (strFileName == source().fileName())
+            {
+                /* Calc the SHA-256 on the bytes, creating a string: */
+                uint8_t abHash[RTSHA256_HASH_SIZE];
+                RTSha256(m_receivedData.constData(), m_receivedData.length(), abHash);
+                char szDigest[RTSHA256_DIGEST_LEN + 1];
+                int rc = RTSha256ToString(abHash, szDigest, sizeof(szDigest));
+                if (RT_FAILURE(rc))
+                {
+                    AssertRC(rc);
+                    szDigest[0] = '\0';
+                }
+                strCalculatedSumm = szDigest;
+                //printf("Downloaded SHA-256 summ: [%s]\n", strDownloadedSumm.toUtf8().constData());
+                //printf("Calculated SHA-256 summ: [%s]\n", strCalculatedSumm.toUtf8().constData());
+                /* Make sure checksum is valid: */
+                fSuccess = strDownloadedSumm == strCalculatedSumm;
+                break;
+            }
+        }
+    }
+    while (false);
+
+    /* If SHA-256 checksum verification failed: */
+    if (!fSuccess)
+    {
+        /* Warn the user about additions-image was downloaded and saved but checksum is invalid: */
+        msgCenter().cannotValidateExtentionPackSHA256Sum(GUI_ExtPackName, source().toString(), QDir::toNativeSeparators(target()));
+        return;
+    }
+
     /* Serialize that buffer into the file: */
     while (true)
     {
@@ -105,22 +166,11 @@ void UIDownloaderExtensionPack::handleDownloadedObject(UINetworkReply *pReply)
         if (file.open(QIODevice::WriteOnly))
         {
             /* Write buffer into the file: */
-            file.write(receivedData);
+            file.write(m_receivedData);
             file.close();
 
-            /* Calc the SHA-256 on the bytes, creating a string: */
-            uint8_t abHash[RTSHA256_HASH_SIZE];
-            RTSha256(receivedData.constData(), receivedData.length(), abHash);
-            char szDigest[RTSHA256_DIGEST_LEN + 1];
-            int rc = RTSha256ToString(abHash, szDigest, sizeof(szDigest));
-            if (RT_FAILURE(rc))
-            {
-                AssertRC(rc);
-                szDigest[0] = '\0';
-            }
-
             /* Warn the listener about extension-pack was downloaded: */
-            emit sigDownloadFinished(source().toString(), target(), &szDigest[0]);
+            emit sigDownloadFinished(source().toString(), target(), strCalculatedSumm);
             break;
         }
 
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.h b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.h
index 1334194..c8f9c9e 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.h
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.h
@@ -49,9 +49,11 @@ private:
     /* Virtual stuff reimplementations: */
     bool askForDownloadingConfirmation(UINetworkReply *pReply);
     void handleDownloadedObject(UINetworkReply *pReply);
+    void handleVerifiedObject(UINetworkReply *pReply);
 
     /* Variables: */
     static UIDownloaderExtensionPack *m_spInstance;
+    QByteArray m_receivedData;
 };
 
 #endif // __UIDownloaderExtensionPack_h__
diff --git a/src/VBox/Frontends/VirtualBox/src/net/UIUpdateManager.cpp b/src/VBox/Frontends/VirtualBox/src/net/UIUpdateManager.cpp
index 1658074..88a2200 100644
--- a/src/VBox/Frontends/VirtualBox/src/net/UIUpdateManager.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/net/UIUpdateManager.cpp
@@ -55,10 +55,8 @@
 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
 
 
-#if 0
 /* enable to test the version update check */
-#define VBOX_NEW_VERSION_TEST "0.0.0_0 http://unknown.unknown.org/0.0.0/VirtualBox-0.0.0-0-unknown.pkg"
-#endif
+//#define VBOX_NEW_VERSION_TEST "5.1.12_0 http://unknown.unknown.org/0.0.0/VirtualBox-0.0.0-0-unknown.pkg"
 
 /* Forward declarations: */
 class UIUpdateStep;
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp
index 94587d0..d23a179 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp
@@ -47,6 +47,8 @@
 
 UIMultiScreenLayout::UIMultiScreenLayout(UIMachineLogic *pMachineLogic)
     : m_pMachineLogic(pMachineLogic)
+    , m_cGuestScreens(m_pMachineLogic->machine().GetMonitorCount())
+    , m_cHostScreens(0)
 {
     /* Calculate host/guest screen count: */
     calculateHostMonitorCount();
@@ -68,7 +70,6 @@ void UIMultiScreenLayout::update()
     /* Load all combinations stored in the settings file.
      * We have to make sure they are valid, which means there have to be unique combinations
      * and all guests screens need there own host screen. */
-    CDisplay display = m_pMachineLogic->session().GetConsole().GetDisplay();
     bool fShouldWeAutoMountGuestScreens = gEDataManager->autoMountGuestScreensEnabled(vboxGlobal().managedVMUuid());
     LogRel(("GUI: UIMultiScreenLayout::update: GUI/AutomountGuestScreens is %s\n", fShouldWeAutoMountGuestScreens ? "enabled" : "disabled"));
     foreach (int iGuestScreen, m_guestScreens)
@@ -129,7 +130,7 @@ void UIMultiScreenLayout::update()
         {
             /* Then we have to disable excessive guest-screen: */
             LogRel(("GUI: UIMultiScreenLayout::update: Disabling excessive guest-screen %d\n", iGuestScreen));
-            display.SetVideoModeHint(iGuestScreen, false, false, 0, 0, 0, 0, 0);
+            m_pMachineLogic->display().SetVideoModeHint(iGuestScreen, false, false, 0, 0, 0, 0, 0);
             m_pMachineLogic->uisession()->setScreenVisibleHostDesires(iGuestScreen, false);
         }
     }
@@ -163,7 +164,7 @@ void UIMultiScreenLayout::update()
             /* Re-enable guest-screen with proper resolution: */
             LogRel(("GUI: UIMultiScreenLayout::update: Enabling guest-screen %d with following resolution: %dx%d\n",
                     iGuestScreen, uWidth, uHeight));
-            display.SetVideoModeHint(iGuestScreen, true, false, 0, 0, uWidth, uHeight, 32);
+            m_pMachineLogic->display().SetVideoModeHint(iGuestScreen, true, false, 0, 0, uWidth, uHeight, 32);
             m_pMachineLogic->uisession()->setScreenVisibleHostDesires(iGuestScreen, true);
         }
     }
@@ -226,10 +227,9 @@ void UIMultiScreenLayout::sltHandleScreenLayoutChange(int iRequestedGuestScreen,
 
     /* Check the memory requirements first: */
     bool fSuccess = true;
-    CMachine machine = m_pMachineLogic->session().GetMachine();
     if (m_pMachineLogic->uisession()->isGuestSupportsGraphics())
     {
-        quint64 availBits = machine.GetVRAMSize() * _1M * 8;
+        quint64 availBits = m_pMachineLogic->machine().GetVRAMSize() * _1M * 8;
         quint64 usedBits = memoryRequirements(tmpMap);
         fSuccess = availBits >= usedBits;
         if (!fSuccess)
@@ -262,12 +262,10 @@ void UIMultiScreenLayout::calculateHostMonitorCount()
 
 void UIMultiScreenLayout::calculateGuestScreenCount()
 {
-    /* Get machine: */
-    CMachine machine = m_pMachineLogic->session().GetMachine();
     /* Enumerate all the guest screens: */
     m_guestScreens.clear();
     m_disabledGuestScreens.clear();
-    for (uint iGuestScreen = 0; iGuestScreen < machine.GetMonitorCount(); ++iGuestScreen)
+    for (uint iGuestScreen = 0; iGuestScreen < m_cGuestScreens; ++iGuestScreen)
         if (m_pMachineLogic->uisession()->isScreenVisible(iGuestScreen))
             m_guestScreens << iGuestScreen;
         else
@@ -291,7 +289,6 @@ quint64 UIMultiScreenLayout::memoryRequirements(const QMap<int, int> &screenLayo
     LONG xOrigin = 0;
     LONG yOrigin = 0;
     quint64 usedBits = 0;
-    CDisplay display = m_pMachineLogic->uisession()->session().GetConsole().GetDisplay();
     foreach (int iGuestScreen, m_guestScreens)
     {
         QRect screen;
@@ -300,7 +297,7 @@ quint64 UIMultiScreenLayout::memoryRequirements(const QMap<int, int> &screenLayo
         else
             screen = gpDesktop->screenGeometry(screenLayout.value(iGuestScreen, 0));
         KGuestMonitorStatus monitorStatus = KGuestMonitorStatus_Enabled;
-        display.GetScreenResolution(iGuestScreen, width, height, guestBpp, xOrigin, yOrigin, monitorStatus);
+        m_pMachineLogic->display().GetScreenResolution(iGuestScreen, width, height, guestBpp, xOrigin, yOrigin, monitorStatus);
         usedBits += screen.width() * /* display width */
                     screen.height() * /* display height */
                     guestBpp + /* guest bits per pixel */
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.h b/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.h
index 0c28fe7..56a38be 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.h
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.h
@@ -74,6 +74,7 @@ private:
     UIMachineLogic *m_pMachineLogic;
     QList<int> m_guestScreens;
     QList<int> m_disabledGuestScreens;
+    const uint m_cGuestScreens;
     int m_cHostScreens;
     QMap<int, int> m_screenMap;
     QList<QMenu*> m_screenMenuList;
diff --git a/src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp b/src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp
index cb8d42f..0352a37 100644
--- a/src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp
@@ -558,7 +558,7 @@ void VBoxSnapshotsWgt::onCurrentChanged (QTreeWidgetItem *aItem)
                                       (item && !mCurSnapshotItem)));
 
     /* Enable/disable cloning snapshots */
-    mCloneSnapshotAction->setEnabled(!busy && item);
+    mCloneSnapshotAction->setEnabled(item && (!item->isCurrentStateItem() || !busy));
 }
 
 void VBoxSnapshotsWgt::onContextMenuRequested (const QPoint &aPoint)
diff --git a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp
index d093b1a..7827e8e 100644
--- a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp
@@ -115,12 +115,12 @@ static const osTypePattern gs_OSTypePattern[] =
     { QRegExp("((Mac)|(Tig)|(Leop)|(Yose)|(os[ ]*x)).*32",                                      Qt::CaseInsensitive), "MacOS" },
 
     /* Code names for Linux distributions: */
-    { QRegExp("((bianca)|(cassandra)|(celena)|(daryna)|(elyssa)|(felicia)|(gloria)|(helena)|(isadora)|(julia)|(katya)|(lisa)|(maya)|(nadia)|(olivia)|(petra)|(qiana)|(rebecca)|(rafaela)|(rosa)).*64",    Qt::CaseInsensitive), "Ubuntu_64" },
-    { QRegExp("((bianca)|(cassandra)|(celena)|(daryna)|(elyssa)|(felicia)|(gloria)|(helena)|(isadora)|(julia)|(katya)|(lisa)|(maya)|(nadia)|(olivia)|(petra)|(qiana)|(rebecca)|(rafaela)|(rosa)).*32",    Qt::CaseInsensitive), "Ubuntu" },
-    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)|(saucy)|(trusty)|(utopic)|(vivid)|(wily)|(xenial)).*64",    Qt::CaseInsensitive), "Ubuntu_64" },
-    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)|(saucy)|(trusty)|(utopic)|(vivid)|(wily)|(xenial)).*32",    Qt::CaseInsensitive), "Ubuntu" },
-    { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(sid)).*64",                                                                          Qt::CaseInsensitive), "Debian_64" },
-    { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(sid)).*32",                                                                          Qt::CaseInsensitive), "Debian" },
+    { QRegExp("((bianca)|(cassandra)|(celena)|(daryna)|(elyssa)|(felicia)|(gloria)|(helena)|(isadora)|(julia)|(katya)|(lisa)|(maya)|(nadia)|(olivia)|(petra)|(qiana)|(rebecca)|(rafaela)|(rosa)).*64", Qt::CaseInsensitive), "Ubuntu_64" },
+    { QRegExp("((bianca)|(cassandra)|(celena)|(daryna)|(elyssa)|(felicia)|(gloria)|(helena)|(isadora)|(julia)|(katya)|(lisa)|(maya)|(nadia)|(olivia)|(petra)|(qiana)|(rebecca)|(rafaela)|(rosa)).*32", Qt::CaseInsensitive), "Ubuntu" },
+    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)|(saucy)|(trusty)|(utopic)|(vivid)|(wily)|(xenial)|(yakkety)|(zesty)).*64", Qt::CaseInsensitive), "Ubuntu_64" },
+    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)|(saucy)|(trusty)|(utopic)|(vivid)|(wily)|(xenial)|(yakkety)|(zesty)).*32", Qt::CaseInsensitive), "Ubuntu" },
+    { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(stretch)|(buster)|(sid)).*64", Qt::CaseInsensitive), "Debian_64" },
+    { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(stretch)|(buster)|(sid)).*32", Qt::CaseInsensitive), "Debian" },
     { QRegExp("((moonshine)|(werewolf)|(sulphur)|(cambridge)|(leonidas)|(constantine)|(goddard)|(laughlin)|(lovelock)|(verne)|(beefy)|(spherical)).*64", Qt::CaseInsensitive), "Fedora_64" },
     { QRegExp("((moonshine)|(werewolf)|(sulphur)|(cambridge)|(leonidas)|(constantine)|(goddard)|(laughlin)|(lovelock)|(verne)|(beefy)|(spherical)).*32", Qt::CaseInsensitive), "Fedora" },
 
diff --git a/src/VBox/HostServices/SharedFolders/shflhandle.h b/src/VBox/HostServices/SharedFolders/shflhandle.h
index 8a0ea63..ba25f9c 100644
--- a/src/VBox/HostServices/SharedFolders/shflhandle.h
+++ b/src/VBox/HostServices/SharedFolders/shflhandle.h
@@ -43,6 +43,7 @@ typedef struct _SHFLHANDLEHDR
 typedef struct _SHFLFILEHANDLE
 {
     SHFLHANDLEHDR Header;
+    SHFLROOT root; /* Where the handle has been opened. */
     union
     {
         struct
diff --git a/src/VBox/HostServices/SharedFolders/vbsf.cpp b/src/VBox/HostServices/SharedFolders/vbsf.cpp
index 46f636a..6af14fb 100644
--- a/src/VBox/HostServices/SharedFolders/vbsf.cpp
+++ b/src/VBox/HostServices/SharedFolders/vbsf.cpp
@@ -142,15 +142,62 @@ static void vbsfFreeFullPath(char *pszFullPath)
     vbsfFreeHostPath(pszFullPath);
 }
 
+typedef enum VBSFCHECKACCESS
+{
+    VBSF_CHECK_ACCESS_READ = 0,
+    VBSF_CHECK_ACCESS_WRITE = 1
+} VBSFCHECKACCESS;
+
+/**
+ * Check if the handle data is valid and the operation is allowed on the shared folder.
+ *
+ * @returns IPRT status code
+ * @param  pClient               Data structure describing the client accessing the shared folder
+ * @param  root                  The index of the shared folder in the table of mappings.
+ * @param  pHandle               Information about the file or directory object.
+ * @param  enmCheckAccess        Whether the operation needs read only or write access.
+ */
+static int vbsfCheckHandleAccess(SHFLCLIENTDATA *pClient, SHFLROOT root,
+                                 SHFLFILEHANDLE *pHandle, VBSFCHECKACCESS enmCheckAccess)
+{
+    /* Handle from the same 'root' index? */
+    if (RT_LIKELY(RT_VALID_PTR(pHandle) && root == pHandle->root))
+    { /* likely */ }
+    else
+        return VERR_INVALID_HANDLE;
+
+    /* Check if the guest is still allowed to access this share.
+     * vbsfMappingsQueryWritable returns error if the shared folder has been removed from the VM settings.
+     */
+    bool fWritable;
+    int rc = vbsfMappingsQueryWritable(pClient, root, &fWritable);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return VERR_ACCESS_DENIED;
+
+    if (enmCheckAccess == VBSF_CHECK_ACCESS_WRITE)
+    {
+        /* Operation requires write access. Check if the shared folder is writable too. */
+        if (RT_LIKELY(fWritable))
+        { /* likely */ }
+        else
+            return VERR_WRITE_PROTECT;
+    }
+
+    return VINF_SUCCESS;
+}
+
 /**
  * Convert shared folder create flags (see include/iprt/shflsvc.h) into iprt create flags.
  *
  * @returns iprt status code
+ * @param  fWritable  whether the shared folder is writable
  * @param  fShflFlags shared folder create flags
  * @param  fMode      file attributes
  * @retval pfOpen     iprt create flags
  */
-static int vbsfConvertFileOpenFlags(unsigned fShflFlags, RTFMODE fMode, SHFLHANDLE handleInitial, uint32_t *pfOpen)
+static int vbsfConvertFileOpenFlags(bool fWritable, unsigned fShflFlags, RTFMODE fMode, SHFLHANDLE handleInitial, uint32_t *pfOpen)
 {
     uint32_t fOpen = 0;
     int rc = VINF_SUCCESS;
@@ -366,6 +413,9 @@ static int vbsfConvertFileOpenFlags(unsigned fShflFlags, RTFMODE fMode, SHFLHAND
 
     if (RT_SUCCESS(rc))
     {
+        if (!fWritable)
+            fOpen &= ~RTFILE_O_WRITE;
+
         *pfOpen = fOpen;
     }
     return rc;
@@ -376,6 +426,7 @@ static int vbsfConvertFileOpenFlags(unsigned fShflFlags, RTFMODE fMode, SHFLHAND
  *
  * @returns IPRT status code
  * @param  pClient               Data structure describing the client accessing the shared folder
+ * @param  root                  The index of the shared folder in the table of mappings.
  * @param  pszPath               Path to the file or folder on the host.
  * @param  pParms->CreateFlags   Creation or open parameters, see include/VBox/shflsvc.h
  * @param  pParms->Info          When a new file is created this specifies the initial parameters.
@@ -386,7 +437,7 @@ static int vbsfConvertFileOpenFlags(unsigned fShflFlags, RTFMODE fMode, SHFLHAND
  *                               created
  * @retval pParms->Info          On success the parameters of the file opened or created
  */
-static int vbsfOpenFile(SHFLCLIENTDATA *pClient, const char *pszPath, SHFLCREATEPARMS *pParms)
+static int vbsfOpenFile(SHFLCLIENTDATA *pClient, SHFLROOT root, const char *pszPath, SHFLCREATEPARMS *pParms)
 {
     LogFlow(("vbsfOpenFile: pszPath = %s, pParms = %p\n", pszPath, pParms));
     Log(("SHFL create flags %08x\n", pParms->CreateFlags));
@@ -398,7 +449,13 @@ static int vbsfOpenFile(SHFLCLIENTDATA *pClient, const char *pszPath, SHFLCREATE
     bool fNoError = false;
     static int cErrors;
 
-    int rc = vbsfConvertFileOpenFlags(pParms->CreateFlags, pParms->Info.Attr.fMode, pParms->Handle, &fOpen);
+    /* is the guest allowed to write to this share? */
+    bool fWritable;
+    int rc = vbsfMappingsQueryWritable(pClient, root, &fWritable);
+    if (RT_FAILURE(rc))
+        fWritable = false;
+
+    rc = vbsfConvertFileOpenFlags(fWritable, pParms->CreateFlags, pParms->Info.Attr.fMode, pParms->Handle, &fOpen);
     if (RT_SUCCESS(rc))
     {
         rc = VERR_NO_MEMORY;  /* Default error. */
@@ -408,6 +465,7 @@ static int vbsfOpenFile(SHFLCLIENTDATA *pClient, const char *pszPath, SHFLCREATE
             pHandle = vbsfQueryFileHandle(pClient, handle);
             if (pHandle)
             {
+                pHandle->root = root;
                 rc = RTFileOpen(&pHandle->file.Handle, pszPath, fOpen);
             }
         }
@@ -550,6 +608,7 @@ static int vbsfOpenFile(SHFLCLIENTDATA *pClient, const char *pszPath, SHFLCREATE
  * Open a folder or create and open a new one.
  *
  * @returns IPRT status code
+ * @param  root                  The index of the shared folder in the table of mappings.
  * @param  pszPath               Path to the file or folder on the host.
  * @param  pParms->CreateFlags   Creation or open parameters, see include/VBox/shflsvc.h
  * @retval pParms->Result        Shared folder status code, see include/VBox/shflsvc.h
@@ -559,7 +618,7 @@ static int vbsfOpenFile(SHFLCLIENTDATA *pClient, const char *pszPath, SHFLCREATE
  *
  * @note folders are created with fMode = 0777
  */
-static int vbsfOpenDir(SHFLCLIENTDATA *pClient, const char *pszPath,
+static int vbsfOpenDir(SHFLCLIENTDATA *pClient, SHFLROOT root, const char *pszPath,
                        SHFLCREATEPARMS *pParms)
 {
     LogFlow(("vbsfOpenDir: pszPath = %s, pParms = %p\n", pszPath, pParms));
@@ -570,6 +629,7 @@ static int vbsfOpenDir(SHFLCLIENTDATA *pClient, const char *pszPath,
     SHFLFILEHANDLE *pHandle = vbsfQueryDirHandle(pClient, handle);
     if (0 != pHandle)
     {
+        pHandle->root = root;
         rc = VINF_SUCCESS;
         pParms->Result = SHFL_FILE_EXISTS;  /* May be overwritten with SHFL_FILE_CREATED. */
         /** @todo Can anyone think of a sensible, race-less way to do this?  Although
@@ -869,11 +929,11 @@ int vbsfCreate(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint32
             {
                 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))
                 {
-                    rc = vbsfOpenDir(pClient, pszFullPath, pParms);
+                    rc = vbsfOpenDir(pClient, root, pszFullPath, pParms);
                 }
                 else
                 {
-                    rc = vbsfOpenFile(pClient, pszFullPath, pParms);
+                    rc = vbsfOpenFile(pClient, root, pszFullPath, pParms);
                 }
             }
             else
@@ -904,34 +964,39 @@ void testClose(RTTEST hTest)
 
 int vbsfClose(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle)
 {
-    RT_NOREF1(root);
-    int rc = VINF_SUCCESS;
-
-    LogFlow(("vbsfClose: pClient = %p, Handle = %RX64\n",
-             pClient, Handle));
+    LogFunc(("pClient = %p, root 0x%RX32, Handle = 0x%RX64\n",
+             pClient, root, Handle));
 
+    int rc = VERR_INVALID_HANDLE;
     uint32_t type = vbsfQueryHandleType(pClient, Handle);
     Assert((type & ~(SHFL_HF_TYPE_DIR | SHFL_HF_TYPE_FILE)) == 0);
-
     switch (type & (SHFL_HF_TYPE_DIR | SHFL_HF_TYPE_FILE))
     {
         case SHFL_HF_TYPE_DIR:
         {
-            rc = vbsfCloseDir(vbsfQueryDirHandle(pClient, Handle));
+            SHFLFILEHANDLE *pHandle = vbsfQueryDirHandle(pClient, Handle);
+            if (RT_LIKELY(pHandle && root == pHandle->root))
+            {
+                rc = vbsfCloseDir(pHandle);
+                vbsfFreeFileHandle(pClient, Handle);
+            }
             break;
         }
         case SHFL_HF_TYPE_FILE:
         {
-            rc = vbsfCloseFile(vbsfQueryFileHandle(pClient, Handle));
+            SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
+            if (RT_LIKELY(pHandle && root == pHandle->root))
+            {
+                rc = vbsfCloseFile(pHandle);
+                vbsfFreeFileHandle(pClient, Handle);
+            }
             break;
         }
         default:
-            return VERR_INVALID_HANDLE;
+            break;
     }
-    vbsfFreeFileHandle(pClient, Handle);
-
-    Log(("vbsfClose: rc = %Rrc\n", rc));
 
+    LogFunc(("rc = %Rrc\n", rc));
     return rc;
 }
 
@@ -947,41 +1012,39 @@ void testRead(RTTEST hTest)
     /* Add tests as required... */
 }
 #endif
-int vbsfRead  (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
+int vbsfRead(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
 {
+    LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64, offset 0x%RX64, bytes 0x%RX32\n",
+             pClient, root, Handle, offset, pcbBuffer? *pcbBuffer: 0));
+
+    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
+
     SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-    size_t count = 0;
-    int rc;
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_READ);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
 
-    if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
+    if (RT_LIKELY(*pcbBuffer != 0))
     {
-        AssertFailed();
-        return VERR_INVALID_PARAMETER;
+        rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
+        if (RT_SUCCESS(rc))
+        {
+            size_t count = 0;
+            rc = RTFileRead(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
+            *pcbBuffer = (uint32_t)count;
+        }
+        else
+            AssertRC(rc);
     }
-
-    Log(("vbsfRead %RX64 offset %RX64 bytes %x\n", Handle, offset, *pcbBuffer));
-
-    /* Is the guest allowed to access this share?
-     * Checked here because the shared folder can be removed from the VM settings. */
-    bool fWritable;
-    rc = vbsfMappingsQueryWritable(pClient, root, &fWritable);
-    if (RT_FAILURE(rc))
-        return VERR_ACCESS_DENIED;
-
-    if (*pcbBuffer == 0)
-        return VINF_SUCCESS; /** @todo correct? */
-
-
-    rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
-    if (rc != VINF_SUCCESS)
+    else
     {
-        AssertRC(rc);
-        return rc;
+        /* Reading zero bytes always succeeds. */
+        rc = VINF_SUCCESS;
     }
 
-    rc = RTFileRead(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
-    *pcbBuffer = (uint32_t)count;
-    Log(("RTFileRead returned %Rrc bytes read %x\n", rc, count));
+    LogFunc(("%Rrc bytes read 0x%RX32\n", rc, *pcbBuffer));
     return rc;
 }
 
@@ -999,38 +1062,37 @@ void testWrite(RTTEST hTest)
 #endif
 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
 {
+    LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64, offset 0x%RX64, bytes 0x%RX32\n",
+             pClient, root, Handle, offset, pcbBuffer? *pcbBuffer: 0));
+
+    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
+
     SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-    size_t count = 0;
-    int rc;
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
 
-    if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
+    if (RT_LIKELY(*pcbBuffer != 0))
     {
-        AssertFailed();
-        return VERR_INVALID_PARAMETER;
+        rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
+        if (RT_SUCCESS(rc))
+        {
+            size_t count = 0;
+            rc = RTFileWrite(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
+            *pcbBuffer = (uint32_t)count;
+        }
+        else
+            AssertRC(rc);
     }
-
-    Log(("vbsfWrite %RX64 offset %RX64 bytes %x\n", Handle, offset, *pcbBuffer));
-
-    /* Is the guest allowed to write to this share?
-     * Checked here because the shared folder can be removed from the VM settings. */
-    bool fWritable;
-    rc = vbsfMappingsQueryWritable(pClient, root, &fWritable);
-    if (RT_FAILURE(rc) || !fWritable)
-        return VERR_WRITE_PROTECT;
-
-    if (*pcbBuffer == 0)
-        return VINF_SUCCESS; /** @todo correct? */
-
-    rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
-    if (rc != VINF_SUCCESS)
+    else
     {
-        AssertRC(rc);
-        return rc;
+        /** @todo: What writing zero bytes should do? */
+        rc = VINF_SUCCESS;
     }
 
-    rc = RTFileWrite(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
-    *pcbBuffer = (uint32_t)count;
-    Log(("RTFileWrite returned %Rrc bytes written %x\n", rc, count));
+    LogFunc(("%Rrc bytes written 0x%RX32\n", rc, *pcbBuffer));
     return rc;
 }
 
@@ -1050,19 +1112,21 @@ void testFlush(RTTEST hTest)
 
 int vbsfFlush(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle)
 {
-    RT_NOREF1(root);
-    SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-    int rc = VINF_SUCCESS;
+    LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64\n",
+             pClient, root, Handle));
 
-    if (pHandle == 0)
-    {
-        AssertFailed();
-        return VERR_INVALID_HANDLE;
-    }
+    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
+
+    SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
 
-    Log(("vbsfFlush %RX64\n", Handle));
     rc = RTFileFlush(pHandle->file.Handle);
-    AssertRC(rc);
+
+    LogFunc(("%Rrc\n", rc));
     return rc;
 }
 
@@ -1081,31 +1145,23 @@ void testDirList(RTTEST hTest)
 int vbsfDirList(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, SHFLSTRING *pPath, uint32_t flags,
                 uint32_t *pcbBuffer, uint8_t *pBuffer, uint32_t *pIndex, uint32_t *pcFiles)
 {
-    SHFLFILEHANDLE *pHandle = vbsfQueryDirHandle(pClient, Handle);
     PRTDIRENTRYEX  pDirEntry = 0, pDirEntryOrg;
     uint32_t       cbDirEntry, cbBufferOrg;
-    int            rc = VINF_SUCCESS;
     PSHFLDIRINFO   pSFDEntry;
     PRTUTF16       pwszString;
     PRTDIR         DirHandle;
-    bool           fUtf8;
+    const bool     fUtf8 = BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8) != 0;
 
-    fUtf8 = BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8) != 0;
+    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
 
-    if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
-    {
-        AssertFailed();
-        return VERR_INVALID_PARAMETER;
-    }
-
-    /* Is the guest allowed to access this share?
-     * Checked here because the shared folder can be removed from the VM settings. */
-    bool fWritable;
-    rc = vbsfMappingsQueryWritable(pClient, root, &fWritable);
-    if (RT_FAILURE(rc))
-        return VERR_ACCESS_DENIED;
+    SHFLFILEHANDLE *pHandle = vbsfQueryDirHandle(pClient, Handle);
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_READ);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
 
-    Assert(pIndex && *pIndex == 0);
+    Assert(*pIndex == 0);
     DirHandle = pHandle->dir.Handle;
 
     cbDirEntry = 4096;
@@ -1344,7 +1400,7 @@ int vbsfReadLink(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint
 int vbsfQueryFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags,
                       uint32_t *pcbBuffer, uint8_t *pBuffer)
 {
-    RT_NOREF2(root, flags);
+    RT_NOREF1(flags);
     uint32_t type = vbsfQueryHandleType(pClient, Handle);
     int            rc = VINF_SUCCESS;
     SHFLFSOBJINFO   *pObjInfo = (SHFLFSOBJINFO *)pBuffer;
@@ -1368,12 +1424,16 @@ int vbsfQueryFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle,
     if (type == SHFL_HF_TYPE_DIR)
     {
         SHFLFILEHANDLE *pHandle = vbsfQueryDirHandle(pClient, Handle);
-        rc = RTDirQueryInfo(pHandle->dir.Handle, &fileinfo, RTFSOBJATTRADD_NOTHING);
+        rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_READ);
+        if (RT_SUCCESS(rc))
+            rc = RTDirQueryInfo(pHandle->dir.Handle, &fileinfo, RTFSOBJATTRADD_NOTHING);
     }
     else
     {
         SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-        rc = RTFileQueryInfo(pHandle->file.Handle, &fileinfo, RTFSOBJATTRADD_NOTHING);
+        rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_READ);
+        if (RT_SUCCESS(rc))
+            rc = RTFileQueryInfo(pHandle->file.Handle, &fileinfo, RTFSOBJATTRADD_NOTHING);
 #ifdef RT_OS_WINDOWS
         if (RT_SUCCESS(rc) && RTFS_IS_FILE(pObjInfo->Attr.fMode))
             pObjInfo->Attr.fMode |= 0111;
@@ -1393,7 +1453,7 @@ int vbsfQueryFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle,
 static int vbsfSetFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags,
                            uint32_t *pcbBuffer, uint8_t *pBuffer)
 {
-    RT_NOREF2(root, flags);
+    RT_NOREF1(flags);
     uint32_t type = vbsfQueryHandleType(pClient, Handle);
     int             rc = VINF_SUCCESS;
     SHFLFSOBJINFO  *pSFDEntry;
@@ -1416,22 +1476,26 @@ static int vbsfSetFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Ha
     if (type == SHFL_HF_TYPE_DIR)
     {
         SHFLFILEHANDLE *pHandle = vbsfQueryDirHandle(pClient, Handle);
-        rc = RTDirSetTimes(pHandle->dir.Handle,
-                            (RTTimeSpecGetNano(&pSFDEntry->AccessTime)) ?       &pSFDEntry->AccessTime : NULL,
-                            (RTTimeSpecGetNano(&pSFDEntry->ModificationTime)) ? &pSFDEntry->ModificationTime: NULL,
-                            (RTTimeSpecGetNano(&pSFDEntry->ChangeTime)) ?       &pSFDEntry->ChangeTime: NULL,
-                            (RTTimeSpecGetNano(&pSFDEntry->BirthTime)) ?        &pSFDEntry->BirthTime: NULL
-                            );
+        rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
+        if (RT_SUCCESS(rc))
+            rc = RTDirSetTimes(pHandle->dir.Handle,
+                                (RTTimeSpecGetNano(&pSFDEntry->AccessTime)) ?       &pSFDEntry->AccessTime : NULL,
+                                (RTTimeSpecGetNano(&pSFDEntry->ModificationTime)) ? &pSFDEntry->ModificationTime: NULL,
+                                (RTTimeSpecGetNano(&pSFDEntry->ChangeTime)) ?       &pSFDEntry->ChangeTime: NULL,
+                                (RTTimeSpecGetNano(&pSFDEntry->BirthTime)) ?        &pSFDEntry->BirthTime: NULL
+                                );
     }
     else
     {
         SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-        rc = RTFileSetTimes(pHandle->file.Handle,
-                            (RTTimeSpecGetNano(&pSFDEntry->AccessTime)) ?       &pSFDEntry->AccessTime : NULL,
-                            (RTTimeSpecGetNano(&pSFDEntry->ModificationTime)) ? &pSFDEntry->ModificationTime: NULL,
-                            (RTTimeSpecGetNano(&pSFDEntry->ChangeTime)) ?       &pSFDEntry->ChangeTime: NULL,
-                            (RTTimeSpecGetNano(&pSFDEntry->BirthTime)) ?        &pSFDEntry->BirthTime: NULL
-                            );
+        rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
+        if (RT_SUCCESS(rc))
+            rc = RTFileSetTimes(pHandle->file.Handle,
+                                 (RTTimeSpecGetNano(&pSFDEntry->AccessTime)) ?       &pSFDEntry->AccessTime : NULL,
+                                 (RTTimeSpecGetNano(&pSFDEntry->ModificationTime)) ? &pSFDEntry->ModificationTime: NULL,
+                                 (RTTimeSpecGetNano(&pSFDEntry->ChangeTime)) ?       &pSFDEntry->ChangeTime: NULL,
+                                 (RTTimeSpecGetNano(&pSFDEntry->BirthTime)) ?        &pSFDEntry->BirthTime: NULL
+                                 );
     }
     if (rc != VINF_SUCCESS)
     {
@@ -1447,24 +1511,28 @@ static int vbsfSetFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Ha
     if (type == SHFL_HF_TYPE_FILE)
     {
         SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-        /* Change file attributes if necessary */
-        if (pSFDEntry->Attr.fMode)
+        rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
+        if (RT_SUCCESS(rc))
         {
-            RTFMODE fMode = pSFDEntry->Attr.fMode;
+            /* Change file attributes if necessary */
+            if (pSFDEntry->Attr.fMode)
+            {
+                RTFMODE fMode = pSFDEntry->Attr.fMode;
 
 #ifndef RT_OS_WINDOWS
-            /* Don't allow the guest to clear the own bit, otherwise the guest wouldn't be
-             * able to access this file anymore. Only for guests, which set the UNIX mode. */
-            if (fMode & RTFS_UNIX_MASK)
-                fMode |= RTFS_UNIX_IRUSR;
+                /* Don't allow the guest to clear the own bit, otherwise the guest wouldn't be
+                 * able to access this file anymore. Only for guests, which set the UNIX mode. */
+                if (fMode & RTFS_UNIX_MASK)
+                    fMode |= RTFS_UNIX_IRUSR;
 #endif
 
-            rc = RTFileSetMode(pHandle->file.Handle, fMode);
-            if (rc != VINF_SUCCESS)
-            {
-                Log(("RTFileSetMode %x failed with %Rrc\n", fMode, rc));
-                /* silent failure, because this tends to fail with e.g. windows guest & linux host */
-                rc = VINF_SUCCESS;
+                rc = RTFileSetMode(pHandle->file.Handle, fMode);
+                if (rc != VINF_SUCCESS)
+                {
+                    Log(("RTFileSetMode %x failed with %Rrc\n", fMode, rc));
+                    /* silent failure, because this tends to fail with e.g. windows guest & linux host */
+                    rc = VINF_SUCCESS;
+                }
             }
         }
     }
@@ -1490,9 +1558,8 @@ static int vbsfSetFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Ha
 static int vbsfSetEndOfFile(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags,
                             uint32_t *pcbBuffer, uint8_t *pBuffer)
 {
-    RT_NOREF2(root, flags);
+    RT_NOREF1(flags);
     SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-    int             rc = VINF_SUCCESS;
     SHFLFSOBJINFO  *pSFDEntry;
 
     if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0 || *pcbBuffer < sizeof(SHFLFSOBJINFO))
@@ -1501,6 +1568,12 @@ static int vbsfSetEndOfFile(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE H
         return VERR_INVALID_PARAMETER;
     }
 
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
+
     *pcbBuffer  = 0;
     pSFDEntry   = (SHFLFSOBJINFO *)pBuffer;
 
@@ -1632,12 +1705,6 @@ int vbsfSetFSInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uin
         return VERR_INVALID_PARAMETER;
     }
 
-    /* is the guest allowed to write to this share? */
-    bool fWritable;
-    int rc = vbsfMappingsQueryWritable(pClient, root, &fWritable);
-    if (RT_FAILURE(rc) || !fWritable)
-        return VERR_WRITE_PROTECT;
-
     if (flags & SHFL_INFO_FILE)
         return vbsfSetFileInfo(pClient, root, Handle, flags, pcbBuffer, pBuffer);
 
@@ -1665,18 +1732,17 @@ void testLock(RTTEST hTest)
 
 int vbsfLock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags)
 {
-    RT_NOREF1(root);
     SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
     uint32_t        fRTLock = 0;
-    int             rc;
 
     Assert((flags & SHFL_LOCK_MODE_MASK) != SHFL_LOCK_CANCEL);
 
-    if (pHandle == 0)
-    {
-        AssertFailed();
-        return VERR_INVALID_HANDLE;
-    }
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_READ);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
+
     if (   ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL)
         || (flags & SHFL_LOCK_ENTIRE)
        )
@@ -1721,16 +1787,16 @@ int vbsfLock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t
 
 int vbsfUnlock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags)
 {
-    RT_NOREF1(root);
     SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
-    int             rc;
 
     Assert((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL);
 
-    if (pHandle == 0)
-    {
-        return VERR_INVALID_HANDLE;
-    }
+    int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_READ);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else
+        return rc;
+
     if (   ((flags & SHFL_LOCK_MODE_MASK) != SHFL_LOCK_CANCEL)
         || (flags & SHFL_LOCK_ENTIRE)
        )
@@ -1943,13 +2009,32 @@ int vbsfSymlink(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pNewPath, SH
  */
 int vbsfDisconnect(SHFLCLIENTDATA *pClient)
 {
-    for (int i=0; i<SHFLHANDLE_MAX; i++)
+    for (int i = 0; i < SHFLHANDLE_MAX; ++i)
     {
+        SHFLFILEHANDLE *pHandle = NULL;
         SHFLHANDLE Handle = (SHFLHANDLE)i;
-        if (vbsfQueryHandleType(pClient, Handle))
+
+        uint32_t type = vbsfQueryHandleType(pClient, Handle);
+        switch (type & (SHFL_HF_TYPE_DIR | SHFL_HF_TYPE_FILE))
+        {
+            case SHFL_HF_TYPE_DIR:
+            {
+                pHandle = vbsfQueryDirHandle(pClient, Handle);
+                break;
+            }
+            case SHFL_HF_TYPE_FILE:
+            {
+                pHandle = vbsfQueryFileHandle(pClient, Handle);
+                break;
+            }
+            default:
+                break;
+        }
+
+        if (pHandle)
         {
-            Log(("Open handle %08x\n", i));
-            vbsfClose(pClient, SHFL_HANDLE_ROOT /* incorrect, but it's not important */, (SHFLHANDLE)i);
+            LogFunc(("Opened handle 0x%08x\n", i));
+            vbsfClose(pClient, pHandle->root, Handle);
         }
     }
     return VINF_SUCCESS;
diff --git a/src/VBox/Main/include/GuestSessionImpl.h b/src/VBox/Main/include/GuestSessionImpl.h
index 9f6db7e..1de95db 100644
--- a/src/VBox/Main/include/GuestSessionImpl.h
+++ b/src/VBox/Main/include/GuestSessionImpl.h
@@ -467,8 +467,6 @@ public:
     static HRESULT          i_setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
     int                     i_setSessionStatus(GuestSessionStatus_T sessionStatus, int sessionRc);
     int                     i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */);
-    int                     i_startTaskAsync(const Utf8Str &strTaskDesc, GuestSessionTask *pTask,
-                                             ComObjPtr<Progress> &pProgress);
     int                     i_determineProtocolVersion(void);
     int                     i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc);
     int                     i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS,
diff --git a/src/VBox/Main/include/MachineImpl.h b/src/VBox/Main/include/MachineImpl.h
index 4512f13..e6c30a8 100644
--- a/src/VBox/Main/include/MachineImpl.h
+++ b/src/VBox/Main/include/MachineImpl.h
@@ -38,6 +38,7 @@
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
 #include "Performance.h"
 #include "PerformanceImpl.h"
+#include "ThreadTask.h"
 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
 // generated header
@@ -789,54 +790,32 @@ protected:
      * the static Machine::taskHandler, which then calls the handler() method
      * in here (implemented by the subclasses).
      */
-    struct Task
+    class Task : public ThreadTask
     {
+    public:
         Task(Machine *m, Progress *p, const Utf8Str &t)
-            : m_pMachine(m),
+            : ThreadTask(t),
+              m_pMachine(m),
               m_machineCaller(m),
               m_pProgress(p),
-              m_strTaskName(t),
               m_machineStateBackup(m->mData->mMachineState) // save the current machine state
         {}
         virtual ~Task(){}
 
-        HRESULT createThread()
-        {
-            int vrc = RTThreadCreate(NULL,
-                                     taskHandler,
-                                     (void *)this,
-                                     0,
-                                     RTTHREADTYPE_MAIN_WORKER,
-                                     0,
-                                     m_strTaskName.c_str());
-            if (RT_FAILURE(vrc))
-            {
-                HRESULT rc = Machine::i_setErrorStatic(E_FAIL, Machine::tr("Could not create thread \"%s\" (%Rrc)"), m_strTaskName.c_str(), vrc);
-                delete this;
-                return rc;
-            }
-            return S_OK;
-        }
-
         void modifyBackedUpState(MachineState_T s)
         {
             *const_cast<MachineState_T *>(&m_machineStateBackup) = s;
         }
 
-        virtual void handler() = 0;
-
-        ComObjPtr<Machine>       m_pMachine;
+        ComObjPtr<Machine>              m_pMachine;
         AutoCaller                      m_machineCaller;
         ComObjPtr<Progress>             m_pProgress;
-        Utf8Str                         m_strTaskName;
         const MachineState_T            m_machineStateBackup;
     };
 
-    struct DeleteConfigTask;
+    class DeleteConfigTask;
     void i_deleteConfigHandler(DeleteConfigTask &task);
 
-    static DECLCALLBACK(int) taskHandler(RTTHREAD thread, void *pvUser);
-
     friend class SessionMachine;
     friend class SnapshotMachine;
     friend class Appliance;
@@ -1436,15 +1415,11 @@ private:
         void *mDeleteSnapshotInfo;
     };
 
-    struct SaveStateTask;
-    struct SnapshotTask;
-    struct TakeSnapshotTask;
-    struct DeleteSnapshotTask;
-    struct RestoreSnapshotTask;
-
-    friend struct TakeSnapshotTask;
-    friend struct DeleteSnapshotTask;
-    friend struct RestoreSnapshotTask;
+    class SaveStateTask;
+    class SnapshotTask;
+    class TakeSnapshotTask;
+    class DeleteSnapshotTask;
+    class RestoreSnapshotTask;
 
     void i_saveStateHandler(SaveStateTask &aTask);
 
diff --git a/src/VBox/Main/include/ThreadTask.h b/src/VBox/Main/include/ThreadTask.h
index 35ab301..840cf7e 100644
--- a/src/VBox/Main/include/ThreadTask.h
+++ b/src/VBox/Main/include/ThreadTask.h
@@ -34,8 +34,7 @@ class ThreadTask
 {
 public:
     ThreadTask(const Utf8Str &t)
-        : m_hThread(NIL_RTTHREAD)
-        , m_strTaskName(t)
+        : m_strTaskName(t)
         , mAsync(false)
     { }
 
@@ -44,20 +43,17 @@ public:
 
     HRESULT createThread(void);
     HRESULT createThreadWithType(RTTHREADTYPE enmType);
-    HRESULT createThreadWithRaceCondition(PRTTHREAD pThread);
 
     inline Utf8Str getTaskName() const { return m_strTaskName; }
     bool isAsync() { return mAsync; }
 
 protected:
-    HRESULT createThreadInternal(RTTHREADTYPE enmType, PRTTHREAD pThread);
+    HRESULT createThreadInternal(RTTHREADTYPE enmType);
     static DECLCALLBACK(int) taskHandlerThreadProc(RTTHREAD thread, void *pvUser);
 
-    ThreadTask() : m_hThread(NIL_RTTHREAD), m_strTaskName("GenericTask")
+    ThreadTask() : m_strTaskName("GenericTask")
     { }
 
-    /** The worker thread handle (may be invalid if the thread has shut down). */
-    RTTHREAD m_hThread;
     Utf8Str m_strTaskName;
     bool mAsync;
 
diff --git a/src/VBox/Main/include/ovfreader.h b/src/VBox/Main/include/ovfreader.h
index e0ac7db..9809f63 100644
--- a/src/VBox/Main/include/ovfreader.h
+++ b/src/VBox/Main/include/ovfreader.h
@@ -346,6 +346,7 @@ public:
 
     VirtualHardwareItem()
         : ulInstanceID(0),
+          fResourceRequired(false),
           fAutomaticAllocation(false),
           fAutomaticDeallocation(false),
           ullVirtualQuantity(0),
@@ -353,7 +354,8 @@ public:
           ullLimit(0),
           ullWeight(0),
           ulBusNumber(0),
-          ulLineNumber(0)
+          ulLineNumber(0),
+          fDefault(false)
     {
         itemName = "Item";
     };
diff --git a/src/VBox/Main/src-all/ThreadTask.cpp b/src/VBox/Main/src-all/ThreadTask.cpp
index 282961d..b85cca8 100644
--- a/src/VBox/Main/src-all/ThreadTask.cpp
+++ b/src/VBox/Main/src-all/ThreadTask.cpp
@@ -46,11 +46,11 @@
         return pTask->createThread(); // pTask is always consumed
    @endcode
  *
- * @sa createThreadWithType, createThreadWithRaceCondition
+ * @sa createThreadWithType
  */
 HRESULT ThreadTask::createThread(void)
 {
-    return createThreadInternal(RTTHREADTYPE_MAIN_WORKER, NULL /*phThread*/);
+    return createThreadInternal(RTTHREADTYPE_MAIN_WORKER);
 }
 
 
@@ -61,33 +61,20 @@ HRESULT ThreadTask::createThread(void)
  */
 HRESULT ThreadTask::createThreadWithType(RTTHREADTYPE enmType)
 {
-    return createThreadInternal(enmType, NULL /*phThread*/);
-}
-
-
-/**
- * Same ThreadTask::createThread(), except it returns a thread handle.
- *
- * If the task thread is incorrectly mananged, the caller may easily race the
- * completion and termination of the task thread!  Use with care!
- *
- * @param   phThread    Handle of the worker thread.
- */
-HRESULT ThreadTask::createThreadWithRaceCondition(PRTTHREAD phThread)
-{
-    return createThreadInternal(RTTHREADTYPE_MAIN_WORKER, phThread);
+    return createThreadInternal(enmType);
 }
 
 
 /**
  * Internal worker for ThreadTask::createThread,
- * ThreadTask::createThreadWithType, ThreadTask::createThreadwithRaceCondition.
+ * ThreadTask::createThreadWithType.
  *
  * @note Always consumes @a this!
  */
-HRESULT ThreadTask::createThreadInternal(RTTHREADTYPE enmType, PRTTHREAD phThread)
+HRESULT ThreadTask::createThreadInternal(RTTHREADTYPE enmType)
 {
-    int vrc = RTThreadCreate(&m_hThread,
+    mAsync = true;
+    int vrc = RTThreadCreate(NULL,
                              taskHandlerThreadProc,
                              (void *)this,
                              0,
@@ -95,13 +82,9 @@ HRESULT ThreadTask::createThreadInternal(RTTHREADTYPE enmType, PRTTHREAD phThrea
                              0,
                              this->getTaskName().c_str());
     if (RT_SUCCESS(vrc))
-    {
-        mAsync = true;
-        if (phThread)
-            *phThread = m_hThread;
         return S_OK;
-    }
 
+    mAsync = false;
     delete this;
     return E_FAIL;
 }
@@ -123,7 +106,6 @@ HRESULT ThreadTask::createThreadInternal(RTTHREADTYPE enmType, PRTTHREAD phThrea
      */
     pTask->handler();
 
-    pTask->m_hThread = NIL_RTTHREAD; /* unnecessary, but whatever. */
     delete pTask;
     return VINF_SUCCESS;
 }
diff --git a/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp b/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
index 764cede..af476d6 100644
--- a/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
+++ b/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
@@ -570,10 +570,8 @@ void GuestDnDTarget::i_sendDataThreadTask(SendDataTask *pTask)
     if (FAILED(autoCaller.rc()))
         return;
 
-    int vrc = RTThreadUserSignal(RTThreadSelf());
-    AssertRC(vrc);
-
-    vrc = pThis->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
+    int vrc = pThis->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
+    NOREF(vrc);
 /** @todo
  *
  *  r=bird: What happens with @a vrc?
diff --git a/src/VBox/Main/src-client/GuestSessionImpl.cpp b/src/VBox/Main/src-client/GuestSessionImpl.cpp
index ca91abb..b77548f 100644
--- a/src/VBox/Main/src-client/GuestSessionImpl.cpp
+++ b/src/VBox/Main/src-client/GuestSessionImpl.cpp
@@ -2146,39 +2146,6 @@ int GuestSession::i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc
     return vrc;
 }
 
-int GuestSession::i_startTaskAsync(const Utf8Str &strTaskDesc,
-                                   GuestSessionTask *pTask, ComObjPtr<Progress> &pProgress)
-{
-    LogFlowThisFunc(("strTaskDesc=%s, pTask=%p\n", strTaskDesc.c_str(), pTask));
-
-    AssertPtrReturn(pTask, VERR_INVALID_POINTER);
-
-    /* Create the progress object. */
-    HRESULT hr = pProgress.createObject();
-    if (FAILED(hr))
-        return VERR_COM_UNEXPECTED;
-
-    hr = pProgress->init(static_cast<IGuestSession*>(this),
-                         Bstr(strTaskDesc).raw(),
-                         TRUE /* aCancelable */);
-    if (FAILED(hr))
-        return VERR_COM_UNEXPECTED;
-
-    /* Initialize our worker task. */
-    RT_GCC_NO_WARN_DEPRECATED_BEGIN
-    std::auto_ptr<GuestSessionTask> task(pTask);
-    RT_GCC_NO_WARN_DEPRECATED_END
-    int rc = task->RunAsync(strTaskDesc, pProgress);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    /* Don't destruct on success. */
-    task.release();
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
 /**
  * Determines the protocol version (sets mData.mProtocolVersion).
  *
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 094e80d..0198019 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -5255,9 +5255,10 @@ HRESULT Machine::unregister(AutoCaller &autoCaller,
 /**
  * Task record for deleting a machine config.
  */
-struct Machine::DeleteConfigTask
+class Machine::DeleteConfigTask
     : public Machine::Task
 {
+public:
     DeleteConfigTask(Machine *m,
                      Progress *p,
                      const Utf8Str &t,
@@ -5268,13 +5269,23 @@ struct Machine::DeleteConfigTask
           m_llFilesToDelete(llFilesToDelete)
     {}
 
+private:
     void handler()
     {
-        m_pMachine->i_deleteConfigHandler(*this);
+        try
+        {
+            m_pMachine->i_deleteConfigHandler(*this);
+        }
+        catch(...)
+        {
+            LogRel(("Some exception in the function Machine::i_deleteConfigHandler()\n"));
+        }
     }
 
     RTCList<ComPtr<IMedium> >   m_llMediums;
     StringsList                 m_llFilesToDelete;
+
+    friend void Machine::i_deleteConfigHandler(DeleteConfigTask &task);
 };
 
 /**
@@ -12845,9 +12856,10 @@ HRESULT SessionMachine::reportVmStatistics(ULONG aValidStats, ULONG aCpuUser,
 /**
  * Task record for saving the machine state.
  */
-struct SessionMachine::SaveStateTask
+class SessionMachine::SaveStateTask
     : public Machine::Task
 {
+public:
     SaveStateTask(SessionMachine *m,
                   Progress *p,
                   const Utf8Str &t,
@@ -12858,6 +12870,7 @@ struct SessionMachine::SaveStateTask
           m_strStateFilePath(strStateFilePath)
     {}
 
+private:
     void handler()
     {
         ((SessionMachine *)(Machine *)m_pMachine)->i_saveStateHandler(*this);
@@ -12865,6 +12878,8 @@ struct SessionMachine::SaveStateTask
 
     Reason_T m_enmReason;
     Utf8Str m_strStateFilePath;
+
+    friend class SessionMachine;
 };
 
 /**
@@ -14778,24 +14793,6 @@ HRESULT SessionMachine::i_updateMachineStateOnClient()
 }
 
 
-/**
- * Static Machine method that can get passed to RTThreadCreate to
- * have a thread started for a Task. See Machine::Task.
- */
-/* static */ DECLCALLBACK(int) Machine::taskHandler(RTTHREAD /* thread */, void *pvUser)
-{
-    AssertReturn(pvUser, VERR_INVALID_POINTER);
-
-    Task *pTask = static_cast<Task *>(pvUser);
-    pTask->handler();
-    /** @todo r=klaus it would be safer to update the progress object here,
-     * as it avoids possible races due to scoping issues/tricks in the handler */
-    // it's our responsibility to delete the task
-    delete pTask;
-
-    return 0;
-}
-
 /*static*/
 HRESULT Machine::i_setErrorStatic(HRESULT aResultCode, const char *pcszMsg, ...)
 {
diff --git a/src/VBox/Main/src-server/SnapshotImpl.cpp b/src/VBox/Main/src-server/SnapshotImpl.cpp
index 45e4e89..34e5d6f 100644
--- a/src/VBox/Main/src-server/SnapshotImpl.cpp
+++ b/src/VBox/Main/src-server/SnapshotImpl.cpp
@@ -1299,9 +1299,10 @@ HRESULT SnapshotMachine::i_onSnapshotChange(Snapshot *aSnapshot)
  * Still abstract base class for SessionMachine::TakeSnapshotTask,
  * SessionMachine::RestoreSnapshotTask and SessionMachine::DeleteSnapshotTask.
  */
-struct SessionMachine::SnapshotTask
+class SessionMachine::SnapshotTask
     : public SessionMachine::Task
 {
+public:
     SnapshotTask(SessionMachine *m,
                  Progress *p,
                  const Utf8Str &t,
@@ -1314,9 +1315,10 @@ struct SessionMachine::SnapshotTask
 };
 
 /** Take snapshot task */
-struct SessionMachine::TakeSnapshotTask
+class SessionMachine::TakeSnapshotTask
     : public SessionMachine::SnapshotTask
 {
+public:
     TakeSnapshotTask(SessionMachine *m,
                      Progress *p,
                      const Utf8Str &t,
@@ -1343,9 +1345,17 @@ struct SessionMachine::TakeSnapshotTask
             m_fPause = false;
     }
 
+private:
     void handler()
     {
-        ((SessionMachine *)(Machine *)m_pMachine)->i_takeSnapshotHandler(*this);
+        try
+        {
+            ((SessionMachine *)(Machine *)m_pMachine)->i_takeSnapshotHandler(*this);
+        }
+        catch(...)
+        {
+            LogRel(("Some exception in the function i_takeSnapshotHandler()\n"));
+        }
     }
 
     Utf8Str m_strName;
@@ -1356,12 +1366,17 @@ struct SessionMachine::TakeSnapshotTask
     bool m_fPause;
     uint32_t m_uMemSize;
     bool m_fTakingSnapshotOnline;
+
+    friend HRESULT SessionMachine::i_finishTakingSnapshot(TakeSnapshotTask &task, AutoWriteLock &alock, bool aSuccess);
+    friend void SessionMachine::i_takeSnapshotHandler(TakeSnapshotTask &task);
+    friend void SessionMachine::i_takeSnapshotProgressCancelCallback(void *pvUser);
 };
 
 /** Restore snapshot task */
-struct SessionMachine::RestoreSnapshotTask
+class SessionMachine::RestoreSnapshotTask
     : public SessionMachine::SnapshotTask
 {
+public:
     RestoreSnapshotTask(SessionMachine *m,
                         Progress *p,
                         const Utf8Str &t,
@@ -1369,16 +1384,25 @@ struct SessionMachine::RestoreSnapshotTask
         : SnapshotTask(m, p, t, s)
     {}
 
+private:
     void handler()
     {
-        ((SessionMachine *)(Machine *)m_pMachine)->i_restoreSnapshotHandler(*this);
+        try
+        {
+            ((SessionMachine *)(Machine *)m_pMachine)->i_restoreSnapshotHandler(*this);
+        }
+        catch(...)
+        {
+            LogRel(("Some exception in the function i_restoreSnapshotHandler()\n"));
+        }
     }
 };
 
 /** Delete snapshot task */
-struct SessionMachine::DeleteSnapshotTask
+class SessionMachine::DeleteSnapshotTask
     : public SessionMachine::SnapshotTask
 {
+public:
     DeleteSnapshotTask(SessionMachine *m,
                        Progress *p,
                        const Utf8Str &t,
@@ -1388,12 +1412,21 @@ struct SessionMachine::DeleteSnapshotTask
           m_fDeleteOnline(fDeleteOnline)
     {}
 
+private:
     void handler()
     {
-        ((SessionMachine *)(Machine *)m_pMachine)->i_deleteSnapshotHandler(*this);
+        try
+        {
+            ((SessionMachine *)(Machine *)m_pMachine)->i_deleteSnapshotHandler(*this);
+        }
+        catch(...)
+        {
+            LogRel(("Some exception in the function i_deleteSnapshotHandler()\n"));
+        }
     }
 
     bool m_fDeleteOnline;
+    friend void SessionMachine::i_deleteSnapshotHandler(DeleteSnapshotTask &task);
 };
 
 
diff --git a/src/VBox/Main/src-server/VirtualBoxImpl.cpp b/src/VBox/Main/src-server/VirtualBoxImpl.cpp
index dc4cd21..011cbac 100644
--- a/src/VBox/Main/src-server/VirtualBoxImpl.cpp
+++ b/src/VBox/Main/src-server/VirtualBoxImpl.cpp
@@ -80,10 +80,11 @@
 
 #ifdef RT_OS_WINDOWS
 # include "win/svchlp.h"
-# include "ThreadTask.h"
 # include "tchar.h"
 #endif
 
+#include "ThreadTask.h"
+
 ////////////////////////////////////////////////////////////////////////////////
 //
 // Definitions
@@ -3968,15 +3969,42 @@ void VirtualBox::i_rememberMachineNameChangeForMedia(const Utf8Str &strOldConfig
     m->llPendingMachineRenames.push_back(pmr);
 }
 
-struct SaveMediaRegistriesDesc
+static DECLCALLBACK(int) fntSaveMediaRegistries(void *pvUser);
+
+class SaveMediaRegistriesDesc : public ThreadTask
 {
+
+public:
+    SaveMediaRegistriesDesc()
+    {
+        m_strTaskName = "SaveMediaReg";
+    }
+    virtual ~SaveMediaRegistriesDesc(void) { }
+
+private:
+    void handler()
+    {
+        try
+        {
+            fntSaveMediaRegistries(this);
+        }
+        catch(...)
+        {
+            LogRel(("Exception in the function fntSaveMediaRegistries()\n"));
+        }
+    }
+
     MediaList llMedia;
     ComObjPtr<VirtualBox> pVirtualBox;
+
+    friend DECLCALLBACK(int) fntSaveMediaRegistries(void *pvUser);
+    friend void VirtualBox::i_saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
+                                                const Guid &uuidRegistry,
+                                                const Utf8Str &strMachineFolder);
 };
 
-static DECLCALLBACK(int) fntSaveMediaRegistries(RTTHREAD ThreadSelf, void *pvUser)
+DECLCALLBACK(int) fntSaveMediaRegistries(void *pvUser)
 {
-    NOREF(ThreadSelf);
     SaveMediaRegistriesDesc *pDesc = (SaveMediaRegistriesDesc *)pvUser;
     if (!pDesc)
     {
@@ -3996,7 +4024,6 @@ static DECLCALLBACK(int) fntSaveMediaRegistries(RTTHREAD ThreadSelf, void *pvUse
 
     pDesc->llMedia.clear();
     pDesc->pVirtualBox.setNull();
-    delete pDesc;
 
     return VINF_SUCCESS;
 }
@@ -4086,20 +4113,24 @@ void VirtualBox::i_saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
             // levels up to whoever triggered saveSettings, as there are
             // lots of places which would need to handle saving more settings.
             pDesc->pVirtualBox = this;
-            int vrc = RTThreadCreate(NULL,
-                                     fntSaveMediaRegistries,
-                                     (void *)pDesc,
-                                     0,     // cbStack (default)
-                                     RTTHREADTYPE_MAIN_WORKER,
-                                     0,     // flags
-                                     "SaveMediaReg");
-            ComAssertRC(vrc);
-            // failure means that settings aren't saved, but there isn't
-            // much we can do besides avoiding memory leaks
-            if (RT_FAILURE(vrc))
+            HRESULT hr = S_OK;
+            try
+            {
+                //the function createThread() takes ownership of pDesc
+                //so there is no need to use delete operator for pDesc
+                //after calling this function
+                hr = pDesc->createThread();
+            }
+            catch(...)
+            {
+                hr = E_FAIL;
+            }
+
+            if (FAILED(hr))
             {
-                LogRelFunc(("Failed to create thread for saving media registries (%Rrc)\n", vrc));
-                delete pDesc;
+                // failure means that settings aren't saved, but there isn't
+                // much we can do besides avoiding memory leaks
+                LogRelFunc(("Failed to create thread for saving media registries (%Rhr)\n", hr));
             }
         }
         else
diff --git a/src/VBox/Main/src-server/xpcom/server.cpp b/src/VBox/Main/src-server/xpcom/server.cpp
index 094691e..4bc59c1 100644
--- a/src/VBox/Main/src-server/xpcom/server.cpp
+++ b/src/VBox/Main/src-server/xpcom/server.cpp
@@ -261,6 +261,9 @@ public:
                  * connect after this event has been posted to the main queue
                  * but before it started to process it. */
                 LogFlowFunc(("Destruction is canceled (refcnt=%d).\n", count));
+                /* Important: restore previous refcount, we decreased it
+                 * above based on the assumption that the object is unused! */
+                sInstance->AddRef();
             }
 
             RTCritSectLeave(&sLock);
diff --git a/src/VBox/Runtime/common/ldr/ldrFile.cpp b/src/VBox/Runtime/common/ldr/ldrFile.cpp
index 1c0471b..11d00d3 100644
--- a/src/VBox/Runtime/common/ldr/ldrFile.cpp
+++ b/src/VBox/Runtime/common/ldr/ldrFile.cpp
@@ -242,17 +242,34 @@ static int rtldrFileCreate(PRTLDRREADER *ppReader, const char *pszFilename)
 
 
 /**
- * Open a binary image file, extended version.
+ * Open a binary image file.
  *
  * @returns iprt status code.
  * @param   pszFilename Image filename.
- * @param   fFlags      Reserved, MBZ.
+ * @param   fFlags      Valid RTLDR_O_XXX combination.
  * @param   enmArch     CPU architecture specifier for the image to be loaded.
  * @param   phLdrMod    Where to store the handle to the loader module.
  */
 RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
 {
-    LogFlow(("RTLdrOpen: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
+    return RTLdrOpenEx(pszFilename, fFlags, enmArch, phLdrMod, NULL /*pErrInfo*/);
+}
+RT_EXPORT_SYMBOL(RTLdrOpen);
+
+
+/**
+ * Open a binary image file, extended version.
+ *
+ * @returns iprt status code.
+ * @param   pszFilename Image filename.
+ * @param   fFlags      Valid RTLDR_O_XXX combination.
+ * @param   enmArch     CPU architecture specifier for the image to be loaded.
+ * @param   phLdrMod    Where to store the handle to the loader module.
+ * @param   pErrInfo    Where to return extended error information. Optional.
+ */
+RTDECL(int) RTLdrOpenEx(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
+{
+    LogFlow(("RTLdrOpenEx: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
              pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
     AssertMsgReturn(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     AssertMsgReturn(enmArch > RTLDRARCH_INVALID && enmArch < RTLDRARCH_END, ("%d\n", enmArch), VERR_INVALID_PARAMETER);
@@ -264,19 +281,19 @@ RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArc
     int rc = rtldrFileCreate(&pReader, pszFilename);
     if (RT_SUCCESS(rc))
     {
-        rc = RTLdrOpenWithReader(pReader, fFlags, enmArch, phLdrMod, NULL);
+        rc = RTLdrOpenWithReader(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
         if (RT_SUCCESS(rc))
         {
-            LogFlow(("RTLdrOpen: return %Rrc *phLdrMod=%p\n", rc, *phLdrMod));
+            LogFlow(("RTLdrOpenEx: return %Rrc *phLdrMod=%p\n", rc, *phLdrMod));
             return rc;
         }
         pReader->pfnDestroy(pReader);
     }
     *phLdrMod = NIL_RTLDRMOD;
-    LogFlow(("RTLdrOpen: return %Rrc\n", rc));
+    LogFlow(("RTLdrOpenEx: return %Rrc\n", rc));
     return rc;
 }
-RT_EXPORT_SYMBOL(RTLdrOpen);
+RT_EXPORT_SYMBOL(RTLdrOpenEx);
 
 
 /**
diff --git a/src/VBox/Runtime/common/ldr/ldrPE.cpp b/src/VBox/Runtime/common/ldr/ldrPE.cpp
index 589bce3..0a32bd5 100644
--- a/src/VBox/Runtime/common/ldr/ldrPE.cpp
+++ b/src/VBox/Runtime/common/ldr/ldrPE.cpp
@@ -2978,13 +2978,22 @@ static void rtldrPEConvert32BitLoadConfigTo64Bit(PIMAGE_LOAD_CONFIG_DIRECTORY64
     /*
      * volatile everywhere! Trying to prevent the compiler being a smarta$$ and reorder stuff.
      */
-    IMAGE_LOAD_CONFIG_DIRECTORY32_V7 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32_V7 volatile *)pLoadCfg;
-    IMAGE_LOAD_CONFIG_DIRECTORY64_V7 volatile *pLoadCfg64 = pLoadCfg;
-
-    pLoadCfg64->GuardAddressTakenIatEntryTable  = pLoadCfg32->GuardAddressTakenIatEntryTable;
-    pLoadCfg64->GuardAddressTakenIatEntryCount  = pLoadCfg32->GuardAddressTakenIatEntryCount;
-    pLoadCfg64->GuardLongJumpTargetTable        = pLoadCfg32->GuardLongJumpTargetTable;
+    IMAGE_LOAD_CONFIG_DIRECTORY32_V8 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32_V8 volatile *)pLoadCfg;
+    IMAGE_LOAD_CONFIG_DIRECTORY64_V8 volatile *pLoadCfg64 = pLoadCfg;
+
+    pLoadCfg64->HotPatchTableOffset             = pLoadCfg32->HotPatchTableOffset;
+    pLoadCfg64->GuardRFVerifyStackPointerFunctionPointer = pLoadCfg32->GuardRFVerifyStackPointerFunctionPointer;
+    pLoadCfg64->Reserved2                       = pLoadCfg32->Reserved2;
+    pLoadCfg64->DynamicValueRelocTableSection   = pLoadCfg32->DynamicValueRelocTableSection;
+    pLoadCfg64->DynamicValueRelocTableOffset    = pLoadCfg32->DynamicValueRelocTableOffset;
+    pLoadCfg64->GuardRFFailureRoutineFunctionPointer = pLoadCfg32->GuardRFFailureRoutineFunctionPointer;
+    pLoadCfg64->GuardRFFailureRoutine           = pLoadCfg32->GuardRFFailureRoutine;
+    pLoadCfg64->CHPEMetadataPointer             = pLoadCfg32->CHPEMetadataPointer;
+    pLoadCfg64->DynamicValueRelocTable          = pLoadCfg32->DynamicValueRelocTable;
     pLoadCfg64->GuardLongJumpTargetCount        = pLoadCfg32->GuardLongJumpTargetCount;
+    pLoadCfg64->GuardLongJumpTargetTable        = pLoadCfg32->GuardLongJumpTargetTable;
+    pLoadCfg64->GuardAddressTakenIatEntryCount  = pLoadCfg32->GuardAddressTakenIatEntryCount;
+    pLoadCfg64->GuardAddressTakenIatEntryTable  = pLoadCfg32->GuardAddressTakenIatEntryTable;
     pLoadCfg64->CodeIntegrity.Reserved          = pLoadCfg32->CodeIntegrity.Reserved;
     pLoadCfg64->CodeIntegrity.CatalogOffset     = pLoadCfg32->CodeIntegrity.CatalogOffset;
     pLoadCfg64->CodeIntegrity.Catalog           = pLoadCfg32->CodeIntegrity.Catalog;
@@ -3535,6 +3544,9 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
     IMAGE_DATA_DIRECTORY Dir = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
     if (Dir.Size)
     {
+        const size_t cbExpectV8 = !pModPe->f64Bit
+                                ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V8)
+                                : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V8);
         const size_t cbExpectV7 = !pModPe->f64Bit
                                 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V7)
                                 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V7);
@@ -3557,10 +3569,11 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
                                 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V1)
                                 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V2) /*No V1*/;
         const size_t cbNewHack  = cbExpectV5; /* Playing safe here since there might've been revisions between V5 and V6 we don't know about . */
-        const size_t cbMaxKnown = cbExpectV7;
+        const size_t cbMaxKnown = cbExpectV8;
 
         bool fNewerStructureHack = false;
-        if (   Dir.Size != cbExpectV7
+        if (   Dir.Size != cbExpectV8
+            && Dir.Size != cbExpectV7
             && Dir.Size != cbExpectV6
             && Dir.Size != cbExpectV5
             && Dir.Size != cbExpectV4
@@ -3570,13 +3583,13 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
         {
             fNewerStructureHack = Dir.Size > cbNewHack /* These structure changes are slowly getting to us! More futher down. */
                                && Dir.Size <= sizeof(u);
-            Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u bytes, expected %zu, %zu, %zu, %zu, %zu, %zu, or %zu.%s\n",
-                 pszLogName, Dir.Size, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
+            Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u bytes, expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu.%s\n",
+                 pszLogName, Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
                  fNewerStructureHack ? " Will try ignore extra bytes if all zero." : ""));
             if (!fNewerStructureHack)
                 return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
-                                     "Unexpected load config dir size of %u bytes; supported sized: %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
-                                     Dir.Size, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
+                                     "Unexpected load config dir size of %u bytes; supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
+                                     Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
         }
 
         /*
@@ -3614,7 +3627,8 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
             }
             /* Kludge #2: This happens a lot. Structure changes, but the linker doesn't get
                updated and stores some old size in the directory.  Use the header size. */
-            else if (   u.Cfg64.Size == cbExpectV7
+            else if (   u.Cfg64.Size == cbExpectV8
+                     || u.Cfg64.Size == cbExpectV7
                      || u.Cfg64.Size == cbExpectV6
                      || u.Cfg64.Size == cbExpectV5
                      || u.Cfg64.Size == cbExpectV4
@@ -3649,11 +3663,11 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
             }
             else
             {
-                Log(("rtldrPEOpen: %s: load cfg hdr: unexpected hdr size of %u bytes (dir %u), expected %zu, %zu, %zu, %zu, %zu, %zu, or %zu.\n",
-                     pszLogName, u.Cfg64.Size, Dir.Size, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1));
+                Log(("rtldrPEOpen: %s: load cfg hdr: unexpected hdr size of %u bytes (dir %u), expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu.\n",
+                     pszLogName, u.Cfg64.Size, Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1));
                 return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
-                                     "Unexpected load config header size of %u bytes (dir %u); supported sized: %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
-                                     u.Cfg64.Size, Dir.Size, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
+                                     "Unexpected load config header size of %u bytes (dir %u); supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, or %zu",
+                                     u.Cfg64.Size, Dir.Size, cbExpectV8, cbExpectV7, cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
             }
         }
         if (u.Cfg64.LockPrefixTable && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)))
@@ -3698,12 +3712,14 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
                  u.Cfg64.GuardCFFunctionTable, u.Cfg64.GuardCFFunctionCount, u.Cfg64.GuardFlags,
                  u.Cfg64.GuardAddressTakenIatEntryTable, u.Cfg64.GuardAddressTakenIatEntryCount,
                  u.Cfg64.GuardLongJumpTargetTable, u.Cfg64.GuardLongJumpTargetCount ));
+#if 0 /* ntdll 15002 uses this. */
             return RTErrInfoSetF(pErrInfo, VERR_LDRPE_GUARD_CF_STUFF,
                                  "Guard bits in load config: %RX64,%RX64,%RX64,%RX64,%RX32,%RX64,%RX64,%RX64,%RX64!",
                                  u.Cfg64.GuardCFCCheckFunctionPointer, u.Cfg64.GuardCFDispatchFunctionPointer,
                                  u.Cfg64.GuardCFFunctionTable, u.Cfg64.GuardCFFunctionCount, u.Cfg64.GuardFlags,
                                  u.Cfg64.GuardAddressTakenIatEntryTable, u.Cfg64.GuardAddressTakenIatEntryCount,
                                  u.Cfg64.GuardLongJumpTargetTable, u.Cfg64.GuardLongJumpTargetCount);
+#endif
         }
     }
 
diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
index e43712d..4bc2a9b 100644
--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
@@ -1078,7 +1078,11 @@ DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3P
                                 fWrite,                 /* force write access. */
 # endif
                                 &pMemLnx->apPages[0],   /* Page array. */
-                                papVMAs);               /* vmas */
+                                papVMAs                 /* vmas */
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+                                , NULL                  /* locked */
+# endif
+                                );
 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) */
             rc = get_user_pages(pTask,                  /* Task for fault accounting. */
                                 pTask->mm,              /* Whose pages. */
diff --git a/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c
index e12146c..9a3a156 100644
--- a/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c
@@ -37,19 +37,58 @@
 #include <iprt/thread.h>
 #include "r0drv/mp-r0drv.h"
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71) && defined(CONFIG_SMP)
+static enum cpuhp_state g_rtR0MpOnline;
 
+/*
+ * Linux 4.10 completely removed CPU notifiers. So let's switch to CPU hotplug
+ * notification.
+ */
 
-/*********************************************************************************************************************************
-*   Internal Functions                                                                                                           *
-*********************************************************************************************************************************/
-static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu);
+static int rtR0MpNotificationLinuxOnline(unsigned int cpu)
+{
+    RTCPUID idCpu = RTMpCpuIdFromSetIndex(cpu);
+    rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
+    return 0;
+}
 
+static int rtR0MpNotificationLinuxOffline(unsigned int cpu)
+{
+    RTCPUID idCpu = RTMpCpuIdFromSetIndex(cpu);
+    rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
+    return 0;
+}
+
+DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
+{
+    int rc;
+    IPRT_LINUX_SAVE_EFL_AC();
+    rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "vboxdrv:online",
+                                   rtR0MpNotificationLinuxOnline, rtR0MpNotificationLinuxOffline);
+    IPRT_LINUX_RESTORE_EFL_AC();
+    /*
+     * cpuhp_setup_state_nocalls() returns a positive state number for
+     * CPUHP_AP_ONLINE_DYN or -ENOSPC if there is no free slot available
+     * (see cpuhp_reserve_state / definition of CPUHP_AP_ONLINE_DYN).
+     */
+    AssertMsgReturn(rc > 0, ("%d\n", rc), RTErrConvertFromErrno(rc));
+    g_rtR0MpOnline = rc;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
+{
+    IPRT_LINUX_SAVE_EFL_AC();
+    cpuhp_remove_state_nocalls(g_rtR0MpOnline);
+    IPRT_LINUX_RESTORE_EFL_AC();
+}
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71) && defined(CONFIG_SMP)
+
+static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu);
 
-/*********************************************************************************************************************************
-*   Global Variables                                                                                                             *
-*********************************************************************************************************************************/
 /**
  * The notifier block we use for registering the callback.
  */
diff --git a/src/VBox/Runtime/testcase/tstLdr-2.cpp b/src/VBox/Runtime/testcase/tstLdr-2.cpp
index d4b73df..5823376 100644
--- a/src/VBox/Runtime/testcase/tstLdr-2.cpp
+++ b/src/VBox/Runtime/testcase/tstLdr-2.cpp
@@ -93,11 +93,14 @@ static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule,
  */
 static int testLdrOne(const char *pszFilename)
 {
+    RTERRINFOSTATIC ErrInfo;
     RTLDRMOD hLdrMod;
-    int rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_WHATEVER, &hLdrMod);
+    int rc = RTLdrOpenEx(pszFilename, 0, RTLDRARCH_WHATEVER, &hLdrMod, RTErrInfoInitStatic(&ErrInfo));
     if (RT_FAILURE(rc))
     {
         RTPrintf("tstLdr: Failed to open '%s', rc=%Rrc. aborting test.\n", pszFilename, rc);
+        if (ErrInfo.szMsg[0])
+            RTPrintf("tstLdr: %s\n", ErrInfo.szMsg);
         Assert(hLdrMod == NIL_RTLDRMOD);
         return 1;
     }
diff --git a/src/VBox/Runtime/testcase/tstLdr-3.cpp b/src/VBox/Runtime/testcase/tstLdr-3.cpp
index b75ad50..3ce0be6 100644
--- a/src/VBox/Runtime/testcase/tstLdr-3.cpp
+++ b/src/VBox/Runtime/testcase/tstLdr-3.cpp
@@ -301,11 +301,14 @@ int main(int argc, char **argv)
     /*
      * Load the module.
      */
+    RTERRINFOSTATIC ErrInfo;
     g_uLoadAddr = (RTUINTPTR)RTStrToUInt64(argv[1]);
-    int rc = RTLdrOpen(argv[2], 0, RTLDRARCH_WHATEVER, &g_hLdrMod);
+    int rc = RTLdrOpenEx(argv[2], 0, RTLDRARCH_WHATEVER, &g_hLdrMod, RTErrInfoInitStatic(&ErrInfo));
     if (RT_FAILURE(rc))
     {
         RTPrintf("tstLdr-3: Failed to open '%s': %Rra\n", argv[2], rc);
+        if (ErrInfo.szMsg[0])
+            RTPrintf("tstLdr-3: %s\n", ErrInfo.szMsg);
         return 1;
     }
 
diff --git a/src/VBox/Runtime/testcase/tstLdr-4.cpp b/src/VBox/Runtime/testcase/tstLdr-4.cpp
index d05732d..5ff4ccc 100644
--- a/src/VBox/Runtime/testcase/tstLdr-4.cpp
+++ b/src/VBox/Runtime/testcase/tstLdr-4.cpp
@@ -69,8 +69,8 @@ static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule,
         *pValue = (uintptr_t)RTAssertMsg2V;
     else if (!strcmp(pszSymbol, "RTAssertMayPanic")     || !strcmp(pszSymbol, "_RTAssertMayPanic"))
         *pValue = (uintptr_t)RTAssertMayPanic;
-    else if (!strcmp(pszSymbol, "RTLogDefaultInstance") || !strcmp(pszSymbol, "_RTLogDefaultInstance"))
-        *pValue = (uintptr_t)RTLogDefaultInstance;
+    else if (!strcmp(pszSymbol, "RTLogDefaultInstanceEx") || !strcmp(pszSymbol, "RTLogDefaultInstanceEx"))
+        *pValue = (uintptr_t)RTLogDefaultInstanceEx;
     else if (!strcmp(pszSymbol, "RTLogLoggerExV")       || !strcmp(pszSymbol, "_RTLogLoggerExV"))
         *pValue = (uintptr_t)RTLogLoggerExV;
     else if (!strcmp(pszSymbol, "RTLogPrintfV")         || !strcmp(pszSymbol, "_RTLogPrintfV"))
diff --git a/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp b/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
index 8d1c02d..53f85eb 100644
--- a/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
+++ b/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
@@ -338,7 +338,7 @@ static uint8_t const g_afParity[256] =
  * @param   a_cBitsWidth    The width of the result (8, 16, 32, 64).
  */
 #define X86_EFL_CALC_SF(a_uResult, a_cBitsWidth) \
-    ( (uint32_t)((a_uResult) >> ((a_cBitsWidth) - X86_EFL_SF_BIT)) & X86_EFL_SF )
+    ( (uint32_t)((a_uResult) >> ((a_cBitsWidth) - X86_EFL_SF_BIT - 1)) & X86_EFL_SF )
 
 /**
  * Calculates the zero flag value given a result.
@@ -682,7 +682,7 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_bts_u64_locked,(uint64_t *puDst, uint64_t uSrc,
 IEM_DECL_IMPL_DEF(void, iemAImpl_bsf_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
 {
     /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
-    /** @todo check what real CPUs does. */
+    /** @todo check what real CPUs do. */
     if (uSrc)
     {
         uint8_t  iBit;
@@ -733,19 +733,19 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_bsf_u64,(uint64_t *puDst, uint64_t uSrc, uint32
 IEM_DECL_IMPL_DEF(void, iemAImpl_bsr_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
 {
     /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
-    /** @todo check what real CPUs does. */
+    /** @todo check what real CPUs do. */
     if (uSrc)
     {
         uint8_t  iBit;
         uint32_t u32Src;
         if (uSrc & UINT64_C(0xffffffff00000000))
         {
-            iBit = 64;
+            iBit = 63;
             u32Src = uSrc >> 32;
         }
         else
         {
-            iBit = 32;
+            iBit = 31;
             u32Src = uSrc;
         }
         if (!(u32Src & UINT32_C(0xffff0000)))
@@ -768,11 +768,10 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_bsr_u64,(uint64_t *puDst, uint64_t uSrc, uint32
             iBit -= 2;
             u32Src <<= 2;
         }
-        if (!(u32Src & UINT32_C(0x10000000)))
+        if (!(u32Src & UINT32_C(0x80000000)))
         {
             iBit -= 1;
-            u32Src <<= 1;
-            Assert(u32Src & RT_BIT_64(63));
+            Assert(u32Src & RT_BIT(30));
         }
 
         *puDst     = iBit;
diff --git a/src/VBox/VMM/VMMR0/HMVMXR0.cpp b/src/VBox/VMM/VMMR0/HMVMXR0.cpp
index 58d01e2..d61c2ab 100644
--- a/src/VBox/VMM/VMMR0/HMVMXR0.cpp
+++ b/src/VBox/VMM/VMMR0/HMVMXR0.cpp
@@ -1576,32 +1576,45 @@ static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     Assert(!VMMRZCallRing3IsEnabled(pVCpu));
 
-#define VMXLOCAL_LAZY_LOAD_GUEST_MSR(uMsr, a_GuestMsr, a_HostMsr) \
-    do { \
-        if (pMixedCtx->msr##a_GuestMsr != pVCpu->hm.s.vmx.u64Host##a_HostMsr##Msr) \
-            ASMWrMsr(uMsr, pMixedCtx->msr##a_GuestMsr); \
-        else \
-            Assert(ASMRdMsr(uMsr) == pVCpu->hm.s.vmx.u64Host##a_HostMsr##Msr); \
-    } while (0)
-
     Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
-    if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
-    {
 #if HC_ARCH_BITS == 64
-        if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
+    if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
+    {
+        /*
+         * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
+         * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
+         * we can skip a few MSR writes.
+         *
+         * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
+         * guest MSR values in the guest-CPU context might be different to what's currently
+         * loaded in the CPU. In either case, we need to write the new guest MSR values to the
+         * CPU, see @bugref{8728}.
+         */
+        if (   !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
+            && pMixedCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostKernelGSBaseMsr
+            && pMixedCtx->msrLSTAR        == pVCpu->hm.s.vmx.u64HostLStarMsr
+            && pMixedCtx->msrSTAR         == pVCpu->hm.s.vmx.u64HostStarMsr
+            && pMixedCtx->msrSFMASK       == pVCpu->hm.s.vmx.u64HostSFMaskMsr)
         {
-            VMXLOCAL_LAZY_LOAD_GUEST_MSR(MSR_K8_LSTAR, LSTAR, LStar);
-            VMXLOCAL_LAZY_LOAD_GUEST_MSR(MSR_K6_STAR, STAR, Star);
-            VMXLOCAL_LAZY_LOAD_GUEST_MSR(MSR_K8_SF_MASK, SFMASK, SFMask);
-            VMXLOCAL_LAZY_LOAD_GUEST_MSR(MSR_K8_KERNEL_GS_BASE, KERNELGSBASE, KernelGSBase);
+#ifdef VBOX_STRICT
+            Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pMixedCtx->msrKERNELGSBASE);
+            Assert(ASMRdMsr(MSR_K8_LSTAR)          == pMixedCtx->msrLSTAR);
+            Assert(ASMRdMsr(MSR_K6_STAR)           == pMixedCtx->msrSTAR);
+            Assert(ASMRdMsr(MSR_K8_SF_MASK)        == pMixedCtx->msrSFMASK);
+#endif
         }
+        else
+        {
+            ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pMixedCtx->msrKERNELGSBASE);
+            ASMWrMsr(MSR_K8_LSTAR,          pMixedCtx->msrLSTAR);
+            ASMWrMsr(MSR_K6_STAR,           pMixedCtx->msrSTAR);
+            ASMWrMsr(MSR_K8_SF_MASK,        pMixedCtx->msrSFMASK);
+        }
+    }
 #else
-        RT_NOREF(pMixedCtx);
+    RT_NOREF(pMixedCtx);
 #endif
-        pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
-    }
-
-#undef VMXLOCAL_LAZY_LOAD_GUEST_MSR
+    pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
 }
 
 
diff --git a/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp b/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp
index 603ff89..e524575 100644
--- a/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp
+++ b/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp
@@ -36,6 +36,7 @@
 #include <VBox/version.h>
 #include <VBox/vmm/hm.h>
 #include <iprt/assert.h>
+#include <iprt/dbg.h>
 #include <iprt/time.h>
 #include <iprt/stream.h>
 #include <iprt/string.h>
@@ -471,11 +472,57 @@ VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr)
                         DBGFR3StackWalkEnd(pFirstFrame);
                     }
 
+                    /* Symbols on the stack. */
+#ifdef VMM_R0_SWITCH_STACK
+                    uint32_t const   iLast   = VMM_STACK_SIZE / sizeof(uintptr_t);
+                    uint32_t         iAddr   = (uint32_t)(  pVCpu->vmm.s.CallRing3JmpBufR0.SavedEsp
+                                                          - MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3)) / sizeof(uintptr_t);
+                    if (iAddr > iLast)
+                        iAddr = 0;
+#else
+                    uint32_t const   iLast   = RT_MIN(pVCpu->vmm.s.CallRing3JmpBufR0.cbSavedStack, VMM_STACK_SIZE)
+                                             / sizeof(uintptr_t);
+                    uint32_t         iAddr   = 0;
+#endif
+                    pHlp->pfnPrintf(pHlp,
+                                    "!!\n"
+                                    "!! Addresses on the stack (iAddr=%#x, iLast=%#x)\n"
+                                    "!!\n",
+                                    iAddr, iLast);
+                    uintptr_t const *paAddr  = (uintptr_t const *)pVCpu->vmm.s.pbEMTStackR3;
+                    while (iAddr < iLast)
+                    {
+                        uintptr_t const uAddr = paAddr[iAddr];
+                        if (uAddr > X86_PAGE_SIZE)
+                        {
+                            DBGFADDRESS  Addr;
+                            DBGFR3AddrFromFlat(pVM->pUVM, &Addr, uAddr);
+                            RTGCINTPTR   offDisp = 0;
+                            PRTDBGSYMBOL pSym  = DBGFR3AsSymbolByAddrA(pVM->pUVM, DBGF_AS_R0, &Addr,
+                                                                       RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, &offDisp, NULL);
+                            RTGCINTPTR   offLineDisp;
+                            PRTDBGLINE   pLine = DBGFR3AsLineByAddrA(pVM->pUVM, DBGF_AS_R0, &Addr, &offLineDisp, NULL);
+                            if (pLine || pSym)
+                            {
+                                pHlp->pfnPrintf(pHlp, "%#06x: %p =>", iAddr * sizeof(uintptr_t), uAddr);
+                                if (pSym)
+                                    pHlp->pfnPrintf(pHlp, " %s + %#x", pSym->szName, (intptr_t)offDisp);
+                                if (pLine)
+                                    pHlp->pfnPrintf(pHlp, " [%s:%u + %#x]\n", pLine->szFilename, pLine->uLineNo, offLineDisp);
+                                else
+                                    pHlp->pfnPrintf(pHlp, "\n");
+                                RTDbgSymbolFree(pSym);
+                                RTDbgLineFree(pLine);
+                            }
+                        }
+                        iAddr++;
+                    }
+
                     /* raw stack */
                     Hlp.fRecSummary = false;
                     pHlp->pfnPrintf(pHlp,
                                     "!!\n"
-                                    "!! Raw stack (mind the direction). \n"
+                                    "!! Raw stack (mind the direction).\n"
                                     "!! pbEMTStackR0=%RHv pbEMTStackBottomR0=%RHv VMM_STACK_SIZE=%#x\n"
                                     "!! pbEmtStackR3=%p\n"
                                     "!!\n"
diff --git a/src/VBox/VMM/VMMRZ/VMMRZ.cpp b/src/VBox/VMM/VMMRZ/VMMRZ.cpp
index 8be503a..3d1fcdd 100644
--- a/src/VBox/VMM/VMMRZ/VMMRZ.cpp
+++ b/src/VBox/VMM/VMMRZ/VMMRZ.cpp
@@ -69,10 +69,12 @@ VMMRZDECL(int) VMMRZCallRing3(PVM pVM, PVMCPU pVCpu, VMMCALLRING3 enmOperation,
 #endif
 #ifdef IN_RC
         RTStrPrintf(g_szRTAssertMsg1, sizeof(pVM->vmm.s.szRing0AssertMsg1),
-                    "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x\n", enmOperation, uArg, pVCpu->idCpu);
+                    "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x cCallRing3Disabled=%#x\n",
+                    enmOperation, uArg, pVCpu->idCpu, pVCpu->vmm.s.cCallRing3Disabled);
 #endif
         RTStrPrintf(pVM->vmm.s.szRing0AssertMsg1, sizeof(pVM->vmm.s.szRing0AssertMsg1),
-                    "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x\n", enmOperation, uArg, pVCpu->idCpu);
+                    "VMMRZCallRing3: enmOperation=%d uArg=%#llx idCpu=%#x cCallRing3Disabled=%#x\n",
+                    enmOperation, uArg, pVCpu->idCpu, pVCpu->vmm.s.cCallRing3Disabled);
         enmOperation = VMMCALLRING3_VM_R0_ASSERTION;
     }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-virtualbox/virtualbox.git



More information about the Pkg-virtualbox-commits mailing list