[Pkg-virtualbox-commits] [virtualbox] 01/06: Imported Upstream version 4.3.8-dfsg

Felix Geyer fgeyer at moszumanska.debian.org
Sun Apr 6 15:56:04 UTC 2014


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

fgeyer pushed a commit to branch master
in repository virtualbox.

commit 1e85aed889b772c2f2daa7a6d9e8bd967aa213d8
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date:   Mon Mar 10 10:14:28 2014 +0100

    Imported Upstream version 4.3.8-dfsg
---
 Config.kmk                                         |   96 +-
 doc/manual/Makefile.kmk                            |    2 +-
 doc/manual/en_US/SDKRef.xml                        |  555 +-
 doc/manual/en_US/user_AdvancedTopics.xml           |  121 +-
 doc/manual/en_US/user_Technical.xml                |   12 +-
 doc/manual/en_US/user_VBoxManage.xml               |   12 +-
 doc/manual/fr_FR/user_AdvancedTopics.xml           |   97 +
 doc/manual/user_ChangeLogImpl.xml                  |  262 +-
 include/VBox/HGSMI/HGSMIChSetup.h                  |    4 +-
 include/VBox/HostServices/VBoxCrOpenGLSvc.h        |   51 +-
 include/VBox/VBoxVideo.h                           |  301 +-
 include/VBox/VBoxVideo3D.h                         |   36 +-
 include/VBox/VMMDev.h                              |    2 +
 include/VBox/cdefs.h                               |   12 +-
 include/VBox/com/array.h                           |   46 +-
 include/VBox/com/defs.h                            |    3 +-
 include/VBox/err.h                                 |   10 +
 include/VBox/err.mac                               |    5 +
 include/VBox/log.h                                 |    3 +
 include/VBox/settings.h                            |    2 +-
 include/VBox/vmm/cpum.h                            |  270 +-
 include/VBox/vmm/hm_vmx.h                          |   99 +-
 include/VBox/vmm/mm.h                              |    3 +
 include/VBox/vmm/pdmifs.h                          |    9 +
 include/VBox/vmm/vmm.h                             |    3 +-
 include/iprt/asm-amd64-x86.h                       |   93 +
 include/iprt/cdefs.h                               |    4 +-
 include/iprt/env.h                                 |   12 +
 include/iprt/err.h                                 |    2 +-
 include/iprt/err.mac                               |    2 +-
 include/iprt/mangling.h                            |   16 +
 include/iprt/x86.h                                 |   24 +-
 include/iprt/x86.mac                               |   21 +-
 src/VBox/Additions/common/VBoxControl/Makefile.kmk |   10 -
 .../Additions/common/VBoxGuestLib/Makefile.kmk     |   17 +-
 src/VBox/Additions/common/VBoxService/Makefile.kmk |   14 +-
 .../common/VBoxService/VBoxServiceAutoMount.cpp    |   34 +-
 .../common/VBoxService/VBoxServiceCpuHotPlug.cpp   |   35 +-
 .../common/VBoxService/VBoxServiceVMInfo-win.cpp   |   43 +-
 .../common/VBoxService/VBoxServiceVMInfo.cpp       |   25 +-
 src/VBox/Additions/common/crOpenGL/Makefile.kmk    |   25 +-
 src/VBox/Additions/common/crOpenGL/fakedri_drv.c   |    2 +-
 .../Additions/common/crOpenGL/pack/packspu_get.py  |    3 +-
 .../common/crOpenGL/pack/packspu_getshaders.c      |    8 +-
 .../Additions/common/crOpenGL/pack/packspu_glsl.c  |    2 +-
 .../Additions/common/crOpenGL/pack/packspu_misc.c  |    2 +-
 src/VBox/Additions/common/pam/Makefile.kmk         |   15 -
 src/VBox/Additions/linux/drm/Makefile.module       |    6 +
 src/VBox/Additions/linux/installer/vboxadd-x11.sh  |    8 +-
 .../Additions/linux/sharedfolders/Makefile.kmk     |   10 -
 src/VBox/Additions/x11/VBoxClient/Makefile.kmk     |   10 -
 src/VBox/Additions/x11/vboxmouse/Makefile.kmk      |   13 -
 src/VBox/Additions/x11/vboxvideo/Makefile.kmk      |   69 +-
 src/VBox/Additions/x11/vboxvideo/setmode.c         |    2 +-
 src/VBox/Additions/x11/vboxvideo/undefined         |    2 +
 src/VBox/Additions/x11/vboxvideo/vboxvideo.c       |   14 +-
 src/VBox/Additions/x11/vboxvideo/vboxvideo.h       |    4 +-
 src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c  |   62 +
 .../BiosCommonCode/MakeAlternativeSource.cpp       |   20 +-
 src/VBox/Devices/EFI/DevEFI.cpp                    |    7 +-
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd      |  Bin 1048576 -> 1048576 bytes
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd      |  Bin 1048576 -> 1048576 bytes
 .../Graphics/BIOS/VBoxVgaBiosAlternative.asm       |    6 +-
 .../Graphics/BIOS/VBoxVgaBiosAlternative.md5sum    |    2 +-
 src/VBox/Devices/Graphics/DevVGA-SVGA.cpp          | 3196 +++++++++++
 src/VBox/Devices/Graphics/DevVGA-SVGA.h            |   46 +
 src/VBox/Devices/Graphics/DevVGA.cpp               |  393 +-
 src/VBox/Devices/Graphics/DevVGA.h                 |  102 +-
 src/VBox/Devices/Graphics/DevVGASavedState.h       |    8 +-
 src/VBox/Devices/Graphics/DevVGA_VBVA.cpp          |  133 +-
 src/VBox/Devices/Graphics/DevVGA_VDMA.cpp          |  562 ++
 src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp      |    5 +-
 src/VBox/Devices/Graphics/vmsvga/svga3d_caps.h     |   11 +
 src/VBox/Devices/Graphics/vmsvga/svga3d_reg.h      |   56 +
 src/VBox/Devices/Graphics/vmsvga/svga_escape.h     |   11 +
 src/VBox/Devices/Graphics/vmsvga/svga_overlay.h    |   32 +
 src/VBox/Devices/Graphics/vmsvga/svga_reg.h        |  318 ++
 src/VBox/Devices/Makefile.kmk                      |   34 +
 src/VBox/Devices/Network/DrvNAT.cpp                |   80 +-
 .../Devices/Network/lwip-new/src/core/ipv4/icmp.c  |  103 +
 .../Devices/Network/lwip-new/src/core/ipv4/ip4.c   |   12 +
 .../Devices/Network/lwip-new/src/core/ipv6/icmp6.c |   67 +
 .../Devices/Network/lwip-new/src/core/ipv6/ip6.c   |   20 +-
 .../Network/lwip-new/src/core/ipv6/ip6_frag.c      |  397 +-
 .../Devices/Network/lwip-new/src/core/tcp_out.c    |    3 +-
 src/VBox/Devices/Network/lwip-new/src/core/udp.c   |   20 +-
 .../Network/lwip-new/src/include/ipv4/lwip/icmp.h  |   10 +
 .../lwip-new/src/include/ipv4/lwip/ip4_addr.h      |    2 +-
 .../Network/lwip-new/src/include/ipv6/lwip/icmp6.h |    8 +
 .../lwip-new/src/include/ipv6/lwip/ip6_addr.h      |    2 +-
 .../lwip-new/src/include/ipv6/lwip/ip6_frag.h      |   11 +-
 .../Devices/Network/lwip-new/src/include/lwip/ip.h |   10 +-
 .../Network/lwip-new/vbox/include/lwipopts.h       |    1 +
 src/VBox/Devices/Network/slirp/ip_icmp.c           |   92 +-
 src/VBox/Devices/Network/slirp/libslirp.h          |   15 +
 .../Devices/Network/slirp/resolv_conf_parser.c     |  539 ++
 .../Devices/Network/slirp/resolv_conf_parser.h     |  109 +
 src/VBox/Devices/Network/slirp/slirp.c             |    8 +
 src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm   | 5553 ++++++++++----------
 .../Devices/PC/BIOS/VBoxBiosAlternative.md5sum     |    2 +-
 src/VBox/Devices/PC/BIOS/ahci.c                    |    3 +
 src/VBox/Devices/PC/BIOS/bios.c                    |   16 +-
 src/VBox/Devices/PC/BIOS/logo.c                    |    6 +-
 src/VBox/Devices/PC/BIOS/scsi.c                    |   57 +-
 src/VBox/Devices/PC/DevPcBios.cpp                  |  148 +-
 src/VBox/Devices/Storage/DevAHCI.cpp               |  701 +--
 src/VBox/Devices/Storage/DevATA.cpp                |  546 +-
 src/VBox/Devices/Storage/DrvSCSI.cpp               |    1 +
 src/VBox/Devices/USB/VUSBReadAhead.cpp             |   19 +-
 src/VBox/Devices/testcase/Makefile.kmk             |    3 +-
 src/VBox/Devices/testcase/tstDeviceStructSize.cpp  |    4 +
 .../Devices/testcase/tstDeviceStructSizeRC.cpp     |   20 +-
 src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp   |   31 +-
 .../VBoxHeadless/testcase/tstHeadless.cpp          |   94 +-
 src/VBox/Frontends/VBoxManage/Makefile.kmk         |    3 +-
 .../Frontends/VBoxManage/VBoxManageAppliance.cpp   |  215 +-
 .../VBoxManage/VBoxManageBandwidthControl.cpp      |    6 +
 src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp   |   15 +-
 .../Frontends/VBoxManage/VBoxManageModifyVM.cpp    |    5 +
 src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp    |   19 +-
 src/VBox/Frontends/VBoxSDL/Framebuffer.cpp         |    2 +-
 src/VBox/Frontends/VBoxShell/vboxshell.py          |    4 +-
 src/VBox/Frontends/VirtualBox/Makefile.kmk         |    5 +-
 src/VBox/Frontends/VirtualBox/VirtualBox1.qrc      |    1 +
 src/VBox/Frontends/VirtualBox/VirtualBoxBrand.qrc  |    1 +
 .../VirtualBox/images/close_popup_16px.png         |  Bin 0 -> 3460 bytes
 src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts |   17 +
 .../VirtualBox/src/converter/UIConverterBackend.h  |   26 +
 .../src/converter/UIConverterBackendGlobal.cpp     |  290 +
 .../Frontends/VirtualBox/src/globals/COMDefs.h     |  324 +-
 .../Frontends/VirtualBox/src/globals/UIDefs.cpp    |   10 +
 src/VBox/Frontends/VirtualBox/src/globals/UIDefs.h |  104 +
 .../VirtualBox/src/globals/UIPopupCenter.cpp       |    5 +-
 .../VirtualBox/src/globals/VBoxGlobal.cpp          |  118 +
 .../Frontends/VirtualBox/src/globals/VBoxGlobal.h  |   10 +
 .../VirtualBox/src/medium/UIMediumEnumerator.cpp   |    6 +-
 .../src/platform/darwin/DarwinKeyboard.cpp         |    2 +-
 .../src/platform/darwin/UICocoaApplication.h       |    1 -
 .../src/platform/darwin/UICocoaApplication.mm      |    5 -
 .../VirtualBox/src/platform/win/WinKeyboard.cpp    |  173 +
 .../VirtualBox/src/platform/win/WinKeyboard.h      |   33 +
 .../VirtualBox/src/runtime/UIActionPoolRuntime.cpp |    7 +-
 .../VirtualBox/src/runtime/UIFrameBuffer.cpp       |    8 +
 .../VirtualBox/src/runtime/UIFrameBufferQImage.cpp |    1 +
 .../VirtualBox/src/runtime/UIKeyboardHandler.cpp   |   14 +-
 .../VirtualBox/src/runtime/UIKeyboardHandler.h     |    3 +
 .../VirtualBox/src/runtime/UIMachineLogic.cpp      |  141 +-
 .../VirtualBox/src/runtime/UIMachineLogic.h        |    5 +-
 .../VirtualBox/src/runtime/UIMachineMenuBar.cpp    |  433 +-
 .../VirtualBox/src/runtime/UIMachineView.cpp       |    8 +-
 .../VirtualBox/src/runtime/UIMachineWindow.cpp     |   10 +
 .../VirtualBox/src/runtime/UIMultiScreenLayout.cpp |    4 +
 .../Frontends/VirtualBox/src/runtime/UISession.cpp |   35 +-
 .../Frontends/VirtualBox/src/runtime/UISession.h   |   52 +
 .../fullscreen/UIMachineLogicFullscreen.cpp        |    5 +-
 .../src/runtime/normal/UIMachineLogicNormal.cpp    |   12 +-
 .../src/runtime/normal/UIMachineLogicNormal.h      |    1 -
 .../runtime/seamless/UIMachineLogicSeamless.cpp    |    5 +-
 .../VirtualBox/src/selector/UISelectorWindow.cpp   |   32 +-
 .../VirtualBox/src/selector/UISelectorWindow.h     |    3 -
 .../settings/machine/UIMachineSettingsDisplay.cpp  |   14 +
 .../src/widgets/UIApplianceImportEditorWidget.cpp  |    4 +-
 .../VirtualBox/src/widgets/UIHostComboEditor.cpp   |  110 +-
 .../VirtualBox/src/widgets/UIHostComboEditor.h     |   42 +-
 .../src/widgets/UINameAndSystemEditor.cpp          |   10 +-
 .../VirtualBox/src/widgets/UIPopupPane.cpp         |   23 +-
 .../Frontends/VirtualBox/src/widgets/UIPopupPane.h |    9 +-
 .../src/widgets/UIPopupPaneButtonPane.cpp          |   33 +-
 .../VirtualBox/src/widgets/UIPopupPaneTextPane.cpp |   78 +-
 .../VirtualBox/src/widgets/UIPopupPaneTextPane.h   |   20 +-
 .../VirtualBox/src/widgets/UIPopupStack.cpp        |    6 +-
 .../VirtualBox/src/widgets/UIPopupStack.h          |    3 +-
 .../src/widgets/UIPopupStackViewport.cpp           |    6 +-
 .../VirtualBox/src/widgets/UIPopupStackViewport.h  |    3 +-
 .../src/wizards/newvm/UIWizardNewVMPageBasic1.cpp  |  167 +-
 .../src/wizards/newvm/UIWizardNewVMPageBasic1.h    |    4 +-
 src/VBox/GuestHost/OpenGL/Makefile.kmk             |   51 +-
 src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt |   56 +-
 src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py  |    2 +-
 src/VBox/GuestHost/OpenGL/include/GL/glext.h       |  122 +-
 src/VBox/GuestHost/OpenGL/include/chromium.h       |   30 +-
 src/VBox/GuestHost/OpenGL/include/cr_blitter.h     |  516 +-
 src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h    |   25 +
 src/VBox/GuestHost/OpenGL/include/cr_compositor.h  |  233 +
 src/VBox/GuestHost/OpenGL/include/cr_dump.h        |    4 +
 src/VBox/GuestHost/OpenGL/include/cr_error.h       |   14 +-
 src/VBox/GuestHost/OpenGL/include/cr_glext.h       |   34 +
 src/VBox/GuestHost/OpenGL/include/cr_glstate.h     |    2 +
 src/VBox/GuestHost/OpenGL/include/cr_htable.h      |  120 +
 src/VBox/GuestHost/OpenGL/include/cr_protocol.h    |   33 +-
 src/VBox/GuestHost/OpenGL/include/cr_server.h      |  140 +-
 src/VBox/GuestHost/OpenGL/include/cr_version.h     |    4 +-
 src/VBox/GuestHost/OpenGL/include/cr_vreg.h        |  213 +-
 src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h  |    2 +-
 src/VBox/GuestHost/OpenGL/packer/pack_extensions.c |    2 -
 src/VBox/GuestHost/OpenGL/packer/pack_shaders.c    |    8 +-
 src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp   |   66 +-
 .../GuestHost/OpenGL/state_tracker/dump_gen.py     |    8 +-
 .../OpenGL/state_tracker}/get_components.py        |    4 +-
 .../GuestHost/OpenGL/state_tracker/state_get.py    |    2 +
 .../GuestHost/OpenGL/state_tracker/state_glsl.c    |    2 +-
 .../GuestHost/OpenGL/state_tracker/state_point.c   |  245 +
 .../OpenGL/state_tracker/state_snapshot.c          |   21 +-
 .../GuestHost/OpenGL/state_tracker/state_texture.c |   24 +-
 src/VBox/GuestHost/OpenGL/util/blitter.cpp         | 2886 ++++++----
 src/VBox/GuestHost/OpenGL/util/bmpscale.cpp        |  319 ++
 src/VBox/GuestHost/OpenGL/util/compositor.cpp      | 1015 ++++
 src/VBox/GuestHost/OpenGL/util/error.c             |    2 +
 src/VBox/GuestHost/OpenGL/util/hash.c              |   12 +-
 src/VBox/GuestHost/OpenGL/util/htable.cpp          |  195 +
 src/VBox/GuestHost/OpenGL/util/net.c               |   18 +-
 src/VBox/GuestHost/OpenGL/util/vboxhgcm.c          |  130 +-
 src/VBox/GuestHost/OpenGL/util/vreg.cpp            | 1046 +---
 src/VBox/HostDrivers/Support/SUPDrv.c              |    2 +-
 .../VBoxNetAdp/darwin/VBoxNetAdp-darwin.cpp        |   55 +-
 .../VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp        |   41 +
 .../VBoxNetFlt/win/nobj/VBoxNetFltNobj.h           |    6 +-
 .../VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h         |    6 +-
 src/VBox/HostDrivers/darwin/VBoxNetSend.h          |  107 +
 src/VBox/HostServices/SharedOpenGL/Makefile.kmk    |    4 +-
 .../SharedOpenGL/OpenGLTest/OpenGLTest.cpp         |    2 +-
 .../SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp   |    2 +-
 .../SharedOpenGL/crserver/crservice.cpp            |  255 +-
 .../HostServices/SharedOpenGL/crserverlib/server.h |  228 +-
 .../SharedOpenGL/crserverlib/server_clear.c        |    6 -
 .../SharedOpenGL/crserverlib/server_config.c       |   99 +-
 .../SharedOpenGL/crserverlib/server_context.c      |   34 +-
 .../SharedOpenGL/crserverlib/server_dispatch.py    |   11 +-
 .../SharedOpenGL/crserverlib/server_get.py         |    4 +-
 .../SharedOpenGL/crserverlib/server_getshaders.c   |   14 +-
 .../SharedOpenGL/crserverlib/server_glsl.c         |    6 +-
 .../SharedOpenGL/crserverlib/server_lists.c        |   12 +-
 .../SharedOpenGL/crserverlib/server_main.c         |  740 ++-
 .../SharedOpenGL/crserverlib/server_misc.c         |  325 +-
 .../SharedOpenGL/crserverlib/server_muralfbo.c     | 1364 -----
 .../SharedOpenGL/crserverlib/server_muralfbo.cpp   |  836 +++
 .../SharedOpenGL/crserverlib/server_presenter.cpp  | 4788 ++++++++++++++---
 .../SharedOpenGL/crserverlib/server_rpw.cpp        |   10 +-
 .../SharedOpenGL/crserverlib/server_simpleget.py   |    9 +-
 .../SharedOpenGL/crserverlib/server_special        |   10 +
 .../SharedOpenGL/crserverlib/server_stream.c       |    2 +-
 .../SharedOpenGL/crserverlib/server_texture.c      |   53 +
 .../SharedOpenGL/crserverlib/server_window.c       |  481 +-
 .../HostServices/SharedOpenGL/render/renderspu.c   |   79 +-
 .../HostServices/SharedOpenGL/render/renderspu.h   |   36 +-
 .../SharedOpenGL/render/renderspu_agl.c            |    2 +-
 .../SharedOpenGL/render/renderspu_cocoa.c          |  199 +-
 .../SharedOpenGL/render/renderspu_cocoa_helper.h   |    4 +-
 .../SharedOpenGL/render/renderspu_cocoa_helper.m   |  417 +-
 .../SharedOpenGL/render/renderspu_glx.c            |   11 +-
 .../SharedOpenGL/render/renderspu_init.c           |    5 +-
 .../SharedOpenGL/render/renderspu_wgl.c            |   11 +-
 .../SharedOpenGL/unpacker/unpack_shaders.c         |   25 +-
 .../darwin/VirtualBox_mpkg/Localizable.strings     |    2 +-
 src/VBox/Installer/linux/Makefile.kmk              |    3 +-
 src/VBox/Installer/linux/install.sh                |    2 +-
 src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec  |    4 +-
 src/VBox/Installer/linux/scripts/install.sh        |    4 +-
 src/VBox/Installer/solaris/smf-vboxautostart.sh    |   28 +-
 src/VBox/Installer/solaris/vboxconfig.sh           |    5 +-
 .../Installer/solaris/virtualbox-autostart.xml     |    1 +
 src/VBox/Installer/win/VirtualBox.wxs              |    7 +
 src/VBox/Main/Makefile.kmk                         |   30 +-
 .../{VBoxXPCOMCGlue.c => LegacyVBoxXPCOMCGlue.c}   |  191 +-
 ...{VBoxXPCOMCGlue.h.in => LegacyVBoxXPCOMCGlue.h} |   29 +-
 src/VBox/Main/cbinding/Makefile.kmk                |  164 +-
 src/VBox/Main/cbinding/VBoxCAPI.cpp                |  924 ++++
 .../cbinding/{VBoxXPCOMCGlue.c => VBoxCAPIGlue.c}  |  189 +-
 .../{VBoxXPCOMCGlue.h.in => VBoxCAPIGlue.h.in}     |   30 +-
 src/VBox/Main/cbinding/VBoxXPCOMC.cpp              |  492 --
 src/VBox/Main/cbinding/{xpcidl.xsl => capiidl.xsl} | 1549 ++++--
 src/VBox/Main/cbinding/makefile.tstCAPIGlue        |   50 +
 src/VBox/Main/cbinding/makefile.tstXPCOMCGlue      |   39 -
 src/VBox/Main/cbinding/tstCAPIGlue.c               | 1112 ++++
 src/VBox/Main/cbinding/tstXPCOMCGlue.c             |  822 ---
 src/VBox/Main/glue/glue-java.xsl                   |    8 +-
 src/VBox/Main/glue/initterm.cpp                    |   16 +-
 src/VBox/Main/idl/VirtualBox.xidl                  |   17 +-
 src/VBox/Main/idl/apiwrap-server.xsl               |   43 +-
 src/VBox/Main/idl/midl.xsl                         |    3 +-
 src/VBox/Main/idl/xpidl.xsl                        |   45 +-
 src/VBox/Main/idl/xpidl_iid.xsl                    |  154 +
 src/VBox/Main/include/ApplianceImpl.h              |   21 +-
 src/VBox/Main/include/ApplianceImplPrivate.h       |    1 -
 src/VBox/Main/include/ConsoleImpl.h                |    3 +-
 src/VBox/Main/include/DHCPServerImpl.h             |   18 +-
 src/VBox/Main/include/DisplayImpl.h                |   70 +-
 src/VBox/Main/include/HostPower.h                  |    8 +-
 src/VBox/Main/include/Wrapper.h                    |   39 +-
 src/VBox/Main/include/netif.h                      |   12 +-
 src/VBox/Main/include/ovfreader.h                  |    9 +-
 src/VBox/Main/src-all/Global.cpp                   |   58 +-
 src/VBox/Main/src-client/ConsoleImpl.cpp           |   48 +-
 src/VBox/Main/src-client/ConsoleImpl2.cpp          |  242 +-
 src/VBox/Main/src-client/DisplayImpl.cpp           |  763 ++-
 src/VBox/Main/src-client/GuestDirectoryImpl.cpp    |    6 +-
 src/VBox/Main/src-client/USBDeviceImpl.cpp         |    4 +-
 src/VBox/Main/src-client/VideoRec.cpp              |   28 +
 src/VBox/Main/src-client/VideoRec.h                |    3 +-
 src/VBox/Main/src-server/ApplianceImpl.cpp         |   53 +-
 src/VBox/Main/src-server/ApplianceImplExport.cpp   |  128 +-
 src/VBox/Main/src-server/ApplianceImplImport.cpp   |  109 +-
 src/VBox/Main/src-server/BandwidthControlImpl.cpp  |   24 +-
 src/VBox/Main/src-server/BandwidthGroupImpl.cpp    |    9 +-
 src/VBox/Main/src-server/DHCPServerImpl.cpp        |  134 +-
 src/VBox/Main/src-server/HostDnsService.cpp        |   72 +-
 src/VBox/Main/src-server/HostDnsService.h          |   61 +-
 .../Main/src-server/HostDnsServiceResolvConf.cpp   |   95 +-
 src/VBox/Main/src-server/HostPower.cpp             |   94 +-
 src/VBox/Main/src-server/MachineImpl.cpp           |    7 +
 src/VBox/Main/src-server/NATNetworkImpl.cpp        |   17 +-
 src/VBox/Main/src-server/NetworkServiceRunner.cpp  |    2 +-
 .../src-server/darwin/HostDnsServiceDarwin.cpp     |  155 +-
 src/VBox/Main/src-server/generic/NetIf-generic.cpp |    2 +-
 .../Main/src-server/linux/HostDnsServiceLinux.cpp  |  172 +-
 src/VBox/Main/src-server/os2/NetIf-os2.cpp         |    9 +-
 src/VBox/Main/src-server/win/HostDnsServiceWin.cpp |  112 +-
 src/VBox/Main/src-server/xpcom/server_module.cpp   |   87 +-
 src/VBox/Main/testcase/tstAPI.cpp                  |    8 +-
 src/VBox/Main/testcase/tstOVF.cpp                  |   13 +-
 src/VBox/Main/testcase/tstVBoxAPIXPCOM.cpp         |    3 +-
 src/VBox/Main/webservice/websrv-cpp.xsl            |    3 +-
 src/VBox/Main/webservice/websrv-php.xsl            |    6 +-
 src/VBox/Main/webservice/websrv-python.xsl         |    7 +-
 src/VBox/Main/xml/Settings.cpp                     |    9 +-
 src/VBox/Main/xml/ovfreader.cpp                    |    8 +-
 src/VBox/NetworkServices/DHCP/ClientDataInt.h      |   67 +
 src/VBox/NetworkServices/DHCP/Config.cpp           |  306 +-
 src/VBox/NetworkServices/DHCP/Config.h             |   47 +-
 src/VBox/NetworkServices/DHCP/Makefile.kmk         |    4 +-
 .../NetworkServices/DHCP/NetworkManagerDhcp.cpp    |  188 +
 src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp      |  540 +-
 src/VBox/NetworkServices/NAT/Makefile.kmk          |   30 +-
 src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp    |  671 +--
 src/VBox/NetworkServices/NAT/fwtcp.c               |    2 +-
 src/VBox/NetworkServices/NAT/fwudp.c               |    1 +
 src/VBox/NetworkServices/NAT/portfwd.c             |    1 -
 src/VBox/NetworkServices/NAT/proxy.c               |   16 +-
 src/VBox/NetworkServices/NAT/proxy.h               |    7 +-
 src/VBox/NetworkServices/NAT/proxy_pollmgr.c       |    4 +-
 src/VBox/NetworkServices/NAT/proxy_rtadvd.c        |    2 +-
 src/VBox/NetworkServices/NAT/pxdns.c               |   39 +-
 src/VBox/NetworkServices/NAT/pxping.c              | 1937 +++++++
 src/VBox/NetworkServices/NAT/pxping_win.c          |  629 +++
 src/VBox/NetworkServices/NAT/pxremap.c             |    1 -
 src/VBox/NetworkServices/NAT/pxtcp.c               |    9 +-
 src/VBox/NetworkServices/NAT/pxudp.c               |    1 +
 src/VBox/NetworkServices/NAT/winutils.h            |   79 +-
 src/VBox/NetworkServices/NetLib/ComHostUtils.cpp   |  215 +
 .../NetworkServices/NetLib/VBoxNetBaseService.cpp  |  488 +-
 .../NetworkServices/NetLib/VBoxNetBaseService.h    |  140 +-
 src/VBox/NetworkServices/NetLib/cpp/utils.h        |   34 +
 src/VBox/NetworkServices/NetLib/shared_ptr.h       |   17 +-
 src/VBox/NetworkServices/NetLib/utils.h            |  133 +
 src/VBox/Resources/OSE/virtualbox.svg              |  960 ++++
 src/VBox/Runtime/Makefile.kmk                      |   49 +-
 src/VBox/Runtime/common/asm/ASMCpuIdExSlow.asm     |  136 +
 src/VBox/Runtime/common/asm/ASMRdMsrEx.asm         |   84 +
 src/VBox/Runtime/common/asm/ASMWrMsrEx.asm         |   79 +
 src/VBox/Runtime/common/checksum/manifest.cpp      |    1 -
 src/VBox/Runtime/common/zip/tar.cpp                |   91 +-
 src/VBox/Runtime/generic/env-generic.cpp           |   93 +-
 src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c   |    8 +-
 src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c  |   12 +-
 src/VBox/Runtime/r0drv/linux/the-linux-kernel.h    |    4 +
 .../Runtime/r3/darwin/rtProcInitExePath-darwin.cpp |   11 +-
 src/VBox/Runtime/r3/linux/mp-linux.cpp             |   22 +-
 src/VBox/Runtime/r3/posix/env-posix.cpp            |   41 +-
 src/VBox/Runtime/r3/win/env-win.cpp                |  268 +
 src/VBox/Runtime/r3/win/process-win.cpp            |   18 +-
 src/VBox/Runtime/testcase/tstRTInlineAsm.cpp       |   10 +
 src/VBox/Storage/testcase/Makefile.kmk             |    2 +-
 src/VBox/VMM/Makefile.kmk                          |   23 +-
 src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp                | 5506 +++++++++++++++++++
 src/VBox/VMM/VMMAll/CPUMAllRegs.cpp                |  357 +-
 src/VBox/VMM/VMMAll/EMAll.cpp                      |   19 +-
 src/VBox/VMM/VMMAll/IEMAll.cpp                     |    2 +-
 src/VBox/VMM/VMMAll/MMAll.cpp                      |    4 +
 src/VBox/VMM/VMMAll/MMAllHyper.cpp                 |   18 +-
 src/VBox/VMM/VMMAll/PDMAllCritSect.cpp             |   42 +-
 src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp           |   38 +-
 src/VBox/VMM/VMMAll/SELMAll.cpp                    |   47 +-
 src/VBox/VMM/VMMR0/CPUMR0.cpp                      |  102 +-
 src/VBox/VMM/VMMR0/HMR0.cpp                        |    2 +-
 src/VBox/VMM/VMMR0/HMSVMR0.cpp                     |    8 +-
 src/VBox/VMM/VMMR0/HMVMXR0.cpp                     |    9 +-
 src/VBox/VMM/VMMR3/CPUM.cpp                        | 1150 ++--
 src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp                 | 1312 +++++
 src/VBox/VMM/VMMR3/CPUMR3Db.cpp                    |  769 +++
 src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp               |   12 +-
 src/VBox/VMM/VMMR3/EM.cpp                          |    2 +-
 src/VBox/VMM/VMMR3/MMHyper.cpp                     |    7 +-
 src/VBox/VMM/VMMR3/PGM.cpp                         |    1 +
 src/VBox/VMM/VMMR3/VM.cpp                          |    2 +-
 src/VBox/VMM/VMMR3/VMM.cpp                         |    4 +-
 src/VBox/VMM/VMMR3/VMMTests.cpp                    |  334 ++
 src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h       |  219 +
 src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h   |  378 ++
 src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h   |  267 +
 src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h       |  334 ++
 src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h     |  382 ++
 src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h      |  364 ++
 src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h  |  272 +
 .../VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h |  211 +
 src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h |  240 +
 src/VBox/VMM/VMMR3/cpus/Makefile.kup               |    0
 .../VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h    |  265 +
 .../VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h    |  399 ++
 src/VBox/VMM/VMMRC/SELMRC.cpp                      |    6 +-
 src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp              |   16 +
 src/VBox/VMM/VMMRC/VMMRC.cpp                       |   80 +-
 src/VBox/VMM/VMMRC/VMMRCA.asm                      |   85 +
 src/VBox/VMM/VMMRZ/VMMRZ.cpp                       |   21 +-
 src/VBox/VMM/include/CPUMInternal.h                |  706 ++-
 src/VBox/VMM/include/CPUMInternal.mac              |   20 +-
 src/VBox/VMM/include/SELMInline.h                  |    2 +-
 src/VBox/VMM/include/VMMInternal.h                 |   17 +
 src/VBox/VMM/testcase/tstVMM.cpp                   |   29 +-
 src/VBox/VMM/testcase/tstVMStruct.h                |    3 -
 src/VBox/VMM/{Preload => tools}/Makefile.kmk       |   23 +-
 src/VBox/VMM/tools/VBoxCpuReport.cpp               | 4687 +++++++++++++++++
 src/VBox/VMM/{Preload => tools}/VBoxVMMPreload.cpp |    0
 .../{Preload => tools}/VBoxVMMPreloadHardened.cpp  |    0
 src/apps/adpctl/VBoxNetAdpCtl.cpp                  |   26 +-
 src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp      |    5 +-
 425 files changed, 55744 insertions(+), 16173 deletions(-)

diff --git a/Config.kmk b/Config.kmk
index 8125b2d..44320d5 100644
--- a/Config.kmk
+++ b/Config.kmk
@@ -7,7 +7,7 @@
 #
 
 #
-# Copyright (C) 2006-2013 Oracle Corporation
+# Copyright (C) 2006-2014 Oracle Corporation
 #
 # This file is part of VirtualBox Open Source Edition (OSE), as
 # available from http://www.virtualbox.org. This file is free software;
@@ -206,7 +206,7 @@ VBOX_VERSION_MINOR = 3
 # 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 = 6
+VBOX_VERSION_BUILD = 8
 # 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.
@@ -372,6 +372,8 @@ VBOX_WITH_DEBUGGER_GUI = 1
 VBOX_WITH_PDM_LOCK = 1
 # Enables the first step using IEM (the interpreter).
 VBOX_WITH_FIRST_IEM_STEP = 1
+# Enables the new MSR code.
+VBOX_WITH_NEW_MSR_CODE = 1
 ## @}
 
 
@@ -417,8 +419,10 @@ if1of ($(KBUILD_TARGET), linux solaris)
 endif
 # Disable WINMM support for Windows (not implemented).
 VBOX_WITH_WINMM =
-# Enabled internal networking.
+# Enable internal networking.
 VBOX_WITH_INTERNAL_NETWORKING = 1
+# Enable vmsvga (svga2) graphics device variant, 2D part
+VBOX_WITH_VMSVGA = 1
 # Enable Host Guest Shared Memory Interface.
 VBOX_WITH_HGSMI = 1
 # Enable Video 2D Acceleration.
@@ -831,6 +835,7 @@ VBOX_BRAND_GUI_VBOX_32PX_PNG         := $(PATH_ROOT)/src/VBox/Frontends/VirtualB
 VBOX_BRAND_GUI_VBOX_40PX_PNG         := $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/NonOSE/VirtualBox_40px.png
 VBOX_BRAND_GUI_VBOX_48PX_PNG         := $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/NonOSE/VirtualBox_48px.png
 VBOX_BRAND_GUI_VBOX_64PX_PNG         := $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/NonOSE/VirtualBox_64px.png
+VBOX_BRAND_GUI_VBOX_SVG              := $(PATH_ROOT)/src/VBox/Resources/NonOSE/virtualbox.svg
 VBOX_BRAND_WIN_INST_DLGJPG           := $(PATH_ROOT)/src/VBox/Installer/win/Binary/Dialog.jpg
 VBOX_BRAND_WIN_INST_EXT              :=
 VBOX_BRAND_WIN_ADD_INST_DLGBMP       := $(PATH_ROOT)/src/VBox/Additions/WINNT/Installer/welcome.bmp
@@ -1063,6 +1068,7 @@ ifdef VBOX_OSE
  VBOX_BRAND_GUI_VBOX_48PX_PNG  := $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/OSE/VirtualBox_48px.png
  VBOX_BRAND_GUI_VBOX_64PX_PNG  := $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/OSE/VirtualBox_64px.png
  VBOX_BRAND_GUI_CUBE_42PX_PNG  := $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/OSE/VirtualBox_cube_42px.png
+ VBOX_BRAND_GUI_VBOX_SVG       := $(PATH_ROOT)/src/VBox/Resources/OSE/virtualbox.svg
 endif
 
 #
@@ -2564,7 +2570,7 @@ ifdef VBOX_SIGNING_MODE
    VBOX_CERTIFICATE_SUBJECT_NAME_ARGS ?= /n "$(VBOX_CERTIFICATE_SUBJECT_NAME)"
   else if1of ($(VBOX_SIGNING_MODE), release development)
    VBOX_CERTIFICATE_SUBJECT_NAME ?= Oracle Corporation
-   VBOX_CERTIFICATE_SUBJECT_NAME_ARGS ?= /n "$(VBOX_CERTIFICATE_SUBJECT_NAME)"
+   VBOX_CERTIFICATE_SUBJECT_NAME_ARGS ?= /n "$(VBOX_CERTIFICATE_SUBJECT_NAME)" /a
    VBOX_CROSS_CERTIFICATE_FILE ?= $(VBOX_PATH_SELFSIGN)/MSCV-VSClass3.cer
    VBOX_CROSS_CERTIFICATE_FILE_ARGS ?= /ac "$(VBOX_CROSS_CERTIFICATE_FILE)"
    VBOX_TSA_URL ?= http://timestamp.verisign.com/scripts/timestamp.dll
@@ -3757,7 +3763,7 @@ endif
 #
 TEMPLATE_VBOXR3STATIC                  = VBox Static Ring 3 EXE
 TEMPLATE_VBOXR3STATIC_EXTENDS          = VBOXR3EXE
-TEMPLATE_VBOXR3STATIC_DEFS             = IN_RT_STATIC IN_RT_R3 $(TEMPLATE_VBOXR3EXE_DEFS)
+TEMPLATE_VBOXR3STATIC_DEFS             = IN_RT_STATIC IN_RT_R3 IN_SUP_STATIC $(TEMPLATE_VBOXR3EXE_DEFS)
 ifeq ($(KBUILD_TARGET),win)
  TEMPLATE_VBOXR3STATIC_CFLAGS          = $(filter-out -MD$(VBOX_VCC_CRT_TYPE), $(TEMPLATE_VBOXR3EXE_CFLAGS)) -MT$(VBOX_VCC_CRT_TYPE)
  TEMPLATE_VBOXR3STATIC_CXXFLAGS        = $(filter-out -MD$(VBOX_VCC_CRT_TYPE), $(TEMPLATE_VBOXR3EXE_CFLAGS)) -MT$(VBOX_VCC_CRT_TYPE)
@@ -4190,7 +4196,7 @@ TEMPLATE_VBOXMAINEXE_LDFLAGS.x86         = -m32
 TEMPLATE_VBOXMAINEXE_LDFLAGS.amd64       = -m64
  ifeq ($(KBUILD_TARGET),linux)
 TEMPLATE_VBOXMAINEXE_LIBS                = pthread m rt $(LIB_RUNTIME) dl
-TEMPLATE_VBOXMAINEXE_LDFLAGS.linux       = $(VBOX_LD_as_needed)
+TEMPLATE_VBOXMAINEXE_LDFLAGS.linux       = -Wl,-z,noexecstack $(VBOX_LD_as_needed)
  else ifeq ($(KBUILD_TARGET),os2)
 TEMPLATE_VBOXMAINEXE_TOOL                = GXX3OMF
 TEMPLATE_VBOXMAINEXE_LIBS                = $(LIB_RUNTIME)
@@ -4649,7 +4655,7 @@ ifdef VBOX_WITH_QTGUI
 	$(VBOX_LIB_VMM_LAZY)
 
   ifeq ($(KBUILD_TARGET),linux)
-   TEMPLATE_VBOXQT4GUIEXE_LDFLAGS += $(VBOX_LD_as_needed)
+   TEMPLATE_VBOXQT4GUIEXE_LDFLAGS += -Wl,-z,noexecstack $(VBOX_LD_as_needed)
    TEMPLATE_VBOXQT4GUIEXE_LIBS += \
      $(VBOX_XCURSOR_LIBS) \
 	Xext \
@@ -5022,25 +5028,6 @@ TEMPLATE_NewVBoxGuestR3Exe_LIBS     = \
 	$(VBOX_LIB_VBGL_R3) \
 	$(VBOX_LIB_IPRT_GUEST_R3) \
 	$(TEMPLATE_VBOXGUESTR3EXE_LIBS)
-ifeq ($(KBUILD_TARGET),linux)
- TEMPLATE_NewVBoxGuestR3Exe_LIBS   += crypt
-endif
-
-#
-# Template for building normal 32-bit R3 programs for the guest additions.
-#
-TEMPLATE_NewVBoxGuestR3Exe_X86              = 32-bit VBox Guest Program w/ IPRT and VBGL.
-TEMPLATE_NewVBoxGuestR3Exe_X86_EXTENDS      = NewVBoxGuestR3Exe
-TEMPLATE_NewVBoxGuestR3Exe_X86_BLD_TRG_ARCH = x86
-TEMPLATE_NewVBoxGuestR3Exe_X86_LIBS         = \
-	$(VBOX_LIB_IPRT_GUEST_R3_X86) \
-	$(VBOX_LIB_VBGL_R3_X86) \
-	$(VBOX_LIB_IPRT_GUEST_R3_X86) \
-	$(TEMPLATE_VBOXGUESTR3EXE_LIBS)
-ifeq ($(KBUILD_TARGET),linux)
- TEMPLATE_NewVBoxGuestR3Exe_X86_LIBS       += crypt
-endif
-TEMPLATE_NewVBoxGuestR3Exe_X86_INST         = $(INST_ADDITIONS)/32/
 
 #
 # Template for building R3 (dynamic) libraries for the guest additions.
@@ -5056,14 +5043,6 @@ ifn1of ($(KBUILD_TARGET), darwin os2 win)
 endif
 
 #
-# Template for building normal 32-bit R3 programs for the guest additions.
-#
-TEMPLATE_VBOXGUESTR3DLL_X86              = 32-bit VBox Guest User Dynamic Libraries
-TEMPLATE_VBOXGUESTR3DLL_X86_EXTENDS      = VBOXGUESTR3DLL
-TEMPLATE_VBOXGUESTR3DLL_X86_BLD_TRG_ARCH = x86
-TEMPLATE_VBOXGUESTR3DLL_X86_INST         = $(INST_ADDITIONS)/32/
-
-#
 # Template for building normal R3 (dynamic) libraries for the guest additions, allows warnings.
 #
 ## @todo rename to VBoxGuestR3DllWarn
@@ -5181,7 +5160,7 @@ ifeq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
 endif
 TEMPLATE_VBOXGUESTR3XF86MOD_SYSSUFF = .o
 TEMPLATE_VBOXGUESTR3XF86MOD_LIBS  = \
-        $(VBOX_LIB_VBGL_R3_XFREE86)
+	$(VBOX_LIB_VBGL_R3_XFREE86)
 TEMPLATE_VBOXGUESTR3XF86MOD_DEFS  = $(TEMPLATE_VBOXGUESTR3DLL_DEFS) VBOX_GUESTR3XF86MOD RTMEM_NO_WRAP_TO_EF_APIS
 
 
@@ -5194,27 +5173,6 @@ TEMPLATE_VBOXGUESTR3XF86LIB_INST    = $(INST_ADDITIONS_LIB)
 
 
 #
-# Template for 32-bit XFree86 guest modules (relocatable module, i.e. sysmod).
-#
-TEMPLATE_VBOXGUESTR3XF86MOD_X86      = 32-bit VBox X.org Guest Module
-TEMPLATE_VBOXGUESTR3XF86MOD_X86_EXTENDS = VBOXGUESTR3XF86MOD
-TEMPLATE_VBOXGUESTR3XF86MOD_X86_BLD_TRG_ARCH = x86
-TEMPLATE_VBOXGUESTR3XF86MOD_X86_DEFS = \
-	$(filter-out _XSERVER64,$(TEMPLATE_VBOXGUESTR3XF86MOD_DEFS))
-TEMPLATE_VBOXGUESTR3XF86MOD_X86_LIBS = \
-	$(VBOX_LIB_VBGL_R3_XFREE86_X86)
-TEMPLATE_VBOXGUESTR3XF86MOD_X86_INST = $(INST_ADDITIONS)/32/
-
-
-#
-# Template for 32-bit XFree86 guest libraries.
-#
-TEMPLATE_VBOXGUESTR3XF86LIB_X86         = 32-bit VBox XFree86 Guest Library
-TEMPLATE_VBOXGUESTR3XF86LIB_X86_EXTENDS = VBOXGUESTR3XF86LIB
-TEMPLATE_VBOXGUESTR3XF86LIB_X86_BLD_TRG_ARCH = x86
-
-
-#
 # Template for X.org guest modules (shared libs).
 # This mostly about zapping unnecessary LIBS from VBOXGUESTR3DLL and adding some flags.
 #
@@ -5246,22 +5204,6 @@ TEMPLATE_VBOXGUESTR3XORGMOD_LIBS.freebsd += \
 
 
 #
-# Template for 32-bit X.org guest modules (shared libs).
-#
-TEMPLATE_VBOXGUESTR3XORGMOD_X86      = 32-bit VBox X.org Guest Module
-TEMPLATE_VBOXGUESTR3XORGMOD_X86_EXTENDS = VBOXGUESTR3XORGMOD
-TEMPLATE_VBOXGUESTR3XORGMOD_X86_BLD_TRG_ARCH = x86
-TEMPLATE_VBOXGUESTR3XORGMOD_X86_DEFS = \
-	$(filter-out _XSERVER64,$(TEMPLATE_VBOXGUESTR3XORGMOD_DEFS))
-TEMPLATE_VBOXGUESTR3XORGMOD_X86_LIBS = \
-	$(VBOX_LIB_VBGL_R3_SHARED_X86) \
-	$(VBOX_LIB_IPRT_GUEST_R3_MINI_X86) \
-	$(VBOX_LIB_VBGL_R3_SHARED_X86) \
-	$(VBOX_LIB_IPRT_GUEST_R3_MINI_X86)
-TEMPLATE_VBOXGUESTR3XORGMOD_X86_INST = $(INST_ADDITIONS)/32/
-
-
-#
 # Template for building R0 drivers for the guest additions.
 #
 TEMPLATE_VBOXGUESTR0             = VBox Guest Driver
@@ -5389,15 +5331,11 @@ VBOX_LIB_VBGL_R0BASE             = $(VBOX_PATH_ADDITIONS_LIB)/VBoxGuestR0LibBase
 VBOX_LIB_VBGL_R0                 = $(VBOX_PATH_ADDITIONS_LIB)/VBoxGuestR0Lib$(VBOX_SUFF_LIB)
 ifeq ($(KBUILD_TARGET),x86)
  VBOX_LIB_IPRT_GUEST_R3_X86      = $(VBOX_LIB_IPRT_GUEST_R3)
- VBOX_LIB_IPRT_GUEST_R3_MINI_X86 = $(VBOX_LIB_IPRT_GUEST_R3_MINI)
- VBOX_LIB_VBGL_R3_XFREE86_X86    = $(VBOX_LIB_VBGL_R3_XFREE86)
  VBOX_LIB_IPRT_GUEST_R3_SHARED_X86 = $(VBOX_LIB_IPRT_GUEST_R3_SHARED)
  VBOX_LIB_VBGL_R3_X86            = $(VBOX_LIB_VBGL_R3)
  VBOX_LIB_VBGL_R3_SHARED_X86     = $(VBOX_LIB_VBGL_R3_SHARED)
 else
  VBOX_LIB_IPRT_GUEST_R3_X86      = $(VBOX_PATH_ADDITIONS_LIB)/RuntimeGuestR3-x86$(VBOX_SUFF_LIB)
- VBOX_LIB_IPRT_GUEST_R3_MINI_X86 = $(VBOX_PATH_ADDITIONS_LIB)/RuntimeGuestR3Mini-x86$(VBOX_SUFF_LIB)
- VBOX_LIB_VBGL_R3_XFREE86_X86    = $(VBOX_PATH_ADDITIONS_LIB)/VBoxGuestR3LibXFree86-x86$(VBOX_SUFF_LIB)
  VBOX_LIB_IPRT_GUEST_R3_SHARED_X86 = $(VBOX_PATH_ADDITIONS_LIB)/RuntimeGuestR3Shared-x86$(VBOX_SUFF_LIB)
  VBOX_LIB_VBGL_R3_X86            = $(VBOX_PATH_ADDITIONS_LIB)/VBoxGuestR3Lib-x86$(VBOX_SUFF_LIB)
  VBOX_LIB_VBGL_R3_SHARED_X86     = $(VBOX_PATH_ADDITIONS_LIB)/VBoxGuestR3LibShared-x86$(VBOX_SUFF_LIB)
@@ -5590,7 +5528,7 @@ endif
 SVN                    ?= svn$(HOSTSUFF_EXE)
 VBOX_SVN_REV_KMK        = $(PATH_OUT)/revision.kmk
 ifndef VBOX_SVN_REV
- VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 91406 $  )
+ VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 92456 $  )
  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         :=
@@ -5603,11 +5541,7 @@ $(VBOX_SVN_REV_KMK).ts +| $(VBOX_SVN_REV_KMK): $(if $(VBOX_SVN_DEP), $(VBOX_SVN_
 	$(QUIET)$(MKDIR) -p $(@D)
  ifneq ($(VBOX_SVN_DEP),)
 	$(REDIRECT) -E 'LC_ALL=C' -wo $@.tmp -- $(SVN) info $(PATH_ROOT)
-  ifeq ($(int-mod $(VBOX_VERSION_BUILD), 2),0)
 	$(SED) -e '/^Last Changed Rev/!d'  -e 's/Last Changed Rev\: */export VBOX_SVN_REV=/' --output $@ $@.tmp
-  else
-	$(SED) -e '/^Revision/!d'  -e 's/Revision\: */export VBOX_SVN_REV=/' --output $@ $@.tmp
-  endif
 	$(QUIET)$(RM) -f $@.tmp
  else
 	$(QUIET)$(APPEND) $@ 'export VBOX_SVN_REV=$(VBOX_SVN_REV_FALLBACK)'
diff --git a/doc/manual/Makefile.kmk b/doc/manual/Makefile.kmk
index 4b3d12d..4411d06 100644
--- a/doc/manual/Makefile.kmk
+++ b/doc/manual/Makefile.kmk
@@ -317,7 +317,7 @@ $(foreach f,$(VBOX_MANUAL_LANGUAGES),$(VBOX_PATH_MANUAL_OUTBASE)/$f/user_ChangeL
 	$(QUIET)$(SED) -e '1,/<!--\$$VIRTUALBOX_CHANGELOG_IMPL-->/!d' \
 	               -e 's/<!--\$$VIRTUALBOX_CHANGELOG_IMPL-->//' \
 	               --output $@ $@.tmp
-	var=`$(SED) -n '/!--\$$VIRTUALBOX_CHANGELOG_IMPL-->/p' $<`; \
+	$(QUIET)var=`$(SED) -n '/!--\$$VIRTUALBOX_CHANGELOG_IMPL-->/p' $<`; \
 	               test -n "$${var}" && \
 	               $(SED) -e 's/<?xml version=\"1.0\" encoding=\"UTF-8\"?>//g' \
 	                       --append $@ $(VBOX_PATH_MANUAL_SRC)/user_ChangeLogImpl.xml; \
diff --git a/doc/manual/en_US/SDKRef.xml b/doc/manual/en_US/SDKRef.xml
index 42f40ff..e8c63cc 100644
--- a/doc/manual/en_US/SDKRef.xml
+++ b/doc/manual/en_US/SDKRef.xml
@@ -1718,166 +1718,210 @@ print "Machine '%s' logs in '%s'" %(m.name, m.logFolder)
       </sect2>
 
       <sect2 id="cbinding">
-        <title>C binding to XPCOM API</title>
+        <title>C binding to VirtualBox API</title>
 
-        <note>
-          <para>This section currently applies to Linux, Mac OS X and Solaris
-          hosts only.</para>
-        </note>
+        <para>The VirtualBox API originally is designed as object oriented,
+        using XPCOM or COM as the middleware, which translates natively to C++.
+        This means that in order to use it from C there needs to be some
+        helper code to bridge the language differences and reduce the
+        differences between platforms.</para>
 
-        <para>Starting with version 2.2, VirtualBox offers a C binding for the
-        XPCOM API.</para>
+        <sect3 id="capi_glue">
+          <title>Cross-platform C binding to VirtualBox API</title>
 
-        <para>The C binding provides a layer enabling object creation, method
-        invocation and attribute access from C.</para>
+            <para>Starting with version 4.3, VirtualBox offers a C binding
+            which allows using the same C client sources for all platforms,
+            covering Windows, Linux, Mac OS X and Solaris. It is the
+            preferred way to write API clients, even though the old style
+            is still available.</para>
+
+        </sect3>
 
         <sect3 id="c-gettingstarted">
           <title>Getting started</title>
 
-          <para>The following sections describe how to use the C binding in a
-          C program.</para>
+          <para>The following sections describe how to use the VirtualBox API
+          in a C program. The necessary files are included in the SDK, in the
+          directories <computeroutput>sdk/bindings/c/include</computeroutput>
+          and <computeroutput>sdk/bindings/c/glue</computeroutput>.</para>
 
-          <para>As part of the SDK, a sample program is provided which
-          demonstrates using the C binding to initialize XPCOM, get handles for
+          <para>As part of the SDK, a sample program
+          <computeroutput>tstCAPIGlue.c</computeroutput> is provided in the
+          directory <computeroutput>sdk/bindings/c/samples</computeroutput>
+          which demonstrates
+          using the C binding to initialize the API, get handles for
           VirtualBox and Session objects, make calls to list and start virtual
           machines, monitor events, and uninitialize resources when done. The
-          program uses the VBoxGlue library to open the C binding layer during
-          runtime.</para>
-
-          <para>The sample program
-          <computeroutput>tstXPCOMCGlue</computeroutput> is located in the bin
-          directory and can be run without arguments. It lists registered
-          machines on the host along with some additional information and ask
-          for a machine to start. The source for this program is available in
-          <computeroutput>sdk/bindings/xpcom/cbinding/samples/</computeroutput>
-          directory. The source for the VBoxGlue library is available in the
-          <computeroutput>sdk/bindings/xpcom/cbinding/</computeroutput>
-          directory.</para>
+          sample program is trying to illustrate all relevant concepts, so it
+          is a great source of detail information. Among many other generally
+          useful code sequences it contains a function which shows how to
+          retrieve error details in C code if they are available from the API
+          call.</para>
+
+          <para>The sample program <computeroutput>tstCAPIGlue</computeroutput>
+          can be built using the provided <computeroutput>Makefile</computeroutput>
+          and can be run without arguments.</para>
+          
+          <para>It uses the VBoxCAPIGlue library (source code is in directory
+          <computeroutput>sdk/bindings/c/glue</computeroutput>, to be used in
+          your API client code) to open the C binding layer during runtime,
+          which is preferred to other means as it isolates the code which
+          locates the necessary dynamic library, using a known working way
+          which works on all platforms. If you encounter problems with this
+          glue code in <computeroutput>VBoxCAPIGlue.c</computeroutput>, let the
+          VirtualBox developers know, rather than inventing incompatible
+          solutions.</para>
+
+          <para>The following sections document the important concepts needed
+          to correctly use the C binding, as it is vital for developing API
+          client code which manages memory correctly, updates the reference
+          counters correctly, avoiding crashes and memory leaks. Often API
+          clients need to handle events, so the C API specifics are also
+          described below.</para>
         </sect3>
 
         <sect3 id="c-initialization">
-          <title>XPCOM initialization</title>
-
-          <para>Just like in C++, XPCOM needs to be initialized before it can
-          be used. The <computeroutput>VBoxCAPI_v4_3.h</computeroutput> header
-          provides the interface to the C binding. Here's how to initialize
-          XPCOM:</para>
-
-          <screen>#include "VBoxCAPI_v4_3.h"
+          <title>VirtualBox C API initialization</title>
+
+          <para>Just like in C++, the API and the underlying middleware needs
+          to be initialized before it can be used. The
+          <computeroutput>VBoxCAPI_v4_3.h</computeroutput> header provides the
+          interface to the C binding, but you can alternatively and more
+          conveniently also include <computeroutput>VBoxCAPIGlue.h</computeroutput>,
+          as this avoids the VirtualBox version dependent header file name and
+          makes sure the global variable <code>g_pVBoxFuncs</code> contains a
+          pointer to the structure which contains the helper function pointers.
+          Here's how to initialize the C API:<screen>#include "VBoxCAPIGlue.h"
 ...
-PCVBOXXPCOM g_pVBoxFuncs = NULL;
-IVirtualBox *vbox        = NULL;
-ISession *session        = NULL;
+IVirtualBoxClient *vboxclient   = NULL;
+IVirtualBox *vbox               = NULL;
+ISession *session               = NULL;
+HRESULT rc;
+ULONG revision;
 
 /*
- * VBoxGetXPCOMCFunctions() is the only function exported by
- * VBoxXPCOMC.so and the only one needed to make virtualbox
- * work with C. This functions gives you the pointer to the
- * function table (g_pVBoxFuncs).
+ * VBoxCGlueInit() loads the necessary dynamic library, handles errors
+ * (producing an error message hinting what went wrong) and gives you
+ * the pointer to the function table (g_pVBoxFuncs).
  *
  * Once you get the function table, then how and which functions
  * to use is explained below.
  *
- * g_pVBoxFuncs->pfnComInitialize does all the necessary startup
- * action and provides us with pointers to vbox and session handles.
- * It should be matched by a call to g_pVBoxFuncs->pfnComUninitialize()
+ * g_pVBoxFuncs->pfnClientInitialize does all the necessary startup
+ * action and provides us with pointers to an IVirtualBoxClient instance.
+ * It should be matched by a call to g_pVBoxFuncs->pfnClientUninitialize()
  * when done.
  */
 
-g_pVBoxFuncs = VBoxGetXPCOMCFunctions(VBOX_XPCOMC_VERSION);
-g_pVBoxFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &vbox,
-                               ISESSION_IID_STR, &session);</screen>
-
-          <para>If either <computeroutput>vbox</computeroutput> or
-          <computeroutput>session</computeroutput> is still
-          <computeroutput>NULL</computeroutput>, initialization failed and the
-          XPCOM API cannot be used.</para>
-
-          <para>There is now also a way to use the
-          <xref linkend="IVirtualBoxClient" xreflabel="IVirtualBoxClient" />
-          helper interface, which in comparison to the original (and still
-          available) initialization method above simplifies creating multiple
-          sessions, and also allows handling termination and crashes of the API
-          server (VBoxSVC) in a graceful way. See the sample program how this
-          is used.</para>
+if (VBoxCGlueInit())
+{
+    fprintf(stderr, "s: FATAL: VBoxCGlueInit failed: %s\n",
+            argv[0], g_szVBoxErrMsg);
+    return EXIT_FAILURE;
+}
+    
+g_pVBoxFuncs->pfnClientInitialize(NULL, &vboxclient);
+if (!vboxclient)
+{
+    fprintf(stderr, "%s: FATAL: could not get VirtualBoxClient reference\n",
+            argv[0]);
+    return EXIT_FAILURE;
+}</screen></para>
+
+          <para>If <computeroutput>vboxclient</computeroutput> is still
+          <computeroutput>NULL</computeroutput> this means the initializationi
+          failed and the VirtualBox C API cannot be used.</para>
+
+          <para>It is possible to write C applications using multiple threads
+          which all use the VirtualBox API, as long as you're initializing
+          the C API in each thread which your application creates. This is done
+          with <code>g_pVBoxFuncs->pfnClientThreadInitialize()</code> and
+          likewise before the thread is terminated the API must be
+          uninitialized with
+          <code>g_pVBoxFuncs->pfnClientThreadUninitialize()</code>. You don't
+          have to use these functions in worker threads created by COM/XPCOM
+          (which you might observe if your code uses active event handling),
+          everything is initialized correctly already. On Windows the C
+          bindings create a marshaller which supports a wide range of COM
+          threading models, from STA to MTA, so you don't have to worry about
+          these details unless you plan to use active event handlers. See
+          the sample code how to get this to work reliably (in other words
+          think twice if passive event handling isn't the better solution after
+          you looked at the sample code).</para>
         </sect3>
 
         <sect3 id="c-invocation">
-          <title>XPCOM method invocation</title>
+          <title>C API attribute and method invocation</title>
 
           <para>Method invocation is straightforward. It looks pretty much
-          like the C++ way, augmented with an extra indirection due to
-          accessing the vtable and passing a pointer to the object as the
-          first argument to serve as the <computeroutput>this</computeroutput>
-          pointer.</para>
+          like the C++ way, by using a macro which internally accesses the
+          vtable, and additionally needs to be passed a pointer to the objecti
+          as the first argument to serve as the
+          <computeroutput>this</computeroutput> pointer.</para>
 
           <para>Using the C binding, all method invocations return a numeric
-          result code.</para>
+          result code of type <code>HRESULT</code> (with a few exceptions
+          which normally are not relevant).</para>
 
           <para>If an interface is specified as returning an object, a pointer
           to a pointer to the appropriate object must be passed as the last
           argument. The method will then store an object pointer in that
           location.</para>
 
-          <para>In other words, to call an object's method what you need
-          is</para>
+          <para>Likewise, attributes (properties) can be queried or set using
+          method invocations, using specially named methods. For each
+          attribute there exists a getter method, the name of which is composed
+          of <computeroutput>get_</computeroutput> followed by the capitalized
+          attribute name. Unless the attribute is read-only, an analogous
+          <computeroutput>set_</computeroutput> method exists. Let's apply
+          these rules to get the <computeroutput>IVirtualBox</computeroutput>
+          reference, an <computeroutput>ISession</computeroutput> instance 
+          reference and read the <xref linkend="IVirtualBox__revision"
+          xreflabel="IVirtualBox::revision" /> attribute:<screen>rc = IVirtualBoxClient_get_VirtualBox(vboxclient, &vbox);
+if (FAILED(rc) || !vbox)
+{
+    PrintErrorInfo(argv[0], "FATAL: could not get VirtualBox reference", rc);
+    return EXIT_FAILURE;
+}
+rc = IVirtualBoxClient_get_Session(vboxclient, &session);
+if (FAILED(rc) || !session)
+{
+    PrintErrorInfo(argv[0], "FATAL: could not get Session reference", rc);
+    return EXIT_FAILURE;
+}
+
+rc = IVirtualBox_get_Revision(vbox, &revision);
+if (SUCCEEDED(rc))
+{
+    printf("Revision: %u\n", revision);
+}</screen></para>
 
-          <screen>IObject *object;
-nsresult rc;
-...
-/*
- * Calling void IObject::method(arg, ...)
- */
-rc = object->vtbl->Method(object, arg, ...);
+          <para>The convenience macros for calling a method are named by
+          prepending the method name with the interface name (using
+          <code>_</code>as the separator).</para>
 
+          <para>So far only attribute getters were illustrated, but generic
+          method calls are straightforward, too:<screen>IMachine *machine = NULL;
+BSTR vmname = ...;
 ...
-IFoo *foo;
 /*
- * Calling IFoo IObject::method(arg, ...)
+ * Calling IMachine::findMachine(...)
  */
-rc = object->vtbl->Method(object, args, ..., &foo);</screen>
+rc = IVirtualBox_FindMachine(vbox, vmname, &machine);</screen></para>
 
-          <para>As a real-world example of a method invocation, let's call
-          <xref linkend="IMachine__launchVMProcess"
+          <para>As a more complicated example of a method invocation, let's
+          call <xref linkend="IMachine__launchVMProcess"
           xreflabel="IMachine::launchVMProcess" /> which returns an
           IProgress object. Note again that the method name is
-          capitalized.</para>
-
-          <screen>IProgress *progress;
+          capitalized:<screen>IProgress *progress;
 ...
-rc = vbox->vtbl->LaunchVMProcess(
+rc = IMachine_LaunchVMProcess(
     machine,       /* this  */
     session,       /* arg 1 */
     sessionType,   /* arg 2 */
     env,           /* arg 3 */
     &progress      /* Out   */
-);</screen>
-        </sect3>
-
-        <sect3 id="c-attributes">
-          <title>XPCOM attribute access</title>
-
-          <para>A construct similar to calling non-void methods is used to
-          access object attributes. For each attribute there exists a getter
-          method, the name of which is composed of
-          <computeroutput>Get</computeroutput> followed by the capitalized
-          attribute name. Unless the attribute is read-only, an analogous
-          <computeroutput>Set</computeroutput> method exists. Let's apply
-          these rules to read the <xref linkend="IVirtualBox__revision"
-          xreflabel="IVirtualBox::revision" /> attribute.</para>
-
-          <para>Using the <computeroutput>IVirtualBox</computeroutput> handle
-          <computeroutput>vbox</computeroutput> obtained above, calling its
-          <computeroutput>GetRevision</computeroutput> method looks like
-          this:</para>
-
-          <screen>PRUint32   rev;
-
-rc = vbox->vtbl->GetRevision(vbox, &rev);
-if (NS_SUCCEEDED(rc))
-{
-    printf("Revision: %u\n", (unsigned)rev);
-}</screen>
+);</screen></para>
 
           <para>All objects with their methods and attributes are documented
           in <xref linkend="sdkref_classes" />.</para>
@@ -1889,63 +1933,173 @@ if (NS_SUCCEEDED(rc))
           <para>When dealing with strings you have to be aware of a string's
           encoding and ownership.</para>
 
-          <para>Internally, XPCOM uses UTF-16 encoded strings. A set of
+          <para>Internally, the API uses UTF-16 encoded strings. A set of
           conversion functions is provided to convert other encodings to and
           from UTF-16. The type of a UTF-16 character is
-          <computeroutput>PRUnichar</computeroutput>. Strings of UTF-16
-          characters are arrays of that type. Most string handling functions
-          take pointers to that type. Prototypes for the following conversion
-          functions are declared in
-          <computeroutput>VBoxCAPI_v4_3.h</computeroutput>.</para>
-
-          <sect4>
-            <title>Conversion of UTF-16 to and from UTF-8</title>
+          <computeroutput>BSTR</computeroutput> (or its constant counterpart
+          <computeroutput>CBSTR</computeroutput>), which is an array type,
+          represented by a pointer to the start of the zero-terminated string.
+          There are functions for converting between UTF-8 and UTF-16 strings
+          available through <code>g_pVBoxFuncs</code>:<screen>int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);</screen></para>
+
+          <para>The ownership of a string determines who is responsible for
+          releasing resources associated with the string. Whenever the API
+          creates a string (essentially for output parameters), ownership is
+          transferred to the caller. To avoid resource leaks, the caller
+          should release resources once the string is no longer needed.
+          There are plenty of examples in the sample code.</para>
+        </sect3>
 
-            <screen>int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
-int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);</screen>
-          </sect4>
+        <sect3 id="c-safearray">
+          <title>Array handling</title>
+
+          <para>Arrays are handled somewhat similarly to strings, with the
+          additional information of the number of elements in the array. The
+          exact details of string passing depends on the platform middleware
+          (COM/XPCOM), and therefore the C binding offers helper functions to
+          gloss over these differences.</para>
+
+          <para>Passing arrays as input parameters to API methods is usually
+          done by the following sequence, calling a hypothetical
+          <code>IArrayDemo_PassArray</code> API method:<screen>static const ULONG aElements[] = { 1, 2, 3, 4 };
+ULONG cElements = sizeof(aElements) / sizeof(aElements[0]);
+SAFEARRAY *psa = NULL;
+psa = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0, cElements);
+g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(psa, aElements, sizeof(aElements));
+IArrayDemo_PassArray(pThis, ComSafeArrayAsInParam(psa));
+g_pVBoxFuncs->pfnSafeArrayDestroy(psa);</screen></para>
+
+          <para>Likewise, getting arrays results from output parameters is done
+          using helper functions which manage memory allocations as part of
+          their other functionality:<screen>SAFEARRAY *psa = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc();
+ULONG *pData;
+ULONG cElements;
+IArrayDemo_ReturnArray(pThis, ComSafeArrayAsOutParam(psa));
+g_pVBoxFuncs->pfnSafeArrayCopyOutParamHelper((void **)&pData, &cElements, VT_I4, psa);
+g_pVBoxFuncs->pfnSafeArrayDestroy(psa);</screen></para>
+
+          <para>This covers the necessary functionality for all array element
+          types except interface references. These need special helpers to
+          manage the reference counting correctly. The following code snippet
+          gets the list of VMs, and passes the first IMachine reference to
+          another API function (assuming that there is at least one element
+          in the array, to simplify the example):<screen>SAFEARRAY psa = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc();
+IMachine **machines = NULL;
+ULONG machineCnt = 0;
+ULONG i;
+IVirtualBox_get_Machines(virtualBox, ComSafeArrayAsOutIfaceParam(machinesSA, IMachine *));
+g_pVBoxFuncs->pfnSafeArrayCopyOutIfaceParamHelper((IUnknown ***)&machines, &machineCnt, machinesSA);
+g_pVBoxFuncs->pfnSafeArrayDestroy(machinesSA);
+/* Now "machines" contains the IMachine references, and machineCnt the
+ * number of elements in the array. */
+...
+SAFEARRAY *psa = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_IUNKNOWN, 0, 1);
+g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(psa, (void *)&machines[0], sizeof(machines[0]));
+IVirtualBox_GetMachineStates(ComSafeArrayAsInParam(psa), ...);
+...
+g_pVBoxFuncs->pfnSafeArrayDestroy(psa);
+for (i = 0; i < machineCnt; ++i)
+{
+    IMachine *machine = machines[i];
+    IMachine_Release(machine);
+}
+free(machines);</screen></para>
 
-          <sect4>
-            <title>Ownership</title>
+          <para>Handling output parameters needs more special effort than
+          input parameters, thus only for the former there are special helpers,
+          and the latter is handled through the generic array support.</para>
+        </sect3>
 
-            <para>The ownership of a string determines who is responsible for
-            releasing resources associated with the string. Whenever XPCOM
-            creates a string, ownership is transferred to the caller. To avoid
-            resource leaks, the caller should release resources once the
-            string is no longer needed.</para>
-          </sect4>
+        <sect3 id="c-eventhandling">
+          <title>Event handling</title>
+
+          <para>The VirtualBox API offers two types of event handling, active
+          and passive, and consequently there is support for both with the
+          C API binding. Active event handling (based on asynchronous
+          callback invocation for event delivery) is more difficult, as it
+          requires the construction of valid C++ objects in C, which is
+          inherently platform and compiler dependent. Passive event handling
+          is much simpler, it relies on an event loop, fetching events and
+          triggering the necessary handlers explicitly in the API client code.
+          Both approaches depend on an event loop to make sure that events
+          get delivered in a timely manner, with differences what exactly needs
+          to be done.</para>
+
+          <para>The C API sample contains code for both event handling styles,
+          and one has to modify the appropriate <code>#define</code> to select
+          which style is actually used by the compiled program. It allows a
+          good comparison between the two variants, and the code sequences are
+          probably worth reusing without much change in other API clients
+          with only minor adaptions.</para>
+
+          <para>Active event handling needs to ensure that the following helper
+          function is called frequently enough in the primary thread:
+          <screen>g_pVBoxFuncs->pfnProcessEventQueue(cTimeoutMS);</screen></para>
+
+          <para>The actual event handler implementation is quite tedious, as
+          it has to implement a complete API interface. Especially on Windows
+          it is a lot of work to implement the complicated <code>IDispatch</code>
+          interface, requiring to load COM type information and using it
+          in the <code>IDispatch</code> method implementation. Overall this is
+          quite tedious compared to passive event handling.</para>
+
+          <para>Passive event handling uses a similar event loop structure,
+          which requires calling the following function in a loop, and
+          processing the returned event appropriately:
+          <screen>rc = IEventSource_GetEvent(pEventSource, pListener, cTimeoutMS, &pEvent);</screen></para>
+
+          <para>After processing the event it needs to be marked as processed
+          with the following method call:
+          <screen>rc = IEventSource_EventProcessed(pEventSource, pListener, pEvent);</screen></para>
+
+          <para>This is vital for vetoable events, as they would be stuck
+          otherwise, waiting whether the veto comes or not. It does not do any
+          harm for other event types, and in the end is cheaper than checking
+          if the event at hand is vetoable or not.</para>
+
+          <para>The general event handling concepts are described in the API
+          specification (see <xref linkend="events" />), including how to
+          aggregate multiple event sources for processing in one event loop.
+          As mentioned, the sample illustrates the practical aspects of how to
+          use both types of event handling, active and passive, from a C
+          application. Additional hints are in the comments documenting
+          the helper methods in <computeroutput>VBoxCAPI_v4_3.h</computeroutput>.
+          The code complexity of active event handling (and its inherenly
+          platform/compiler specific aspects) should be motivation to use
+          passive event handling whereever possible.</para>
         </sect3>
 
         <sect3 id="c-uninitialization">
-          <title>XPCOM uninitialization</title>
+          <title>C API uninitialization</title>
 
           <para>Uninitialization is performed by
-          <computeroutput>g_pVBoxFuncs->pfnComUninitialize().</computeroutput>
+          <computeroutput>g_pVBoxFuncs->pfnClientUninitialize().</computeroutput>
           If your program can exit from more than one place, it is a good idea
           to install this function as an exit handler with Standard C's
           <computeroutput>atexit()</computeroutput> just after calling
-          <computeroutput>g_pVBoxFuncs->pfnComInitialize()</computeroutput>
+          <computeroutput>g_pVBoxFuncs->pfnClientInitialize()</computeroutput>
           , e.g. <screen>#include <stdlib.h>
 #include <stdio.h>
 
 ...
 
 /*
- * Make sure g_pVBoxFuncs->pfnComUninitialize() is called at exit, no
+ * Make sure g_pVBoxFuncs->pfnClientUninitialize() is called at exit, no
  * matter if we return from the initial call to main or call exit()
  * somewhere else. Note that atexit registered functions are not
  * called upon abnormal termination, i.e. when calling abort() or
- * signal(). Separate provisions must be taken for these cases.
+ * signal().
  */
 
-if (atexit(g_pVBoxFuncs->pfnComUninitialize()) != 0) {
-    fprintf(stderr, "failed to register g_pVBoxFuncs->pfnComUninitialize()\n");
+if (atexit(g_pVBoxFuncs->pfnClientUninitialize()) != 0) {
+    fprintf(stderr, "failed to register g_pVBoxFuncs->pfnClientUninitialize()\n");
     exit(EXIT_FAILURE);
 }</screen></para>
 
           <para>Another idea would be to write your own <computeroutput>void
           myexit(int status)</computeroutput> function, calling
-          <computeroutput>g_pVBoxFuncs->pfnComUninitialize()</computeroutput>
+          <computeroutput>g_pVBoxFuncs->pfnClientUninitialize()</computeroutput>
           followed by the real <computeroutput>exit()</computeroutput>, and
           use it instead of <computeroutput>exit()</computeroutput> throughout
           your program and at the end of
@@ -1955,13 +2109,14 @@ if (atexit(g_pVBoxFuncs->pfnComUninitialize()) != 0) {
           user types CTRL-C sending SIGINT) you might want to install a signal
           handler setting a flag noting that a signal was sent and then
           calling
-          <computeroutput>g_pVBoxFuncs->pfnComUninitialize()</computeroutput>
+          <computeroutput>g_pVBoxFuncs->pfnClientUninitialize()</computeroutput>
           later on, <emphasis>not</emphasis> from the handler itself.</para>
 
           <para>That said, if a client program forgets to call
-          <computeroutput>g_pVBoxFuncs->pfnComUninitialize()</computeroutput>
+          <computeroutput>g_pVBoxFuncs->pfnClientUninitialize()</computeroutput>
           before it terminates, there is a mechanism in place which will
-          eventually release references held by the client.</para>
+          eventually release references held by the client. On Windows it can
+          take quite a while, in the order of 6-7 minutes.</para>
         </sect3>
 
         <sect3 id="c-linking">
@@ -1969,27 +2124,101 @@ if (atexit(g_pVBoxFuncs->pfnComUninitialize()) != 0) {
 
           <para>A program using the C binding has to open the library during
           runtime using the help of glue code provided and as shown in the
-          example <computeroutput>tstXPCOMCGlue.c</computeroutput>.
-          Compilation and linking can be achieved, e.g., with a makefile
-          fragment similar to</para>
-
-          <screen># Where is the XPCOM include directory?
-INCS_XPCOM    = -I../../include
-# Where is the glue code directory?
-GLUE_DIR      = ..
-GLUE_INC      = -I..
-
-#Compile Glue Library
-VBoxXPCOMCGlue.o: $(GLUE_DIR)/VBoxXPCOMCGlue.c
-    $(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $<
-
-# Compile.
-program.o: program.c VBoxCAPI_v4_3.h
-    $(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $<
-
-# Link.
-program: program.o VBoxXPCOMCGlue.o
-    $(CC) -o $@ $^ -ldl</screen>
+          example <computeroutput>tstCAPIGlue.c</computeroutput>.
+          Compilation and linking can be achieved with a makefile fragment
+          similar to:<screen># Where is the SDK directory?
+PATH_SDK      = ../../..
+CAPI_INC      = -I$(PATH_SDK)/bindings/c/include
+ifeq ($(BUILD_PLATFORM),win)
+PLATFORM_INC  = -I$(PATH_SDK)/bindings/mscom/include
+PLATFORM_LIB  = $(PATH_SDK)/bindings/mscom/lib
+else
+PLATFORM_INC  = -I$(PATH_SDK)/bindings/xpcom/include
+PLATFORM_LIB  = $(PATH_SDK)/bindings/xpcom/lib
+endif
+GLUE_DIR      = $(PATH_SDK)/bindings/c/glue
+GLUE_INC      = -I$(GLUE_DIR)
+
+# Compile Glue Library
+VBoxCAPIGlue.o: $(GLUE_DIR)/VBoxCAPIGlue.c
+    $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+# Compile interface ID list
+VirtualBox_i.o: $(PLATFORM_LIB)/VirtualBox_i.c
+    $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+# Compile program code
+program.o: program.c
+    $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+# Link program.
+program: program.o VBoxCAPICGlue.o VirtualBox_i.o
+    $(CC) -o $@ $^ -ldl -lpthread</screen></para>
+        </sect3>
+
+        <sect3 id="capi_conversion">
+          <title>Conversion of code using legacy C binding</title>
+
+          <para>This section aims to make the task of converting code using
+          the legacy C binding to the new style a breeze, by pointing out some
+          key steps.</para>
+
+          <para>One necessary change is adjusting your Makefile to reflect the
+          different include paths. See above. There are now 3 relevant include
+          directories, and most of it is pointing to the C binding directory.
+          The XPCOM include directory is still relevant for platforms where
+          the XPCOM middleware is used, but most of the include files live
+          elsewhere now, so it's good to have it last. Additionally the
+          <computeroutput>VirtualBox_i.c</computeroutput> file needs to be
+          compiled and linked to the program, it contains the IIDs relevant
+          for the VirtualBox API, making sure they are not replicated endlessly
+          if the code refers to them frequently.</para>
+
+          <para>The C API client code should include <computeroutput>VBoxCAPIGlue.h</computeroutput>
+          instead of <computeroutput>VBoxXPCOMCGlue.h</computeroutput> or
+          <computeroutput>VBoxCAPI_v4_3.h</computeroutput>, as this makes sure
+          the correct macros and internal translations are selected.</para>
+
+          <para>All API method calls (anything mentioning <code>vtbl</code>)
+          should be rewritten using the convenience macros for calling methods,
+          as these hide the internal details, are generally easier to use and
+          shorter to type. You should remove as many as possible
+          <code>(nsISupports **)</code> or similar typecasts, as the new style
+          should use the correct type in most places, increasing the type
+          safety in case of an error in the source code.</para>
+
+          <para>To gloss over the platform differences, API client code should
+          no longer rely on XPCOM specific interface names such as
+          <code>nsISupports</code>, <code>nsIException</code> and
+          <code>nsIEventQueue</code>, and replace them by the platform
+          independent interface names <code>IUnknown</code> and
+          <code>IErrorInfo</code> for the first two respectively. Event queue
+          handling should be replaced by using the platform independent way
+          described in <xref linkend="c-eventhandling" />.</para>
+
+          <para>Finally adjust the string and array handling to use the new
+          helpers, as these make sure the code works without changes with
+          both COM and XPCOM, which are significantly different in this area.
+          The code should be double checked if it uses the correct way to
+          manage memory, and is freeing it only after the last use.</para>
+        </sect3>
+
+        <sect3 id="xpcom_cbinding">
+          <title>Legacy C binding to VirtualBox API for XPCOM</title>
+
+          <note>
+            <para>This section applies to Linux, Mac OS X and Solaris
+            hosts only and describes deprecated use of the API from C.</para>
+          </note>
+
+          <para>Starting with version 2.2, VirtualBox offers a C binding for
+          its API which works only on platforms using XPCOM. Refer to the
+          old SDK documentation (included in the SDK packages for version 4.3.6
+          or earlier), it still applies unchanged. The fundamental concepts are
+          similar (but the syntactical details are quite different) to the
+          newer cross-platform C binding which should be used for all new code,
+          as the support for the old C binding will go away in a major release
+          after version 4.3.</para>
         </sect3>
       </sect2>
     </sect1>
@@ -2138,7 +2367,7 @@ if (prog.getResultCode() != 0)  // check success
       stopped, snapshotted or other things.</para>
     </sect1>
 
-    <sect1>
+    <sect1 id="events">
       <title>VirtualBox events</title>
 
       <para>In VirtualBox, "events" provide a uniform mechanism to register
diff --git a/doc/manual/en_US/user_AdvancedTopics.xml b/doc/manual/en_US/user_AdvancedTopics.xml
index 3a607cb..acc5dbd 100644
--- a/doc/manual/en_US/user_AdvancedTopics.xml
+++ b/doc/manual/en_US/user_AdvancedTopics.xml
@@ -455,7 +455,7 @@ greeter-session=vbox-greeter</screen></para>
         Ubuntu, or simply restart the guest.</para></note>
 
         <note><para>vbox-greeter is independent of the graphical session chosen
-        by the user (like Gnome, KDE, Unity etc). However it requires FLTK 1.3
+        by the user (like Gnome, KDE, Unity etc). However, it requires FLTK 1.3
         for representing its own user interface.</para></note>
 
         <para>There are numerous guest properties which can be used to further
@@ -908,7 +908,7 @@ host path or identifier</screen>
                 <computeroutput>MaxPayloadTransferSize</computeroutput> How many bytes the emulated
                 webcam can send to the guest at a time. Default value is 3060 bytes, which is used by
                 some webcams. Higher values can slightly reduce CPU load, if the guest is able to use
-                larger buffers. However a high <computeroutput>MaxPayloadTransferSize</computeroutput>
+                larger buffers. However, a high <computeroutput>MaxPayloadTransferSize</computeroutput>
                 might be not supported by some guests.
               </listitem>
             </itemizedlist>
@@ -2290,14 +2290,16 @@ VBoxManage setextradata "VM name" VBoxInternal2/CoreDumpLive 1</screen>At
           host key shortcut. Setting an action to <emphasis>None</emphasis> will disable
           that host key action.</para>
         <table>
-          <title>ignoreme</title>
+          <title>Host Key customization</title>
           <tgroup cols="3">
-            <tbody>
+            <thead>
               <row>
                 <entry><emphasis role="bold">Action</emphasis></entry>
                 <entry><emphasis role="bold">Default Key</emphasis></entry>
                 <entry><emphasis role="bold">Action</emphasis></entry>
               </row>
+            </thead>
+            <tbody>
               <row>
                 <entry><computeroutput>TakeSnapshot</computeroutput></entry>
                 <entry>T</entry>
@@ -2455,7 +2457,7 @@ VBoxManage setextradata "VM name" VBoxInternal2/CoreDumpLive 1</screen>At
           </glossentry>
 
           <glossentry>
-            <glossterm><computeroutput>Restore</computeroutput></glossterm>
+            <glossterm><computeroutput>PowerOffRestoringSnapshot</computeroutput></glossterm>
 
             <glossdef>
               <para>Don't allow the user to return to the last snapshot when
@@ -2493,14 +2495,16 @@ VBoxManage setextradata "VM name" VBoxInternal2/CoreDumpLive 1</screen>At
       (<computeroutput>VBOXWEB_HOST</computeroutput>,
       <computeroutput>VBOXWEB_PORT</computeroutput> etc.):
       <table>
-        <title>ignored</title>
+        <title>Web service configuration parameters</title>
         <tgroup cols="3">
-          <tbody>
+          <thead>
             <row>
               <entry><emphasis role="bold">Parameter</emphasis></entry>
               <entry><emphasis role="bold">Description</emphasis></entry>
               <entry><emphasis role="bold">Default</emphasis></entry>
             </row>
+          </thead>
+          <tbody>
             <row>
               <entry><computeroutput>USER</computeroutput></entry>
               <entry>The user as which the web service runs</entry>
@@ -2789,14 +2793,16 @@ svccfg -s svc:/application/virtualbox/webservice:default setprop config/user=roo
       <computeroutput>VBOXBALLOONCTRL_INTERVAL</computeroutput> etc. parameters
       can still be used):
       <table>
-        <title>ignored</title>
+        <title>VirtualBox watchdog configuration parameters</title>
         <tgroup cols="3">
-          <tbody>
+          <thead>
             <row>
               <entry><emphasis role="bold">Parameter</emphasis></entry>
               <entry><emphasis role="bold">Description</emphasis></entry>
               <entry><emphasis role="bold">Default</emphasis></entry>
             </row>
+          </thead>
+          <tbody>
             <row>
               <entry><computeroutput>USER</computeroutput></entry>
               <entry>The user as which the watchdog service runs</entry>
@@ -3021,4 +3027,101 @@ alice = {
     <para>Storage attachments can be reconfigured while the VM is paused afterwards using:</para>
     <screen>VBoxManage storageattach ...</screen>
   </sect1>
+
+  <sect1 id="hostpowertweaks">
+    <title>Handling of host power management events</title>
+
+    <para>Some host power management events are handled by VirtualBox. The
+    actual behavior depends on the platform:</para>
+
+    <para>
+      <glosslist>
+        <glossentry>
+          <glossterm>Host Suspends</glossterm>
+           <glossdef>
+             <para>
+               This event is generated when the host is about to suspend, that is,
+               the host saves the state to some non-volatile storage and powers off.
+             </para>
+             <para>
+               This event is currently only handled on Windows hosts and Mac OS X hosts.
+               When this event is generated, VirtualBox will pause all running VMs.
+             </para>
+           </glossdef>
+         </glossentry>
+         <glossentry>
+           <glossterm>Host Resumes</glossterm>
+           <glossdef>
+             <para>
+               This event is generated when the host woke up from the suspended
+               state.
+             </para>
+             <para>
+               This event is currently only handled on Windows hosts and Mac OS X hosts.
+               When this event is generated, VirtualBox will resume all VMs which
+               are where paused before.
+             </para>
+           </glossdef>
+         </glossentry>
+         <glossentry>
+           <glossterm>Battery Low</glossterm>
+           <glossdef>
+             <para>
+               The battery level reached a critical level (usually less than 5
+               percent charged).
+             </para>
+             <para>
+               This event is currently only handled on Windows hosts and Mac OS X hosts.
+               When this event is generated, VirtualBox will save the state and
+               terminate all VMs in preperation of a potential host powerdown.
+             </para>
+             <para>The behavior can be configured. By executing the following command,
+             no VM is saved:</para>
+             <screen>VBoxManage setextradata global "VBoxInternal2/SavestateOnBatteryLow" 0</screen>
+             <para>This is a global setting as well as a per-VM setting. The per-VM
+               value has higher precedence than the global value. The following command
+               will save the state of all VMs but will not save the state of VM "foo":</para>
+             <screen>VBoxManage setextradata global "VBoxInternal2/SavestateOnBatteryLow" 1
+VBoxManage setextradata "foo" "VBoxInternal2/SavestateOnBatteryLow" 0</screen>
+             <para>The first line is actually not required as by default the savestate
+             action is performed.</para>
+           </glossdef>
+         </glossentry>
+       </glosslist>
+     </para>
+
+   </sect1>
+
+   <sect1 id="sse412passthrough">
+     <title>Experimental support for passing through SSE4.1 / SSE4.2 instructions</title>
+     <para>
+       To provide SSE 4.1 / SSE 4.2 support to guests, the host CPU has to
+       implement these instruction sets. Starting with VirtualBox 4.3.8 it is
+       possible to enable these instructions for certain guests using the
+       following commands:</para><screen>VBoxManage setextradata "VM name" VBoxInternal/CPUM/SSE4.1 1
+VBoxManage setextradata "VM name" VBoxInternal/CPUM/SSE4.2 1</screen>
+     <para>
+       These are a per-VM settings and they are turned off by default.
+     </para>
+   </sect1>
+
+  <sect1 id="hidledssync">
+    <title>Support for keyboard indicators synchronization</title>
+
+    <para>
+      This feature makes the host keyboard lights match those of the virtual machine's virtual
+      keyboard when the machine window is selected. It is currently implemented for Mac OS X and
+      Windows hosts and available as of releases 4.2.24 and 4.3.8. The feature can be enabled using
+      the following command:
+    </para>
+
+    <screen>VBoxManage setextradata "VM name" GUI/HidLedsSync "1"</screen>
+
+    <para>
+      In order to disable it, use the same command but change "1" to "0", or use the VBoxManage
+      command to remove the extra data. This is a per-VM setting and it is disabled by default.
+    </para>
+
+  </sect1>
+
 </chapter>
diff --git a/doc/manual/en_US/user_Technical.xml b/doc/manual/en_US/user_Technical.xml
index 9c19bec..713d80a 100644
--- a/doc/manual/en_US/user_Technical.xml
+++ b/doc/manual/en_US/user_Technical.xml
@@ -188,19 +188,23 @@
     <sect2>
       <title>Summary of 4.0 configuration changes</title>
 
+      <para>The following table gives a brief overview of the configuration
+      changes between older versions and version 4.0 or above:</para>
+
       <table>
-        <title>ignoreme</title>
+        <title>Configuration changes in version 4.0 or above</title>
 
         <tgroup cols="3">
-          <tbody>
+          <thead>
             <row>
-              <entry></entry>
+              <entry><emphasis role="bold">Setting</emphasis></entry>
 
               <entry><emphasis role="bold">Before 4.0</emphasis></entry>
 
               <entry><emphasis role="bold">4.0 or above</emphasis></entry>
             </row>
-
+          </thead>
+          <tbody>
             <row>
               <entry>Default machines folder</entry>
 
diff --git a/doc/manual/en_US/user_VBoxManage.xml b/doc/manual/en_US/user_VBoxManage.xml
index e2dc9d0..8cd65f0 100644
--- a/doc/manual/en_US/user_VBoxManage.xml
+++ b/doc/manual/en_US/user_VBoxManage.xml
@@ -1230,7 +1230,7 @@ Statistics update:  disabled</screen></para>
            when the network type is NAT
            (<computeroutput>keepnatmacs</computeroutput>). If you add
            <computeroutput>keepdisknames</computeroutput> all new disk images
-           are called like the original once, otherwise they are
+           are called like the original ones, otherwise they are
            renamed.</para>
        </listitem>
        <listitem>
@@ -1252,7 +1252,7 @@ Statistics update:  disabled</screen></para>
        <listitem>
            <para><computeroutput>--register</computeroutput>:
            Automatically register the new clone in this VirtualBox
-           installation. If you manually want register the new VM later, see
+           installation. If you manually want to register the new VM later, see
            <xref linkend="vboxmanage-registervm" /> for instructions how to do
            so.</para>
        </listitem>
@@ -1366,6 +1366,14 @@ Virtual system 0:
     <para>For virtualization products which aren't fully compatible with the
     OVF standard 1.0 you can enable a OVF 0.9 legacy mode with the
     <computeroutput>--legacy09</computeroutput> option.</para>
+
+    <para>To specify options controlling the exact content of the appliance
+    file, you can use <computeroutput>--option</computeroutput> to request the
+    creation of a manifest file (encouraged, allows detection of corrupted
+    appliances on import), the additional export of DVD images, and the
+    exclusion of MAC addresses. You can specify a list of options, e.g.
+    <computeroutput>--option manifest,nomacs</computeroutput>. For details,
+    check the help output of <computeroutput>VBoxManage export</computeroutput>.</para>
   </sect1>
 
   <sect1 id="vboxmanage-startvm">
diff --git a/doc/manual/fr_FR/user_AdvancedTopics.xml b/doc/manual/fr_FR/user_AdvancedTopics.xml
index 317bbae..b80a68b 100644
--- a/doc/manual/fr_FR/user_AdvancedTopics.xml
+++ b/doc/manual/fr_FR/user_AdvancedTopics.xml
@@ -3152,4 +3152,101 @@ alice = {
     que la VM est en pause en utilisant :</para>
     <screen>VBoxManage storageattach ...</screen>
   </sect1>
+
+  <sect1 id="hostpowertweaks">
+    <title>Handling of host power management events</title>
+
+    <para>Some host power management events are handled by VirtualBox. The
+    actual behavior depends on the platform:</para>
+
+    <para>
+      <glosslist>
+        <glossentry>
+          <glossterm>Host Suspends</glossterm>
+           <glossdef>
+             <para>
+               This event is generated when the host is about to suspend, that is,
+               the host saves the state to some non-volatile storage and powers off.
+             </para>
+             <para>
+               This event is currently only handled on Windows hosts and Mac OS X hosts.
+               When this event is generated, VirtualBox will pause all running VMs.
+             </para>
+           </glossdef>
+         </glossentry>
+         <glossentry>
+           <glossterm>Host Resumes</glossterm>
+           <glossdef>
+             <para>
+               This event is generated when the host woke up from the suspended
+               state.
+             </para>
+             <para>
+               This event is currently only handled on Windows hosts and Mac OS X hosts.
+               When this event is generated, VirtualBox will resume all VMs which
+               are where paused before.
+             </para>
+           </glossdef>
+         </glossentry>
+         <glossentry>
+           <glossterm>Battery Low</glossterm>
+           <glossdef>
+             <para>
+               The battery level reached a critical level (usually less than 5
+               percent charged).
+             </para>
+             <para>
+               This event is currently only handled on Windows hosts and Mac OS X hosts.
+               When this event is generated, VirtualBox will save the state and
+               terminate all VMs in preperation of a potential host powerdown.
+             </para>
+             <para>The behavior can be configured. By executing the following command,
+             no VM is saved:</para>
+             <screen>VBoxManage setextradata global "VBoxInternal2/SavestateOnBatteryLow" 0</screen>
+             <para>This is a global setting as well as a per-VM setting. The per-VM
+               value has higher precedence than the global value. The following command
+               will save the state of all VMs but will not save the state of VM "foo":</para>
+             <screen>VBoxManage setextradata global "VBoxInternal2/SavestateOnBatteryLow" 1
+VBoxManage setextradata "foo" "VBoxInternal2/SavestateOnBatteryLow" 0</screen>
+             <para>The first line is actually not required as by default the savestate
+             action is performed.</para>
+           </glossdef>
+         </glossentry>
+       </glosslist>
+     </para>
+
+   </sect1>
+
+   <sect1 id="sse412passthrough">
+     <title>Experimental support for passing through SSE4.1 / SSE4.2 instructions</title>
+     <para>
+       To provide SSE 4.1 / SSE 4.2 support to guests, the host CPU has to
+       implement these instruction sets. Starting with VirtualBox 4.3.8 it is
+       possible to enable these instructions for certain guests using the
+       following commands:</para><screen>VBoxManage setextradata "VM name" VBoxInternal/CPUM/SSE4.1 1
+VBoxManage setextradata "VM name" VBoxInternal/CPUM/SSE4.2 1</screen>
+     <para>
+       These are a per-VM settings and they are turned off by default.
+     </para>
+   </sect1>
+
+  <sect1 id="hidledssync">
+    <title>Support for keyboard indicators synchronization</title>
+
+    <para>
+      This feature makes the host keyboard lights match those of the virtual machine's virtual
+      keyboard when the machine window is selected. It is currently implemented for Mac OS X and
+      Windows hosts and available as of releases 4.2.24 and 4.3.8. The feature can be enabled using
+      the following command:
+    </para>
+
+    <screen>VBoxManage setextradata "VM name" GUI/HidLedsSync "1"</screen>
+
+    <para>
+      In order to disable it, use the same command but change "1" to "0", or use the VBoxManage
+      command to remove the extra data. This is a per-VM setting and it is disabled by default.
+    </para>
+
+  </sect1>
+
 </chapter>
diff --git a/doc/manual/user_ChangeLogImpl.xml b/doc/manual/user_ChangeLogImpl.xml
index 453ff0f..33eacdc 100644
--- a/doc/manual/user_ChangeLogImpl.xml
+++ b/doc/manual/user_ChangeLogImpl.xml
@@ -1,6 +1,266 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
   <sect1>
+    <title>Version 4.3.8 (2014-02-25)</title>
+
+    <para>This is a maintenance release. The following items were fixed and/or
+      added:</para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>VMM: more work on improving the emulation of certain MSR registers
+          (e.g. bugs #12224, #12544)</para>
+      </listitem>
+
+      <listitem>
+        <para>VMM: fixed a <emphasis>VERR_INVALID_RPL</emphasis> Guru Meditation
+          when booting certain guests (bug #11350)</para>
+      </listitem>
+
+      <listitem>
+        <para>VMM: experimental support for SSE 4.1 / SSE 4.2 passthrough, see
+          <xref linkend="sse412passthrough" xreflabel="here"/> how to
+          enable it (bug #8651)</para>
+      </listitem>
+
+      <listitem>
+        <para>VMM: fix for recent Linux kernels with software virtualization</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: experimental HID LEDs synchronization for Windows hosts, see
+          <xref linkend="hidledssync" xreflabel="here"/></para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: warn the user if the Oracle Extension Pack is not installed and
+          the user tries to activate the remote display feature (bug #9104)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: make sure that a minimized guest (using mini toolbar in
+          fullscreen/seamless mode) keeps the minimized state (bug #12199)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: popup banner's "do not show this message again" check-box
+          replaced with corresponding button</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: network adapter cables can now be connected/disconnected directly through
+          the running virtual machine Devices / Network menu a Network status-bar
+          indicator</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: the new VM wizard now proposes 64-bit guests on 64-bit hosts
+          by default; better distinction between 32-bit OS types 64-bit OS types
+          (bug #12533)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: better error message if appliance import fails
+          (bug #12657)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: allow to set host-combination to 'None' using the Global settings
+          / Input page (bug #12730)</para>
+      </listitem>
+
+      <listitem>
+        <para>GUI: don't switch the guest to a black screen during online snapshot
+          merge (4.3 regression)</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxManage: when exporting an appliance, support the suppression
+           of MAC addresses, which means they will be always recreated on
+           import, avoiding duplicate MAC addresses for VMs which are imported
+           several times</para>
+      </listitem>
+
+      <listitem>
+        <para>AHCI: fixed a VM hang during suspend under certain circumstances</para>
+      </listitem>
+
+      <listitem>
+        <para>AHCI: fixed a VM hang during online snapshot merge under certain
+          circumstances</para>
+      </listitem>
+
+      <listitem>
+        <para>AHCI: fixed a bug which resulted in Windows XP guest hangs if a
+          SATA CDROM is attached (bug #12417)</para>
+      </listitem>
+
+      <listitem>
+        <para>AHCI: fixed a Guru Meditation under certain conditions</para>
+      </listitem>
+
+      <listitem>
+        <para>AHCI: ejecting a CD/DVD medium failed under certain conditions</para>
+      </listitem>
+
+      <listitem>
+        <para>AHCI: disk hotplugging fixes</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT: transparent handling of host sleep/resume and network configuration
+          changes if the dnsproxy is enabled or if the hostresolver is used
+          (bug #12441)</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT: fixed crash and misbehaviour under some circumstances with
+          ICMP packets having TTL=1</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT Network: fixed IPv6 reassembly</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT Network: ping proxy implemented</para>
+      </listitem>
+
+      <listitem>
+        <para>OVF: fixed reading of the OVF 0.9 section element
+          (4.3 regression; bug #12345)</para>
+      </listitem>
+
+      <listitem>
+        <para>OVF: several fixes</para>
+      </listitem>
+
+      <listitem>
+        <para>3D: several fixes, multiscreen fixes (e.g. bug #9124)</para>
+      </listitem>
+
+      <listitem>
+        <para>3D: include 3D content in captured videos (bug #12666)</para>
+      </listitem>
+
+      <listitem>
+        <para>3D: include 3D content in captured screenshot (bug #11758)</para>
+      </listitem>
+
+      <listitem>
+        <para>VGA: proper handling of legacy graphics modes if the Guest
+          Additions are active (bug #6649)</para>
+      </listitem>
+
+      <listitem>
+        <para>USB: fixed crash during isochronous transfer under rare
+          circumstances</para>
+      </listitem>
+
+      <listitem>
+        <para>BIOS: better disk geometry handling of SCSI drives</para>
+      </listitem>
+
+      <listitem>
+        <para>API: fix crashes in Java API clients using the XPCOM binding,
+           happened with output parameters only (bug #11232)</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxSVC: documented the handling of host power management events
+          (see <xref linkend="hostpowertweaks" xreflabel="here"/>) and
+          added an extradata item for configuring the handling of the battery-low
+          event (bug #9925)</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxSVC: fixed a bug which could trigger a crash if a VM snapshot
+          was restored the second time and the VM has associated bandwidth groups
+          (bug #12569)</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxSVC: properly detect ifconfig if located in <emphasis>/bin</emphasis>
+          (bug #12713)</para>
+      </listitem>
+
+      <listitem>
+        <para>Shared Folders: fixed a failure to restore transient shared folders
+         when starting a VM from a saved state (bug #12578)</para>
+      </listitem>
+
+      <listitem>
+        <para>Mac OS X hosts: fixed issue when the application icon was frozen in
+          the dock if the bridging interface was not connected to a network
+          (bug #12241)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts: also consider the physical package ID when determining
+          the number of physical CPU cores</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts / guests: don't warn in kernel log if memory allocation
+          fails (bug #11171)</para>
+      </listitem>
+
+      <listitem>
+        <para>Solaris hosts: fixed the autostart SMF script (bug #11720)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows hosts: fixes for non-ANSI code page user names and similar
+          environment contents (bug #12596)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows hosts / guests: fixed setting and using a guest user's process
+          environment variables (relevant for Guest Control)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows Additions: fixed handle leaks in VBoxTray (bug #12563)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows Additions: fixed a crash while detecting active guest users</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows Additions: fixed restoring backed up D3D files on
+          XPDM -> WDDM upgrade</para>
+      </listitem>
+
+      <listitem>
+        <para>Guest Control: fixed setting and using a guest user's process
+          environment variables</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux Additions: support Enterprise Linux 6.5 kernels
+          (bug #12505)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux Additions: fixed CPU hot-remove on newer Linux kernels</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux / Solaris Additions: don't automount a shared folder which is already
+          mounted</para>
+      </listitem>
+
+      <listitem>
+        <para>X11 Additions: support X.Org Server 1.15 (bug #12623)</para>
+      </listitem>
+
+    </itemizedlist>
+
+  </sect1>
+
+  <sect1>
     <title>Version 4.3.6 (2013-12-18)</title>
 
     <para>This is a maintenance release. The following items were fixed and/or
@@ -133,7 +393,7 @@
       </listitem>
 
       <listitem>
-        <para>VMM: fixed occassional <emphasis>VINF_EM_TRIPLE_FAULT</emphasis> errors on
+        <para>VMM: fixed occasional <emphasis>VINF_EM_TRIPLE_FAULT</emphasis> errors on
           hosts without the unrestricted guest execution feature (bug #12198)</para>
       </listitem>
 
diff --git a/include/VBox/HGSMI/HGSMIChSetup.h b/include/VBox/HGSMI/HGSMIChSetup.h
index 79cab8d..3084a76 100644
--- a/include/VBox/HGSMI/HGSMIChSetup.h
+++ b/include/VBox/HGSMI/HGSMIChSetup.h
@@ -44,9 +44,9 @@ AssertCompileSize(HGSMIBUFFERLOCATION, 8);
 
 /* HGSMI setup and configuration data structures. */
 /* host->guest commands pending, should be accessed under FIFO lock only */
-#define HGSMIHOSTFLAGS_COMMANDS_PENDING 0x1
+#define HGSMIHOSTFLAGS_COMMANDS_PENDING    0x1
 /* IRQ is fired, should be accessed under VGAState::lock only  */
-#define HGSMIHOSTFLAGS_IRQ              0x2
+#define HGSMIHOSTFLAGS_IRQ                 0x2
 #ifdef VBOX_WITH_WDDM
 /* one or more guest commands is completed, should be accessed under FIFO lock only */
 # define HGSMIHOSTFLAGS_GCOMMAND_COMPLETED 0x4
diff --git a/include/VBox/HostServices/VBoxCrOpenGLSvc.h b/include/VBox/HostServices/VBoxCrOpenGLSvc.h
index 870ecb0..5fd9f2a 100644
--- a/include/VBox/HostServices/VBoxCrOpenGLSvc.h
+++ b/include/VBox/HostServices/VBoxCrOpenGLSvc.h
@@ -31,6 +31,7 @@
 #include <VBox/VMMDev.h>
 #include <VBox/VBoxGuest2.h>
 #include <VBox/hgcmsvc.h>
+#include <VBox/VBoxVideo.h>
 
 /* crOpenGL host functions */
 #define SHCRGL_HOST_FN_SET_CONSOLE (1)
@@ -43,6 +44,11 @@
 #endif
 #define SHCRGL_HOST_FN_VIEWPORT_CHANGED (15)
 #define SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT (20)
+#define SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS   (21)
+#define SHCRGL_HOST_FN_DEV_RESIZE          (22)
+#define SHCRGL_HOST_FN_VIEWPORT_CHANGED2 (23)
+#define SHCRGL_HOST_FN_TAKE_SCREENSHOT (24)
+#define SHCRGL_HOST_FN_WINDOWS_SHOW (25)
 /* crOpenGL guest functions */
 #define SHCRGL_GUEST_FN_WRITE       (2)
 #define SHCRGL_GUEST_FN_READ        (3)
@@ -57,18 +63,21 @@
 /* Parameters count */
 #define SHCRGL_CPARMS_SET_CONSOLE (1)
 #define SHCRGL_CPARMS_SET_VM (1)
-#define SHCRGL_CPARMS_SET_VISIBLE_REGION (2)
+#define SHCRGL_CPARMS_SET_VISIBLE_REGION (1)
 #define SHCRGL_CPARMS_WRITE      (1)
 #define SHCRGL_CPARMS_READ       (2)
 #define SHCRGL_CPARMS_WRITE_READ (3)
 #define SHCRGL_CPARMS_SET_VERSION (2)
 #define SHCRGL_CPARMS_SCREEN_CHANGED (1)
+#define SHCRGL_CPARMS_DEV_RESIZE (1)
 #define SHCRGL_CPARMS_INJECT (2)
 #define SHCRGL_CPARMS_SET_PID (1)
 #define SHCRGL_CPARMS_WRITE_BUFFER        (4)
 #define SHCRGL_CPARMS_WRITE_READ_BUFFERED (3)
 #define SHCRGL_CPARMS_SET_OUTPUT_REDIRECT (1)
+#define SHCRGL_CPARMS_CRCMD_NOTIFY_CMDS (0)
 #define SHCRGL_CPARMS_VIEWPORT_CHANGED (5)
+#define SHCRGL_CPARMS_VIEWPORT_CHANGED2 (1)
 #define SHCRGL_CPARMS_GET_CAPS (1)
 
 /* @todo Move to H3DOR.h begin */
@@ -356,4 +365,44 @@ typedef struct
 
 } CRVBOXHGCMWRITEREADBUFFERED;
 
+
+typedef struct
+{
+    VBVAINFOSCREEN Screen;
+    void *pvVRAM;
+} CRVBOXHGCMDEVRESIZE;
+
+typedef struct
+{
+    uint32_t u32Screen;
+    uint32_t x;
+    uint32_t y;
+    uint32_t width;
+    uint32_t height;
+} CRVBOXHGCMVIEWPORT;
+
+typedef DECLCALLBACKPTR(void, PFNCRSCREENSHOTREPORT)(void *pvCtx, uint32_t uScreen,
+                uint32_t x, uint32_t y, uint32_t uBitsPerPixel,
+                uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
+                uint8_t *pu8BufferAddress, uint64_t u64TimeStamp);
+
+typedef DECLCALLBACKPTR(bool, PFNCRSCREENSHOTBEGIN)(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp);
+typedef DECLCALLBACKPTR(void, PFNCRSCREENSHOTEND)(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp);
+
+#define CRSCREEN_ALL (0xffffffff)
+
+typedef struct
+{
+    /* screen id or CRSCREEN_ALL to specify all enabled */
+    uint32_t u32Screen;
+    uint32_t u32Width;
+    uint32_t u32Height;
+    uint32_t u32Pitch;
+    void *pvBuffer;
+    void *pvContext;
+    PFNCRSCREENSHOTBEGIN pfnScreenshotBegin;
+    PFNCRSCREENSHOTREPORT pfnScreenshotPerform;
+    PFNCRSCREENSHOTEND pfnScreenshotEnd;
+} CRVBOXHGCMTAKESCREENSHOT;
+
 #endif
diff --git a/include/VBox/VBoxVideo.h b/include/VBox/VBoxVideo.h
index 68d4846..fcae7eb 100644
--- a/include/VBox/VBoxVideo.h
+++ b/include/VBox/VBoxVideo.h
@@ -852,6 +852,9 @@ typedef struct VBVABUFFER
 #define VBVA_INFO_CAPS   12 /* informs host about HGSMI caps. see VBVACAPS below */
 #define VBVA_SCANLINE_CFG    13 /* configures scanline, see VBVASCANLINECFG below */
 #define VBVA_SCANLINE_INFO   14 /* requests scanline info, see VBVASCANLINEINFO below */
+#define VBVA_CMDVBVA_ENABLE  15 /* enables command ring buffer VBVA */
+#define VBVA_CMDVBVA_SUBMIT  16 /* inform host about VBVA Command submission */
+#define VBVA_CMDVBVA_FLUSH   17 /* inform host about VBVA Command submission */
 
 /* host->guest commands */
 #define VBVAHG_EVENT              1
@@ -945,6 +948,20 @@ typedef struct VBVAFLUSH
 
 } VBVAFLUSH;
 
+typedef struct VBVACMDVBVASUBMIT
+{
+    uint32_t u32Reserved;
+} VBVACMDVBVASUBMIT;
+
+/* flush is requested because due to guest command buffer overflow */
+#define VBVACMDVBVAFLUSH_F_GUEST_BUFFER_OVERFLOW 1
+
+typedef struct VBVACMDVBVAFLUSH
+{
+    uint32_t u32Flags;
+} VBVACMDVBVAFLUSH;
+
+
 /* VBVAINFOSCREEN::u8Flags */
 #define VBVA_SCREEN_F_NONE     0x0000
 #define VBVA_SCREEN_F_ACTIVE   0x0001
@@ -1420,7 +1437,8 @@ typedef enum
     VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP,
     VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_BEGIN,
     VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END,
-    VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB,
+    VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRCONNECT,
     VBOXVDMACMD_CHROMIUM_CTL_TYPE_SIZEHACK = 0xfffffffe
 } VBOXVDMACMD_CHROMIUM_CTL_TYPE;
 
@@ -1439,19 +1457,296 @@ typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP
         uint64_t uAlignment;
     };
     uint64_t cbVRam;
+    struct VBOXCRCMD_CLTINFO *pCrCmdClientInfo;
 } VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP, *PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP;
 
+
 typedef struct PDMIDISPLAYVBVACALLBACKS *HCRHGSMICMDCOMPLETION;
 typedef DECLCALLBACK(int) FNCRHGSMICMDCOMPLETION(HCRHGSMICMDCOMPLETION hCompletion, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc);
 typedef FNCRHGSMICMDCOMPLETION *PFNCRHGSMICMDCOMPLETION;
 
-typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION
+typedef DECLCALLBACK(bool) FNCROGLHASDATA();
+typedef FNCROGLHASDATA *PFNCROGLHASDATA;
+
+/* callbacks chrogl gives to main */
+typedef struct CR_MAIN_INTERFACE
+{
+    PFNCROGLHASDATA pfnHasData;
+} CR_MAIN_INTERFACE;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB
 {
     VBOXVDMACMD_CHROMIUM_CTL Hdr;
+    /*in*/
     HCRHGSMICMDCOMPLETION hCompletion;
     PFNCRHGSMICMDCOMPLETION pfnCompletion;
-} VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION, *PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION;
+    /*out*/
+    CR_MAIN_INTERFACE MainInterface;
+} VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB, *PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB;
+
+typedef struct VBOXCRCON_SERVER *HVBOXCRCON_SERVER;
+typedef struct PDMIDISPLAYVBVACALLBACKS* HVBOXCRCON_CLIENT;
+
+typedef struct VBOXCRCON_3DRGN_CLIENT* HVBOXCRCON_3DRGN_CLIENT;
+typedef struct VBOXCRCON_3DRGN_ASYNCCLIENT* HVBOXCRCON_3DRGN_ASYNCCLIENT;
+
+/* server callbacks */
+/* submit chromium cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_CRCMD(HVBOXCRCON_SERVER hServer, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
+typedef FNVBOXCRCON_SVR_CRCMD *PFNVBOXCRCON_SVR_CRCMD;
+
+/* submit chromium control cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_CRCTL(HVBOXCRCON_SERVER hServer, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCmd);
+typedef FNVBOXCRCON_SVR_CRCTL *PFNVBOXCRCON_SVR_CRCTL;
+
+/* request 3D data.
+ * The protocol is the following:
+ * 1. if there is no 3D data displayed on screen, returns VINF_EOF immediately w/o calling any PFNVBOXCRCON_3DRGN_XXX callbacks
+ * 2. otherwise calls PFNVBOXCRCON_3DRGN_ONSUBMIT, submits the "regions get" request to the CrOpenGL server to process it asynchronously and returns VINF_SUCCESS
+ * 2.a on "regions get" request processing calls PFNVBOXCRCON_3DRGN_BEGIN,
+ * 2.b then PFNVBOXCRCON_3DRGN_REPORT zero or more times for each 3D region,
+ * 2.c and then PFNVBOXCRCON_3DRGN_END
+ * 3. returns VERR_XXX code on failure
+ * */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_3DRGN_GET(HVBOXCRCON_SERVER hServer, HVBOXCRCON_3DRGN_CLIENT hRgnClient, uint32_t idScreen);
+typedef FNVBOXCRCON_SVR_3DRGN_GET *PFNVBOXCRCON_SVR_3DRGN_GET;
+
+/* 3D Regions Client callbacks */
+/* called from the PFNVBOXCRCON_SVR_3DRGN_GET callback in case server has 3D data and is going to process the request asynchronously,
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_ONSUBMIT(HVBOXCRCON_3DRGN_CLIENT hRgnClient, uint32_t idScreen, HVBOXCRCON_3DRGN_ASYNCCLIENT *phRgnAsyncClient);
+typedef FNVBOXCRCON_3DRGN_ONSUBMIT *PFNVBOXCRCON_3DRGN_ONSUBMIT;
+
+/* called from the "regions get" command processing thread, to indicate that the "regions get" is started.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_BEGIN(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen);
+typedef FNVBOXCRCON_3DRGN_BEGIN *PFNVBOXCRCON_3DRGN_BEGIN;
+
+/* called from the "regions get" command processing thread, to report a 3D region.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_REPORT(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen, void *pvData, uint32_t cbStride, const RTRECT *pRect);
+typedef FNVBOXCRCON_3DRGN_REPORT *PFNVBOXCRCON_3DRGN_REPORT;
+
+/* called from the "regions get" command processing thread, to indicate that the "regions get" is completed.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_END(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen);
+typedef FNVBOXCRCON_3DRGN_END *PFNVBOXCRCON_3DRGN_END;
+
+
+/* client callbacks */
+/* complete chromium cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_CLT_CRCTL_COMPLETE(HVBOXCRCON_CLIENT hClient, PVBOXVDMACMD_CHROMIUM_CTL pCtl, int rc);
+typedef FNVBOXCRCON_CLT_CRCTL_COMPLETE *PFNVBOXCRCON_CLT_CRCTL_COMPLETE;
+
+/* complete chromium control cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_CLT_CRCMD_COMPLETE(HVBOXCRCON_CLIENT hClient, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc);
+typedef FNVBOXCRCON_CLT_CRCMD_COMPLETE *PFNVBOXCRCON_CLT_CRCMD_COMPLETE;
+
+typedef struct VBOXCRCON_SERVER_CALLBACKS
+{
+    HVBOXCRCON_SERVER hServer;
+    PFNVBOXCRCON_SVR_CRCMD pfnCrCmd;
+    PFNVBOXCRCON_SVR_CRCTL pfnCrCtl;
+    PFNVBOXCRCON_SVR_3DRGN_GET pfn3DRgnGet;
+} VBOXCRCON_SERVER_CALLBACKS, *PVBOXCRCON_SERVER_CALLBACKS;
+
+typedef struct VBOXCRCON_CLIENT_CALLBACKS
+{
+    HVBOXCRCON_CLIENT hClient;
+    PFNVBOXCRCON_CLT_CRCMD_COMPLETE pfnCrCmdComplete;
+    PFNVBOXCRCON_CLT_CRCTL_COMPLETE pfnCrCtlComplete;
+    PFNVBOXCRCON_3DRGN_ONSUBMIT pfn3DRgnOnSubmit;
+    PFNVBOXCRCON_3DRGN_BEGIN pfn3DRgnBegin;
+    PFNVBOXCRCON_3DRGN_REPORT pfn3DRgnReport;
+    PFNVBOXCRCON_3DRGN_END pfn3DRgnEnd;
+} VBOXCRCON_CLIENT_CALLBACKS, *PVBOXCRCON_CLIENT_CALLBACKS;
+
+/* issued by Main to establish connection between Main and CrOpenGL service */
+typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRCONNECT
+{
+    VBOXVDMACMD_CHROMIUM_CTL Hdr;
+    /*input (filled by Client) :*/
+    /*class VMMDev*/void *pVMMDev;
+    VBOXCRCON_CLIENT_CALLBACKS ClientCallbacks;
+    /*output (filled by Server) :*/
+    VBOXCRCON_SERVER_CALLBACKS ServerCallbacks;
+} VBOXVDMACMD_CHROMIUM_CTL_CRCONNECT, *PVBOXVDMACMD_CHROMIUM_CTL_CRCONNECT;
+
+/* ring command buffer dr */
+#define VBOXCMDVBVA_STATE_SUBMITTED   1
+#define VBOXCMDVBVA_STATE_CANCELLED   2
+#define VBOXCMDVBVA_STATE_IN_PROGRESS 3
+/* the "completed" state is signalled via the ring buffer values */
+
+/* CrHgsmi command */
+#define VBOXCMDVBVA_OPTYPE_CRCMD                        1
+/* blit command that does blitting of allocations identified by VRAM offset or host id
+ * for VRAM-offset ones the size and format are same as primary */
+#define VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID       2
+/* flip */
+#define VBOXCMDVBVA_OPTYPE_FLIP                         3
+/* ColorFill */
+#define VBOXCMDVBVA_OPTYPE_CLRFILL                      4
+/* allocation paging transfer request */
+#define VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER              5
+/* allocation paging fill request */
+#define VBOXCMDVBVA_OPTYPE_PAGING_FILL                  6
+/* same as VBOXCMDVBVA_OPTYPE_NOP, but contains VBOXCMDVBVA_HDR data */
+#define VBOXCMDVBVA_OPTYPE_NOPCMD                       7
+
+/* nop - is a one-bit command. The buffer size to skip is determined by VBVA buffer size */
+#define VBOXCMDVBVA_OPTYPE_NOP                          0x80
+
+/* u8Flags flags */
+/* source allocation is specified with the host id. if not set - source allocation is specified with VRAM offset */
+#define VBOXCMDVBVA_OPF_ALLOC_SRCID                     0x80
+/* destination allocation is specified with the host id. if not set - destination allocation is specified with VRAM offset */
+#define VBOXCMDVBVA_OPF_ALLOC_DSTID                     0x40
+
+/* transfer from RAM to Allocation */
+#define VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN              0x20
+
+/* VBOXCMDVBVA_OPTYPE_BLT_PRIMARY specific flags*/
+/* if set - src is a primary id */
+#define VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY               0x20
+/* if set - dst is a primary id */
+#define VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY               0x10
+
+
+/* trying to make the header as small as possible,
+ * we'd have pretty few op codes actually, so 8bit is quite enough,
+ * we will be able to extend it in any way. */
+typedef struct VBOXCMDVBVA_HDR
+{
+    /* one VBOXCMDVBVA_OPTYPE_XXX, except NOP, see comments above */
+    uint8_t u8OpCode;
+    /* command-specific
+     * VBOXCMDVBVA_OPTYPE_CRCMD                     - must be null
+     * VBOXCMDVBVA_OPTYPE_BLT_PRIMARY             - OR-ed VBOXCMDVBVA_OPF_ALLOC_XXX flags
+     * VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID    - OR-ed VBOXCMDVBVA_OPF_ALLOC_XXX flags
+     * VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER           - must be null
+     * VBOXCMDVBVA_OPTYPE_PAGING_FILL               - must be null
+     * VBOXCMDVBVA_OPTYPE_NOPCMD                    - must be null
+     * VBOXCMDVBVA_OPTYPE_NOP                       - not applicable (as the entire VBOXCMDVBVA_HDR is not valid) */
+    uint8_t u8Flags;
+    /* one of VBOXCMDVBVA_STATE_XXX*/
+    volatile uint8_t u8State;
+    union
+    {
+        /* result, 0 on success, otherwise contains the failure code TBD */
+        int8_t i8Result;
+        uint8_t u8PrimaryID;
+    };
+    /* DXGK DDI fence ID */
+    volatile uint32_t u32FenceID;
+} VBOXCMDVBVA_HDR;
+
+typedef uint32_t VBOXCMDVBVAOFFSET;
+typedef uint64_t VBOXCMDVBVAPHADDR;
+
+typedef struct VBOXCMDVBVA_CRCMD_BUFFER
+{
+    uint32_t cbBuffer;
+    VBOXCMDVBVAOFFSET offBuffer;
+} VBOXCMDVBVA_CRCMD_BUFFER;
+
+typedef struct VBOXCMDVBVA_CRCMD_CMD
+{
+    uint32_t cBuffers;
+    VBOXCMDVBVA_CRCMD_BUFFER aBuffers[1];
+} VBOXCMDVBVA_CRCMD_CMD;
+
+typedef struct VBOXCMDVBVA_CRCMD
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_CRCMD_CMD Cmd;
+} VBOXCMDVBVA_CRCMD;
+
+typedef struct VBOXCMDVBVA_ALLOCINFO
+{
+    union
+    {
+        VBOXCMDVBVAOFFSET offVRAM;
+        uint32_t id;
+    };
+} VBOXCMDVBVA_ALLOCINFO;
+
+typedef struct VBOXCMDVBVA_RECT
+{
+   /** Coordinates of affected rectangle. */
+   int16_t xLeft;
+   int16_t yTop;
+   int16_t xRight;
+   int16_t yBottom;
+} VBOXCMDVBVA_RECT;
+
+typedef struct VBOXCMDVBVA_POINT
+{
+   int16_t x;
+   int16_t y;
+} VBOXCMDVBVA_POINT;
+
+typedef struct VBOXCMDVBVA_BLT_PRIMARY
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO alloc;
+    VBOXCMDVBVA_POINT Pos;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_PRIMARY;
+
+typedef struct VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO src;
+    VBOXCMDVBVA_ALLOCINFO dst;
+    VBOXCMDVBVA_POINT Pos;
+    /* the rects count is determined from the command size */
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID;
+
+typedef struct VBOXCMDVBVA_FLIP
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO src;
+} VBOXCMDVBVA_FLIP;
+
+typedef struct VBOXCMDVBVA_CLRFILL
+{
+    VBOXCMDVBVA_HDR Hdr;
+    VBOXCMDVBVA_ALLOCINFO dst;
+    VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_CLRFILL;
+
+#define VBOXCMDVBVA_SYSMEMEL_CPAGES_MAX  0x1000
+
+typedef struct VBOXCMDVBVA_SYSMEMEL
+{
+    uint32_t cPagesAfterFirst  : 12;
+    VBOXCMDVBVAPHADDR iPage    : 52;
+} VBOXCMDVBVA_SYSMEMEL;
+
+typedef struct VBOXCMDVBVA_PAGING_TRANSFER
+{
+    VBOXCMDVBVA_HDR Hdr;
+    /* for now can only contain offVRAM.
+     * paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
+    VBOXCMDVBVA_ALLOCINFO Alloc;
+    uint32_t cSysMem;
+    VBOXCMDVBVA_SYSMEMEL aSysMem[1];
+} VBOXCMDVBVA_PAGING_TRANSFER;
+
+typedef struct VBOXCMDVBVA_PAGING_FILL
+{
+    VBOXCMDVBVA_HDR Hdr;
+    uint32_t cbFill;
+    uint32_t Pattern;
+    /* paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
+    VBOXCMDVBVAOFFSET offVRAM;
+} VBOXCMDVBVA_PAGING_FILL;
+
 # pragma pack()
+
 #endif
 
 #ifdef VBOXVDMA_WITH_VBVA
diff --git a/include/VBox/VBoxVideo3D.h b/include/VBox/VBoxVideo3D.h
index 908929d..2a04b66 100644
--- a/include/VBox/VBoxVideo3D.h
+++ b/include/VBox/VBoxVideo3D.h
@@ -137,6 +137,40 @@ struct VBOXTLSREFDATA_DUMMY
 
 
 /* host 3D->Fe[/Qt] notification mechanism defines */
-#define VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA 2
+#define VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA  2
+#define VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL 3
+
+
+/* interface between the VGA device and 3D Server Backend
+ * VGA device and 3D backend work together in processing the VBVA-based ring buffer commands comming from guest.
+ * With this interaction VGA device acts like a client, while 3D backend acts as a server.
+ * VGA device can process some commands itself, while some of them are delegated to the 3D backend.
+ *
+ * */
+/* client handle, passed to client callbacks (see below) */
+typedef struct VBOXVDMAHOST *HVBOXCRCMDCLT;
+
+
+typedef struct VBOXCMDVBVA_HDR *PVBOXCMDVBVA_HDR;
+
+/* server queries client for the next command,
+ * the obtained command must be returned to the client right after it gets processed,
+ * the next PFNVBOXCRCMD_CLT_CMDGET call completes the previously submitted command,
+ * Must not be called from the EMT thread.*/
+typedef DECLCALLBACKPTR(int, PFNVBOXCRCMD_CLT_CMDGET)(HVBOXCRCMDCLT hClt, PVBOXCMDVBVA_HDR *ppNextCmd, uint32_t *pcbNextCmd);
+
+struct VBVAINFOSCREEN;
+/* server queries for display mode.*/
+typedef DECLCALLBACKPTR(int, PFNVBOXCRCMD_CLT_DMGET)(HVBOXCRCMDCLT hClt, uint32_t idScreen, struct VBVAINFOSCREEN *pScreen, void **ppvVram);
+
+/* Client callbacks (i.e. those client exposes to the server) */
+typedef struct VBOXCRCMD_CLTINFO
+{
+    HVBOXCRCMDCLT hClient;
+    PFNVBOXCRCMD_CLT_CMDGET pfnCmdGet;
+    PFNVBOXCRCMD_CLT_DMGET pfnDmGet;
+} VBOXCRCMD_CLTINFO;
+
+
 
 #endif /* #ifndef ___VBox_VBoxVideo3D_h */
diff --git a/include/VBox/VMMDev.h b/include/VBox/VMMDev.h
index d010cc6..fb85062 100644
--- a/include/VBox/VMMDev.h
+++ b/include/VBox/VMMDev.h
@@ -2089,6 +2089,8 @@ AssertCompileSize(VBVACMDHDR, 8);
 #define VBVA_F_MODE_VRDP_RESET      (0x00000004)
 #define VBVA_F_MODE_VRDP_ORDER_MASK (0x00000008)
 
+#define VBVA_F_STATE_PROCESSING     (0x00010000)
+
 #define VBVA_F_RECORD_PARTIAL       (0x80000000)
 /** @} */
 
diff --git a/include/VBox/cdefs.h b/include/VBox/cdefs.h
index 7eb36ce..0744b76 100644
--- a/include/VBox/cdefs.h
+++ b/include/VBox/cdefs.h
@@ -203,9 +203,17 @@
  * @param   type    The return type of the function declaration.
  */
 #ifdef IN_SUP_R3
-# define SUPR3DECL(type)    DECLEXPORT(type) VBOXCALL
+# ifdef IN_SUP_STATIC
+#  define SUPR3DECL(type)   DECLHIDDEN(type) VBOXCALL
+# else
+#  define SUPR3DECL(type)   DECLEXPORT(type) VBOXCALL
+# endif
 #else
-# define SUPR3DECL(type)    DECLIMPORT(type) VBOXCALL
+# ifdef IN_SUP_STATIC
+#  define SUPR3DECL(type)   DECLHIDDEN(type) VBOXCALL
+# else
+#  define SUPR3DECL(type)   DECLIMPORT(type) VBOXCALL
+# endif
 #endif
 
 /** @def IN_SUP_R0
diff --git a/include/VBox/com/array.h b/include/VBox/com/array.h
index ddabc16..77f9d60 100644
--- a/include/VBox/com/array.h
+++ b/include/VBox/com/array.h
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -607,21 +607,18 @@ public:
      */
     SafeArray(ComSafeArrayIn(T, aArg))
     {
+        if (aArg)
+        {
 #ifdef VBOX_WITH_XPCOM
 
-        AssertReturnVoid(aArg != NULL);
-
-        m.size = aArgSize;
-        m.arr = aArg;
-        m.isWeak = true;
+            m.size = aArgSize;
+            m.arr = aArg;
+            m.isWeak = true;
 
 #else /* !VBOX_WITH_XPCOM */
 
-        AssertReturnVoid(aArg != NULL);
-        SAFEARRAY *arg = aArg;
+            SAFEARRAY *arg = aArg;
 
-        if (arg)
-        {
             AssertReturnVoid(arg->cDims == 1);
 
             VARTYPE vt;
@@ -633,12 +630,12 @@ public:
 
             rc = SafeArrayAccessData(arg, (void HUGEP **)&m.raw);
             AssertComRCReturnVoid(rc);
-        }
 
-        m.arr = arg;
-        m.isWeak = true;
+            m.arr = arg;
+            m.isWeak = true;
 
 #endif /* !VBOX_WITH_XPCOM */
+        }
     }
 
     /**
@@ -974,7 +971,7 @@ public:
      */
     virtual SafeArray &detachTo(ComSafeArrayOut(T, aArg))
     {
-        AssertReturn(m.isWeak == false, *this);
+        AssertReturn(!m.isWeak, *this);
 
 #ifdef VBOX_WITH_XPCOM
 
@@ -1550,21 +1547,18 @@ public:
      */
     SafeIfaceArray(ComSafeArrayIn(I *, aArg))
     {
+        if (aArg)
+        {
 #ifdef VBOX_WITH_XPCOM
 
-        AssertReturnVoid(aArg != NULL);
-
-        Base::m.size = aArgSize;
-        Base::m.arr = aArg;
-        Base::m.isWeak = true;
+            Base::m.size = aArgSize;
+            Base::m.arr = aArg;
+            Base::m.isWeak = true;
 
 #else /* !VBOX_WITH_XPCOM */
 
-        AssertReturnVoid(aArg != NULL);
-        SAFEARRAY *arg = aArg;
+            SAFEARRAY *arg = aArg;
 
-        if (arg)
-        {
             AssertReturnVoid(arg->cDims == 1);
 
             VARTYPE vt;
@@ -1582,12 +1576,12 @@ public:
 
             rc = SafeArrayAccessData(arg, (void HUGEP **)&m.raw);
             AssertComRCReturnVoid(rc);
-        }
 
-        m.arr = arg;
-        m.isWeak = true;
+            m.arr = arg;
+            m.isWeak = true;
 
 #endif /* !VBOX_WITH_XPCOM */
+        }
     }
 
     /**
diff --git a/include/VBox/com/defs.h b/include/VBox/com/defs.h
index d4b9f78..65db793 100644
--- a/include/VBox/com/defs.h
+++ b/include/VBox/com/defs.h
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -380,6 +380,7 @@ typedef nsIID   IID;
 
 #define STDMETHOD(a) NS_IMETHOD a
 #define STDMETHODIMP NS_IMETHODIMP
+#define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
 
 #define COM_IIDOF(I) NS_GET_IID(I)
 
diff --git a/include/VBox/err.h b/include/VBox/err.h
index c98e323..ef99940 100644
--- a/include/VBox/err.h
+++ b/include/VBox/err.h
@@ -610,6 +610,16 @@
 /** CPUMR3DisasmInstrCPU unexpectedly failed to determin the hidden
  * parts of the CS register. */
 #define VERR_CPUM_HIDDEN_CS_LOAD_ERROR          (-1752)
+/** Couldn't find the end of CPUID sub-leaves. */
+#define VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES      (-1753)
+/** CPUM internal processing error \#1. */
+#define VERR_CPUM_IPE_1                         (-1754)
+/** CPUM internal processing error \#2. */
+#define VERR_CPUM_IPE_2                         (-1755)
+/** The specified CPU cannot be found in the CPU database. */
+#define VERR_CPUM_DB_CPU_NOT_FOUND              (-1756)
+/** Invalid CPUMCPU offset in MSR range. */
+#define VERR_CPUM_MSR_BAD_CPUMCPU_OFFSET        (-1757)
 /** @} */
 
 
diff --git a/include/VBox/err.mac b/include/VBox/err.mac
index e7812c8..ac39b10 100644
--- a/include/VBox/err.mac
+++ b/include/VBox/err.mac
@@ -215,6 +215,11 @@
 %define VERR_CPUM_RAISE_GP_0    (-1750)
 %define VERR_CPUM_INCOMPATIBLE_CONFIG    (-1751)
 %define VERR_CPUM_HIDDEN_CS_LOAD_ERROR    (-1752)
+%define VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES    (-1753)
+%define VERR_CPUM_IPE_1    (-1754)
+%define VERR_CPUM_IPE_2    (-1755)
+%define VERR_CPUM_DB_CPU_NOT_FOUND    (-1756)
+%define VERR_CPUM_MSR_BAD_CPUMCPU_OFFSET    (-1757)
 %define VERR_SSM_UNIT_EXISTS    (-1800)
 %define VERR_SSM_UNIT_NOT_FOUND    (-1801)
 %define VERR_SSM_UNIT_NOT_OWNER    (-1802)
diff --git a/include/VBox/log.h b/include/VBox/log.h
index d8f5ae6..cdf4e11 100644
--- a/include/VBox/log.h
+++ b/include/VBox/log.h
@@ -147,6 +147,8 @@ typedef enum LOGGROUP
     LOG_GROUP_DEV_VMM_BACKDOOR,
     /** VMM Device group for logging guest backdoor logging to stderr. */
     LOG_GROUP_DEV_VMM_STDERR,
+    /** VMSVGA Device group. */
+    LOG_GROUP_DEV_VMSVGA,
     /** Disassembler group. */
     LOG_GROUP_DIS,
     /** Generic driver group. */
@@ -732,6 +734,7 @@ typedef enum LOGGROUP
     "DEV_VMM",      \
     "DEV_VMM_BACKDOOR", \
     "DEV_VMM_STDERR", \
+    "DEV_VMSVGA",   \
     "DIS",          \
     "DRV",          \
     "DRV_ACPI",     \
diff --git a/include/VBox/settings.h b/include/VBox/settings.h
index 96fc8ba..eb931d6 100644
--- a/include/VBox/settings.h
+++ b/include/VBox/settings.h
@@ -1243,7 +1243,7 @@ public:
     enum
     {
         BuildMachineXML_IncludeSnapshots = 0x01,
-        BuildMachineXML_WriteVboxVersionAttribute = 0x02,
+        BuildMachineXML_WriteVBoxVersionAttribute = 0x02,
         BuildMachineXML_SkipRemovableMedia = 0x04,
         BuildMachineXML_MediaRegistry = 0x08,
         BuildMachineXML_SuppressSavedState = 0x10
diff --git a/include/VBox/vmm/cpum.h b/include/VBox/vmm/cpum.h
index 73ecd1c..0ce5aba 100644
--- a/include/VBox/vmm/cpum.h
+++ b/include/VBox/vmm/cpum.h
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -77,13 +77,259 @@ typedef enum CPUMCPUVENDOR
     CPUMCPUVENDOR_INTEL,
     CPUMCPUVENDOR_AMD,
     CPUMCPUVENDOR_VIA,
+    CPUMCPUVENDOR_CYRIX,
     CPUMCPUVENDOR_UNKNOWN,
-    CPUMCPUVENDOR_SYNTHETIC,
     /** 32bit hackishness. */
     CPUMCPUVENDOR_32BIT_HACK = 0x7fffffff
 } CPUMCPUVENDOR;
 
 
+/**
+ * X86 and AMD64 CPU microarchitectures and in processor generations.
+ *
+ * @remarks The separation here is sometimes a little bit too finely grained,
+ *          and the differences is more like processor generation than micro
+ *          arch.  This can be useful, so we'll provide functions for getting at
+ *          more coarse grained info.
+ */
+typedef enum CPUMMICROARCH
+{
+    kCpumMicroarch_Invalid = 0,
+
+    kCpumMicroarch_Intel_First,
+
+    kCpumMicroarch_Intel_8086 = kCpumMicroarch_Intel_First,
+    kCpumMicroarch_Intel_80186,
+    kCpumMicroarch_Intel_80286,
+    kCpumMicroarch_Intel_80386,
+    kCpumMicroarch_Intel_80486,
+    kCpumMicroarch_Intel_P5,
+
+    kCpumMicroarch_Intel_P6_Core_Atom_First,
+    kCpumMicroarch_Intel_P6 = kCpumMicroarch_Intel_P6_Core_Atom_First,
+    kCpumMicroarch_Intel_P6_II,
+    kCpumMicroarch_Intel_P6_III,
+
+    kCpumMicroarch_Intel_P6_M_Banias,
+    kCpumMicroarch_Intel_P6_M_Dothan,
+    kCpumMicroarch_Intel_Core_Yonah,        /**< Core, also known as Enhanced Pentium M. */
+
+    kCpumMicroarch_Intel_Core2_First,
+    kCpumMicroarch_Intel_Core2_Merom = kCpumMicroarch_Intel_Core2_First,
+    kCpumMicroarch_Intel_Core2_Penryn,
+
+    kCpumMicroarch_Intel_Core7_First,
+    kCpumMicroarch_Intel_Core7_Nehalem = kCpumMicroarch_Intel_Core7_First,
+    kCpumMicroarch_Intel_Core7_Westmere,
+    kCpumMicroarch_Intel_Core7_SandyBridge,
+    kCpumMicroarch_Intel_Core7_IvyBridge,
+    kCpumMicroarch_Intel_Core7_Haswell,
+    kCpumMicroarch_Intel_Core7_Broadwell,
+    kCpumMicroarch_Intel_Core7_Skylake,
+    kCpumMicroarch_Intel_Core7_Cannonlake,
+    kCpumMicroarch_Intel_Core7_End,
+
+    kCpumMicroarch_Intel_Atom_First,
+    kCpumMicroarch_Intel_Atom_Bonnell = kCpumMicroarch_Intel_Atom_First,
+    kCpumMicroarch_Intel_Atom_Lincroft,     /**< Second generation bonnell (44nm). */
+    kCpumMicroarch_Intel_Atom_Saltwell,     /**< 32nm shrink of Bonnell. */
+    kCpumMicroarch_Intel_Atom_Silvermont,   /**< 22nm */
+    kCpumMicroarch_Intel_Atom_Airmount,     /**< 14nm */
+    kCpumMicroarch_Intel_Atom_Goldmont,     /**< 14nm */
+    kCpumMicroarch_Intel_Atom_Unknown,
+    kCpumMicroarch_Intel_Atom_End,
+
+    kCpumMicroarch_Intel_P6_Core_Atom_End,
+
+    kCpumMicroarch_Intel_NB_First,
+    kCpumMicroarch_Intel_NB_Willamette = kCpumMicroarch_Intel_NB_First, /**< 180nm */
+    kCpumMicroarch_Intel_NB_Northwood,      /**< 130nm */
+    kCpumMicroarch_Intel_NB_Prescott,       /**< 90nm */
+    kCpumMicroarch_Intel_NB_Prescott2M,     /**< 90nm */
+    kCpumMicroarch_Intel_NB_CedarMill,      /**< 65nm */
+    kCpumMicroarch_Intel_NB_Gallatin,       /**< 90nm Xeon, Pentium 4 Extreme Edition ("Emergency Edition"). */
+    kCpumMicroarch_Intel_NB_Unknown,
+    kCpumMicroarch_Intel_NB_End,
+
+    kCpumMicroarch_Intel_Unknown,
+    kCpumMicroarch_Intel_End,
+
+    kCpumMicroarch_AMD_First,
+    kCpumMicroarch_AMD_Am286 = kCpumMicroarch_AMD_First,
+    kCpumMicroarch_AMD_Am386,
+    kCpumMicroarch_AMD_Am486,
+    kCpumMicroarch_AMD_Am486Enh,            /**< Covers Am5x86 as well. */
+    kCpumMicroarch_AMD_K5,
+    kCpumMicroarch_AMD_K6,
+
+    kCpumMicroarch_AMD_K7_First,
+    kCpumMicroarch_AMD_K7_Palomino = kCpumMicroarch_AMD_K7_First,
+    kCpumMicroarch_AMD_K7_Spitfire,
+    kCpumMicroarch_AMD_K7_Thunderbird,
+    kCpumMicroarch_AMD_K7_Morgan,
+    kCpumMicroarch_AMD_K7_Thoroughbred,
+    kCpumMicroarch_AMD_K7_Barton,
+    kCpumMicroarch_AMD_K7_Unknown,
+    kCpumMicroarch_AMD_K7_End,
+
+    kCpumMicroarch_AMD_K8_First,
+    kCpumMicroarch_AMD_K8_130nm = kCpumMicroarch_AMD_K8_First, /**< 130nm Clawhammer, Sledgehammer, Newcastle, Paris, Odessa, Dublin */
+    kCpumMicroarch_AMD_K8_90nm,             /**< 90nm shrink */
+    kCpumMicroarch_AMD_K8_90nm_DualCore,    /**< 90nm with two cores. */
+    kCpumMicroarch_AMD_K8_90nm_AMDV,        /**< 90nm with AMD-V (usually) and two cores (usually). */
+    kCpumMicroarch_AMD_K8_65nm,             /**< 65nm shrink. */
+    kCpumMicroarch_AMD_K8_End,
+
+    kCpumMicroarch_AMD_K10,
+    kCpumMicroarch_AMD_K10_Lion,
+    kCpumMicroarch_AMD_K10_Llano,
+    kCpumMicroarch_AMD_Bobcat,
+    kCpumMicroarch_AMD_Jaguar,
+
+    kCpumMicroarch_AMD_15h_First,
+    kCpumMicroarch_AMD_15h_Bulldozer = kCpumMicroarch_AMD_15h_First,
+    kCpumMicroarch_AMD_15h_Piledriver,
+    kCpumMicroarch_AMD_15h_Steamroller,     /**< Yet to be released, might have different family.  */
+    kCpumMicroarch_AMD_15h_Excavator,       /**< Yet to be released, might have different family.  */
+    kCpumMicroarch_AMD_15h_Unknown,
+    kCpumMicroarch_AMD_15h_End,
+
+    kCpumMicroarch_AMD_16h_First,
+    kCpumMicroarch_AMD_16h_End,
+
+    kCpumMicroarch_AMD_Unknown,
+    kCpumMicroarch_AMD_End,
+
+    kCpumMicroarch_VIA_First,
+    kCpumMicroarch_Centaur_C6 = kCpumMicroarch_VIA_First,
+    kCpumMicroarch_Centaur_C2,
+    kCpumMicroarch_Centaur_C3,
+    kCpumMicroarch_VIA_C3_M2,
+    kCpumMicroarch_VIA_C3_C5A,          /**< 180nm Samuel - Cyrix III, C3, 1GigaPro. */
+    kCpumMicroarch_VIA_C3_C5B,          /**< 150nm Samuel 2 - Cyrix III, C3, 1GigaPro, Eden ESP, XP 2000+. */
+    kCpumMicroarch_VIA_C3_C5C,          /**< 130nm Ezra - C3, Eden ESP. */
+    kCpumMicroarch_VIA_C3_C5N,          /**< 130nm Ezra-T - C3. */
+    kCpumMicroarch_VIA_C3_C5XL,         /**< 130nm Nehemiah - C3, Eden ESP, Eden-N. */
+    kCpumMicroarch_VIA_C3_C5P,          /**< 130nm Nehemiah+ - C3. */
+    kCpumMicroarch_VIA_C7_C5J,          /**< 90nm Esther - C7, C7-D, C7-M, Eden, Eden ULV. */
+    kCpumMicroarch_VIA_Isaiah,
+    kCpumMicroarch_VIA_Unknown,
+    kCpumMicroarch_VIA_End,
+
+    kCpumMicroarch_Cyrix_First,
+    kCpumMicroarch_Cyrix_5x86 = kCpumMicroarch_Cyrix_First,
+    kCpumMicroarch_Cyrix_M1,
+    kCpumMicroarch_Cyrix_MediaGX,
+    kCpumMicroarch_Cyrix_MediaGXm,
+    kCpumMicroarch_Cyrix_M2,
+    kCpumMicroarch_Cyrix_Unknown,
+    kCpumMicroarch_Cyrix_End,
+
+    kCpumMicroarch_Unknown,
+
+    kCpumMicroarch_32BitHack = 0x7fffffff
+} CPUMMICROARCH;
+
+
+/** Predicate macro for catching netburst CPUs. */
+#define CPUMMICROARCH_IS_INTEL_NETBURST(a_enmMicroarch) \
+    ((a_enmMicroarch) >= kCpumMicroarch_Intel_NB_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_NB_End)
+
+/** Predicate macro for catching Core7 CPUs. */
+#define CPUMMICROARCH_IS_INTEL_CORE7(a_enmMicroarch) \
+    ((a_enmMicroarch) >= kCpumMicroarch_Intel_Core7_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_Core7_End)
+
+/** Predicate macro for catching AMD Family OFh CPUs (aka K8).    */
+#define CPUMMICROARCH_IS_AMD_FAM_0FH(a_enmMicroarch) \
+    ((a_enmMicroarch) >= kCpumMicroarch_AMD_K8_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_K8_End)
+
+/** Predicate macro for catching AMD Family 10H CPUs (aka K10).    */
+#define CPUMMICROARCH_IS_AMD_FAM_10H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10)
+
+/** Predicate macro for catching AMD Family 11H CPUs (aka Lion).    */
+#define CPUMMICROARCH_IS_AMD_FAM_11H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10_Lion)
+
+/** Predicate macro for catching AMD Family 12H CPUs (aka Llano).    */
+#define CPUMMICROARCH_IS_AMD_FAM_12H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10_Llano)
+
+/** Predicate macro for catching AMD Family 14H CPUs (aka Bobcat).    */
+#define CPUMMICROARCH_IS_AMD_FAM_14H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_Bobcat)
+
+/** Predicate macro for catching AMD Family 15H CPUs (bulldozer and it's
+ * decendants). */
+#define CPUMMICROARCH_IS_AMD_FAM_15H(a_enmMicroarch) \
+    ((a_enmMicroarch) >= kCpumMicroarch_AMD_15h_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_15h_End)
+
+/** Predicate macro for catching AMD Family 16H CPUs. */
+#define CPUMMICROARCH_IS_AMD_FAM_16H(a_enmMicroarch) \
+    ((a_enmMicroarch) >= kCpumMicroarch_AMD_16h_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_16h_End)
+
+
+
+/**
+ * CPUID leaf.
+ */
+typedef struct CPUMCPUIDLEAF
+{
+    /** The leaf number. */
+    uint32_t    uLeaf;
+    /** The sub-leaf number. */
+    uint32_t    uSubLeaf;
+    /** Sub-leaf mask.  This is 0 when sub-leaves aren't used. */
+    uint32_t    fSubLeafMask;
+
+    /** The EAX value. */
+    uint32_t    uEax;
+    /** The EBX value. */
+    uint32_t    uEbx;
+    /** The ECX value. */
+    uint32_t    uEcx;
+    /** The EDX value. */
+    uint32_t    uEdx;
+
+    /** Flags. */
+    uint32_t    fFlags;
+} CPUMCPUIDLEAF;
+/** Pointer to a CPUID leaf. */
+typedef CPUMCPUIDLEAF *PCPUMCPUIDLEAF;
+/** Pointer to a const CPUID leaf. */
+typedef CPUMCPUIDLEAF const *PCCPUMCPUIDLEAF;
+
+/** @name CPUMCPUIDLEAF::fFlags
+ * @{ */
+/** Indicates that ECX (the sub-leaf indicator) doesn't change when
+ * requesting the final leaf and all undefined leaves that follows it.
+ * Observed for 0x0000000b on Intel. */
+#define CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED RT_BIT_32(0)
+/** @} */
+
+/**
+ * Method used to deal with unknown CPUID leafs.
+ */
+typedef enum CPUMUKNOWNCPUID
+{
+    /** Invalid zero value. */
+    CPUMUKNOWNCPUID_INVALID = 0,
+    /** Use given default values (DefCpuId). */
+    CPUMUKNOWNCPUID_DEFAULTS,
+    /** Return the last standard leaf.
+     * Intel Sandy Bridge has been observed doing this. */
+    CPUMUKNOWNCPUID_LAST_STD_LEAF,
+    /** Return the last standard leaf, with ecx observed.
+     * Intel Sandy Bridge has been observed doing this. */
+    CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
+    /** The register values are passed thru unmodified. */
+    CPUMUKNOWNCPUID_PASSTHRU,
+    /** End of valid value. */
+    CPUMUKNOWNCPUID_END,
+    /** Ensure 32-bit type. */
+    CPUMUKNOWNCPUID_32BIT_HACK = 0x7fffffff
+} CPUMUKNOWNCPUID;
+/** Pointer to unknown CPUID leaf method. */
+typedef CPUMUKNOWNCPUID *PCPUMUKNOWNCPUID;
+
+
+
 /** @name Guest Register Getters.
  * @{ */
 VMMDECL(void)       CPUMGetGuestGDTR(PVMCPU pVCpu, PVBOXGDTR pGDTR);
@@ -172,6 +418,8 @@ VMMDECL(bool)       CPUMGetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeatur
 VMMDECL(void)       CPUMSetGuestCtx(PVMCPU pVCpu, const PCPUMCTX pCtx);
 VMM_INT_DECL(void)  CPUMGuestLazyLoadHiddenCsAndSs(PVMCPU pVCpu);
 VMM_INT_DECL(void)  CPUMGuestLazyLoadHiddenSelectorReg(PVMCPU pVCpu, PCPUMSELREG pSReg);
+VMMR0_INT_DECL(void)        CPUMR0SetGuestTscAux(PVMCPU pVCpu, uint64_t uValue);
+VMMR0_INT_DECL(uint64_t)    CPUMR0GetGuestTscAux(PVMCPU pVCpu);
 /** @} */
 
 
@@ -288,17 +536,11 @@ DECLINLINE(bool)    CPUMIsGuestPagingEnabledEx(PCPUMCTX pCtx)
  */
 DECLINLINE(bool)    CPUMIsGuestInPAEModeEx(PCPUMCTX pCtx)
 {
-#ifdef VBOX_WITH_OLD_VTX_CODE
-    return (    (pCtx->cr4 & X86_CR4_PAE)
-            &&  CPUMIsGuestInPagedProtectedModeEx(pCtx)
-            &&  !CPUMIsGuestInLongModeEx(pCtx));
-#else
     /* Intel mentions EFER.LMA and EFER.LME in different parts of their spec. We shall use EFER.LMA rather
        than EFER.LME as it reflects if the CPU has entered paging with EFER.LME set.  */
     return (   (pCtx->cr4 & X86_CR4_PAE)
             && CPUMIsGuestPagingEnabledEx(pCtx)
             && !(pCtx->msrEFER & MSR_K6_EFER_LMA));
-#endif
 }
 
 #endif /* VBOX_WITHOUT_UNNAMED_UNIONS */
@@ -434,6 +676,7 @@ VMMDECL(uint32_t)       CPUMGetGuestCPL(PVMCPU pVCpu);
 VMMDECL(CPUMMODE)       CPUMGetGuestMode(PVMCPU pVCpu);
 VMMDECL(uint32_t)       CPUMGetGuestCodeBits(PVMCPU pVCpu);
 VMMDECL(DISCPUMODE)     CPUMGetGuestDisMode(PVMCPU pVCpu);
+VMMDECL(uint64_t)       CPUMGetGuestBusFrequency(PVM pVM);
 
 
 #ifdef IN_RING3
@@ -448,7 +691,7 @@ VMMR3DECL(void)         CPUMR3LogCpuIds(PVM pVM);
 VMMR3DECL(void)         CPUMR3Relocate(PVM pVM);
 VMMR3DECL(int)          CPUMR3Term(PVM pVM);
 VMMR3DECL(void)         CPUMR3Reset(PVM pVM);
-VMMR3DECL(void)         CPUMR3ResetCpu(PVMCPU pVCpu);
+VMMR3DECL(void)         CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu);
 VMMDECL(bool)           CPUMR3IsStateRestorePending(PVM pVM);
 VMMR3DECL(void)         CPUMR3SetHWVirtEx(PVM pVM, bool fHWVirtExEnabled);
 VMMR3DECL(int)          CPUMR3SetCR4Feature(PVM pVM, RTHCUINTREG fOr, RTHCUINTREG fAnd);
@@ -457,6 +700,15 @@ VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdExtRCPtr(PVM pVM);
 VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdCentaurRCPtr(PVM pVM);
 VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdDefRCPtr(PVM pVM);
 
+VMMR3DECL(CPUMMICROARCH)    CPUMR3CpuIdDetermineMicroarchEx(CPUMCPUVENDOR enmVendor, uint8_t bFamily,
+                                                            uint8_t bModel, uint8_t bStepping);
+VMMR3DECL(const char *)     CPUMR3MicroarchName(CPUMMICROARCH enmMicroarch);
+VMMR3DECL(int)              CPUMR3CpuIdCollectLeaves(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves);
+VMMR3DECL(int)              CPUMR3CpuIdDetectUnknownLeafMethod(PCPUMUKNOWNCPUID penmUnknownMethod, PCPUMCPUID pDefUnknown);
+VMMR3DECL(const char *)     CPUMR3CpuIdUnknownLeafMethodName(CPUMUKNOWNCPUID enmUnknownMethod);
+VMMR3DECL(CPUMCPUVENDOR)    CPUMR3CpuIdDetectVendorEx(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX);
+VMMR3DECL(const char *)     CPUMR3CpuVendorName(CPUMCPUVENDOR enmVendor);
+
 /** @} */
 #endif /* IN_RING3 */
 
diff --git a/include/VBox/vmm/hm_vmx.h b/include/VBox/vmm/hm_vmx.h
index ab0f777..b499fa3 100644
--- a/include/VBox/vmm/hm_vmx.h
+++ b/include/VBox/vmm/hm_vmx.h
@@ -379,7 +379,6 @@ AssertCompileSize(VMXRESTOREHOST, 56);
 /** @name VMX VMCS-Read cache indices.
  * @{
  */
-#ifndef VBOX_WITH_OLD_VTX_CODE
 # define VMX_VMCS_GUEST_ES_BASE_CACHE_IDX                       0
 # define VMX_VMCS_GUEST_CS_BASE_CACHE_IDX                       1
 # define VMX_VMCS_GUEST_SS_BASE_CACHE_IDX                       2
@@ -398,69 +397,6 @@ AssertCompileSize(VMXRESTOREHOST, 56);
 # define VMX_VMCS_MAX_CACHE_IDX                                 (VMX_VMCS_RO_EXIT_QUALIFICATION_CACHE_IDX + 1)
 # define VMX_VMCS_GUEST_CR3_CACHE_IDX                           15
 # define VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX                   (VMX_VMCS_GUEST_CR3_CACHE_IDX + 1)
-#else /* VBOX_WITH_OLD_VTX_CODE */
-# define VMX_VMCS_GUEST_RIP_CACHE_IDX                           0
-# define VMX_VMCS_GUEST_RSP_CACHE_IDX                           1
-# define VMX_VMCS_GUEST_RFLAGS_CACHE_IDX                        2
-# define VMX_VMCS32_GUEST_INTERRUPTIBILITY_STATE_CACHE_IDX      3
-# define VMX_VMCS_CTRL_CR0_READ_SHADOW_CACHE_IDX                4
-# define VMX_VMCS_GUEST_CR0_CACHE_IDX                           5
-# define VMX_VMCS_CTRL_CR4_READ_SHADOW_CACHE_IDX                6
-# define VMX_VMCS_GUEST_CR4_CACHE_IDX                           7
-# define VMX_VMCS_GUEST_DR7_CACHE_IDX                           8
-# define VMX_VMCS32_GUEST_SYSENTER_CS_CACHE_IDX                 9
-# define VMX_VMCS_GUEST_SYSENTER_EIP_CACHE_IDX                  10
-# define VMX_VMCS_GUEST_SYSENTER_ESP_CACHE_IDX                  11
-# define VMX_VMCS32_GUEST_GDTR_LIMIT_CACHE_IDX                  12
-# define VMX_VMCS_GUEST_GDTR_BASE_CACHE_IDX                     13
-# define VMX_VMCS32_GUEST_IDTR_LIMIT_CACHE_IDX                  14
-# define VMX_VMCS_GUEST_IDTR_BASE_CACHE_IDX                     15
-# define VMX_VMCS16_GUEST_FIELD_CS_CACHE_IDX                    16
-# define VMX_VMCS32_GUEST_CS_LIMIT_CACHE_IDX                    17
-# define VMX_VMCS_GUEST_CS_BASE_CACHE_IDX                       18
-# define VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS_CACHE_IDX            19
-# define VMX_VMCS16_GUEST_FIELD_DS_CACHE_IDX                    20
-# define VMX_VMCS32_GUEST_DS_LIMIT_CACHE_IDX                    21
-# define VMX_VMCS_GUEST_DS_BASE_CACHE_IDX                       22
-# define VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS_CACHE_IDX            23
-# define VMX_VMCS16_GUEST_FIELD_ES_CACHE_IDX                    24
-# define VMX_VMCS32_GUEST_ES_LIMIT_CACHE_IDX                    25
-# define VMX_VMCS_GUEST_ES_BASE_CACHE_IDX                       26
-# define VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS_CACHE_IDX            27
-# define VMX_VMCS16_GUEST_FIELD_FS_CACHE_IDX                    28
-# define VMX_VMCS32_GUEST_FS_LIMIT_CACHE_IDX                    29
-# define VMX_VMCS_GUEST_FS_BASE_CACHE_IDX                       30
-# define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS_CACHE_IDX            31
-# define VMX_VMCS16_GUEST_FIELD_GS_CACHE_IDX                    32
-# define VMX_VMCS32_GUEST_GS_LIMIT_CACHE_IDX                    33
-# define VMX_VMCS_GUEST_GS_BASE_CACHE_IDX                       34
-# define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS_CACHE_IDX            35
-# define VMX_VMCS16_GUEST_FIELD_SS_CACHE_IDX                    36
-# define VMX_VMCS32_GUEST_SS_LIMIT_CACHE_IDX                    37
-# define VMX_VMCS_GUEST_SS_BASE_CACHE_IDX                       38
-# define VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS_CACHE_IDX            39
-# define VMX_VMCS16_GUEST_FIELD_TR_CACHE_IDX                    40
-# define VMX_VMCS32_GUEST_TR_LIMIT_CACHE_IDX                    41
-# define VMX_VMCS_GUEST_TR_BASE_CACHE_IDX                       42
-# define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS_CACHE_IDX            43
-# define VMX_VMCS16_GUEST_FIELD_LDTR_CACHE_IDX                  44
-# define VMX_VMCS32_GUEST_LDTR_LIMIT_CACHE_IDX                  45
-# define VMX_VMCS_GUEST_LDTR_BASE_CACHE_IDX                     46
-# define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS_CACHE_IDX          47
-# define VMX_VMCS32_RO_EXIT_REASON_CACHE_IDX                    48
-# define VMX_VMCS32_RO_VM_INSTR_ERROR_CACHE_IDX                 49
-# define VMX_VMCS32_RO_EXIT_INSTR_LENGTH_CACHE_IDX              50
-# define VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE_CACHE_IDX   51
-# define VMX_VMCS32_RO_EXIT_INSTR_INFO_CACHE_IDX                52
-# define VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO_CACHE_IDX         53
-# define VMX_VMCS_RO_EXIT_QUALIFICATION_CACHE_IDX               54
-# define VMX_VMCS32_RO_IDT_INFO_CACHE_IDX                       55
-# define VMX_VMCS32_RO_IDT_ERROR_CODE_CACHE_IDX                 56
-# define VMX_VMCS_MAX_CACHE_IDX                                 (VMX_VMCS32_RO_IDT_ERROR_CODE_CACHE_IDX + 1)
-# define VMX_VMCS_GUEST_CR3_CACHE_IDX                           57
-# define VMX_VMCS64_EXIT_GUEST_PHYS_ADDR_FULL_CACHE_IDX         58
-# define VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX                   (VMX_VMCS64_EXIT_GUEST_PHYS_ADDR_FULL_CACHE_IDX + 1)
-#endif  /* VBOX_WITH_OLD_VTX_CODE */
 /** @} */
 
 /** @name VMX EPT paging structures
@@ -1493,9 +1429,6 @@ typedef VMXMSRS *PVMXMSRS;
 #define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID               RT_BIT(11)
 #define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(a)         RT_BOOL((a) & VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID)
 #define VMX_EXIT_INTERRUPTION_INFO_NMI_UNBLOCK(a)                 ((a) & RT_BIT(12))
-#ifdef VBOX_WITH_OLD_VTX_CODE
-# define VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT                    31
-#endif
 #define VMX_EXIT_INTERRUPTION_INFO_VALID                          RT_BIT(31)
 #define VMX_EXIT_INTERRUPTION_INFO_IS_VALID(a)                    RT_BOOL((a) & RT_BIT(31))
 /** Construct an irq event injection value from the exit interruption info value (same except that bit 12 is reserved). */
@@ -2179,28 +2112,20 @@ DECLINLINE(int) VMXWriteVmcs64(uint32_t idxField, uint64_t u64Val)
 VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val);
 #endif
 
-#ifdef VBOX_WITH_OLD_VTX_CODE
-# if ARCH_BITS == 64
-#  define VMXWriteVmcs VMXWriteVmcs64
-# else
-#  define VMXWriteVmcs VMXWriteVmcs32
-# endif
-#else /* !VBOX_WITH_OLD_VTX_CODE */
-# ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
-#  define VMXWriteVmcsHstN(idxField, uVal)       HMVMX_IS_64BIT_HOST_MODE() ?                     \
+#ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
+# define VMXWriteVmcsHstN(idxField, uVal)       HMVMX_IS_64BIT_HOST_MODE() ?                     \
                                                    VMXWriteVmcs64(idxField, uVal)                 \
                                                  : VMXWriteVmcs32(idxField, uVal)
-#  define VMXWriteVmcsGstN(idxField, u64Val)     (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests) ? \
+# define VMXWriteVmcsGstN(idxField, u64Val)     (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests) ? \
                                                    VMXWriteVmcs64(idxField, u64Val)               \
                                                  : VMXWriteVmcs32(idxField, u64Val)
-# elif ARCH_BITS == 32
-#  define VMXWriteVmcsHstN                       VMXWriteVmcs32
-#  define VMXWriteVmcsGstN(idxField, u64Val)     VMXWriteVmcs64Ex(pVCpu, idxField, u64Val)
+#elif ARCH_BITS == 32
+# define VMXWriteVmcsHstN                       VMXWriteVmcs32
+# define VMXWriteVmcsGstN(idxField, u64Val)     VMXWriteVmcs64Ex(pVCpu, idxField, u64Val)
 # else  /* ARCH_BITS == 64 */
-#  define VMXWriteVmcsHstN                       VMXWriteVmcs64
-#  define VMXWriteVmcsGstN                       VMXWriteVmcs64
+# define VMXWriteVmcsHstN                       VMXWriteVmcs64
+# define VMXWriteVmcsGstN                       VMXWriteVmcs64
 # endif
-#endif  /* !VBOX_WITH_OLD_VTX_CODE */
 
 
 /**
@@ -2346,14 +2271,6 @@ DECLINLINE(int) VMXReadVmcs64(uint32_t idxField, uint64_t *pData)
 }
 #endif
 
-#ifdef VBOX_WITH_OLD_VTX_CODE
-# if ARCH_BITS == 64
-#  define VMXReadVmcsField VMXReadVmcs64
-# else
-#  define VMXReadVmcsField VMXReadVmcs32
-# endif
-#endif
-
 /**
  * Gets the last instruction error value from the current VMCS
  *
diff --git a/include/VBox/vmm/mm.h b/include/VBox/vmm/mm.h
index 27a2caa..bcb55c1 100644
--- a/include/VBox/vmm/mm.h
+++ b/include/VBox/vmm/mm.h
@@ -58,6 +58,8 @@ typedef enum MMTAG
     MM_TAG_CSAM_PATCH,
 
     MM_TAG_CPUM_CTX,
+    MM_TAG_CPUM_CPUID,
+    MM_TAG_CPUM_MSRS,
 
     MM_TAG_DBGF,
     MM_TAG_DBGF_AS,
@@ -205,6 +207,7 @@ DECLINLINE(RTRCPTR) MMHyperCCToRC(PVM pVM, void *pv)
 
 
 VMMDECL(int)        MMHyperAlloc(PVM pVM, size_t cb, uint32_t uAlignment, MMTAG enmTag, void **ppv);
+VMMDECL(int)        MMHyperDupMem(PVM pVM, const void *pvSrc, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv);
 VMMDECL(int)        MMHyperFree(PVM pVM, void *pv);
 VMMDECL(void)       MMHyperHeapCheck(PVM pVM);
 VMMDECL(int)        MMR3LockCall(PVM pVM);
diff --git a/include/VBox/vmm/pdmifs.h b/include/VBox/vmm/pdmifs.h
index 684f4c2..94805d8 100644
--- a/include/VBox/vmm/pdmifs.h
+++ b/include/VBox/vmm/pdmifs.h
@@ -749,6 +749,15 @@ typedef struct PDMIDISPLAYCONNECTOR
      * @param   pCmd                Video HW Acceleration Command to be processed.
      * @thread  The emulation thread.
      */
+    DECLR3CALLBACKMEMBER(int, pfnCrCmdNotifyCmds, (PPDMIDISPLAYCONNECTOR pInterface));
+
+    /**
+     * Process the guest chromium command.
+     *
+     * @param   pInterface          Pointer to this interface.
+     * @param   pCmd                Video HW Acceleration Command to be processed.
+     * @thread  The emulation thread.
+     */
     DECLR3CALLBACKMEMBER(void, pfnCrHgsmiCommandProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd));
 
     /**
diff --git a/include/VBox/vmm/vmm.h b/include/VBox/vmm/vmm.h
index 651fc12..bd3cee0 100644
--- a/include/VBox/vmm/vmm.h
+++ b/include/VBox/vmm/vmm.h
@@ -112,7 +112,8 @@ typedef enum VMMCALLRING3
     VMMCALLRING3_VM_SET_RUNTIME_ERROR,
     /** Signal a ring 0 assertion. */
     VMMCALLRING3_VM_R0_ASSERTION,
-    /** Ring switch to force preemption. */
+    /** Ring switch to force preemption.  This is also used by PDMCritSect to
+     *  handle VERR_INTERRUPTED in kernel context. */
     VMMCALLRING3_VM_R0_PREEMPT,
     /** Sync the FTM state with the standby node. */
     VMMCALLRING3_FTM_SET_CHECKPOINT,
diff --git a/include/iprt/asm-amd64-x86.h b/include/iprt/asm-amd64-x86.h
index 0b4b895..b0f0c5b 100644
--- a/include/iprt/asm-amd64-x86.h
+++ b/include/iprt/asm-amd64-x86.h
@@ -674,6 +674,23 @@ DECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pv
 
 
 /**
+ * CPUID variant that initializes all 4 registers before the CPUID instruction.
+ *
+ * @returns The EAX result value.
+ * @param   uOperator   CPUID operation (eax).
+ * @param   uInitEBX    The value to assign EBX prior to the CPUID instruction.
+ * @param   uInitECX    The value to assign ECX prior to the CPUID instruction.
+ * @param   uInitEDX    The value to assign EDX prior to the CPUID instruction.
+ * @param   pvEAX       Where to store eax. Optional.
+ * @param   pvEBX       Where to store ebx. Optional.
+ * @param   pvECX       Where to store ecx. Optional.
+ * @param   pvEDX       Where to store edx. Optional.
+ */
+DECLASM(uint32_t) ASMCpuIdExSlow(uint32_t uOperator, uint32_t uInitEBX, uint32_t uInitECX, uint32_t uInitEDX,
+                                 void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
+
+
+/**
  * Performs the cpuid instruction returning ecx and edx.
  *
  * @param   uOperator   CPUID operation (eax).
@@ -1749,6 +1766,82 @@ DECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val)
 
 
 /**
+ * Reads a machine specific register, extended version (for AMD).
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to read.
+ * @param   uXDI        RDI/EDI value.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint64_t) ASMRdMsrEx(uint32_t uRegister, RTCCUINTREG uXDI);
+#else
+DECLINLINE(uint64_t) ASMRdMsrEx(uint32_t uRegister, RTCCUINTREG uXDI)
+{
+    RTUINT64U u;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("rdmsr\n\t"
+                         : "=a" (u.s.Lo),
+                           "=d" (u.s.Hi)
+                         : "c" (uRegister),
+                           "D" (uXDI));
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        xchg    edi, [uXDI]
+        rdmsr
+        mov     [u.s.Lo], eax
+        mov     [u.s.Hi], edx
+        xchg    edi, [uXDI]
+    }
+# endif
+
+    return u.u;
+}
+#endif
+
+
+/**
+ * Writes a machine specific register, extended version (for AMD).
+ *
+ * @returns Register content.
+ * @param   uRegister   Register to write to.
+ * @param   uXDI        RDI/EDI value.
+ * @param   u64Val      Value to write.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMWrMsrEx(uint32_t uRegister, RTCCUINTREG uXDI, uint64_t u64Val);
+#else
+DECLINLINE(void) ASMWrMsrEx(uint32_t uRegister, RTCCUINTREG uXDI, uint64_t u64Val)
+{
+    RTUINT64U u;
+
+    u.u = u64Val;
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__("wrmsr\n\t"
+                         ::"a" (u.s.Lo),
+                           "d" (u.s.Hi),
+                           "c" (uRegister),
+                           "D" (uXDI));
+
+# else
+    __asm
+    {
+        mov     ecx, [uRegister]
+        xchg    edi, [uXDI]
+        mov     edx, [u.s.Hi]
+        mov     eax, [u.s.Lo]
+        wrmsr
+        xchg    edi, [uXDI]
+    }
+# endif
+}
+#endif
+
+
+
+/**
  * Reads low part of a machine specific register.
  *
  * @returns Register content.
diff --git a/include/iprt/cdefs.h b/include/iprt/cdefs.h
index 0073d5d..744fd48 100644
--- a/include/iprt/cdefs.h
+++ b/include/iprt/cdefs.h
@@ -1681,9 +1681,9 @@
 /** @def RT_LO_U16
  * Gets the low uint16_t of a uint32_t or something equivalent. */
 #ifdef __GNUC__
-# define RT_LO_U16(a)   __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint64_t)); (uint32_t)(a); })
+# define RT_LO_U16(a)   __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint32_t)); (uint16_t)(a); })
 #else
-# define RT_LO_U16(a)                           ( (uint32_t)(a) )
+# define RT_LO_U16(a)                           ( (uint16_t)(a) )
 #endif
 /** @def RT_HI_U16
  * Gets the high uint16_t of a uint32_t or something equivalent). */
diff --git a/include/iprt/env.h b/include/iprt/env.h
index 4046e6a..d956a06 100644
--- a/include/iprt/env.h
+++ b/include/iprt/env.h
@@ -89,6 +89,8 @@ RTDECL(int) RTEnvDestroy(RTENV Env);
  * @returns NULL if Env is NULL or invalid.
  *
  * @param   Env     Environment block handle.
+ * @todo    This needs to change to return a copy of the env vars like
+ *          RTEnvQueryUtf16Block does!
  */
 RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env);
 
@@ -120,6 +122,8 @@ RTDECL(void) RTEnvFreeUtf16Block(PRTUTF16 pwszzBlock);
  *          codeset conversion. We'll figure this out when it becomes necessary.
  */
 RTDECL(bool) RTEnvExist(const char *pszVar);
+RTDECL(bool) RTEnvExistsBad(const char *pszVar);
+RTDECL(bool) RTEnvExistsUtf8(const char *pszVar);
 
 /**
  * Checks if an environment variable exists in a specific environment block.
@@ -145,6 +149,8 @@ RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar);
  *          codeset conversion. We'll figure this out when it becomes necessary.
  */
 RTDECL(const char *) RTEnvGet(const char *pszVar);
+RTDECL(const char *) RTEnvGetBad(const char *pszVar);
+RTDECL(int) RTEnvGetUtf8(const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual);
 
 /**
  * Gets an environment variable in a specific environment block.
@@ -173,6 +179,8 @@ RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbV
  *          codeset conversion. We'll figure this out when it becomes necessary.
  */
 RTDECL(int) RTEnvPut(const char *pszVarEqualValue);
+RTDECL(int) RTEnvPutBad(const char *pszVarEqualValue);
+RTDECL(int) RTEnvPutUtf8(const char *pszVarEqualValue);
 
 /**
  * Puts a copy of the passed in 'variable=value' string into the environment block.
@@ -197,6 +205,8 @@ RTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue);
  *          codeset conversion. We'll figure this out when it becomes necessary.
  */
 RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue);
+RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue);
+RTDECL(int) RTEnvSetUtf8(const char *pszVar, const char *pszValue);
 
 /**
  * Sets an environment variable (setenv(,,1)).
@@ -221,6 +231,8 @@ RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue);
  *          codeset conversion. We'll figure this out when it becomes necessary.
  */
 RTDECL(int) RTEnvUnset(const char *pszVar);
+RTDECL(int) RTEnvUnsetBad(const char *pszVar);
+RTDECL(int) RTEnvUnsetUtf8(const char *pszVar);
 
 /**
  * Removes an environment variable from the specified environment block.
diff --git a/include/iprt/err.h b/include/iprt/err.h
index 55fd34a..5a613d8 100644
--- a/include/iprt/err.h
+++ b/include/iprt/err.h
@@ -1696,7 +1696,7 @@ RT_C_DECLS_END
 /** Too long name or link string. */
 #define VERR_TAR_NAME_TOO_LONG                  (-947)
 /** A directory entry in the archive. */
-#define VINF_TAR_DIR_PATH                        (925)
+#define VINF_TAR_DIR_PATH                        (948)
 /** @} */
 
 /** @name RTPoll status codes
diff --git a/include/iprt/err.mac b/include/iprt/err.mac
index 2520925..39ac4e9 100644
--- a/include/iprt/err.mac
+++ b/include/iprt/err.mac
@@ -454,7 +454,7 @@
 %define VERR_TAR_BAD_CHKSUM_FIELD    (-945)
 %define VERR_TAR_MALFORMED_GNU_LONGXXXX    (-946)
 %define VERR_TAR_NAME_TOO_LONG    (-947)
-%define VINF_TAR_DIR_PATH    (925)
+%define VINF_TAR_DIR_PATH    (948)
 %define VERR_POLL_HANDLE_NOT_POLLABLE    (-950)
 %define VERR_POLL_HANDLE_ID_EXISTS    (-951)
 %define VERR_POLL_HANDLE_ID_NOT_FOUND    (-952)
diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h
index 34c02f3..58c9e94 100644
--- a/include/iprt/mangling.h
+++ b/include/iprt/mangling.h
@@ -65,6 +65,12 @@
 # define ASMAtomicUoOrU32_EndProc                       RT_MANGLER(ASMAtomicUoOrU32_EndProc)
 # define ASMAtomicXchgU64                               RT_MANGLER(ASMAtomicXchgU64)        /* not-some-systems... */
 # define ASMAtomicXchgU64_EndProc                       RT_MANGLER(ASMAtomicXchgU64_EndProc)
+# define ASMRdMsrEx                                     RT_MANGLER(ASMRdMsrEx)
+# define ASMRdMsrEx_EndProc                             RT_MANGLER(ASMRdMsrEx_EndProc)
+# define ASMWrMsrEx                                     RT_MANGLER(ASMWrMsrEx)
+# define ASMWrMsrEx_EndProc                             RT_MANGLER(ASMWrMsrEx_EndProc)
+# define ASMCpuIdExSlow                                 RT_MANGLER(ASMCpuIdExSlow)
+# define ASMCpuIdExSlow_EndProc                         RT_MANGLER(ASMCpuIdExSlow_EndProc)
 # define RTAssertAreQuiet                               RT_MANGLER(RTAssertAreQuiet)
 # define RTAssertMayPanic                               RT_MANGLER(RTAssertMayPanic)
 # define RTAssertMsg1                                   RT_MANGLER(RTAssertMsg1)
@@ -486,17 +492,27 @@
 # define RTEnvDestroy                                   RT_MANGLER(RTEnvDestroy)
 # define RTEnvDupEx                                     RT_MANGLER(RTEnvDupEx)
 # define RTEnvExist                                     RT_MANGLER(RTEnvExist)
+# define RTEnvExistsBad                                 RT_MANGLER(RTEnvExistsBad)
+# define RTEnvExistsUtf8                                RT_MANGLER(RTEnvExistsUtf8)
 # define RTEnvExistEx                                   RT_MANGLER(RTEnvExistEx)
 # define RTEnvFreeUtf16Block                            RT_MANGLER(RTEnvFreeUtf16Block)
 # define RTEnvGet                                       RT_MANGLER(RTEnvGet)
+# define RTEnvGetBad                                    RT_MANGLER(RTEnvGetBad)
+# define RTEnvGetUtf8                                   RT_MANGLER(RTEnvGetUtf8)
 # define RTEnvGetEx                                     RT_MANGLER(RTEnvGetEx)
 # define RTEnvGetExecEnvP                               RT_MANGLER(RTEnvGetExecEnvP)
 # define RTEnvPut                                       RT_MANGLER(RTEnvPut)
+# define RTEnvPutBad                                    RT_MANGLER(RTEnvPutBad)
+# define RTEnvPutUtf8                                   RT_MANGLER(RTEnvPutUtf8)
 # define RTEnvPutEx                                     RT_MANGLER(RTEnvPutEx)
 # define RTEnvQueryUtf16Block                           RT_MANGLER(RTEnvQueryUtf16Block)
 # define RTEnvSet                                       RT_MANGLER(RTEnvSet)
+# define RTEnvSetBad                                    RT_MANGLER(RTEnvSetBad)
+# define RTEnvSetUtf8                                   RT_MANGLER(RTEnvSetUtf8)
 # define RTEnvSetEx                                     RT_MANGLER(RTEnvSetEx)
 # define RTEnvUnset                                     RT_MANGLER(RTEnvUnset)
+# define RTEnvUnsetBad                                  RT_MANGLER(RTEnvUnsetBad)
+# define RTEnvUnsetUtf8                                 RT_MANGLER(RTEnvUnsetUtf8)
 # define RTEnvUnsetEx                                   RT_MANGLER(RTEnvUnsetEx)
 # define RTErrCOMGet                                    RT_MANGLER(RTErrCOMGet)
 # define RTErrConvertFromErrno                          RT_MANGLER(RTErrConvertFromErrno)
diff --git a/include/iprt/x86.h b/include/iprt/x86.h
index af92809..204a2ec 100644
--- a/include/iprt/x86.h
+++ b/include/iprt/x86.h
@@ -1036,25 +1036,25 @@ AssertCompile(X86_DR7_ANY_RW_IO(UINT32_C(0x00040000)) == 0);
 /** Enable misc. processor features (R/W). */
 #define MSR_IA32_MISC_ENABLE                   0x1A0
 /** Enable fast-strings feature (for REP MOVS and REP STORS). */
-#define MSR_IA32_MISC_ENABLE_FAST_STRINGS      RT_BIT(0)
+#define MSR_IA32_MISC_ENABLE_FAST_STRINGS      RT_BIT_64(0)
 /** Automatic Thermal Control Circuit Enable (R/W). */
-#define MSR_IA32_MISC_ENABLE_TCC               RT_BIT(3)
+#define MSR_IA32_MISC_ENABLE_TCC               RT_BIT_64(3)
 /** Performance Monitoring Available (R). */
-#define MSR_IA32_MISC_ENABLE_PERF_MON          RT_BIT(7)
+#define MSR_IA32_MISC_ENABLE_PERF_MON          RT_BIT_64(7)
 /** Branch Trace Storage Unavailable (R/O). */
-#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       RT_BIT(11)
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       RT_BIT_64(11)
 /** Precise Event Based Sampling (PEBS) Unavailable (R/O). */
-#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      RT_BIT(12)
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      RT_BIT_64(12)
 /** Enhanced Intel SpeedStep Technology Enable (R/W). */
-#define MSR_IA32_MISC_ENABLE_SST_ENABLE        RT_BIT(16)
+#define MSR_IA32_MISC_ENABLE_SST_ENABLE        RT_BIT_64(16)
 /** If MONITOR/MWAIT is supported (R/W). */
-#define MSR_IA32_MISC_ENABLE_MONITOR           RT_BIT(18)
+#define MSR_IA32_MISC_ENABLE_MONITOR           RT_BIT_64(18)
 /** Limit CPUID Maxval to 3 leafs (R/W). */
-#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       RT_BIT(22)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       RT_BIT_64(22)
 /** When set to 1, xTPR messages are disabled (R/W). */
-#define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE  RT_BIT(23)
+#define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE  RT_BIT_64(23)
 /** When set to 1, the Execute Disable Bit feature (XD Bit) is disabled (R/W). */
-#define MSR_IA32_MISC_ENABLE_XD_DISABLE        RT_BIT(34)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE        RT_BIT_64(34)
 
 /** Trace/Profile Resource Control (R/W) */
 #define MSR_IA32_DEBUGCTL                   UINT32_C(0x000001d9)
@@ -1302,6 +1302,10 @@ typedef X86PGPAEUINT const *PCX86PGPAEUINT;
 /** The 4MB page base mask for virtual addresses - 32bit version. */
 #define X86_PAGE_4M_BASE_MASK_32            0xffc00000U
 
+/**
+ * Check if the given address is canonical.
+ */
+#define X86_IS_CANONICAL(a_u64Addr)         ((uint64_t)(a_u64Addr) + UINT64_C(0x800000000000) < UINT64_C(0x1000000000000))
 
 
 /** @name Page Table Entry
diff --git a/include/iprt/x86.mac b/include/iprt/x86.mac
index 28af8cb..bf10b66 100644
--- a/include/iprt/x86.mac
+++ b/include/iprt/x86.mac
@@ -316,16 +316,16 @@
 %define MSR_IA32_PERF_CTL                   0x199
 %define MSR_IA32_THERM_STATUS               0x19c
 %define MSR_IA32_MISC_ENABLE                   0x1A0
-%define MSR_IA32_MISC_ENABLE_FAST_STRINGS      RT_BIT(0)
-%define MSR_IA32_MISC_ENABLE_TCC               RT_BIT(3)
-%define MSR_IA32_MISC_ENABLE_PERF_MON          RT_BIT(7)
-%define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       RT_BIT(11)
-%define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      RT_BIT(12)
-%define MSR_IA32_MISC_ENABLE_SST_ENABLE        RT_BIT(16)
-%define MSR_IA32_MISC_ENABLE_MONITOR           RT_BIT(18)
-%define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       RT_BIT(22)
-%define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE  RT_BIT(23)
-%define MSR_IA32_MISC_ENABLE_XD_DISABLE        RT_BIT(34)
+%define MSR_IA32_MISC_ENABLE_FAST_STRINGS      RT_BIT_64(0)
+%define MSR_IA32_MISC_ENABLE_TCC               RT_BIT_64(3)
+%define MSR_IA32_MISC_ENABLE_PERF_MON          RT_BIT_64(7)
+%define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       RT_BIT_64(11)
+%define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      RT_BIT_64(12)
+%define MSR_IA32_MISC_ENABLE_SST_ENABLE        RT_BIT_64(16)
+%define MSR_IA32_MISC_ENABLE_MONITOR           RT_BIT_64(18)
+%define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       RT_BIT_64(22)
+%define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE  RT_BIT_64(23)
+%define MSR_IA32_MISC_ENABLE_XD_DISABLE        RT_BIT_64(34)
 %define MSR_IA32_DEBUGCTL                   0x000001d9
 %define MSR_P4_LASTBRANCH_TOS               0x000001da
 %define MSR_P4_LASTBRANCH_0                 0x000001db
@@ -452,6 +452,7 @@
 %define X86_PAGE_4M_OFFSET_MASK             0x003fffff
 %define X86_PAGE_4M_BASE_MASK               0xffffffffffc00000
 %define X86_PAGE_4M_BASE_MASK_32            0xffc00000
+%define X86_IS_CANONICAL(a_u64Addr)         ((uint64_t)(a_u64Addr) + 0x800000000000 < UINT64_C(0x1000000000000))
 %define X86_PTE_BIT_P                       0
 %define X86_PTE_BIT_RW                      1
 %define X86_PTE_BIT_US                      2
diff --git a/src/VBox/Additions/common/VBoxControl/Makefile.kmk b/src/VBox/Additions/common/VBoxControl/Makefile.kmk
index b7c1f21..e2de0e2 100644
--- a/src/VBox/Additions/common/VBoxControl/Makefile.kmk
+++ b/src/VBox/Additions/common/VBoxControl/Makefile.kmk
@@ -44,15 +44,5 @@ VBoxControl_SOURCES.win = \
 	VBoxControl.rc
 VBoxControl_LDFLAGS.darwin = -framework IOKit
 
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  PROGRAMS += VBoxControl_32
-  VBoxControl_32_EXTENDS  = VBoxControl
-  VBoxControl_32_TEMPLATE = NewVBoxGuestR3Exe_X86
-  VBoxControl_32_NAME     = VBoxControl
- endif
-endif
-
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk b/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk
index e601995..244fc2b 100644
--- a/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk
+++ b/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk
@@ -41,16 +41,10 @@ LIBRARIES += \
 ifndef VBOX_ONLY_TESTSUITE
  if1of ($(KBUILD_TARGET), freebsd linux netbsd openbsd)
   LIBRARIES += \
-        VBoxGuestR3LibXFree86
+  	VBoxGuestR3LibXFree86
  endif
 endif
 LIBRARIES.win.amd64 += VBoxGuestR3Lib-x86 VBoxGuestR3LibShared-x86
-ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
- LIBRARIES.linux.amd64 += \
-        VBoxGuestR3Lib-x86 \
-        VBoxGuestR3LibShared-x86 \
-        VBoxGuestR3LibXFree86-x86
-endif
 
 
 #
@@ -166,7 +160,7 @@ VBoxGuestR3Lib-x86_BLD_TRG_ARCH := x86
 
 
 #
-# VBoxGuestR3LibShared-x86 - an x86 (32-bit) variant of VBoxGuestR3LibShared for 64-bit Linux.
+# VBoxGuestR3LibShared-x86 - an x86 (32-bit) variant of VBoxGuestR3LibShared for 64-bit Windows.
 #
 VBoxGuestR3LibShared-x86_EXTENDS      := VBoxGuestR3LibShared
 VBoxGuestR3LibShared-x86_BLD_TRG_ARCH := x86
@@ -203,12 +197,5 @@ VBoxGuestR3LibXFree86_INCS     = \
 
 VBoxGuestR3LibRuntimeXF86.cpp_CXXFLAGS = -Wno-shadow
 
-#
-# VBoxGuestR3LibXFree86-x86 - an x86 (32-bit) variant of VBoxGuestR3LibXFree86 for 64-bit Linux.
-#
-VBoxGuestR3LibXFree86-x86_TEMPLATE     := VBOXGUESTR3XF86LIB_X86
-VBoxGuestR3LibXFree86-x86_EXTENDS      := VBoxGuestR3LibXFree86
-
-
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/VBox/Additions/common/VBoxService/Makefile.kmk b/src/VBox/Additions/common/VBoxService/Makefile.kmk
index d693a38..8a42bab 100644
--- a/src/VBox/Additions/common/VBoxService/Makefile.kmk
+++ b/src/VBox/Additions/common/VBoxService/Makefile.kmk
@@ -121,6 +121,10 @@ VBoxService_SOURCES.os2   = \
 
 VBoxService_LDFLAGS.darwin = -framework IOKit
 
+VBoxService_LIBS        += \
+	$(VBOX_LIB_IPRT_GUEST_R3) \
+	$(VBOX_LIB_VBGL_R3) \
+	$(VBOX_LIB_IPRT_GUEST_R3)       # (The joy of unix linkers.)
 if1of ($(KBUILD_TARGET), linux)
  VBoxService_LIBS        += \
 	crypt
@@ -142,16 +146,6 @@ ifdef VBOX_WITH_GUEST_PROPS
 	contract
 endif
 
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  PROGRAMS += VBoxService_32
-  VBoxService_32_EXTENDS  = VBoxService
-  VBoxService_32_TEMPLATE = NewVBoxGuestR3Exe_X86
-  VBoxService_32_NAME     = VBoxService
- endif
-endif
-
 #
 # VBoxServiceNT - NT4 version of VBoxService.
 #
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp
index 04e4d52..190418b 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp
@@ -243,22 +243,32 @@ static int VBoxServiceAutoMountSharedFolder(const char *pszShareName, const char
 
     int rc = VINF_SUCCESS;
     char szAlreadyMountedTo[RTPATH_MAX];
-    /* If a Shared Folder already is mounted but not to our desired mount point,
-     * do an unmount first! */
-    if (   VBoxServiceAutoMountShareIsMounted(pszShareName, szAlreadyMountedTo, sizeof(szAlreadyMountedTo))
-        && RTStrICmp(pszMountPoint, szAlreadyMountedTo))
+    bool fSkip = false;
+
+    /* Already mounted? */
+    if (VBoxServiceAutoMountShareIsMounted(pszShareName, szAlreadyMountedTo, sizeof(szAlreadyMountedTo)))
     {
-        VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Shared folder \"%s\" already mounted to \"%s\", unmounting ...\n",
-                           pszShareName, szAlreadyMountedTo);
-        rc = VBoxServiceAutoMountUnmount(szAlreadyMountedTo);
-        if (RT_FAILURE(rc))
-            VBoxServiceError("VBoxServiceAutoMountWorker: Failed to unmount \"%s\", %s (%d)!\n",
-                             szAlreadyMountedTo, strerror(errno), errno);
+        fSkip = true;
+        /* Do if it not mounted to our desired mount point */
+        if (RTStrICmp(pszMountPoint, szAlreadyMountedTo))
+        {
+            VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Shared folder \"%s\" already mounted to \"%s\", unmounting ...\n",
+                               pszShareName, szAlreadyMountedTo);
+            rc = VBoxServiceAutoMountUnmount(szAlreadyMountedTo);
+            if (RT_FAILURE(rc))
+                VBoxServiceError("VBoxServiceAutoMountWorker: Failed to unmount \"%s\", %s (%d)!\n",
+                                 szAlreadyMountedTo, strerror(errno), errno);
+            else
+                fSkip = false;
+        }
+        if (fSkip)
+            VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Shared folder \"%s\" already mounted to \"%s\", skipping\n",
+                               pszShareName, szAlreadyMountedTo);
     }
 
-    if (RT_SUCCESS(rc))
+    if (!fSkip && RT_SUCCESS(rc))
         rc = VBoxServiceAutoMountPrepareMountPoint(pszMountPoint, pszShareName, pOpts);
-    if (RT_SUCCESS(rc))
+    if (!fSkip && RT_SUCCESS(rc))
     {
 #ifdef RT_OS_SOLARIS
         char achOptBuf[MAX_MNTOPT_STR] = { '\0', };
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceCpuHotPlug.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceCpuHotPlug.cpp
index 9e80808..ba3a64c 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceCpuHotPlug.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceCpuHotPlug.cpp
@@ -120,6 +120,18 @@ SYSFSCPUPATH g_aAcpiCpuPath[] =
     /** Level 4 */
     {ACPI_CPU_PATH_NOT_PROBED, g_aAcpiCpuPathLvl4, RT_ELEMENTS(g_aAcpiCpuPathLvl4), NULL, NULL},
 };
+
+/**
+ * Possible directories to get to the topology directory for reading core and package id.
+ *
+ * @remark: This is not part of the path above because the eject file is not in one of the directories
+ *          below and would make the hot unplug code fail.
+ */
+const char *g_apszTopologyPath[] =
+{
+    "sysdev",
+    "physical_node"
+};
 #endif
 
 #ifdef RT_OS_LINUX
@@ -277,10 +289,25 @@ static int VBoxServiceCpuHotPlugGetACPIDevicePath(char **ppszPath, uint32_t idCp
                     if (iLvlCurr == RT_ELEMENTS(g_aAcpiCpuPath) - 1)
                     {
                         /* Get the sysdev */
-                        uint32_t idCore    = RTLinuxSysFsReadIntFile(10, "%s/sysdev/topology/core_id",
-                                                                     pszPathCurr);
-                        uint32_t idPackage = RTLinuxSysFsReadIntFile(10, "%s/sysdev/topology/physical_package_id",
-                                                                     pszPathCurr);
+                        uint32_t idCore = 0;
+                        uint32_t idPackage = 0;
+
+                        for (unsigned i = 0; i < RT_ELEMENTS(g_apszTopologyPath); i++)
+                        {
+                            int64_t i64Core    = RTLinuxSysFsReadIntFile(10, "%s/%s/topology/core_id",
+                                                                         pszPathCurr, g_apszTopologyPath[i]);
+                            int64_t i64Package = RTLinuxSysFsReadIntFile(10, "%s/%s/topology/physical_package_id",
+                                                                         pszPathCurr, g_apszTopologyPath[i]);
+
+                            if (   i64Core != -1
+                                && i64Package != -1)
+                            {
+                                idCore = (uint32_t)i64Core;
+                                idPackage = (uint32_t)i64Package;
+                                break;
+                            }
+                        }
+
                         if (   idCore    == idCpuCore
                             && idPackage == idCpuPackage)
                         {
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
index 354735b..e9191a1 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
@@ -363,7 +363,8 @@ static int VBoxServiceVMInfoWinProcessesGetTokenInfo(PVBOXSERVICEVMINFOPROC pPro
                         Assert(dwLength);
                         if (dwLength)
                         {
-                            pProc->pSid = (PSID)RTMemAlloc(dwLength);
+                            pProc->pSid = (PSID)HeapAlloc(GetProcessHeap(),
+                                                          HEAP_ZERO_MEMORY, dwLength);
                             AssertPtr(pProc->pSid);
                             if (CopySid(dwLength, pProc->pSid, pUser->User.Sid))
                             {
@@ -377,8 +378,15 @@ static int VBoxServiceVMInfoWinProcessesGetTokenInfo(PVBOXSERVICEVMINFOPROC pPro
                             dwErr = ERROR_NO_DATA;
 
                         if (dwErr != ERROR_SUCCESS)
+                        {
                             VBoxServiceError("Error retrieving SID of process PID=%ld: %ld\n",
                                              pProc->id, dwErr);
+                            if (pProc->pSid)
+                            {
+                                HeapFree(GetProcessHeap(), 0 /* Flags */, pProc->pSid);
+                                pProc->pSid = NULL;
+                            }
+                        }
                         break;
                     }
 
@@ -456,6 +464,7 @@ int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppaProcs, PDW
             break;
         }
     } while (cProcesses <= _32K); /* Should be enough; see: http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx */
+
     if (RT_SUCCESS(rc))
     {
         /*
@@ -494,7 +503,7 @@ int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppaProcs, PDW
                 *ppaProcs = paProcs;
             }
             else
-                RTMemFree(paProcs);
+                VBoxServiceVMInfoWinProcessesFree(cProcesses, paProcs);
         }
         else
             rc = VERR_NO_MEMORY;
@@ -515,7 +524,11 @@ void VBoxServiceVMInfoWinProcessesFree(DWORD cProcs, PVBOXSERVICEVMINFOPROC paPr
     for (DWORD i = 0; i < cProcs; i++)
     {
         if (paProcs[i].pSid)
-            RTMemFree(paProcs[i].pSid);
+        {
+            HeapFree(GetProcessHeap(), 0 /* Flags */, paProcs[i].pSid);
+            paProcs[i].pSid = NULL;
+        }
+
     }
     RTMemFree(paProcs);
 }
@@ -991,6 +1004,9 @@ int VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache,
     int rc2 = VbglR3GuestPropConnect(&s_uDebugGuestPropClientID);
     AssertRC(rc2);
 
+    char *pszUserList = NULL;
+    uint32_t cUsersInList = 0;
+
     /* This function can report stale or orphaned interactive logon sessions
        of already logged off users (especially in Windows 2000). */
     PLUID    paSessions = NULL;
@@ -1138,7 +1154,6 @@ int VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache,
             VBoxServiceVerbose(3, "Found %u unique logged-in user(s)\n",
                                cUniqueUsers);
 
-            *pcUsersInList = 0;
             for (ULONG i = 0; i < cUniqueUsers; i++)
             {
                 if (g_cVerbosity > 3)
@@ -1158,13 +1173,13 @@ int VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache,
                     VBoxServiceVerbose(3, "User \"%ls\" has %RU32 interactive processes (session=%RU32)\n",
                                        pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, pUserInfo[i].ulLastSession);
 
-                    if (*pcUsersInList > 0)
+                    if (cUsersInList > 0)
                     {
-                        rc = RTStrAAppend(ppszUserList, ",");
-                        AssertRCBreakStmt(rc, RTStrFree(*ppszUserList));
+                        rc = RTStrAAppend(&pszUserList, ",");
+                        AssertRCBreakStmt(rc, RTStrFree(pszUserList));
                     }
 
-                    *pcUsersInList += 1;
+                    cUsersInList += 1;
 
                     char *pszUser = NULL;
                     char *pszDomain = NULL;
@@ -1175,19 +1190,19 @@ int VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache,
                     if (RT_SUCCESS(rc))
                     {
                         /* Append user to users list. */
-                        rc = RTStrAAppend(ppszUserList, pszUser);
+                        rc = RTStrAAppend(&pszUserList, pszUser);
 
                         /* Do idle detection. */
                         if (RT_SUCCESS(rc))
                             rc = vboxServiceVMInfoWinWriteLastInput(pCache, pszUser, pszDomain);
                     }
                     else
-                        rc = RTStrAAppend(ppszUserList, "<string-conversion-error>");
+                        rc = RTStrAAppend(&pszUserList, "<string-conversion-error>");
 
                     RTStrFree(pszUser);
                     RTStrFree(pszDomain);
 
-                    AssertRCBreakStmt(rc, RTStrFree(*ppszUserList));
+                    AssertRCBreakStmt(rc, RTStrFree(pszUserList));
                 }
             }
 
@@ -1198,6 +1213,12 @@ int VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache,
     if (paSessions)
         LsaFreeReturnBuffer(paSessions);
 
+    if (RT_SUCCESS(rc))
+    {
+        *ppszUserList = pszUserList;
+        *pcUsersInList = cUsersInList;
+    }
+
     s_uDebugIter++;
     VbglR3GuestPropDisconnect(s_uDebugGuestPropClientID);
 
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
index cc02261..d8dbe7c 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
@@ -796,20 +796,23 @@ static int vboxserviceVMInfoWriteUsers(void)
     }
 
     /* Build the user list. */
-    if (RT_SUCCESS(rc))
-        rc = RTStrAllocEx(&pszUserList, cchUserList + 1);
-    if (RT_SUCCESS(rc))
+    if (cchUserList > 0)
     {
-        char *psz = pszUserList;
-        for (uint32_t i = 0; i < cUsersInList; i++)
+        if (RT_SUCCESS(rc))
+            rc = RTStrAllocEx(&pszUserList, cchUserList + 1);
+        if (RT_SUCCESS(rc))
         {
-            if (i != 0)
-                *psz++ = ',';
-            size_t cch = strlen(papszUsers[i]);
-            memcpy(psz, papszUsers[i], cch);
-            psz += cch;
+            char *psz = pszUserList;
+            for (uint32_t i = 0; i < cUsersInList; i++)
+            {
+                if (i != 0)
+                    *psz++ = ',';
+                size_t cch = strlen(papszUsers[i]);
+                memcpy(psz, papszUsers[i], cch);
+                psz += cch;
+            }
+            *psz = '\0';
         }
-        *psz = '\0';
     }
 
     /* Cleanup. */
diff --git a/src/VBox/Additions/common/crOpenGL/Makefile.kmk b/src/VBox/Additions/common/crOpenGL/Makefile.kmk
index cd70f78..42a04d7 100644
--- a/src/VBox/Additions/common/crOpenGL/Makefile.kmk
+++ b/src/VBox/Additions/common/crOpenGL/Makefile.kmk
@@ -51,15 +51,6 @@ ifdef VBOX_WITH_WDDM
  DLLS.win.amd64 += $(VBOX_OGL_X86_GUEST_DLLS)
 endif
 
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  DLLS += $(VBOX_OGL_X86_GUEST_DLLS)
-  $(foreach i,$(VBOX_OGL_X86_GUEST_DLLS),$(eval $(i)_INST = $(INST_ADDITIONS)/32/))
-  $(foreach i,$(VBOX_OGL_X86_GUEST_DLLS),$(eval $(i)_NAME = $(subst -x86,,$(i))))
- endif
-endif
-
 if1of ($(KBUILD_TARGET), linux solaris freebsd)
  #VBoxOGL_DRI = 1
  ifn1of ($(KBUILD_TARGET),solaris)   # No DRI on Solaris yet
@@ -75,6 +66,7 @@ if1of ($(KBUILD_TARGET), linux solaris freebsd)
  endif
 endif
 
+
 #
 # VBoxOGL
 #
@@ -244,9 +236,11 @@ ifdef VBOX_WITH_WDDM
 VBoxOGL_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+ifdef VBOX_WITH_WDDM
 #
 # VBoxOGL-x86 - x86 VBoxOGL version built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGL-x86
 VBoxOGL-x86_EXTENDS = VBoxOGL
 VBoxOGL-x86_BLD_TRG_ARCH = x86
 VBoxOGL-x86_LIBS = $(VBOX_LIB_IPRT_GUEST_R3_SHARED_X86) \
@@ -256,6 +250,7 @@ VBoxOGL-x86_LIBS = $(VBOX_LIB_IPRT_GUEST_R3_SHARED_X86) \
 VBoxOGL-x86_SOURCES.win = $(subst cropengl.def,cropengl-x86.def,$(VBoxOGL_SOURCES.win))
 VBoxOGL-x86_CLEAN.win = $(subst cropengl.def,cropengl-x86.def,$(VBoxOGL_CLEAN.win))
 VBoxOGL-x86_DEFS = $(VBoxOGL_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # Generate files for VBoxOGL.
@@ -469,15 +464,18 @@ ifdef VBOX_WITH_WDDM
 VBoxOGLarrayspu_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+ifdef VBOX_WITH_WDDM
 #
 # VBoxOGLarrayspu-x86 - x86 version of VBoxOGLarrayspu built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGLarrayspu-x86
 VBoxOGLarrayspu-x86_EXTENDS = VBoxOGLarrayspu
 VBoxOGLarrayspu-x86_BLD_TRG_ARCH = x86
 VBoxOGLarrayspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \
 	$(PATH_STAGE_LIB)/additions/VBoxOGLspuload-x86$(VBOX_SUFF_LIB) \
 	$(PATH_STAGE_LIB)/additions/VBoxOGLcrstate-x86$(VBOX_SUFF_LIB)
 VBoxOGLarrayspu-x86_DEFS = $(VBoxOGLarrayspu_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # VBoxOGLpassthroughspu
@@ -510,13 +508,16 @@ ifdef VBOX_WITH_WDDM
 VBoxOGLpassthroughspu_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+ifdef VBOX_WITH_WDDM
 #
 # VBoxOGLpassthroughspu-x86 - x86 version of VBoxOGLpassthroughspu built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGLpassthroughspu-x86
 VBoxOGLpassthroughspu-x86_EXTENDS = VBoxOGLpassthroughspu
 VBoxOGLpassthroughspu-x86_BLD_TRG_ARCH = x86
 VBoxOGLpassthroughspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86)
 VBoxOGLpassthroughspu-x86_DEFS = $(VBoxOGLpassthroughspu_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # Generate files for VBoxOGLpassthroughspu.
@@ -589,9 +590,11 @@ ifdef VBOX_WITH_WDDM
 VBoxOGLpackspu_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+ifdef VBOX_WITH_WDDM
 #
 # VBoxOGLpackspu-x86 - x86 version of VBoxOGLpackspu built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGLpackspu-x86
 VBoxOGLpackspu-x86_EXTENDS = VBoxOGLpackspu
 VBoxOGLpackspu-x86_BLD_TRG_ARCH = x86
 VBoxOGLpackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \
@@ -599,6 +602,7 @@ VBoxOGLpackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \
 	$(PATH_STAGE_LIB)/additions/VBoxOGLcrstate-x86$(VBOX_SUFF_LIB) \
 	$(PATH_STAGE_LIB)/additions/VBoxOGLcrpacker-x86$(VBOX_SUFF_LIB)
 VBoxOGLpackspu-x86_DEFS = $(VBoxOGLpackspu_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # Generate files for VBoxOGLpackspu.
@@ -663,15 +667,18 @@ ifdef VBOX_WITH_WDDM
 VBoxOGLfeedbackspu_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+ifdef VBOX_WITH_WDDM
 #
 # VBoxOGLfeedbackspu-x86 - x86 version of VBoxOGLfeedbackspu built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGLfeedbackspu-x86
 VBoxOGLfeedbackspu-x86_EXTENDS = VBoxOGLfeedbackspu
 VBoxOGLfeedbackspu-x86_BLD_TRG_ARCH = x86
 VBoxOGLfeedbackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \
 	$(PATH_STAGE_LIB)/additions/VBoxOGLspuload-x86$(VBOX_SUFF_LIB) \
 	$(PATH_STAGE_LIB)/additions/VBoxOGLcrstate-x86$(VBOX_SUFF_LIB)
 VBoxOGLfeedbackspu-x86_DEFS = $(VBoxOGLfeedbackspu_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # Generate files for VBoxOGLfeedbackspu.
diff --git a/src/VBox/Additions/common/crOpenGL/fakedri_drv.c b/src/VBox/Additions/common/crOpenGL/fakedri_drv.c
index 03b537e..f6793da 100644
--- a/src/VBox/Additions/common/crOpenGL/fakedri_drv.c
+++ b/src/VBox/Additions/common/crOpenGL/fakedri_drv.c
@@ -360,7 +360,7 @@ vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd
 
 #ifndef VBOX_NO_MESA_PATCH_REPORTS
     crDebug("Mesa Entry: %p, start: %p(%s:%s), size: %li", pMesaEntry, dlip.dli_saddr, dlip.dli_fname, dlip.dli_sname, sym->st_size);
-    crDebug("Vbox code: start: %p, end %p, size: %li", pStart, pEnd, pEnd-pStart);
+    crDebug("VBox code: start: %p, end %p, size: %li", pStart, pEnd, pEnd-pStart);
 #endif
 
 #ifndef VBOX_OGL_GLX_USE_CSTUBS
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py
index 0c0f335..82f00a8 100644
--- a/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py
+++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py
@@ -48,7 +48,6 @@ GLboolean crPackIsPixelStoreParm(GLenum pname)
 """
 
 from get_sizes import *
-from get_components import *
 
 easy_swaps = { 
     'GenTextures': '(unsigned int) n',
@@ -205,7 +204,7 @@ for func_name in keys:
         if func_name in hard_funcs.keys():
             print '\tif (pack_spu.swap)'
             print '\t{'
-            print '\t\tfor (i = 0 ; i < lookupComponents(pname) ; i++)'
+            print '\t\tfor (i = 0 ; i < crStateHlpComponentsCount(pname) ; i++)'
             print '\t\t{'
             if hard_funcs[func_name] == 'SWAPDOUBLE':
                 print '\t\t\t%s[i] = %s(%s[i]);' % (lastParamName, hard_funcs[func_name], lastParamName)
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c
index 7592b2e..6b3271d 100644
--- a/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c
+++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c
@@ -98,7 +98,7 @@ void PACKSPU_APIENTRY packspu_GetAttachedShaders(GLuint program, GLsizei maxCoun
     crFree(pLocal);
 }
 
-void PACKSPU_APIENTRY packspu_GetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj)
+void PACKSPU_APIENTRY packspu_GetAttachedObjectsARB(VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * count, VBoxGLhandleARB * obj)
 {
     GET_THREAD(thread);
     int writeback = 1;
@@ -106,7 +106,7 @@ void PACKSPU_APIENTRY packspu_GetAttachedObjectsARB(GLhandleARB containerObj, GL
 
     if (!obj) return;
 
-    pLocal = (GLsizei*) crAlloc(maxCount*sizeof(GLhandleARB)+sizeof(GLsizei));
+    pLocal = (GLsizei*) crAlloc(maxCount*sizeof(VBoxGLhandleARB)+sizeof(GLsizei));
     if (!pLocal) return;
 
     crPackGetAttachedObjectsARB(containerObj, maxCount, pLocal, NULL, &writeback);
@@ -115,13 +115,13 @@ void PACKSPU_APIENTRY packspu_GetAttachedObjectsARB(GLhandleARB containerObj, GL
     CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
 
     if (count) *count=*pLocal;
-    crMemcpy(obj, &pLocal[1], *pLocal*sizeof(GLhandleARB));
+    crMemcpy(obj, &pLocal[1], *pLocal*sizeof(VBoxGLhandleARB));
     crFree(pLocal);
 }
 
 AssertCompile(sizeof(GLsizei) == 4);
 
-void PACKSPU_APIENTRY packspu_GetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
+void PACKSPU_APIENTRY packspu_GetInfoLogARB(VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
 {
     GET_THREAD(thread);
     int writeback = 1;
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c
index 8a130f8..d58202e 100644
--- a/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c
+++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c
@@ -129,7 +129,7 @@ void PACKSPU_APIENTRY packspu_DeleteProgram(GLuint program)
     crPackDeleteProgram(program);
 }
 
-void PACK_APIENTRY packspu_DeleteObjectARB(GLhandleARB obj)
+void PACK_APIENTRY packspu_DeleteObjectARB(VBoxGLhandleARB obj)
 {
     GLuint hwid = crStateGetProgramHWID(obj);
 
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c
index e190d08..3048bbc 100644
--- a/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c
+++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c
@@ -722,7 +722,7 @@ void PACKSPU_APIENTRY packspu_VBoxPackDetachThread()
 }
 #endif /*CHROMIUM_THREADSAFE*/
 
-void PACKSPU_APIENTRY packspu_VBoxPresentComposition(GLint win, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
+void PACKSPU_APIENTRY packspu_VBoxPresentComposition(GLint win, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
 {
 }
 
diff --git a/src/VBox/Additions/common/pam/Makefile.kmk b/src/VBox/Additions/common/pam/Makefile.kmk
index 5e651e1..a6dd4df 100644
--- a/src/VBox/Additions/common/pam/Makefile.kmk
+++ b/src/VBox/Additions/common/pam/Makefile.kmk
@@ -32,19 +32,4 @@ pam_vbox_LIBS = \
 	$(VBOX_LIB_VBGL_R3_SHARED) \
 	$(VBOX_LIB_IPRT_GUEST_R3_SHARED)
 
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  DLLS += pam_vbox_32
-  pam_vbox_32_EXTENDS  = pam_vbox
-  pam_vbox_32_TEMPLATE = VBOXGUESTR3DLL_X86
-  pam_vbox_32_NAME     = pam_vbox
-  pam_vbox_32_LIBS = \
-        pam \
-        $(VBOX_LIB_IPRT_GUEST_R3_SHARED_X86) \
-        $(VBOX_LIB_VBGL_R3_SHARED_X86) \
-        $(VBOX_LIB_IPRT_GUEST_R3_SHARED_X86)
- endif
-endif
-
 include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/src/VBox/Additions/linux/drm/Makefile.module b/src/VBox/Additions/linux/drm/Makefile.module
index 81b69a4..58daaef 100644
--- a/src/VBox/Additions/linux/drm/Makefile.module
+++ b/src/VBox/Additions/linux/drm/Makefile.module
@@ -31,6 +31,12 @@ MOD_CFLAGS = -fshort-wchar -include $(MANGLING)
 MOD_INCL   = $(addprefix -I$(KBUILD_EXTMOD),/ /include /r0drv/linux)
 # What on earth is this?
 MOD_INCL  += $(addprefix -I$(KBUILD_EXTMOD)/vboxvideo,/ /include /r0drv/linux)
+# Enterprise Linux 6.5 does not include the drm user API headers with the kernel
+# headers.
+MOD_INCL += $(foreach inc,$(KERN_INCL) include,\
+              $(if $(wildcard $(inc)/linux/utsrelease.h),\
+                $(if $(shell grep '"2.6.32.*el6.*"' $(inc)/linux/utsrelease.h),\
+		      -I/usr/include,),))
 MOD_DEFS  := -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 \
 	     -DIN_SUP_R0 -DVBOX -DVBOX_WITH_HGCM -DLOG_TO_BACKDOOR -DIN_MODULE \
 	     -DIN_GUEST_R0
diff --git a/src/VBox/Additions/linux/installer/vboxadd-x11.sh b/src/VBox/Additions/linux/installer/vboxadd-x11.sh
index 8198dcf..1d87127 100755
--- a/src/VBox/Additions/linux/installer/vboxadd-x11.sh
+++ b/src/VBox/Additions/linux/installer/vboxadd-x11.sh
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Linux Additions X11 setup init script ($Revision: 86440 $)
+# Linux Additions X11 setup init script ($Revision: 91688 $)
 #
 
 #
@@ -316,7 +316,11 @@ setup()
     fi
 
     test -z "$x_version" -o -z "$modules_dir" &&
-        fail "Could not find the X.Org or XFree86 Window System."
+        {
+            echo
+            echo "Could not find the X.Org or XFree86 Window System, skipping."
+            exit 0
+        }
 
     echo
     # openSUSE 10.3 shipped X.Org 7.2 with X.Org Server 1.3, but didn't
diff --git a/src/VBox/Additions/linux/sharedfolders/Makefile.kmk b/src/VBox/Additions/linux/sharedfolders/Makefile.kmk
index f212df4..61688a8 100644
--- a/src/VBox/Additions/linux/sharedfolders/Makefile.kmk
+++ b/src/VBox/Additions/linux/sharedfolders/Makefile.kmk
@@ -81,15 +81,5 @@ mount.vboxsf_SOURCES     = \
 	mount.vboxsf.c \
 	vbsfmount.c
 
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  PROGRAMS += mount.vboxsf_32
-  mount.vboxsf_32_EXTENDS  = mount.vboxsf
-  mount.vboxsf_32_TEMPLATE = NewVBoxGuestR3Exe_X86
-  mount.vboxsf_32_NAME     = mount.vboxsf
- endif
-endif
-
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/VBox/Additions/x11/VBoxClient/Makefile.kmk b/src/VBox/Additions/x11/VBoxClient/Makefile.kmk
index dea18de..9a4e587 100644
--- a/src/VBox/Additions/x11/VBoxClient/Makefile.kmk
+++ b/src/VBox/Additions/x11/VBoxClient/Makefile.kmk
@@ -75,16 +75,6 @@ ifdef VBOX_WITH_DRAG_AND_DROP
 	draganddrop.cpp
 endif
 
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  PROGRAMS += VBoxClient_32
-  VBoxClient_32_EXTENDS  = VBoxClient
-  VBoxClient_32_TEMPLATE = NewVBoxGuestR3Exe_X86
-  VBoxClient_32_NAME     = VBoxClient
- endif
-endif
-
 ifdef VBOX_X11_SEAMLESS_GUEST
  if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK)
   if1of ($(KBUILD_TARGET), freebsd linux netbsd openbsd solaris)
diff --git a/src/VBox/Additions/x11/vboxmouse/Makefile.kmk b/src/VBox/Additions/x11/vboxmouse/Makefile.kmk
index 05c4c82..5a4dbf4 100644
--- a/src/VBox/Additions/x11/vboxmouse/Makefile.kmk
+++ b/src/VBox/Additions/x11/vboxmouse/Makefile.kmk
@@ -238,19 +238,6 @@ vboxmouse_drv_112_SOURCES = \
 
 endif # neq ($(KBUILD_TARGET),linux)
 
-# 32-bit modules for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  SYSMODS += vboxmouse_drv_32
-  vboxmouse_drv_32_EXTENDS  = vboxmouse_drv
-  vboxmouse_drv_32_TEMPLATE = VBOXGUESTR3XF86MOD_X86
-  vboxmouse_drv_32_NAME     = vboxmouse_drv
-  $(foreach i,$(filter vboxmouse_drv_%,$(DLLS)),$(eval DLLS += $(i)_32))
-  $(foreach i,$(filter vboxmouse_drv_%_32,$(DLLS)),$(eval $(i)_EXTENDS = $(subst _32,,$(i))))
-  $(foreach i,$(filter vboxmouse_drv_%_32,$(DLLS)),$(eval $(i)_TEMPLATE = VBOXGUESTR3XORGMOD_X86))
-  $(foreach i,$(filter vboxmouse_drv_%_32,$(DLLS)),$(eval $(i)_NAME = $(subst _32,,$(i))))
- endif
-endif
 
 ifdef VBOX_USE_SYSTEM_XORG_HEADERS
  # As vboxmouse_drv is not needed at all for X.Org Server 1.7 and later do not
diff --git a/src/VBox/Additions/x11/vboxvideo/Makefile.kmk b/src/VBox/Additions/x11/vboxvideo/Makefile.kmk
index 5a85702..7dde54c 100644
--- a/src/VBox/Additions/x11/vboxvideo/Makefile.kmk
+++ b/src/VBox/Additions/x11/vboxvideo/Makefile.kmk
@@ -32,8 +32,13 @@ ifeq ($(KBUILD_TARGET),solaris) # don't use .solaris or anything here.
 endif
 vboxvideo_13_DEFS := $(vboxvideo_70_DEFS) VBOXVIDEO_13
 vboxvideo_15_DEFS := \
-	$(vboxvideo_13_DEFS) VBOX_DRI NO_ANSIC PCIACCESS XSERVER_LIBPCIACCESS
+	$(vboxvideo_13_DEFS) NO_ANSIC PCIACCESS XSERVER_LIBPCIACCESS
+if1of ($(KBUILD_TARGET), linux solaris)
+ vboxvideo_15_DEFS += \
+ 	VBOX_DRI
+endif
 vboxvideo_xorg_INCS = \
+    $(VBOX_PATH_X11_ROOT)/dri2proto-2.8 \
 	$(VBOX_PATH_X11_ROOT)/fontsproto-2.1.0 \
 	$(VBOX_PATH_X11_ROOT)/glproto-1.4.10 \
 	$(VBOX_PATH_X11_ROOT)/MesaLib-8.0.4-GL \
@@ -194,7 +199,8 @@ vboxvideo_drv_15_TEMPLATE = VBOXGUESTR3XORGMOD
 vboxvideo_drv_15_CFLAGS := $(vboxvideo_drv_70_CFLAGS)
 vboxvideo_drv_15_DEFS := $(vboxvideo_15_DEFS) XORG_VERSION_CURRENT=100503000
 if1of ($(KBUILD_TARGET), linux solaris)
- vboxvideo_drv_15_DEFS += VBOX_DRI
+ vboxvideo_drv_15_DEFS += \
+ 	VBOX_DRI_OLD
 endif
 vboxvideo_drv_15_INCS = \
 	$(vboxvideo_xorg_INCS) \
@@ -203,7 +209,7 @@ vboxvideo_drv_15_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
 vboxvideo_drv_15_SOURCES  = $(vboxvideo_drv_13_SOURCES)
 if1of ($(KBUILD_TARGET), linux solaris)
  vboxvideo_drv_15_SOURCES += \
-	vboxvideo_dri.c
+ 	vboxvideo_dri.c
 endif
 
 
@@ -214,6 +220,10 @@ DLLS += vboxvideo_drv_16
 vboxvideo_drv_16_TEMPLATE = VBOXGUESTR3XORGMOD
 vboxvideo_drv_16_CFLAGS := $(vboxvideo_drv_70_CFLAGS)
 vboxvideo_drv_16_DEFS := $(vboxvideo_15_DEFS) XORG_VERSION_CURRENT=100600000
+if1of ($(KBUILD_TARGET), linux solaris)
+ vboxvideo_drv_16_DEFS += \
+ 	VBOX_DRI_OLD
+endif
 vboxvideo_drv_16_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.6.0 \
@@ -232,7 +242,11 @@ vboxvideo_drv_17_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.7.7
 vboxvideo_drv_17_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_17_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_17_SOURCES := $(vboxvideo_drv_13_SOURCES)
+if1of ($(KBUILD_TARGET), linux solaris)
+ vboxvideo_drv_17_SOURCES += \
+ 	vboxvideo_dri2.c
+endif
 
 
 #
@@ -246,7 +260,7 @@ vboxvideo_drv_18_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.8.0
 vboxvideo_drv_18_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_18_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_18_SOURCES := $(vboxvideo_drv_17_SOURCES)
 
 
 #
@@ -260,7 +274,7 @@ vboxvideo_drv_19_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.9.0
 vboxvideo_drv_19_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_19_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_19_SOURCES := $(vboxvideo_drv_17_SOURCES)
 
 
 #
@@ -274,7 +288,7 @@ vboxvideo_drv_110_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.10.0
 vboxvideo_drv_110_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_110_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_110_SOURCES := $(vboxvideo_drv_17_SOURCES)
 
 
 #
@@ -288,7 +302,7 @@ vboxvideo_drv_111_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.11.0
 vboxvideo_drv_111_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_111_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_111_SOURCES := $(vboxvideo_drv_17_SOURCES)
 
 
 #
@@ -302,7 +316,7 @@ vboxvideo_drv_112_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.12.0
 vboxvideo_drv_112_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_112_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_112_SOURCES := $(vboxvideo_drv_17_SOURCES)
 
 
 #
@@ -316,7 +330,7 @@ vboxvideo_drv_113_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.13.0
 vboxvideo_drv_113_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_113_SOURCES := $(vboxvideo_drv_15_SOURCES)
+vboxvideo_drv_113_SOURCES := $(vboxvideo_drv_17_SOURCES)
 
 
 #
@@ -330,22 +344,22 @@ vboxvideo_drv_114_INCS = \
 	$(vboxvideo_xorg_INCS) \
 	$(VBOX_PATH_X11_ROOT)/xorg-server-1.14.0
 vboxvideo_drv_114_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
-vboxvideo_drv_114_SOURCES := $(vboxvideo_drv_15_SOURCES)
-
-
-# 32-bit modules for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  SYSMODS += vboxvideo_drv_32
-  vboxvideo_drv_32_EXTENDS  = vboxvideo_drv
-  vboxvideo_drv_32_TEMPLATE = VBOXGUESTR3XF86MOD_X86
-  vboxvideo_drv_32_NAME     = vboxvideo_drv
-  $(foreach i,$(filter vboxvideo_drv_%,$(DLLS)),$(eval DLLS += $(i)_32))
-  $(foreach i,$(filter vboxvideo_drv_%_32,$(DLLS)),$(eval $(i)_EXTENDS = $(subst _32,,$(i))))
-  $(foreach i,$(filter vboxvideo_drv_%_32,$(DLLS)),$(eval $(i)_TEMPLATE = VBOXGUESTR3XORGMOD_X86))
-  $(foreach i,$(filter vboxvideo_drv_%_32,$(DLLS)),$(eval $(i)_NAME = $(subst _32,,$(i))))
- endif
-endif
+vboxvideo_drv_114_SOURCES := $(vboxvideo_drv_17_SOURCES)
+
+
+#
+# vboxvideo_drv_115
+#
+DLLS += vboxvideo_drv_115
+vboxvideo_drv_115_TEMPLATE = VBOXGUESTR3XORGMOD
+vboxvideo_drv_115_CFLAGS := $(vboxvideo_drv_70_CFLAGS)
+vboxvideo_drv_115_DEFS := $(vboxvideo_15_DEFS) XORG_VERSION_CURRENT=101500000
+vboxvideo_drv_115_INCS = \
+	$(vboxvideo_xorg_INCS) \
+	$(VBOX_PATH_X11_ROOT)/xorg-server-1.15.0
+vboxvideo_drv_115_INCS += $(PATH_ROOT)/src/VBox/Runtime/include
+vboxvideo_drv_115_SOURCES := $(vboxvideo_drv_17_SOURCES)
+
 
 ifdef VBOX_USE_SYSTEM_XORG_HEADERS
  # Build using local X.Org headers.  We assume X.Org Server 1.7 or later.
@@ -365,6 +379,7 @@ ifdef VBOX_USE_SYSTEM_XORG_HEADERS
  vboxvideo_drv_system_SOURCES := $(vboxvideo_drv_15_SOURCES)
 endif
 
+
 # Check the undefined symbols in the X.Org modules against lists of allowed
 # symbols.  Not very elegant, but it will catch problems early.
 
@@ -399,7 +414,7 @@ $$(vboxvideo_drv_0_OUTDIR)/tstvboxvideo68.run: $$(vboxvideo_drv_1_STAGE_TARGET)
 	$$(QUIET)$$(APPEND) -t "$$@" "done"
     endef
 
-    $(foreach ver, _70 _71 _13 _14 _15 _16 _17 _18 _19 _110 _111 _112 _113 _114, $(eval $(def_vboxvideo_test)))
+    $(foreach ver, _70 _71 _13 _14 _15 _16 _17 _18 _19 _110 _111 _112 _113 _114 _115, $(eval $(def_vboxvideo_test)))
 
     endif # ! VBOX_ONLY_SDK
    endif # eq ($(KBUILD_HOST_ARCH),$(KBUILD_TARGET_ARCH))
diff --git a/src/VBox/Additions/x11/vboxvideo/setmode.c b/src/VBox/Additions/x11/vboxvideo/setmode.c
index fcb9eb6..7e082f8 100644
--- a/src/VBox/Additions/x11/vboxvideo/setmode.c
+++ b/src/VBox/Additions/x11/vboxvideo/setmode.c
@@ -170,7 +170,7 @@ Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
     pScrn->virtualY = height;
     pScrn->displayWidth = displayWidth;
     pVBox->cbLine = cbLine;
-#ifdef VBOX_DRI
+#ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
         VBOXDRIUpdateStride(pScrn, pVBox);
 #endif
diff --git a/src/VBox/Additions/x11/vboxvideo/undefined b/src/VBox/Additions/x11/vboxvideo/undefined
index 1a7c825..d2ef2bd 100644
--- a/src/VBox/Additions/x11/vboxvideo/undefined
+++ b/src/VBox/Additions/x11/vboxvideo/undefined
@@ -1,3 +1,5 @@
+DRI2CloseScreen
+DRI2ScreenInit
 DRICloseScreen
 DRICreateInfoRec
 DRICreatePCIBusID
diff --git a/src/VBox/Additions/x11/vboxvideo/vboxvideo.c b/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
index f5ca576..d3affd9 100644
--- a/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
+++ b/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
@@ -827,10 +827,16 @@ VBOXPreInit(ScrnInfoPtr pScrn, int flags)
     if (!xf86LoadSubModule(pScrn, "vgahw"))
         return FALSE;
 
-#ifdef VBOX_DRI
+#ifdef VBOX_DRI_OLD
     /* Load the dri module. */
     if (!xf86LoadSubModule(pScrn, "dri"))
         return FALSE;
+#else
+# ifdef VBOX_DRI
+    /* Load the dri module. */
+    if (!xf86LoadSubModule(pScrn, "dri2"))
+        return FALSE;
+# endif
 #endif
 
 #ifndef PCIACCESS
@@ -1159,7 +1165,7 @@ static Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv)
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
 
-#ifdef VBOX_DRI
+#ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
         pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
 #endif
@@ -1174,7 +1180,7 @@ static Bool VBOXEnterVT(ScrnInfoPtr pScrn)
     vboxClearVRAM(pScrn, 0, 0);
     if (pVBox->fHaveHGSMI)
         vboxEnableVbva(pScrn);
-#ifdef VBOX_DRI
+#ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
         DRIUnlock(xf86ScrnToScreen(pScrn));
 #endif
@@ -1203,7 +1209,7 @@ static void VBOXLeaveVT(ScrnInfoPtr pScrn)
     vboxClearVRAM(pScrn, 0, 0);
     VBOXRestoreMode(pScrn);
     vboxDisableGraphicsCap(pVBox);
-#ifdef VBOX_DRI
+#ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
         DRILock(xf86ScrnToScreen(pScrn), 0);
 #endif
diff --git a/src/VBox/Additions/x11/vboxvideo/vboxvideo.h b/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
index 5486323..6564e6f 100644
--- a/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
+++ b/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
@@ -105,7 +105,7 @@ if (!(expr)) \
 #define VBOX_NAME               "VBoxVideo"
 #define VBOX_DRIVER_NAME        "vboxvideo"
 
-#ifdef VBOX_DRI
+#ifdef VBOX_DRI_OLD
 /* DRI support */
 #define _XF86DRI_SERVER_
 /* Hack to work around a libdrm header which is broken on Solaris */
@@ -191,10 +191,12 @@ typedef struct VBOXRec
     Bool fAnyX;
 #ifdef VBOX_DRI
     Bool useDRI;
+#ifdef VBOX_DRI_OLD
     int cVisualConfigs;
     __GLXvisualConfig *pVisualConfigs;
     DRIInfoRec *pDRIInfo;
     int drmFD;
+# endif
 #endif
 } VBOXRec, *VBOXPtr;
 
diff --git a/src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c b/src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c
new file mode 100644
index 0000000..493f205
--- /dev/null
+++ b/src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c
@@ -0,0 +1,62 @@
+/** @file $Id: vboxvideo_dri2.c $
+ *
+ * VirtualBox X11 Additions graphics driver, DRI2 support
+ */
+
+/*
+ * Copyright (C) 2006-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "vboxvideo.h"
+#include <drm.h>
+#include <dri2.h>
+
+static void VBOXDRICopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
+                              DRI2BufferPtr pDest, DRI2BufferPtr pSrc)
+{
+}
+
+static DRI2Buffer2Ptr VBOXDRICreateBuffer(DrawablePtr pDraw,
+                                          unsigned int cAttachment,
+                                          unsigned int cFormat)
+{
+    return calloc(1, sizeof(DRI2Buffer2Rec));
+}
+
+static void VBOXDRIDestroyBuffer(DrawablePtr pDraw, DRI2Buffer2Ptr pBuffer)
+{
+    free(pBuffer);
+}
+
+/** As long as we are using our fake DRI driver inside of Mesa, we only want
+ *  to implement the minimum here to make Mesa load it.  Notably we just set
+ *  "DRI2Info.fd" to -1 as we do not need authentication to work. */
+Bool VBOXDRIScreenInit(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
+{
+    DRI2InfoRec DRI2Info;
+
+    memset(&DRI2Info, 0, sizeof(DRI2Info));
+    DRI2Info.version = 3;
+    DRI2Info.fd = -1;
+    DRI2Info.driverName = VBOX_DRI_DRIVER_NAME;
+    DRI2Info.deviceName = "/dev/dri/card0";  /** @todo: do this right. */
+    DRI2Info.CopyRegion = VBOXDRICopyRegion;
+    DRI2Info.Wait = NULL;
+    DRI2Info.CreateBuffer = VBOXDRICreateBuffer;
+    DRI2Info.DestroyBuffer = VBOXDRIDestroyBuffer;
+    return DRI2ScreenInit(pScreen, &DRI2Info);
+}
+
+void
+VBOXDRICloseScreen(ScreenPtr pScreen, VBOXPtr pVBox)
+{
+    DRI2CloseScreen(pScreen);
+}
diff --git a/src/VBox/Devices/BiosCommonCode/MakeAlternativeSource.cpp b/src/VBox/Devices/BiosCommonCode/MakeAlternativeSource.cpp
index fdb95fc..8b86e87 100644
--- a/src/VBox/Devices/BiosCommonCode/MakeAlternativeSource.cpp
+++ b/src/VBox/Devices/BiosCommonCode/MakeAlternativeSource.cpp
@@ -1025,7 +1025,25 @@ static bool disCode(uint32_t uFlatAddr, uint32_t cb, bool fIs16Bit)
                      && pb[2] == 0x8d
                      && pb[3] == 0xbb
                      && pb[4] == 0x8c
-                     && pb[5] == 0x2f)
+                     && pb[5] == 0x2f
+                     )
+                 || (   pb[0] == 0xec   /* _int15_function switch */
+                     && pb[1] == 0xe9
+                     && pb[2] == 0xd8
+                     && pb[3] == 0xc1
+                     && pb[4] == 0xc0
+                     && pb[5] == 0xbf
+                     && pb[6] == 0x91
+                    )
+                 || (   pb[0] == 0x00
+                     && pb[1] == 0xe0
+                     && pb[2] == 0x94
+                     && pb[3] == 0xe2
+                     && pb[4] == 0x94
+                     && pb[5] == 0xe6
+                     && pb[6] == 0x94
+                     && pb[7] == 0xe6
+                    )
                  || 0
                  )
             return disByteData(uFlatAddr, cb);
diff --git a/src/VBox/Devices/EFI/DevEFI.cpp b/src/VBox/Devices/EFI/DevEFI.cpp
index 353ef67..1400a63 100644
--- a/src/VBox/Devices/EFI/DevEFI.cpp
+++ b/src/VBox/Devices/EFI/DevEFI.cpp
@@ -22,6 +22,7 @@
 
 #include <VBox/vmm/pdmdev.h>
 #include <VBox/vmm/pgm.h>
+#include <VBox/vmm/cpum.h>
 #include <VBox/vmm/mm.h>
 #include <VBox/log.h>
 #include <VBox/err.h>
@@ -2208,7 +2209,8 @@ static DECLCALLBACK(int)  efiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
         return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
                                    N_("Configuration error: Querying \"BootArgs\" as a string failed"));
 
-    //strcpy(pThis->szBootArgs, "-v keepsyms=1 io=0xf");
+    //strcpy(pThis->szBootArgs, "-v keepsyms=1 io=0xf debug=0x2a");
+    //strcpy(pThis->szBootArgs, "-v keepsyms=1 debug=0x2a");
     LogRel(("EFI: boot args = %s\n", pThis->szBootArgs));
 
     /*
@@ -2238,9 +2240,8 @@ static DECLCALLBACK(int)  efiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
      * CPU frequencies.
      */
     pThis->u64TscFrequency = TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns));
-    /* Multiplier is read from MSR_IA32_PERF_STATUS, and now is hardcoded as 4. */
-    pThis->u64FsbFrequency = pThis->u64TscFrequency / 4;
     pThis->u64CpuFrequency = pThis->u64TscFrequency;
+    pThis->u64FsbFrequency = CPUMGetGuestBusFrequency(PDMDevHlpGetVM(pDevIns));
 
     /*
      * GOP graphics.
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd
index 9040878..22c648a 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 fd73b84..eab9b08 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/VBoxVgaBiosAlternative.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
index 14aab00..850c34f 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
@@ -6781,7 +6781,7 @@ vesa_pm_end:                                 ; 0xc4714 LB 0x1
 
 section _DATA progbits vstart=0x4800 align=1 ; size=0x36e0 class=DATA group=DGROUP
 _msg_vga_init:                               ; 0xc4800 LB 0x2e
-    db  'Oracle VM VirtualBox Version 4.3.6 VGA BIOS', 00dh, 00ah, 000h
+    db  'Oracle VM VirtualBox Version 4.3.8 VGA BIOS', 00dh, 00ah, 000h
 _vga_modes:                                  ; 0xc482e 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
@@ -7669,7 +7669,7 @@ _vbebios_vendor_name:                        ; 0xc7e35 LB 0x13
 _vbebios_product_name:                       ; 0xc7e48 LB 0x21
     db  'Oracle VM VirtualBox VBE Adapter', 000h
 _vbebios_product_revision:                   ; 0xc7e69 LB 0x23
-    db  'Oracle VM VirtualBox Version 4.3.6', 000h
+    db  'Oracle VM VirtualBox Version 4.3.8', 000h
 _vbebios_info_string:                        ; 0xc7e8c LB 0x2b
     db  'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h
 _no_vbebios_info_string:                     ; 0xc7eb7 LB 0x29
@@ -7697,4 +7697,4 @@ section CONST2 progbits vstart=0x7ee0 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, 01ah
+    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 016h
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum
index 74cbcaa..4f54140 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum
@@ -1 +1 @@
-91ea1d88bf4f3e90ef38a1983674c9db *VBoxVgaBios.rom
+86355c5abda5dd1b0bf3f2f65828c6a1 *VBoxVgaBios.rom
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
new file mode 100644
index 0000000..8d473a0
--- /dev/null
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
@@ -0,0 +1,3196 @@
+/** @file
+ * VMWare SVGA device
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/version.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <VBox/vmm/pgm.h>
+
+#include <iprt/assert.h>
+#include <iprt/semaphore.h>
+#include <iprt/uuid.h>
+#ifdef IN_RING3
+#include <iprt/mem.h>
+#endif
+
+#include <VBox/VMMDev.h>
+#include <VBox/VBoxVideo.h>
+#include <VBox/bioslogo.h>
+
+/* 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"
+#include "vmsvga/svga_overlay.h"
+#include "vmsvga/svga3d_reg.h"
+#include "vmsvga/svga3d_caps.h"
+#ifdef VBOX_WITH_VMSVGA3D
+#include "DevVGA-SVGA3d.h"
+#endif
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/* 64-bit GMR descriptor */
+typedef struct 
+{
+   RTGCPHYS GCPhys;
+   uint64_t numPages;
+} VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR;
+
+/* GMR slot */
+typedef struct
+{
+    uint32_t                    cbTotal;
+    uint32_t                    numDescriptors;
+    PVMSVGAGMRDESCRIPTOR        paDesc;
+} GMR, *PGMR;
+
+/* Internal SVGA state. */
+typedef struct
+{
+    GMR                     aGMR[VMSVGA_MAX_GMR_IDS];
+    struct
+    {
+        SVGAGuestPtr        ptr;
+        uint32_t            bytesPerLine;
+        SVGAGMRImageFormat  format;
+    } GMRFB;
+    SVGAColorBGRX           colorAnnotation;
+    STAMPROFILE             StatR3CmdPresent;
+    STAMPROFILE             StatR3CmdDrawPrimitive;
+    STAMPROFILE             StatR3CmdSurfaceDMA;
+} VMSVGASTATE, *PVMSVGASTATE;
+
+#ifdef IN_RING3
+
+/**
+ * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure.
+ */
+static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] =
+{
+    SSMFIELD_ENTRY_GCPHYS(      VMSVGAGMRDESCRIPTOR,     GCPhys),
+    SSMFIELD_ENTRY(             VMSVGAGMRDESCRIPTOR,     numPages),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * SSM descriptor table for the GMR structure.
+ */
+static SSMFIELD const g_aGMRFields[] =
+{
+    SSMFIELD_ENTRY(             GMR, cbTotal),
+    SSMFIELD_ENTRY(             GMR, numDescriptors),
+    SSMFIELD_ENTRY_IGN_HCPTR(   GMR, paDesc),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * SSM descriptor table for the VMSVGASTATE structure.
+ */
+static SSMFIELD const g_aVMSVGASTATEFields[] =
+{
+    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, aGMR),
+    SSMFIELD_ENTRY(             VMSVGASTATE, GMRFB),
+    SSMFIELD_ENTRY(             VMSVGASTATE, colorAnnotation),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatR3CmdPresent),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatR3CmdDrawPrimitive),
+    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatR3CmdSurfaceDMA),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * SSM descriptor table for the VGAState.svga structure.
+ */
+static SSMFIELD const g_aVGAStateSVGAFields[] =
+{
+    SSMFIELD_ENTRY_IGNORE(          VGAState, svga.u64HostWindowId),
+    SSMFIELD_ENTRY_IGN_HCPTR(       VGAState, svga.pFIFOR3),
+    SSMFIELD_ENTRY_IGN_HCPTR(       VGAState, svga.pFIFOR0),
+    SSMFIELD_ENTRY_IGN_HCPTR(       VGAState, svga.pSVGAState),
+    SSMFIELD_ENTRY_IGN_HCPTR(       VGAState, svga.p3dState),
+    SSMFIELD_ENTRY_IGNORE(          VGAState, svga.pFrameBufferBackup),
+    SSMFIELD_ENTRY_IGN_GCPHYS(      VGAState, svga.GCPhysFIFO),
+    SSMFIELD_ENTRY_IGNORE(          VGAState, svga.cbFIFO),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32SVGAId),
+    SSMFIELD_ENTRY(                 VGAState, svga.fEnabled),
+    SSMFIELD_ENTRY(                 VGAState, svga.fConfigured),
+    SSMFIELD_ENTRY(                 VGAState, svga.fBusy),
+    SSMFIELD_ENTRY(                 VGAState, svga.fTraces),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32GuestId),
+    SSMFIELD_ENTRY(                 VGAState, svga.cScratchRegion),
+    SSMFIELD_ENTRY(                 VGAState, svga.au32ScratchRegion),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32IrqStatus),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32IrqMask),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32PitchLock),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32CurrentGMRId),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32RegCaps),
+    SSMFIELD_ENTRY_IGNORE(          VGAState, svga.BasePort),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32IndexReg),
+    SSMFIELD_ENTRY_IGNORE(          VGAState, svga.FIFORequestSem),
+    SSMFIELD_ENTRY_IGN_HCPTR(       VGAState, svga.pFIFOIOThread),
+    SSMFIELD_ENTRY(                 VGAState, svga.iWidth),
+    SSMFIELD_ENTRY(                 VGAState, svga.iHeight),
+    SSMFIELD_ENTRY(                 VGAState, svga.iBpp),
+    SSMFIELD_ENTRY(                 VGAState, svga.cbScanline),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32MaxWidth),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32MaxHeight),
+    SSMFIELD_ENTRY(                 VGAState, svga.u32ActionFlags),
+    SSMFIELD_ENTRY(                 VGAState, svga.f3DEnabled),
+    SSMFIELD_ENTRY(                 VGAState, svga.fVRAMTracking),
+    SSMFIELD_ENTRY(                 VGAState, svga.Padding6),
+    SSMFIELD_ENTRY_TERM()
+};
+#endif /* IN_RING3 */
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING3
+static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces);
+#endif
+
+RT_C_DECLS_END
+
+
+#ifdef LOG_ENABLED
+/**
+ * Index register string name lookup
+ *
+ * @returns Index register string or "UNKNOWN"
+ * @param   pThis       VMSVGA State
+ */
+static const char *vmsvgaIndexToString(PVGASTATE pThis)
+{
+    switch (pThis->svga.u32IndexReg)
+    {
+    case SVGA_REG_ID:
+        return "SVGA_REG_ID";
+    case SVGA_REG_ENABLE:
+        return "SVGA_REG_ENABLE";
+    case SVGA_REG_WIDTH:
+        return "SVGA_REG_WIDTH";
+    case SVGA_REG_HEIGHT:
+        return "SVGA_REG_HEIGHT";
+    case SVGA_REG_MAX_WIDTH:
+        return "SVGA_REG_MAX_WIDTH";
+    case SVGA_REG_MAX_HEIGHT:
+        return "SVGA_REG_MAX_HEIGHT";
+    case SVGA_REG_DEPTH:
+        return "SVGA_REG_DEPTH";
+    case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
+        return "SVGA_REG_BITS_PER_PIXEL";
+    case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
+        return "SVGA_REG_HOST_BITS_PER_PIXEL";
+    case SVGA_REG_PSEUDOCOLOR:
+        return "SVGA_REG_PSEUDOCOLOR";
+    case SVGA_REG_RED_MASK:
+        return "SVGA_REG_RED_MASK";
+    case SVGA_REG_GREEN_MASK:
+        return "SVGA_REG_GREEN_MASK";
+    case SVGA_REG_BLUE_MASK:
+        return "SVGA_REG_BLUE_MASK";
+    case SVGA_REG_BYTES_PER_LINE:
+        return "SVGA_REG_BYTES_PER_LINE";
+    case SVGA_REG_VRAM_SIZE:            /* VRAM size */
+        return "SVGA_REG_VRAM_SIZE";
+    case SVGA_REG_FB_START:             /* Frame buffer physical address. */
+        return "SVGA_REG_FB_START";
+    case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
+        return "SVGA_REG_FB_OFFSET";
+    case SVGA_REG_FB_SIZE:              /* Frame buffer size */
+        return "SVGA_REG_FB_SIZE";
+    case SVGA_REG_CAPABILITIES:
+        return "SVGA_REG_CAPABILITIES";
+    case SVGA_REG_MEM_START:           /* FIFO start */
+        return "SVGA_REG_MEM_START";
+    case SVGA_REG_MEM_SIZE:            /* FIFO size */
+        return "SVGA_REG_MEM_SIZE";
+    case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
+        return "SVGA_REG_CONFIG_DONE";
+    case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
+        return "SVGA_REG_SYNC";
+    case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
+        return "SVGA_REG_BUSY";
+    case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
+        return "SVGA_REG_GUEST_ID";
+    case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
+        return "SVGA_REG_SCRATCH_SIZE";
+    case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
+        return "SVGA_REG_MEM_REGS";
+    case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
+        return "SVGA_REG_PITCHLOCK";
+    case SVGA_REG_IRQMASK:             /* Interrupt mask */
+        return "SVGA_REG_IRQMASK";
+    case SVGA_REG_GMR_ID:
+        return "SVGA_REG_GMR_ID";
+    case SVGA_REG_GMR_DESCRIPTOR:
+        return "SVGA_REG_GMR_DESCRIPTOR";
+    case SVGA_REG_GMR_MAX_IDS:
+        return "SVGA_REG_GMR_MAX_IDS";
+    case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
+        return "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH";
+    case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
+        return "SVGA_REG_TRACES";
+    case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
+        return "SVGA_REG_GMRS_MAX_PAGES";
+    case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
+        return "SVGA_REG_MEMORY_SIZE";
+    case SVGA_REG_TOP:               /* Must be 1 more than the last register */
+        return "SVGA_REG_TOP";
+    case SVGA_PALETTE_BASE:         /* Base of SVGA color map */
+        return "SVGA_PALETTE_BASE";
+    case SVGA_REG_CURSOR_ID:
+        return "SVGA_REG_CURSOR_ID";
+    case SVGA_REG_CURSOR_X:
+        return "SVGA_REG_CURSOR_X";
+    case SVGA_REG_CURSOR_Y:
+        return "SVGA_REG_CURSOR_Y";
+    case SVGA_REG_CURSOR_ON:
+        return "SVGA_REG_CURSOR_ON";
+    case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
+        return "SVGA_REG_NUM_GUEST_DISPLAYS";
+    case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
+        return "SVGA_REG_DISPLAY_ID";
+    case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
+        return "SVGA_REG_DISPLAY_IS_PRIMARY";
+    case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
+        return "SVGA_REG_DISPLAY_POSITION_X";
+    case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
+        return "SVGA_REG_DISPLAY_POSITION_Y";
+    case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
+        return "SVGA_REG_DISPLAY_WIDTH";
+    case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
+        return "SVGA_REG_DISPLAY_HEIGHT";
+    case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
+        return "SVGA_REG_NUM_DISPLAYS";
+
+    default:
+        if (    pThis->svga.u32IndexReg >= SVGA_SCRATCH_BASE
+            &&  pThis->svga.u32IndexReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion)
+        {
+            return "SVGA_SCRATCH_BASE reg";
+        }
+        return "UNKNOWN";
+    }
+}
+
+/**
+ * FIFO command name lookup
+ *
+ * @returns FIFO command string or "UNKNOWN"
+ * @param   u32Cmd      FIFO command
+ */
+static const char *vmsvgaFIFOCmdToString(uint32_t u32Cmd)
+{
+    switch (u32Cmd)
+    {
+    case SVGA_CMD_INVALID_CMD:
+        return "SVGA_CMD_INVALID_CMD";
+    case SVGA_CMD_UPDATE:
+        return "SVGA_CMD_UPDATE";
+    case SVGA_CMD_RECT_COPY:
+        return "SVGA_CMD_RECT_COPY";
+    case SVGA_CMD_DEFINE_CURSOR:
+        return "SVGA_CMD_DEFINE_CURSOR";
+    case SVGA_CMD_DEFINE_ALPHA_CURSOR:
+        return "SVGA_CMD_DEFINE_ALPHA_CURSOR";
+    case SVGA_CMD_UPDATE_VERBOSE:
+        return "SVGA_CMD_UPDATE_VERBOSE";
+    case SVGA_CMD_FRONT_ROP_FILL:
+        return "SVGA_CMD_FRONT_ROP_FILL";
+    case SVGA_CMD_FENCE:
+        return "SVGA_CMD_FENCE";
+    case SVGA_CMD_ESCAPE:
+        return "SVGA_CMD_ESCAPE";
+    case SVGA_CMD_DEFINE_SCREEN:
+        return "SVGA_CMD_DEFINE_SCREEN";
+    case SVGA_CMD_DESTROY_SCREEN:
+        return "SVGA_CMD_DESTROY_SCREEN";
+    case SVGA_CMD_DEFINE_GMRFB:
+        return "SVGA_CMD_DEFINE_GMRFB";
+    case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
+        return "SVGA_CMD_BLIT_GMRFB_TO_SCREEN";
+    case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
+        return "SVGA_CMD_BLIT_SCREEN_TO_GMRFB";
+    case SVGA_CMD_ANNOTATION_FILL:
+        return "SVGA_CMD_ANNOTATION_FILL";
+    case SVGA_CMD_ANNOTATION_COPY:
+        return "SVGA_CMD_ANNOTATION_COPY";
+    case SVGA_CMD_DEFINE_GMR2:
+        return "SVGA_CMD_DEFINE_GMR2";
+    case SVGA_CMD_REMAP_GMR2:
+        return "SVGA_CMD_REMAP_GMR2";
+    case SVGA_3D_CMD_SURFACE_DEFINE:
+        return "SVGA_3D_CMD_SURFACE_DEFINE";
+    case SVGA_3D_CMD_SURFACE_DESTROY:
+        return "SVGA_3D_CMD_SURFACE_DESTROY";
+    case SVGA_3D_CMD_SURFACE_COPY:
+        return "SVGA_3D_CMD_SURFACE_COPY";
+    case SVGA_3D_CMD_SURFACE_STRETCHBLT:
+        return "SVGA_3D_CMD_SURFACE_STRETCHBLT";
+    case SVGA_3D_CMD_SURFACE_DMA:
+        return "SVGA_3D_CMD_SURFACE_DMA";
+    case SVGA_3D_CMD_CONTEXT_DEFINE:
+        return "SVGA_3D_CMD_CONTEXT_DEFINE";
+    case SVGA_3D_CMD_CONTEXT_DESTROY:
+        return "SVGA_3D_CMD_CONTEXT_DESTROY";
+    case SVGA_3D_CMD_SETTRANSFORM:
+        return "SVGA_3D_CMD_SETTRANSFORM";
+    case SVGA_3D_CMD_SETZRANGE:
+        return "SVGA_3D_CMD_SETZRANGE";
+    case SVGA_3D_CMD_SETRENDERSTATE:
+        return "SVGA_3D_CMD_SETRENDERSTATE";
+    case SVGA_3D_CMD_SETRENDERTARGET:
+        return "SVGA_3D_CMD_SETRENDERTARGET";
+    case SVGA_3D_CMD_SETTEXTURESTATE:
+        return "SVGA_3D_CMD_SETTEXTURESTATE";
+    case SVGA_3D_CMD_SETMATERIAL:
+        return "SVGA_3D_CMD_SETMATERIAL";
+    case SVGA_3D_CMD_SETLIGHTDATA:
+        return "SVGA_3D_CMD_SETLIGHTDATA";
+    case SVGA_3D_CMD_SETLIGHTENABLED:
+        return "SVGA_3D_CMD_SETLIGHTENABLED";
+    case SVGA_3D_CMD_SETVIEWPORT:
+        return "SVGA_3D_CMD_SETVIEWPORT";
+    case SVGA_3D_CMD_SETCLIPPLANE:
+        return "SVGA_3D_CMD_SETCLIPPLANE";
+    case SVGA_3D_CMD_CLEAR:
+        return "SVGA_3D_CMD_CLEAR";
+    case SVGA_3D_CMD_PRESENT:
+        return "SVGA_3D_CMD_PRESENT";
+    case SVGA_3D_CMD_SHADER_DEFINE:
+        return "SVGA_3D_CMD_SHADER_DEFINE";
+    case SVGA_3D_CMD_SHADER_DESTROY:
+        return "SVGA_3D_CMD_SHADER_DESTROY";
+    case SVGA_3D_CMD_SET_SHADER:
+        return "SVGA_3D_CMD_SET_SHADER";
+    case SVGA_3D_CMD_SET_SHADER_CONST:
+        return "SVGA_3D_CMD_SET_SHADER_CONST";
+    case SVGA_3D_CMD_DRAW_PRIMITIVES:
+        return "SVGA_3D_CMD_DRAW_PRIMITIVES";
+    case SVGA_3D_CMD_SETSCISSORRECT:
+        return "SVGA_3D_CMD_SETSCISSORRECT";
+    case SVGA_3D_CMD_BEGIN_QUERY:
+        return "SVGA_3D_CMD_BEGIN_QUERY";
+    case SVGA_3D_CMD_END_QUERY:
+        return "SVGA_3D_CMD_END_QUERY";
+    case SVGA_3D_CMD_WAIT_FOR_QUERY:
+        return "SVGA_3D_CMD_WAIT_FOR_QUERY";
+    case SVGA_3D_CMD_PRESENT_READBACK:
+        return "SVGA_3D_CMD_PRESENT_READBACK";
+    case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
+        return "SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN";
+    case SVGA_3D_CMD_SURFACE_DEFINE_V2:
+        return "SVGA_3D_CMD_SURFACE_DEFINE_V2";
+    case SVGA_3D_CMD_GENERATE_MIPMAPS:
+        return "SVGA_3D_CMD_GENERATE_MIPMAPS";
+    case SVGA_3D_CMD_ACTIVATE_SURFACE:
+        return "SVGA_3D_CMD_ACTIVATE_SURFACE";
+    case SVGA_3D_CMD_DEACTIVATE_SURFACE:
+        return "SVGA_3D_CMD_DEACTIVATE_SURFACE";
+    default:
+        return "UNKNOWN";
+    }
+}
+#endif
+
+/**
+ * Read port register
+ *
+ * @returns VBox status code.
+ * @param   pThis       VMSVGA State
+ * @param   pu32        Where to store the read value
+ */
+PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
+{
+    int rc = VINF_SUCCESS;
+
+    *pu32 = 0;
+    switch (pThis->svga.u32IndexReg)
+    {
+    case SVGA_REG_ID:
+        *pu32 = pThis->svga.u32SVGAId;
+        break;
+
+    case SVGA_REG_ENABLE:
+        *pu32 = pThis->svga.fEnabled;
+        break;
+
+    case SVGA_REG_WIDTH:
+    {
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.iWidth != -1)
+        {
+            *pu32 = pThis->svga.iWidth;
+        }
+        else
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+#else
+            *pu32 = pThis->pDrv->cx;
+#endif
+        }
+        break;
+    }
+
+    case SVGA_REG_HEIGHT:
+    {
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.iHeight != -1)
+        {
+            *pu32 = pThis->svga.iHeight;
+        }
+        else
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+#else
+            *pu32 = pThis->pDrv->cy;
+#endif
+        }
+        break;
+    }
+
+    case SVGA_REG_MAX_WIDTH:
+        *pu32 = pThis->svga.u32MaxWidth;
+        break;
+
+    case SVGA_REG_MAX_HEIGHT:
+        *pu32 = pThis->svga.u32MaxHeight;
+        break;
+
+    case SVGA_REG_DEPTH:
+        /* This returns the color depth of the current mode. */
+        switch (pThis->svga.iBpp)
+        {
+        case 15:
+        case 16:
+        case 24:
+            *pu32 = pThis->svga.iBpp;
+            break;
+
+        default:
+        case 32:
+            *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
+            break;
+        }
+        break;
+
+    case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.iBpp != (unsigned)-1)
+        {
+            *pu32 = pThis->svga.iBpp;
+        }
+        else
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+#else
+            *pu32 = pThis->pDrv->cBits;
+#endif
+        }
+        break;
+
+    case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.iBpp != (unsigned)-1)
+        {
+            *pu32 = (pThis->svga.iBpp + 7) & ~7;
+        }
+        else
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+#else
+            *pu32 = (pThis->pDrv->cBits + 7) & ~7;
+#endif
+        }
+        break;
+
+    case SVGA_REG_PSEUDOCOLOR:
+        *pu32 = 0;
+        break;
+
+    case SVGA_REG_RED_MASK:
+    case SVGA_REG_GREEN_MASK:
+    case SVGA_REG_BLUE_MASK:
+    {
+        uint32_t iBpp;
+
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.iBpp != (unsigned)-1)
+        {
+            iBpp = pThis->svga.iBpp;
+        }
+        else
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+            break;
+#else
+            iBpp = pThis->pDrv->cBits;
+#endif
+        }
+        uint32_t u32RedMask, u32GreenMask, u32BlueMask;
+        switch (iBpp)
+        {
+        case 8:
+            u32RedMask   = 0x07;
+            u32GreenMask = 0x38;
+            u32BlueMask  = 0xc0;
+            break;
+
+        case 15:
+            u32RedMask   = 0x0000001f;
+            u32GreenMask = 0x000003e0;
+            u32BlueMask  = 0x00007c00;
+            break;
+
+        case 16:
+            u32RedMask   = 0x0000001f;
+            u32GreenMask = 0x000007e0;
+            u32BlueMask  = 0x0000f800;
+            break;
+
+        case 24:
+        case 32:
+        default:
+            u32RedMask   = 0x00ff0000;
+            u32GreenMask = 0x0000ff00;
+            u32BlueMask  = 0x000000ff;
+            break;
+        }
+        switch (pThis->svga.u32IndexReg)
+        {
+        case SVGA_REG_RED_MASK:
+            *pu32 = u32RedMask;
+            break;
+
+        case SVGA_REG_GREEN_MASK:
+            *pu32 = u32GreenMask;
+            break;
+
+        case SVGA_REG_BLUE_MASK:
+            *pu32 = u32BlueMask;
+            break;
+        }
+        break;
+    }
+
+    case SVGA_REG_BYTES_PER_LINE:
+    {
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.cbScanline)
+        {
+            *pu32 = pThis->svga.cbScanline;
+        }
+        else
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+#else
+            *pu32 = pThis->pDrv->cbScanline;
+#endif
+        }
+        break;
+    }
+
+    case SVGA_REG_VRAM_SIZE:            /* VRAM size */
+        *pu32 = pThis->vram_size;
+        break;
+
+    case SVGA_REG_FB_START:             /* Frame buffer physical address. */
+        Assert(pThis->GCPhysVRAM <= 0xffffffff);
+        *pu32 = pThis->GCPhysVRAM;
+        break;
+
+    case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
+        /* Always zero in our case. */
+        *pu32 = 0;
+        break;
+
+    case SVGA_REG_FB_SIZE:              /* Frame buffer size */
+    {
+#ifndef IN_RING3
+        rc = VINF_IOM_R3_IOPORT_READ;
+#else
+        /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.iHeight != -1)
+        {
+            /* Hardware enabled; return real framebuffer size .*/
+            *pu32 = (uint32_t)pThis->svga.iHeight * pThis->svga.cbScanline;
+        }
+        else
+            *pu32 = RT_MAX(0x100000, (uint32_t)pThis->pDrv->cy * pThis->pDrv->cbScanline);
+
+        *pu32 = RT_MIN(pThis->vram_size, *pu32);
+        Log(("h=%d w=%d bpp=%d\n", pThis->pDrv->cy, pThis->pDrv->cx, pThis->pDrv->cBits));
+#endif
+        break;
+    }
+
+    case SVGA_REG_CAPABILITIES:
+        *pu32 = pThis->svga.u32RegCaps;
+        break;
+
+    case SVGA_REG_MEM_START:           /* FIFO start */
+        Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
+        *pu32 = pThis->svga.GCPhysFIFO;
+        break;
+
+    case SVGA_REG_MEM_SIZE:            /* FIFO size */
+        *pu32 = pThis->svga.cbFIFO;
+        break;
+
+    case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
+        *pu32 = pThis->svga.fConfigured;
+        break;
+
+    case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
+        *pu32 = 0;
+        break;
+
+    case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
+        if (pThis->svga.fBusy)
+        {
+#ifndef IN_RING3
+            rc = VINF_IOM_R3_IOPORT_READ;
+            break;
+#else
+            /* @todo bit crude */
+            RTThreadSleep(50);
+#endif
+        }
+        *pu32 = pThis->svga.fBusy;
+        break;
+
+    case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
+        *pu32 = pThis->svga.u32GuestId;
+        break;
+
+    case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
+        *pu32 = pThis->svga.cScratchRegion;
+        break;
+
+    case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
+        *pu32 = SVGA_FIFO_NUM_REGS;
+        break;
+
+    case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
+        *pu32 = pThis->svga.u32PitchLock;
+        break;
+
+    case SVGA_REG_IRQMASK:             /* Interrupt mask */
+        *pu32 = pThis->svga.u32IrqMask;
+        break;
+
+    /* See "Guest memory regions" below. */
+    case SVGA_REG_GMR_ID:
+        *pu32 = pThis->svga.u32CurrentGMRId;
+        break;
+
+    case SVGA_REG_GMR_DESCRIPTOR:
+        /* Write only */
+        *pu32 = 0;
+        break;
+
+    case SVGA_REG_GMR_MAX_IDS:
+        *pu32 = VMSVGA_MAX_GMR_IDS;
+        break;
+
+    case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
+        *pu32 = VMSVGA_MAX_GMR_PAGES;
+        break;
+
+    case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
+        *pu32 = pThis->svga.fTraces;
+        break;
+
+    case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
+        *pu32 = VMSVGA_MAX_GMR_PAGES;
+        break;
+
+    case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
+        *pu32 = VMSVGA_SURFACE_SIZE;
+        break;
+
+    case SVGA_REG_TOP:               /* Must be 1 more than the last register */
+        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:
+        break;
+
+    /* Legacy multi-monitor support */
+    case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
+        *pu32 = 1;
+        break;
+
+    case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
+    case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
+    case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
+    case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
+        *pu32 = 0;
+        break;
+
+    case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
+        *pu32 = pThis->svga.iWidth;
+        break;
+
+    case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
+        *pu32 = pThis->svga.iHeight;
+        break;
+
+    case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
+        *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)
+        {
+            *pu32 = pThis->svga.au32ScratchRegion[pThis->svga.u32IndexReg - SVGA_SCRATCH_BASE];
+        }
+        break;
+    }
+    Log(("vmsvgaReadPort index=%s (%d) val=%x rc=%x\n", vmsvgaIndexToString(pThis), pThis->svga.u32IndexReg, *pu32, rc));
+    return rc;
+}
+
+#ifdef IN_RING3
+/**
+ * Apply the current resolution settings to change the video mode.
+ *
+ * @returns VBox status code.
+ * @param   pThis       VMSVGA State
+ */
+int vmsvgaChangeMode(PVGASTATE pThis)
+{
+    int rc;
+
+    if (    pThis->svga.iWidth == -1
+        ||  pThis->svga.iHeight == -1
+        ||  pThis->svga.iBpp == (unsigned)-1)
+    {
+        /* Mode change in progress; wait for all values to be set. */
+        Log(("vmsvgaChangeMode: BOGUS sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.iWidth, pThis->svga.iHeight, pThis->svga.iBpp));
+        return VINF_SUCCESS;
+    }
+
+    if (    pThis->last_bpp         == (unsigned)pThis->svga.iBpp
+        &&  pThis->last_scr_width   == (unsigned)pThis->svga.iWidth
+        &&  pThis->last_scr_height  == (unsigned)pThis->svga.iHeight
+        &&  pThis->last_width       == (unsigned)pThis->svga.iWidth
+        &&  pThis->last_height      == (unsigned)pThis->svga.iHeight
+        )
+    {
+        /* Nothing to do. */
+        Log(("vmsvgaChangeMode: nothing changed; ignore\n"));
+        return VINF_SUCCESS;
+    }
+
+    Log(("vmsvgaChangeMode: sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.iWidth, pThis->svga.iHeight, pThis->svga.iBpp));
+    pThis->svga.cbScanline = ((pThis->svga.iWidth * pThis->svga.iBpp + 7) & ~7) / 8;
+
+    pThis->pDrv->pfnLFBModeChange(pThis->pDrv, true);
+    rc = pThis->pDrv->pfnResize(pThis->pDrv, pThis->svga.iBpp, pThis->CTX_SUFF(vram_ptr), pThis->svga.cbScanline, pThis->svga.iWidth, pThis->svga.iHeight);
+    AssertRC(rc);
+    AssertReturn(rc == VINF_SUCCESS || rc == VINF_VGA_RESIZE_IN_PROGRESS, rc);
+
+    /* last stuff */
+    pThis->last_bpp         = pThis->svga.iBpp;
+    pThis->last_scr_width   = pThis->svga.iWidth;
+    pThis->last_scr_height  = pThis->svga.iHeight;
+    pThis->last_width       = pThis->svga.iWidth;
+    pThis->last_height      = pThis->svga.iHeight;
+    
+    ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
+
+    return VINF_SUCCESS;
+}
+#endif /* IN_RING3 */
+
+/**
+ * Write port register
+ *
+ * @returns VBox status code.
+ * @param   pThis       VMSVGA State
+ * @param   u32         Value to write
+ */
+PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
+{
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    int          rc = VINF_SUCCESS;
+
+    Log(("vmsvgaWritePort index=%s (%d) val=%x\n", vmsvgaIndexToString(pThis), pThis->svga.u32IndexReg, u32));
+    switch (pThis->svga.u32IndexReg)
+    {
+    case SVGA_REG_ID:
+        if (    u32 == SVGA_ID_0 
+            ||  u32 == SVGA_ID_1
+            ||  u32 == SVGA_ID_2)
+            pThis->svga.u32SVGAId = u32;
+        break;
+
+    case SVGA_REG_ENABLE:
+        if (    pThis->svga.fEnabled    == u32
+            &&  pThis->last_bpp         == (unsigned)pThis->svga.iBpp
+            &&  pThis->last_scr_width   == (unsigned)pThis->svga.iWidth
+            &&  pThis->last_scr_height  == (unsigned)pThis->svga.iHeight
+            &&  pThis->last_width       == (unsigned)pThis->svga.iWidth
+            &&  pThis->last_height      == (unsigned)pThis->svga.iHeight
+            )
+            /* Nothing to do. */
+            break;
+
+#ifdef IN_RING3
+        if (    u32 == 1 
+            &&  pThis->svga.fEnabled == false)
+        {
+            /* Make a backup copy of the first 32k in order to save font data etc. */
+            memcpy(pThis->svga.pFrameBufferBackup, pThis->vram_ptrR3, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+        }
+
+        pThis->svga.fEnabled = u32;
+        if (pThis->svga.fEnabled)
+        {
+            if (    pThis->svga.iWidth == -1
+                &&  pThis->svga.iHeight == -1
+                &&  pThis->svga.iBpp == (unsigned)-1)
+            {
+                /* Keep the current mode. */
+                pThis->svga.iWidth  = pThis->pDrv->cx;
+                pThis->svga.iHeight = pThis->pDrv->cy;
+                pThis->svga.iBpp    = (pThis->pDrv->cBits + 7) & ~7;
+            }
+
+            if (    pThis->svga.iWidth != -1
+                &&  pThis->svga.iHeight != -1
+                &&  pThis->svga.iBpp != (unsigned)-1)
+            {
+                rc = vmsvgaChangeMode(pThis);
+                AssertRCReturn(rc, rc);
+            }
+            Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
+            uint32_t *pFIFO = pThis->svga.pFIFOR3;
+            Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
+
+            /* Disable or enable dirty page tracking according to the current fTraces value. */
+            vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
+        }
+        else
+        {
+            /* Restore the text mode backup. */
+            memcpy(pThis->vram_ptrR3, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+
+/*            pThis->svga.iHeight    = -1;
+            pThis->svga.iWidth     = -1;
+            pThis->svga.iBpp       = -1;
+            pThis->svga.cbScanline = 0; */
+            pThis->pDrv->pfnLFBModeChange(pThis->pDrv, false);
+
+            /* Enable dirty page tracking again when going into legacy mode. */
+            vmsvgaSetTraces(pThis, true);
+        }
+#else
+        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
+        break;
+
+    case SVGA_REG_WIDTH:
+        if (pThis->svga.iWidth == (int) u32)
+            break; /* nop */
+
+        pThis->svga.iWidth = (int) u32;
+        if (pThis->svga.fEnabled)
+        {
+#ifdef IN_RING3
+            rc = vmsvgaChangeMode(pThis);
+            AssertRCReturn(rc, rc);
+#else
+            rc = VINF_IOM_R3_IOPORT_WRITE;
+            break;
+#endif
+        }
+        break;
+
+    case SVGA_REG_HEIGHT:
+        if (pThis->svga.iHeight == (int) u32)
+            break; /* nop */
+
+        pThis->svga.iHeight = (int) u32;
+        if (pThis->svga.fEnabled)
+        {
+#ifdef IN_RING3
+            rc = vmsvgaChangeMode(pThis);
+            AssertRCReturn(rc, rc);
+#else
+            rc = VINF_IOM_R3_IOPORT_WRITE;
+            break;
+#endif
+        }
+        break;
+
+    case SVGA_REG_DEPTH:
+        /* @todo read-only?? */
+        break;
+
+    case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
+        if (pThis->svga.iBpp == u32)
+            break; /* nop */
+
+        pThis->svga.iBpp = u32;
+        if (pThis->svga.fEnabled)
+        {
+#ifdef IN_RING3
+            rc = vmsvgaChangeMode(pThis);
+            AssertRCReturn(rc, rc);
+#else
+            rc = VINF_IOM_R3_IOPORT_WRITE;
+            break;
+#endif
+        }
+        break;
+
+    case SVGA_REG_PSEUDOCOLOR:
+        break;
+
+    case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
+#ifdef IN_RING3
+        pThis->svga.fConfigured = u32;
+        /* Disabling the FIFO enables tracing (dirty page detection) by default. */
+        if (!pThis->svga.fConfigured)
+        {
+            pThis->svga.fTraces = true;
+        }
+        vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
+#else
+        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
+        break;
+
+    case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
+        if (    pThis->svga.fEnabled
+            &&  pThis->svga.fConfigured)
+        {
+#ifdef IN_RING3        
+            Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
+            pThis->svga.fBusy = true;  
+            pThis->svga.pFIFOR3[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
+
+            /* Kick the FIFO thread to start processing commands again. */
+            RTSemEventSignal(pThis->svga.FIFORequestSem);
+#else
+            rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
+        }
+        /* else nothing to do. */
+        else
+            Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
+
+        break;
+
+    case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" (read-only) */
+        break;
+
+    case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
+        pThis->svga.u32GuestId = u32;
+        break;
+
+    case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
+        pThis->svga.u32PitchLock = u32;
+        break;
+
+    case SVGA_REG_IRQMASK:             /* Interrupt mask */
+        pThis->svga.u32IrqMask = u32;
+
+        /* Irq pending after the above change? */
+        if (pThis->svga.u32IrqMask & pThis->svga.u32IrqStatus)
+        {
+            Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
+            PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 1);
+        }
+        else
+            PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 0);
+        break;
+
+    /* Mouse cursor support */
+    case SVGA_REG_CURSOR_ID:
+    case SVGA_REG_CURSOR_X:
+    case SVGA_REG_CURSOR_Y:
+    case SVGA_REG_CURSOR_ON:
+        break;
+
+    /* Legacy multi-monitor support */
+    case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
+        break;
+    case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
+        break;
+    case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
+        break;
+    case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
+        break;
+    case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
+        break;
+    case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
+        break;
+    case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
+        break;
+#ifdef VBOX_WITH_VMSVGA3D
+    /* See "Guest memory regions" below. */
+    case SVGA_REG_GMR_ID:
+        pThis->svga.u32CurrentGMRId = u32;
+        break;
+
+    case SVGA_REG_GMR_DESCRIPTOR:
+#ifndef IN_RING3
+        rc = VINF_IOM_R3_IOPORT_WRITE;
+        break;
+#else
+    {
+        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;
+
+        /* Validate current GMR id. */
+        AssertBreak(idGMR < VMSVGA_MAX_GMR_IDS);
+
+        /* Free the old GMR if present. */
+        vmsvgaGMRFree(pThis, idGMR);
+
+        /* Just undefine the GMR? */
+        if (GCPhys == 0)
+            break;
+
+        pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
+        AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
+
+        /* Never cross a page boundary automatically. */
+        while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
+        {
+            /* Read descriptor. */
+            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)
+            {
+                /* Pointer to the next physical page of descriptors. */
+                GCPhys = GCPhysBase = desc.ppn << PAGE_SHIFT;
+            }
+            else
+            {
+                if (iDescriptor == cDescriptorsAllocated)
+                {
+                    cDescriptorsAllocated += 16;
+                    pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemRealloc(pSVGAState->aGMR[idGMR].paDesc, cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
+                    AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
+                }
+
+                pSVGAState->aGMR[idGMR].paDesc[iDescriptor].GCPhys     = desc.ppn << PAGE_SHIFT;
+                pSVGAState->aGMR[idGMR].paDesc[iDescriptor++].numPages = desc.numPages;
+                pSVGAState->aGMR[idGMR].cbTotal += desc.numPages * PAGE_SIZE;
+
+                /* Continue with the next descriptor. */
+                GCPhys += sizeof(desc);
+            }
+        }
+        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)
+        {
+            AssertFailed();
+            RTMemFree(pSVGAState->aGMR[idGMR].paDesc);
+            pSVGAState->aGMR[idGMR].paDesc = NULL;
+        }
+        AssertRC(rc);
+        break;
+    }
+#endif
+#endif // VBOX_WITH_VMSVGA3D
+
+    case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
+        if (pThis->svga.fTraces == u32)
+            break; /* nothing to do */
+
+#ifdef IN_RING3        
+        vmsvgaSetTraces(pThis, !!u32);
+#else
+        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
+        break;
+
+    case SVGA_REG_TOP:               /* Must be 1 more than the last register */
+        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));
+        break;
+
+    case SVGA_REG_FB_START:
+    case SVGA_REG_MEM_START:
+    case SVGA_REG_HOST_BITS_PER_PIXEL:
+    case SVGA_REG_MAX_WIDTH:
+    case SVGA_REG_MAX_HEIGHT:
+    case SVGA_REG_VRAM_SIZE:
+    case SVGA_REG_FB_SIZE:
+    case SVGA_REG_CAPABILITIES:
+    case SVGA_REG_MEM_SIZE:
+    case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
+    case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
+    case SVGA_REG_BYTES_PER_LINE:
+    case SVGA_REG_FB_OFFSET:
+    case SVGA_REG_RED_MASK:
+    case SVGA_REG_GREEN_MASK:
+    case SVGA_REG_BLUE_MASK:
+    case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
+    case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
+    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));
+        break;
+
+    default:
+        if (    pThis->svga.u32IndexReg >= SVGA_SCRATCH_BASE
+            &&  pThis->svga.u32IndexReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion)
+        {
+            pThis->svga.au32ScratchRegion[pThis->svga.u32IndexReg - SVGA_SCRATCH_BASE] = u32;
+        }
+        break;
+    }
+    return rc;
+}
+
+/**
+ * Port I/O Handler for IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param   pDevIns     The device instance.
+ * @param   pvUser      User argument.
+ * @param   uPort       Port number used for the IN operation.
+ * @param   pu32        Where to store the result.  This is always a 32-bit
+ *                      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)
+{
+    PVGASTATE   pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    int rc = VINF_SUCCESS;
+
+    /* Ignore non-dword accesses. */
+    if (cb != 4)
+    {
+        Log(("Ignoring non-dword read at %x cb=%d\n", Port, cb));
+        *pu32 = ~0;
+        return VINF_SUCCESS;
+    }
+
+    switch (Port - pThis->svga.BasePort)
+    {
+    case SVGA_INDEX_PORT:
+        *pu32 = pThis->svga.u32IndexReg;
+        break;
+
+    case SVGA_VALUE_PORT:
+        return vmsvgaReadPort(pThis, pu32);
+
+    case SVGA_BIOS_PORT:
+        Log(("Ignoring BIOS port read\n"));
+        *pu32 = 0;
+        break;
+
+    case SVGA_IRQSTATUS_PORT:
+        Log(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
+        *pu32 = pThis->svga.u32IrqStatus;
+        break;
+    }
+    return rc;
+}
+
+/**
+ * Port I/O Handler for OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param   pDevIns     The device instance.
+ * @param   pvUser      User argument.
+ * @param   uPort       Port number used for the OUT operation.
+ * @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)
+{
+    PVGASTATE   pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    int rc = VINF_SUCCESS;
+
+    /* Ignore non-dword accesses. */
+    if (cb != 4)
+    {
+        Log(("Ignoring non-dword write at %x val=%x cb=%d\n", Port, u32, cb));
+        return VINF_SUCCESS;
+    }
+
+    switch (Port - pThis->svga.BasePort)
+    {
+    case SVGA_INDEX_PORT:
+        pThis->svga.u32IndexReg = u32;
+        break;
+
+    case SVGA_VALUE_PORT:
+        return vmsvgaWritePort(pThis, u32);
+
+    case SVGA_BIOS_PORT:
+        Log(("Ignoring BIOS port write (val=%x)\n", u32));
+        break;
+
+    case SVGA_IRQSTATUS_PORT:
+        Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
+        ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
+        /* Clear the irq in case all events have been cleared. */
+        if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
+            PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
+        break;
+    }
+    return rc;
+}
+
+#ifdef DEBUG_FIFO_ACCESS
+
+# ifdef IN_RING3
+/**
+ * Handle LFB access.
+ * @returns VBox status code.
+ * @param   pVM             VM handle.
+ * @param   pThis           VGA device instance data.
+ * @param   GCPhys          The access physical address.
+ * @param   fWriteAccess    Read or write access
+ */
+static int vmsvgaFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
+{   
+    RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
+    uint32_t *pFIFO = pThis->svga.pFIFOR3;
+
+    switch (GCPhysOffset >> 2)
+    {
+    case SVGA_FIFO_MIN:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_MAX:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_NEXT_CMD:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_STOP:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CAPABILITIES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_FLAGS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_FENCE:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_HWVERSION:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_PITCHLOCK:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CURSOR_ON:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CURSOR_X:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CURSOR_Y:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CURSOR_COUNT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CURSOR_LAST_UPDATED:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_RESERVED:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_CURSOR_SCREEN_ID:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_DEAD:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_HWVERSION_REVISED:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_ALPHATOCOVERAGE:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_ALPHATOCOVERAGE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SUPERSAMPLE:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SUPERSAMPLE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_AYUV:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_AYUV = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_3D_CAPS_LAST:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_GUEST_3D_HWVERSION:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_FENCE_GOAL:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    case SVGA_FIFO_BUSY:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
+        break;
+    default:
+        Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
+        break;
+    }
+
+    return VINF_EM_RAW_EMULATE_INSTR;
+}
+
+/**
+ * HC access handler for the FIFO.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param   pVM             VM Handle.
+ * @param   GCPhys          The physical address the guest is writing to.
+ * @param   pvPhys          The HC mapping of that address.
+ * @param   pvBuf           What the guest is reading/writing.
+ * @param   cbBuf           How much it's reading/writing.
+ * @param   enmAccessType   The access type.
+ * @param   pvUser          User argument.
+ */
+static DECLCALLBACK(int) vmsvgaR3FIFOAccessHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
+{
+    PVGASTATE   pThis = (PVGASTATE)pvUser;
+    int         rc;
+    Assert(pThis);
+    Assert(GCPhys >= pThis->GCPhysVRAM);
+    NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf);
+
+    rc = vmsvgaFIFOAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
+    if (RT_SUCCESS(rc))
+        return VINF_PGM_HANDLER_DO_DEFAULT;
+    AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
+    return rc;
+}
+# endif /* IN_RING3 */
+#endif /* DEBUG */
+
+#ifdef DEBUG_GMR_ACCESS
+/**
+ * HC access handler for the FIFO.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param   pVM             VM Handle.
+ * @param   GCPhys          The physical address the guest is writing to.
+ * @param   pvPhys          The HC mapping of that address.
+ * @param   pvBuf           What the guest is reading/writing.
+ * @param   cbBuf           How much it's reading/writing.
+ * @param   enmAccessType   The access type.
+ * @param   pvUser          User argument.
+ */
+static DECLCALLBACK(int) vmsvgaR3GMRAccessHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
+{
+    PVGASTATE   pThis = (PVGASTATE)pvUser;
+    Assert(pThis);
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf);
+
+    Log(("vmsvgaR3GMRAccessHandler: GMR access to page %RGp\n", GCPhys));
+
+    for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
+    {
+        PGMR pGMR = &pSVGAState->aGMR[i];
+
+        if (pGMR->numDescriptors)
+        {
+            for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
+            {
+                if (    GCPhys >= pGMR->paDesc[j].GCPhys 
+                    &&  GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * PAGE_SIZE)
+                {
+                    /*
+                     * Turn off the write handler for this particular page and make it R/W.
+                     * Then return telling the caller to restart the guest instruction.
+                     */
+                    int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
+                    goto end;
+                }
+            }
+        }
+    }
+end:
+    return VINF_PGM_HANDLER_DO_DEFAULT;
+}
+
+#ifdef IN_RING3
+/* Callback handler for VMR3ReqCallWait */
+static DECLCALLBACK(int) vmsvgaRegisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
+{
+    PVGASTATE    pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    PGMR pGMR = &pSVGAState->aGMR[gmrId];
+    int rc;
+
+    for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
+    {
+        rc = PGMR3HandlerPhysicalRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
+                                            PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
+                                            pGMR->paDesc[i].GCPhys, pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * PAGE_SIZE - 1,
+                                            vmsvgaR3GMRAccessHandler, pThis,
+                                            NULL, NULL, NULL,
+                                            NULL, NULL, NULL,
+                                            "VMSVGA GMR");
+        AssertRC(rc);
+    }
+    return VINF_SUCCESS;
+}
+
+/* Callback handler for VMR3ReqCallWait */
+static DECLCALLBACK(int) vmsvgaUnregisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
+{
+    PVGASTATE    pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    PGMR pGMR = &pSVGAState->aGMR[gmrId];
+
+    for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
+    {
+        int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pThis->pDevInsR3), pGMR->paDesc[i].GCPhys);
+        AssertRC(rc);
+    }
+    return VINF_SUCCESS;
+}
+
+/* Callback handler for VMR3ReqCallWait */
+static DECLCALLBACK(int) vmsvgaResetGMRHandlers(PVGASTATE pThis)
+{
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+
+    for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
+    {
+        PGMR pGMR = &pSVGAState->aGMR[i];
+
+        if (pGMR->numDescriptors)
+        {
+            for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
+            {
+                int rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pThis->pDevInsR3), pGMR->paDesc[j].GCPhys);
+                AssertRC(rc);
+            }
+        }
+    }
+    return VINF_SUCCESS;   
+}
+#endif /* IN_RING3 */
+
+
+#endif /* DEBUG_GMR_ACCESS */
+
+/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
+
+#ifdef IN_RING3
+
+#include <iprt/mem.h>
+
+static void *vmsvgaFIFOGetCmdBuffer(PPDMTHREAD pThread, uint32_t *pFIFO, uint32_t cbCmd, uint32_t *pSize, void **ppfBounceBuffer)
+{
+    uint32_t cbLeft;
+    uint32_t cbFIFOCmd = pFIFO[SVGA_FIFO_MAX] - pFIFO[SVGA_FIFO_MIN];
+    uint32_t u32Current = pFIFO[SVGA_FIFO_STOP] + sizeof(uint32_t);     /* skip command dword */
+    uint8_t *pCmdBuffer;
+
+    Assert(ppfBounceBuffer);
+
+    *pSize          += cbCmd;
+    *ppfBounceBuffer = NULL;
+
+    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+    {
+        Assert(pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP]);
+
+        if (pFIFO[SVGA_FIFO_NEXT_CMD] >= u32Current)
+            cbLeft = pFIFO[SVGA_FIFO_NEXT_CMD] - u32Current;
+        else
+            cbLeft = cbFIFOCmd - (u32Current - pFIFO[SVGA_FIFO_NEXT_CMD]);
+
+        if (cbCmd <= cbLeft)
+            break;
+
+        /* Guest still busy copying into the FIFO; wait a bit. */
+        Log(("Guest still copying (%x vs %x) current %x next %x stop %x; sleep a bit\n", cbCmd, cbLeft, u32Current, pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
+        RTThreadSleep(2);
+    }
+
+    if (u32Current + cbCmd <= pFIFO[SVGA_FIFO_MAX])
+    {
+        pCmdBuffer = (uint8_t *)pFIFO + u32Current;
+    }
+    else
+    {
+        /* command data split; allocate memory and copy. */
+        uint8_t *pFIFOMin = (uint8_t *)pFIFO + pFIFO[SVGA_FIFO_MIN];
+        uint32_t cbPart1 = pFIFO[SVGA_FIFO_MAX] - u32Current;
+        uint32_t cbPart2 = cbCmd - cbPart1;
+
+        LogFlow(("Split data buffer at %x (%d-%d)\n", u32Current, cbPart1, cbPart2));
+        pCmdBuffer = (uint8_t *)RTMemAlloc(cbCmd);
+        AssertReturn(pCmdBuffer, NULL);
+        *ppfBounceBuffer = (void *)pCmdBuffer;
+
+        memcpy(pCmdBuffer,           (uint8_t *)pFIFO + u32Current, cbPart1);
+        memcpy(pCmdBuffer + cbPart1,  pFIFOMin,                     cbPart2);
+    }
+
+    return pCmdBuffer;
+}
+
+
+/* The async FIFO handling thread. */
+static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+    PVGASTATE    pThis = (PVGASTATE)pThread->pvUser;
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    int          rc;
+
+    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
+        return VINF_SUCCESS;
+
+    LogFlow(("vmsvgaFIFOLoop: started loop\n"));
+    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+    {
+        uint32_t *pFIFO = pThis->svga.pFIFOR3;
+
+        /* Wait for at most 250 ms to start polling. */
+        rc = RTSemEventWait(pThis->svga.FIFORequestSem, 250);
+        AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
+        if (pThread->enmState != PDMTHREADSTATE_RUNNING)
+        {
+            LogFlow(("vmsvgaFIFOLoop: thread state %x\n", pThread->enmState));
+            return VINF_SUCCESS;
+        }
+        if (rc == VERR_TIMEOUT)
+        {
+            if (pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
+                continue;
+
+            Log(("vmsvgaFIFOLoop: timeout\n"));
+        }
+        Log(("vmsvgaFIFOLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
+        Log(("vmsvgaFIFOLoop: min  %x max  %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
+        Log(("vmsvgaFIFOLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
+
+        if (    !pThis->svga.fEnabled
+            ||  !pThis->svga.fConfigured)
+        {
+            pThis->svga.fBusy = false;
+            pThis->svga.pFIFOR3[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
+            continue;   /* device not enabled. */
+        }
+
+        if (pFIFO[SVGA_FIFO_STOP] >= pFIFO[SVGA_FIFO_MAX])
+        {
+            Log(("vmsvgaFIFOLoop: Invalid stop %x max=%x\n", pFIFO[SVGA_FIFO_STOP], pFIFO[SVGA_FIFO_MAX]));
+            continue;   /* invalid. */
+        }
+
+        if (pFIFO[SVGA_FIFO_MAX] < VMSVGA_FIFO_SIZE)
+        {
+            Log(("vmsvgaFIFOLoop: Invalid max %x fifo max=%x\n", pFIFO[SVGA_FIFO_MAX], VMSVGA_FIFO_SIZE));
+            continue;   /* invalid. */
+        }
+
+        if (pFIFO[SVGA_FIFO_STOP] < pFIFO[SVGA_FIFO_MIN])
+        {
+            Log(("vmsvgaFIFOLoop: Invalid stop %x min=%x\n", pFIFO[SVGA_FIFO_STOP], pFIFO[SVGA_FIFO_MIN]));
+            continue;   /* invalid. */
+        }
+        pThis->svga.fBusy = true;
+        pThis->svga.pFIFOR3[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
+
+        /* Execute all queued FIFO commands. */
+        while (     pThread->enmState == PDMTHREADSTATE_RUNNING
+               &&   pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
+        {
+            uint32_t u32Cmd;
+            uint32_t u32Current, size;
+            uint32_t u32IrqStatus = 0;
+            bool     fTriggerIrq = false;
+            void    *pBounceBuffer = NULL;
+
+            /* First check any pending actions. */
+            if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
+#ifdef VBOX_WITH_VMSVGA3D
+                vmsvga3dChangeMode(pThis);
+#else
+                {}
+#endif
+            u32Current = pFIFO[SVGA_FIFO_STOP];
+
+            u32Cmd = u32Current / sizeof(uint32_t);
+            LogFlow(("vmsvgaFIFOLoop: FIFO command (iCmd=0x%x) %s 0x%x\n", u32Cmd, vmsvgaFIFOCmdToString(pFIFO[u32Cmd]), pFIFO[u32Cmd]));
+            size = sizeof(uint32_t);    /* command dword */
+
+            switch (pFIFO[u32Cmd])
+            {
+            case SVGA_CMD_INVALID_CMD:
+                /* Nothing to do. */
+                break;
+
+            case SVGA_CMD_FENCE:
+            {                
+                SVGAFifoCmdFence *pCmdFence = (SVGAFifoCmdFence *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdFence), &size, &pBounceBuffer);
+
+                Log(("vmsvgaFIFOLoop: SVGA_CMD_FENCE %x\n", pCmdFence->fence));
+                pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
+                if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
+                {
+                    Log(("vmsvgaFIFOLoop: any fence irq\n"));
+                    u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
+                }
+                else
+                if (    (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
+                    &&  pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
+                {
+                    Log(("vmsvgaFIFOLoop: fence goal reached irq (fence=%x)\n", pCmdFence->fence));
+                    u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
+                }
+                break;
+            }
+            case SVGA_CMD_UPDATE:
+            case SVGA_CMD_UPDATE_VERBOSE:
+            {
+                SVGAFifoCmdUpdate *pUpdate = (SVGAFifoCmdUpdate *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdUpdate), &size, &pBounceBuffer);
+
+                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;
+            }
+
+            case SVGA_CMD_DEFINE_CURSOR:
+            {
+                /* Followed by bitmap data. */
+                SVGAFifoCmdDefineCursor *pCursor = (SVGAFifoCmdDefineCursor *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdDefineCursor), &size, &pBounceBuffer);
+
+                AssertFailed();
+                break;
+            }
+
+            case SVGA_CMD_DEFINE_ALPHA_CURSOR:
+            {
+                /* Followed by bitmap data. */
+                SVGAFifoCmdDefineAlphaCursor *pCursor = (SVGAFifoCmdDefineAlphaCursor *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdDefineAlphaCursor), &size, &pBounceBuffer);
+                uint32_t cbCursorShape, cbAndMask;
+                uint8_t *pCursorCopy;
+                uint32_t cbCmd;
+
+                Log(("vmsvgaFIFOLoop: ALPHA_CURSOR id=%d size (%d,%d) hotspot (%d,%d)\n", pCursor->id, pCursor->width, pCursor->height, pCursor->hotspotX, pCursor->hotspotY));
+
+                /* Refetch the command buffer with the added bitmap data; undo size increase (ugly) */
+                cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCursor->width * pCursor->height * sizeof(uint32_t) /* 32-bit BRGA format */;
+                size  = sizeof(uint32_t);    /* command dword */
+                if (pBounceBuffer)
+                    RTMemFree(pBounceBuffer);
+                pCursor = (SVGAFifoCmdDefineAlphaCursor *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, cbCmd, &size, &pBounceBuffer);
+
+                /* The mouse pointer interface always expects an AND mask followed by the color data (XOR mask). */
+                cbAndMask     = (pCursor->width + 7) / 8 * pCursor->height;                         /* size of the AND mask */
+                cbAndMask     = ((cbAndMask + 3) & ~3);                                             /* + gap for alignment */
+                cbCursorShape = cbAndMask + pCursor->width * sizeof(uint32_t) * pCursor->height;    /* + size of the XOR mask (32-bit BRGA format) */
+
+                pCursorCopy = (uint8_t *)RTMemAlloc(cbCursorShape);
+                AssertBreak(pCursorCopy);
+
+                LogFlow(("Cursor data:\n%.*Rhxd\n", pCursor->width * pCursor->height * sizeof(uint32_t), pCursor+1));
+
+                /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */
+                memset(pCursorCopy, 0xff, cbAndMask);
+                /* Colour data */
+                memcpy(pCursorCopy + cbAndMask, (pCursor + 1), pCursor->width * pCursor->height * sizeof(uint32_t));
+
+                rc = pThis->pDrv->pfnVBVAMousePointerShape (pThis->pDrv,
+                                                            true,
+                                                            true,
+                                                            pCursor->hotspotX,
+                                                            pCursor->hotspotY,
+                                                            pCursor->width,
+                                                            pCursor->height,
+                                                            pCursorCopy);
+                AssertRC(rc);
+                RTMemFree(pCursorCopy);
+
+                break;
+            }
+
+            case SVGA_CMD_ESCAPE:
+            {
+                /* Followed by nsize bytes of data. */
+                SVGAFifoCmdEscape *pEscape = (SVGAFifoCmdEscape *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdEscape), &size, &pBounceBuffer);
+                uint32_t cbCmd;
+
+                /* Refetch the command buffer with the variable data; undo size increase (ugly) */
+                cbCmd = sizeof(SVGAFifoCmdEscape) + pEscape->size;
+                size  = sizeof(uint32_t);    /* command dword */
+                if (pBounceBuffer)
+                    RTMemFree(pBounceBuffer);
+                pEscape = (SVGAFifoCmdEscape *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, cbCmd, &size, &pBounceBuffer);
+
+                if (pEscape->nsid == SVGA_ESCAPE_NSID_VMWARE)
+                {
+                    Assert(pEscape->size >= sizeof(uint32_t));
+                    uint32_t cmd = *(uint32_t *)(pEscape + 1);
+                    Log(("vmsvgaFIFOLoop: ESCAPE (%x %x) VMWARE cmd=%x\n", pEscape->nsid, pEscape->size, cmd));
+
+                    switch (cmd)
+                    {
+                    case SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS:
+                    {
+                        SVGAEscapeVideoSetRegs *pVideoCmd = (SVGAEscapeVideoSetRegs *)(pEscape + 1);
+                        uint32_t cRegs = (pEscape->size - sizeof(pVideoCmd->header)) / sizeof(pVideoCmd->items[0]);
+
+                        Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: stream %x\n", pVideoCmd->header.streamId));
+                        for (uint32_t iReg = 0; iReg < cRegs; iReg++)
+                        {
+                            Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: reg %x val %x\n", pVideoCmd->items[iReg].registerId, pVideoCmd->items[iReg].value));
+                        }
+                        break;
+                    }
+
+                    case SVGA_ESCAPE_VMWARE_VIDEO_FLUSH:
+                        SVGAEscapeVideoFlush *pVideoCmd = (SVGAEscapeVideoFlush *)(pEscape + 1);
+                        Log(("SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: stream %x\n", pVideoCmd->streamId));
+                        break;
+                    }
+                }
+                else
+                    Log(("vmsvgaFIFOLoop: ESCAPE %x %x\n", pEscape->nsid, pEscape->size));
+
+                break;
+            }
+#ifdef VBOX_WITH_VMSVGA3D
+            case SVGA_CMD_DEFINE_GMR2:
+            {
+                SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdDefineGMR2), &size, &pBounceBuffer);
+                Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_GMR2 id=%x %x pages\n", pCmd->gmrId, pCmd->numPages));
+
+                /* Validate current GMR id. */
+                AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
+                AssertBreak(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES);
+
+                if (!pCmd->numPages)
+                    vmsvgaGMRFree(pThis, pCmd->gmrId);
+                /* else everything done in remap */
+
+                break;
+            }
+
+            case SVGA_CMD_REMAP_GMR2:
+            {
+                /* Followed by page descriptors. */
+                SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdRemapGMR2), &size, &pBounceBuffer);
+                uint32_t cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
+                uint32_t cbCmd;
+
+                Log(("vmsvgaFIFOLoop: SVGA_CMD_REMAP_GMR2 id=%x flags=%x offset=%x npages=%x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
+
+                /* @todo */
+                AssertBreak(pCmd->offsetPages == 0);
+
+                /* Refetch the command buffer with the variable data; undo size increase (ugly) */
+                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
+                    cbCmd += cbPageDesc * pCmd->numPages;
+                size = sizeof(uint32_t);    /* command dword */
+
+                if (pBounceBuffer)
+                    RTMemFree(pBounceBuffer);
+                pCmd = (SVGAFifoCmdRemapGMR2 *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, cbCmd, &size, &pBounceBuffer);
+                AssertReturn(pCmd, VERR_INTERNAL_ERROR);
+
+                PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
+
+                /* Validate current GMR id. */
+                AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
+                AssertBreak(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES);
+
+                /* Free the old GMR if present. */
+                vmsvgaGMRFree(pThis, pCmd->gmrId);
+
+                pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pCmd->numPages * sizeof(VMSVGAGMRDESCRIPTOR));
+                AssertBreak(pGMR->paDesc);
+
+                if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
+                {
+                    /* @todo */
+                    AssertFailed();
+                }
+                else
+                {
+                    uint32_t *pPage32 = (uint32_t *)(pCmd + 1);
+                    uint64_t *pPage64 = (uint64_t *)(pCmd + 1);
+                    uint32_t iDescriptor = 0;
+                    RTGCPHYS GCPhys;
+
+                    if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
+                        GCPhys = (pPage64[0] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL;    /* seeing rubbish in the top bits with certain linux guests*/
+                    else
+                        GCPhys = pPage32[0] << PAGE_SHIFT;
+
+                    pGMR->paDesc[0].GCPhys    = GCPhys;
+                    pGMR->paDesc[0].numPages  = 1;
+                    pGMR->cbTotal             = PAGE_SIZE;
+
+                    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*/
+                        else
+                            GCPhys = pPage32[i] << PAGE_SHIFT;
+
+                        /* Continuous physical memory? */
+                        if (GCPhys == pGMR->paDesc[iDescriptor].GCPhys + pGMR->paDesc[iDescriptor].numPages * PAGE_SIZE)
+                        {
+                            Assert(pGMR->paDesc[iDescriptor].numPages);
+                            pGMR->paDesc[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));
+                        }
+
+                        pGMR->cbTotal += PAGE_SIZE;
+                    }
+                    LogFlow(("Nr of descriptors %x\n", iDescriptor + 1));
+                    pGMR->numDescriptors = iDescriptor + 1;
+                }
+
+#ifdef DEBUG_GMR_ACCESS
+                VMR3ReqCallWait(PDMDevHlpGetVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaRegisterGMR, 2, pThis->pDevInsR3, pCmd->gmrId);
+#endif
+                break;
+            }
+#endif // VBOX_WITH_VMSVGA3D
+            case SVGA_CMD_DEFINE_SCREEN:
+            {
+                /* @note optional size depending on the capabilities */
+                Assert(!(pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT));
+                SVGAFifoCmdDefineScreen *pCmd = (SVGAFifoCmdDefineScreen *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdDefineScreen), &size, &pBounceBuffer);
+
+                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)
+                    Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_HAS_ROOT\n"));
+                if (pCmd->screen.flags & SVGA_SCREEN_IS_PRIMARY)
+                    Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_IS_PRIMARY\n"));
+                if (pCmd->screen.flags & SVGA_SCREEN_FULLSCREEN_HINT)
+                    Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_FULLSCREEN_HINT\n"));
+                if (pCmd->screen.flags & SVGA_SCREEN_DEACTIVATE )
+                    Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_DEACTIVATE \n"));
+                if (pCmd->screen.flags & SVGA_SCREEN_BLANKING)
+                    Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_BLANKING\n"));
+
+                pThis->svga.iWidth  = pCmd->screen.size.width;
+                pThis->svga.iHeight = pCmd->screen.size.height;
+                vmsvgaChangeMode(pThis);
+                break;
+            }
+
+            case SVGA_CMD_DESTROY_SCREEN:
+            {
+                SVGAFifoCmdDestroyScreen *pCmd = (SVGAFifoCmdDestroyScreen *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdDestroyScreen), &size, &pBounceBuffer);
+
+                Log(("vmsvgaFIFOLoop: SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
+                break;
+            }
+#ifdef VBOX_WITH_VMSVGA3D
+            case SVGA_CMD_DEFINE_GMRFB:
+            {
+                SVGAFifoCmdDefineGMRFB *pCmd = (SVGAFifoCmdDefineGMRFB *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdDefineGMRFB), &size, &pBounceBuffer);
+
+                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;
+                pSVGAState->GMRFB.bytesPerLine = pCmd->bytesPerLine;
+                pSVGAState->GMRFB.format       = pCmd->format;
+                break;
+            }
+
+            case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
+            {
+                SVGAFifoCmdBlitGMRFBToScreen *pCmd = (SVGAFifoCmdBlitGMRFBToScreen *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdBlitGMRFBToScreen), &size, &pBounceBuffer);
+                int32_t width, height;
+
+                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));
+
+                /* @todo */
+                AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pThis->svga.iBpp);
+                AssertBreak(pCmd->destScreenId == 0);
+
+                if (pCmd->destRect.left < 0)
+                    pCmd->destRect.left = 0;
+                if (pCmd->destRect.top < 0)
+                    pCmd->destRect.top = 0;
+                if (pCmd->destRect.right < 0)
+                    pCmd->destRect.right = 0;
+                if (pCmd->destRect.bottom < 0)
+                    pCmd->destRect.bottom = 0;
+
+                width  = pCmd->destRect.right - pCmd->destRect.left;
+                height = pCmd->destRect.bottom - pCmd->destRect.top;
+
+                if (    width == 0
+                    ||  height == 0)
+                    break;  /* Nothing to do. */
+
+                /* Clip to screen dimensions. */
+                if (width > pThis->svga.iWidth)
+                    width = pThis->svga.iWidth;
+                if (height > pThis->svga.iHeight)
+                    height = pThis->svga.iHeight;
+
+                unsigned offsetSource = (pCmd->srcOrigin.x * pSVGAState->GMRFB.format.s.bitsPerPixel) / 8 + pSVGAState->GMRFB.bytesPerLine * pCmd->srcOrigin.y;
+                unsigned offsetDest   = (pCmd->destRect.left * RT_ALIGN(pThis->svga.iBpp, 8)) / 8 + pThis->svga.cbScanline * pCmd->destRect.top;
+                unsigned cbCopyWidth  = (width * RT_ALIGN(pThis->svga.iBpp, 8)) / 8;
+
+                rc = vmsvgaGMRTransfer(pThis, SVGA3D_WRITE_HOST_VRAM, pThis->CTX_SUFF(vram_ptr) + offsetDest, pThis->svga.cbScanline, pSVGAState->GMRFB.ptr, offsetSource, pSVGAState->GMRFB.bytesPerLine, cbCopyWidth, height);
+                AssertRC(rc);
+
+                vgaR3UpdateDisplay(pThis, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right - pCmd->destRect.left, pCmd->destRect.bottom - pCmd->destRect.top);
+                break;
+            }
+
+            case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
+            {
+                SVGAFifoCmdBlitScreenToGMRFB *pCmd = (SVGAFifoCmdBlitScreenToGMRFB *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdBlitScreenToGMRFB), &size, &pBounceBuffer);
+
+                /* @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));
+                AssertFailed();
+                break;
+            }
+#endif // VBOX_WITH_VMSVGA3D
+            case SVGA_CMD_ANNOTATION_FILL:
+            {
+                SVGAFifoCmdAnnotationFill *pCmd = (SVGAFifoCmdAnnotationFill *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdAnnotationFill), &size, &pBounceBuffer);
+
+                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; 
+                break;
+            }
+
+            case SVGA_CMD_ANNOTATION_COPY:
+            {
+                SVGAFifoCmdAnnotationCopy *pCmd = (SVGAFifoCmdAnnotationCopy*)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGAFifoCmdAnnotationCopy), &size, &pBounceBuffer);
+
+                Log(("vmsvgaFIFOLoop: SVGA_CMD_ANNOTATION_COPY\n"));
+                AssertFailed();
+                break;
+            }
+
+            default:
+#ifdef VBOX_WITH_VMSVGA3D
+                if (    pFIFO[u32Cmd] >= SVGA_3D_CMD_BASE
+                    &&  pFIFO[u32Cmd] < SVGA_3D_CMD_MAX)
+                {
+                    /* All 3d commands start with a common header, which defines the size of the command. */
+                    SVGA3dCmdHeader *pHdr = (SVGA3dCmdHeader *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, sizeof(SVGA3dCmdHeader), &size, &pBounceBuffer);
+                    uint32_t cbCmd;
+
+                    /* Refetch the command buffer with the variable data; undo size increase (ugly) */
+                    cbCmd = sizeof(SVGA3dCmdHeader) + pHdr->size;
+                    size  = sizeof(uint32_t);    /* command dword */
+                    if (pBounceBuffer)
+                        RTMemFree(pBounceBuffer);
+                    pHdr = (SVGA3dCmdHeader *)vmsvgaFIFOGetCmdBuffer(pThread, pFIFO, cbCmd, &size, &pBounceBuffer);
+
+                    switch (pFIFO[u32Cmd])
+                    {
+                    case SVGA_3D_CMD_SURFACE_DEFINE:
+                    {
+                        SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)(pHdr + 1);
+                        uint32_t                cMipLevels;
+
+                        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);
+#endif
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SURFACE_DEFINE_V2:
+                    {
+                        SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)(pHdr + 1);
+                        uint32_t                   cMipLevels;
+
+                        cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
+                        rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, pCmd->surfaceFlags, pCmd->format, pCmd->face, pCmd->multisampleCount, pCmd->autogenFilter, cMipLevels, (SVGA3dSize *)(pCmd + 1));
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SURFACE_DESTROY:
+                    {
+                        SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)(pHdr + 1);
+                        rc = vmsvga3dSurfaceDestroy(pThis, pCmd->sid);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SURFACE_COPY:
+                    {
+                        SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)(pHdr + 1);
+                        uint32_t              cCopyBoxes;
+
+                        cCopyBoxes = (pHdr->size - sizeof(pCmd)) / sizeof(SVGA3dCopyBox);
+                        rc = vmsvga3dSurfaceCopy(pThis, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SURFACE_STRETCHBLT:
+                    {
+                        SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)(pHdr + 1);
+
+                        rc = vmsvga3dSurfaceStretchBlt(pThis, pCmd->dest, pCmd->boxDest, pCmd->src, pCmd->boxSrc, pCmd->mode);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SURFACE_DMA:
+                    {
+                        SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)(pHdr + 1);
+                        uint32_t             cCopyBoxes;
+
+                        cCopyBoxes = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox);
+                        STAM_PROFILE_START(&pSVGAState->StatR3CmdSurfaceDMA, a);
+                        rc = vmsvga3dSurfaceDMA(pThis, pCmd->guest, pCmd->host, pCmd->transfer, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
+                        STAM_PROFILE_STOP(&pSVGAState->StatR3CmdSurfaceDMA, a);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
+                    {
+                        SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)(pHdr + 1);
+                        uint32_t                      cRects;
+
+                        cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGASignedRect);
+                        rc = vmsvga3dSurfaceBlitToScreen(pThis, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage, pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1));
+                        break;                
+                    }
+
+                    case SVGA_3D_CMD_CONTEXT_DEFINE:
+                    {
+                        SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)(pHdr + 1);
+
+                        rc = vmsvga3dContextDefine(pThis, pCmd->cid);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_CONTEXT_DESTROY:
+                    {
+                        SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)(pHdr + 1);
+
+                        rc = vmsvga3dContextDestroy(pThis, pCmd->cid);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETTRANSFORM:
+                    {
+                        SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)(pHdr + 1);
+
+                        rc = vmsvga3dSetTransform(pThis, pCmd->cid, pCmd->type, pCmd->matrix);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETZRANGE:
+                    {
+                        SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)(pHdr + 1);
+
+                        rc = vmsvga3dSetZRange(pThis, pCmd->cid, pCmd->zRange);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETRENDERSTATE:
+                    {
+                        SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)(pHdr + 1);
+                        uint32_t                 cRenderStates;
+
+                        cRenderStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRenderState);
+                        rc = vmsvga3dSetRenderState(pThis, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1));
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETRENDERTARGET:
+                    {
+                        SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)(pHdr + 1);
+
+                        rc = vmsvga3dSetRenderTarget(pThis, pCmd->cid, pCmd->type, pCmd->target);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETTEXTURESTATE:
+                    {
+                        SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)(pHdr + 1);
+                        uint32_t                  cTextureStates;
+
+                        cTextureStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dTextureState);
+                        rc = vmsvga3dSetTextureState(pThis, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1));
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETMATERIAL:
+                    {
+                        SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)(pHdr + 1);
+
+                        rc = vmsvga3dSetMaterial(pThis, pCmd->cid, pCmd->face, &pCmd->material);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETLIGHTDATA:
+                    {
+                        SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)(pHdr + 1);
+
+                        rc = vmsvga3dSetLightData(pThis, pCmd->cid, pCmd->index, &pCmd->data);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETLIGHTENABLED:
+                    {
+                        SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)(pHdr + 1);
+
+                        rc = vmsvga3dSetLightEnabled(pThis, pCmd->cid, pCmd->index, pCmd->enabled);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETVIEWPORT:
+                    {
+                        SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)(pHdr + 1);
+
+                        rc = vmsvga3dSetViewPort(pThis, pCmd->cid, &pCmd->rect);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETCLIPPLANE:
+                    {
+                        SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)(pHdr + 1);
+
+                        rc = vmsvga3dSetClipPlane(pThis, pCmd->cid, pCmd->index, pCmd->plane);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_CLEAR:
+                    {
+                        SVGA3dCmdClear  *pCmd = (SVGA3dCmdClear *)(pHdr + 1);
+                        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;
+                    }
+
+                    case SVGA_3D_CMD_PRESENT:
+                    {
+                        SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)(pHdr + 1);
+                        uint32_t          cRects;
+
+                        cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
+
+                        STAM_PROFILE_START(&pSVGAState->StatR3CmdPresent, a);
+                        rc = vmsvga3dCommandPresent(pThis, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1));
+                        STAM_PROFILE_STOP(&pSVGAState->StatR3CmdPresent, a);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SHADER_DEFINE:
+                    {
+                        SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)(pHdr + 1);
+                        uint32_t               cbData;
+
+                        cbData = (pHdr->size - sizeof(*pCmd));
+                        rc = vmsvga3dShaderDefine(pThis, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1));
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SHADER_DESTROY:
+                    {
+                        SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)(pHdr + 1);
+
+                        rc = vmsvga3dShaderDestroy(pThis, pCmd->cid, pCmd->shid, pCmd->type);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SET_SHADER:
+                    {
+                        SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)(pHdr + 1);
+
+                        rc = vmsvga3dShaderSet(pThis, pCmd->cid, pCmd->type, pCmd->shid);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SET_SHADER_CONST:
+                    {
+                        SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)(pHdr + 1);
+
+                        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);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_DRAW_PRIMITIVES:
+                    {
+                        SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)(pHdr + 1);
+                        uint32_t                 cVertexDivisor;
+
+                        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);
+
+                        SVGA3dVertexDecl     *pVertexDecl    = (SVGA3dVertexDecl *)(pCmd + 1);
+                        SVGA3dPrimitiveRange *pNumRange      = (SVGA3dPrimitiveRange *) (&pVertexDecl[pCmd->numVertexDecls]);
+                        SVGA3dVertexDivisor  *pVertexDivisor = (cVertexDivisor) ? (SVGA3dVertexDivisor *)(&pNumRange[pCmd->numRanges]) : NULL;
+
+                        STAM_PROFILE_START(&pSVGAState->StatR3CmdDrawPrimitive, a);
+                        rc = vmsvga3dDrawPrimitives(pThis, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges, pNumRange, cVertexDivisor, pVertexDivisor);
+                        STAM_PROFILE_STOP(&pSVGAState->StatR3CmdDrawPrimitive, a);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_SETSCISSORRECT:
+                    {
+                        SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)(pHdr + 1);
+
+                        rc = vmsvga3dSetScissorRect(pThis, pCmd->cid, &pCmd->rect);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_BEGIN_QUERY:
+                    {
+                        SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)(pHdr + 1);
+
+                        rc = vmsvga3dQueryBegin(pThis, pCmd->cid, pCmd->type);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_END_QUERY:
+                    {
+                        SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)(pHdr + 1);
+
+                        rc = vmsvga3dQueryEnd(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_WAIT_FOR_QUERY:
+                    {
+                        SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)(pHdr + 1);
+
+                        rc = vmsvga3dQueryWait(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_GENERATE_MIPMAPS:
+                    {
+                        SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)(pHdr + 1);
+
+                        rc = vmsvga3dGenerateMipmaps(pThis, pCmd->sid, pCmd->filter);
+                        break;
+                    }
+
+                    case SVGA_3D_CMD_ACTIVATE_SURFACE:
+                    case SVGA_3D_CMD_DEACTIVATE_SURFACE:
+                        /* context id + surface id? */
+                        break;
+                    }
+                }
+                else
+#endif // VBOX_WITH_VMSVGA3D
+                    AssertFailed();
+            }
+            if (pBounceBuffer)
+                RTMemFree(pBounceBuffer);
+
+            /* Go to the next slot */
+            if (u32Current + size >= pFIFO[SVGA_FIFO_MAX])
+                ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], pFIFO[SVGA_FIFO_MIN] + u32Current + size - pFIFO[SVGA_FIFO_MAX]);
+            else
+                ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], u32Current + size);
+
+            /* FIFO progress might trigger an interrupt. */
+            if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
+            {
+                Log(("vmsvgaFIFOLoop: fifo progress irq\n"));
+                u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
+            }
+
+            /* Irq pending? */
+            if (pThis->svga.u32IrqMask & u32IrqStatus)
+            {
+                Log(("vmsvgaFIFOLoop: Trigger interrupt with status %x\n", u32IrqStatus));
+                ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
+                PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1);
+            }
+        }
+        /* Done? */
+        if (pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
+        {
+            Log(("vmsvgaFIFOLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
+            pThis->svga.fBusy = false;
+            pThis->svga.pFIFOR3[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * Free the specified GMR
+ *
+ * @param   pThis           VGA device instance data.
+ * @param   idGMR           GMR id
+ */
+void vmsvgaGMRFree(PVGASTATE pThis, uint32_t idGMR)
+{
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+
+    /* Free the old descriptor if present. */
+    if (pSVGAState->aGMR[idGMR].numDescriptors)
+    {
+#ifdef DEBUG_GMR_ACCESS
+        VMR3ReqCallWait(PDMDevHlpGetVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaUnregisterGMR, 2, pThis->pDevInsR3, idGMR);
+#endif
+
+        Assert(pSVGAState->aGMR[idGMR].paDesc);
+        RTMemFree(pSVGAState->aGMR[idGMR].paDesc);
+        pSVGAState->aGMR[idGMR].paDesc         = NULL;
+        pSVGAState->aGMR[idGMR].numDescriptors = 0;
+        pSVGAState->aGMR[idGMR].cbTotal        = 0;
+    }
+    Assert(!pSVGAState->aGMR[idGMR].cbTotal);
+}
+
+/**
+ * Copy from a GMR to host memory or vice versa
+ *
+ * @returns VBox status code.
+ * @param   pThis           VGA device instance data.
+ * @param   transfer        Transfer type (read/write)
+ * @param   pDest           Host destination pointer
+ * @param   cbDestPitch     Destination buffer pitch
+ * @param   src             GMR description
+ * @param   cbSrcOffset     Source buffer offset
+ * @param   cbSrcPitch      Source buffer pitch
+ * @param   cbWidth         Source width in bytes
+ * @param   cHeight         Source height
+ */
+int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType transfer, uint8_t *pDest, uint32_t cbDestPitch, SVGAGuestPtr src, uint32_t cbSrcOffset, uint32_t cbSrcPitch, uint32_t cbWidth, uint32_t cHeight)
+{
+    PVMSVGASTATE            pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    PGMR                    pGMR;
+    int                     rc;
+    PVMSVGAGMRDESCRIPTOR    pDesc;
+    unsigned                uDescOffset = 0;
+
+    Log(("vmsvgaGMRTransfer: gmr=%x offset=%x pitch=%d cbWidth=%d cHeight=%d; src offset=%d src pitch=%d\n", src.gmrId, src.offset, cbDestPitch, cbWidth, cHeight, cbSrcOffset, cbSrcPitch));
+    Assert(cbWidth && cHeight);
+
+    /* Shortcut for the framebuffer. */
+    if (src.gmrId == SVGA_GMR_FRAMEBUFFER)
+    {
+        cbSrcOffset += src.offset;
+        AssertReturn(cbSrcOffset + cbSrcPitch * (cHeight - 1) + cbWidth <= pThis->vram_size, VERR_INVALID_PARAMETER);
+
+        uint8_t *pSrc  = pThis->CTX_SUFF(vram_ptr) + cbSrcOffset;
+
+        if (transfer == SVGA3D_READ_HOST_VRAM)
+        {
+            /* switch src & dest */
+            uint8_t *pTemp       = pDest;
+            uint32_t cbTempPitch = cbDestPitch;
+
+            pDest = pSrc;
+            pSrc  = pTemp;
+
+            cbDestPitch = cbSrcPitch;
+            cbSrcPitch  = cbTempPitch;
+        }
+
+        if (    pThis->svga.cbScanline == cbDestPitch
+            &&  cbWidth == cbDestPitch)
+        {
+            memcpy(pDest, pSrc, cbWidth * cHeight);
+        }
+        else
+        {
+            for(uint32_t i = 0; i < cHeight; i++) 
+            {
+                memcpy(pDest, pSrc, cbWidth);
+
+                pDest += cbDestPitch;
+                pSrc  += cbSrcPitch;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    AssertReturn(src.gmrId < VMSVGA_MAX_GMR_IDS, VERR_INVALID_PARAMETER);
+    pGMR   = &pSVGAState->aGMR[src.gmrId];
+    pDesc  = pGMR->paDesc;
+
+    cbSrcOffset += src.offset;
+    AssertReturn(cbSrcOffset + cbSrcPitch * (cHeight - 1) + cbWidth <= pGMR->cbTotal, VERR_INVALID_PARAMETER);
+
+    for (unsigned i = 0; i < cHeight; i++)
+    {
+        unsigned cbCurrentWidth = cbWidth;
+        unsigned uCurrentOffset = cbSrcOffset;
+        uint8_t *pCurrentDest   = pDest;
+
+        /* Find the right descriptor */
+        while (uDescOffset + pDesc->numPages * PAGE_SIZE <= uCurrentOffset)
+        {
+            uDescOffset += pDesc->numPages * PAGE_SIZE;
+            AssertReturn(uDescOffset < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */
+            pDesc++;
+        }
+
+        while (cbCurrentWidth)
+        {
+            unsigned cbToCopy;
+            
+            if (uCurrentOffset + cbCurrentWidth <= uDescOffset + pDesc->numPages * PAGE_SIZE) 
+                cbToCopy = cbCurrentWidth;
+            else 
+                cbToCopy = (uDescOffset + pDesc->numPages * PAGE_SIZE - uCurrentOffset);
+
+            LogFlow(("vmsvgaGMRTransfer: %s phys=%RGp\n", (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", pDesc->GCPhys + uCurrentOffset - uDescOffset));
+
+            if (transfer == SVGA3D_WRITE_HOST_VRAM)
+                rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pDesc->GCPhys + uCurrentOffset - uDescOffset, pCurrentDest, cbToCopy);
+            else
+                rc = PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), pDesc->GCPhys + uCurrentOffset - uDescOffset, pCurrentDest, cbToCopy);
+            AssertRCBreak(rc);
+
+            cbCurrentWidth -= cbToCopy;
+            uCurrentOffset += cbToCopy;
+            pCurrentDest   += cbToCopy;
+
+            /* Go to the next descriptor if there's anything left. */
+            if (cbCurrentWidth)
+            {
+                uDescOffset += pDesc->numPages * PAGE_SIZE;
+                pDesc++;
+            }
+        }
+
+        cbSrcOffset += cbSrcPitch;
+        pDest       += cbDestPitch;
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Unblock the FIFO I/O thread so it can respond to a state change.
+ *
+ * @returns VBox status code.
+ * @param   pDevIns     The VGA device instance.
+ * @param   pThread     The send thread.
+ */
+static DECLCALLBACK(int) vmsvgaFIFOLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+    PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
+    Log(("vmsvgaFIFOLoopWakeUp\n"));
+    return RTSemEventSignal(pThis->svga.FIFORequestSem);
+}
+
+/**
+ * Enables or disables dirty page tracking for the framebuffer
+ *
+ * @param   pThis           VGA device instance data.
+ * @param   fTraces         Enable/disable traces
+ */
+static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces)
+{
+    if (    (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
+        &&  !fTraces)
+    {
+        //Assert(pThis->svga.fTraces);
+        Log(("vmsvgaSetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
+        return;
+    }
+
+    pThis->svga.fTraces = fTraces;
+    if (pThis->svga.fTraces)
+    {
+        unsigned cbFrameBuffer = pThis->vram_size;
+
+        Log(("vmsvgaSetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
+        if (pThis->svga.iHeight != -1)
+        {
+            Assert(pThis->svga.cbScanline);
+            /* Hardware enabled; return real framebuffer size .*/
+            cbFrameBuffer = (uint32_t)pThis->svga.iHeight * pThis->svga.cbScanline;
+            cbFrameBuffer = RT_ALIGN(cbFrameBuffer, PAGE_SIZE);
+        }
+
+        if (!pThis->svga.fVRAMTracking)
+        {
+            Log(("vmsvgaSetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
+            vgaR3RegisterVRAMHandler(pThis, cbFrameBuffer);
+            pThis->svga.fVRAMTracking = true;
+        }
+    }
+    else
+    {
+        if (pThis->svga.fVRAMTracking)
+        {
+            Log(("vmsvgaSetTraces: disable frame buffer dirty page tracking\n"));
+            vgaR3UnregisterVRAMHandler(pThis);
+            pThis->svga.fVRAMTracking = false;
+        }
+    }
+}
+
+/**
+ * Callback function for mapping a PCI I/O region.
+ *
+ * @return VBox status code.
+ * @param   pPciDev         Pointer to PCI device.
+ *                          Use pPciDev->pDevIns to get the device instance.
+ * @param   iRegion         The region number.
+ * @param   GCPhysAddress   Physical address of the region.
+ *                          If iType is PCI_ADDRESS_SPACE_IO, this is an
+ *                          I/O port, else it's a physical address.
+ *                          This address is *NOT* relative
+ *                          to pci_mem_base like earlier!
+ * @param   enmType         One of the PCI_ADDRESS_SPACE_* values.
+ */
+DECLCALLBACK(int) vmsvgaR3IORegionMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
+{
+    int         rc;
+    PPDMDEVINS  pDevIns = pPciDev->pDevIns;
+    PVGASTATE   pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+
+    if (enmType == PCI_ADDRESS_SPACE_IO)
+    {
+        AssertReturn(iRegion == 0, VERR_INTERNAL_ERROR);
+        rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0, vmsvgaIOWrite, vmsvgaIORead, NULL /* OutStr */, NULL /* InStr */, "VMSVGA");
+        if (RT_FAILURE(rc))
+            return rc;
+
+        pThis->svga.BasePort = GCPhysAddress;
+        Log(("vmsvgaR3IORegionMap: base port = %x\n", pThis->svga.BasePort));
+    }
+    else
+    {
+        AssertReturn(iRegion == 2 && enmType == PCI_ADDRESS_SPACE_MEM, VERR_INTERNAL_ERROR);
+        if (GCPhysAddress != NIL_RTGCPHYS)
+        {
+            /*
+             * Mapping the FIFO RAM.
+             */
+            rc = PDMDevHlpMMIO2Map(pDevIns, iRegion, GCPhysAddress);
+            AssertRC(rc);
+
+#ifdef DEBUG_FIFO_ACCESS
+            if (RT_SUCCESS(rc))
+            {
+                rc = PGMR3HandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),
+                                                  PGMPHYSHANDLERTYPE_PHYSICAL_ALL,
+                                                  GCPhysAddress, GCPhysAddress + (VMSVGA_FIFO_SIZE - 1),
+                                                  vmsvgaR3FIFOAccessHandler, pThis,
+                                                  NULL, NULL, NULL,
+                                                  NULL, NULL, NULL,
+                                                  "VMSVGA FIFO");
+                AssertRC(rc);
+            }
+#endif
+            if (RT_SUCCESS(rc))
+            {
+                pThis->svga.GCPhysFIFO = GCPhysAddress;
+                Log(("vmsvgaR3IORegionMap: FIFO address = %RGp\n", GCPhysAddress));
+            }
+        }
+        else
+        {
+            Assert(pThis->svga.GCPhysFIFO);
+#ifdef DEBUG_FIFO_ACCESS
+            rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
+            AssertRC(rc);
+#endif
+            pThis->svga.GCPhysFIFO = 0;
+        }
+
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @copydoc FNSSMDEVLOADEXEC
+ */
+int vmsvgaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+    PVGASTATE    pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    int          rc;
+
+    /* Load our part of the VGAState */
+    rc = SSMR3GetStruct(pSSM, &pThis->svga, g_aVGAStateSVGAFields);
+    AssertReturn(rc, rc);
+
+    /* Load the framebuffer backup. */
+    rc = SSMR3GetMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+    AssertReturn(rc, rc);
+
+    /* Load the VMSVGA state. */
+    rc = SSMR3GetStruct(pSSM, pSVGAState, g_aVMSVGASTATEFields);
+    AssertReturn(rc, rc);
+
+    /* Save the GMR state */
+    for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
+    {
+        rc = SSMR3GetStruct(pSSM, &pSVGAState->aGMR[i], g_aGMRFields);
+        AssertReturn(rc, rc); 
+
+        for (uint32_t j = 0; j < pSVGAState->aGMR[i].numDescriptors; j++)
+        {
+            rc = SSMR3GetStruct(pSSM, &pSVGAState->aGMR[i].paDesc[j], g_aVMSVGAGMRDESCRIPTORFields);
+            AssertReturn(rc, rc);
+        }
+    }
+
+#ifdef VBOX_WITH_VMSVGA3D
+    if (    uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA
+        &&  pThis->svga.f3DEnabled)
+        vmsvga3dLoadExec(pThis, pSSM, uVersion, uPass);
+#endif
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @copydoc FNSSMDEVSAVEEXEC
+ */
+int vmsvgaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+    PVGASTATE    pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+    int          rc;
+
+    /* Save our part of the VGAState */
+    rc = SSMR3PutStruct(pSSM, &pThis->svga, g_aVGAStateSVGAFields);
+    AssertReturn(rc, rc);
+
+    /* Save the framebuffer backup. */
+    rc = SSMR3PutMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+    AssertReturn(rc, rc);
+
+    /* Save the VMSVGA state. */
+    rc = SSMR3PutStruct(pSSM, pSVGAState, g_aVMSVGASTATEFields);
+    AssertReturn(rc, rc);
+
+    /* Save the GMR state */
+    for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
+    {
+        rc = SSMR3PutStruct(pSSM, &pSVGAState->aGMR[i], g_aGMRFields);
+        AssertReturn(rc, rc);
+
+        for (uint32_t j = 0; j < pSVGAState->aGMR[i].numDescriptors; j++)
+        {
+            rc = SSMR3PutStruct(pSSM, &pSVGAState->aGMR[i].paDesc[j], g_aVMSVGAGMRDESCRIPTORFields);
+            AssertReturn(rc, rc);
+        }
+    }
+
+#ifdef VBOX_WITH_VMSVGA3D
+    if (pThis->svga.f3DEnabled)
+        vmsvga3dSaveExec(pThis, pSSM);
+#endif
+    return VINF_SUCCESS;
+}
+
+/**
+ * Cleans up the SVGA hardware state
+ *
+ * @returns VBox status code.
+ * @param   pDevIns     The device instance.
+ */
+int vmsvgaDestruct(PPDMDEVINS pDevIns)
+{
+    PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+
+    if (pSVGAState)
+    {
+        for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
+        {
+            if (pSVGAState->aGMR[i].paDesc)
+                RTMemFree(pSVGAState->aGMR[i].paDesc);
+        }
+        RTMemFree(pSVGAState);
+    }
+
+#ifdef VBOX_WITH_VMSVGA3D
+    /** @todo */
+    if (pThis->svga.f3DEnabled)
+        vmsvga3dTerminate(pThis);
+#endif
+    return VINF_SUCCESS;
+}
+
+/**
+ * Initialize the SVGA hardware state
+ *
+ * @returns VBox status code.
+ * @param   pDevIns     The device instance.
+ */
+int vmsvgaInit(PPDMDEVINS pDevIns)
+{
+    PVGASTATE       pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    PVMSVGASTATE    pSVGAState;
+    PVM             pVM   = PDMDevHlpGetVM(pDevIns);
+    int             rc;
+
+    pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
+    memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
+
+    pThis->svga.pSVGAState = RTMemAllocZ(sizeof(VMSVGASTATE));
+    AssertReturn(pThis->svga.pSVGAState, VERR_NO_MEMORY);
+    pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
+
+    /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
+    pThis->svga.pFrameBufferBackup = RTMemAllocZ(VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+    AssertReturn(pThis->svga.pFrameBufferBackup, VERR_NO_MEMORY);
+
+    /* Create event semaphore. */
+    rc = RTSemEventCreate(&pThis->svga.FIFORequestSem);
+    if (RT_FAILURE(rc))
+    {
+        Log(("%s: Failed to create event semaphore for FIFO handling.\n", __FUNCTION__));
+        return rc;
+    }
+
+    /* Register caps. */
+    pThis->svga.u32RegCaps = SVGA_CAP_GMR | SVGA_CAP_GMR2 | SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | SVGA_CAP_EXTENDED_FIFO | SVGA_CAP_IRQMASK | SVGA_CAP_PITCHLOCK | SVGA_CAP_TRACES | SVGA_CAP_SCREEN_OBJECT_2;
+#ifdef VBOX_WITH_VMSVGA3D
+    pThis->svga.u32RegCaps |= SVGA_CAP_3D;
+#endif
+
+    /* Setup FIFO capabilities. */
+    pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] = SVGA_FIFO_CAP_FENCE | SVGA_FIFO_CAP_CURSOR_BYPASS_3 | SVGA_FIFO_CAP_GMR2 | SVGA_FIFO_CAP_3D_HWVERSION_REVISED | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
+
+    /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
+    pThis->svga.pFIFOR3[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
+
+    pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION] = pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION_REVISED] = 0;    /* no 3d available. */
+#ifdef VBOX_WITH_VMSVGA3D
+    if (pThis->svga.f3DEnabled)
+    {
+        rc = vmsvga3dInit(pThis);
+        if (RT_FAILURE(rc))
+            pThis->svga.f3DEnabled = false;
+    }
+#endif
+    /* VRAM tracking is enabled by default during bootup. */
+    pThis->svga.fVRAMTracking = true;
+
+    /* Invalidate current settings. */
+    pThis->svga.iWidth     = -1;
+    pThis->svga.iHeight    = -1;
+    pThis->svga.iBpp       = -1;
+    pThis->svga.cbScanline = 0;
+
+    pThis->svga.u32MaxWidth  = VBE_DISPI_MAX_YRES;
+    pThis->svga.u32MaxHeight = VBE_DISPI_MAX_XRES;
+    while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
+    {
+        pThis->svga.u32MaxWidth  -= 256;
+        pThis->svga.u32MaxHeight -= 256;
+    }
+    Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
+
+    /* Create the async IO thread. */
+    rc = PDMDevHlpThreadCreate(pDevIns, &pThis->svga.pFIFOIOThread, pThis, vmsvgaFIFOLoop, vmsvgaFIFOLoopWakeUp, 0,
+                                RTTHREADTYPE_IO, "VMSVGA FIFO");
+    if (RT_FAILURE(rc))
+    {
+        AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
+        return rc;
+    }
+
+    /*
+     * 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.");
+   
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Power On notification.
+ *
+ * @returns VBox status.
+ * @param   pDevIns     The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
+{
+    PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+    int       rc;
+#ifdef VBOX_WITH_VMSVGA3D
+    if (pThis->svga.f3DEnabled)
+    {
+        rc = vmsvga3dPowerOn(pThis);
+
+        if (RT_SUCCESS(rc))
+        {
+            SVGA3dCapsRecord *pCaps;
+            SVGA3dCapPair    *pData;
+            uint32_t          idxCap  = 0;
+
+            /* 3d hardware version; latest and greatest */
+            pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
+            pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION]         = SVGA3D_HWVERSION_CURRENT;
+
+            pCaps = (SVGA3dCapsRecord *)&pThis->svga.pFIFOR3[SVGA_FIFO_3D_CAPS];
+            pCaps->header.type   = SVGA3DCAPS_RECORD_DEVCAPS;
+            pData = (SVGA3dCapPair *)&pCaps->data;
+
+            /* Fill out all 3d capabilities. */
+            for (unsigned i = 0; i < SVGA3D_DEVCAP_MAX; i++)
+            {
+                uint32_t val = 0;
+
+                rc = vmsvga3dQueryCaps(pThis, i, &val);
+                if (RT_SUCCESS(rc))
+                {
+                    pData[idxCap][0] = i;
+                    pData[idxCap][1] = val;
+                    idxCap++;
+                }
+            }
+            pCaps->header.length = (sizeof(pCaps->header) + idxCap * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
+            pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
+
+            /* Mark end of record array. */
+            pCaps->header.length = 0;
+        }
+    }
+#endif // VBOX_WITH_VMSVGA3D
+}
+
+#endif /* IN_RING3 */
+
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.h b/src/VBox/Devices/Graphics/DevVGA-SVGA.h
new file mode 100644
index 0000000..31564e4
--- /dev/null
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.h
@@ -0,0 +1,46 @@
+/** @file
+ * VMware SVGA device
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __DEVVGA_SVGA_H__
+#define __DEVVGA_SVGA_H__
+
+
+/** Default FIFO size. */
+#define VMSVGA_FIFO_SIZE                0x20000
+/** Default scratch region size. */
+#define VMSVGA_SCRATCH_SIZE             0x100
+/** Surface memory available to the guest. */
+#define VMSVGA_SURFACE_SIZE             (512*1024*1024)
+/** Maximum GMR pages. */
+#define VMSVGA_MAX_GMR_PAGES            0x2000
+/** Maximum nr of GMR ids. */
+#define VMSVGA_MAX_GMR_IDS              0x100
+/** Size of the region to backup when switching into svga mode. */
+#define VMSVGA_FRAMEBUFFER_BACKUP_SIZE  (32*1024)
+
+/* u32ActionFlags */
+#define VMSVGA_ACTION_CHANGEMODE_BIT    0
+#define VMSVGA_ACTION_CHANGEMODE        RT_BIT(VMSVGA_ACTION_CHANGEMODE_BIT)
+
+DECLCALLBACK(int) vmsvgaR3IORegionMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType);
+
+int vmsvgaInit(PPDMDEVINS pDevIns);
+int vmsvgaDestruct(PPDMDEVINS pDevIns);
+int vmsvgaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+int vmsvgaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns);
+
+#endif  /* __DEVVGA_SVGA_H__ */
+
diff --git a/src/VBox/Devices/Graphics/DevVGA.cpp b/src/VBox/Devices/Graphics/DevVGA.cpp
index ee7de1b..e55a4ed 100644
--- a/src/VBox/Devices/Graphics/DevVGA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA.cpp
@@ -137,6 +137,10 @@
 #include "VBoxDD.h"
 #include "VBoxDD2.h"
 
+#ifdef VBOX_WITH_VMSVGA
+#include "DevVGA-SVGA.h"
+#include "vmsvga/svga_reg.h"
+#endif
 
 /*******************************************************************************
 *   Structures and Typedefs                                                    *
@@ -1122,6 +1126,9 @@ static int vbe_ioport_write_data(PVGASTATE pThis, uint32_t addr, uint32_t val)
              * is used by the display to disable VBVA.
              */
             pThis->pDrv->pfnLFBModeChange(pThis->pDrv, (val & VBE_DISPI_ENABLED) != 0);
+#ifdef VBOX_WITH_HGSMI
+            VBVAPause(pThis, (val & VBE_DISPI_ENABLED) == 0);
+#endif /* VBOX_WITH_HGSMI */
 
             /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
             if (pThis->fRemappedVGA)
@@ -2073,6 +2080,183 @@ static int vga_resize_graphic(PVGASTATE pThis, int cx, int cy)
     return VINF_SUCCESS;
 }
 
+#ifdef VBOX_WITH_VMSVGA
+int vgaR3UpdateDisplay(VGAState *s, unsigned xStart, unsigned yStart, unsigned width, unsigned height)
+{
+    int bits;
+    uint32_t v;
+    vga_draw_line_func *vga_draw_line;
+
+    if (!s->fRenderVRAM)
+    {
+        s->pDrv->pfnUpdateRect(s->pDrv, xStart, yStart, width, height);
+        return VINF_SUCCESS;
+    }
+    /* @todo might crash if a blit follows a resolution change very quickly (seen this many times!) */
+
+    if (    s->svga.iWidth == -1
+        ||  s->svga.iHeight == -1
+        ||  s->svga.iBpp == UINT32_MAX)
+    {
+        /* Intermediate state; skip redraws. */
+        AssertFailed();
+        return VINF_SUCCESS;
+    }
+
+    switch(s->svga.iBpp) {
+    default:
+    case 0:
+    case 8:
+        AssertFailed();
+        return VERR_NOT_IMPLEMENTED;
+    case 15:
+        v = VGA_DRAW_LINE15;
+        bits = 16;
+        break;
+    case 16:
+        v = VGA_DRAW_LINE16;
+        bits = 16;
+        break;
+    case 24:
+        v = VGA_DRAW_LINE24;
+        bits = 24;
+        break;
+    case 32:
+        v = VGA_DRAW_LINE32;
+        bits = 32;
+        break;
+    }
+    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->pDrv->cBits)];
+
+    unsigned offsetSource = (xStart * bits) / 8 + s->svga.cbScanline * yStart;
+    unsigned offsetDest   = (xStart * RT_ALIGN(s->pDrv->cBits, 8)) / 8 + s->pDrv->cbScanline * yStart;
+
+    uint8_t *dest = s->pDrv->pu8Data      + offsetDest;
+    uint8_t *src  = s->CTX_SUFF(vram_ptr) + offsetSource;
+
+    for(unsigned y = yStart; y < yStart + height; y++) 
+    {
+        vga_draw_line(s, dest, src, width);
+
+        dest += s->pDrv->cbScanline;
+        src  += s->svga.cbScanline;
+    }
+    s->pDrv->pfnUpdateRect(s->pDrv, xStart, yStart, width, height);
+
+    return VINF_SUCCESS;
+}
+
+/*
+ * graphic modes
+ */
+static int vmsvga_draw_graphic(PVGASTATE pThis, bool full_update, bool fFailOnResize, bool reset_dirty)
+{
+    int y, page_min, page_max, linesize, y_start;
+    int width, height, page0, page1, bwidth, bits;
+    int disp_width;
+    uint8_t *d;
+    uint32_t v, addr1, addr;
+    vga_draw_line_func *vga_draw_line;
+
+    if (    pThis->svga.iWidth == -1
+        ||  pThis->svga.iHeight == -1
+        ||  pThis->svga.iBpp == UINT32_MAX)
+    {
+        /* Intermediate state; skip redraws. */
+        return VINF_SUCCESS;
+    }
+
+    width  = pThis->svga.iWidth;
+    height = pThis->svga.iHeight;
+
+    disp_width = width;
+
+    switch(pThis->svga.iBpp) {
+    default:
+    case 0:
+    case 8:
+        AssertFailed();
+        return VERR_NOT_IMPLEMENTED;
+    case 15:
+        v = VGA_DRAW_LINE15;
+        bits = 16;
+        break;
+    case 16:
+        v = VGA_DRAW_LINE16;
+        bits = 16;
+        break;
+    case 24:
+        v = VGA_DRAW_LINE24;
+        bits = 24;
+        break;
+    case 32:
+        v = VGA_DRAW_LINE32;
+        bits = 32;
+        break;
+    }
+    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(pThis->pDrv->cBits)];
+
+    if (pThis->cursor_invalidate)
+        pThis->cursor_invalidate(pThis);
+
+    addr1 = 0;  /* always start at the beginning of the framebuffer */
+    bwidth = (width * bits + 7) / 8;    /* The visible width of a scanline. */
+    y_start = -1;
+    page_min = 0x7fffffff;
+    page_max = -1;
+    d = pThis->pDrv->pu8Data;
+    linesize = pThis->pDrv->cbScanline;
+
+    for(y = 0; y < height; y++) 
+    {
+        addr = addr1 + y * bwidth;
+
+        page0 = addr & ~PAGE_OFFSET_MASK;
+        page1 = (addr + bwidth - 1) & ~PAGE_OFFSET_MASK;
+        bool update = full_update | vga_is_dirty(pThis, page0) | vga_is_dirty(pThis, page1);
+        if (page1 - page0 > PAGE_SIZE)
+            /* if wide line, can use another page */
+            update |= vga_is_dirty(pThis, page0 + PAGE_SIZE);
+        /* explicit invalidation for the hardware cursor */
+        update |= (pThis->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
+        if (update)
+        {
+            if (y_start < 0)
+                y_start = y;
+            if (page0 < page_min)
+                page_min = page0;
+            if (page1 > page_max)
+                page_max = page1;
+            if (pThis->fRenderVRAM)
+                vga_draw_line(pThis, d, pThis->CTX_SUFF(vram_ptr) + addr, width);
+            if (pThis->cursor_draw_line)
+                pThis->cursor_draw_line(pThis, d, y);
+        } else
+        {
+            if (y_start >= 0)
+            {
+                /* flush to display */
+                Log(("Flush to display (%d,%d)(%d,%d)\n", 0, y_start, disp_width, y - y_start));
+                pThis->pDrv->pfnUpdateRect(pThis->pDrv, 0, y_start, disp_width, y - y_start);
+                y_start = -1;
+            }
+        }
+        d += linesize;
+    }
+    if (y_start >= 0)
+    {
+        /* flush to display */
+        Log(("Flush to display (%d,%d)(%d,%d)\n", 0, y_start, disp_width, y - y_start));
+        pThis->pDrv->pfnUpdateRect(pThis->pDrv, 0, y_start, disp_width, y - y_start);
+    }
+    /* reset modified pages */
+    if (page_max != -1 && reset_dirty)
+        vga_reset_dirty(pThis, page_min, page_max + PAGE_SIZE);
+    memset(pThis->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
+    return VINF_SUCCESS;
+}
+#endif /* VBOX_WITH_VMSVGA */
+
 /*
  * graphic modes
  */
@@ -2291,6 +2475,9 @@ static DECLCALLBACK(void) voidUpdateRect(PPDMIDISPLAYCONNECTOR pInterface, uint3
 #define GMODE_TEXT     0
 #define GMODE_GRAPH    1
 #define GMODE_BLANK 2
+#ifdef VBOX_WITH_VMSVGA
+#define GMODE_SVGA      3
+#endif
 
 static int vga_update_display(PVGASTATE pThis, bool fUpdateAll, bool fFailOnResize, bool reset_dirty)
 {
@@ -2344,6 +2531,13 @@ static int vga_update_display(PVGASTATE pThis, bool fUpdateAll, bool fFailOnResi
             }
 
             /* Do a complete redraw, which will pick up a new screen resolution. */
+#ifdef VBOX_WITH_VMSVGA
+            if (pThis->svga.fEnabled) {
+                pThis->graphic_mode = GMODE_SVGA;
+                rc = vmsvga_draw_graphic(pThis, 1, false, reset_dirty);
+            }
+            else
+#endif
             if (pThis->gr[6] & 1) {
                 pThis->graphic_mode = GMODE_GRAPH;
                 rc = vga_draw_graphic(pThis, 1, false, reset_dirty);
@@ -2362,6 +2556,12 @@ static int vga_update_display(PVGASTATE pThis, bool fUpdateAll, bool fFailOnResi
             return rc;
         }
 
+#ifdef VBOX_WITH_VMSVGA
+        if (pThis->svga.fEnabled) {
+            graphic_mode = GMODE_SVGA;
+        }
+        else
+#endif
         if (!(pThis->ar_index & 0x20) || (pThis->sr[0x01] & 0x20)) {
             graphic_mode = GMODE_BLANK;
         } else {
@@ -2378,6 +2578,11 @@ static int vga_update_display(PVGASTATE pThis, bool fUpdateAll, bool fFailOnResi
         case GMODE_GRAPH:
             rc = vga_draw_graphic(pThis, full_update, fFailOnResize, reset_dirty);
             break;
+#ifdef VBOX_WITH_VMSVGA
+        case GMODE_SVGA:
+            rc = vmsvga_draw_graphic(pThis, full_update, fFailOnResize, reset_dirty);
+            break;
+#endif
         case GMODE_BLANK:
         default:
             vga_draw_blank(pThis, full_update);
@@ -4315,6 +4520,16 @@ static DECLCALLBACK(int) vgaPortUpdateDisplay(PPDMIDISPLAYPORT pInterface)
     int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
     AssertRC(rc);
 
+#ifdef VBOX_WITH_VMSVGA
+    if (    pThis->svga.fEnabled
+        &&  !pThis->svga.fTraces)
+    {
+        /* Nothing to do as the guest will explicitely update us about frame buffer changes. */
+        PDMCritSectLeave(&pThis->CritSect);
+        return VINF_SUCCESS;
+    }
+#endif
+
 #ifndef VBOX_WITH_HGSMI
     /* This should be called only in non VBVA mode. */
 #else
@@ -4350,9 +4565,17 @@ static int updateDisplayAll(PVGASTATE pThis)
 {
     PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns);
 
+#ifdef VBOX_WITH_VMSVGA
+    if (    !pThis->svga.fEnabled
+        ||  pThis->svga.fTraces)
+    {
+#endif
     /* The dirty bits array has been just cleared, reset handlers as well. */
     if (pThis->GCPhysVRAM && pThis->GCPhysVRAM != NIL_RTGCPHYS)
         PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pThis->GCPhysVRAM);
+#ifdef VBOX_WITH_VMSVGA
+    }
+#endif
     if (pThis->fRemappedVGA)
     {
         IOMMMIOResetRegion(PDMDevHlpGetVM(pDevIns), 0x000a0000);
@@ -4916,6 +5139,13 @@ static DECLCALLBACK(int) vgaPortCopyRect (PPDMIDISPLAYPORT pInterface,
     int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
     AssertRC(rc);
 
+    /* This method only works if the VGA device is in a VBE mode. */
+    if ((pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) == 0)
+    {
+        PDMCritSectLeave(&pThis->CritSect);
+        return VERR_INVALID_STATE;
+    }
+
     vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(u32DstBitsPerPixel)];
 
     /* Compute source and destination addresses and pitches. */
@@ -4981,8 +5211,37 @@ static DECLCALLBACK(void) vgaTimerRefresh(PPDMDEVINS pDevIns, PTMTIMER pTimer, v
     vbvaTimerCb(pThis);
 #endif
 
+    vboxCmdVBVACmdTimer(pThis);
 }
 
+#ifdef VBOX_WITH_VMSVGA
+int vgaR3RegisterVRAMHandler(PVGASTATE pVGAState, uint64_t cbFrameBuffer)
+{
+    PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
+
+    Assert(pVGAState->GCPhysVRAM);
+
+    int rc = PGMR3HandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),
+                                          PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
+                                          pVGAState->GCPhysVRAM, pVGAState->GCPhysVRAM + (cbFrameBuffer - 1),
+                                          vgaR3LFBAccessHandler, pVGAState,
+                                          g_DeviceVga.szR0Mod, "vgaR0LFBAccessHandler", pDevIns->pvInstanceDataR0,
+                                          g_DeviceVga.szRCMod, "vgaGCLFBAccessHandler", pDevIns->pvInstanceDataRC,
+                                          "VGA LFB");
+    AssertRC(rc);
+    return rc;
+}
+
+int vgaR3UnregisterVRAMHandler(PVGASTATE pVGAState)
+{
+    PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
+
+    Assert(pVGAState->GCPhysVRAM);
+    int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pVGAState->GCPhysVRAM);
+    AssertRC(rc);
+    return rc;
+}
+#endif
 
 /* -=-=-=-=-=- Ring 3: PCI Device -=-=-=-=-=- */
 
@@ -5003,7 +5262,11 @@ static DECLCALLBACK(int) vgaR3IORegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int i
     PPDMDEVINS  pDevIns = pPciDev->pDevIns;
     PVGASTATE   pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
     LogFlow(("vgaR3IORegionMap: iRegion=%d GCPhysAddress=%RGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
+#ifdef VBOX_WITH_VMSVGA
+    AssertReturn((iRegion == ((pThis->fVMSVGAEnabled) ? 1 : 0)) && (enmType == ((pThis->fVMSVGAEnabled) ? PCI_ADDRESS_SPACE_MEM : PCI_ADDRESS_SPACE_MEM_PREFETCH)), VERR_INTERNAL_ERROR);    
+#else
     AssertReturn(iRegion == 0 && enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH, VERR_INTERNAL_ERROR);
+#endif
 
     if (GCPhysAddress != NIL_RTGCPHYS)
     {
@@ -5036,6 +5299,9 @@ static DECLCALLBACK(int) vgaR3IORegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int i
          * Deregister the access handler so PGM doesn't get upset.
          */
         Assert(pThis->GCPhysVRAM);
+#ifdef VBOX_WITH_VMSVGA
+        Assert(!pThis->svga.fEnabled);
+#endif
         rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->GCPhysVRAM);
         AssertRC(rc);
         pThis->GCPhysVRAM = 0;
@@ -5113,8 +5379,13 @@ static DECLCALLBACK(int) vgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     return rc;
 #else
     SSMR3PutBool(pSSM, false);
-    return VINF_SUCCESS;
 #endif
+#ifdef VBOX_WITH_VMSVGA
+    if (    rc == VINF_SUCCESS
+        &&  pThis->fVMSVGAEnabled)
+        rc = vmsvgaSaveExec(pDevIns, pSSM);
+#endif
+    return rc;
 }
 
 
@@ -5165,6 +5436,14 @@ static DECLCALLBACK(int) vgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint
             return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("HGSMI is not compiled in, but it is present in the saved state"));
 #endif
         }
+#ifdef VBOX_WITH_VMSVGA
+        if (    uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_2D
+            &&  pThis->fVMSVGAEnabled)
+        {
+            rc = vmsvgaLoadExec(pDevIns, pSSM, uVersion, uPass);
+            AssertRCReturn(rc, rc);
+        }
+#endif
     }
     return VINF_SUCCESS;
 }
@@ -5410,6 +5689,11 @@ static DECLCALLBACK(int) vgaR3Destruct(PPDMDEVINS pDevIns)
     vboxVDMADestruct(pThis->pVdma);
 # endif
 
+#ifdef VBOX_WITH_VMSVGA
+    if (pThis->fVMSVGAEnabled)
+        vmsvgaDestruct(pDevIns);
+#endif
+
     /*
      * Free MM heap pointers.
      */
@@ -5535,7 +5819,15 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
                                           "CustomVideoMode15\0"
                                           "CustomVideoMode16\0"
                                           "MaxBiosXRes\0"
-                                          "MaxBiosYRes\0"))
+                                          "MaxBiosYRes\0"
+#ifdef VBOX_WITH_VMSVGA
+                                          "VMSVGAEnabled\0"
+#endif
+#ifdef VBOX_WITH_VMSVGA3D
+                                          "VMSVGA3dEnabled\0"
+                                          "HostWindowId\0"
+#endif
+                                          ))
         return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
                                 N_("Invalid configuration for vga device"));
 
@@ -5564,6 +5856,20 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
     AssertLogRelRCReturn(rc, rc);
     Log(("VGA: VRamSize=%#x fGCenabled=%RTbool fR0Enabled=%RTbool\n", pThis->vram_size, pThis->fGCEnabled, pThis->fR0Enabled));
 
+#ifdef VBOX_WITH_VMSVGA
+    rc = CFGMR3QueryBoolDef(pCfg, "VMSVGAEnabled", &pThis->fVMSVGAEnabled, false);
+    AssertLogRelRCReturn(rc, rc);
+    Log(("VMSVGA: VMSVGAEnabled   = %d\n", pThis->fVMSVGAEnabled));
+#endif
+#ifdef VBOX_WITH_VMSVGA3D
+    rc = CFGMR3QueryBoolDef(pCfg, "VMSVGA3dEnabled", &pThis->svga.f3DEnabled, false);
+    AssertLogRelRCReturn(rc, rc);
+    rc = CFGMR3QueryU64Def(pCfg, "HostWindowId", &pThis->svga.u64HostWindowId, 0);
+    AssertLogRelRCReturn(rc, rc);
+    Log(("VMSVGA: VMSVGA3dEnabled = %d\n", pThis->svga.f3DEnabled));
+    Log(("VMSVGA: HostWindowId    = 0x%x\n", pThis->svga.u64HostWindowId));
+#endif
+
     pThis->pDevInsR3 = pDevIns;
     pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
@@ -5571,8 +5877,23 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
     vgaR3Reset(pDevIns);
 
     /* The PCI devices configuration. */
+#ifdef VBOX_WITH_VMSVGA
+    if (pThis->fVMSVGAEnabled)
+    {
+        /* Extend our VGA device with VMWare SVGA functionality. */
+        PCIDevSetVendorId(&pThis->Dev, PCI_VENDOR_ID_VMWARE);
+        PCIDevSetDeviceId(&pThis->Dev, PCI_DEVICE_ID_VMWARE_SVGA2);
+        PCIDevSetSubSystemVendorId(&pThis->Dev, PCI_VENDOR_ID_VMWARE);
+        PCIDevSetSubSystemId(&pThis->Dev, PCI_DEVICE_ID_VMWARE_SVGA2);
+    }
+    else
+    {
+#endif /* VBOX_WITH_VMSVGA */
     PCIDevSetVendorId(  &pThis->Dev, 0x80ee);   /* PCI vendor, just a free bogus value */
     PCIDevSetDeviceId(  &pThis->Dev, 0xbeef);
+#ifdef VBOX_WITH_VMSVGA
+    }
+#endif
     PCIDevSetClassSub(  &pThis->Dev,   0x00);   /* VGA controller */
     PCIDevSetClassBase( &pThis->Dev,   0x03);
     PCIDevSetHeaderType(&pThis->Dev,   0x00);
@@ -5616,25 +5937,55 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
     /*
      * Allocate the VRAM and map the first 512KB of it into GC so we can speed up VGA support.
      */
-    rc = PDMDevHlpMMIO2Register(pDevIns, 0 /* iRegion */, pThis->vram_size, 0, (void **)&pThis->vram_ptrR3, "VRam");
+#ifdef VBOX_WITH_VMSVGA
+    int iPCIRegionVRAM = (pThis->fVMSVGAEnabled) ? 1 : 0;
+
+    if (pThis->fVMSVGAEnabled)
+    {
+        /*
+         * Allocate and initialize the FIFO MMIO2 memory.
+         */
+        rc = PDMDevHlpMMIO2Register(pDevIns, 2 /*iRegion*/, VMSVGA_FIFO_SIZE, 0 /*fFlags*/, (void **)&pThis->svga.pFIFOR3, "VMSVGA-FIFO");
+        if (RT_FAILURE(rc))
+            return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+                                        N_("Failed to allocate %u bytes of memory for the VMSVGA device"), VMSVGA_FIFO_SIZE);
+        pThis->svga.pFIFOR0 = (RTR0PTR)pThis->svga.pFIFOR3;
+        pThis->svga.cbFIFO  = VMSVGA_FIFO_SIZE;
+    }
+#else
+    int iPCIRegionVRAM = 0;
+#endif
+    rc = PDMDevHlpMMIO2Register(pDevIns, iPCIRegionVRAM, pThis->vram_size, 0, (void **)&pThis->vram_ptrR3, "VRam");
     AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMMIO2Register(%#x,) -> %Rrc\n", pThis->vram_size, rc), rc);
     pThis->vram_ptrR0 = (RTR0PTR)pThis->vram_ptrR3; /** @todo @bugref{1865} Map parts into R0 or just use PGM access (Mac only). */
 
     if (pThis->fGCEnabled)
     {
         RTRCPTR pRCMapping = 0;
-        rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, 0 /* iRegion */, 0 /* off */,  VGA_MAPPING_SIZE, "VGA VRam", &pRCMapping);
+        rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, iPCIRegionVRAM, 0 /* off */,  VGA_MAPPING_SIZE, "VGA VRam", &pRCMapping);
         AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMMHyperMapMMIO2(%#x,) -> %Rrc\n", VGA_MAPPING_SIZE, rc), rc);
         pThis->vram_ptrRC = pRCMapping;
+# ifdef VBOX_WITH_VMSVGA
+        /* Don't need a mapping in RC */
+# endif
     }
 
 #if defined(VBOX_WITH_2X_4GB_ADDR_SPACE)
     if (pThis->fR0Enabled)
     {
         RTR0PTR pR0Mapping = 0;
-        rc = PDMDevHlpMMIO2MapKernel(pDevIns, 0 /* iRegion */, 0 /* off */,  VGA_MAPPING_SIZE, "VGA VRam", &pR0Mapping);
+        rc = PDMDevHlpMMIO2MapKernel(pDevIns, iPCIRegionVRAM, 0 /* off */,  VGA_MAPPING_SIZE, "VGA VRam", &pR0Mapping);
         AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMapMMIO2IntoR0(%#x,) -> %Rrc\n", VGA_MAPPING_SIZE, rc), rc);
         pThis->vram_ptrR0 = pR0Mapping;
+# ifdef VBOX_WITH_VMSVGA
+        if (pThis->fVMSVGAEnabled)
+        {
+            RTR0PTR pR0Mapping = 0;
+            rc = PDMDevHlpMMIO2MapKernel(pDevIns, 2 /* iRegion */, 0 /* off */,  VMSVGA_FIFO_SIZE, "VMSVGA-FIFO", &pR0Mapping);
+            AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMapMMIO2IntoR0(%#x,) -> %Rrc\n", VMSVGA_FIFO_SIZE, rc), rc);
+            pThis->svga.pFIFOR0 = pR0Mapping;
+        }
+# endif
     }
 #endif
 
@@ -5888,7 +6239,24 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
     if (pThis->Dev.devfn != 16 && iInstance == 0)
         Log(("!!WARNING!!: pThis->dev.devfn=%d (ignore if testcase or not started by Main)\n", pThis->Dev.devfn));
 
-    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0 /* iRegion */, pThis->vram_size, PCI_ADDRESS_SPACE_MEM_PREFETCH, vgaR3IORegionMap);
+#ifdef VBOX_WITH_VMSVGA
+    if (pThis->fVMSVGAEnabled)
+    {
+        /* Register the io command ports. */
+        rc = PDMDevHlpPCIIORegionRegister (pDevIns, 0 /* iRegion */, 0x10, PCI_ADDRESS_SPACE_IO, vmsvgaR3IORegionMap);
+        if (RT_FAILURE (rc))
+            return rc;
+        /* VMware's MetalKit doesn't like PCI_ADDRESS_SPACE_MEM_PREFETCH */
+        rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1 /* iRegion */, pThis->vram_size, PCI_ADDRESS_SPACE_MEM /* PCI_ADDRESS_SPACE_MEM_PREFETCH */, vgaR3IORegionMap);
+        if (RT_FAILURE(rc))
+            return rc;
+        rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2 /* iRegion */, VMSVGA_FIFO_SIZE, PCI_ADDRESS_SPACE_MEM /* PCI_ADDRESS_SPACE_MEM_PREFETCH */, vmsvgaR3IORegionMap);
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+    else
+#endif /* VBOX_WITH_VMSVGA */
+    rc = PDMDevHlpPCIIORegionRegister(pDevIns, iPCIRegionVRAM, pThis->vram_size, PCI_ADDRESS_SPACE_MEM_PREFETCH, vgaR3IORegionMap);
     if (RT_FAILURE(rc))
         return rc;
 
@@ -6296,6 +6664,15 @@ static DECLCALLBACK(int)   vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
         AssertRC(rc);
     }
 #endif
+
+#ifdef VBOX_WITH_VMSVGA
+    if (    rc == VINF_SUCCESS
+        &&  pThis->fVMSVGAEnabled)
+    {
+        rc = vmsvgaInit(pDevIns);
+    }
+#endif
+
     /*
      * Statistics.
      */
@@ -6344,7 +6721,11 @@ const PDMDEVREG g_DeviceVga =
     /* pfnMemSetup */
     NULL,
     /* pfnPowerOn */
+#ifdef VBOX_WITH_VMSVGA
+    vmsvgaR3PowerOn,
+#else
     NULL,
+#endif
     /* pfnReset */
     vgaR3Reset,
     /* pfnSuspend */
diff --git a/src/VBox/Devices/Graphics/DevVGA.h b/src/VBox/Devices/Graphics/DevVGA.h
index 530e943..f3617bb 100644
--- a/src/VBox/Devices/Graphics/DevVGA.h
+++ b/src/VBox/Devices/Graphics/DevVGA.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -64,6 +64,10 @@
 #endif /* VBOX_WITH_HGSMI */
 #include "DevVGASavedState.h"
 
+#ifdef VBOX_WITH_VMSVGA
+# include "DevVGA-SVGA.h"
+#endif
+
 # include <iprt/list.h>
 
 #define MSR_COLOR_EMULATION 0x01
@@ -304,6 +308,81 @@ typedef struct VGAState {
     /** The R0 vram pointer... */
     R0PTRTYPE(uint8_t *)        vram_ptrR0;
 
+#ifdef VBOX_WITH_VMSVGA
+    struct
+    {
+        /** The host window handle */
+        uint64_t                    u64HostWindowId;
+        /** The R3 FIFO pointer. */
+        R3PTRTYPE(uint32_t *)       pFIFOR3;
+        /** The R0 FIFO pointer. */
+        R0PTRTYPE(uint32_t *)       pFIFOR0;
+        /** R3 Opaque pointer to svga state. */
+        R3PTRTYPE(void *)           pSVGAState;
+        /** R3 Opaque pointer to 3d state. */
+        R3PTRTYPE(void *)           p3dState;
+        /** R3 Opaque pointer to a copy of the first 32k of the framebuffer before switching into svga mode. */
+        R3PTRTYPE(void *)           pFrameBufferBackup;
+#if HC_ARCH_BITS == 32
+        uint32_t                    Padding3;
+#endif
+        /** Guest physical address of the FIFO memory range. */
+        RTGCPHYS                    GCPhysFIFO;
+        /** Size in bytes of the FIFO memory range. */
+        uint32_t                    cbFIFO;
+        /** SVGA id. */
+        uint32_t                    u32SVGAId;
+        /** SVGA extensions enabled or not. */
+        uint32_t                    fEnabled;
+        /** SVGA memory area configured status. */
+        uint32_t                    fConfigured;
+        /** Device is busy handling FIFO requests. */
+        uint32_t                    fBusy;
+        /** Traces (dirty page detection) enabled or not. */
+        uint32_t                    fTraces;
+        /** Guest OS identifier. */
+        uint32_t                    u32GuestId;
+        /** Scratch region size. */
+        uint32_t                    cScratchRegion;
+        /** Scratch array. */
+        uint32_t                    au32ScratchRegion[VMSVGA_SCRATCH_SIZE];
+        /** Irq status. */
+        uint32_t                    u32IrqStatus;
+        /** Irq mask. */
+        uint32_t                    u32IrqMask;
+        /** Pitch lock. */
+        uint32_t                    u32PitchLock;
+        /** Current GMR id. (SVGA_REG_GMR_ID) */
+        uint32_t                    u32CurrentGMRId;
+        /** Register caps. */
+        uint32_t                    u32RegCaps;
+        /** Physical address of command mmio range. */
+        uint32_t                    Padding2;
+        RTIOPORT                    BasePort;
+        /** Port io index register. */
+        uint32_t                    u32IndexReg;
+        /** FIFO request semaphore. */
+        RTSEMEVENT                  FIFORequestSem;
+        /** FIFO IO Thread. */
+        R3PTRTYPE(PPDMTHREAD)       pFIFOIOThread;
+        int32_t                     iWidth;
+        int32_t                     iHeight;
+        uint32_t                    iBpp;
+        uint32_t                    cbScanline;
+        /** Maximum width supported. */
+        uint32_t                    u32MaxWidth;
+        /** Maximum height supported. */
+        uint32_t                    u32MaxHeight;
+        /** Action flags */
+        uint32_t                    u32ActionFlags;
+        /** SVGA 3d extensions enabled or not. */
+        bool                        f3DEnabled;
+        /** VRAM page monitoring enabled or not. */
+        bool                        fVRAMTracking;
+        bool                        Padding6[2];
+    } svga;
+#endif
+
     /** The number of monitors. */
     uint32_t                    cMonitors;
     /** Current refresh timer interval. */
@@ -323,7 +402,13 @@ typedef struct VGAState {
     bool                        fRemappedVGA;
     /** Whether to render the guest VRAM to the framebuffer memory. False only for some LFB modes. */
     bool                        fRenderVRAM;
+#ifdef VBOX_WITH_VMSVGA
+    /* Whether the SVGA emulation is enabled or not. */
+    bool                        fVMSVGAEnabled;
+    bool                        Padding1[1];
+#else
     bool                        Padding1[2];
+#endif
 
     /** The physical address the VRAM was assigned. */
     RTGCPHYS                    GCPhysVRAM;
@@ -507,10 +592,13 @@ int      VBVAInit       (PVGASTATE pVGAState);
 void     VBVADestroy    (PVGASTATE pVGAState);
 int      VBVAUpdateDisplay (PVGASTATE pVGAState);
 void     VBVAReset (PVGASTATE pVGAState);
+void     VBVAPause (PVGASTATE pVGAState, bool fPause);
+int      VBVAGetScreenInfo(PVGASTATE pVGAState, unsigned uScreenId, struct VBVAINFOSCREEN *pScreen, void **ppvVram);
 
 bool VBVAIsEnabled(PVGASTATE pVGAState);
 
 void VBVARaiseIrq (PVGASTATE pVGAState, uint32_t fFlags);
+void VBVARaiseIrqNoWait(PVGASTATE pVGAState, uint32_t fFlags);
 
 /* @return host-guest flags that were set on reset
  * this allows the caller to make further cleaning when needed,
@@ -551,8 +639,20 @@ int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM);
 int vboxVDMASaveStateExecDone(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM);
 # endif /* VBOX_WITH_VDMA */
 
+int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA);
+int vboxCmdVBVADisable(PVGASTATE pVGAState);
+int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState);
+int vboxCmdVBVACmdFlush(PVGASTATE pVGAState);
+void vboxCmdVBVACmdTimer(PVGASTATE pVGAState);
+
 #endif /* VBOX_WITH_HGSMI */
 
+# ifdef VBOX_WITH_VMSVGA
+int vgaR3RegisterVRAMHandler(PVGASTATE pVGAState, uint64_t cbFrameBuffer);
+int vgaR3UnregisterVRAMHandler(PVGASTATE pVGAState);
+int vgaR3UpdateDisplay(PVGASTATE pVGAState, unsigned xStart, unsigned yStart, unsigned width, unsigned height);
+# endif
+
 #ifndef VBOX
 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
                      unsigned long vga_ram_offset, int vga_ram_size);
diff --git a/src/VBox/Devices/Graphics/DevVGASavedState.h b/src/VBox/Devices/Graphics/DevVGASavedState.h
index 377a807..1ee861a 100644
--- a/src/VBox/Devices/Graphics/DevVGASavedState.h
+++ b/src/VBox/Devices/Graphics/DevVGASavedState.h
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -22,7 +22,13 @@
 #ifndef Graphics_DevVGASavedState_h
 #define Graphics_DevVGASavedState_h
 
+#ifdef VBOX_WITH_VMSVGA
+#define VGA_SAVEDSTATE_VERSION_VMSVGA_2D    10 /* <- internal build with 2d state only */
+#define VGA_SAVEDSTATE_VERSION_VMSVGA       11
+#define VGA_SAVEDSTATE_VERSION              11
+#else
 #define VGA_SAVEDSTATE_VERSION              10
+#endif
 #define VGA_SAVEDSTATE_VERSION_WITH_PENDVHWA 10
 #define VGA_SAVEDSTATE_VERSION_INV_GCMDFIFO 8 /* <- states upto and including this version may contain invalid completed Guest Commands fifo entries */
 #define VGA_SAVEDSTATE_VERSION_INV_VHEIGHT  8 /* <- states upto and including this version may contain invalid vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] value */
diff --git a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
index b37fcd2..e7dccbb 100644
--- a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
@@ -81,6 +81,7 @@ typedef struct VBVACONTEXT
     uint32_t cViews;
     VBVAVIEW aViews[64 /* @todo SchemaDefs::MaxGuestMonitors*/];
     VBVAMOUSESHAPEINFO mouseShapeInfo;
+    bool fPaused;
 } VBVACONTEXT;
 
 
@@ -1890,6 +1891,18 @@ void VBVARaiseIrq (PVGASTATE pVGAState, uint32_t fFlags)
     PDMCritSectLeave(&pVGAState->CritSect);
 }
 
+void VBVARaiseIrqNoWait(PVGASTATE pVGAState, uint32_t fFlags)
+{
+    PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
+    PDMCritSectEnter(&pVGAState->CritSect, VERR_SEM_BUSY);
+
+    HGSMISetHostGuestFlags(pVGAState->pHGSMI, HGSMIHOSTFLAGS_IRQ | fFlags);
+    PDMDevHlpPCISetIrqNoWait(pDevIns, 0, PDM_IRQ_LEVEL_HIGH);
+
+    PDMCritSectLeave(&pVGAState->CritSect);
+}
+
+
 /*
  *
  * New VBVA uses a new interface id: #define VBE_DISPI_ID_VBOX_VIDEO         0xBE01
@@ -1905,7 +1918,7 @@ static DECLCALLBACK(void) vbvaNotifyGuest (void *pvCallback)
 {
 #if defined(VBOX_WITH_HGSMI) && (defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_VDMA) || defined(VBOX_WITH_WDDM))
     PVGASTATE pVGAState = (PVGASTATE)pvCallback;
-    VBVARaiseIrq (pVGAState, 0);
+    VBVARaiseIrqNoWait (pVGAState, 0);
 #else
     NOREF(pvCallback);
     /* Do nothing. Later the VMMDev/VGA IRQ can be used for the notification. */
@@ -2239,6 +2252,54 @@ static DECLCALLBACK(int) vbvaChannelHandler (void *pvHandler, uint16_t u16Channe
             pCaps->rc = VINF_SUCCESS;
         } break;
 #endif
+
+        case VBVA_CMDVBVA_ENABLE:
+        {
+            if (cbBuffer < sizeof (VBVAENABLE))
+            {
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            VBVAENABLE *pEnable = (VBVAENABLE *)pvBuffer;
+
+            if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE)
+            {
+                uint32_t u32Offset = pEnable->u32Offset;
+                VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost (pIns, u32Offset);
+
+                if (pVBVA)
+                    rc = vboxCmdVBVAEnable(pVGAState, pVBVA);
+                else
+                {
+                    LogRel(("Invalid VBVABUFFER offset 0x%x!!!\n",
+                         pEnable->u32Offset));
+                    rc = VERR_INVALID_PARAMETER;
+                }
+            }
+            else if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_DISABLE)
+            {
+                rc = vboxCmdVBVADisable(pVGAState);
+            }
+            else
+            {
+                LogRel(("Invalid VBVA_ENABLE flags 0x%x!!!\n", pEnable->u32Flags));
+                rc = VERR_INVALID_PARAMETER;
+            }
+
+            pEnable->i32Result = rc;
+            break;
+        }
+        case VBVA_CMDVBVA_SUBMIT:
+        {
+            rc = vboxCmdVBVACmdSubmit(pVGAState);
+            break;
+        }
+        case VBVA_CMDVBVA_FLUSH:
+        {
+            rc =vboxCmdVBVACmdFlush(pVGAState);
+            break;
+        }
         case VBVA_SCANLINE_CFG:
         {
             if (cbBuffer < sizeof (VBVASCANLINECFG))
@@ -2260,6 +2321,24 @@ static DECLCALLBACK(int) vbvaChannelHandler (void *pvHandler, uint16_t u16Channe
     return rc;
 }
 
+/* When VBVA is paused, then VGA device is allowed to work but
+ * no HGSMI etc state is changed.
+ */
+void VBVAPause(PVGASTATE pVGAState, bool fPause)
+{
+    if (!pVGAState || !pVGAState->pHGSMI)
+    {
+        return;
+    }
+
+    VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pVGAState->pHGSMI);
+
+    if (pCtx)
+    {
+        pCtx->fPaused = fPause;
+    }
+}
+
 void VBVAReset (PVGASTATE pVGAState)
 {
     if (!pVGAState || !pVGAState->pHGSMI)
@@ -2308,14 +2387,17 @@ int VBVAUpdateDisplay (PVGASTATE pVGAState)
 
     if (pCtx)
     {
-        rc = vbvaFlush (pVGAState, pCtx);
-
-        if (RT_SUCCESS (rc))
+        if (!pCtx->fPaused)
         {
-            if (!pCtx->aViews[0].pVBVA)
+            rc = vbvaFlush (pVGAState, pCtx);
+
+            if (RT_SUCCESS (rc))
             {
-                /* VBVA is not enabled for the first view, so VGA device must do updates. */
-                rc = VERR_NOT_SUPPORTED;
+                if (!pCtx->aViews[0].pVBVA)
+                {
+                    /* VBVA is not enabled for the first view, so VGA device must do updates. */
+                    rc = VERR_NOT_SUPPORTED;
+                }
             }
         }
     }
@@ -2352,6 +2434,7 @@ int VBVAInit (PVGASTATE pVGAState)
          {
              VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext (pVGAState->pHGSMI);
              pCtx->cViews = pVGAState->cMonitors;
+             pCtx->fPaused = true;
          }
      }
 
@@ -2375,3 +2458,39 @@ void VBVADestroy (PVGASTATE pVGAState)
     HGSMIDestroy (pVGAState->pHGSMI);
     pVGAState->pHGSMI = NULL;
 }
+
+int VBVAGetScreenInfo(PVGASTATE pVGAState, unsigned uScreenId, struct VBVAINFOSCREEN *pScreen, void **ppvVram)
+{
+    PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
+    PHGSMIINSTANCE pIns = pVGAState->pHGSMI;
+    VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext (pIns);
+    int rc = PDMCritSectEnter(&pVGAState->CritSect, VERR_SEM_BUSY);
+    if (RT_SUCCESS(rc))
+    {
+        if (uScreenId < pCtx->cViews)
+        {
+            VBVAVIEW *pView = &pCtx->aViews[uScreenId];
+            if (pView->pVBVA)
+            {
+                uint8_t *pu8VRAM = pVGAState->vram_ptrR3 + pView->view.u32ViewOffset;
+                *pScreen = pView->screen;
+                *ppvVram = (void*)pu8VRAM;
+                rc = VINF_SUCCESS;
+            }
+            else
+            {
+                /* pretend disabled */
+                memset(pScreen, 0, sizeof (*pScreen));
+                pScreen->u16Flags = VBVA_SCREEN_F_DISABLED;
+                pScreen->u32ViewIndex = uScreenId;
+                *ppvVram = NULL;
+                rc = VINF_SUCCESS;
+            }
+        }
+        else
+            rc = VERR_INVALID_PARAMETER;
+
+        PDMCritSectLeave(&pVGAState->CritSect);
+    }
+    return rc;
+}
diff --git a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
index 389e3d3..bdec54a 100644
--- a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
@@ -25,6 +25,18 @@
 #include "HGSMI/SHGSMIHost.h"
 #include "HGSMI/HGSMIHostHlp.h"
 
+#include <VBox/VBoxVideo3D.h>
+
+#ifdef DEBUG_misha
+#define WARN_BP() do { AssertFailed(); } while (0)
+#else
+#define WARN_BP() do { } while (0)
+#endif
+#define WARN(_msg) do { \
+        LogRel(_msg); \
+        WARN_BP(); \
+    } while (0)
+
 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
 typedef enum
 {
@@ -78,10 +90,63 @@ typedef struct VBOXVDMAPIPE_CMD_POOL
 } VBOXVDMAPIPE_CMD_POOL, *PVBOXVDMAPIPE_CMD_POOL;
 #endif
 
+
+/* state transformations:
+ *
+ *   submitter   |    processor
+ *   STOPPED
+ *      |
+ *      |
+ *      >
+ *  LISTENING   --->  PROCESSING
+ *      ^               _/
+ *      |             _/
+ *      |           _/
+ *      |         _/
+ *      |       _/
+ *      |     _/
+ *      |    /
+ *      <   >
+ *     PAUSED
+ *
+ *  */
+#define VBVAEXHOSTCONTEXT_STATE_STOPPED        0
+#define VBVAEXHOSTCONTEXT_STATE_LISTENING      1
+#define VBVAEXHOSTCONTEXT_STATE_PROCESSING     2
+#define VBVAEXHOSTCONTEXT_STATE_PAUSED         3
+
+typedef struct VBVAEXHOSTCONTEXT
+{
+    VBVABUFFER *pVBVA;
+    uint32_t cbCurData;
+    volatile uint32_t u32State;
+    volatile uint32_t u32Pause;
+    volatile uint32_t u32cOtherCommands;
+} VBVAEXHOSTCONTEXT;
+
+/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
+ * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently.
+ * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands
+ * see mor edetailed comments in headers for function definitions */
+static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva);
+static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
+
+/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
+ * can be called concurrently with istelf as well as with other VBoxVBVAEx** functions except Init/Start/Term aparently */
+static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva);
+
+static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);
+static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA);
+static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva);
+static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva);
+static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM);
+static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version);
+
 typedef struct VBOXVDMAHOST
 {
     PHGSMIINSTANCE pHgsmi;
     PVGASTATE pVGAState;
+    VBVAEXHOSTCONTEXT CmdVbva;
 #ifdef VBOX_VDMA_WITH_WATCHDOG
     PTMTIMERR3 WatchDogTimer;
 #endif
@@ -205,6 +270,99 @@ static int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd
     return rc;
 }
 
+static void vboxVDMACrCmdNotifyPerform(struct VBOXVDMAHOST *pVdma)
+{
+    PVGASTATE pVGAState = pVdma->pVGAState;
+    pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv);
+}
+
+/*
+ * @returns
+ *
+ */
+static int vboxVDMACrCmdPreprocess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
+{
+    if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
+        return VINF_EOF;
+
+    PVBOXCMDVBVA_HDR pCmd = (PVBOXCMDVBVA_HDR)pu8Cmd;
+
+    /* check if the command is cancelled */
+    if (!ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_IN_PROGRESS, VBOXCMDVBVA_STATE_SUBMITTED))
+    {
+        Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
+        return VINF_EOF;
+    }
+
+    /* come commands can be handled right away? */
+    switch (pCmd->u8OpCode)
+    {
+        case VBOXCMDVBVA_OPTYPE_NOPCMD:
+            pCmd->i8Result = 0;
+            return VINF_EOF;
+        default:
+            return VINF_SUCCESS;
+    }
+}
+
+static DECLCALLBACK(int) vboxVDMACrCmdCltCmdGet(HVBOXCRCMDCLT hClt, PVBOXCMDVBVA_HDR *ppNextCmd, uint32_t *pcbNextCmd)
+{
+    struct VBOXVDMAHOST *pVdma = hClt;
+
+    VBoxVBVAExHPCmdCheckRelease(&pVdma->CmdVbva);
+
+    uint32_t cbCmd;
+    uint8_t *pu8Cmd;
+
+    for(;;)
+    {
+        int rc = VBoxVBVAExHPCmdGet(&pVdma->CmdVbva, &pu8Cmd, &cbCmd);
+        switch (rc)
+        {
+            case VINF_SUCCESS:
+            {
+                rc = vboxVDMACrCmdPreprocess(pVdma, pu8Cmd, cbCmd);
+                switch (rc)
+                {
+                    case VINF_SUCCESS:
+                        *ppNextCmd = (PVBOXCMDVBVA_HDR)pu8Cmd;
+                        *pcbNextCmd = cbCmd;
+                        return VINF_SUCCESS;
+                    case VINF_EOF:
+                        continue;
+                    default:
+                        Assert(!RT_FAILURE(rc));
+                        return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR;
+                }
+                break;
+            }
+            case VINF_EOF:
+                return VINF_EOF;
+            case VINF_PERMISSION_DENIED:
+                /* processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed */
+                return VINF_EOF;
+            case VINF_INTERRUPTED:
+                /* command processing was interrupted, processor state remains set. client can process any commands */
+                vboxVDMACrCmdNotifyPerform(pVdma);
+                return VINF_EOF;
+            default:
+                Assert(!RT_FAILURE(rc));
+                return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR;
+        }
+    }
+
+    WARN(("Warning: vboxVDMACrCmdCltCmdGet unexpected state\n"));
+    return VERR_INTERNAL_ERROR;
+}
+
+static DECLCALLBACK(int) vboxVDMACrCmdCltDmGet(HVBOXCRCMDCLT hClt, uint32_t idScreen, struct VBVAINFOSCREEN *pScreen, void **ppvVram)
+{
+    struct VBOXVDMAHOST *pVdma = hClt;
+    PVGASTATE pVGAState = pVdma->pVGAState;
+
+    return VBVAGetScreenInfo(pVGAState, idScreen, pScreen, ppvVram);
+}
+
 static int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma)
 {
     PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd;
@@ -212,9 +370,14 @@ static int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma)
                                                                           sizeof (*pCmd));
     if (pCmd)
     {
+        VBOXCRCMD_CLTINFO CltInfo;
+        CltInfo.hClient = pVdma;
+        CltInfo.pfnCmdGet = vboxVDMACrCmdCltCmdGet;
+        CltInfo.pfnDmGet = vboxVDMACrCmdCltDmGet;
         PVGASTATE pVGAState = pVdma->pVGAState;
         pCmd->pvVRamBase = pVGAState->vram_ptrR3;
         pCmd->cbVRam = pVGAState->vram_size;
+        pCmd->pCrCmdClientInfo = &CltInfo;
         int rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd));
         Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
         if (RT_SUCCESS(rc))
@@ -1159,6 +1322,7 @@ int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements)
 # endif
 #endif
                 pVGAState->pVdma = pVdma;
+                VBoxVBVAExHSInit(&pVdma->CmdVbva);
 #ifdef VBOX_WITH_CRHGSMI
                 int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
 #endif
@@ -1185,6 +1349,7 @@ int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma)
     /* @todo: implement*/
     AssertBreakpoint();
 #endif
+    VBoxVBVAExHSTerm(&pVdma->CmdVbva);
     RTMemFree(pVdma);
     return VINF_SUCCESS;
 }
@@ -1378,3 +1543,400 @@ void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t
     AssertRC(tmpRc);
 #endif
 }
+
+/**/
+static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED);
+
+    uint32_t oldState;
+    if (!ASMAtomicReadU32(&pCmdVbva->u32Pause))
+    {
+        if (ASMAtomicCmpXchgExU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING, &oldState))
+            return VINF_SUCCESS;
+        return oldState == VBVAEXHOSTCONTEXT_STATE_PROCESSING ? VERR_SEM_BUSY : VERR_INVALID_STATE;
+    }
+    return VERR_INVALID_STATE;
+}
+
+static bool vboxVBVAExHPCheckPause(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    if (!ASMAtomicReadU32(&pCmdVbva->u32Pause))
+        return false;
+
+    ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED);
+    return true;
+}
+
+static bool vboxVBVAExHPCheckOtherCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    return !!ASMAtomicUoReadU32(&pCmdVbva->u32cOtherCommands);
+}
+
+static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    if (!vboxVBVAExHPCheckPause(pCmdVbva))
+        ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
+    else
+        ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED);
+}
+
+static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING);
+}
+
+static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING);
+}
+
+static bool vboxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    if (!pCmdVbva->cbCurData)
+        return false;
+
+    VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
+    pVBVA->off32Data = (pVBVA->off32Data + pCmdVbva->cbCurData) % pVBVA->cbData;
+
+    pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords);
+
+    pCmdVbva->cbCurData = 0;
+
+    return true;
+}
+
+static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
+
+    uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
+    uint32_t indexRecordFree = pVBVA->indexRecordFree;
+
+    Log(("first = %d, free = %d\n",
+                   indexRecordFirst, indexRecordFree));
+
+    if (indexRecordFirst == indexRecordFree)
+    {
+        /* No records to process. Return without assigning output variables. */
+        return VINF_EOF;
+    }
+
+    uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord);
+
+    /* A new record need to be processed. */
+    if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL)
+    {
+        /* the record is being recorded, try again */
+        return VINF_TRY_AGAIN;
+    }
+
+    uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;
+
+    if (!cbRecord)
+    {
+        /* the record is being recorded, try again */
+        return VINF_TRY_AGAIN;
+    }
+
+    /* we should not get partial commands here actually */
+    Assert(cbRecord);
+
+    /* The size of largest contiguous chunk in the ring biffer. */
+    uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data;
+
+    /* The pointer to data in the ring buffer. */
+    uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data];
+
+    /* Fetch or point the data. */
+    if (u32BytesTillBoundary >= cbRecord)
+    {
+        /* The command does not cross buffer boundary. Return address in the buffer. */
+        *ppCmd = pSrc;
+        *pcbCmd = cbRecord;
+        pCmdVbva->cbCurData = cbRecord;
+        return VINF_SUCCESS;
+    }
+
+    LogRel(("CmdVbva: cross-bound writes unsupported\n"));
+    return VERR_INVALID_STATE;
+}
+
+/* Resumes command processing
+ * @returns - same as VBoxVBVAExHSCheckCommands
+ */
+static int vboxVBVAExHSResume(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED);
+
+    ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
+
+    return VBoxVBVAExHSCheckCommands(pCmdVbva);
+}
+
+/* pause the command processing. this will make the processor stop the command processing and release the processing state
+ * to resume the command processing the vboxVBVAExHSResume must be called */
+static void vboxVBVAExHSPause(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED);
+
+    Assert(!pCmdVbva->u32Pause);
+
+    ASMAtomicWriteU32(&pCmdVbva->u32Pause, 1);
+
+    for(;;)
+    {
+        if (ASMAtomicCmpXchgU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED, VBVAEXHOSTCONTEXT_STATE_LISTENING))
+            break;
+
+        if (ASMAtomicReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_PAUSED)
+            break;
+
+        RTThreadSleep(2);
+    }
+
+    pCmdVbva->u32Pause = 0;
+}
+
+/* releases (completed) the command previously acquired by VBoxVBVAExHCmdGet
+ * for convenience can be called if no command is currently acquired
+ * in that case it will do nothing and return false.
+ * if the completion notification is needed returns true. */
+static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    return vboxVBVAExHPCmdCheckRelease(pCmdVbva);
+}
+
+/*
+ * @returns
+ *  VINF_SUCCESS - new command is obtained
+ *  VINF_EOF - processor has completed all commands and release the processing state, only VBoxVBVAExHS*** calls are now allowed
+ *  VINF_PERMISSION_DENIED - processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed
+ *  VINF_INTERRUPTED - command processing was interrupted, processor state remains set. client can process any commands,
+ *                     and call VBoxVBVAExHPCmdGet again for further processing
+ *  VERR_** - error happened, most likely guest corrupted VBVA data
+ *
+ */
+static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
+{
+    Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
+
+    for(;;)
+    {
+        if (vboxVBVAExHPCheckPause(pCmdVbva))
+            return VINF_PERMISSION_DENIED;
+        if (vboxVBVAExHPCheckOtherCommands(pCmdVbva))
+            return VINF_INTERRUPTED;
+
+        int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd);
+        switch (rc)
+        {
+            case VINF_SUCCESS:
+                return VINF_SUCCESS;
+            case VINF_EOF:
+                vboxVBVAExHPHgEventClear(pCmdVbva);
+                vboxVBVAExHPProcessorRelease(pCmdVbva);
+                /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
+                 * 1. we check the queue -> and it is empty
+                 * 2. submitter adds command to the queue
+                 * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification
+                 * 4. we clear the "processing" state
+                 * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
+                 * 6. if the queue appears to be not-empty set the "processing" state back to "true"
+                 **/
+                if (VBoxVBVAExHSCheckCommands(pCmdVbva) == VINF_SUCCESS)
+                    continue;
+                return VINF_EOF;
+            case VINF_TRY_AGAIN:
+                RTThreadSleep(1);
+                continue;
+            default:
+                /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */
+                if (RT_FAILURE(rc))
+                    return rc;
+
+                WARN(("Warning: vboxVBVAExHCmdGet returned unexpected success status %d\n", rc));
+                return VERR_INTERNAL_ERROR;
+        }
+    }
+
+    WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n"));
+    return VERR_INTERNAL_ERROR;
+}
+
+/* Checks whether the new commands are ready for processing
+ * @returns
+ *   VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread)
+ *   VINF_EOF - no commands in a queue
+ *   VINF_ALREADY_INITIALIZED - another thread already processing the commands
+ *   VERR_INVALID_STATE - the VBVA is paused or pausing */
+static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED)
+        return VINF_EOF;
+
+    int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
+    if (RT_SUCCESS(rc))
+    {
+        /* we are the processor now */
+        VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
+
+        uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
+        uint32_t indexRecordFree = pVBVA->indexRecordFree;
+
+        if (indexRecordFirst != indexRecordFree)
+        {
+            vboxVBVAExHPHgEventSet(pCmdVbva);
+            return VINF_SUCCESS;
+        }
+
+        vboxVBVAExHPProcessorRelease(pCmdVbva);
+        return VINF_EOF;
+    }
+    if (rc == VERR_SEM_BUSY)
+        return VINF_ALREADY_INITIALIZED;
+    Assert(rc == VERR_INVALID_STATE);
+    return VERR_INVALID_STATE;
+}
+
+static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    memset(pCmdVbva, 0, sizeof (*pCmdVbva));
+}
+
+static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA)
+{
+    if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED)
+        return VINF_ALREADY_INITIALIZED;
+
+    pCmdVbva->pVBVA = pVBVA;
+    pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
+    ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
+    return VINF_SUCCESS;
+}
+
+static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED)
+        return VINF_SUCCESS;
+
+    /* ensure no commands pending and one tries to submit them */
+    int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
+    if (RT_SUCCESS(rc))
+    {
+        pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
+        memset(pCmdVbva, 0, sizeof (*pCmdVbva));
+        return VINF_SUCCESS;
+    }
+    return VERR_INVALID_STATE;
+}
+
+static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva)
+{
+    /* ensure the processor is stopped */
+    if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED)
+        return;
+
+    /* ensure no one tries to submit the command */
+    vboxVBVAExHSPause(pCmdVbva);
+    pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
+    memset(pCmdVbva, 0, sizeof (*pCmdVbva));
+}
+
+/* Saves state
+ * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
+ */
+static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
+{
+    int rc;
+    if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED)
+    {
+        vboxVBVAExHSPause(pCmdVbva);
+        rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase));
+        AssertRCReturn(rc, rc);
+        return vboxVBVAExHSResume(pCmdVbva);
+    }
+
+    rc = SSMR3PutU32(pSSM, 0xffffffff);
+    AssertRCReturn(rc, rc);
+
+    return VINF_EOF;
+}
+
+/* Loads state
+ * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
+ */
+static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+    uint32_t u32;
+    int rc = SSMR3GetU32(pSSM, &u32);
+    AssertRCReturn(rc, rc);
+    if (u32 != 0xffffffff)
+    {
+        VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32;
+        rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA);
+        AssertRCReturn(rc, rc);
+        return VBoxVBVAExHSCheckCommands(pCmdVbva);
+    }
+
+    return VINF_EOF;
+}
+
+int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA)
+{
+    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
+    return VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA);
+}
+
+int vboxCmdVBVADisable(PVGASTATE pVGAState)
+{
+    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
+    return VBoxVBVAExHSDisable(&pVdma->CmdVbva);
+}
+
+static int vboxCmdVBVACmdSubmitPerform(PVGASTATE pVGAState)
+{
+    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
+    int rc = VBoxVBVAExHSCheckCommands(&pVdma->CmdVbva);
+    switch (rc)
+    {
+        case VINF_SUCCESS:
+            return pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv);
+        case VINF_ALREADY_INITIALIZED:
+        case VINF_EOF:
+        case VERR_INVALID_STATE:
+            return VINF_SUCCESS;
+        default:
+            Assert(!RT_FAILURE(rc));
+            return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR;
+    }
+}
+
+int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState)
+{
+    return vboxCmdVBVACmdSubmitPerform(pVGAState);
+}
+
+int vboxCmdVBVACmdFlush(PVGASTATE pVGAState)
+{
+    return vboxCmdVBVACmdSubmitPerform(pVGAState);
+}
+
+void vboxCmdVBVACmdTimer(PVGASTATE pVGAState)
+{
+    vboxCmdVBVACmdSubmitPerform(pVGAState);
+}
diff --git a/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp b/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp
index b28efa0..c0d2c0b 100644
--- a/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp
+++ b/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp
@@ -1817,7 +1817,10 @@ int HGSMICompleteGuestCommand(PHGSMIINSTANCE pIns,
     LogFlowFunc(("pIns = %p, pvMem = %p\n", pIns, pvMem));
 
     int rc = VINF_SUCCESS;
-    HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (&pIns->hostHeap, pvMem);
+
+    HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvMem);
+    HGSMIOFFSET offBuffer = HGSMIPointerToOffset(&pIns->area, pHeader);
+
     Assert(offBuffer != HGSMIOFFSET_VOID);
     if (offBuffer != HGSMIOFFSET_VOID)
     {
diff --git a/src/VBox/Devices/Graphics/vmsvga/svga3d_caps.h b/src/VBox/Devices/Graphics/vmsvga/svga3d_caps.h
new file mode 100644
index 0000000..0f90699
--- /dev/null
+++ b/src/VBox/Devices/Graphics/vmsvga/svga3d_caps.h
@@ -0,0 +1,11 @@
+/*
+ * VMware SVGA II 3D capability definitions
+ */
+
+#ifndef _SVGA3D_CAPS_H_
+#define _SVGA3D_CAPS_H_
+
+
+
+#endif /* _SVGA3D_CAPS_H_ */
+
diff --git a/src/VBox/Devices/Graphics/vmsvga/svga3d_reg.h b/src/VBox/Devices/Graphics/vmsvga/svga3d_reg.h
new file mode 100644
index 0000000..3991d38
--- /dev/null
+++ b/src/VBox/Devices/Graphics/vmsvga/svga3d_reg.h
@@ -0,0 +1,56 @@
+/*
+ * VMware SVGA II 3D definitions
+ */
+
+#ifndef _SVGA3D_REG_H_
+#define _SVGA3D_REG_H_
+
+#define SVGA_3D_CMD_LEGACY_BASE            1000
+#define SVGA_3D_CMD_BASE                   1040
+
+#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0
+#define SVGA_3D_CMD_SURFACE_DESTROY        SVGA_3D_CMD_BASE + 1
+#define SVGA_3D_CMD_SURFACE_COPY           SVGA_3D_CMD_BASE + 2
+#define SVGA_3D_CMD_SURFACE_STRETCHBLT     SVGA_3D_CMD_BASE + 3
+#define SVGA_3D_CMD_SURFACE_DMA            SVGA_3D_CMD_BASE + 4
+#define SVGA_3D_CMD_CONTEXT_DEFINE         SVGA_3D_CMD_BASE + 5
+#define SVGA_3D_CMD_CONTEXT_DESTROY        SVGA_3D_CMD_BASE + 6
+#define SVGA_3D_CMD_SETTRANSFORM           SVGA_3D_CMD_BASE + 7
+#define SVGA_3D_CMD_SETZRANGE              SVGA_3D_CMD_BASE + 8
+#define SVGA_3D_CMD_SETRENDERSTATE         SVGA_3D_CMD_BASE + 9
+#define SVGA_3D_CMD_SETRENDERTARGET        SVGA_3D_CMD_BASE + 10
+#define SVGA_3D_CMD_SETTEXTURESTATE        SVGA_3D_CMD_BASE + 11
+#define SVGA_3D_CMD_SETMATERIAL            SVGA_3D_CMD_BASE + 12
+#define SVGA_3D_CMD_SETLIGHTDATA           SVGA_3D_CMD_BASE + 13
+#define SVGA_3D_CMD_SETLIGHTENABLED        SVGA_3D_CMD_BASE + 14
+#define SVGA_3D_CMD_SETVIEWPORT            SVGA_3D_CMD_BASE + 15
+#define SVGA_3D_CMD_SETCLIPPLANE           SVGA_3D_CMD_BASE + 16
+#define SVGA_3D_CMD_CLEAR                  SVGA_3D_CMD_BASE + 17
+#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18
+#define SVGA_3D_CMD_SHADER_DEFINE          SVGA_3D_CMD_BASE + 19
+#define SVGA_3D_CMD_SHADER_DESTROY         SVGA_3D_CMD_BASE + 20
+#define SVGA_3D_CMD_SET_SHADER             SVGA_3D_CMD_BASE + 21
+#define SVGA_3D_CMD_SET_SHADER_CONST       SVGA_3D_CMD_BASE + 22
+#define SVGA_3D_CMD_DRAW_PRIMITIVES        SVGA_3D_CMD_BASE + 23
+#define SVGA_3D_CMD_SETSCISSORRECT         SVGA_3D_CMD_BASE + 24
+#define SVGA_3D_CMD_BEGIN_QUERY            SVGA_3D_CMD_BASE + 25
+#define SVGA_3D_CMD_END_QUERY              SVGA_3D_CMD_BASE + 26
+#define SVGA_3D_CMD_WAIT_FOR_QUERY         SVGA_3D_CMD_BASE + 27
+#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28
+#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
+#define SVGA_3D_CMD_SURFACE_DEFINE_V2      SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_GENERATE_MIPMAPS       SVGA_3D_CMD_BASE + 31
+#define SVGA_3D_CMD_ACTIVATE_SURFACE       SVGA_3D_CMD_BASE + 40
+#define SVGA_3D_CMD_DEACTIVATE_SURFACE     SVGA_3D_CMD_BASE + 41
+#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 42
+
+#define SVGA_3D_CMD_FUTURE_MAX             2000
+
+typedef enum
+{
+   SVGA3D_WRITE_HOST_VRAM        = 1,
+   SVGA3D_READ_HOST_VRAM         = 2
+} SVGA3dTransferType;
+
+#endif /* _SVGA3D_REG_H_ */
+
diff --git a/src/VBox/Devices/Graphics/vmsvga/svga_escape.h b/src/VBox/Devices/Graphics/vmsvga/svga_escape.h
new file mode 100644
index 0000000..b96705c
--- /dev/null
+++ b/src/VBox/Devices/Graphics/vmsvga/svga_escape.h
@@ -0,0 +1,11 @@
+/*
+ * SVGA escape commands
+ */
+
+#ifndef _SVGA_ESCAPE_H_
+#define _SVGA_ESCAPE_H_
+
+#define SVGA_ESCAPE_NSID_VMWARE 0x00000000
+
+
+#endif /* _SVGA_ESCAPE_H_ */
diff --git a/src/VBox/Devices/Graphics/vmsvga/svga_overlay.h b/src/VBox/Devices/Graphics/vmsvga/svga_overlay.h
new file mode 100644
index 0000000..08aae92
--- /dev/null
+++ b/src/VBox/Devices/Graphics/vmsvga/svga_overlay.h
@@ -0,0 +1,32 @@
+/*
+ * VMware SVGA video overlay definitions
+ */
+
+#ifndef _SVGA_OVERLAY_H_
+#define _SVGA_OVERLAY_H_
+
+#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS    0x00020001
+#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH       0x00020002
+
+typedef struct SVGAEscapeVideoSetRegs
+{
+   struct
+   {
+      uint32_t cmdType;
+      uint32_t streamId;
+   } header;
+
+   struct
+   {
+      uint32_t registerId;
+      uint32_t value;
+   } items[1];
+} SVGAEscapeVideoSetRegs;
+
+typedef struct SVGAEscapeVideoFlush
+{
+   uint32_t cmdType;
+   uint32_t streamId;
+} SVGAEscapeVideoFlush;
+
+#endif /* _SVGA_OVERLAY_H_ */
diff --git a/src/VBox/Devices/Graphics/vmsvga/svga_reg.h b/src/VBox/Devices/Graphics/vmsvga/svga_reg.h
new file mode 100644
index 0000000..6a1c69b
--- /dev/null
+++ b/src/VBox/Devices/Graphics/vmsvga/svga_reg.h
@@ -0,0 +1,318 @@
+/*
+ * VMware SVGA II hardware definitions
+ */
+
+#ifndef _SVGA_REG_H_
+#define _SVGA_REG_H_
+
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_SVGA2      0x0405
+
+#define SVGA_IRQFLAG_ANY_FENCE            0x1
+#define SVGA_IRQFLAG_FIFO_PROGRESS        0x2
+#define SVGA_IRQFLAG_FENCE_GOAL           0x4
+
+#define SVGA_MAX_PSEUDOCOLOR_DEPTH      8
+#define SVGA_MAX_PSEUDOCOLORS           (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
+#define SVGA_NUM_PALETTE_REGS           (3 * SVGA_MAX_PSEUDOCOLORS)
+
+#define SVGA_MAGIC         0x900000UL
+#define SVGA_MAKE_ID(ver)  (SVGA_MAGIC << 8 | (ver))
+
+#define SVGA_VERSION_2     2
+#define SVGA_ID_2          SVGA_MAKE_ID(SVGA_VERSION_2)
+
+#define SVGA_VERSION_1     1
+#define SVGA_ID_1          SVGA_MAKE_ID(SVGA_VERSION_1)
+
+#define SVGA_VERSION_0     0
+#define SVGA_ID_0          SVGA_MAKE_ID(SVGA_VERSION_0)
+
+#define SVGA_ID_INVALID    0xFFFFFFFF
+
+#define SVGA_INDEX_PORT         0x0
+#define SVGA_VALUE_PORT         0x1
+#define SVGA_BIOS_PORT          0x2
+#define SVGA_IRQSTATUS_PORT     0x8
+
+#define SVGA_IRQFLAG_ANY_FENCE            0x1
+#define SVGA_IRQFLAG_FIFO_PROGRESS        0x2
+#define SVGA_IRQFLAG_FENCE_GOAL           0x4
+
+enum
+{
+   SVGA_REG_ID = 0,
+   SVGA_REG_ENABLE = 1,
+   SVGA_REG_WIDTH = 2,
+   SVGA_REG_HEIGHT = 3,
+   SVGA_REG_MAX_WIDTH = 4,
+   SVGA_REG_MAX_HEIGHT = 5,
+   SVGA_REG_DEPTH = 6,
+   SVGA_REG_BITS_PER_PIXEL = 7,
+   SVGA_REG_PSEUDOCOLOR = 8,
+   SVGA_REG_RED_MASK = 9,
+   SVGA_REG_GREEN_MASK = 10,
+   SVGA_REG_BLUE_MASK = 11,
+   SVGA_REG_BYTES_PER_LINE = 12,
+   SVGA_REG_FB_START = 13,
+   SVGA_REG_FB_OFFSET = 14,
+   SVGA_REG_VRAM_SIZE = 15,
+   SVGA_REG_FB_SIZE = 16,
+   SVGA_REG_CAPABILITIES = 17,
+   SVGA_REG_MEM_START = 18,
+   SVGA_REG_MEM_SIZE = 19,
+   SVGA_REG_CONFIG_DONE = 20,
+   SVGA_REG_SYNC = 21,
+   SVGA_REG_BUSY = 22,
+   SVGA_REG_GUEST_ID = 23,
+   SVGA_REG_CURSOR_ID = 24,
+   SVGA_REG_CURSOR_X = 25,
+   SVGA_REG_CURSOR_Y = 26,
+   SVGA_REG_CURSOR_ON = 27,
+   SVGA_REG_HOST_BITS_PER_PIXEL = 28,
+   SVGA_REG_SCRATCH_SIZE = 29,
+   SVGA_REG_MEM_REGS = 30,
+   SVGA_REG_NUM_DISPLAYS = 31,
+   SVGA_REG_PITCHLOCK = 32,
+   SVGA_REG_IRQMASK = 33,
+   SVGA_REG_NUM_GUEST_DISPLAYS = 34,
+   SVGA_REG_DISPLAY_ID = 35,
+   SVGA_REG_DISPLAY_IS_PRIMARY = 36,
+   SVGA_REG_DISPLAY_POSITION_X = 37,
+   SVGA_REG_DISPLAY_POSITION_Y = 38,
+   SVGA_REG_DISPLAY_WIDTH = 39,
+   SVGA_REG_DISPLAY_HEIGHT = 40,
+   SVGA_REG_GMR_ID = 41,
+   SVGA_REG_GMR_DESCRIPTOR = 42,
+   SVGA_REG_GMR_MAX_IDS = 43,
+   SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
+   SVGA_REG_TRACES = 45,
+   SVGA_REG_GMRS_MAX_PAGES = 46,
+   SVGA_REG_MEMORY_SIZE = 47,
+   SVGA_REG_TOP = 48,
+   SVGA_PALETTE_BASE = 1024,
+   SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
+};
+
+enum
+{
+   SVGA_FIFO_MIN = 0,
+   SVGA_FIFO_MAX,
+   SVGA_FIFO_NEXT_CMD,
+   SVGA_FIFO_STOP,
+   SVGA_FIFO_CAPABILITIES = 4,
+   SVGA_FIFO_FLAGS,
+   SVGA_FIFO_FENCE,
+   SVGA_FIFO_3D_HWVERSION,
+   SVGA_FIFO_PITCHLOCK,
+   SVGA_FIFO_CURSOR_ON,
+   SVGA_FIFO_CURSOR_X,
+   SVGA_FIFO_CURSOR_Y,
+   SVGA_FIFO_CURSOR_COUNT,
+   SVGA_FIFO_CURSOR_LAST_UPDATED,
+   SVGA_FIFO_RESERVED,
+   SVGA_FIFO_CURSOR_SCREEN_ID,
+   SVGA_FIFO_DEAD,
+   SVGA_FIFO_3D_HWVERSION_REVISED,
+   SVGA_FIFO_3D_CAPS      = 32,
+   SVGA_FIFO_3D_CAPS_LAST = 32 + 255,
+   SVGA_FIFO_GUEST_3D_HWVERSION,
+   SVGA_FIFO_FENCE_GOAL,
+   SVGA_FIFO_BUSY,
+   SVGA_FIFO_NUM_REGS
+};
+
+typedef enum
+{
+   SVGA_CMD_INVALID_CMD           = 0,
+   SVGA_CMD_UPDATE                = 1,
+   SVGA_CMD_RECT_COPY             = 3,
+   SVGA_CMD_DEFINE_CURSOR         = 19,
+   SVGA_CMD_DEFINE_ALPHA_CURSOR   = 22,
+   SVGA_CMD_UPDATE_VERBOSE        = 25,
+   SVGA_CMD_FRONT_ROP_FILL        = 29,
+   SVGA_CMD_FENCE                 = 30,
+   SVGA_CMD_ESCAPE                = 33,
+   SVGA_CMD_DEFINE_SCREEN         = 34,
+   SVGA_CMD_DESTROY_SCREEN        = 35,
+   SVGA_CMD_DEFINE_GMRFB          = 36,
+   SVGA_CMD_BLIT_GMRFB_TO_SCREEN  = 37,
+   SVGA_CMD_BLIT_SCREEN_TO_GMRFB  = 38,
+   SVGA_CMD_ANNOTATION_FILL       = 39,
+   SVGA_CMD_ANNOTATION_COPY       = 40,
+   SVGA_CMD_DEFINE_GMR2           = 41,
+   SVGA_CMD_REMAP_GMR2            = 42,
+   SVGA_CMD_MAX
+} SVGAFifoCmdId;
+
+typedef struct SVGAColorBGRX
+{
+   union
+   {
+      struct
+      {
+         uint32_t b : 8;
+         uint32_t g : 8;
+         uint32_t r : 8;
+         uint32_t x : 8;
+      } s;
+
+      uint32_t value;
+   };
+} SVGAColorBGRX;
+
+typedef struct SVGASignedPoint
+{
+   int32_t  x;
+   int32_t  y;
+} SVGASignedPoint;
+
+#define SVGA_CAP_NONE               0x00000000
+#define SVGA_CAP_RECT_COPY          0x00000002
+#define SVGA_CAP_CURSOR             0x00000020
+#define SVGA_CAP_CURSOR_BYPASS      0x00000040
+#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080
+#define SVGA_CAP_8BIT_EMULATION     0x00000100
+#define SVGA_CAP_ALPHA_CURSOR       0x00000200
+#define SVGA_CAP_3D                 0x00004000
+#define SVGA_CAP_EXTENDED_FIFO      0x00008000
+#define SVGA_CAP_MULTIMON           0x00010000
+#define SVGA_CAP_PITCHLOCK          0x00020000
+#define SVGA_CAP_IRQMASK            0x00040000
+#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000
+#define SVGA_CAP_GMR                0x00100000
+#define SVGA_CAP_TRACES             0x00200000
+#define SVGA_CAP_GMR2               0x00400000
+#define SVGA_CAP_SCREEN_OBJECT_2    0x00800000
+
+#define SVGA_GMR_NULL         ((uint32_t) -1)
+#define SVGA_GMR_FRAMEBUFFER  ((uint32_t) -2)
+
+typedef struct SVGAGuestPtr
+{
+   uint32_t gmrId;
+   uint32_t offset;
+} SVGAGuestPtr;
+
+typedef struct SVGAGMRImageFormat
+{
+   union
+   {
+      struct
+      {
+         uint32_t bitsPerPixel : 8;
+         uint32_t colorDepth   : 8;
+         uint32_t reserved     : 16;
+      } s;
+
+      uint32_t value;
+   };
+} SVGAGMRImageFormat;
+
+typedef struct SVGAGuestImage
+{
+   SVGAGuestPtr         ptr;
+   uint32_t pitch;
+} SVGAGuestImage;
+
+#define SVGA_SCREEN_MUST_BE_SET     (1 << 0)
+#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET
+#define SVGA_SCREEN_IS_PRIMARY      (1 << 1)
+#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2)
+#define SVGA_SCREEN_DEACTIVATE  (1 << 3)
+#define SVGA_SCREEN_BLANKING (1 << 4)
+
+typedef struct SVGAScreenObject
+{
+   uint32_t structSize;
+   uint32_t id;
+   uint32_t flags;
+   struct
+   {
+      uint32_t width;
+      uint32_t height;
+   } size;
+   struct
+   {
+      int32_t x;
+      int32_t y;
+   } root;
+   SVGAGuestImage backingStore;
+   uint32_t cloneCount;
+} SVGAScreenObject;
+
+typedef struct
+{
+   uint32_t screenId;
+} SVGAFifoCmdDestroyScreen;
+
+typedef struct
+{
+   uint32_t x;
+   uint32_t y;
+   uint32_t width;
+   uint32_t height;
+} SVGAFifoCmdUpdate;
+
+typedef struct
+{
+   uint32_t fence;
+} SVGAFifoCmdFence;
+
+typedef struct
+{
+   uint32_t nsid;
+   uint32_t size;
+} SVGAFifoCmdEscape;
+
+typedef struct
+{
+   uint32_t id;
+   uint32_t hotspotX;
+   uint32_t hotspotY;
+   uint32_t width;
+   uint32_t height;
+   uint32_t andMaskDepth;
+   uint32_t xorMaskDepth;
+} SVGAFifoCmdDefineCursor;
+
+typedef struct
+{
+   uint32_t id;
+   uint32_t hotspotX;
+   uint32_t hotspotY;
+   uint32_t width;
+   uint32_t height;
+} SVGAFifoCmdDefineAlphaCursor;
+
+typedef struct
+{
+   SVGAScreenObject screen;
+} SVGAFifoCmdDefineScreen;
+
+typedef struct
+{
+   SVGAColorBGRX  color;
+} SVGAFifoCmdAnnotationFill;
+
+typedef struct
+{
+   SVGASignedPoint  srcOrigin;
+   uint32_t           srcScreenId;
+} SVGAFifoCmdAnnotationCopy;
+
+#define SVGA_FIFO_CAP_NONE                  0
+#define SVGA_FIFO_CAP_FENCE             (1<<0)
+#define SVGA_FIFO_CAP_ACCELFRONT        (1<<1)
+#define SVGA_FIFO_CAP_PITCHLOCK         (1<<2)
+#define SVGA_FIFO_CAP_VIDEO             (1<<3)
+#define SVGA_FIFO_CAP_CURSOR_BYPASS_3   (1<<4)
+#define SVGA_FIFO_CAP_ESCAPE            (1<<5)
+#define SVGA_FIFO_CAP_RESERVE           (1<<6)
+#define SVGA_FIFO_CAP_SCREEN_OBJECT     (1<<7)
+#define SVGA_FIFO_CAP_GMR2              (1<<8)
+#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED  SVGA_FIFO_CAP_GMR2
+#define SVGA_FIFO_CAP_SCREEN_OBJECT_2   (1<<9)
+#define SVGA_FIFO_CAP_DEAD              (1<<10)
+
+#endif /* _SVGA_REG_H_ */
diff --git a/src/VBox/Devices/Makefile.kmk b/src/VBox/Devices/Makefile.kmk
index b643851..8c72337 100644
--- a/src/VBox/Devices/Makefile.kmk
+++ b/src/VBox/Devices/Makefile.kmk
@@ -239,6 +239,23 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
  	Graphics/HGSMI/SHGSMIHost.cpp
  endif
 
+ ifdef VBOX_WITH_VMSVGA
+  VBoxDD_DEFS         += VBOX_WITH_VMSVGA
+  VBoxDD_SOURCES      += Graphics/DevVGA-SVGA.cpp
+ endif
+ ifdef VBOX_WITH_VMSVGA3D
+  VBoxDD_DEFS         += VBOX_WITH_VMSVGA3D
+  VBoxDD_SOURCES      += Graphics/DevVGA-SVGA3d-shared.cpp
+  ifeq ($(KBUILD_TARGET),win)
+    VBoxDD_SOURCES += Graphics/DevVGA-SVGA3d-win.cpp
+  else
+    VBoxDD_SOURCES += Graphics/DevVGA-SVGA3d-ogl.cpp
+    VBoxDD_LIBS    += $(PATH_STAGE_BIN)/vmsvgashader$(VBOX_SUFF_DLL)
+  endif
+  VBoxDD_LIBS.win      += d3d9.lib
+  VBoxDD_LIBS.linux    += GL X11
+ endif
+
  ifdef VBOX_WITH_VDMA
   VBoxDD_DEFS           += VBOX_WITH_VDMA
   VBoxDD_SOURCES        += \
@@ -823,6 +840,14 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
   ifdef VBOXWDDM_WITH_VBVA
    VBoxDDGC_DEFS        += VBOXWDDM_WITH_VBVA
   endif
+  ifdef VBOX_WITH_VMSVGA
+   VBoxDDGC_DEFS         += VBOX_WITH_VMSVGA
+   VBoxDDGC_SOURCES      += \
+    Graphics/DevVGA-SVGA.cpp
+  endif
+  ifdef VBOX_WITH_VMSVGA3D
+   VBoxDDGC_DEFS         += VBOX_WITH_VMSVGA3D
+  endif
   ifdef VBOX_VDMA_WITH_WATCHDOG
    VBoxDDGC_DEFS        += VBOX_VDMA_WITH_WATCHDOG
   endif
@@ -965,6 +990,15 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
  	Network/DrvNetShaper.cpp
  endif
 
+ ifdef VBOX_WITH_VMSVGA
+  VBoxDDR0_DEFS         += VBOX_WITH_VMSVGA
+  VBoxDDR0_SOURCES      += \
+    Graphics/DevVGA-SVGA.cpp
+ endif
+ ifdef VBOX_WITH_VMSVGA3D
+  VBoxDDR0_DEFS         += VBOX_WITH_VMSVGA3D
+ endif
+
  ifdef VBOX_WITH_HGSMI
   VBoxDDR0_DEFS         += VBOX_WITH_HGSMI
  endif
diff --git a/src/VBox/Devices/Network/DrvNAT.cpp b/src/VBox/Devices/Network/DrvNAT.cpp
index cc1a5c5..c7e86fb 100644
--- a/src/VBox/Devices/Network/DrvNAT.cpp
+++ b/src/VBox/Devices/Network/DrvNAT.cpp
@@ -23,6 +23,9 @@
 #define __STDC_LIMIT_MACROS
 #define __STDC_CONSTANT_MACROS
 #include "slirp/libslirp.h"
+extern "C" {
+#include "slirp/slirp_dns.h"
+}
 #include "slirp/ctl.h"
 
 #include <VBox/vmm/dbgf.h>
@@ -217,6 +220,10 @@ typedef DRVNAT *PDRVNAT;
 *   Internal Functions                                                         *
 *******************************************************************************/
 static void drvNATNotifyNATThread(PDRVNAT pThis, const char *pszWho);
+DECLINLINE(void) drvNATHostNetworkConfigurationChangeEventStrategySelector(
+  PDRVNAT pThis,
+  bool fHostNetworkConfigurationEventListener);
+static DECLCALLBACK(int) drvNATReinitializeHostNameResolving(PDRVNAT pThis);
 
 
 static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
@@ -971,7 +978,7 @@ static DECLCALLBACK(void) drvNatDnsChanged(SCDynamicStoreRef hDynStor, CFArrayRe
     {
         CFArrayRef hArrAddresses = (CFArrayRef)CFDictionaryGetValue(hDnsDict, kSCPropNetDNSServerAddresses);
         if (hArrAddresses)
-            pThis->pIAboveConfig->pfnSetLinkState(pThis->pIAboveConfig, PDMNETWORKLINKSTATE_DOWN_RESUME);
+            drvNATHostNetworkConfigurationChangeEventStrategySelector(pThis, /* RT_OS_DARWIN */ true);
 
         CFRelease(hDnsDict);
     }
@@ -1044,17 +1051,76 @@ static DECLCALLBACK(void) drvNATResume(PPDMDRVINS pDrvIns)
     switch (enmReason)
     {
         case VMRESUMEREASON_HOST_RESUME:
+#if RT_OS_DARWIN
+            drvNATHostNetworkConfigurationChangeEventStrategySelector(pThis, false);
+#else
+            drvNATHostNetworkConfigurationChangeEventStrategySelector(pThis, true);
+#endif
+            return;
+        default: /* Ignore every other resume reason. */
+            /* do nothing */
+            return;
+    }
+}
+
+
+static DECLCALLBACK(int) drvNATReinitializeHostNameResolving(PDRVNAT pThis)
+{
+    slirpReleaseDnsSettings(pThis->pNATState);
+    slirpInitializeDnsSettings(pThis->pNATState);
+    return VINF_SUCCESS;
+}
+
+/**
+ * This function at this stage could be called from two places, but both from non-NAT thread,
+ * - drvNATResume (EMT?)
+ * - drvNatDnsChanged (darwin, GUI or main) "listener"
+ * When Main's interface IHost will support host network configuration change event on every host,
+ * we won't call it from drvNATResume, but from listener of Main event in the similar way it done 
+ * for port-forwarding, and it wan't be on GUI/main thread, but on EMT thread only.
+ *
+ * Thread here is important, because we need to change DNS server list and domain name (+ perhaps, 
+ * search string) at runtime (VBOX_NAT_ENFORCE_INTERNAL_DNS_UPDATE), we can do it safely on NAT thread,
+ * so with changing other variables (place where we handle update) the main mechanism of update 
+ * _won't_ be changed, the only thing will change is drop of fHostNetworkConfigurationEventListener parameter. 
+ */
+DECLINLINE(void) drvNATHostNetworkConfigurationChangeEventStrategySelector(PDRVNAT pThis,
+                                                                        bool fHostNetworkConfigurationEventListener)
+{
+    int strategy = slirp_host_network_configuration_change_strategy_selector(pThis->pNATState);
+    switch (strategy)
+    {
+                 
+        case VBOX_NAT_HNCE_DNSPROXY:
+            {
+                /**
+                 * It's unsafe to to do it directly on non-NAT thread
+                 * so we schedule the worker and kick the NAT thread. 
+                 */
+                RTREQQUEUE hQueue = pThis->hSlirpReqQueue;
+                
+                int rc = RTReqQueueCallEx(hQueue, NULL /*ppReq*/, 0 /*cMillies*/, 
+                                          RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
+                                          (PFNRT)drvNATReinitializeHostNameResolving, 1, pThis);
+                if (RT_SUCCESS(rc))
+                    drvNATNotifyNATThread(pThis, "drvNATNetworkUp_SendBuf");
+
+
+                return;
+
+            }
+        case VBOX_NAT_HNCE_EXSPOSED_NAME_RESOLUTION_INFO:
             /*
              * Host resumed from a suspend and the network might have changed.
              * Disconnect the guest from the network temporarily to let it pick up the changes.
              */
-#ifndef RT_OS_DARWIN
-            pThis->pIAboveConfig->pfnSetLinkState(pThis->pIAboveConfig,
-                                                  PDMNETWORKLINKSTATE_DOWN_RESUME);
-#endif
+
+            if (fHostNetworkConfigurationEventListener)
+                pThis->pIAboveConfig->pfnSetLinkState(pThis->pIAboveConfig,
+                                                      PDMNETWORKLINKSTATE_DOWN_RESUME);
             return;
-        default: /* Ignore every other resume reason. */
-            /* do nothing */
+        case VBOX_NAT_HNCE_HOSTRESOLVER:
+        default:
             return;
     }
 }
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c
index af47153..464d14e 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c
@@ -52,6 +52,12 @@
 
 #include <string.h>
 
+/* see comment in "lwip/ip.h" */
+#ifdef IP_HDRINCL
+#undef IP_HDRINCL
+#endif
+#define IP_HDRINCL LWIP_IP_HDRINCL
+
 /** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
  * used to modify and send a response packet (and to 1 if this is not the case,
  * e.g. when link header is stripped of when receiving) */
@@ -64,6 +70,12 @@
 
 static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
 
+#if LWIP_CONNECTION_PROXY
+static ping_proxy_fn ping_proxy_accept_callback;
+static void* ping_proxy_accept_arg;
+#endif
+
+
 /**
  * Processes ICMP input packets, called from ip_input().
  *
@@ -247,6 +259,97 @@ memerr:
 #endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
 }
 
+#if LWIP_CONNECTION_PROXY
+
+void
+ping_proxy_accept(ping_proxy_fn callback, void *arg)
+{
+  ping_proxy_accept_callback = callback;
+  ping_proxy_accept_arg = arg;
+}
+
+
+/**
+ * Proxy ICMP input packets, called from ip_input().
+ *
+ * @param p the icmp echo request packet, p->payload pointing to the icmp header
+ * @param inp the netif on which this packet was received
+ */
+void
+icmp_proxy_input(struct pbuf *p, struct netif *inp)
+{
+  u8_t type, code;
+
+  ICMP_STATS_INC(icmp.recv);
+  snmp_inc_icmpinmsgs();
+
+  if (p->tot_len < 4) {         /* type(1), code(1), checksum(2) */
+    LWIP_DEBUGF(ICMP_DEBUG,
+      ("icmp_proxy_input: short ICMP (%"U16_F" bytes) received\n",
+       p->tot_len));
+    goto lenerr;
+  }
+
+  if (inet_chksum_pbuf(p) != 0) {
+    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_proxy_input: bad checksum\n"));
+    pbuf_free(p);
+    ICMP_STATS_INC(icmp.chkerr);
+    snmp_inc_icmpinerrors();
+    return;
+  }
+
+  type = *((u8_t *)p->payload);
+  code = *(((u8_t *)p->payload)+1);
+  switch (type) {
+
+  case ICMP_ER:
+    /* ignore silently */
+    pbuf_free(p);
+    break;
+
+  case ICMP_DUR:
+    /* TODO: anything useful we can do? */
+    pbuf_free(p);
+    break;
+
+  case ICMP_ECHO:
+    if (code != 0) {
+      goto proterr;
+    }
+    if (p->tot_len < 8) {
+      goto lenerr;
+    }
+
+    if (ping_proxy_accept_callback != NULL) {
+      (*ping_proxy_accept_callback)(ping_proxy_accept_arg, p);
+    }
+    break;
+
+  default:
+    goto proterr;
+  }
+  return;
+
+ lenerr:  
+  ICMP_STATS_INC(icmp.lenerr);
+  goto drop;
+
+ proterr:
+  LWIP_DEBUGF(ICMP_DEBUG,
+              ("icmp_proxy_input: ICMP type %"S16_F" code %"S16_F
+               " not supported.\n",
+               (s16_t)type, (s16_t)code));
+  ICMP_STATS_INC(icmp.proterr);
+  goto drop;
+
+ drop:
+  pbuf_free(p);
+  ICMP_STATS_INC(icmp.drop);
+  snmp_inc_icmpinerrors();
+  return;
+}
+#endif /* LWIP_CONNECTION_PROXY */
+
 /**
  * Send an icmp 'destination unreachable' packet, called from ip_input() if
  * the transport layer protocol is unknown and from udp_input() if the local
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c
index 2186973..4cb40fe 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c
@@ -58,6 +58,12 @@
 
 #include <string.h>
 
+/* see comment in "lwip/ip.h" */
+#ifdef IP_HDRINCL
+#undef IP_HDRINCL
+#endif
+#define IP_HDRINCL LWIP_IP_HDRINCL
+
 /** Set this to 0 in the rare case of wanting to call an extra function to
  * generate the IP checksum (in contrast to calculating it on-the-fly). */
 #ifndef LWIP_INLINE_IP_CHKSUM
@@ -614,6 +620,12 @@ ip_input(struct pbuf *p, struct netif *inp)
 
     switch (IPH_PROTO(iphdr)) {
 
+#if LWIP_ICMP
+    case IP_PROTO_ICMP:
+      icmp_proxy_input(p, inp);
+      break;
+#endif
+
 #if LWIP_UDP
     case IP_PROTO_UDP:
 #if LWIP_UDPLITE
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c
index bad7930..09d598f 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c
@@ -66,6 +66,11 @@
 /* Forward declarations */
 static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
 
+#if LWIP_CONNECTION_PROXY
+static ping6_proxy_fn ping6_proxy_accept_callback;
+static void *ping6_proxy_accept_arg;
+#endif
+
 
 /**
  * Process an input ICMPv6 message. Called by ip6_input.
@@ -199,6 +204,68 @@ icmp6_input(struct pbuf *p, struct netif *inp)
 }
 
 
+#if LWIP_CONNECTION_PROXY
+
+void
+ping6_proxy_accept(ping6_proxy_fn callback, void *arg)
+{
+  ping6_proxy_accept_callback = callback;
+  ping6_proxy_accept_arg = arg;
+}
+
+
+void
+icmp6_proxy_input(struct pbuf *p, struct netif *inp)
+{
+  struct icmp6_hdr *icmp6hdr;
+  struct pbuf * r;
+  ip6_addr_t * reply_src;
+
+  ICMP6_STATS_INC(icmp6.recv);
+
+  /* Check that ICMPv6 header fits in payload */
+  if (p->len < sizeof(struct icmp6_hdr)) {
+    /* drop short packets */
+    pbuf_free(p);
+    ICMP6_STATS_INC(icmp6.lenerr);
+    ICMP6_STATS_INC(icmp6.drop);
+    return;
+  }
+
+  icmp6hdr = (struct icmp6_hdr *)p->payload;
+  if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
+                        ip6_current_dest_addr()) != 0) {
+    /* Checksum failed */
+    pbuf_free(p);
+    ICMP6_STATS_INC(icmp6.chkerr);
+    ICMP6_STATS_INC(icmp6.drop);
+    return;
+  }
+
+  switch (icmp6hdr->type) {
+
+  case ICMP6_TYPE_EREQ:
+    if (ping6_proxy_accept_callback != NULL) {
+      (*ping6_proxy_accept_callback)(ping6_proxy_accept_arg, p);
+      return;
+    }
+    ICMP6_STATS_INC(icmp6.drop);
+    break;
+
+  case ICMP6_TYPE_EREP:
+    /* ignore silently */
+    ICMP6_STATS_INC(icmp6.drop);
+    break;
+
+  default:
+    ICMP6_STATS_INC(icmp6.drop);
+    break;
+  }
+
+  pbuf_free(p);
+}
+#endif /* LWIP_CONNECTION_PROXY */
+
 /**
  * Send an icmpv6 'destination unreachable' packet.
  *
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c
index 13b7a24..b890073 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c
@@ -60,6 +60,12 @@
 #include "lwip/debug.h"
 #include "lwip/stats.h"
 
+/* see comment in "lwip/ip.h" */
+#ifdef IP_HDRINCL
+#undef IP_HDRINCL
+#endif
+#define IP_HDRINCL LWIP_IP_HDRINCL
+
 #if LWIP_CONNECTION_PROXY
 proxy_ip6_divert_hook_fn proxy_ip6_divert_hook;
 #endif
@@ -704,9 +710,9 @@ netif_found:
       }
 
       /* Offset == 0 and more_fragments == 0? */
-      if (((frag_hdr->_fragment_offset & IP6_FRAG_OFFSET_MASK) == 0) &&
-          ((frag_hdr->_fragment_offset & IP6_FRAG_MORE_FLAG) == 0)) {
-
+      if ((frag_hdr->_fragment_offset
+           & PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0)
+      {
         /* This is a 1-fragment packet, usually a packet that we have
          * already reassembled. Skip this header anc continue. */
         pbuf_header(p, -hlen);
@@ -779,6 +785,14 @@ options_done:
       break;
 #endif /* LWIP_TCP */
 
+#if LWIP_ICMP6
+    case IP6_NEXTH_ICMP6:
+      /* Point to payload. */
+      pbuf_header(p, -ip_data.current_ip_header_tot_len);
+      icmp6_proxy_input(p, inp);
+      break;
+#endif /* LWIP_ICMP */
+
     default:
       /* no proxy support for this protocol */
       /* XXX: TODO: icmp administratively prohibited? */
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6_frag.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6_frag.c
index 47882d4..ee1ea31 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6_frag.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6_frag.c
@@ -75,23 +75,13 @@
 /** This is a helper struct which holds the starting
  * offset and the ending offset of this fragment to
  * easily chain the fragments.
- * It has the same packing requirements as the IPv6 header, since it replaces
- * the Fragment Header in memory in incoming fragments to keep
- * track of the various fragments.
  */
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
 struct ip6_reass_helper {
-  PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
-  PACK_STRUCT_FIELD(u16_t start);
-  PACK_STRUCT_FIELD(u16_t end);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/epstruct.h"
-#endif
+  struct ip6_reass_helper *next;
+  struct pbuf *p;
+  u16_t start;
+  u16_t end;
+};
 
 /* static variables */
 static struct ip6_reassdata *reassdatagrams;
@@ -136,61 +126,45 @@ ip6_reass_tmr(void)
 static void
 ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
 {
-  struct ip6_reassdata *prev;
+  struct ip6_reassdata **pipr;
   u16_t pbufs_freed = 0;
   u8_t clen;
   struct pbuf *p;
   struct ip6_reass_helper *iprh;
 
+  /* First, free all received pbufs.  The individual pbufs need to be released
+     separately as they have not yet been chained */
+  iprh = ipr->iprh;
+  while (iprh != NULL) {
+    struct ip6_reass_helper *next = iprh->next;
+    p = iprh->p;
+
 #if LWIP_ICMP6
-  iprh = (struct ip6_reass_helper *)ipr->p->payload;
-  if (iprh->start == 0) {
-    /* The first fragment was received, send ICMP time exceeded. */
-    /* First, de-queue the first pbuf from r->p. */
-    p = ipr->p;
-    ipr->p = iprh->next_pbuf;
-    /* Then, move back to the original header (we are now pointing to Fragment header). */
-    if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) {
-      LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0);
-    }
-    else {
-      icmp6_time_exceeded(p, ICMP6_TE_FRAG);
+    /* If the first fragment was received, send ICMP time exceeded. */
+    if (iprh->start == 0) {
+      SMEMCPY(ipr->iphdr0, &ipr->iphdr, IP6_HLEN);
+      if (pbuf_header(p, (u8_t *)p->payload - (u8_t *)ipr->iphdr0) == 0) {
+        icmp6_time_exceeded(p, ICMP6_TE_FRAG);
+      }
+      else {
+        LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0);
+      }
     }
+#endif /* LWIP_ICMP6 */
+
     clen = pbuf_clen(p);
     LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
     pbufs_freed += clen;
     pbuf_free(p);
-  }
-#endif /* LWIP_ICMP6 */
 
-  /* First, free all received pbufs.  The individual pbufs need to be released
-     separately as they have not yet been chained */
-  p = ipr->p;
-  while (p != NULL) {
-    struct pbuf *pcur;
-    iprh = (struct ip6_reass_helper *)p->payload;
-    pcur = p;
-    /* get the next pointer before freeing */
-    p = iprh->next_pbuf;
-    clen = pbuf_clen(pcur);
-    LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
-    pbufs_freed += clen;
-    pbuf_free(pcur);
+    iprh = next;
   }
 
   /* Then, unchain the struct ip6_reassdata from the list and free it. */
-  if (ipr == reassdatagrams) {
-    reassdatagrams = ipr->next;
-  } else {
-    prev = reassdatagrams;
-    while (prev != NULL) {
-      if (prev->next == ipr) {
-        break;
-      }
-      prev = prev->next;
-    }
-    if (prev != NULL) {
-      prev->next = ipr->next;
+  for (pipr = &reassdatagrams; *pipr != NULL; pipr = &(*pipr)->next) {
+    if (*pipr == ipr) {
+      (*pipr) = ipr->next;
+      break;
     }
   }
   memp_free(MEMP_IP6_REASSDATA, ipr);
@@ -245,12 +219,13 @@ ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed)
 struct pbuf *
 ip6_reass(struct pbuf *p)
 {
-  struct ip6_reassdata *ipr, *ipr_prev;
-  struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
+  struct ip6_reassdata *ipr, **pipr;
+  struct ip6_reass_helper *iprh, *iprh_tmp;
+  struct ip6_reass_helper **pnext;
   struct ip6_frag_hdr * frag_hdr;
-  u16_t offset, len;
-  u8_t clen, valid = 1;
-  struct pbuf *q;
+  size_t unfrag_len;
+  u16_t offset, len, start, end, validlen;
+  u8_t clen;
 
   IP6_FRAG_STATS_INC(ip6_frag.recv);
 
@@ -267,19 +242,22 @@ ip6_reass(struct pbuf *p)
   len -= ((u8_t*)p->payload - (u8_t*)ip6_current_header()) - IP6_HLEN;
   len -= IP6_FRAG_HLEN;
 
+  start = (offset & IP6_FRAG_OFFSET_MASK);
+  end = start + len;
+
+
   /* Look for the datagram the fragment belongs to in the current datagram queue,
    * remembering the previous in the queue for later dequeueing. */
-  for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) {
+  for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) {
     /* Check if the incoming fragment matches the one currently present
        in the reassembly buffer. If so, we proceed with copying the
        fragment into the buffer. */
     if ((frag_hdr->_identification == ipr->identification) &&
-        ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr->src)) &&
-        ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr->dest))) {
+        ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr.src)) &&
+        ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr.dest))) {
       IP6_FRAG_STATS_INC(ip6_frag.cachehit);
       break;
     }
-    ipr_prev = ipr;
   }
 
   if (ipr == NULL) {
@@ -309,225 +287,206 @@ ip6_reass(struct pbuf *p)
     /* Use the current IPv6 header for src/dest address reference.
      * Eventually, we will replace it when we get the first fragment
      * (it might be this one, in any case, it is done later). */
-    ipr->iphdr = (struct ip6_hdr *)ip6_current_header();
+    SMEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
+    if (start == 0) {
+      ipr->iphdr0 = (struct ip6_hdr *)ip6_current_header();
+    }
 
     /* copy the fragmented packet id. */
     ipr->identification = frag_hdr->_identification;
-
-    /* copy the nexth field */
-    ipr->nexth = frag_hdr->_nexth;
   }
 
-  /* Check if we are allowed to enqueue more datagrams. */
-  if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
-#if IP_REASS_FREE_OLDEST
-    ip6_reass_remove_oldest_datagram(ipr, clen);
-    if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)
-#endif /* IP_REASS_FREE_OLDEST */
-    {
-      /* @todo: send ICMPv6 time exceeded here? */
-      /* drop this pbuf */
-      IP6_FRAG_STATS_INC(ip6_frag.memerr);
+  /* If this is the last fragment, save total packet length. */
+  if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
+#if IP_REASS_CHECK_OVERLAP
+    if (ipr->datagram_len != 0) {
+      IP6_FRAG_STATS_INC(ip6_frag.proterr);
       IP6_FRAG_STATS_INC(ip6_frag.drop);
       goto nullreturn;
     }
+#endif /* IP_REASS_CHECK_OVERLAP */
+    ipr->datagram_len = end;
   }
 
-  /* Overwrite Fragment Header with our own helper struct. */
-  iprh = (struct ip6_reass_helper *)p->payload;
-  iprh->next_pbuf = NULL;
-  iprh->start = (offset & IP6_FRAG_OFFSET_MASK);
-  iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len;
-
-  /* find the right place to insert this pbuf */
-  /* Iterate through until we either get to the end of the list (append),
-   * or we find on with a larger offset (insert). */
-  for (q = ipr->p; q != NULL;) {
-    iprh_tmp = (struct ip6_reass_helper*)q->payload;
-    if (iprh->start < iprh_tmp->start) {
+  /* find the place to insert this pbuf */
+  validlen = 0;
+  for (pnext = &ipr->iprh; *pnext != NULL; pnext = &(*pnext)->next) {
+    iprh_tmp = *pnext;
+
+    if (start < iprh_tmp->start) {
+      /* the new pbuf should be inserted before this */
 #if IP_REASS_CHECK_OVERLAP
-      if (iprh->end > iprh_tmp->start) {
+      if (end > iprh_tmp->start) {
         /* fragment overlaps with following, throw away */
         IP6_FRAG_STATS_INC(ip6_frag.proterr);
         IP6_FRAG_STATS_INC(ip6_frag.drop);
         goto nullreturn;
       }
-      if (iprh_prev != NULL) {
-        if (iprh->start < iprh_prev->end) {
-          /* fragment overlaps with previous, throw away */
-          IP6_FRAG_STATS_INC(ip6_frag.proterr);
-          IP6_FRAG_STATS_INC(ip6_frag.drop);
-          goto nullreturn;
-        }
-      }
 #endif /* IP_REASS_CHECK_OVERLAP */
-      /* the new pbuf should be inserted before this */
-      iprh->next_pbuf = q;
-      if (iprh_prev != NULL) {
-        /* not the fragment with the lowest offset */
-        iprh_prev->next_pbuf = p;
-      } else {
-        /* fragment with the lowest offset */
-        ipr->p = p;
-      }
       break;
-    } else if(iprh->start == iprh_tmp->start) {
+    }
+    else if (start == iprh_tmp->start) {
       /* received the same datagram twice: no need to keep the datagram */
       IP6_FRAG_STATS_INC(ip6_frag.drop);
       goto nullreturn;
+    }
 #if IP_REASS_CHECK_OVERLAP
-    } else if(iprh->start < iprh_tmp->end) {
+    else if (start < iprh_tmp->end) {
       /* overlap: no need to keep the new datagram */
       IP6_FRAG_STATS_INC(ip6_frag.proterr);
       IP6_FRAG_STATS_INC(ip6_frag.drop);
       goto nullreturn;
+    }
 #endif /* IP_REASS_CHECK_OVERLAP */
-    } else {
+    else {
       /* Check if the fragments received so far have no gaps. */
-      if (iprh_prev != NULL) {
-        if (iprh_prev->end != iprh_tmp->start) {
-          /* There is a fragment missing between the current
-           * and the previous fragment */
-          valid = 0;
-        }
+      if (validlen == iprh_tmp->start) {
+        validlen = iprh_tmp->end;
+      }
+      else {
+        validlen = 0;
       }
     }
-    q = iprh_tmp->next_pbuf;
-    iprh_prev = iprh_tmp;
   }
 
-  /* If q is NULL, then we made it to the end of the list. Determine what to do now */
-  if (q == NULL) {
-    if (iprh_prev != NULL) {
-      /* this is (for now), the fragment with the highest offset:
-       * chain it to the last fragment */
-#if IP_REASS_CHECK_OVERLAP
-      LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
-#endif /* IP_REASS_CHECK_OVERLAP */
-      iprh_prev->next_pbuf = p;
-      if (iprh_prev->end != iprh->start) {
-        valid = 0;
-      }
-    } else {
-#if IP_REASS_CHECK_OVERLAP
-      LWIP_ASSERT("no previous fragment, this must be the first fragment!",
-        ipr->p == NULL);
-#endif /* IP_REASS_CHECK_OVERLAP */
-      /* this is the first fragment we ever received for this ip datagram */
-      ipr->p = p;
+  /* Check if we are allowed to enqueue more datagrams. */
+  if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
+#if IP_REASS_FREE_OLDEST
+    ip6_reass_remove_oldest_datagram(ipr, clen);
+    if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)
+#endif /* IP_REASS_FREE_OLDEST */
+    {
+      /* @todo: send ICMPv6 time exceeded here? */
+      /* drop this pbuf */
+      IP6_FRAG_STATS_INC(ip6_frag.memerr);
+      IP6_FRAG_STATS_INC(ip6_frag.drop);
+      goto nullreturn;
     }
   }
 
+  if (start == 0 && ipr->iphdr0 == NULL) {
+    /*
+     * We've got the fragment with offset 0 out of order, remember its
+     * IPv6 header location (in the hidden part of the current pbuf)
+     * and update the copy in ip6_reassdata::iphdr.  We don't need to
+     * copy complete header since src and dest are the same as in the
+     * first fragment we received.
+     */
+    ipr->iphdr0 = (struct ip6_hdr *)ip6_current_header();
+    SMEMCPY(&ipr->iphdr, ip6_current_header(),
+            IP6_HLEN - 2 * sizeof(ip_addr_p_t));
+  }
+
+  /* Overwrite IPv6 Header with our own helper struct (aligned). */
+  iprh = (struct ip6_reass_helper *)
+    (((uintptr_t)(u8_t *)ip6_current_header() + sizeof(void *) - 1)
+     & ~(sizeof(void *) - 1));
+  iprh->p = p;
+  iprh->start = start;
+  iprh->end = end;
+
+  /* insert it into the list */
+  iprh->next = *pnext;
+  *pnext = iprh;
+
   /* Track the current number of pbufs current 'in-flight', in order to limit
   the number of fragments that may be enqueued at any one time */
   ip6_reass_pbufcount += clen;
 
-  /* Remember IPv6 header if this is the first fragment. */
-  if (iprh->start == 0) {
-    ipr->iphdr = (struct ip6_hdr *)ip6_current_header();
-  }
-
-  /* If this is the last fragment, calculate total packet length. */
-  if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
-    ipr->datagram_len = iprh->end;
-  }
-
-  /* Additional validity tests: we have received first and last fragment. */
-  iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload;
-  if (iprh_tmp->start != 0) {
-    valid = 0;
-  }
   if (ipr->datagram_len == 0) {
-    valid = 0;
+    /* We still don't have the last fragment. */
+    return NULL;
   }
 
-  /* Final validity test: no gaps between current and last fragment. */
-  iprh_prev = iprh;
-  q = iprh->next_pbuf;
-  while ((q != NULL) && valid) {
-    iprh = (struct ip6_reass_helper*)q->payload;
-    if (iprh_prev->end != iprh->start) {
-      valid = 0;
-      break;
-    }
-    iprh_prev = iprh;
-    q = iprh->next_pbuf;
+  if (validlen == start) {
+    validlen = end;
+  }
+  else {
+    /* There are gaps before this fragment. */
+    return NULL;
   }
 
-  if (valid) {
-    /* All fragments have been received */
-
-    /* chain together the pbufs contained within the ip6_reassdata list. */
-    iprh = (struct ip6_reass_helper*) ipr->p->payload;
-    while(iprh != NULL) {
-
-      if (iprh->next_pbuf != NULL) {
-        /* Save next helper struct (will be hidden in next step). */
-        iprh_tmp = (struct ip6_reass_helper*) iprh->next_pbuf->payload;
-
-        /* hide the fragment header for every succeding fragment */
-        pbuf_header(iprh->next_pbuf, -IP6_FRAG_HLEN);
-        pbuf_cat(ipr->p, iprh->next_pbuf);
+  if (validlen != 0) {
+    /*
+     * We know we have all the data up to the end of this fragment and
+     * we know the total length.  Check if the reassembly is complete.
+     */
+    for (iprh_tmp = iprh->next; iprh_tmp != NULL; iprh_tmp = iprh_tmp->next) {
+      if (validlen == iprh_tmp->start) {
+        validlen = iprh_tmp->end;
       }
       else {
-        iprh_tmp = NULL;
+        validlen = 0;
+        break;
       }
-
-      iprh = iprh_tmp;
     }
 
-    /* Adjust datagram length by adding header lengths. */
-    ipr->datagram_len += ((u8_t*)ipr->p->payload - (u8_t*)ipr->iphdr)
-                         + IP6_FRAG_HLEN
-                         - IP6_HLEN ;
+    if (validlen != ipr->datagram_len) {
+      /* the datagram is not yet reassembled completely */
+      return NULL;
+    }
+  }
 
-    /* Set payload length in ip header. */
-    ipr->iphdr->_plen = htons(ipr->datagram_len);
+  /*
+   * All fragments have been received.  Reassemble original datagram
+   * and return it to ip6_input() to be processed instead of the final
+   * fragment that completed the reassembly.
+   */
+
+  /* chain together the pbufs contained within the ip6_reassdata list. */
+  p = NULL;
+  for (iprh = ipr->iprh; iprh != NULL; iprh = iprh->next) {
+    if (p == NULL) {
+      p = iprh->p;
+    }
+    else {
+      /* hide the fragment header for every succeeding fragment */
+      pbuf_header(iprh->p, -IP6_FRAG_HLEN);
+      pbuf_cat(p, iprh->p);
+    }
+  }
 
-    /* Get the furst pbuf. */
-    p = ipr->p;
+  /* Adjust datagram length by adding preceding header lengths. */
+  unfrag_len = (u8_t *)p->payload - (u8_t *)ipr->iphdr0;
+  ipr->datagram_len += unfrag_len - IP6_HLEN + IP6_FRAG_HLEN;
 
-    /* Restore Fragment Header in first pbuf. Mark as "single fragment"
-     * packet. Restore nexth. */
-    frag_hdr = (struct ip6_frag_hdr *) p->payload;
-    frag_hdr->_nexth = ipr->nexth;
-    frag_hdr->reserved = 0;
-    frag_hdr->_fragment_offset = 0;
-    frag_hdr->_identification = 0;
+  /* Set payload length in ip header. */
+  ipr->iphdr._plen = htons(ipr->datagram_len);
 
-    /* release the sources allocate for the fragment queue entry */
-    if (reassdatagrams == ipr) {
-      /* it was the first in the list */
-      reassdatagrams = ipr->next;
-    } else {
-      /* it wasn't the first, so it must have a valid 'prev' */
-      LWIP_ASSERT("sanity check linked list", ipr_prev != NULL);
-      ipr_prev->next = ipr->next;
-    }
-    memp_free(MEMP_IP6_REASSDATA, ipr);
+  /* restore IPv6 header (overwritten with ip6_reass_helper) */
+  SMEMCPY(ipr->iphdr0, &ipr->iphdr, IP6_HLEN);
 
-    /* adjust the number of pbufs currently queued for reassembly. */
-    ip6_reass_pbufcount -= pbuf_clen(p);
+  /* Mark as "single fragment" packet (see caller). */
+  frag_hdr = (struct ip6_frag_hdr *) p->payload;
+  frag_hdr->_fragment_offset = 0;
 
-    /* Move pbuf back to IPv6 header. */
-    if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) {
-      LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0);
-      pbuf_free(p);
-      return NULL;
+  /* Unlink from the reassdatagrams list */
+  for (pipr = &reassdatagrams; *pipr != NULL; pipr = &(*pipr)->next) {
+    if (*pipr == ipr) {
+      (*pipr) = ipr->next;
+      break;
     }
+  }
+  memp_free(MEMP_IP6_REASSDATA, ipr);
 
-    /* Return the pbuf chain */
-    return p;
+  /* adjust the number of pbufs currently queued for reassembly. */
+  ip6_reass_pbufcount -= pbuf_clen(p);
+
+  /* Move pbuf back to IPv6 header. */
+  if (pbuf_header(p, unfrag_len) != 0) {
+    LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0);
+    goto nullreturn;
   }
-  /* the datagram is not (yet?) reassembled completely */
-  return NULL;
+
+  /* Return the pbuf chain */
+  return p;
 
 nullreturn:
   pbuf_free(p);
   return NULL;
 }
 
-#endif /* LWIP_IPV6 ^^ LWIP_IPV6_REASS */
+#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
 
 #if LWIP_IPV6 && LWIP_IPV6_FRAG
 
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c b/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c
index cd173fe..0fcd0f1 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c
@@ -778,7 +778,8 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
     TCP_STATS_INC(tcp.memerr);
     return ERR_MEM;
   }
-  LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
+  LWIP_ASSERT("seg->tcphdr not aligned",
+	      ((mem_ptr_t)seg->tcphdr % (MEM_ALIGNMENT < 4 ? MEM_ALIGNMENT : 4)) == 0);
   LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
 
   LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/udp.c b/src/VBox/Devices/Network/lwip-new/src/core/udp.c
index 9e7bf7a..93f1c3e 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/udp.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/udp.c
@@ -532,10 +532,26 @@ udp_proxy_input(struct pbuf *p, struct netif *inp)
     goto end;
   }
 
-  udphdr = (struct udp_hdr *)p->payload;
-
   LWIP_DEBUGF(UDP_DEBUG, ("udp_proxy_input: received datagram of length %"U16_F"\n", p->tot_len));
 
+  udphdr = (struct udp_hdr *)p->payload;
+  if (udphdr->chksum != 0) {
+    LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE,
+                ("udp_proxy_input: calculating checksum\n"));
+    if (ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_UDP, p->tot_len,
+                          ipX_current_src_addr(),
+                          ipX_current_dest_addr()) != 0)
+    {
+      LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_WARNING,
+                  ("udp_proxy_input: UDP datagram discarded due to failing checksum\n"));
+      UDP_STATS_INC(udp.chkerr);
+      UDP_STATS_INC(udp.drop);
+      snmp_inc_udpinerrors();
+      pbuf_free(p);
+      goto end;
+    }
+  }
+
   /* convert src and dest ports to host byte order */
   src = ntohs(udphdr->src);
   dest = ntohs(udphdr->dest);
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/icmp.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/icmp.h
index fa893b6..4b4e63e 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/icmp.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/icmp.h
@@ -45,6 +45,8 @@
 extern "C" {
 #endif
 
+#define ICMP_HLEN 8
+
 #define ICMP_ER   0    /* echo reply */
 #define ICMP_DUR  3    /* destination unreachable */
 #define ICMP_SQ   4    /* source quench */
@@ -103,9 +105,17 @@ PACK_STRUCT_END
 #if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
 
 void icmp_input(struct pbuf *p, struct netif *inp);
+#if LWIP_CONNECTION_PROXY
+void icmp_proxy_input(struct pbuf *p, struct netif *inp);
+#endif
 void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
 void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
 
+#if LWIP_CONNECTION_PROXY
+typedef void (*ping_proxy_fn)(void *arg, struct pbuf *p);
+void ping_proxy_accept(ping_proxy_fn callback, void *arg);
+#endif
+
 #endif /* LWIP_ICMP */
 
 #if (LWIP_IPV6 && LWIP_ICMP6)
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h
index b05ae53..923d4b0 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h
@@ -210,7 +210,7 @@ u8_t ip4_addr_netmask_valid(u32_t netmask);
 #define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL))
 
 #define ip_addr_debug_print(debug, ipaddr) \
-  LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F,             \
+  LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F,      \
                       ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0,       \
                       ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0,       \
                       ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0,       \
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/icmp6.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/icmp6.h
index 74bfdbe..2eba6c6 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/icmp6.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/icmp6.h
@@ -136,11 +136,19 @@ PACK_STRUCT_END
 #if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
 
 void icmp6_input(struct pbuf *p, struct netif *inp);
+#if LWIP_CONNECTION_PROXY
+void icmp6_proxy_input(struct pbuf *p, struct netif *inp);
+#endif
 void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c);
 void icmp6_packet_too_big(struct pbuf *p, u32_t mtu);
 void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c);
 void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer);
 
+#if LWIP_CONNECTION_PROXY
+typedef void (*ping6_proxy_fn)(void *arg, struct pbuf *p);
+void ping6_proxy_accept(ping6_proxy_fn callback, void *arg);
+#endif
+
 #endif /* LWIP_ICMP6 && LWIP_IPV6 */
 
 
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h
index a9244ba..56da0d3 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h
@@ -260,7 +260,7 @@ Little-endian version, stored in network order (no htonl). */
 #define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED)
 
 #define ip6_addr_debug_print(debug, ipaddr) \
-  LWIP_DEBUGF(debug, ("%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F, \
+  LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \
                       ipaddr != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0,    \
                       ipaddr != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0,    \
                       ipaddr != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0,    \
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_frag.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_frag.h
index 75898b8..95e917e 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_frag.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_frag.h
@@ -43,6 +43,7 @@
 
 #include "lwip/opt.h"
 #include "lwip/pbuf.h"
+#include "lwip/ip6.h"
 #include "lwip/ip6_addr.h"
 #include "lwip/netif.h"
 
@@ -56,16 +57,18 @@ extern "C" {
 /* The IPv6 reassembly timer interval in milliseconds. */
 #define IP6_REASS_TMR_INTERVAL 1000
 
-/* IPv6 reassembly helper struct.
+struct ip6_reass_helper;
+
+/* IPv6 reassembly struct.
  * This is exported because memp needs to know the size.
  */
 struct ip6_reassdata {
   struct ip6_reassdata *next;
-  struct pbuf *p;
-  struct ip6_hdr * iphdr;
+  struct ip6_reass_helper *iprh;
+  struct ip6_hdr *iphdr0;
+  struct ip6_hdr iphdr;
   u32_t identification;
   u16_t datagram_len;
-  u8_t nexth;
   u8_t timer;
 };
 
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/ip.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/ip.h
index a0cd1d4..b9139f2 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/ip.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/ip.h
@@ -49,10 +49,18 @@ extern "C" {
 /* This is passed as the destination address to ip_output_if (not
    to ip_output), meaning that an IP header already is constructed
    in the pbuf. This is used when TCP retransmits. */
+#if 0
+/* XXX: "IP_HDRINCL" is a name of a socket option and the #undef below
+   is a good sign that reusing this name was rather unfortuate.  Other
+   naming conflicts are mostly restricted to "lwip/sockets.h" but this
+   one is pretty nasty since it affects all code that uses lwip.
+   Rename it out of the way here and do undef/redef dance in the few
+   lwip files that use this name to minimize diffs to upstream. */
 #ifdef IP_HDRINCL
 #undef IP_HDRINCL
 #endif /* IP_HDRINCL */
-#define IP_HDRINCL  NULL
+#endif /* XXX: 0 */
+#define LWIP_IP_HDRINCL  NULL
 
 #if LWIP_NETIF_HWADDRHINT
 #define IP_PCB_ADDRHINT ;u8_t addr_hint
diff --git a/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h b/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h
index 7ae101f..befb1d2 100644
--- a/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h
+++ b/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h
@@ -138,6 +138,7 @@
 #define LWIP_IPV6_DUP_DETECT_ATTEMPTS   0
 #endif
 
+#define LWIP_IPV6_FRAG                  1
 
 /** 
  * aka Slirp mode.
diff --git a/src/VBox/Devices/Network/slirp/ip_icmp.c b/src/VBox/Devices/Network/slirp/ip_icmp.c
index 28d9c58..b760cdd 100644
--- a/src/VBox/Devices/Network/slirp/ip_icmp.c
+++ b/src/VBox/Devices/Network/slirp/ip_icmp.c
@@ -601,11 +601,12 @@ done:
  * be fully correct and in host byte order.
  * ICMP fragmentation is illegal.  All machines must accept 576 bytes in one
  * packet.  The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
+ * @note: implementation note: MSIZE is 256 bytes (minimal buffer), m_getjcl we allocate two mbufs on: clust_zone 
+ * and mbuf_zone. the maximum payload 256 - 14 (Ethernet header) - 20 (IPv4 hdr) - 8 (ICMPv4 header) = 214
  *
  * @note This function will free msrc!
  */
 
-#define ICMP_MAXDATALEN (IP_MSS-28)
 void icmp_error(PNATState pData, struct mbuf *msrc, u_char type, u_char code, int minsize, const char *message)
 {
     unsigned hlen, shlen, s_ip_len;
@@ -653,71 +654,80 @@ void icmp_error(PNATState pData, struct mbuf *msrc, u_char type, u_char code, in
             goto end_error;
     }
 
-    new_ip_size = sizeof(struct ip) + ICMP_MINLEN + ICMP_MAXDATALEN;
-    new_m_size = if_maxlinkhdr + new_ip_size;
-    if (new_m_size < MSIZE)
-        size = MCLBYTES;
-    else if (new_m_size < MCLBYTES)
-        size = MCLBYTES;
-    else if(new_m_size < MJUM9BYTES)
-        size = MJUM9BYTES;
-    else if (new_m_size < MJUM16BYTES)
-        size = MJUM16BYTES;
-    else
-        AssertMsgFailed(("Unsupported size"));
-    m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, size);
+    m = m_gethdr(pData, M_NOWAIT, MT_HEADER);
     if (!m)
         goto end_error;
 
+    m->m_flags |= M_SKIP_FIREWALL;
     m->m_data += if_maxlinkhdr;
     m->m_pkthdr.header = mtod(m, void *);
 
-    m->m_len = msrc->m_len < new_ip_size ? msrc->m_len : new_ip_size;
-    memcpy(m->m_data, msrc->m_data, m->m_len);   /* copy msrc to m */
+    memcpy(m->m_pkthdr.header, ip, shlen); /* initialize respond IP header with data from original one. */
 
-    /* make the header of the reply packet */
-    ip   = mtod(m, struct ip *);
-    hlen = sizeof(struct ip);             /* no options in reply */
+    ip   = mtod(m, struct ip *); /* ip points to new IP header */
+    hlen = sizeof(struct ip);  /* trim the IP header no options in reply */
 
     /* fill in icmp */
-    m->m_data += hlen;
-    m->m_len  -= hlen;
-
-    icp = mtod(m, struct icmp *);
-
-    if (minsize)
-        s_ip_len = shlen+ICMP_MINLEN;      /* return header+8b only */
-    else if (s_ip_len > ICMP_MAXDATALEN)   /* maximum size */
-        s_ip_len = ICMP_MAXDATALEN;
-
-    m->m_len = ICMP_MINLEN + s_ip_len;     /* 8 bytes ICMP header */
-
-    /* min. size = 8+sizeof(struct ip)+8 */
+    m->m_data += hlen; /* shifts m_data to ICMP header */
+    icp = mtod(m, struct icmp *); /* _icp_: points to the ICMP header */
+    m->m_data += RT_OFFSETOF(struct icmp, icmp_ip); /* shifts m_data to IP header payload */
 
     icp->icmp_type = type;
     icp->icmp_code = code;
     icp->icmp_id = 0;
     icp->icmp_seq = 0;
 
-    memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len);   /* report the ip packet */
-
     HTONS(icp->icmp_ip.ip_len);
     HTONS(icp->icmp_ip.ip_id);
     HTONS(icp->icmp_ip.ip_off);
 
+    memcpy(mtod(m, void *), mtod(msrc, void *), shlen);  /* copy original IP header (with options) */
+    msrc->m_data += shlen; /* _msrc_: shifts m_data of original mbuf to the end of original IP header */
+    msrc->m_len -= shlen; /* _msrc_: alter m_len to size of original IP datagram payload */
+    m->m_data += shlen; /* _m_: shifts m_data to the end of reported IP datagram */
+    /* initialize reported payload of original datagram  with MUST size RFC792 or with rest of allocated mbuf */
+    s_ip_len = minsize ? 8 : M_TRAILINGSPACE(m);
+    /* trims original IP datagram's payload to the lenght of its mbuf size or already reserved space if it's smaller */
+    s_ip_len = RT_MIN(s_ip_len, msrc->m_len);
+    memcpy(mtod(m, void *), mtod(msrc, void *), s_ip_len);
+
 #if DEBUG
     if (message)
     {
-        /* DEBUG : append message to ICMP packet */
+
         size_t message_len;
+        /**
+         * Trim reported payload to first eight bytes (RFC792) to let sniffering tools do
+         * their audit duties, and add hint message to the tail of mandatory piece.
+         */
+        s_ip_len = 8;
+        /**
+         * _m_: shifts m_data to the end of mandatory 8b piece to let M_TRAILINGSPACE
+         * to returns available space with counting mandatory region.
+         */
+        m->m_data += s_ip_len;
         message_len = strlen(message);
-        if (message_len > ICMP_MAXDATALEN)
-            message_len = ICMP_MAXDATALEN;
+        if (message_len > M_TRAILINGSPACE(m))
+            message_len = M_TRAILINGSPACE(m);
+   
+        /**
+         * m->m_data points to the end of 8 bytes payload, and m->m_len is length of appended 
+         * message.
+         */
         m_append(pData, m, (int)message_len, message);
+        m->m_data -= s_ip_len; /* now we're ready for further processing, with pointing to mandatory payload */
     }
 #else
     NOREF(message);
 #endif
+    
+    m->m_data -= shlen + RT_OFFSETOF(struct icmp, icmp_ip); /* _m_: shifts m_data to the start of ICMP header */
+    m->m_len += s_ip_len + shlen + RT_OFFSETOF(struct icmp, icmp_ip); /* _m_: m_len counts bytes in IP payload */
+
+    /**
+     * It asserts if calculation above is wrong. 
+     */
+    Assert(icp == mtod(m, struct icmp*));
 
     icp->icmp_cksum = 0;
     icp->icmp_cksum = cksum(m, m->m_len);
@@ -736,6 +746,11 @@ void icmp_error(PNATState pData, struct mbuf *msrc, u_char type, u_char code, in
     /* returns pointer back. */
     m->m_data -= hlen;
     m->m_len  += hlen;
+    
+    /**
+     * paranoid. if something goes wrong previous assert should be triggered.
+     */
+    Assert(ip == mtod(m, struct ip*));
     (void) ip_output0(pData, (struct socket *)NULL, m, 1);
 
     icmpstat.icps_reflect++;
@@ -750,7 +765,7 @@ end_error:
     /*
      * clear source datagramm in case if some of requirement haven't been met.
      */
-    if (!msrc)
+    if (msrc)
         m_freem(pData, msrc);
 
     {
@@ -763,7 +778,6 @@ end_error:
     }
     LogFlowFuncLeave();
 }
-#undef ICMP_MAXDATALEN
 
 /*
  * Reflect the ip packet back to the source
diff --git a/src/VBox/Devices/Network/slirp/libslirp.h b/src/VBox/Devices/Network/slirp/libslirp.h
index 7c3ea1e..c00071c 100644
--- a/src/VBox/Devices/Network/slirp/libslirp.h
+++ b/src/VBox/Devices/Network/slirp/libslirp.h
@@ -95,6 +95,21 @@ void slirp_set_mtu(PNATState, int);
 void slirp_info(PNATState pData, const void *pvArg, const char *pszArgs);
 void slirp_set_somaxconn(PNATState pData, int iSoMaxConn);
 
+/**
+ * This method help DrvNAT to select strategy: about VMRESUMEREASON_HOST_RESUME:
+ * - proceed with link termination (we let guest track host DNS settings)
+ *    VBOX_NAT_HNCE_EXPOSED_NAME_RESOLVING_INFO
+ * - enforce internal DNS update (we are using dnsproxy and track but don't export DNS host settings)
+ *    VBOX_NAT_HNCE_DNSPROXY
+ * - ignore (NAT configured to use hostresolver - we aren't track any host DNS changes)
+ *    VBOX_NAT_HNCE_HOSTRESOLVER
+ * @note: It's safe to call this method from any thread, because settings we're checking 
+ * are immutable at runtime.
+ */
+#define VBOX_NAT_HNCE_EXSPOSED_NAME_RESOLUTION_INFO 0
+#define VBOX_NAT_HNCE_DNSPROXY 1
+#define VBOX_NAT_HNCE_HOSTRESOLVER 2
+int slirp_host_network_configuration_change_strategy_selector(const PNATState);
 #if defined(RT_OS_WINDOWS)
 
 
diff --git a/src/VBox/Devices/Network/slirp/resolv_conf_parser.c b/src/VBox/Devices/Network/slirp/resolv_conf_parser.c
new file mode 100644
index 0000000..dd5fb82
--- /dev/null
+++ b/src/VBox/Devices/Network/slirp/resolv_conf_parser.c
@@ -0,0 +1,539 @@
+/* $Id: resolv_conf_parser.c $ */
+/** @file
+ * resolv_conf_parser.c - parser of resolv.conf resolver(5)
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <iprt/assert.h>
+#include <iprt/initterm.h>
+#include <iprt/net.h>
+#include <iprt/string.h>
+#include <iprt/stream.h>
+#include <iprt/thread.h>
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+
+#include "resolv_conf_parser.h"
+
+enum RCP_TOKEN
+{
+  tok_eof = -1, /* EOF */
+  tok_string = -2, /* string */
+  tok_number = -3, /* number */
+  tok_ipv4 = -4, /* ipv4 */
+  tok_ipv4_port = -5, /* ipv4 port */
+  tok_ipv6 = -6, /* ipv6 */
+  tok_ipv6_port = -7, /* ipv6 port */
+  tok_nameserver = -8, /* nameserver */
+  tok_port = -9, /* port, Mac OSX specific */
+  tok_domain = -10, /* domain */
+  tok_search = -11, /* search */
+  tok_search_order = -12, /* search order */
+  tok_sortlist = -13, /* sortlist */
+  tok_timeout = -14, /* timeout */
+  tok_options = -15, /* options */
+  tok_option = -16, /* option */
+  tok_comment = -17, /* comment */
+  tok_error = -20
+};
+
+#define RCP_BUFFER_SIZE 256
+
+
+struct rcp_parser
+{
+    enum RCP_TOKEN rcpp_token;
+    char rcpp_str_buffer[RCP_BUFFER_SIZE];
+    struct rcp_state *rcpp_state;
+    PRTSTREAM rcpp_stream;
+};
+
+
+#define GETCHAR(parser) (RTStrmGetCh((parser)->rcpp_stream))
+#define EOF (-1)
+
+
+#define PARSER_STOP(tok, parser, ptr) (   (tok) != EOF \
+                                       && (((ptr) - (parser)->rcpp_str_buffer) != (RCP_BUFFER_SIZE - 1)))
+#define PARSER_BUFFER_EXCEEDED(parser, ptr)                             \
+  do {                                                                  \
+      if (((ptr) - (parser)->rcpp_str_buffer) == (RCP_BUFFER_SIZE - 1)) { \
+          return tok_error;                                             \
+      }                                                                 \
+  }while(0);
+
+static int rcp_get_token(struct rcp_parser *parser)
+{
+    char tok = ' ';
+    char *ptr;
+    size_t ptr_len;
+
+    while (isspace(tok))
+        tok = GETCHAR(parser);
+
+    ptr = parser->rcpp_str_buffer;
+
+    /* tok can't be ipv4 */
+    if (isalnum(tok)) {
+        int xdigit, digit, dot_number;
+        RT_ZERO(parser->rcpp_str_buffer);
+
+        dot_number = 0;
+        xdigit = 1;
+        digit = 1;
+        do {
+            *ptr++ = tok;
+            tok = GETCHAR(parser);
+
+            if (!isalnum(tok) && tok != ':' && tok != '.' && tok != '-' && tok != '_')
+                break;
+
+            /**
+             * if before ':' there were only [0-9][a-f][A-F],
+             * then it can't be option.
+             */
+            xdigit &= (isxdigit(tok) || (tok == ':'));
+            /**
+             * We want hint to differ ipv4 and network name.
+             */
+            digit &= (isdigit(tok) || (tok == '.'));
+
+            if (tok == ':')
+            {
+                if (xdigit == 1)
+                {
+                    int port = 0;
+                    do
+                    {
+                        *ptr++ = tok;
+                        tok = GETCHAR(parser);
+
+                        if (tok == '.')
+                            port++;
+
+                    } while(PARSER_STOP(tok, parser, ptr) && (tok == ':' || tok == '.' || isxdigit(tok)));
+
+                    PARSER_BUFFER_EXCEEDED(parser, ptr);
+
+                    if (port == 0)
+                        return tok_ipv6;
+                    else if (port == 1)
+                        return tok_ipv6_port;
+                    else
+                    {
+                        /* eats rest of the token */
+                        do
+                        {
+                            *ptr++ = tok;
+                            tok = GETCHAR(parser);
+                        } while(   PARSER_STOP(tok, parser, ptr)
+                                && (isalnum(tok) || tok == '.'  || tok == '_' || tok == '-'));
+
+                        PARSER_BUFFER_EXCEEDED(parser, ptr);
+
+                        return tok_string;
+                    }
+                }
+                else {
+                    /* XXX: need further experiments */
+                    return tok_option; /* option with value */
+                }
+            }
+
+            if (tok == '.')
+            {
+                do {
+                    if (tok == '.') dot_number++;
+
+                    *ptr++ = tok;
+                    digit &= (isdigit(tok) || (tok == '.'));
+                    tok = GETCHAR(parser);
+                } while(   PARSER_STOP(tok, parser, ptr)
+                        && (isalnum(tok) || tok == '.' || tok == '_' || tok == '-'));
+
+                PARSER_BUFFER_EXCEEDED(parser, ptr);
+
+                if (dot_number == 3 && digit)
+                    return tok_ipv4;
+                else if (dot_number == 4 && digit)
+                    return tok_ipv4_port;
+                else
+                    return tok_string;
+            }
+        } while(   PARSER_STOP(tok, parser, ptr)
+                && (isalnum(tok) || tok == ':' || tok == '.' || tok == '-' || tok == '_'));
+
+        PARSER_BUFFER_EXCEEDED(parser, ptr);
+
+        if (digit || xdigit)
+            return tok_number;
+        if (RTStrCmp(parser->rcpp_str_buffer, "nameserver") == 0)
+            return tok_nameserver;
+        if (RTStrCmp(parser->rcpp_str_buffer, "port") == 0)
+            return tok_port;
+        if (RTStrCmp(parser->rcpp_str_buffer, "domain") == 0)
+            return tok_domain;
+        if (RTStrCmp(parser->rcpp_str_buffer, "search") == 0)
+            return tok_search;
+        if (RTStrCmp(parser->rcpp_str_buffer, "search_order") == 0)
+            return tok_search_order;
+        if (RTStrCmp(parser->rcpp_str_buffer, "sortlist") == 0)
+            return tok_sortlist;
+        if (RTStrCmp(parser->rcpp_str_buffer, "timeout") == 0)
+            return tok_timeout;
+        if (RTStrCmp(parser->rcpp_str_buffer, "options") == 0)
+            return tok_options;
+
+        return tok_string;
+    }
+
+    if (tok == EOF) return tok_eof;
+
+    if (tok == '#')
+    {
+        do{
+            tok = GETCHAR(parser);
+        } while (tok != EOF && tok != '\r' && tok != '\n');
+
+        if (tok == EOF) return tok_eof;
+
+        return tok_comment;
+    }
+    return tok;
+}
+
+#undef PARSER_STOP
+#undef PARSER_BUFFER_EXCEEDED
+
+/**
+ * nameserverexpr ::= 'nameserver' ip+
+ * @note: resolver(5) ip ::= (ipv4|ipv6)(.number)?
+ */
+static enum RCP_TOKEN rcp_parse_nameserver(struct rcp_parser *parser)
+{
+    enum RCP_TOKEN tok = rcp_get_token(parser); /* eats 'nameserver' */
+
+    if (  (   tok != tok_ipv4
+           && tok != tok_ipv4_port
+           && tok != tok_ipv6
+           && tok != tok_ipv6_port)
+        || tok == EOF)
+        return tok_error;
+
+    while (   tok == tok_ipv4
+           || tok == tok_ipv4_port
+           || tok == tok_ipv6
+           || tok == tok_ipv6_port)
+    {
+        struct rcp_state *st;
+        RTNETADDR *address;
+        char *str_address;
+
+        Assert(parser->rcpp_state);
+
+        st = parser->rcpp_state;
+
+        /* It's still valid resolv.conf file, just rest of the nameservers should be ignored */
+        if (st->rcps_num_nameserver >= RCPS_MAX_NAMESERVERS)
+            return rcp_get_token(parser);
+
+        address = &st->rcps_nameserver[st->rcps_num_nameserver];
+        str_address = &st->rcps_nameserver_str_buffer[st->rcps_num_nameserver * RCPS_IPVX_SIZE];
+
+#ifdef RT_OS_DARWIN
+        if (   tok == tok_ipv4_port
+            || (   tok == tok_ipv6_port
+                && (st->rcps_flags & RCPSF_IGNORE_IPV6) == 0))
+        {
+            char *ptr = &parser->rcpp_str_buffer[strlen(parser->rcpp_str_buffer)];
+            while (*(--ptr) != '.');
+            *ptr = '\0';
+            address->uPort = RTStrToUInt16(ptr + 1);
+
+            if (address->uPort == 0) return tok_error;
+        }
+#endif
+        /**
+         * if we on Darwin upper code will cut off port if it's.
+         */
+        if ((st->rcps_flags & RCPSF_NO_STR2IPCONV) != 0)
+        {
+            if (strlen(parser->rcpp_str_buffer) > RCPS_IPVX_SIZE)
+                return tok_error;
+
+            strcpy(str_address, parser->rcpp_str_buffer);
+
+            st->rcps_str_nameserver[st->rcps_num_nameserver] = str_address;
+
+            goto loop_prolog;
+        }
+
+        switch (tok)
+        {
+            case tok_ipv4:
+            case tok_ipv4_port:
+                {
+                    int rc = RTNetStrToIPv4Addr(parser->rcpp_str_buffer, &address->uAddr.IPv4);
+                    if (RT_FAILURE(rc)) return tok_error;
+
+                    address->enmType = RTNETADDRTYPE_IPV4;
+                }
+
+                break;
+            case tok_ipv6:
+            case tok_ipv6_port:
+                {
+                    int rc;
+
+                    if ((st->rcps_flags & RCPSF_IGNORE_IPV6) != 0)
+                        return rcp_get_token(parser);
+
+                    rc = inet_pton(AF_INET6, parser->rcpp_str_buffer,
+                                       &address->uAddr.IPv6);
+                    if (rc == -1)
+                        return tok_error;
+
+                    address->enmType = RTNETADDRTYPE_IPV6;
+                }
+
+                break;
+            default: /* loop condition doesn't let enter enything */
+                AssertMsgFailed(("shouldn't ever happen tok:%d, %s", tok,
+                                 isprint(tok) ? parser->rcpp_str_buffer : "#"));
+                break;
+        }
+
+    loop_prolog:
+        st->rcps_num_nameserver++;
+        tok = rcp_get_token(parser);
+    }
+    return tok;
+}
+
+/**
+ * portexpr ::= 'port' [0-9]+
+ */
+static enum RCP_TOKEN rcp_parse_port(struct rcp_parser *parser)
+{
+    struct rcp_state *st;
+    enum RCP_TOKEN tok = rcp_get_token(parser); /* eats 'port' */
+
+    Assert(parser->rcpp_state);
+    st = parser->rcpp_state;
+
+    if (   tok != tok_number
+        || tok == tok_eof)
+        return tok_error;
+
+    st->rcps_port = RTStrToUInt16(parser->rcpp_str_buffer);
+
+    if (st->rcps_port == 0)
+        return tok_error;
+
+    return rcp_get_token(parser);
+}
+
+/**
+ * domainexpr ::= 'domain' string
+ */
+static enum RCP_TOKEN rcp_parse_domain(struct rcp_parser *parser)
+{
+    struct rcp_state *st;
+    enum RCP_TOKEN tok = rcp_get_token(parser); /* eats 'domain' */
+
+    Assert(parser->rcpp_state);
+    st = parser->rcpp_state;
+
+    /**
+     * It's nowhere specified how resolver should react on dublicats
+     * of 'domain' declarations, let's assume that resolv.conf is broken.
+     */
+    if (   tok == tok_eof
+        || tok == tok_error
+        || st->rcps_domain != NULL)
+        return tok_error;
+
+    strcpy(st->rcps_domain_buffer, parser->rcpp_str_buffer);
+    /**
+     * We initialize this pointer in place, just make single pointer check
+     * in 'domain'-less resolv.conf.
+     */
+    st->rcps_domain = st->rcps_domain_buffer;
+
+    return rcp_get_token(parser);
+}
+
+/**
+ * searchexpr ::= 'search' (string)+
+ * @note: resolver (5) Mac OSX:
+ * "The search list is currently limited to six domains with a total of 256 characters."
+ * @note: resolv.conf (5) Linux:
+ * "The search list is currently limited to six domains with a total of 256 characters."
+ */
+static enum RCP_TOKEN rcp_parse_search(struct rcp_parser *parser)
+{
+    unsigned i, len, trailing;
+    char *ptr;
+    struct rcp_state *st;
+    enum RCP_TOKEN tok = rcp_get_token(parser); /* eats 'search' */
+
+    Assert(parser->rcpp_state);
+    st = parser->rcpp_state;
+
+    /**
+     * We asume that duplication of search list in resolv.conf isn't correct.
+     */
+    if (   tok == tok_eof
+        || tok == tok_error
+        || tok != tok_string
+        || st->rcps_searchlist[0] != NULL)
+        return tok_error;
+
+    i = 0;
+    trailing = RCPS_BUFFER_SIZE;
+    do {
+        len = strlen(parser->rcpp_str_buffer);
+
+        if (len + 1 > trailing)
+            break; /* not enough room for new entry */
+
+        ptr = st->rcps_searchlist_buffer + RCPS_BUFFER_SIZE - trailing;
+        strcpy(ptr, parser->rcpp_str_buffer);
+
+        trailing -= len + 1; /* 1 reserved for '\0' */
+
+        st->rcps_searchlist[i] = ptr;
+
+    } while(  (tok = rcp_get_token(parser)) == tok_string
+            && ++i != RCPS_MAX_SEARCHLIST);
+
+    st->rcps_num_searchlist = i;
+
+    return tok;
+}
+
+/**
+ * expr ::= nameserverexpr | expr
+ *      ::= portexpr | expr
+ *      ::= domainexpr | expr
+ *      ::= searchexpr | expr
+ *      ::= searchlistexpr | expr
+ *      ::= search_orderexpr | expr
+ *      ::= timeoutexpr | expr
+ *      ::= optionsexpr | expr
+ */
+static int rcp_parse_primary(struct rcp_parser *parser)
+{
+    enum RCP_TOKEN tok;
+    tok = rcp_get_token(parser);
+
+    while(   tok != tok_eof
+          && tok != tok_error)
+    {
+        switch (tok)
+        {
+            case tok_nameserver:
+                tok = rcp_parse_nameserver(parser);
+                break;
+            case tok_port:
+                tok = rcp_parse_port(parser);
+                break;
+            case tok_domain:
+                tok = rcp_parse_domain(parser);
+                break;
+            case tok_search:
+                tok = rcp_parse_search(parser);
+                break;
+            default:
+                tok = rcp_get_token(parser);
+        }
+    }
+
+    if (tok == tok_error)
+        return -1;
+
+    return 0;
+}
+
+
+int rcp_parse(struct rcp_state* state, const char *filename)
+{
+    unsigned i;
+    uint32_t flags;
+    int rc;
+    struct rcp_parser parser;
+    flags = state->rcps_flags;
+
+    RT_ZERO(parser);
+    RT_ZERO(*state);
+
+    state->rcps_flags = flags;
+
+    parser.rcpp_state = state;
+
+    /**
+     * for debugging need: with RCP_STANDALONE it's possible
+     * to run simplefied scenarious like
+     *
+     * # cat /etc/resolv.conf | rcp-test-0
+     * or in lldb
+     * # process launch -i /etc/resolv.conf
+     */
+#ifdef RCP_STANDALONE
+    if (filename == NULL)
+        parser.rcpp_stream = g_pStdIn;
+#else
+    if (filename == NULL)
+        return -1;
+#endif
+    else
+    {
+        rc = RTStrmOpen(filename, "r", &parser.rcpp_stream);
+        if (RT_FAILURE(rc)) return -1;
+    }
+
+    rc = rcp_parse_primary(&parser);
+
+    if (filename != NULL)
+        RTStrmClose(parser.rcpp_stream);
+
+    if (rc == -1)
+        return -1;
+
+#ifdef RT_OS_DARWIN
+    /**
+     * port recolv.conf's option and IP.port are Mac OSX extentions, there're no need to care on
+     * other hosts.
+     */
+    if (state->rcps_port == 0)
+        state->rcps_port = 53;
+
+    for(i = 0;  (state->rcps_flags & RCPSF_NO_STR2IPCONV) == 0
+             && i != RCPS_MAX_NAMESERVERS; ++i)
+    {
+        RTNETADDR *addr = &state->rcps_nameserver[i];
+
+        if (addr->uPort == 0)
+            addr->uPort = state->rcps_port;
+    }
+#endif
+
+    if (   state->rcps_domain == NULL
+        && state->rcps_searchlist[0] != NULL)
+        state->rcps_domain = state->rcps_searchlist[0];
+
+    return 0;
+}
diff --git a/src/VBox/Devices/Network/slirp/resolv_conf_parser.h b/src/VBox/Devices/Network/slirp/resolv_conf_parser.h
new file mode 100644
index 0000000..21353fe
--- /dev/null
+++ b/src/VBox/Devices/Network/slirp/resolv_conf_parser.h
@@ -0,0 +1,109 @@
+/* $Id: resolv_conf_parser.h $ */
+/** @file
+ * resolv_conf_parser.h - interface to parser of resolv.conf resolver(5) 
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __RESOLV_CONF_PARSER_H__
+#define __RESOLV_CONF_PARSER_H__
+
+#include <iprt/cdefs.h>
+#include <iprt/net.h>
+
+RT_C_DECLS_BEGIN
+
+#define RCPS_MAX_NAMESERVERS 3
+#define RCPS_MAX_SEARCHLIST 10
+#define RCPS_BUFFER_SIZE 256
+#define RCPS_IPVX_SIZE 47
+/**
+ * In Slirp we don't need IPv6 for general case (only for dnsproxy mode 
+ * it's potentially acceptable) 
+ */
+#define RCPSF_IGNORE_IPV6 RT_BIT(0)
+/**
+ * In Main, we perhaps don't need parsed IPv6 and IPv4, because parsed values are
+ * used in Network services.
+ */
+#define RCPSF_NO_STR2IPCONV RT_BIT(1)
+
+struct rcp_state
+{
+    uint16_t rcps_port;
+    /**
+     * Filling of this array ommited iff RCPSF_NO_STR2IPCONF in rcp_state::rcps_flags set.
+     */
+    RTNETADDR rcps_nameserver[RCPS_MAX_NAMESERVERS];
+    /**
+     * this array contains non-NULL (pointing to rcp_state::rcps_nameserver_str_buffer) iff
+     * RCPSF_NO_STR2IPCONF in rcp_state::rcps_flags set.
+     */
+    char *rcps_str_nameserver[RCPS_MAX_NAMESERVERS];
+    unsigned rcps_num_nameserver;
+    /**
+     * Shortcuts to storage, note that domain is optional
+     * and if it's missed in resolv.conf rcps_domain should be equal
+     * to rcps_search_list[0]
+     */
+    char *rcps_domain;
+    char *rcps_searchlist[RCPS_MAX_SEARCHLIST];
+    unsigned rcps_num_searchlist;
+
+    uint32_t rcps_flags;
+
+    char rcps_domain_buffer[RCPS_BUFFER_SIZE];
+    char rcps_searchlist_buffer[RCPS_BUFFER_SIZE];
+    char rcps_nameserver_str_buffer[RCPS_MAX_NAMESERVERS * RCPS_IPVX_SIZE];
+};
+
+
+/**
+ *  This function parses specified file (expected to conform resolver (5) Mac OSX or resolv.conf (3) Linux)
+ *  and fills the structure.
+ * @return 0 - on success
+ *         -1 - on fail.
+ *   <code>
+ *   struct rcp_state state;
+ *   int rc;
+ *
+ *   rc = rcp_parse(&state, "/etc/resolv.conf");
+ *   for(i = 0; rc == 0 && i != state.rcps_num_nameserver; ++i)
+ *   {
+ *      if ((state.rcps_flags & RCPSF_NO_STR2IPCONV) == 0)
+ *      {
+ *          const RTNETADDR *addr = &state.rcps_nameserver[i];
+ *
+ *          switch (state.rcps_nameserver[i].enmType)
+ *          {
+ *              case RTNETADDRTYPE_IPV4:
+ *                  RTPrintf("nameserver[%d]: [%RTnaipv4]:%d\n", i, addr->uAddr.IPv4, addr->uPort);
+ *                  break;
+ *              case RTNETADDRTYPE_IPV6:
+ *                  RTPrintf("nameserver[%d]: [%RTnaipv6]:%d\n", i, &addr->uAddr.IPv6, addr->uPort);
+ *                  break;
+ *              default:
+ *                   break;
+ *          }
+ *      }
+ *      else
+ *          RTPrintf("nameserver[%d]: %s\n", i, state.rcps_str_nameserver[i]);
+ *  }
+ *   </code>
+ *
+ */
+int rcp_parse(struct rcp_state *, const char *);
+
+RT_C_DECLS_END
+
+#endif
diff --git a/src/VBox/Devices/Network/slirp/slirp.c b/src/VBox/Devices/Network/slirp/slirp.c
index 69eaa93..2a7ecfd 100644
--- a/src/VBox/Devices/Network/slirp/slirp.c
+++ b/src/VBox/Devices/Network/slirp/slirp.c
@@ -2027,3 +2027,11 @@ void slirp_info(PNATState pData, const void *pvArg, const char *pszArgs)
                         rule->activated ? ' ' : '*');
     }
 }
+
+
+int slirp_host_network_configuration_change_strategy_selector(const PNATState pData)
+{
+    if (pData->fUseHostResolver) return VBOX_NAT_HNCE_HOSTRESOLVER;
+    if (pData->fUseDnsProxy) return VBOX_NAT_HNCE_DNSPROXY;
+    return VBOX_NAT_HNCE_EXSPOSED_NAME_RESOLUTION_INFO;
+}
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm
index 82dc3be..ef96042 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm
@@ -838,15 +838,15 @@ _fd_parm:                                    ; 0xf0000 LB 0x5b
 _fd_map:                                     ; 0xf005b LB 0xf
     db  001h, 000h, 002h, 002h, 003h, 003h, 004h, 004h, 005h, 005h, 00eh, 006h, 00fh, 006h, 000h
 _pktacc:                                     ; 0xf006a LB 0xc
-    db  000h, 000h, 000h, 000h, 000h, 000h, 02ah, 028h, 0cdh, 078h, 023h, 086h
+    db  000h, 000h, 000h, 000h, 000h, 000h, 03fh, 028h, 0e2h, 078h, 0aah, 086h
 _softrst:                                    ; 0xf0076 LB 0xc
-    db  000h, 000h, 000h, 000h, 000h, 000h, 012h, 02bh, 022h, 036h, 022h, 036h
+    db  000h, 000h, 000h, 000h, 000h, 000h, 027h, 02bh, 037h, 036h, 037h, 036h
 _dskacc:                                     ; 0xf0082 LB 0x2e
-    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 073h, 027h, 0edh, 027h, 000h, 000h, 000h, 000h
-    db  061h, 077h, 017h, 078h, 01fh, 085h, 0b3h, 085h, 000h, 000h, 000h, 000h, 000h, 000h, 05fh, 033h
+    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 088h, 027h, 002h, 028h, 000h, 000h, 000h, 000h
+    db  076h, 077h, 02ch, 078h, 0a6h, 085h, 03ah, 086h, 000h, 000h, 000h, 000h, 000h, 000h, 05fh, 033h
     db  032h, 05fh, 000h, 0dah, 00fh, 000h, 000h, 001h, 0f3h, 000h, 000h, 000h, 000h, 000h
 
-section CONST progbits vstart=0xb0 align=1 ; size=0xce0 class=DATA group=DGROUP
+section CONST progbits vstart=0xb0 align=1 ; size=0xcf8 class=DATA group=DGROUP
     db   'NMI Handler called', 00ah, 000h
     db   'INT18: BOOT FAILURE', 00ah, 000h
     db   '%s', 00ah, 000h, 000h
@@ -922,10 +922,11 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xce0 class=DATA group=DGROUP
     db   'INT 15h C2 AL=6, BH=%02x', 00ah, 000h
     db   'INT 15h C2 default case entered', 00ah, 000h, 000h
     db   'Key pressed: %x', 00ah, 000h
-    db   00ah, 00ah, 'AHCI controller:', 00ah, 000h
+    db   00ah, 00ah, '  AHCI controller:', 000h
     db   00ah, '    %d) Hard disk', 000h
-    db   00ah, 00ah, 'SCSI controller:', 00ah, 000h
-    db   'IDE controller:', 00ah, 000h
+    db   00ah, 00ah, '  SCSI controller:', 000h
+    db   '  IDE controller:', 000h
+    db   00ah, 00ah, 'AHCI controller:', 00ah, 000h
     db   00ah, '    %d) ', 000h
     db   'Secondary ', 000h
     db   'Primary ', 000h
@@ -939,7 +940,7 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xce0 class=DATA group=DGROUP
     db   00ah, 'Other boot devices:', 00ah, ' f) Floppy', 00ah, ' c) CD-ROM', 00ah
     db   ' l) LAN', 00ah, 00ah, ' b) Continue booting', 00ah, 000h
     db   'Delaying boot for %d seconds:', 000h
-    db   ' %d', 000h
+    db   ' %d', 000h, 000h
     db   'scsi_read_sectors: device_id out of range %d', 00ah, 000h
     db   'scsi_write_sectors: device_id out of range %d', 00ah, 000h
     db   'scsi_cmd_packet', 000h
@@ -962,20 +963,20 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xce0 class=DATA group=DGROUP
     db   'APM: Unsupported function AX=%04X BX=%04X called', 00ah, 000h, 000h
     db   'PCI: Unsupported function AX=%04X BX=%04X called', 00ah, 000h
 
-section CONST2 progbits vstart=0xd90 align=1 ; size=0x3fa class=DATA group=DGROUP
-_bios_cvs_version_string:                    ; 0xf0d90 LB 0x12
-    db  'VirtualBox 4.3.6', 000h, 000h
-_bios_prefix_string:                         ; 0xf0da2 LB 0x8
+section CONST2 progbits vstart=0xda8 align=1 ; size=0x3fa class=DATA group=DGROUP
+_bios_cvs_version_string:                    ; 0xf0da8 LB 0x12
+    db  'VirtualBox 4.3.8', 000h, 000h
+_bios_prefix_string:                         ; 0xf0dba LB 0x8
     db  'BIOS: ', 000h, 000h
-_isotag:                                     ; 0xf0daa LB 0x6
+_isotag:                                     ; 0xf0dc2 LB 0x6
     db  'CD001', 000h
-_eltorito:                                   ; 0xf0db0 LB 0x18
+_eltorito:                                   ; 0xf0dc8 LB 0x18
     db  'EL TORITO SPECIFICATION', 000h
-_drivetypes:                                 ; 0xf0dc8 LB 0x28
+_drivetypes:                                 ; 0xf0de0 LB 0x28
     db  046h, 06ch, 06fh, 070h, 070h, 079h, 000h, 000h, 000h, 000h, 048h, 061h, 072h, 064h, 020h, 044h
     db  069h, 073h, 06bh, 000h, 043h, 044h, 02dh, 052h, 04fh, 04dh, 000h, 000h, 000h, 000h, 04ch, 041h
     db  04eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h
-_scan_to_scanascii:                          ; 0xf0df0 LB 0x37a
+_scan_to_scanascii:                          ; 0xf0e08 LB 0x37a
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01bh, 001h, 01bh, 001h, 01bh, 001h
     db  000h, 001h, 000h, 000h, 031h, 002h, 021h, 002h, 000h, 000h, 000h, 078h, 000h, 000h, 032h, 003h
     db  040h, 003h, 000h, 003h, 000h, 079h, 000h, 000h, 033h, 004h, 023h, 004h, 000h, 000h, 000h, 07ah
@@ -1032,13 +1033,13 @@ _scan_to_scanascii:                          ; 0xf0df0 LB 0x37a
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 056h, 07ch, 056h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 085h, 000h, 087h, 000h, 089h, 000h, 08bh, 000h, 000h
     db  000h, 086h, 000h, 088h, 000h, 08ah, 000h, 08ch, 000h, 000h
-_panic_msg_keyb_buffer_full:                 ; 0xf116a LB 0x20
+_panic_msg_keyb_buffer_full:                 ; 0xf1182 LB 0x20
     db  '%s: keyboard input buffer full', 00ah, 000h
 
-  ; Padding 0x476 bytes at 0xf118a
-  times 1142 db 0
+  ; Padding 0x45e bytes at 0xf11a2
+  times 1118 db 0
 
-section _TEXT progbits vstart=0x1600 align=1 ; size=0x7e65 class=CODE group=AUTO
+section _TEXT progbits vstart=0x1600 align=1 ; size=0x7f15 class=CODE group=AUTO
 read_byte_:                                  ; 0xf1600 LB 0xe
     push bx                                   ; 53
     push bp                                   ; 55
@@ -1101,13 +1102,18 @@ write_dword_:                                ; 0xf164a LB 0x12
     pop bp                                    ; 5d
     pop si                                    ; 5e
     retn                                      ; c3
-inb_cmos_:                                   ; 0xf165c LB 0x14
+inb_cmos_:                                   ; 0xf165c LB 0x1d
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
-    mov dx, strict word 00070h                ; ba 70 00
+    mov AH, strict byte 070h                  ; b4 70
+    cmp AL, strict byte 080h                  ; 3c 80
+    jc short 01668h                           ; 72 02
+    mov AH, strict byte 072h                  ; b4 72
+    movzx dx, ah                              ; 0f b6 d4
     out DX, AL                                ; ee
-    mov dx, strict word 00071h                ; ba 71 00
+    movzx dx, ah                              ; 0f b6 d4
+    inc dx                                    ; 42
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
@@ -1115,19 +1121,26 @@ inb_cmos_:                                   ; 0xf165c LB 0x14
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-outb_cmos_:                                  ; 0xf1670 LB 0x13
+outb_cmos_:                                  ; 0xf1679 LB 0x1f
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
+    push bx                                   ; 53
     mov ah, dl                                ; 88 d4
-    mov dx, strict word 00070h                ; ba 70 00
+    mov BL, strict byte 070h                  ; b3 70
+    cmp AL, strict byte 080h                  ; 3c 80
+    jc short 01687h                           ; 72 02
+    mov BL, strict byte 072h                  ; b3 72
+    movzx dx, bl                              ; 0f b6 d3
     out DX, AL                                ; ee
+    movzx dx, bl                              ; 0f b6 d3
+    inc dx                                    ; 42
     mov al, ah                                ; 88 e0
-    mov dx, strict word 00071h                ; ba 71 00
     out DX, AL                                ; ee
-    mov sp, bp                                ; 89 ec
+    lea sp, [bp-002h]                         ; 8d 66 fe
+    pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-_dummy_isr_function:                         ; 0xf1683 LB 0x6b
+_dummy_isr_function:                         ; 0xf1698 LB 0x6b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push ax                                   ; 50
@@ -1141,7 +1154,7 @@ _dummy_isr_function:                         ; 0xf1683 LB 0x6b
     mov bx, ax                                ; 89 c3
     mov byte [bp-002h], al                    ; 88 46 fe
     test al, al                               ; 84 c0
-    je short 016deh                           ; 74 43
+    je short 016f3h                           ; 74 43
     mov AL, strict byte 00bh                  ; b0 0b
     mov dx, 000a0h                            ; ba a0 00
     out DX, AL                                ; ee
@@ -1150,7 +1163,7 @@ _dummy_isr_function:                         ; 0xf1683 LB 0x6b
     ; sub ah, ah                                ; 2a e4
     mov cx, ax                                ; 89 c1
     test al, al                               ; 84 c0
-    je short 016c0h                           ; 74 16
+    je short 016d5h                           ; 74 16
     mov dx, 000a1h                            ; ba a1 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -1162,7 +1175,7 @@ _dummy_isr_function:                         ; 0xf1683 LB 0x6b
     mov AL, strict byte 020h                  ; b0 20
     mov dx, 000a0h                            ; ba a0 00
     out DX, AL                                ; ee
-    jmp short 016d5h                          ; eb 15
+    jmp short 016eah                          ; eb 15
     mov dx, strict word 00021h                ; ba 21 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -1180,67 +1193,67 @@ _dummy_isr_function:                         ; 0xf1683 LB 0x6b
     movzx bx, cl                              ; 0f b6 d9
     mov dx, strict word 0006bh                ; ba 6b 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 24 ff
+    call 0160eh                               ; e8 0f ff
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_nmi_handler_msg:                            ; 0xf16ee LB 0x12
+_nmi_handler_msg:                            ; 0xf1703 LB 0x12
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push 000b0h                               ; 68 b0 00
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 14 02
+    call 01922h                               ; e8 14 02
     add sp, strict byte 00004h                ; 83 c4 04
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_int18_panic_msg:                            ; 0xf1700 LB 0x12
+_int18_panic_msg:                            ; 0xf1715 LB 0x12
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push 000c4h                               ; 68 c4 00
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 02 02
+    call 01922h                               ; e8 02 02
     add sp, strict byte 00004h                ; 83 c4 04
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_log_bios_start:                             ; 0xf1712 LB 0x20
+_log_bios_start:                             ; 0xf1727 LB 0x20
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
-    mov bx, 00da2h                            ; bb a2 0d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 ac 01
-    push 00d90h                               ; 68 90 0d
+    call 018e1h                               ; e8 ac 01
+    push 00da8h                               ; 68 a8 0d
     push 000d9h                               ; 68 d9 00
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 e2 01
+    call 01922h                               ; e8 e2 01
     add sp, strict byte 00006h                ; 83 c4 06
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_print_bios_banner:                          ; 0xf1732 LB 0x2e
+_print_bios_banner:                          ; 0xf1747 LB 0x2e
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov dx, strict word 00072h                ; ba 72 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 de fe
+    call 0161ch                               ; e8 c9 fe
     mov cx, ax                                ; 89 c1
     xor bx, bx                                ; 31 db
     mov dx, strict word 00072h                ; ba 72 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 df fe
+    call 0162ah                               ; e8 ca fe
     cmp cx, 01234h                            ; 81 f9 34 12
-    jne short 01759h                          ; 75 08
+    jne short 0176eh                          ; 75 08
     mov AL, strict byte 003h                  ; b0 03
     mov AH, strict byte 000h                  ; b4 00
     int 010h                                  ; cd 10
-    jmp short 0175ch                          ; eb 03
-    call 07370h                               ; e8 14 5c
+    jmp short 01771h                          ; eb 03
+    call 07385h                               ; e8 14 5c
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-send_:                                       ; 0xf1760 LB 0x3b
+send_:                                       ; 0xf1775 LB 0x3b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -1248,19 +1261,19 @@ send_:                                       ; 0xf1760 LB 0x3b
     mov bx, ax                                ; 89 c3
     mov cl, dl                                ; 88 d1
     test AL, strict byte 008h                 ; a8 08
-    je short 01773h                           ; 74 06
+    je short 01788h                           ; 74 06
     mov al, dl                                ; 88 d0
     mov dx, 00403h                            ; ba 03 04
     out DX, AL                                ; ee
     test bl, 004h                             ; f6 c3 04
-    je short 0177eh                           ; 74 06
+    je short 01793h                           ; 74 06
     mov al, cl                                ; 88 c8
     mov dx, 00504h                            ; ba 04 05
     out DX, AL                                ; ee
     test bl, 002h                             ; f6 c3 02
-    je short 01794h                           ; 74 11
+    je short 017a9h                           ; 74 11
     cmp cl, 00ah                              ; 80 f9 0a
-    jne short 0178eh                          ; 75 06
+    jne short 017a3h                          ; 75 06
     mov AL, strict byte 00dh                  ; b0 0d
     mov AH, strict byte 00eh                  ; b4 0e
     int 010h                                  ; cd 10
@@ -1272,7 +1285,7 @@ send_:                                       ; 0xf1760 LB 0x3b
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-put_int_:                                    ; 0xf179b LB 0x5f
+put_int_:                                    ; 0xf17b0 LB 0x5f
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -1287,24 +1300,24 @@ put_int_:                                    ; 0xf179b LB 0x5f
     idiv di                                   ; f7 ff
     mov word [bp-006h], ax                    ; 89 46 fa
     test ax, ax                               ; 85 c0
-    je short 017c0h                           ; 74 0a
+    je short 017d5h                           ; 74 0a
     dec bx                                    ; 4b
     mov dx, ax                                ; 89 c2
     mov ax, si                                ; 89 f0
-    call 0179bh                               ; e8 dd ff
-    jmp short 017dbh                          ; eb 1b
+    call 017b0h                               ; e8 dd ff
+    jmp short 017f0h                          ; eb 1b
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jle short 017cfh                          ; 7e 0a
+    jle short 017e4h                          ; 7e 0a
     mov dx, strict word 00020h                ; ba 20 00
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 93 ff
-    jmp short 017c0h                          ; eb f1
+    call 01775h                               ; e8 93 ff
+    jmp short 017d5h                          ; eb f1
     test cx, cx                               ; 85 c9
-    je short 017dbh                           ; 74 08
+    je short 017f0h                           ; 74 08
     mov dx, strict word 0002dh                ; ba 2d 00
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 85 ff
+    call 01775h                               ; e8 85 ff
     mov al, byte [bp-006h]                    ; 8a 46 fa
     mov DL, strict byte 00ah                  ; b2 0a
     mul dl                                    ; f6 e2
@@ -1314,13 +1327,13 @@ put_int_:                                    ; 0xf179b LB 0x5f
     add AL, strict byte 030h                  ; 04 30
     movzx dx, al                              ; 0f b6 d0
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 6d ff
+    call 01775h                               ; e8 6d ff
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-put_uint_:                                   ; 0xf17fa LB 0x60
+put_uint_:                                   ; 0xf180f LB 0x60
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -1335,24 +1348,24 @@ put_uint_:                                   ; 0xf17fa LB 0x60
     div di                                    ; f7 f7
     mov word [bp-006h], ax                    ; 89 46 fa
     test ax, ax                               ; 85 c0
-    je short 01820h                           ; 74 0a
+    je short 01835h                           ; 74 0a
     dec bx                                    ; 4b
     mov dx, ax                                ; 89 c2
     mov ax, si                                ; 89 f0
-    call 017fah                               ; e8 dc ff
-    jmp short 0183bh                          ; eb 1b
+    call 0180fh                               ; e8 dc ff
+    jmp short 01850h                          ; eb 1b
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jle short 0182fh                          ; 7e 0a
+    jle short 01844h                          ; 7e 0a
     mov dx, strict word 00020h                ; ba 20 00
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 33 ff
-    jmp short 01820h                          ; eb f1
+    call 01775h                               ; e8 33 ff
+    jmp short 01835h                          ; eb f1
     test cx, cx                               ; 85 c9
-    je short 0183bh                           ; 74 08
+    je short 01850h                           ; 74 08
     mov dx, strict word 0002dh                ; ba 2d 00
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 25 ff
+    call 01775h                               ; e8 25 ff
     mov al, byte [bp-006h]                    ; 8a 46 fa
     mov DL, strict byte 00ah                  ; b2 0a
     mul dl                                    ; f6 e2
@@ -1362,13 +1375,13 @@ put_uint_:                                   ; 0xf17fa LB 0x60
     add AL, strict byte 030h                  ; 04 30
     movzx dx, al                              ; 0f b6 d0
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 0d ff
+    call 01775h                               ; e8 0d ff
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-put_luint_:                                  ; 0xf185a LB 0x72
+put_luint_:                                  ; 0xf186f LB 0x72
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -1382,30 +1395,30 @@ put_luint_:                                  ; 0xf185a LB 0x72
     mov dx, cx                                ; 89 ca
     mov bx, strict word 0000ah                ; bb 0a 00
     xor cx, cx                                ; 31 c9
-    call 09370h                               ; e8 fc 7a
+    call 09420h                               ; e8 97 7b
     mov word [bp-008h], ax                    ; 89 46 f8
     mov cx, dx                                ; 89 d1
     mov dx, ax                                ; 89 c2
     or dx, cx                                 ; 09 ca
-    je short 0188eh                           ; 74 0f
+    je short 018a3h                           ; 74 0f
     push word [bp+004h]                       ; ff 76 04
     lea dx, [di-001h]                         ; 8d 55 ff
     mov bx, ax                                ; 89 c3
     mov ax, si                                ; 89 f0
-    call 0185ah                               ; e8 ce ff
-    jmp short 018abh                          ; eb 1d
+    call 0186fh                               ; e8 ce ff
+    jmp short 018c0h                          ; eb 1d
     dec di                                    ; 4f
     test di, di                               ; 85 ff
-    jle short 0189dh                          ; 7e 0a
+    jle short 018b2h                          ; 7e 0a
     mov dx, strict word 00020h                ; ba 20 00
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 c5 fe
-    jmp short 0188eh                          ; eb f1
+    call 01775h                               ; e8 c5 fe
+    jmp short 018a3h                          ; eb f1
     cmp word [bp+004h], strict byte 00000h    ; 83 7e 04 00
-    je short 018abh                           ; 74 08
+    je short 018c0h                           ; 74 08
     mov dx, strict word 0002dh                ; ba 2d 00
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 b5 fe
+    call 01775h                               ; e8 b5 fe
     mov al, byte [bp-008h]                    ; 8a 46 f8
     mov DL, strict byte 00ah                  ; b2 0a
     mul dl                                    ; f6 e2
@@ -1415,13 +1428,13 @@ put_luint_:                                  ; 0xf185a LB 0x72
     add AL, strict byte 030h                  ; 04 30
     movzx dx, al                              ; 0f b6 d0
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 9d fe
+    call 01775h                               ; e8 9d fe
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00002h                               ; c2 02 00
-put_str_:                                    ; 0xf18cc LB 0x21
+put_str_:                                    ; 0xf18e1 LB 0x21
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
@@ -1430,18 +1443,18 @@ put_str_:                                    ; 0xf18cc LB 0x21
     mov es, cx                                ; 8e c1
     mov dl, byte [es:bx]                      ; 26 8a 17
     test dl, dl                               ; 84 d2
-    je short 018e6h                           ; 74 0a
+    je short 018fbh                           ; 74 0a
     xor dh, dh                                ; 30 f6
     mov ax, si                                ; 89 f0
-    call 01760h                               ; e8 7d fe
+    call 01775h                               ; e8 7d fe
     inc bx                                    ; 43
-    jmp short 018d3h                          ; eb ed
+    jmp short 018e8h                          ; eb ed
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop si                                    ; 5e
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-put_str_near_:                               ; 0xf18ed LB 0x20
+put_str_near_:                               ; 0xf1902 LB 0x20
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -1450,18 +1463,18 @@ put_str_near_:                               ; 0xf18ed LB 0x20
     mov bx, dx                                ; 89 d3
     mov dl, byte [bx]                         ; 8a 17
     test dl, dl                               ; 84 d2
-    je short 01906h                           ; 74 0a
+    je short 0191bh                           ; 74 0a
     xor dh, dh                                ; 30 f6
     mov ax, cx                                ; 89 c8
-    call 01760h                               ; e8 5d fe
+    call 01775h                               ; e8 5d fe
     inc bx                                    ; 43
-    jmp short 018f6h                          ; eb f0
+    jmp short 0190bh                          ; eb f0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop cx                                    ; 59
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-bios_printf_:                                ; 0xf190d LB 0x23b
+bios_printf_:                                ; 0xf1922 LB 0x23b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -1478,31 +1491,31 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     mov ax, word [bp+004h]                    ; 8b 46 04
     and ax, strict word 00007h                ; 25 07 00
     cmp ax, strict word 00007h                ; 3d 07 00
-    jne short 0193bh                          ; 75 0b
+    jne short 01950h                          ; 75 0b
     push 000deh                               ; 68 de 00
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 d5 ff
+    call 01922h                               ; e8 d5 ff
     add sp, strict byte 00004h                ; 83 c4 04
     mov bx, word [bp+006h]                    ; 8b 5e 06
     mov dl, byte [bx]                         ; 8a 17
     test dl, dl                               ; 84 d2
-    je near 01b2ch                            ; 0f 84 e6 01
+    je near 01b41h                            ; 0f 84 e6 01
     cmp dl, 025h                              ; 80 fa 25
-    jne short 01953h                          ; 75 08
+    jne short 01968h                          ; 75 08
     mov cx, strict word 00001h                ; b9 01 00
     xor si, si                                ; 31 f6
-    jmp near 01b26h                           ; e9 d3 01
+    jmp near 01b3bh                           ; e9 d3 01
     test cx, cx                               ; 85 c9
-    je near 01b1eh                            ; 0f 84 c5 01
+    je near 01b33h                            ; 0f 84 c5 01
     cmp dl, 030h                              ; 80 fa 30
-    jc short 01971h                           ; 72 13
+    jc short 01986h                           ; 72 13
     cmp dl, 039h                              ; 80 fa 39
-    jnbe short 01971h                         ; 77 0e
+    jnbe short 01986h                         ; 77 0e
     movzx ax, dl                              ; 0f b6 c2
     imul si, si, strict byte 0000ah           ; 6b f6 0a
     sub ax, strict word 00030h                ; 2d 30 00
     add si, ax                                ; 01 c6
-    jmp near 01b26h                           ; e9 b5 01
+    jmp near 01b3bh                           ; e9 b5 01
     mov ax, word [bp-010h]                    ; 8b 46 f0
     mov word [bp-010h], ax                    ; 89 46 f0
     add word [bp-012h], strict byte 00002h    ; 83 46 ee 02
@@ -1510,20 +1523,20 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     mov ax, word [es:bx-002h]                 ; 26 8b 47 fe
     mov word [bp-00ch], ax                    ; 89 46 f4
     cmp dl, 078h                              ; 80 fa 78
-    je short 0198fh                           ; 74 05
+    je short 019a4h                           ; 74 05
     cmp dl, 058h                              ; 80 fa 58
-    jne short 019d8h                          ; 75 49
+    jne short 019edh                          ; 75 49
     test si, si                               ; 85 f6
-    jne short 01996h                          ; 75 03
+    jne short 019abh                          ; 75 03
     mov si, strict word 00004h                ; be 04 00
     cmp dl, 078h                              ; 80 fa 78
-    jne short 019a0h                          ; 75 05
+    jne short 019b5h                          ; 75 05
     mov di, strict word 00061h                ; bf 61 00
-    jmp short 019a3h                          ; eb 03
+    jmp short 019b8h                          ; eb 03
     mov di, strict word 00041h                ; bf 41 00
     lea bx, [si-001h]                         ; 8d 5c ff
     test bx, bx                               ; 85 db
-    jl near 01b1ah                            ; 0f 8c 6e 01
+    jl near 01b2fh                            ; 0f 8c 6e 01
     mov cx, bx                                ; 89 d9
     sal cx, 002h                              ; c1 e1 02
     mov ax, word [bp-00ch]                    ; 8b 46 f4
@@ -1531,29 +1544,29 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     xor ah, ah                                ; 30 e4
     and AL, strict byte 00fh                  ; 24 0f
     cmp ax, strict word 00009h                ; 3d 09 00
-    jnbe short 019c6h                         ; 77 07
+    jnbe short 019dbh                         ; 77 07
     mov dx, ax                                ; 89 c2
     add dx, strict byte 00030h                ; 83 c2 30
-    jmp short 019cdh                          ; eb 07
+    jmp short 019e2h                          ; eb 07
     mov dx, ax                                ; 89 c2
     sub dx, strict byte 0000ah                ; 83 ea 0a
     add dx, di                                ; 01 fa
     xor dh, dh                                ; 30 f6
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 01760h                               ; e8 8b fd
+    call 01775h                               ; e8 8b fd
     dec bx                                    ; 4b
-    jmp short 019a6h                          ; eb ce
+    jmp short 019bbh                          ; eb ce
     cmp dl, 075h                              ; 80 fa 75
-    jne short 019ech                          ; 75 0f
+    jne short 01a01h                          ; 75 0f
     xor cx, cx                                ; 31 c9
     mov bx, si                                ; 89 f3
     mov dx, ax                                ; 89 c2
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 017fah                               ; e8 11 fe
-    jmp near 01b1ah                           ; e9 2e 01
+    call 0180fh                               ; e8 11 fe
+    jmp near 01b2fh                           ; e9 2e 01
     lea bx, [si-001h]                         ; 8d 5c ff
     cmp dl, 06ch                              ; 80 fa 6c
-    jne near 01aa8h                           ; 0f 85 b2 00
+    jne near 01abdh                           ; 0f 85 b2 00
     inc word [bp+006h]                        ; ff 46 06
     mov di, word [bp+006h]                    ; 8b 7e 06
     mov dl, byte [di]                         ; 8a 15
@@ -1564,9 +1577,9 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     mov ax, word [es:di-002h]                 ; 26 8b 45 fe
     mov word [bp-00eh], ax                    ; 89 46 f2
     cmp dl, 064h                              ; 80 fa 64
-    jne short 01a44h                          ; 75 2d
+    jne short 01a59h                          ; 75 2d
     test byte [bp-00dh], 080h                 ; f6 46 f3 80
-    je short 01a32h                           ; 74 15
+    je short 01a47h                           ; 74 15
     push strict byte 00001h                   ; 6a 01
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     mov cx, word [bp-00eh]                    ; 8b 4e f2
@@ -1575,77 +1588,77 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     sbb cx, strict byte 00000h                ; 83 d9 00
     mov dx, bx                                ; 89 da
     mov bx, ax                                ; 89 c3
-    jmp short 01a3bh                          ; eb 09
+    jmp short 01a50h                          ; eb 09
     push strict byte 00000h                   ; 6a 00
     mov bx, word [bp-00ch]                    ; 8b 5e f4
     mov dx, si                                ; 89 f2
     mov cx, ax                                ; 89 c1
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0185ah                               ; e8 19 fe
-    jmp near 01b1ah                           ; e9 d6 00
+    call 0186fh                               ; e8 19 fe
+    jmp near 01b2fh                           ; e9 d6 00
     cmp dl, 075h                              ; 80 fa 75
-    jne short 01a4bh                          ; 75 02
-    jmp short 01a32h                          ; eb e7
+    jne short 01a60h                          ; 75 02
+    jmp short 01a47h                          ; eb e7
     cmp dl, 078h                              ; 80 fa 78
-    je short 01a57h                           ; 74 07
+    je short 01a6ch                           ; 74 07
     cmp dl, 058h                              ; 80 fa 58
-    jne near 01b1ah                           ; 0f 85 c3 00
+    jne near 01b2fh                           ; 0f 85 c3 00
     test si, si                               ; 85 f6
-    jne short 01a5eh                          ; 75 03
+    jne short 01a73h                          ; 75 03
     mov si, strict word 00008h                ; be 08 00
     cmp dl, 078h                              ; 80 fa 78
-    jne short 01a68h                          ; 75 05
+    jne short 01a7dh                          ; 75 05
     mov di, strict word 00061h                ; bf 61 00
-    jmp short 01a6bh                          ; eb 03
+    jmp short 01a80h                          ; eb 03
     mov di, strict word 00041h                ; bf 41 00
     lea bx, [si-001h]                         ; 8d 5c ff
     test bx, bx                               ; 85 db
-    jl near 01b1ah                            ; 0f 8c a6 00
+    jl near 01b2fh                            ; 0f 8c a6 00
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     mov cx, bx                                ; 89 d9
     sal cx, 002h                              ; c1 e1 02
     mov dx, word [bp-00eh]                    ; 8b 56 f2
-    jcxz 01a87h                               ; e3 06
+    jcxz 01a9ch                               ; e3 06
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 01a81h                               ; e2 fa
+    loop 01a96h                               ; e2 fa
     and ax, strict word 0000fh                ; 25 0f 00
     cmp ax, strict word 00009h                ; 3d 09 00
-    jnbe short 01a96h                         ; 77 07
+    jnbe short 01aabh                         ; 77 07
     mov dx, ax                                ; 89 c2
     add dx, strict byte 00030h                ; 83 c2 30
-    jmp short 01a9dh                          ; eb 07
+    jmp short 01ab2h                          ; eb 07
     mov dx, ax                                ; 89 c2
     sub dx, strict byte 0000ah                ; 83 ea 0a
     add dx, di                                ; 01 fa
     xor dh, dh                                ; 30 f6
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 01760h                               ; e8 bb fc
+    call 01775h                               ; e8 bb fc
     dec bx                                    ; 4b
-    jmp short 01a6eh                          ; eb c6
+    jmp short 01a83h                          ; eb c6
     cmp dl, 064h                              ; 80 fa 64
-    jne short 01acah                          ; 75 1d
+    jne short 01adfh                          ; 75 1d
     test byte [bp-00bh], 080h                 ; f6 46 f5 80
-    je short 01abch                           ; 74 09
+    je short 01ad1h                           ; 74 09
     mov dx, ax                                ; 89 c2
     neg dx                                    ; f7 da
     mov cx, strict word 00001h                ; b9 01 00
-    jmp short 01ac2h                          ; eb 06
+    jmp short 01ad7h                          ; eb 06
     xor cx, cx                                ; 31 c9
     mov bx, si                                ; 89 f3
     mov dx, ax                                ; 89 c2
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0179bh                               ; e8 d3 fc
-    jmp short 01b1ah                          ; eb 50
+    call 017b0h                               ; e8 d3 fc
+    jmp short 01b2fh                          ; eb 50
     cmp dl, 073h                              ; 80 fa 73
-    jne short 01adbh                          ; 75 0c
+    jne short 01af0h                          ; 75 0c
     mov cx, ds                                ; 8c d9
     mov bx, ax                                ; 89 c3
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 018cch                               ; e8 f3 fd
-    jmp short 01b1ah                          ; eb 3f
+    call 018e1h                               ; e8 f3 fd
+    jmp short 01b2fh                          ; eb 3f
     cmp dl, 053h                              ; 80 fa 53
-    jne short 01afeh                          ; 75 1e
+    jne short 01b13h                          ; 75 1e
     mov word [bp-00eh], ax                    ; 89 46 f2
     mov ax, word [bp-010h]                    ; 8b 46 f0
     mov word [bp-010h], ax                    ; 89 46 f0
@@ -1655,32 +1668,32 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     mov word [bp-00ch], ax                    ; 89 46 f4
     mov bx, ax                                ; 89 c3
     mov cx, word [bp-00eh]                    ; 8b 4e f2
-    jmp short 01ad3h                          ; eb d5
+    jmp short 01ae8h                          ; eb d5
     cmp dl, 063h                              ; 80 fa 63
-    jne short 01b0fh                          ; 75 0c
+    jne short 01b24h                          ; 75 0c
     movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 01760h                               ; e8 53 fc
-    jmp short 01b1ah                          ; eb 0b
+    call 01775h                               ; e8 53 fc
+    jmp short 01b2fh                          ; eb 0b
     push 000e6h                               ; 68 e6 00
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 f6 fd
+    call 01922h                               ; e8 f6 fd
     add sp, strict byte 00004h                ; 83 c4 04
     xor cx, cx                                ; 31 c9
-    jmp short 01b26h                          ; eb 08
+    jmp short 01b3bh                          ; eb 08
     xor dh, dh                                ; 30 f6
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 01760h                               ; e8 3a fc
+    call 01775h                               ; e8 3a fc
     inc word [bp+006h]                        ; ff 46 06
-    jmp near 0193bh                           ; e9 0f fe
+    jmp near 01950h                           ; e9 0f fe
     xor ax, ax                                ; 31 c0
     mov word [bp-012h], ax                    ; 89 46 ee
     mov word [bp-010h], ax                    ; 89 46 f0
     test byte [bp+004h], 001h                 ; f6 46 04 01
-    je short 01b3eh                           ; 74 04
+    je short 01b53h                           ; 74 04
     cli                                       ; fa
     hlt                                       ; f4
-    jmp short 01b3bh                          ; eb fd
+    jmp short 01b50h                          ; eb fd
     lea sp, [bp-00ah]                         ; 8d 66 f6
     pop di                                    ; 5f
     pop si                                    ; 5e
@@ -1689,19 +1702,19 @@ bios_printf_:                                ; 0xf190d LB 0x23b
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-_ata_init:                                   ; 0xf1b48 LB 0xc4
+_ata_init:                                   ; 0xf1b5d LB 0xc4
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 c7 fa
+    call 0161ch                               ; e8 b2 fa
     mov si, 00122h                            ; be 22 01
     mov dx, ax                                ; 89 c2
     xor al, al                                ; 30 c0
-    jmp short 01b62h                          ; eb 04
+    jmp short 01b77h                          ; eb 04
     cmp AL, strict byte 004h                  ; 3c 04
-    jnc short 01b86h                          ; 73 24
+    jnc short 01b9bh                          ; 73 24
     movzx bx, al                              ; 0f b6 d8
     imul bx, bx, strict byte 00006h           ; 6b db 06
     mov es, dx                                ; 8e c2
@@ -1712,11 +1725,11 @@ _ata_init:                                   ; 0xf1b48 LB 0xc4
     mov byte [es:bx+001c1h], 000h             ; 26 c6 87 c1 01 00
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
-    jmp short 01b5eh                          ; eb d8
+    jmp short 01b73h                          ; eb d8
     xor al, al                                ; 30 c0
-    jmp short 01b8eh                          ; eb 04
+    jmp short 01ba3h                          ; eb 04
     cmp AL, strict byte 008h                  ; 3c 08
-    jnc short 01bd9h                          ; 73 4b
+    jnc short 01beeh                          ; 73 4b
     movzx bx, al                              ; 0f b6 d8
     imul bx, bx, strict byte 00018h           ; 6b db 18
     mov es, dx                                ; 8e c2
@@ -1736,11 +1749,11 @@ _ata_init:                                   ; 0xf1b48 LB 0xc4
     ; mov dword [es:bx+032h], strict dword 000000000h ; 66 26 c7 47 32 00 00 00 00
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
-    jmp short 01b8ah                          ; eb b1
+    jmp short 01b9fh                          ; eb b1
     xor al, al                                ; 30 c0
-    jmp short 01be1h                          ; eb 04
+    jmp short 01bf6h                          ; eb 04
     cmp AL, strict byte 010h                  ; 3c 10
-    jnc short 01bf8h                          ; 73 17
+    jnc short 01c0dh                          ; 73 17
     movzx bx, al                              ; 0f b6 d8
     mov es, dx                                ; 8e c2
     add bx, si                                ; 01 f3
@@ -1748,7 +1761,7 @@ _ata_init:                                   ; 0xf1b48 LB 0xc4
     mov byte [es:bx+001b0h], 010h             ; 26 c6 87 b0 01 10
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
-    jmp short 01bddh                          ; eb e5
+    jmp short 01bf2h                          ; eb e5
     mov es, dx                                ; 8e c2
     mov byte [es:si+0019eh], 000h             ; 26 c6 84 9e 01 00
     mov byte [es:si+001afh], 000h             ; 26 c6 84 af 01 00
@@ -1756,7 +1769,7 @@ _ata_init:                                   ; 0xf1b48 LB 0xc4
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-ata_reset_:                                  ; 0xf1c0c LB 0xde
+ata_reset_:                                  ; 0xf1c21 LB 0xde
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -1769,7 +1782,7 @@ ata_reset_:                                  ; 0xf1c0c LB 0xde
     push ax                                   ; 50
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 fc f9
+    call 0161ch                               ; e8 e7 f9
     mov word [bp-00eh], 00122h                ; c7 46 f2 22 01
     mov di, ax                                ; 89 c7
     mov bx, word [bp-010h]                    ; 8b 5e f0
@@ -1789,14 +1802,14 @@ ata_reset_:                                  ; 0xf1c0c LB 0xde
     mov bx, 000ffh                            ; bb ff 00
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 01c64h                          ; 76 0c
+    jbe short 01c79h                          ; 76 0c
     mov dx, cx                                ; 89 ca
     add dx, strict byte 00007h                ; 83 c2 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 080h                 ; a8 80
-    je short 01c53h                           ; 74 ef
+    je short 01c68h                           ; 74 ef
     lea dx, [si+006h]                         ; 8d 54 06
     mov AL, strict byte 00ah                  ; b0 0a
     out DX, AL                                ; ee
@@ -1804,11 +1817,11 @@ ata_reset_:                                  ; 0xf1c0c LB 0xde
     mov es, di                                ; 8e c7
     add bx, word [bp-00eh]                    ; 03 5e f2
     cmp byte [es:bx+01eh], 000h               ; 26 80 7f 1e 00
-    je short 01cc6h                           ; 74 4c
+    je short 01cdbh                           ; 74 4c
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    je short 01c85h                           ; 74 05
+    je short 01c9ah                           ; 74 05
     mov ax, 000b0h                            ; b8 b0 00
-    jmp short 01c88h                          ; eb 03
+    jmp short 01c9dh                          ; eb 03
     mov ax, 000a0h                            ; b8 a0 00
     mov dx, cx                                ; 89 ca
     add dx, strict byte 00006h                ; 83 c2 06
@@ -1826,36 +1839,36 @@ ata_reset_:                                  ; 0xf1c0c LB 0xde
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp bl, 001h                              ; 80 fb 01
-    jne short 01cc6h                          ; 75 22
+    jne short 01cdbh                          ; 75 22
     cmp al, bl                                ; 38 d8
-    jne short 01cc6h                          ; 75 1e
+    jne short 01cdbh                          ; 75 1e
     mov bx, strict word 0ffffh                ; bb ff ff
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 01cc6h                          ; 76 16
+    jbe short 01cdbh                          ; 76 16
     mov dx, cx                                ; 89 ca
     add dx, strict byte 00007h                ; 83 c2 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 080h                 ; a8 80
-    je short 01cc6h                           ; 74 0a
+    je short 01cdbh                           ; 74 0a
     mov ax, strict word 0ffffh                ; b8 ff ff
     dec ax                                    ; 48
     test ax, ax                               ; 85 c0
-    jnbe short 01cbfh                         ; 77 fb
-    jmp short 01cabh                          ; eb e5
+    jnbe short 01cd4h                         ; 77 fb
+    jmp short 01cc0h                          ; eb e5
     mov bx, strict word 00010h                ; bb 10 00
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 01cdah                          ; 76 0c
+    jbe short 01cefh                          ; 76 0c
     mov dx, cx                                ; 89 ca
     add dx, strict byte 00007h                ; 83 c2 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 040h                 ; a8 40
-    je short 01cc9h                           ; 74 ef
+    je short 01cdeh                           ; 74 ef
     lea dx, [si+006h]                         ; 8d 54 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
@@ -1867,7 +1880,7 @@ ata_reset_:                                  ; 0xf1c0c LB 0xde
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
+ata_cmd_data_in_:                            ; 0xf1cff LB 0x258
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -1898,30 +1911,30 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     mov ax, word [es:di+024h]                 ; 26 8b 45 24
     mov word [bp-00ch], ax                    ; 89 46 f4
     test ax, ax                               ; 85 c0
-    jne short 01d52h                          ; 75 14
+    jne short 01d67h                          ; 75 14
     cmp byte [bp-006h], 001h                  ; 80 7e fa 01
-    jne short 01d4bh                          ; 75 07
+    jne short 01d60h                          ; 75 07
     mov word [bp-00ch], 04000h                ; c7 46 f4 00 40
-    jmp short 01d61h                          ; eb 16
+    jmp short 01d76h                          ; eb 16
     mov word [bp-00ch], 08000h                ; c7 46 f4 00 80
-    jmp short 01d61h                          ; eb 0f
+    jmp short 01d76h                          ; eb 0f
     cmp byte [bp-006h], 001h                  ; 80 7e fa 01
-    jne short 01d5eh                          ; 75 06
+    jne short 01d73h                          ; 75 06
     shr word [bp-00ch], 002h                  ; c1 6e f4 02
-    jmp short 01d61h                          ; eb 03
+    jmp short 01d76h                          ; eb 03
     shr word [bp-00ch], 1                     ; d1 6e f4
     lea dx, [bx+007h]                         ; 8d 57 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 080h                 ; a8 80
-    je short 01d7ah                           ; 74 0f
+    je short 01d8fh                           ; 74 0f
     mov dx, word [bp-01ch]                    ; 8b 56 e4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00001h                ; ba 01 00
-    jmp near 01f39h                           ; e9 bf 01
+    jmp near 01f4eh                           ; e9 bf 01
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov ax, word [es:si]                      ; 26 8b 04
     mov word [bp-020h], ax                    ; 89 46 e0
@@ -1938,13 +1951,13 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     mov word [bp-018h], ax                    ; 89 46 e8
     mov ax, word [bp-010h]                    ; 8b 46 f0
     test ax, ax                               ; 85 c0
-    jne short 01e18h                          ; 75 67
+    jne short 01e2dh                          ; 75 67
     mov dx, word [bp-020h]                    ; 8b 56 e0
     add dx, word [bp-014h]                    ; 03 56 ec
     adc ax, word [bp-01eh]                    ; 13 46 e2
     cmp ax, 01000h                            ; 3d 00 10
-    jnbe short 01dc1h                         ; 77 02
-    jne short 01dech                          ; 75 2b
+    jnbe short 01dd6h                         ; 77 02
+    jne short 01e01h                          ; 75 2b
     mov ax, word [bp-01eh]                    ; 8b 46 e2
     xor al, al                                ; 30 c0
     shr ax, 008h                              ; c1 e8 08
@@ -1969,7 +1982,7 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     mov cx, strict word 00008h                ; b9 08 00
     shr word [bp-01eh], 1                     ; d1 6e e2
     rcr word [bp-020h], 1                     ; d1 5e e0
-    loop 01df7h                               ; e2 f8
+    loop 01e0ch                               ; e2 f8
     mov ax, word [bp-020h]                    ; 8b 46 e0
     mov word [bp-012h], ax                    ; 89 46 ee
     mov ax, word [bp-01eh]                    ; 8b 46 e2
@@ -1998,9 +2011,9 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     lea dx, [bx+005h]                         ; 8d 57 05
     out DX, AL                                ; ee
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    je short 01e4eh                           ; 74 05
+    je short 01e63h                           ; 74 05
     mov ax, 000b0h                            ; b8 b0 00
-    jmp short 01e51h                          ; eb 03
+    jmp short 01e66h                          ; eb 03
     mov ax, 000a0h                            ; b8 a0 00
     movzx dx, byte [bp-018h]                  ; 0f b6 56 e8
     or ax, dx                                 ; 09 d0
@@ -2011,13 +2024,13 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     out DX, AL                                ; ee
     mov ax, word [bp-016h]                    ; 8b 46 ea
     cmp ax, 000c4h                            ; 3d c4 00
-    je short 01e6fh                           ; 74 05
+    je short 01e84h                           ; 74 05
     cmp ax, strict word 00029h                ; 3d 29 00
-    jne short 01e7ch                          ; 75 0d
+    jne short 01e91h                          ; 75 0d
     mov ax, word [bp-014h]                    ; 8b 46 ec
     mov word [bp-01ah], ax                    ; 89 46 e6
     mov word [bp-014h], strict word 00001h    ; c7 46 ec 01 00
-    jmp short 01e81h                          ; eb 05
+    jmp short 01e96h                          ; eb 05
     mov word [bp-01ah], strict word 00001h    ; c7 46 e6 01 00
     lea dx, [bx+007h]                         ; 8d 57 07
     in AL, DX                                 ; ec
@@ -2025,38 +2038,38 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
     test AL, strict byte 080h                 ; a8 80
-    jne short 01e81h                          ; 75 f4
+    jne short 01e96h                          ; 75 f4
     test AL, strict byte 001h                 ; a8 01
-    je short 01ea0h                           ; 74 0f
+    je short 01eb5h                           ; 74 0f
     mov dx, word [bp-01ch]                    ; 8b 56 e4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00002h                ; ba 02 00
-    jmp near 01f39h                           ; e9 99 00
+    jmp near 01f4eh                           ; e9 99 00
     test dl, 008h                             ; f6 c2 08
-    jne short 01eb4h                          ; 75 0f
+    jne short 01ec9h                          ; 75 0f
     mov dx, word [bp-01ch]                    ; 8b 56 e4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00003h                ; ba 03 00
-    jmp near 01f39h                           ; e9 85 00
+    jmp near 01f4eh                           ; e9 85 00
     sti                                       ; fb
     cmp di, 0f800h                            ; 81 ff 00 f8
-    jc short 01ec8h                           ; 72 0d
+    jc short 01eddh                           ; 72 0d
     sub di, 00800h                            ; 81 ef 00 08
     mov ax, word [bp-00eh]                    ; 8b 46 f2
     add ax, 00080h                            ; 05 80 00
     mov word [bp-00eh], ax                    ; 89 46 f2
     cmp byte [bp-006h], 001h                  ; 80 7e fa 01
-    jne short 01edbh                          ; 75 0d
+    jne short 01ef0h                          ; 75 0d
     mov dx, bx                                ; 89 da
     mov cx, word [bp-00ch]                    ; 8b 4e f4
     mov es, [bp-00eh]                         ; 8e 46 f2
     db  0f3h, 066h, 06dh
     ; rep insd                                  ; f3 66 6d
-    jmp short 01ee5h                          ; eb 0a
+    jmp short 01efah                          ; eb 0a
     mov dx, bx                                ; 89 da
     mov cx, word [bp-00ch]                    ; 8b 4e f4
     mov es, [bp-00eh]                         ; 8e 46 f2
@@ -2071,28 +2084,28 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
     test AL, strict byte 080h                 ; a8 80
-    jne short 01ef2h                          ; 75 f4
+    jne short 01f07h                          ; 75 f4
     cmp word [bp-014h], strict byte 00000h    ; 83 7e ec 00
-    jne short 01f18h                          ; 75 14
+    jne short 01f2dh                          ; 75 14
     and AL, strict byte 0c9h                  ; 24 c9
     cmp AL, strict byte 040h                  ; 3c 40
-    je short 01f2eh                           ; 74 24
+    je short 01f43h                           ; 74 24
     mov dx, word [bp-01ch]                    ; 8b 56 e4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00004h                ; ba 04 00
-    jmp short 01f39h                          ; eb 21
+    jmp short 01f4eh                          ; eb 21
     mov al, dl                                ; 88 d0
     and AL, strict byte 0c9h                  ; 24 c9
     cmp AL, strict byte 048h                  ; 3c 48
-    je short 01eb5h                           ; 74 95
+    je short 01ecah                           ; 74 95
     mov dx, word [bp-01ch]                    ; 8b 56 e4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00005h                ; ba 05 00
-    jmp short 01f39h                          ; eb 0b
+    jmp short 01f4eh                          ; eb 0b
     mov dx, word [bp-01ch]                    ; 8b 56 e4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
@@ -2104,7 +2117,7 @@ ata_cmd_data_in_:                            ; 0xf1cea LB 0x258
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-_ata_detect:                                 ; 0xf1f42 LB 0x617
+_ata_detect:                                 ; 0xf1f57 LB 0x617
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -2112,7 +2125,7 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     sub sp, 0025ch                            ; 81 ec 5c 02
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 c8 f6
+    call 0161ch                               ; e8 b3 f6
     mov word [bp-024h], ax                    ; 89 46 dc
     mov di, 00122h                            ; bf 22 01
     mov es, ax                                ; 8e c0
@@ -2130,7 +2143,7 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov byte [bp-00ah], al                    ; 88 46 f6
     mov byte [bp-006h], al                    ; 88 46 fa
     mov byte [bp-00eh], al                    ; 88 46 f2
-    jmp near 024e4h                           ; e9 48 05
+    jmp near 024f9h                           ; e9 48 05
     mov ax, 000a0h                            ; b8 a0 00
     lea dx, [si+006h]                         ; 8d 54 06
     out DX, AL                                ; ee
@@ -2162,20 +2175,20 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp cl, 055h                              ; 80 f9 55
-    jne near 02096h                           ; 0f 85 c0 00
+    jne near 020abh                           ; 0f 85 c0 00
     cmp AL, strict byte 0aah                  ; 3c aa
-    jne near 02096h                           ; 0f 85 ba 00
+    jne near 020abh                           ; 0f 85 ba 00
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     les bx, [bp-028h]                         ; c4 5e d8
     add bx, ax                                ; 01 c3
     mov byte [es:bx+01eh], 001h               ; 26 c6 47 1e 01
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 01c0ch                               ; e8 18 fc
+    call 01c21h                               ; e8 18 fc
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    je short 01fffh                           ; 74 05
+    je short 02014h                           ; 74 05
     mov ax, 000b0h                            ; b8 b0 00
-    jmp short 02002h                          ; eb 03
+    jmp short 02017h                          ; eb 03
     mov ax, 000a0h                            ; b8 a0 00
     lea dx, [si+006h]                         ; 8d 54 06
     out DX, AL                                ; ee
@@ -2189,9 +2202,9 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp bl, 001h                              ; 80 fb 01
-    jne near 02096h                           ; 0f 85 7b 00
+    jne near 020abh                           ; 0f 85 7b 00
     cmp al, bl                                ; 38 d8
-    jne near 02096h                           ; 0f 85 75 00
+    jne near 020abh                           ; 0f 85 75 00
     lea dx, [si+004h]                         ; 8d 54 04
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -2209,31 +2222,31 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp bl, 014h                              ; 80 fb 14
-    jne short 02059h                          ; 75 18
+    jne short 0206eh                          ; 75 18
     cmp cl, 0ebh                              ; 80 f9 eb
-    jne short 02059h                          ; 75 13
+    jne short 0206eh                          ; 75 13
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     les bx, [bp-028h]                         ; c4 5e d8
     add bx, ax                                ; 01 c3
     mov byte [es:bx+01eh], 003h               ; 26 c6 47 1e 03
-    jmp short 02096h                          ; eb 3d
+    jmp short 020abh                          ; eb 3d
     test bh, bh                               ; 84 ff
-    jne short 0207bh                          ; 75 1e
+    jne short 02090h                          ; 75 1e
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    jne short 0207bh                          ; 75 18
+    jne short 02090h                          ; 75 18
     test al, al                               ; 84 c0
-    je short 0207bh                           ; 74 14
+    je short 02090h                           ; 74 14
     movzx bx, byte [bp-00eh]                  ; 0f b6 5e f2
     imul bx, bx, strict byte 00018h           ; 6b db 18
     mov es, [bp-026h]                         ; 8e 46 da
     add bx, word [bp-028h]                    ; 03 5e d8
     mov byte [es:bx+01eh], 002h               ; 26 c6 47 1e 02
-    jmp short 02096h                          ; eb 1b
+    jmp short 020abh                          ; eb 1b
     cmp bh, 0ffh                              ; 80 ff ff
-    jne short 02096h                          ; 75 16
+    jne short 020abh                          ; 75 16
     cmp bh, byte [bp-00ch]                    ; 3a 7e f4
-    jne short 02096h                          ; 75 11
+    jne short 020abh                          ; 75 11
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     les bx, [bp-028h]                         ; c4 5e d8
@@ -2250,7 +2263,7 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov al, byte [es:si+01eh]                 ; 26 8a 44 1e
     mov byte [bp-010h], al                    ; 88 46 f0
     cmp AL, strict byte 002h                  ; 3c 02
-    jne near 022bch                           ; 0f 85 03 02
+    jne near 022d1h                           ; 0f 85 03 02
     mov byte [es:si+01fh], 0ffh               ; 26 c6 44 1f ff
     mov byte [es:si+022h], 000h               ; 26 c6 44 22 00
     lea dx, [bp-00260h]                       ; 8d 96 a0 fd
@@ -2263,12 +2276,12 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov bx, 000ech                            ; bb ec 00
     mov ax, word [bp-028h]                    ; 8b 46 d8
     mov dx, es                                ; 8c c2
-    call 01ceah                               ; e8 03 fc
+    call 01cffh                               ; e8 03 fc
     test ax, ax                               ; 85 c0
-    je short 020f6h                           ; 74 0b
+    je short 0210bh                           ; 74 0b
     push 00104h                               ; 68 04 01
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 1a f8
+    call 01922h                               ; e8 1a f8
     add sp, strict byte 00004h                ; 83 c4 04
     test byte [bp-00260h], 080h               ; f6 86 a0 fd 80
     db  00fh, 095h, 0c0h
@@ -2291,65 +2304,65 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov word [bp-020h], ax                    ; 89 46 e0
     mov si, word [bp-001e6h]                  ; 8b b6 1a fe
     cmp si, 00fffh                            ; 81 fe ff 0f
-    jne short 0214bh                          ; 75 10
+    jne short 02160h                          ; 75 10
     cmp ax, strict word 0ffffh                ; 3d ff ff
-    jne short 0214bh                          ; 75 0b
+    jne short 02160h                          ; 75 0b
     mov ax, word [bp-00198h]                  ; 8b 86 68 fe
     mov word [bp-020h], ax                    ; 89 46 e0
     mov si, word [bp-00196h]                  ; 8b b6 6a fe
     mov al, byte [bp-00eh]                    ; 8a 46 f2
     cmp AL, strict byte 001h                  ; 3c 01
-    jc short 0215eh                           ; 72 0c
-    jbe short 02166h                          ; 76 12
+    jc short 02173h                           ; 72 0c
+    jbe short 0217bh                          ; 76 12
     cmp AL, strict byte 003h                  ; 3c 03
-    je short 0216eh                           ; 74 16
+    je short 02183h                           ; 74 16
     cmp AL, strict byte 002h                  ; 3c 02
-    je short 0216ah                           ; 74 0e
-    jmp short 021abh                          ; eb 4d
+    je short 0217fh                           ; 74 0e
+    jmp short 021c0h                          ; eb 4d
     test al, al                               ; 84 c0
-    jne short 021abh                          ; 75 49
+    jne short 021c0h                          ; 75 49
     mov BL, strict byte 01eh                  ; b3 1e
-    jmp short 02170h                          ; eb 0a
+    jmp short 02185h                          ; eb 0a
     mov BL, strict byte 026h                  ; b3 26
-    jmp short 02170h                          ; eb 06
+    jmp short 02185h                          ; eb 06
     mov BL, strict byte 067h                  ; b3 67
-    jmp short 02170h                          ; eb 02
+    jmp short 02185h                          ; eb 02
     mov BL, strict byte 070h                  ; b3 70
     mov al, bl                                ; 88 d8
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     xor ah, ah                                ; 30 e4
-    call 0165ch                               ; e8 e3 f4
+    call 0165ch                               ; e8 ce f4
     xor ah, ah                                ; 30 e4
     mov dx, ax                                ; 89 c2
     sal dx, 008h                              ; c1 e2 08
     movzx ax, bl                              ; 0f b6 c3
-    call 0165ch                               ; e8 d6 f4
+    call 0165ch                               ; e8 c1 f4
     xor ah, ah                                ; 30 e4
     add ax, dx                                ; 01 d0
     mov word [bp-034h], ax                    ; 89 46 cc
     mov al, bl                                ; 88 d8
     add AL, strict byte 002h                  ; 04 02
     xor ah, ah                                ; 30 e4
-    call 0165ch                               ; e8 c6 f4
+    call 0165ch                               ; e8 b1 f4
     xor ah, ah                                ; 30 e4
     mov word [bp-036h], ax                    ; 89 46 ca
     mov al, bl                                ; 88 d8
     add AL, strict byte 007h                  ; 04 07
     xor ah, ah                                ; 30 e4
-    call 0165ch                               ; e8 b8 f4
+    call 0165ch                               ; e8 a3 f4
     xor ah, ah                                ; 30 e4
     mov word [bp-032h], ax                    ; 89 46 ce
-    jmp short 021b8h                          ; eb 0d
+    jmp short 021cdh                          ; eb 0d
     mov bx, word [bp-020h]                    ; 8b 5e e0
     mov cx, si                                ; 89 f1
     mov dx, ss                                ; 8c d2
     lea ax, [bp-036h]                         ; 8d 46 ca
-    call 0532ch                               ; e8 74 31
-    mov bx, 00da2h                            ; bb a2 0d
+    call 05341h                               ; e8 74 31
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 09 f7
+    call 018e1h                               ; e8 09 f7
     mov ax, word [bp-032h]                    ; 8b 46 ce
     push ax                                   ; 50
     mov ax, word [bp-036h]                    ; 8b 46 ca
@@ -2365,7 +2378,7 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     push ax                                   ; 50
     push 0012dh                               ; 68 2d 01
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 23 f7
+    call 01922h                               ; e8 23 f7
     add sp, strict byte 00014h                ; 83 c4 14
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
@@ -2398,11 +2411,11 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     pop DS                                    ; 1f
     mov al, byte [bp-00eh]                    ; 8a 46 f2
     cmp AL, strict byte 002h                  ; 3c 02
-    jnc short 022a7h                          ; 73 60
+    jnc short 022bch                          ; 73 60
     test al, al                               ; 84 c0
-    jne short 02250h                          ; 75 05
+    jne short 02265h                          ; 75 05
     mov di, strict word 0003dh                ; bf 3d 00
-    jmp short 02253h                          ; eb 03
+    jmp short 02268h                          ; eb 03
     mov di, strict word 0004dh                ; bf 4d 00
     mov dx, word [bp-024h]                    ; 8b 56 dc
     mov ax, word [bp-034h]                    ; 8b 46 cc
@@ -2421,16 +2434,16 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov byte [es:di+00eh], al                 ; 26 88 45 0e
     xor al, al                                ; 30 c0
     xor ah, ah                                ; 30 e4
-    jmp short 02291h                          ; eb 05
+    jmp short 022a6h                          ; eb 05
     cmp ah, 00fh                              ; 80 fc 0f
-    jnc short 0229fh                          ; 73 0e
+    jnc short 022b4h                          ; 73 0e
     movzx bx, ah                              ; 0f b6 dc
     mov es, dx                                ; 8e c2
     add bx, di                                ; 01 fb
     add al, byte [es:bx]                      ; 26 02 07
     db  0feh, 0c4h
     ; inc ah                                    ; fe c4
-    jmp short 0228ch                          ; eb ed
+    jmp short 022a1h                          ; eb ed
     neg al                                    ; f6 d8
     mov es, dx                                ; 8e c2
     mov byte [es:di+00fh], al                 ; 26 88 45 0f
@@ -2441,7 +2454,7 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov byte [es:bx+0019fh], al               ; 26 88 87 9f 01
     inc byte [bp-006h]                        ; fe 46 fa
     cmp byte [bp-010h], 003h                  ; 80 7e f0 03
-    jne near 0235ch                           ; 0f 85 98 00
+    jne near 02371h                           ; 0f 85 98 00
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     les bx, [bp-028h]                         ; c4 5e d8
@@ -2458,12 +2471,12 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov bx, 000a1h                            ; bb a1 00
     mov ax, word [bp-028h]                    ; 8b 46 d8
     mov dx, es                                ; 8c c2
-    call 01ceah                               ; e8 ec f9
+    call 01cffh                               ; e8 ec f9
     test ax, ax                               ; 85 c0
-    je short 0230dh                           ; 74 0b
+    je short 02322h                           ; 74 0b
     push 00154h                               ; 68 54 01
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 03 f6
+    call 01922h                               ; e8 03 f6
     add sp, strict byte 00004h                ; 83 c4 04
     mov cl, byte [bp-0025fh]                  ; 8a 8e a1 fd
     and cl, 01fh                              ; 80 e1 1f
@@ -2492,9 +2505,9 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     inc byte [bp-00ah]                        ; fe 46 f6
     mov al, byte [bp-010h]                    ; 8a 46 f0
     cmp AL, strict byte 003h                  ; 3c 03
-    je short 0238fh                           ; 74 2c
+    je short 023a4h                           ; 74 2c
     cmp AL, strict byte 002h                  ; 3c 02
-    jne near 023f2h                           ; 0f 85 89 00
+    jne near 02407h                           ; 0f 85 89 00
     movzx bx, byte [bp-00eh]                  ; 0f b6 5e f2
     imul bx, bx, strict byte 00018h           ; 6b db 18
     mov es, [bp-026h]                         ; 8e 46 da
@@ -2506,25 +2519,25 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov cx, strict word 0000bh                ; b9 0b 00
     shr word [bp-02eh], 1                     ; d1 6e d2
     rcr word [bp-030h], 1                     ; d1 5e d0
-    loop 02387h                               ; e2 f8
+    loop 0239ch                               ; e2 f8
     movzx dx, byte [bp-001bfh]                ; 0f b6 96 41 fe
     sal dx, 008h                              ; c1 e2 08
     movzx ax, byte [bp-001c0h]                ; 0f b6 86 40 fe
     or dx, ax                                 ; 09 c2
     mov byte [bp-012h], 00fh                  ; c6 46 ee 0f
-    jmp short 023adh                          ; eb 09
+    jmp short 023c2h                          ; eb 09
     dec byte [bp-012h]                        ; fe 4e ee
     cmp byte [bp-012h], 000h                  ; 80 7e ee 00
-    jbe short 023bah                          ; 76 0d
+    jbe short 023cfh                          ; 76 0d
     movzx cx, byte [bp-012h]                  ; 0f b6 4e ee
     mov ax, strict word 00001h                ; b8 01 00
     sal ax, CL                                ; d3 e0
     test dx, ax                               ; 85 c2
-    je short 023a4h                           ; 74 ea
+    je short 023b9h                           ; 74 ea
     xor di, di                                ; 31 ff
-    jmp short 023c3h                          ; eb 05
+    jmp short 023d8h                          ; eb 05
     cmp di, strict byte 00014h                ; 83 ff 14
-    jnl short 023d8h                          ; 7d 15
+    jnl short 023edh                          ; 7d 15
     mov si, di                                ; 89 fe
     add si, di                                ; 01 fe
     mov al, byte [bp+si-00229h]               ; 8a 82 d7 fd
@@ -2532,111 +2545,111 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov al, byte [bp+si-0022ah]               ; 8a 82 d6 fd
     mov byte [bp+si-05fh], al                 ; 88 42 a1
     inc di                                    ; 47
-    jmp short 023beh                          ; eb e6
+    jmp short 023d3h                          ; eb e6
     mov byte [bp-038h], 000h                  ; c6 46 c8 00
     mov di, strict word 00027h                ; bf 27 00
-    jmp short 023e6h                          ; eb 05
+    jmp short 023fbh                          ; eb 05
     dec di                                    ; 4f
     test di, di                               ; 85 ff
-    jle short 023f2h                          ; 7e 0c
+    jle short 02407h                          ; 7e 0c
     cmp byte [bp+di-060h], 020h               ; 80 7b a0 20
-    jne short 023f2h                          ; 75 06
+    jne short 02407h                          ; 75 06
     mov byte [bp+di-060h], 000h               ; c6 43 a0 00
-    jmp short 023e1h                          ; eb ef
+    jmp short 023f6h                          ; eb ef
     mov al, byte [bp-010h]                    ; 8a 46 f0
     cmp AL, strict byte 003h                  ; 3c 03
-    je short 02455h                           ; 74 5c
+    je short 0246ah                           ; 74 5c
     cmp AL, strict byte 002h                  ; 3c 02
-    je short 02406h                           ; 74 09
+    je short 0241bh                           ; 74 09
     cmp AL, strict byte 001h                  ; 3c 01
-    je near 024bch                            ; 0f 84 b9 00
-    jmp near 024dbh                           ; e9 d5 00
+    je near 024d1h                            ; 0f 84 b9 00
+    jmp near 024f0h                           ; e9 d5 00
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    je short 02411h                           ; 74 05
+    je short 02426h                           ; 74 05
     mov ax, 0017fh                            ; b8 7f 01
-    jmp short 02414h                          ; eb 03
+    jmp short 02429h                          ; eb 03
     mov ax, 00186h                            ; b8 86 01
     push ax                                   ; 50
     movzx ax, byte [bp-018h]                  ; 0f b6 46 e8
     push ax                                   ; 50
     push 0018dh                               ; 68 8d 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 eb f4
+    call 01922h                               ; e8 eb f4
     add sp, strict byte 00008h                ; 83 c4 08
     xor di, di                                ; 31 ff
     movzx ax, byte [bp+di-060h]               ; 0f b6 43 a0
     inc di                                    ; 47
     test ax, ax                               ; 85 c0
-    je short 0243eh                           ; 74 0e
+    je short 02453h                           ; 74 0e
     push ax                                   ; 50
     push 00198h                               ; 68 98 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 d4 f4
+    call 01922h                               ; e8 d4 f4
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp short 02427h                          ; eb e9
+    jmp short 0243ch                          ; eb e9
     push dword [bp-030h]                      ; 66 ff 76 d0
     movzx ax, byte [bp-012h]                  ; 0f b6 46 ee
     push ax                                   ; 50
     push 0019bh                               ; 68 9b 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 be f4
+    call 01922h                               ; e8 be f4
     add sp, strict byte 0000ah                ; 83 c4 0a
-    jmp near 024dbh                           ; e9 86 00
+    jmp near 024f0h                           ; e9 86 00
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    je short 02460h                           ; 74 05
+    je short 02475h                           ; 74 05
     mov ax, 0017fh                            ; b8 7f 01
-    jmp short 02463h                          ; eb 03
+    jmp short 02478h                          ; eb 03
     mov ax, 00186h                            ; b8 86 01
     push ax                                   ; 50
     movzx ax, byte [bp-018h]                  ; 0f b6 46 e8
     push ax                                   ; 50
     push 0018dh                               ; 68 8d 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 9c f4
+    call 01922h                               ; e8 9c f4
     add sp, strict byte 00008h                ; 83 c4 08
     xor di, di                                ; 31 ff
     movzx ax, byte [bp+di-060h]               ; 0f b6 43 a0
     inc di                                    ; 47
     test ax, ax                               ; 85 c0
-    je short 0248dh                           ; 74 0e
+    je short 024a2h                           ; 74 0e
     push ax                                   ; 50
     push 00198h                               ; 68 98 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 85 f4
+    call 01922h                               ; e8 85 f4
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp short 02476h                          ; eb e9
+    jmp short 0248bh                          ; eb e9
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     les bx, [bp-028h]                         ; c4 5e d8
     add bx, ax                                ; 01 c3
     cmp byte [es:bx+01fh], 005h               ; 26 80 7f 1f 05
-    jne short 024aah                          ; 75 0a
+    jne short 024bfh                          ; 75 0a
     movzx ax, byte [bp-012h]                  ; 0f b6 46 ee
     push ax                                   ; 50
     push 001bbh                               ; 68 bb 01
-    jmp short 024b2h                          ; eb 08
+    jmp short 024c7h                          ; eb 08
     movzx ax, byte [bp-012h]                  ; 0f b6 46 ee
     push ax                                   ; 50
     push 001d5h                               ; 68 d5 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 56 f4
+    call 01922h                               ; e8 56 f4
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp short 024dbh                          ; eb 1f
+    jmp short 024f0h                          ; eb 1f
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    je short 024c7h                           ; 74 05
+    je short 024dch                           ; 74 05
     mov ax, 0017fh                            ; b8 7f 01
-    jmp short 024cah                          ; eb 03
+    jmp short 024dfh                          ; eb 03
     mov ax, 00186h                            ; b8 86 01
     push ax                                   ; 50
     movzx ax, byte [bp-018h]                  ; 0f b6 46 e8
     push ax                                   ; 50
     push 001e7h                               ; 68 e7 01
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 35 f4
+    call 01922h                               ; e8 35 f4
     add sp, strict byte 00008h                ; 83 c4 08
     inc byte [bp-00eh]                        ; fe 46 f2
     cmp byte [bp-00eh], 008h                  ; 80 7e f2 08
-    jnc short 02532h                          ; 73 4e
+    jnc short 02547h                          ; 73 4e
     movzx bx, byte [bp-00eh]                  ; 0f b6 5e f2
     mov ax, bx                                ; 89 d8
     cwd                                       ; 99
@@ -2664,9 +2677,9 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     mov AL, strict byte 00ah                  ; b0 0a
     out DX, AL                                ; ee
     test cl, cl                               ; 84 c9
-    je near 01f9ch                            ; 0f 84 70 fa
+    je near 01fb1h                            ; 0f 84 70 fa
     mov ax, 000b0h                            ; b8 b0 00
-    jmp near 01f9fh                           ; e9 6d fa
+    jmp near 01fb4h                           ; e9 6d fa
     mov al, byte [bp-006h]                    ; 8a 46 fa
     les bx, [bp-028h]                         ; c4 5e d8
     mov byte [es:bx+0019eh], al               ; 26 88 87 9e 01
@@ -2675,13 +2688,13 @@ _ata_detect:                                 ; 0xf1f42 LB 0x617
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     mov dx, strict word 00075h                ; ba 75 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 bc f0
+    call 0160eh                               ; e8 a7 f0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
+ata_cmd_data_out_:                           ; 0xf256e LB 0x21a
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -2710,22 +2723,22 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     mov al, byte [es:si+022h]                 ; 26 8a 44 22
     mov byte [bp-008h], al                    ; 88 46 f8
     cmp AL, strict byte 001h                  ; 3c 01
-    jne short 025adh                          ; 75 07
+    jne short 025c2h                          ; 75 07
     mov word [bp-012h], 00080h                ; c7 46 ee 80 00
-    jmp short 025b2h                          ; eb 05
+    jmp short 025c7h                          ; eb 05
     mov word [bp-012h], 00100h                ; c7 46 ee 00 01
     lea dx, [bx+007h]                         ; 8d 57 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 080h                 ; a8 80
-    je short 025cbh                           ; 74 0f
+    je short 025e0h                           ; 74 0f
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00001h                ; ba 01 00
-    jmp near 0276ah                           ; e9 9f 01
+    jmp near 0277fh                           ; e9 9f 01
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov ax, word [es:di]                      ; 26 8b 05
     mov word [bp-01eh], ax                    ; 89 46 e2
@@ -2742,13 +2755,13 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     mov word [bp-014h], ax                    ; 89 46 ec
     mov ax, word [bp-010h]                    ; 8b 46 f0
     test ax, ax                               ; 85 c0
-    jne short 02669h                          ; 75 67
+    jne short 0267eh                          ; 75 67
     mov dx, word [bp-01eh]                    ; 8b 56 e2
     add dx, word [bp-00eh]                    ; 03 56 f2
     adc ax, word [bp-01ch]                    ; 13 46 e4
     cmp ax, 01000h                            ; 3d 00 10
-    jnbe short 02612h                         ; 77 02
-    jne short 0263dh                          ; 75 2b
+    jnbe short 02627h                         ; 77 02
+    jne short 02652h                          ; 75 2b
     mov ax, word [bp-01ch]                    ; 8b 46 e4
     xor al, al                                ; 30 c0
     shr ax, 008h                              ; c1 e8 08
@@ -2773,7 +2786,7 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     mov cx, strict word 00008h                ; b9 08 00
     shr word [bp-01ch], 1                     ; d1 6e e4
     rcr word [bp-01eh], 1                     ; d1 5e e2
-    loop 02648h                               ; e2 f8
+    loop 0265dh                               ; e2 f8
     mov ax, word [bp-01eh]                    ; 8b 46 e2
     mov word [bp-016h], ax                    ; 89 46 ea
     mov ax, word [bp-01ch]                    ; 8b 46 e4
@@ -2802,9 +2815,9 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     lea dx, [bx+005h]                         ; 8d 57 05
     out DX, AL                                ; ee
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
-    je short 0269fh                           ; 74 05
+    je short 026b4h                           ; 74 05
     mov ax, 000b0h                            ; b8 b0 00
-    jmp short 026a2h                          ; eb 03
+    jmp short 026b7h                          ; eb 03
     mov ax, 000a0h                            ; b8 a0 00
     movzx dx, byte [bp-014h]                  ; 0f b6 56 ec
     or ax, dx                                 ; 09 d0
@@ -2819,38 +2832,38 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
     test AL, strict byte 080h                 ; a8 80
-    jne short 026b3h                          ; 75 f4
+    jne short 026c8h                          ; 75 f4
     test AL, strict byte 001h                 ; a8 01
-    je short 026d2h                           ; 74 0f
+    je short 026e7h                           ; 74 0f
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00002h                ; ba 02 00
-    jmp near 0276ah                           ; e9 98 00
+    jmp near 0277fh                           ; e9 98 00
     test dl, 008h                             ; f6 c2 08
-    jne short 026e6h                          ; 75 0f
+    jne short 026fbh                          ; 75 0f
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00003h                ; ba 03 00
-    jmp near 0276ah                           ; e9 84 00
+    jmp near 0277fh                           ; e9 84 00
     sti                                       ; fb
     cmp si, 0f800h                            ; 81 fe 00 f8
-    jc short 026fah                           ; 72 0d
+    jc short 0270fh                           ; 72 0d
     sub si, 00800h                            ; 81 ee 00 08
     mov ax, word [bp-018h]                    ; 8b 46 e8
     add ax, 00080h                            ; 05 80 00
     mov word [bp-018h], ax                    ; 89 46 e8
     cmp byte [bp-008h], 001h                  ; 80 7e f8 01
-    jne short 0270eh                          ; 75 0e
+    jne short 02723h                          ; 75 0e
     mov dx, bx                                ; 89 da
     mov cx, word [bp-012h]                    ; 8b 4e ee
     mov es, [bp-018h]                         ; 8e 46 e8
     db  0f3h, 066h, 026h, 06fh
     ; rep es outsd                              ; f3 66 26 6f
-    jmp short 02719h                          ; eb 0b
+    jmp short 0272eh                          ; eb 0b
     mov dx, bx                                ; 89 da
     mov cx, word [bp-012h]                    ; 8b 4e ee
     mov es, [bp-018h]                         ; 8e 46 e8
@@ -2865,28 +2878,28 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
     test AL, strict byte 080h                 ; a8 80
-    jne short 02723h                          ; 75 f4
+    jne short 02738h                          ; 75 f4
     cmp word [bp-00eh], strict byte 00000h    ; 83 7e f2 00
-    jne short 02749h                          ; 75 14
+    jne short 0275eh                          ; 75 14
     and AL, strict byte 0e9h                  ; 24 e9
     cmp AL, strict byte 040h                  ; 3c 40
-    je short 0275fh                           ; 74 24
+    je short 02774h                           ; 74 24
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00006h                ; ba 06 00
-    jmp short 0276ah                          ; eb 21
+    jmp short 0277fh                          ; eb 21
     mov al, dl                                ; 88 d0
     and AL, strict byte 0c9h                  ; 24 c9
     cmp AL, strict byte 048h                  ; 3c 48
-    je short 026e7h                           ; 74 96
+    je short 026fch                           ; 74 96
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00007h                ; ba 07 00
-    jmp short 0276ah                          ; eb 0b
+    jmp short 0277fh                          ; eb 0b
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
@@ -2898,7 +2911,7 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
- at ata_read_sectors:                           ; 0xf2773 LB 0x7a
+ at ata_read_sectors:                           ; 0xf2788 LB 0x7a
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -2912,24 +2925,24 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     sal dx, 009h                              ; c1 e2 09
     mov ax, word [es:si+012h]                 ; 26 8b 44 12
     test ax, ax                               ; 85 c0
-    je short 027a1h                           ; 74 0d
+    je short 027b6h                           ; 74 0d
     movzx di, bl                              ; 0f b6 fb
     imul di, di, strict byte 00018h           ; 6b ff 18
     mov [bp-006h], es                         ; 8c 46 fa
     add di, si                                ; 01 f7
-    jmp short 027cdh                          ; eb 2c
+    jmp short 027e2h                          ; eb 2c
     mov di, word [es:si]                      ; 26 8b 3c
     add di, cx                                ; 01 cf
     mov word [bp-006h], di                    ; 89 7e fa
     adc ax, word [es:si+002h]                 ; 26 13 44 02
     cmp ax, 01000h                            ; 3d 00 10
-    jnbe short 027b4h                         ; 77 02
-    jne short 027c0h                          ; 75 0c
+    jnbe short 027c9h                         ; 77 02
+    jne short 027d5h                          ; 75 0c
     mov bx, strict word 00024h                ; bb 24 00
     mov ax, si                                ; 89 f0
     mov dx, es                                ; 8c c2
-    call 01ceah                               ; e8 2c f5
-    jmp short 027e4h                          ; eb 24
+    call 01cffh                               ; e8 2c f5
+    jmp short 027f9h                          ; eb 24
     movzx ax, bl                              ; 0f b6 c3
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov [bp-006h], es                         ; 8c 46 fa
@@ -2939,7 +2952,7 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     mov bx, 000c4h                            ; bb c4 00
     mov ax, si                                ; 89 f0
     mov dx, es                                ; 8c c2
-    call 01ceah                               ; e8 0f f5
+    call 01cffh                               ; e8 0f f5
     mov es, [bp-006h]                         ; 8e 46 fa
     mov word [es:di+024h], 00200h             ; 26 c7 45 24 00 02
     lea sp, [bp-004h]                         ; 8d 66 fc
@@ -2947,33 +2960,33 @@ ata_cmd_data_out_:                           ; 0xf2559 LB 0x21a
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
- at ata_write_sectors:                          ; 0xf27ed LB 0x3d
+ at ata_write_sectors:                          ; 0xf2802 LB 0x3d
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
     les si, [bp+004h]                         ; c4 76 04
     mov cx, word [es:si+00ah]                 ; 26 8b 4c 0a
     cmp word [es:si+012h], strict byte 00000h ; 26 83 7c 12 00
-    je short 0280bh                           ; 74 0c
+    je short 02820h                           ; 74 0c
     mov bx, strict word 00030h                ; bb 30 00
     mov ax, si                                ; 89 f0
     mov dx, es                                ; 8c c2
-    call 02559h                               ; e8 50 fd
-    jmp short 02822h                          ; eb 17
+    call 0256eh                               ; e8 50 fd
+    jmp short 02837h                          ; eb 17
     xor ax, ax                                ; 31 c0
     mov dx, word [es:si]                      ; 26 8b 14
     add dx, cx                                ; 01 ca
     adc ax, word [es:si+002h]                 ; 26 13 44 02
     cmp ax, 01000h                            ; 3d 00 10
-    jnbe short 0281dh                         ; 77 02
-    jne short 027ffh                          ; 75 e2
+    jnbe short 02832h                         ; 77 02
+    jne short 02814h                          ; 75 e2
     mov bx, strict word 00034h                ; bb 34 00
-    jmp short 02802h                          ; eb e0
+    jmp short 02817h                          ; eb e0
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
-ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
+ata_cmd_packet_:                             ; 0xf283f LB 0x2e8
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -2984,7 +2997,7 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     mov di, bx                                ; 89 df
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 db ed
+    call 0161ch                               ; e8 c6 ed
     mov word [bp-012h], 00122h                ; c7 46 ee 22 01
     mov word [bp-00eh], ax                    ; 89 46 f2
     mov ax, word [bp-01ah]                    ; 8b 46 e6
@@ -2993,20 +3006,20 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     and ah, 001h                              ; 80 e4 01
     mov byte [bp-006h], ah                    ; 88 66 fa
     cmp byte [bp+00ah], 002h                  ; 80 7e 0a 02
-    jne short 0287ch                          ; 75 1f
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 02891h                          ; 75 1f
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 64 f0
+    call 018e1h                               ; e8 64 f0
     push 00201h                               ; 68 01 02
     push 00210h                               ; 68 10 02
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 9a f0
+    call 01922h                               ; e8 9a f0
     add sp, strict byte 00006h                ; 83 c4 06
     mov dx, strict word 00001h                ; ba 01 00
-    jmp near 02b07h                           ; e9 8b 02
+    jmp near 02b1ch                           ; e9 8b 02
     test byte [bp+004h], 001h                 ; f6 46 04 01
-    jne short 02876h                          ; 75 f4
+    jne short 0288bh                          ; 75 f4
     xor ah, ah                                ; 30 e4
     imul ax, ax, strict byte 00006h           ; 6b c0 06
     mov es, [bp-00eh]                         ; 8e 46 f2
@@ -3024,10 +3037,10 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     mov word [bp-016h], ax                    ; 89 46 ea
     mov al, byte [bp-008h]                    ; 8a 46 f8
     cmp AL, strict byte 00ch                  ; 3c 0c
-    jnc short 028bfh                          ; 73 06
+    jnc short 028d4h                          ; 73 06
     mov byte [bp-008h], 00ch                  ; c6 46 f8 0c
-    jmp short 028c5h                          ; eb 06
-    jbe short 028c5h                          ; 76 04
+    jmp short 028dah                          ; eb 06
+    jbe short 028dah                          ; 76 04
     mov byte [bp-008h], 010h                  ; c6 46 f8 10
     shr byte [bp-008h], 1                     ; d0 6e f8
     mov es, [bp-00eh]                         ; 8e 46 f2
@@ -3040,9 +3053,9 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 080h                 ; a8 80
-    je short 028edh                           ; 74 06
+    je short 02902h                           ; 74 06
     mov dx, strict word 00002h                ; ba 02 00
-    jmp near 02b07h                           ; e9 1a 02
+    jmp near 02b1ch                           ; e9 1a 02
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 00ah                  ; b0 0a
@@ -3054,9 +3067,9 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     mov AL, strict byte 0ffh                  ; b0 ff
     out DX, AL                                ; ee
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
-    je short 0290dh                           ; 74 05
+    je short 02922h                           ; 74 05
     mov ax, 000b0h                            ; b8 b0 00
-    jmp short 02910h                          ; eb 03
+    jmp short 02925h                          ; eb 03
     mov ax, 000a0h                            ; b8 a0 00
     lea dx, [bx+006h]                         ; 8d 57 06
     out DX, AL                                ; ee
@@ -3069,23 +3082,23 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
     test AL, strict byte 080h                 ; a8 80
-    jne short 0291ah                          ; 75 f4
+    jne short 0292fh                          ; 75 f4
     test AL, strict byte 001h                 ; a8 01
-    je short 02939h                           ; 74 0f
+    je short 0294eh                           ; 74 0f
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00003h                ; ba 03 00
-    jmp near 02b07h                           ; e9 ce 01
+    jmp near 02b1ch                           ; e9 ce 01
     test dl, 008h                             ; f6 c2 08
-    jne short 0294dh                          ; 75 0f
+    jne short 02962h                          ; 75 0f
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov dx, strict word 00004h                ; ba 04 00
-    jmp near 02b07h                           ; e9 ba 01
+    jmp near 02b1ch                           ; e9 ba 01
     sti                                       ; fb
     mov ax, di                                ; 89 f8
     shr ax, 004h                              ; c1 e8 04
@@ -3098,38 +3111,38 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     db  0f3h, 026h, 06fh
     ; rep es outsw                              ; f3 26 6f
     cmp byte [bp+00ah], 000h                  ; 80 7e 0a 00
-    jne short 02976h                          ; 75 0b
+    jne short 0298bh                          ; 75 0b
     lea dx, [bx+007h]                         ; 8d 57 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
-    jmp near 02ae8h                           ; e9 72 01
+    jmp near 02afdh                           ; e9 72 01
     lea dx, [bx+007h]                         ; 8d 57 07
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     mov dl, al                                ; 88 c2
     test AL, strict byte 080h                 ; a8 80
-    jne short 02976h                          ; 75 f4
+    jne short 0298bh                          ; 75 f4
     test AL, strict byte 088h                 ; a8 88
-    je near 02ae8h                            ; 0f 84 60 01
+    je near 02afdh                            ; 0f 84 60 01
     test AL, strict byte 001h                 ; a8 01
-    je short 02997h                           ; 74 0b
+    je short 029ach                           ; 74 0b
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
-    jmp short 02933h                          ; eb 9c
+    jmp short 02948h                          ; eb 9c
     mov al, dl                                ; 88 d0
     and AL, strict byte 0c9h                  ; 24 c9
     cmp AL, strict byte 048h                  ; 3c 48
-    je short 029aah                           ; 74 0b
+    je short 029bfh                           ; 74 0b
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
-    jmp short 02947h                          ; eb 9d
+    jmp short 0295ch                          ; eb 9d
     mov ax, word [bp+00ch]                    ; 8b 46 0c
     shr ax, 004h                              ; c1 e8 04
     mov dx, word [bp+00eh]                    ; 8b 56 0e
@@ -3152,21 +3165,21 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     mov word [bp-014h], cx                    ; 89 4e ec
     mov ax, word [bp+004h]                    ; 8b 46 04
     cmp ax, cx                                ; 39 c8
-    jbe short 029eah                          ; 76 0c
+    jbe short 029ffh                          ; 76 0c
     mov ax, cx                                ; 89 c8
     sub word [bp+004h], cx                    ; 29 4e 04
     xor ax, cx                                ; 31 c8
     mov word [bp-014h], ax                    ; 89 46 ec
-    jmp short 029f4h                          ; eb 0a
+    jmp short 02a09h                          ; eb 0a
     mov cx, ax                                ; 89 c1
     mov word [bp+004h], strict word 00000h    ; c7 46 04 00 00
     sub word [bp-014h], ax                    ; 29 46 ec
     xor ax, ax                                ; 31 c0
     cmp word [bp+008h], strict byte 00000h    ; 83 7e 08 00
-    jne short 02a1dh                          ; 75 21
+    jne short 02a32h                          ; 75 21
     mov dx, word [bp-014h]                    ; 8b 56 ec
     cmp dx, word [bp+006h]                    ; 3b 56 06
-    jbe short 02a1dh                          ; 76 19
+    jbe short 02a32h                          ; 76 19
     mov ax, word [bp-014h]                    ; 8b 46 ec
     sub ax, word [bp+006h]                    ; 2b 46 06
     mov word [bp-00ch], ax                    ; 89 46 f4
@@ -3175,7 +3188,7 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     xor ax, ax                                ; 31 c0
     mov word [bp+006h], ax                    ; 89 46 06
     mov word [bp+008h], ax                    ; 89 46 08
-    jmp short 02a29h                          ; eb 0c
+    jmp short 02a3eh                          ; eb 0c
     mov word [bp-00ch], ax                    ; 89 46 f4
     mov dx, word [bp-014h]                    ; 8b 56 ec
     sub word [bp+006h], dx                    ; 29 56 06
@@ -3183,39 +3196,39 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     mov si, word [bp-014h]                    ; 8b 76 ec
     mov al, byte [bp-00ah]                    ; 8a 46 f6
     test cl, 003h                             ; f6 c1 03
-    je short 02a36h                           ; 74 02
+    je short 02a4bh                           ; 74 02
     xor al, al                                ; 30 c0
     test byte [bp-014h], 003h                 ; f6 46 ec 03
-    je short 02a3eh                           ; 74 02
+    je short 02a53h                           ; 74 02
     xor al, al                                ; 30 c0
     test byte [bp-00ch], 003h                 ; f6 46 f4 03
-    je short 02a46h                           ; 74 02
+    je short 02a5bh                           ; 74 02
     xor al, al                                ; 30 c0
     test byte [bp-014h], 001h                 ; f6 46 ec 01
-    je short 02a5eh                           ; 74 12
+    je short 02a73h                           ; 74 12
     inc word [bp-014h]                        ; ff 46 ec
     cmp word [bp-00ch], strict byte 00000h    ; 83 7e f4 00
-    jbe short 02a5eh                          ; 76 09
+    jbe short 02a73h                          ; 76 09
     test byte [bp-00ch], 001h                 ; f6 46 f4 01
-    je short 02a5eh                           ; 74 03
+    je short 02a73h                           ; 74 03
     dec word [bp-00ch]                        ; ff 4e f4
     cmp AL, strict byte 001h                  ; 3c 01
-    jne short 02a6fh                          ; 75 0d
+    jne short 02a84h                          ; 75 0d
     shr word [bp-014h], 002h                  ; c1 6e ec 02
     shr cx, 002h                              ; c1 e9 02
     shr word [bp-00ch], 002h                  ; c1 6e f4 02
-    jmp short 02a77h                          ; eb 08
+    jmp short 02a8ch                          ; eb 08
     shr word [bp-014h], 1                     ; d1 6e ec
     shr cx, 1                                 ; d1 e9
     shr word [bp-00ch], 1                     ; d1 6e f4
     cmp AL, strict byte 001h                  ; 3c 01
-    jne short 02aa7h                          ; 75 2c
+    jne short 02abch                          ; 75 2c
     test cx, cx                               ; 85 c9
-    je short 02a89h                           ; 74 0a
+    je short 02a9eh                           ; 74 0a
     mov dx, bx                                ; 89 da
     push eax                                  ; 66 50
     in eax, DX                                ; 66 ed
-    loop 02a83h                               ; e2 fc
+    loop 02a98h                               ; e2 fc
     pop eax                                   ; 66 58
     mov dx, bx                                ; 89 da
     mov cx, word [bp-014h]                    ; 8b 4e ec
@@ -3224,28 +3237,28 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     ; rep insd                                  ; f3 66 6d
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     test ax, ax                               ; 85 c0
-    je short 02ac6h                           ; 74 2b
+    je short 02adbh                           ; 74 2b
     mov cx, ax                                ; 89 c1
     push eax                                  ; 66 50
     in eax, DX                                ; 66 ed
-    loop 02a9fh                               ; e2 fc
+    loop 02ab4h                               ; e2 fc
     pop eax                                   ; 66 58
-    jmp short 02ac6h                          ; eb 1f
+    jmp short 02adbh                          ; eb 1f
     test cx, cx                               ; 85 c9
-    je short 02ab0h                           ; 74 05
+    je short 02ac5h                           ; 74 05
     mov dx, bx                                ; 89 da
     in ax, DX                                 ; ed
-    loop 02aadh                               ; e2 fd
+    loop 02ac2h                               ; e2 fd
     mov dx, bx                                ; 89 da
     mov cx, word [bp-014h]                    ; 8b 4e ec
     les di, [bp+00ch]                         ; c4 7e 0c
     rep insw                                  ; f3 6d
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     test ax, ax                               ; 85 c0
-    je short 02ac6h                           ; 74 05
+    je short 02adbh                           ; 74 05
     mov cx, ax                                ; 89 c1
     in ax, DX                                 ; ed
-    loop 02ac3h                               ; e2 fd
+    loop 02ad8h                               ; e2 fd
     add word [bp+00ch], si                    ; 01 76 0c
     xor ax, ax                                ; 31 c0
     add word [bp-018h], si                    ; 01 76 e8
@@ -3256,16 +3269,16 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     mov word [es:si+016h], ax                 ; 26 89 44 16
     mov ax, word [bp-016h]                    ; 8b 46 ea
     mov word [es:si+018h], ax                 ; 26 89 44 18
-    jmp near 02976h                           ; e9 8e fe
+    jmp near 0298bh                           ; e9 8e fe
     mov al, dl                                ; 88 d0
     and AL, strict byte 0e9h                  ; 24 e9
     cmp AL, strict byte 040h                  ; 3c 40
-    je short 02afch                           ; 74 0c
+    je short 02b11h                           ; 74 0c
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
-    jmp near 02947h                           ; e9 4b fe
+    jmp near 0295ch                           ; e9 4b fe
     mov dx, word [bp-010h]                    ; 8b 56 f0
     add dx, strict byte 00006h                ; 83 c2 06
     mov AL, strict byte 008h                  ; b0 08
@@ -3277,7 +3290,7 @@ ata_cmd_packet_:                             ; 0xf282a LB 0x2e8
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 0000ch                               ; c2 0c 00
-ata_soft_reset_:                             ; 0xf2b12 LB 0x80
+ata_soft_reset_:                             ; 0xf2b27 LB 0x80
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3287,7 +3300,7 @@ ata_soft_reset_:                             ; 0xf2b12 LB 0x80
     mov bx, ax                                ; 89 c3
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 f8 ea
+    call 0161ch                               ; e8 e3 ea
     mov dx, bx                                ; 89 da
     shr dx, 1                                 ; d1 ea
     and bl, 001h                              ; 80 e3 01
@@ -3302,9 +3315,9 @@ ata_soft_reset_:                             ; 0xf2b12 LB 0x80
     mov AL, strict byte 00ah                  ; b0 0a
     out DX, AL                                ; ee
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    je short 02b54h                           ; 74 05
+    je short 02b69h                           ; 74 05
     mov ax, 000b0h                            ; b8 b0 00
-    jmp short 02b57h                          ; eb 03
+    jmp short 02b6ch                          ; eb 03
     mov ax, 000a0h                            ; b8 a0 00
     mov dx, cx                                ; 89 ca
     add dx, strict byte 00006h                ; 83 c2 06
@@ -3319,15 +3332,15 @@ ata_soft_reset_:                             ; 0xf2b12 LB 0x80
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 080h                 ; a8 80
-    jne short 02b65h                          ; 75 f4
+    jne short 02b7ah                          ; 75 f4
     and AL, strict byte 0e9h                  ; 24 e9
     cmp AL, strict byte 040h                  ; 3c 40
-    je short 02b82h                           ; 74 0b
+    je short 02b97h                           ; 74 0b
     lea dx, [bx+006h]                         ; 8d 57 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
     mov ax, strict word 00001h                ; b8 01 00
-    jmp short 02b8ah                          ; eb 08
+    jmp short 02b9fh                          ; eb 08
     lea dx, [bx+006h]                         ; 8d 57 06
     mov AL, strict byte 008h                  ; b0 08
     out DX, AL                                ; ee
@@ -3338,7 +3351,7 @@ ata_soft_reset_:                             ; 0xf2b12 LB 0x80
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-set_diskette_ret_status_:                    ; 0xf2b92 LB 0x18
+set_diskette_ret_status_:                    ; 0xf2ba7 LB 0x18
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3346,54 +3359,54 @@ set_diskette_ret_status_:                    ; 0xf2b92 LB 0x18
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00041h                ; ba 41 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 6b ea
+    call 0160eh                               ; e8 56 ea
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop dx                                    ; 5a
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-set_diskette_current_cyl_:                   ; 0xf2baa LB 0x2d
+set_diskette_current_cyl_:                   ; 0xf2bbf LB 0x2d
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
     mov bl, al                                ; 88 c3
     cmp AL, strict byte 001h                  ; 3c 01
-    jbe short 02bbfh                          ; 76 0b
+    jbe short 02bd4h                          ; 76 0b
     push 00230h                               ; 68 30 02
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 51 ed
+    call 01922h                               ; e8 51 ed
     add sp, strict byte 00004h                ; 83 c4 04
     movzx ax, dl                              ; 0f b6 c2
     movzx dx, bl                              ; 0f b6 d3
     add dx, 00094h                            ; 81 c2 94 00
     mov bx, ax                                ; 89 c3
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 3d ea
+    call 0160eh                               ; e8 28 ea
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_wait_for_interrupt_:                  ; 0xf2bd7 LB 0x21
+floppy_wait_for_interrupt_:                  ; 0xf2bec LB 0x21
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
     cli                                       ; fa
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 1b ea
+    call 01600h                               ; e8 06 ea
     test AL, strict byte 080h                 ; a8 80
-    je short 02bedh                           ; 74 04
+    je short 02c02h                           ; 74 04
     and AL, strict byte 080h                  ; 24 80
-    jmp short 02bf2h                          ; eb 05
+    jmp short 02c07h                          ; eb 05
     sti                                       ; fb
     hlt                                       ; f4
     cli                                       ; fa
-    jmp short 02bdch                          ; eb ea
+    jmp short 02bf1h                          ; eb ea
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_wait_for_interrupt_or_timeout_:       ; 0xf2bf8 LB 0x46
+floppy_wait_for_interrupt_or_timeout_:       ; 0xf2c0d LB 0x46
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3402,28 +3415,28 @@ floppy_wait_for_interrupt_or_timeout_:       ; 0xf2bf8 LB 0x46
     cli                                       ; fa
     mov dx, strict word 00040h                ; ba 40 00
     mov ax, dx                                ; 89 d0
-    call 01600h                               ; e8 f9 e9
+    call 01600h                               ; e8 e4 e9
     test al, al                               ; 84 c0
-    jne short 02c10h                          ; 75 05
+    jne short 02c25h                          ; 75 05
     sti                                       ; fb
     xor cl, cl                                ; 30 c9
-    jmp short 02c34h                          ; eb 24
+    jmp short 02c49h                          ; eb 24
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 e7 e9
+    call 01600h                               ; e8 d2 e9
     mov cl, al                                ; 88 c1
     test AL, strict byte 080h                 ; a8 80
-    je short 02c2fh                           ; 74 10
+    je short 02c44h                           ; 74 10
     and AL, strict byte 07fh                  ; 24 7f
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 e1 e9
-    jmp short 02c34h                          ; eb 05
+    call 0160eh                               ; e8 cc e9
+    jmp short 02c49h                          ; eb 05
     sti                                       ; fb
     hlt                                       ; f4
     cli                                       ; fa
-    jmp short 02bffh                          ; eb cb
+    jmp short 02c14h                          ; eb cb
     mov al, cl                                ; 88 c8
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop dx                                    ; 5a
@@ -3431,7 +3444,7 @@ floppy_wait_for_interrupt_or_timeout_:       ; 0xf2bf8 LB 0x46
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_reset_controller_:                    ; 0xf2c3e LB 0x2b
+floppy_reset_controller_:                    ; 0xf2c53 LB 0x2b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3453,13 +3466,13 @@ floppy_reset_controller_:                    ; 0xf2c3e LB 0x2b
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 080h                  ; 3c 80
-    jne short 02c56h                          ; 75 f4
+    jne short 02c6bh                          ; 75 f4
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop dx                                    ; 5a
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_prepare_controller_:                  ; 0xf2c69 LB 0x81
+floppy_prepare_controller_:                  ; 0xf2c7e LB 0x81
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3469,12 +3482,12 @@ floppy_prepare_controller_:                  ; 0xf2c69 LB 0x81
     mov cx, ax                                ; 89 c1
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 85 e9
+    call 01600h                               ; e8 70 e9
     and AL, strict byte 07fh                  ; 24 7f
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 85 e9
+    call 0160eh                               ; e8 70 e9
     mov dx, 003f2h                            ; ba f2 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -3482,9 +3495,9 @@ floppy_prepare_controller_:                  ; 0xf2c69 LB 0x81
     and AL, strict byte 004h                  ; 24 04
     mov byte [bp-008h], al                    ; 88 46 f8
     test cx, cx                               ; 85 c9
-    je short 02c9ch                           ; 74 04
+    je short 02cb1h                           ; 74 04
     mov AL, strict byte 020h                  ; b0 20
-    jmp short 02c9eh                          ; eb 02
+    jmp short 02cb3h                          ; eb 02
     mov AL, strict byte 010h                  ; b0 10
     or AL, strict byte 00ch                   ; 0c 0c
     or al, cl                                 ; 08 c8
@@ -3493,10 +3506,10 @@ floppy_prepare_controller_:                  ; 0xf2c69 LB 0x81
     mov bx, strict word 00025h                ; bb 25 00
     mov dx, strict word 00040h                ; ba 40 00
     mov ax, dx                                ; 89 d0
-    call 0160eh                               ; e8 5d e9
+    call 0160eh                               ; e8 48 e9
     mov dx, 0008bh                            ; ba 8b 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 46 e9
+    call 01600h                               ; e8 31 e9
     shr al, 006h                              ; c0 e8 06
     mov dx, 003f7h                            ; ba f7 03
     out DX, AL                                ; ee
@@ -3506,21 +3519,21 @@ floppy_prepare_controller_:                  ; 0xf2c69 LB 0x81
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 080h                  ; 3c 80
-    jne short 02cc1h                          ; 75 f4
+    jne short 02cd6h                          ; 75 f4
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    jne short 02ce2h                          ; 75 0f
-    call 02bd7h                               ; e8 01 ff
+    jne short 02cf7h                          ; 75 0f
+    call 02bech                               ; e8 01 ff
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 2c e9
+    call 0160eh                               ; e8 17 e9
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop dx                                    ; 5a
     pop cx                                    ; 59
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_media_known_:                         ; 0xf2cea LB 0x43
+floppy_media_known_:                         ; 0xf2cff LB 0x43
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3528,32 +3541,32 @@ floppy_media_known_:                         ; 0xf2cea LB 0x43
     mov bx, ax                                ; 89 c3
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 06 e9
+    call 01600h                               ; e8 f1 e8
     mov ah, al                                ; 88 c4
     test bx, bx                               ; 85 db
-    je short 02d02h                           ; 74 02
+    je short 02d17h                           ; 74 02
     shr al, 1                                 ; d0 e8
     and AL, strict byte 001h                  ; 24 01
-    jne short 02d0ah                          ; 75 04
+    jne short 02d1fh                          ; 75 04
     xor ah, ah                                ; 30 e4
-    jmp short 02d26h                          ; eb 1c
+    jmp short 02d3bh                          ; eb 1c
     mov dx, 00090h                            ; ba 90 00
     test bx, bx                               ; 85 db
-    je short 02d14h                           ; 74 03
+    je short 02d29h                           ; 74 03
     mov dx, 00091h                            ; ba 91 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 e6 e8
+    call 01600h                               ; e8 d1 e8
     xor ah, ah                                ; 30 e4
     sar ax, 004h                              ; c1 f8 04
     and AL, strict byte 001h                  ; 24 01
-    je short 02d06h                           ; 74 e3
+    je short 02d1bh                           ; 74 e3
     mov ax, strict word 00001h                ; b8 01 00
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop dx                                    ; 5a
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_read_id_:                             ; 0xf2d2d LB 0x40
+floppy_read_id_:                             ; 0xf2d42 LB 0x40
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3561,24 +3574,24 @@ floppy_read_id_:                             ; 0xf2d2d LB 0x40
     push si                                   ; 56
     sub sp, strict byte 00008h                ; 83 ec 08
     mov bx, ax                                ; 89 c3
-    call 02c69h                               ; e8 2e ff
+    call 02c7eh                               ; e8 2e ff
     mov AL, strict byte 04ah                  ; b0 4a
     mov dx, 003f5h                            ; ba f5 03
     out DX, AL                                ; ee
     mov al, bl                                ; 88 d8
     out DX, AL                                ; ee
-    call 02bd7h                               ; e8 90 fe
+    call 02bech                               ; e8 90 fe
     xor si, si                                ; 31 f6
-    jmp short 02d50h                          ; eb 05
+    jmp short 02d65h                          ; eb 05
     cmp si, strict byte 00007h                ; 83 fe 07
-    jnl short 02d5ch                          ; 7d 0c
+    jnl short 02d71h                          ; 7d 0c
     mov dx, 003f5h                            ; ba f5 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     mov byte [bp+si-00eh], al                 ; 88 42 f2
     inc si                                    ; 46
-    jmp short 02d4bh                          ; eb ef
+    jmp short 02d60h                          ; eb ef
     test byte [bp-00eh], 0c0h                 ; f6 46 f2 c0
     db  00fh, 094h, 0c0h
     ; sete al                                   ; 0f 94 c0
@@ -3589,35 +3602,35 @@ floppy_read_id_:                             ; 0xf2d2d LB 0x40
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_drive_recal_:                         ; 0xf2d6d LB 0x48
+floppy_drive_recal_:                         ; 0xf2d82 LB 0x48
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
     push cx                                   ; 51
     push dx                                   ; 52
     mov bx, ax                                ; 89 c3
-    call 02c69h                               ; e8 f1 fe
+    call 02c7eh                               ; e8 f1 fe
     mov AL, strict byte 007h                  ; b0 07
     mov dx, 003f5h                            ; ba f5 03
     out DX, AL                                ; ee
     mov al, bl                                ; 88 d8
     out DX, AL                                ; ee
-    call 02bd7h                               ; e8 53 fe
+    call 02bech                               ; e8 53 fe
     test bx, bx                               ; 85 db
-    je short 02d8fh                           ; 74 07
+    je short 02da4h                           ; 74 07
     or AL, strict byte 002h                   ; 0c 02
     mov cx, 00095h                            ; b9 95 00
-    jmp short 02d94h                          ; eb 05
+    jmp short 02da9h                          ; eb 05
     or AL, strict byte 001h                   ; 0c 01
     mov cx, 00094h                            ; b9 94 00
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 6e e8
+    call 0160eh                               ; e8 59 e8
     xor bx, bx                                ; 31 db
     mov dx, cx                                ; 89 ca
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 64 e8
+    call 0160eh                               ; e8 4f e8
     mov ax, strict word 00001h                ; b8 01 00
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop dx                                    ; 5a
@@ -3625,7 +3638,7 @@ floppy_drive_recal_:                         ; 0xf2d6d LB 0x48
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_media_sense_:                         ; 0xf2db5 LB 0xf0
+floppy_media_sense_:                         ; 0xf2dca LB 0xf0
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -3634,85 +3647,85 @@ floppy_media_sense_:                         ; 0xf2db5 LB 0xf0
     push si                                   ; 56
     push di                                   ; 57
     mov di, ax                                ; 89 c7
-    call 02d6dh                               ; e8 ab ff
+    call 02d82h                               ; e8 ab ff
     test ax, ax                               ; 85 c0
-    jne short 02dcbh                          ; 75 05
+    jne short 02de0h                          ; 75 05
     xor cx, cx                                ; 31 c9
-    jmp near 02e99h                           ; e9 ce 00
+    jmp near 02eaeh                           ; e9 ce 00
     mov ax, strict word 00010h                ; b8 10 00
-    call 0165ch                               ; e8 8b e8
+    call 0165ch                               ; e8 76 e8
     test di, di                               ; 85 ff
-    jne short 02ddch                          ; 75 07
+    jne short 02df1h                          ; 75 07
     mov cl, al                                ; 88 c1
     shr cl, 004h                              ; c0 e9 04
-    jmp short 02de1h                          ; eb 05
+    jmp short 02df6h                          ; eb 05
     mov cl, al                                ; 88 c1
     and cl, 00fh                              ; 80 e1 0f
     cmp cl, 001h                              ; 80 f9 01
-    jne short 02defh                          ; 75 09
+    jne short 02e04h                          ; 75 09
     xor cl, cl                                ; 30 c9
     mov CH, strict byte 015h                  ; b5 15
     mov si, strict word 00001h                ; be 01 00
-    jmp short 02e2dh                          ; eb 3e
+    jmp short 02e42h                          ; eb 3e
     cmp cl, 002h                              ; 80 f9 02
-    jne short 02dfah                          ; 75 06
+    jne short 02e0fh                          ; 75 06
     xor cl, cl                                ; 30 c9
     mov CH, strict byte 035h                  ; b5 35
-    jmp short 02deah                          ; eb f0
+    jmp short 02dffh                          ; eb f0
     cmp cl, 003h                              ; 80 f9 03
-    jne short 02e05h                          ; 75 06
+    jne short 02e1ah                          ; 75 06
     xor cl, cl                                ; 30 c9
     mov CH, strict byte 017h                  ; b5 17
-    jmp short 02deah                          ; eb e5
+    jmp short 02dffh                          ; eb e5
     cmp cl, 004h                              ; 80 f9 04
-    jne short 02e10h                          ; 75 06
+    jne short 02e25h                          ; 75 06
     xor cl, cl                                ; 30 c9
     mov CH, strict byte 017h                  ; b5 17
-    jmp short 02deah                          ; eb da
+    jmp short 02dffh                          ; eb da
     cmp cl, 005h                              ; 80 f9 05
-    jne short 02e1bh                          ; 75 06
+    jne short 02e30h                          ; 75 06
     mov CL, strict byte 0cch                  ; b1 cc
     mov CH, strict byte 0d7h                  ; b5 d7
-    jmp short 02deah                          ; eb cf
+    jmp short 02dffh                          ; eb cf
     cmp cl, 00eh                              ; 80 f9 0e
-    je short 02e25h                           ; 74 05
+    je short 02e3ah                           ; 74 05
     cmp cl, 00fh                              ; 80 f9 0f
-    jne short 02e27h                          ; 75 02
-    jmp short 02e15h                          ; eb ee
+    jne short 02e3ch                          ; 75 02
+    jmp short 02e2ah                          ; eb ee
     xor cl, cl                                ; 30 c9
     xor ch, ch                                ; 30 ed
     xor si, si                                ; 31 f6
     movzx bx, cl                              ; 0f b6 d9
     mov dx, 0008bh                            ; ba 8b 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 d5 e7
+    call 0160eh                               ; e8 c0 e7
     mov ax, di                                ; 89 f8
-    call 02d2dh                               ; e8 ef fe
+    call 02d42h                               ; e8 ef fe
     test ax, ax                               ; 85 c0
-    jne short 02e74h                          ; 75 32
+    jne short 02e89h                          ; 75 32
     mov al, cl                                ; 88 c8
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 080h                  ; 3c 80
-    je short 02e74h                           ; 74 2a
+    je short 02e89h                           ; 74 2a
     mov al, cl                                ; 88 c8
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 0c0h                  ; 3c c0
-    je short 02e61h                           ; 74 0f
+    je short 02e76h                           ; 74 0f
     mov ah, cl                                ; 88 cc
     and ah, 03fh                              ; 80 e4 3f
     cmp AL, strict byte 040h                  ; 3c 40
-    je short 02e6dh                           ; 74 12
+    je short 02e82h                           ; 74 12
     test al, al                               ; 84 c0
-    je short 02e66h                           ; 74 07
-    jmp short 02e2dh                          ; eb cc
+    je short 02e7bh                           ; 74 07
+    jmp short 02e42h                          ; eb cc
     and cl, 03fh                              ; 80 e1 3f
-    jmp short 02e2dh                          ; eb c7
+    jmp short 02e42h                          ; eb c7
     mov cl, ah                                ; 88 e1
     or cl, 040h                               ; 80 c9 40
-    jmp short 02e2dh                          ; eb c0
+    jmp short 02e42h                          ; eb c0
     mov cl, ah                                ; 88 e1
     or cl, 080h                               ; 80 c9 80
-    jmp short 02e2dh                          ; eb b9
+    jmp short 02e42h                          ; eb b9
     test di, di                               ; 85 ff
     db  00fh, 095h, 0c0h
     ; setne al                                  ; 0f 95 c0
@@ -3721,11 +3734,11 @@ floppy_media_sense_:                         ; 0xf2db5 LB 0xf0
     movzx bx, cl                              ; 0f b6 d9
     mov dx, 0008bh                            ; ba 8b 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 82 e7
+    call 0160eh                               ; e8 6d e7
     movzx bx, ch                              ; 0f b6 dd
     mov dx, di                                ; 89 fa
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 77 e7
+    call 0160eh                               ; e8 62 e7
     mov cx, si                                ; 89 f1
     mov ax, cx                                ; 89 c8
     lea sp, [bp-00ah]                         ; 8d 66 f6
@@ -3736,17 +3749,17 @@ floppy_media_sense_:                         ; 0xf2db5 LB 0xf0
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-floppy_drive_exists_:                        ; 0xf2ea5 LB 0x24
+floppy_drive_exists_:                        ; 0xf2eba LB 0x24
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
     mov dx, ax                                ; 89 c2
     mov ax, strict word 00010h                ; b8 10 00
-    call 0165ch                               ; e8 ab e7
+    call 0165ch                               ; e8 96 e7
     test dx, dx                               ; 85 d2
-    jne short 02ebah                          ; 75 05
+    jne short 02ecfh                          ; 75 05
     shr al, 004h                              ; c0 e8 04
-    jmp short 02ebch                          ; eb 02
+    jmp short 02ed1h                          ; eb 02
     and AL, strict byte 00fh                  ; 24 0f
     test al, al                               ; 84 c0
     db  00fh, 095h, 0c0h
@@ -3756,7 +3769,7 @@ floppy_drive_exists_:                        ; 0xf2ea5 LB 0x24
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-_int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
+_int13_diskette_function:                    ; 0xf2ede LB 0x72a
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -3769,75 +3782,75 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     and si, 000ffh                            ; 81 e6 ff 00
     mov ah, byte [bp+00eh]                    ; 8a 66 0e
     cmp bl, 008h                              ; 80 fb 08
-    jc short 02f22h                           ; 72 3a
+    jc short 02f37h                           ; 72 3a
     mov dx, word [bp+01ch]                    ; 8b 56 1c
     or dl, 001h                               ; 80 ca 01
     cmp bl, 008h                              ; 80 fb 08
-    jbe near 03472h                           ; 0f 86 7d 05
+    jbe near 03487h                           ; 0f 86 7d 05
     cmp bl, 016h                              ; 80 fb 16
-    jc short 02f18h                           ; 72 1e
+    jc short 02f2dh                           ; 72 1e
     or si, 00100h                             ; 81 ce 00 01
     mov cx, si                                ; 89 f1
     cmp bl, 016h                              ; 80 fb 16
-    jbe near 035aeh                           ; 0f 86 a7 06
+    jbe near 035c3h                           ; 0f 86 a7 06
     cmp bl, 018h                              ; 80 fb 18
-    je near 035b3h                            ; 0f 84 a5 06
+    je near 035c8h                            ; 0f 84 a5 06
     cmp bl, 017h                              ; 80 fb 17
-    je near 035b3h                            ; 0f 84 9e 06
-    jmp near 035d0h                           ; e9 b8 06
+    je near 035c8h                            ; 0f 84 9e 06
+    jmp near 035e5h                           ; e9 b8 06
     cmp bl, 015h                              ; 80 fb 15
-    je near 03568h                            ; 0f 84 49 06
-    jmp near 035d0h                           ; e9 ae 06
+    je near 0357dh                            ; 0f 84 49 06
+    jmp near 035e5h                           ; e9 ae 06
     cmp bl, 001h                              ; 80 fb 01
-    jc short 02f3ch                           ; 72 15
-    jbe near 02fb5h                           ; 0f 86 8a 00
+    jc short 02f51h                           ; 72 15
+    jbe near 02fcah                           ; 0f 86 8a 00
     cmp bl, 005h                              ; 80 fb 05
-    je near 032f8h                            ; 0f 84 c6 03
+    je near 0330dh                            ; 0f 84 c6 03
     cmp bl, 004h                              ; 80 fb 04
-    jbe near 02fd3h                           ; 0f 86 9a 00
-    jmp near 035d0h                           ; e9 94 06
+    jbe near 02fe8h                           ; 0f 86 9a 00
+    jmp near 035e5h                           ; e9 94 06
     test bl, bl                               ; 84 db
-    jne near 035d0h                           ; 0f 85 8e 06
+    jne near 035e5h                           ; 0f 85 8e 06
     mov al, byte [bp+00eh]                    ; 8a 46 0e
     mov byte [bp-00eh], al                    ; 88 46 f2
     cmp AL, strict byte 001h                  ; 3c 01
-    jbe short 02f60h                          ; 76 14
+    jbe short 02f75h                          ; 76 14
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 00001h                ; b8 01 00
-    call 02b92h                               ; e8 35 fc
-    jmp near 032d4h                           ; e9 74 03
+    call 02ba7h                               ; e8 35 fc
+    jmp near 032e9h                           ; e9 74 03
     mov ax, strict word 00010h                ; b8 10 00
-    call 0165ch                               ; e8 f6 e6
+    call 0165ch                               ; e8 e1 e6
     cmp byte [bp-00eh], 000h                  ; 80 7e f2 00
-    jne short 02f73h                          ; 75 07
+    jne short 02f88h                          ; 75 07
     mov dl, al                                ; 88 c2
     shr dl, 004h                              ; c0 ea 04
-    jmp short 02f78h                          ; eb 05
+    jmp short 02f8dh                          ; eb 05
     mov dl, al                                ; 88 c2
     and dl, 00fh                              ; 80 e2 0f
     test dl, dl                               ; 84 d2
-    jne short 02f8ch                          ; 75 10
+    jne short 02fa1h                          ; 75 10
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 080h                               ; 80 cc 80
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, 00080h                            ; b8 80 00
-    jmp short 02f5ah                          ; eb ce
+    jmp short 02f6fh                          ; eb ce
     xor bx, bx                                ; 31 db
     mov dx, strict word 0003eh                ; ba 3e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 77 e6
+    call 0160eh                               ; e8 62 e6
     xor al, al                                ; 30 c0
     mov byte [bp+017h], al                    ; 88 46 17
     xor ah, ah                                ; 30 e4
-    call 02b92h                               ; e8 f1 fb
+    call 02ba7h                               ; e8 f1 fb
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     xor dx, dx                                ; 31 d2
-    call 02baah                               ; e8 fc fb
+    call 02bbfh                               ; e8 fc fb
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
@@ -3846,14 +3859,14 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     mov dx, 00441h                            ; ba 41 04
     xor ax, ax                                ; 31 c0
-    call 01600h                               ; e8 3f e6
+    call 01600h                               ; e8 2a e6
     movzx dx, al                              ; 0f b6 d0
     sal dx, 008h                              ; c1 e2 08
     or si, dx                                 ; 09 d6
     mov word [bp+016h], si                    ; 89 76 16
     test al, al                               ; 84 c0
-    je short 02faeh                           ; 74 de
-    jmp near 032d4h                           ; e9 01 03
+    je short 02fc3h                           ; 74 de
+    jmp near 032e9h                           ; e9 01 03
     mov al, byte [bp+016h]                    ; 8a 46 16
     mov byte [bp-00ch], al                    ; 88 46 f4
     mov dx, word [bp+014h]                    ; 8b 56 14
@@ -3866,50 +3879,50 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov byte [bp-006h], dl                    ; 88 56 fa
     mov byte [bp-00eh], ah                    ; 88 66 f2
     cmp ah, 001h                              ; 80 fc 01
-    jnbe short 03009h                         ; 77 10
+    jnbe short 0301eh                         ; 77 10
     cmp dl, 001h                              ; 80 fa 01
-    jnbe short 03009h                         ; 77 0b
+    jnbe short 0301eh                         ; 77 0b
     mov al, byte [bp-00ch]                    ; 8a 46 f4
     test al, al                               ; 84 c0
-    je short 03009h                           ; 74 04
+    je short 0301eh                           ; 74 04
     cmp AL, strict byte 048h                  ; 3c 48
-    jbe short 03032h                          ; 76 29
-    mov bx, 00da2h                            ; bb a2 0d
+    jbe short 03047h                          ; 76 29
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 b8 e8
+    call 018e1h                               ; e8 b8 e8
     push 00255h                               ; 68 55 02
     push 0026dh                               ; 68 6d 02
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 ee e8
+    call 01922h                               ; e8 ee e8
     add sp, strict byte 00006h                ; 83 c4 06
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 00001h                ; b8 01 00
-    jmp short 030a3h                          ; eb 71
+    jmp short 030b8h                          ; eb 71
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02ea5h                               ; e8 6c fe
+    call 02ebah                               ; e8 6c fe
     test ax, ax                               ; 85 c0
-    je near 03136h                            ; 0f 84 f7 00
+    je near 0314bh                            ; 0f 84 f7 00
     movzx dx, byte [bp-00eh]                  ; 0f b6 56 f2
     mov ax, dx                                ; 89 d0
-    call 02ceah                               ; e8 a2 fc
+    call 02cffh                               ; e8 a2 fc
     test ax, ax                               ; 85 c0
-    jne short 03065h                          ; 75 19
+    jne short 0307ah                          ; 75 19
     mov ax, dx                                ; 89 d0
-    call 02db5h                               ; e8 64 fd
+    call 02dcah                               ; e8 64 fd
     test ax, ax                               ; 85 c0
-    jne short 03065h                          ; 75 10
+    jne short 0307ah                          ; 75 10
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 00ch                               ; 80 cc 0c
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 0000ch                ; b8 0c 00
-    jmp short 030a3h                          ; eb 3e
+    jmp short 030b8h                          ; eb 3e
     cmp ch, 002h                              ; 80 fd 02
-    jne near 031cdh                           ; 0f 85 61 01
+    jne near 031e2h                           ; 0f 85 61 01
     mov dx, word [bp+006h]                    ; 8b 56 06
     shr dx, 00ch                              ; c1 ea 0c
     mov ah, dl                                ; 88 d4
@@ -3918,7 +3931,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov bx, word [bp+010h]                    ; 8b 5e 10
     add bx, cx                                ; 01 cb
     cmp bx, cx                                ; 39 cb
-    jnc short 03085h                          ; 73 02
+    jnc short 0309ah                          ; 73 02
     db  0feh, 0c4h
     ; inc ah                                    ; fe c4
     movzx cx, byte [bp-00ch]                  ; 0f b6 4e f4
@@ -3927,15 +3940,15 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov dx, bx                                ; 89 da
     add dx, cx                                ; 01 ca
     cmp dx, bx                                ; 39 da
-    jnc short 030adh                          ; 73 18
+    jnc short 030c2h                          ; 73 18
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 009h                               ; 80 cc 09
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 00009h                ; b8 09 00
-    call 02b92h                               ; e8 ec fa
+    call 02ba7h                               ; e8 ec fa
     mov byte [bp+016h], 000h                  ; c6 46 16 00
-    jmp near 032d4h                           ; e9 27 02
+    jmp near 032e9h                           ; e9 27 02
     mov AL, strict byte 006h                  ; b0 06
     mov dx, strict word 0000ah                ; ba 0a 00
     out DX, AL                                ; ee
@@ -3968,7 +3981,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     out DX, AL                                ; ee
     out DX, AL                                ; ee
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02c69h                               ; e8 78 fb
+    call 02c7eh                               ; e8 78 fb
     mov AL, strict byte 0e6h                  ; b0 e6
     mov dx, 003f5h                            ; ba f5 03
     out DX, AL                                ; ee
@@ -3996,32 +4009,32 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     out DX, AL                                ; ee
     mov AL, strict byte 0ffh                  ; b0 ff
     out DX, AL                                ; ee
-    call 02bf8h                               ; e8 c9 fa
+    call 02c0dh                               ; e8 c9 fa
     test al, al                               ; 84 c0
-    jne short 03147h                          ; 75 14
-    call 02c3eh                               ; e8 08 fb
+    jne short 0315ch                          ; 75 14
+    call 02c53h                               ; e8 08 fb
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 080h                               ; 80 cc 80
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, 00080h                            ; b8 80 00
-    jmp near 030a3h                           ; e9 5c ff
+    jmp near 030b8h                           ; e9 5c ff
     mov dx, 003f4h                            ; ba f4 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 0c0h                  ; 3c c0
-    je short 03161h                           ; 74 0e
+    je short 03176h                           ; 74 0e
     push 00255h                               ; 68 55 02
     push 00288h                               ; 68 88 02
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 af e7
+    call 01922h                               ; e8 af e7
     add sp, strict byte 00006h                ; 83 c4 06
     xor si, si                                ; 31 f6
-    jmp short 0316ah                          ; eb 05
+    jmp short 0317fh                          ; eb 05
     cmp si, strict byte 00007h                ; 83 fe 07
-    jnl short 03182h                          ; 7d 18
+    jnl short 03197h                          ; 7d 18
     mov dx, 003f5h                            ; ba f5 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -4030,17 +4043,17 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     movzx bx, al                              ; 0f b6 d8
     lea dx, [si+042h]                         ; 8d 54 42
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 8f e4
+    call 0160eh                               ; e8 7a e4
     inc si                                    ; 46
-    jmp short 03165h                          ; eb e3
+    jmp short 0317ah                          ; eb e3
     test byte [bp-016h], 0c0h                 ; f6 46 ea c0
-    je short 03199h                           ; 74 11
+    je short 031aeh                           ; 74 11
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 020h                               ; 80 cc 20
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 00020h                ; b8 20 00
-    jmp near 030a3h                           ; e9 0a ff
+    jmp near 030b8h                           ; e9 0a ff
     movzx ax, byte [bp-00ch]                  ; 0f b6 46 f4
     sal ax, 009h                              ; c1 e0 09
     cwd                                       ; 99
@@ -4058,12 +4071,12 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     pop DS                                    ; 1f
     movzx dx, byte [bp-008h]                  ; 0f b6 56 f8
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02baah                               ; e8 e8 f9
+    call 02bbfh                               ; e8 e8 f9
     mov byte [bp+017h], 000h                  ; c6 46 17 00
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
-    jmp near 02faeh                           ; e9 e1 fd
+    jmp near 02fc3h                           ; e9 e1 fd
     cmp ch, 003h                              ; 80 fd 03
-    jne near 032e2h                           ; 0f 85 0e 01
+    jne near 032f7h                           ; 0f 85 0e 01
     mov cx, word [bp+006h]                    ; 8b 4e 06
     shr cx, 00ch                              ; c1 e9 0c
     mov ah, cl                                ; 88 cc
@@ -4072,7 +4085,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov bx, word [bp+010h]                    ; 8b 5e 10
     add bx, dx                                ; 01 d3
     cmp bx, dx                                ; 39 d3
-    jnc short 031edh                          ; 73 02
+    jnc short 03202h                          ; 73 02
     db  0feh, 0c4h
     ; inc ah                                    ; fe c4
     movzx cx, byte [bp-00ch]                  ; 0f b6 4e f4
@@ -4081,7 +4094,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov dx, bx                                ; 89 da
     add dx, cx                                ; 01 ca
     cmp dx, bx                                ; 39 da
-    jc near 03095h                            ; 0f 82 96 fe
+    jc near 030aah                            ; 0f 82 96 fe
     mov AL, strict byte 006h                  ; b0 06
     mov dx, strict word 0000ah                ; ba 0a 00
     out DX, AL                                ; ee
@@ -4113,7 +4126,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov dx, strict word 0000ah                ; ba 0a 00
     out DX, AL                                ; ee
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02c69h                               ; e8 27 fa
+    call 02c7eh                               ; e8 27 fa
     mov AL, strict byte 0c5h                  ; b0 c5
     mov dx, 003f5h                            ; ba f5 03
     out DX, AL                                ; ee
@@ -4141,25 +4154,25 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     out DX, AL                                ; ee
     mov AL, strict byte 0ffh                  ; b0 ff
     out DX, AL                                ; ee
-    call 02bf8h                               ; e8 78 f9
+    call 02c0dh                               ; e8 78 f9
     test al, al                               ; 84 c0
-    je near 03133h                            ; 0f 84 ad fe
+    je near 03148h                            ; 0f 84 ad fe
     mov dx, 003f4h                            ; ba f4 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 0c0h                  ; 3c c0
-    je short 032a0h                           ; 74 0e
+    je short 032b5h                           ; 74 0e
     push 00255h                               ; 68 55 02
     push 00288h                               ; 68 88 02
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 70 e6
+    call 01922h                               ; e8 70 e6
     add sp, strict byte 00006h                ; 83 c4 06
     xor si, si                                ; 31 f6
-    jmp short 032a9h                          ; eb 05
+    jmp short 032beh                          ; eb 05
     cmp si, strict byte 00007h                ; 83 fe 07
-    jnl short 032c1h                          ; 7d 18
+    jnl short 032d6h                          ; 7d 18
     mov dx, 003f5h                            ; ba f5 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -4168,24 +4181,24 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     movzx bx, al                              ; 0f b6 d8
     lea dx, [si+042h]                         ; 8d 54 42
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 50 e3
+    call 0160eh                               ; e8 3b e3
     inc si                                    ; 46
-    jmp short 032a4h                          ; eb e3
+    jmp short 032b9h                          ; eb e3
     test byte [bp-016h], 0c0h                 ; f6 46 ea c0
-    je near 031b7h                            ; 0f 84 ee fe
+    je near 031cch                            ; 0f 84 ee fe
     test byte [bp-015h], 002h                 ; f6 46 eb 02
-    je short 032dbh                           ; 74 0c
+    je short 032f0h                           ; 74 0c
     mov word [bp+016h], 00300h                ; c7 46 16 00 03
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
-    jmp near 02faeh                           ; e9 d3 fc
+    jmp near 02fc3h                           ; e9 d3 fc
     mov word [bp+016h], 00100h                ; c7 46 16 00 01
-    jmp short 032d4h                          ; eb f2
+    jmp short 032e9h                          ; eb f2
     movzx dx, byte [bp-008h]                  ; 0f b6 56 f8
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02baah                               ; e8 bd f8
+    call 02bbfh                               ; e8 bd f8
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     mov byte [bp+017h], 000h                  ; c6 46 17 00
-    jmp near 02faeh                           ; e9 b6 fc
+    jmp near 02fc3h                           ; e9 b6 fc
     mov al, byte [bp+016h]                    ; 8a 46 16
     mov byte [bp-00ch], al                    ; 88 46 f4
     mov dx, word [bp+014h]                    ; 8b 56 14
@@ -4196,36 +4209,36 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov bl, byte [bp+00eh]                    ; 8a 5e 0e
     mov byte [bp-00eh], bl                    ; 88 5e f2
     cmp bl, 001h                              ; 80 fb 01
-    jnbe short 0332ch                         ; 77 14
+    jnbe short 03341h                         ; 77 14
     cmp AL, strict byte 001h                  ; 3c 01
-    jnbe short 0332ch                         ; 77 10
+    jnbe short 03341h                         ; 77 10
     cmp dl, 04fh                              ; 80 fa 4f
-    jnbe short 0332ch                         ; 77 0b
+    jnbe short 03341h                         ; 77 0b
     mov al, byte [bp-00ch]                    ; 8a 46 f4
     test al, al                               ; 84 c0
-    je short 0332ch                           ; 74 04
+    je short 03341h                           ; 74 04
     cmp AL, strict byte 012h                  ; 3c 12
-    jbe short 03341h                          ; 76 15
+    jbe short 03356h                          ; 76 15
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 00001h                ; b8 01 00
-    call 02b92h                               ; e8 55 f8
+    call 02ba7h                               ; e8 55 f8
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02ea5h                               ; e8 5d fb
+    call 02ebah                               ; e8 5d fb
     test ax, ax                               ; 85 c0
-    je near 02f7ch                            ; 0f 84 2e fc
+    je near 02f91h                            ; 0f 84 2e fc
     movzx dx, byte [bp-00eh]                  ; 0f b6 56 f2
     mov ax, dx                                ; 89 d0
-    call 02ceah                               ; e8 93 f9
+    call 02cffh                               ; e8 93 f9
     test ax, ax                               ; 85 c0
-    jne short 03366h                          ; 75 0b
+    jne short 0337bh                          ; 75 0b
     mov ax, dx                                ; 89 d0
-    call 02db5h                               ; e8 55 fa
+    call 02dcah                               ; e8 55 fa
     test ax, ax                               ; 85 c0
-    je near 03055h                            ; 0f 84 ef fc
+    je near 0306ah                            ; 0f 84 ef fc
     mov dx, word [bp+006h]                    ; 8b 56 06
     shr dx, 00ch                              ; c1 ea 0c
     mov ah, dl                                ; 88 d4
@@ -4234,7 +4247,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov bx, word [bp+010h]                    ; 8b 5e 10
     add bx, cx                                ; 01 cb
     cmp bx, cx                                ; 39 cb
-    jnc short 0337fh                          ; 73 02
+    jnc short 03394h                          ; 73 02
     db  0feh, 0c4h
     ; inc ah                                    ; fe c4
     movzx cx, byte [bp-00ch]                  ; 0f b6 4e f4
@@ -4243,7 +4256,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov dx, bx                                ; 89 da
     add dx, cx                                ; 01 ca
     cmp dx, bx                                ; 39 da
-    jc near 03095h                            ; 0f 82 04 fd
+    jc near 030aah                            ; 0f 82 04 fd
     mov AL, strict byte 006h                  ; b0 06
     mov dx, strict word 0000ah                ; ba 0a 00
     out DX, AL                                ; ee
@@ -4275,7 +4288,7 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     mov dx, strict word 0000ah                ; ba 0a 00
     out DX, AL                                ; ee
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
-    call 02c69h                               ; e8 95 f8
+    call 02c7eh                               ; e8 95 f8
     mov AL, strict byte 04dh                  ; b0 4d
     mov dx, 003f5h                            ; ba f5 03
     out DX, AL                                ; ee
@@ -4293,27 +4306,27 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     out DX, AL                                ; ee
     mov AL, strict byte 0f6h                  ; b0 f6
     out DX, AL                                ; ee
-    call 02bf8h                               ; e8 fd f7
+    call 02c0dh                               ; e8 fd f7
     test al, al                               ; 84 c0
-    jne short 03405h                          ; 75 06
-    call 02c3eh                               ; e8 3c f8
-    jmp near 02f7ch                           ; e9 77 fb
+    jne short 0341ah                          ; 75 06
+    call 02c53h                               ; e8 3c f8
+    jmp near 02f91h                           ; e9 77 fb
     mov dx, 003f4h                            ; ba f4 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 0c0h                  ; 3c c0
-    je short 0341fh                           ; 74 0e
+    je short 03434h                           ; 74 0e
     push 00255h                               ; 68 55 02
     push 00288h                               ; 68 88 02
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 f1 e4
+    call 01922h                               ; e8 f1 e4
     add sp, strict byte 00006h                ; 83 c4 06
     xor si, si                                ; 31 f6
-    jmp short 03428h                          ; eb 05
+    jmp short 0343dh                          ; eb 05
     cmp si, strict byte 00007h                ; 83 fe 07
-    jnl short 03440h                          ; 7d 18
+    jnl short 03455h                          ; 7d 18
     mov dx, 003f5h                            ; ba f5 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -4322,29 +4335,29 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     movzx bx, al                              ; 0f b6 d8
     lea dx, [si+042h]                         ; 8d 54 42
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 d1 e1
+    call 0160eh                               ; e8 bc e1
     inc si                                    ; 46
-    jmp short 03423h                          ; eb e3
+    jmp short 03438h                          ; eb e3
     test byte [bp-016h], 0c0h                 ; f6 46 ea c0
-    je short 0345ch                           ; 74 16
+    je short 03471h                           ; 74 16
     test byte [bp-015h], 002h                 ; f6 46 eb 02
-    jne near 032cfh                           ; 0f 85 81 fe
+    jne near 032e4h                           ; 0f 85 81 fe
     push 00255h                               ; 68 55 02
     push 0029ch                               ; 68 9c 02
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 b4 e4
+    call 01922h                               ; e8 b4 e4
     add sp, strict byte 00006h                ; 83 c4 06
     xor al, al                                ; 30 c0
     mov byte [bp+017h], al                    ; 88 46 17
     xor ah, ah                                ; 30 e4
-    call 02b92h                               ; e8 2c f7
+    call 02ba7h                               ; e8 2c f7
     movzx ax, byte [bp-00eh]                  ; 0f b6 46 f2
     xor dx, dx                                ; 31 d2
-    call 02baah                               ; e8 3b f7
-    jmp near 031c6h                           ; e9 54 fd
+    call 02bbfh                               ; e8 3b f7
+    jmp near 031dbh                           ; e9 54 fd
     mov byte [bp-00eh], ah                    ; 88 66 f2
     cmp ah, 001h                              ; 80 fc 01
-    jbe short 0349ah                          ; 76 20
+    jbe short 034afh                          ; 76 20
     xor ax, ax                                ; 31 c0
     mov word [bp+016h], ax                    ; 89 46 16
     mov word [bp+010h], ax                    ; 89 46 10
@@ -4355,22 +4368,22 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     movzx ax, cl                              ; 0f b6 c1
     mov word [bp+012h], ax                    ; 89 46 12
     mov word [bp+01ch], dx                    ; 89 56 1c
-    jmp near 02faeh                           ; e9 14 fb
+    jmp near 02fc3h                           ; e9 14 fb
     mov ax, strict word 00010h                ; b8 10 00
-    call 0165ch                               ; e8 bc e1
+    call 0165ch                               ; e8 a7 e1
     mov dl, al                                ; 88 c2
     xor cl, cl                                ; 30 c9
     test AL, strict byte 0f0h                 ; a8 f0
-    je short 034aah                           ; 74 02
+    je short 034bfh                           ; 74 02
     mov CL, strict byte 001h                  ; b1 01
     test dl, 00fh                             ; f6 c2 0f
-    je short 034b1h                           ; 74 02
+    je short 034c6h                           ; 74 02
     db  0feh, 0c1h
     ; inc cl                                    ; fe c1
     cmp byte [bp-00eh], 000h                  ; 80 7e f2 00
-    jne short 034bch                          ; 75 05
+    jne short 034d1h                          ; 75 05
     shr dl, 004h                              ; c0 ea 04
-    jmp short 034bfh                          ; eb 03
+    jmp short 034d4h                          ; eb 03
     and dl, 00fh                              ; 80 e2 0f
     mov byte [bp+011h], 000h                  ; c6 46 11 00
     movzx ax, dl                              ; 0f b6 c2
@@ -4386,292 +4399,292 @@ _int13_diskette_function:                    ; 0xf2ec9 LB 0x72a
     or ah, 001h                               ; 80 cc 01
     mov word [bp+012h], ax                    ; 89 46 12
     cmp dl, 003h                              ; 80 fa 03
-    jc short 034ffh                           ; 72 15
-    jbe short 03526h                          ; 76 3a
+    jc short 03514h                           ; 72 15
+    jbe short 0353bh                          ; 76 3a
     cmp dl, 005h                              ; 80 fa 05
-    jc short 0352dh                           ; 72 3c
-    jbe short 03534h                          ; 76 41
+    jc short 03542h                           ; 72 3c
+    jbe short 03549h                          ; 76 41
     cmp dl, 00fh                              ; 80 fa 0f
-    je short 03542h                           ; 74 4a
+    je short 03557h                           ; 74 4a
     cmp dl, 00eh                              ; 80 fa 0e
-    je short 0353bh                           ; 74 3e
-    jmp short 03549h                          ; eb 4a
+    je short 03550h                           ; 74 3e
+    jmp short 0355eh                          ; eb 4a
     cmp dl, 002h                              ; 80 fa 02
-    je short 0351fh                           ; 74 1b
+    je short 03534h                           ; 74 1b
     cmp dl, 001h                              ; 80 fa 01
-    je short 03518h                           ; 74 0f
+    je short 0352dh                           ; 74 0f
     test dl, dl                               ; 84 d2
-    jne short 03549h                          ; 75 3c
+    jne short 0355eh                          ; 75 3c
     mov word [bp+014h], strict word 00000h    ; c7 46 14 00 00
     mov byte [bp+013h], 000h                  ; c6 46 13 00
-    jmp short 03557h                          ; eb 3f
+    jmp short 0356ch                          ; eb 3f
     mov word [bp+014h], 02709h                ; c7 46 14 09 27
-    jmp short 03557h                          ; eb 38
+    jmp short 0356ch                          ; eb 38
     mov word [bp+014h], 04f0fh                ; c7 46 14 0f 4f
-    jmp short 03557h                          ; eb 31
+    jmp short 0356ch                          ; eb 31
     mov word [bp+014h], 04f09h                ; c7 46 14 09 4f
-    jmp short 03557h                          ; eb 2a
+    jmp short 0356ch                          ; eb 2a
     mov word [bp+014h], 04f12h                ; c7 46 14 12 4f
-    jmp short 03557h                          ; eb 23
+    jmp short 0356ch                          ; eb 23
     mov word [bp+014h], 04f24h                ; c7 46 14 24 4f
-    jmp short 03557h                          ; eb 1c
+    jmp short 0356ch                          ; eb 1c
     mov word [bp+014h], 0fe3fh                ; c7 46 14 3f fe
-    jmp short 03557h                          ; eb 15
+    jmp short 0356ch                          ; eb 15
     mov word [bp+014h], 0feffh                ; c7 46 14 ff fe
-    jmp short 03557h                          ; eb 0e
+    jmp short 0356ch                          ; eb 0e
     push 00255h                               ; 68 55 02
     push 002adh                               ; 68 ad 02
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 b9 e3
+    call 01922h                               ; e8 b9 e3
     add sp, strict byte 00006h                ; 83 c4 06
     mov word [bp+006h], 0f000h                ; c7 46 06 00 f0
     movzx ax, dl                              ; 0f b6 c2
-    call 035f3h                               ; e8 91 00
+    call 03608h                               ; e8 91 00
     mov word [bp+008h], ax                    ; 89 46 08
-    jmp near 031c6h                           ; e9 5e fc
+    jmp near 031dbh                           ; e9 5e fc
     mov byte [bp-00eh], ah                    ; 88 66 f2
     cmp ah, 001h                              ; 80 fc 01
-    jbe short 03576h                          ; 76 06
+    jbe short 0358bh                          ; 76 06
     mov word [bp+016h], si                    ; 89 76 16
-    jmp near 03494h                           ; e9 1e ff
+    jmp near 034a9h                           ; e9 1e ff
     mov ax, strict word 00010h                ; b8 10 00
-    call 0165ch                               ; e8 e0 e0
+    call 0165ch                               ; e8 cb e0
     cmp byte [bp-00eh], 000h                  ; 80 7e f2 00
-    jne short 03589h                          ; 75 07
+    jne short 0359eh                          ; 75 07
     mov dl, al                                ; 88 c2
     shr dl, 004h                              ; c0 ea 04
-    jmp short 0358eh                          ; eb 05
+    jmp short 035a3h                          ; eb 05
     mov dl, al                                ; 88 c2
     and dl, 00fh                              ; 80 e2 0f
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     mov bx, word [bp+016h]                    ; 8b 5e 16
     xor bh, bh                                ; 30 ff
     test dl, dl                               ; 84 d2
-    je short 035a8h                           ; 74 0d
+    je short 035bdh                           ; 74 0d
     cmp dl, 001h                              ; 80 fa 01
-    jbe short 035a5h                          ; 76 05
+    jbe short 035bah                          ; 76 05
     or bh, 002h                               ; 80 cf 02
-    jmp short 035a8h                          ; eb 03
+    jmp short 035bdh                          ; eb 03
     or bh, 001h                               ; 80 cf 01
     mov word [bp+016h], bx                    ; 89 5e 16
-    jmp near 02faeh                           ; e9 00 fa
+    jmp near 02fc3h                           ; e9 00 fa
     cmp ah, 001h                              ; 80 fc 01
-    jbe short 035bfh                          ; 76 0c
+    jbe short 035d4h                          ; 76 0c
     mov word [bp+016h], si                    ; 89 76 16
     mov ax, strict word 00001h                ; b8 01 00
-    call 02b92h                               ; e8 d6 f5
-    jmp near 03494h                           ; e9 d5 fe
+    call 02ba7h                               ; e8 d6 f5
+    jmp near 034a9h                           ; e9 d5 fe
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 006h                               ; 80 cc 06
     mov word [bp+016h], ax                    ; 89 46 16
     mov ax, strict word 00006h                ; b8 06 00
-    jmp near 02f5ah                           ; e9 8a f9
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 02f6fh                           ; e9 8a f9
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 f1 e2
+    call 018e1h                               ; e8 f1 e2
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 00255h                               ; 68 55 02
     push 002c2h                               ; 68 c2 02
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 20 e3
+    call 01922h                               ; e8 20 e3
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp near 02f4ch                           ; e9 59 f9
-get_floppy_dpt_:                             ; 0xf35f3 LB 0x2f
+    jmp near 02f61h                           ; e9 59 f9
+get_floppy_dpt_:                             ; 0xf3608 LB 0x2f
     push bx                                   ; 53
     push dx                                   ; 52
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov dl, al                                ; 88 c2
     xor ax, ax                                ; 31 c0
-    jmp short 03604h                          ; eb 06
+    jmp short 03619h                          ; eb 06
     inc ax                                    ; 40
     cmp ax, strict word 00007h                ; 3d 07 00
-    jnc short 0361bh                          ; 73 17
+    jnc short 03630h                          ; 73 17
     mov bx, ax                                ; 89 c3
     add bx, ax                                ; 01 c3
     cmp dl, byte [word bx+0005bh]             ; 3a 97 5b 00
-    jne short 035feh                          ; 75 f0
+    jne short 03613h                          ; 75 f0
     movzx ax, byte [word bx+0005ch]           ; 0f b6 87 5c 00
     imul ax, ax, strict byte 0000dh           ; 6b c0 0d
     add ax, strict word 00000h                ; 05 00 00
-    jmp short 0361eh                          ; eb 03
+    jmp short 03633h                          ; eb 03
     mov ax, strict word 00041h                ; b8 41 00
     pop bp                                    ; 5d
     pop dx                                    ; 5a
     pop bx                                    ; 5b
     retn                                      ; c3
-dummy_soft_reset_:                           ; 0xf3622 LB 0x7
+dummy_soft_reset_:                           ; 0xf3637 LB 0x7
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     xor ax, ax                                ; 31 c0
     pop bp                                    ; 5d
     retn                                      ; c3
-_cdemu_init:                                 ; 0xf3629 LB 0x18
+_cdemu_init:                                 ; 0xf363e LB 0x18
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 e7 df
+    call 0161ch                               ; e8 d2 df
     xor bx, bx                                ; 31 db
     mov dx, 00322h                            ; ba 22 03
-    call 0160eh                               ; e8 d1 df
+    call 0160eh                               ; e8 bc df
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_cdemu_isactive:                             ; 0xf3641 LB 0x16
+_cdemu_isactive:                             ; 0xf3656 LB 0x16
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 cf df
+    call 0161ch                               ; e8 ba df
     mov dx, 00322h                            ; ba 22 03
-    call 01600h                               ; e8 ad df
+    call 01600h                               ; e8 98 df
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_cdemu_emulated_drive:                       ; 0xf3657 LB 0x16
+_cdemu_emulated_drive:                       ; 0xf366c LB 0x16
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 b9 df
+    call 0161ch                               ; e8 a4 df
     mov dx, 00324h                            ; ba 24 03
-    call 01600h                               ; e8 97 df
+    call 01600h                               ; e8 82 df
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_int13_eltorito:                             ; 0xf366d LB 0x189
+_int13_eltorito:                             ; 0xf3682 LB 0x189
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
     push di                                   ; 57
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 a1 df
+    call 0161ch                               ; e8 8c df
     mov si, 00322h                            ; be 22 03
     mov di, ax                                ; 89 c7
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     cmp ax, strict word 0004bh                ; 3d 4b 00
-    jc short 03695h                           ; 72 0a
-    jbe short 036bbh                          ; 76 2e
+    jc short 036aah                           ; 72 0a
+    jbe short 036d0h                          ; 76 2e
     cmp ax, strict word 0004dh                ; 3d 4d 00
-    jbe short 0369ch                          ; 76 0a
-    jmp near 037bah                           ; e9 25 01
+    jbe short 036b1h                          ; 76 0a
+    jmp near 037cfh                           ; e9 25 01
     cmp ax, strict word 0004ah                ; 3d 4a 00
-    jne near 037bah                           ; 0f 85 1e 01
-    mov bx, 00da2h                            ; bb a2 0d
+    jne near 037cfh                           ; 0f 85 1e 01
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 25 e2
+    call 018e1h                               ; e8 25 e2
     push word [bp+016h]                       ; ff 76 16
     push 002dch                               ; 68 dc 02
     push 002ebh                               ; 68 eb 02
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 58 e2
+    call 01922h                               ; e8 58 e2
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp near 037d5h                           ; e9 1a 01
+    jmp near 037eah                           ; e9 1a 01
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     mov ax, word [bp+004h]                    ; 8b 46 04
     mov bx, strict word 00013h                ; bb 13 00
-    call 0160eh                               ; e8 47 df
+    call 0160eh                               ; e8 32 df
     mov es, di                                ; 8e c7
     movzx bx, byte [es:si+001h]               ; 26 0f b6 5c 01
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     inc dx                                    ; 42
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0160eh                               ; e8 36 df
+    call 0160eh                               ; e8 21 df
     mov es, di                                ; 8e c7
     movzx bx, byte [es:si+002h]               ; 26 0f b6 5c 02
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     inc dx                                    ; 42
     inc dx                                    ; 42
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0160eh                               ; e8 24 df
+    call 0160eh                               ; e8 0f df
     mov es, di                                ; 8e c7
     movzx bx, byte [es:si+003h]               ; 26 0f b6 5c 03
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 00003h                ; 83 c2 03
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0160eh                               ; e8 11 df
+    call 0160eh                               ; e8 fc de
     mov es, di                                ; 8e c7
     mov bx, word [es:si+008h]                 ; 26 8b 5c 08
     mov cx, word [es:si+00ah]                 ; 26 8b 4c 0a
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 00004h                ; 83 c2 04
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0164ah                               ; e8 37 df
+    call 0164ah                               ; e8 22 df
     mov es, di                                ; 8e c7
     mov bx, word [es:si+004h]                 ; 26 8b 5c 04
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 00008h                ; 83 c2 08
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0162ah                               ; e8 05 df
+    call 0162ah                               ; e8 f0 de
     mov es, di                                ; 8e c7
     mov bx, word [es:si+006h]                 ; 26 8b 5c 06
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 0000ah                ; 83 c2 0a
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0162ah                               ; e8 f3 de
+    call 0162ah                               ; e8 de de
     mov es, di                                ; 8e c7
     mov bx, word [es:si+00ch]                 ; 26 8b 5c 0c
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 0000ch                ; 83 c2 0c
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0162ah                               ; e8 e1 de
+    call 0162ah                               ; e8 cc de
     mov es, di                                ; 8e c7
     mov bx, word [es:si+00eh]                 ; 26 8b 5c 0e
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 0000eh                ; 83 c2 0e
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0162ah                               ; e8 cf de
+    call 0162ah                               ; e8 ba de
     mov es, di                                ; 8e c7
     movzx bx, byte [es:si+012h]               ; 26 0f b6 5c 12
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 00010h                ; 83 c2 10
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0160eh                               ; e8 a0 de
+    call 0160eh                               ; e8 8b de
     mov es, di                                ; 8e c7
     movzx bx, byte [es:si+014h]               ; 26 0f b6 5c 14
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 00011h                ; 83 c2 11
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0160eh                               ; e8 8d de
+    call 0160eh                               ; e8 78 de
     mov es, di                                ; 8e c7
     movzx bx, byte [es:si+010h]               ; 26 0f b6 5c 10
     mov dx, word [bp+00ah]                    ; 8b 56 0a
     add dx, strict byte 00012h                ; 83 c2 12
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 0160eh                               ; e8 7a de
+    call 0160eh                               ; e8 65 de
     test byte [bp+016h], 0ffh                 ; f6 46 16 ff
-    jne short 037a0h                          ; 75 06
+    jne short 037b5h                          ; 75 06
     mov es, di                                ; 8e c7
     mov byte [es:si], 000h                    ; 26 c6 04 00
     mov byte [bp+017h], 000h                  ; c6 46 17 00
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 5f de
+    call 0160eh                               ; e8 4a de
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-    mov bx, 00da2h                            ; bb a2 0d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 07 e1
+    call 018e1h                               ; e8 07 e1
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 002dch                               ; 68 dc 02
     push 00313h                               ; 68 13 03
-    jmp near 036b0h                           ; e9 db fe
+    jmp near 036c5h                           ; e9 db fe
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
@@ -4681,10 +4694,10 @@ _int13_eltorito:                             ; 0xf366d LB 0x189
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 1e de
+    call 0160eh                               ; e8 09 de
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
-    jmp short 037b3h                          ; eb bd
-device_is_cdrom_:                            ; 0xf37f6 LB 0x35
+    jmp short 037c8h                          ; eb bd
+device_is_cdrom_:                            ; 0xf380b LB 0x35
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -4692,24 +4705,24 @@ device_is_cdrom_:                            ; 0xf37f6 LB 0x35
     mov bl, al                                ; 88 c3
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 16 de
+    call 0161ch                               ; e8 01 de
     cmp bl, 010h                              ; 80 fb 10
-    jc short 0380fh                           ; 72 04
+    jc short 03824h                           ; 72 04
     xor ax, ax                                ; 31 c0
-    jmp short 03824h                          ; eb 15
+    jmp short 03839h                          ; eb 15
     xor bh, bh                                ; 30 ff
     imul bx, bx, strict byte 00018h           ; 6b db 18
     mov es, ax                                ; 8e c0
     add bx, 00122h                            ; 81 c3 22 01
     cmp byte [es:bx+01fh], 005h               ; 26 80 7f 1f 05
-    jne short 0380bh                          ; 75 ea
+    jne short 03820h                          ; 75 ea
     mov ax, strict word 00001h                ; b8 01 00
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop dx                                    ; 5a
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-cdrom_boot_:                                 ; 0xf382b LB 0x416
+cdrom_boot_:                                 ; 0xf3840 LB 0x416
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -4720,30 +4733,30 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     sub sp, 0081ch                            ; 81 ec 1c 08
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 dc dd
+    call 0161ch                               ; e8 c7 dd
     mov word [bp-018h], ax                    ; 89 46 e8
     mov si, 00322h                            ; be 22 03
     mov word [bp-010h], ax                    ; 89 46 f0
     mov word [bp-014h], 00122h                ; c7 46 ec 22 01
     mov word [bp-012h], ax                    ; 89 46 ee
     mov byte [bp-00ch], 000h                  ; c6 46 f4 00
-    jmp short 03860h                          ; eb 09
+    jmp short 03875h                          ; eb 09
     inc byte [bp-00ch]                        ; fe 46 f4
     cmp byte [bp-00ch], 010h                  ; 80 7e f4 10
-    jnc short 0386bh                          ; 73 0b
+    jnc short 03880h                          ; 73 0b
     movzx ax, byte [bp-00ch]                  ; 0f b6 46 f4
-    call 037f6h                               ; e8 8f ff
+    call 0380bh                               ; e8 8f ff
     test ax, ax                               ; 85 c0
-    je short 03857h                           ; 74 ec
+    je short 0386ch                           ; 74 ec
     cmp byte [bp-00ch], 010h                  ; 80 7e f4 10
-    jc short 03877h                           ; 72 06
+    jc short 0388ch                           ; 72 06
     mov ax, strict word 00002h                ; b8 02 00
-    jmp near 03bdeh                           ; e9 67 03
+    jmp near 03bf3h                           ; e9 67 03
     mov cx, strict word 0000ch                ; b9 0c 00
     xor bx, bx                                ; 31 db
     mov dx, ss                                ; 8c d2
     lea ax, [bp-026h]                         ; 8d 46 da
-    call 093dah                               ; e8 56 5b
+    call 0948ah                               ; e8 f1 5b
     mov word [bp-026h], strict word 00028h    ; c7 46 da 28 00
     mov ax, strict word 00011h                ; b8 11 00
     xor dx, dx                                ; 31 d2
@@ -4759,10 +4772,10 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     db  066h, 026h, 0c7h, 047h, 00ah, 001h, 000h, 000h, 008h
     ; mov dword [es:bx+00ah], strict dword 008000001h ; 66 26 c7 47 0a 01 00 00 08
     mov byte [bp-00eh], 000h                  ; c6 46 f2 00
-    jmp short 038bch                          ; eb 09
+    jmp short 038d1h                          ; eb 09
     inc byte [bp-00eh]                        ; fe 46 f2
     cmp byte [bp-00eh], 004h                  ; 80 7e f2 04
-    jnbe short 038f3h                         ; 77 37
+    jnbe short 03908h                         ; 77 37
     movzx di, byte [bp-00ch]                  ; 0f b6 7e f4
     imul di, di, strict byte 00018h           ; 6b ff 18
     mov es, [bp-012h]                         ; 8e 46 ee
@@ -4782,35 +4795,35 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     mov dx, strict word 0000ch                ; ba 0c 00
     call word [word di+0006ah]                ; ff 95 6a 00
     test ax, ax                               ; 85 c0
-    jne short 038b3h                          ; 75 c0
+    jne short 038c8h                          ; 75 c0
     test ax, ax                               ; 85 c0
-    je short 038fdh                           ; 74 06
+    je short 03912h                           ; 74 06
     mov ax, strict word 00003h                ; b8 03 00
-    jmp near 03bdeh                           ; e9 e1 02
+    jmp near 03bf3h                           ; e9 e1 02
     cmp byte [bp-00826h], 000h                ; 80 be da f7 00
-    je short 0390ah                           ; 74 06
+    je short 0391fh                           ; 74 06
     mov ax, strict word 00004h                ; b8 04 00
-    jmp near 03bdeh                           ; e9 d4 02
+    jmp near 03bf3h                           ; e9 d4 02
     xor di, di                                ; 31 ff
-    jmp short 03914h                          ; eb 06
+    jmp short 03929h                          ; eb 06
     inc di                                    ; 47
     cmp di, strict byte 00005h                ; 83 ff 05
-    jnc short 03924h                          ; 73 10
+    jnc short 03939h                          ; 73 10
     mov al, byte [bp+di-00825h]               ; 8a 83 db f7
-    cmp al, byte [di+00daah]                  ; 3a 85 aa 0d
-    je short 0390eh                           ; 74 f0
+    cmp al, byte [di+00dc2h]                  ; 3a 85 c2 0d
+    je short 03923h                           ; 74 f0
     mov ax, strict word 00005h                ; b8 05 00
-    jmp near 03bdeh                           ; e9 ba 02
+    jmp near 03bf3h                           ; e9 ba 02
     xor di, di                                ; 31 ff
-    jmp short 0392eh                          ; eb 06
+    jmp short 03943h                          ; eb 06
     inc di                                    ; 47
     cmp di, strict byte 00017h                ; 83 ff 17
-    jnc short 0393eh                          ; 73 10
+    jnc short 03953h                          ; 73 10
     mov al, byte [bp+di-0081fh]               ; 8a 83 e1 f7
-    cmp al, byte [di+00db0h]                  ; 3a 85 b0 0d
-    je short 03928h                           ; 74 f0
+    cmp al, byte [di+00dc8h]                  ; 3a 85 c8 0d
+    je short 0393dh                           ; 74 f0
     mov ax, strict word 00006h                ; b8 06 00
-    jmp near 03bdeh                           ; e9 a0 02
+    jmp near 03bf3h                           ; e9 a0 02
     mov ax, word [bp-007dfh]                  ; 8b 86 21 f8
     mov dx, word [bp-007ddh]                  ; 8b 96 23 f8
     mov word [bp-026h], strict word 00028h    ; c7 46 da 28 00
@@ -4841,38 +4854,38 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     mov dx, strict word 0000ch                ; ba 0c 00
     call word [word di+0006ah]                ; ff 95 6a 00
     test ax, ax                               ; 85 c0
-    je short 0399bh                           ; 74 06
+    je short 039b0h                           ; 74 06
     mov ax, strict word 00007h                ; b8 07 00
-    jmp near 03bdeh                           ; e9 43 02
+    jmp near 03bf3h                           ; e9 43 02
     cmp byte [bp-00826h], 001h                ; 80 be da f7 01
-    je short 039a8h                           ; 74 06
+    je short 039bdh                           ; 74 06
     mov ax, strict word 00008h                ; b8 08 00
-    jmp near 03bdeh                           ; e9 36 02
+    jmp near 03bf3h                           ; e9 36 02
     cmp byte [bp-00825h], 000h                ; 80 be db f7 00
-    je short 039b5h                           ; 74 06
+    je short 039cah                           ; 74 06
     mov ax, strict word 00009h                ; b8 09 00
-    jmp near 03bdeh                           ; e9 29 02
+    jmp near 03bf3h                           ; e9 29 02
     cmp byte [bp-00808h], 055h                ; 80 be f8 f7 55
-    je short 039c2h                           ; 74 06
+    je short 039d7h                           ; 74 06
     mov ax, strict word 0000ah                ; b8 0a 00
-    jmp near 03bdeh                           ; e9 1c 02
+    jmp near 03bf3h                           ; e9 1c 02
     cmp byte [bp-00807h], 0aah                ; 80 be f9 f7 aa
-    jne short 039bch                          ; 75 f3
+    jne short 039d1h                          ; 75 f3
     cmp byte [bp-00806h], 088h                ; 80 be fa f7 88
-    je short 039d6h                           ; 74 06
+    je short 039ebh                           ; 74 06
     mov ax, strict word 0000bh                ; b8 0b 00
-    jmp near 03bdeh                           ; e9 08 02
+    jmp near 03bf3h                           ; e9 08 02
     mov al, byte [bp-00805h]                  ; 8a 86 fb f7
     mov es, [bp-010h]                         ; 8e 46 f0
     mov byte [es:si+001h], al                 ; 26 88 44 01
     cmp byte [bp-00805h], 000h                ; 80 be fb f7 00
-    jne short 039efh                          ; 75 07
+    jne short 03a04h                          ; 75 07
     mov byte [es:si+002h], 0e0h               ; 26 c6 44 02 e0
-    jmp short 03a02h                          ; eb 13
+    jmp short 03a17h                          ; eb 13
     cmp byte [bp-00805h], 004h                ; 80 be fb f7 04
-    jnc short 039fdh                          ; 73 07
+    jnc short 03a12h                          ; 73 07
     mov byte [es:si+002h], 000h               ; 26 c6 44 02 00
-    jmp short 03a02h                          ; eb 05
+    jmp short 03a17h                          ; eb 05
     mov byte [es:si+002h], 080h               ; 26 c6 44 02 80
     movzx di, byte [bp-00ch]                  ; 0f b6 7e f4
     mov ax, di                                ; 89 f8
@@ -4890,7 +4903,7 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     mov ax, word [bp-00804h]                  ; 8b 86 fc f7
     mov word [bp-016h], ax                    ; 89 46 ea
     test ax, ax                               ; 85 c0
-    jne short 03a30h                          ; 75 05
+    jne short 03a45h                          ; 75 05
     mov word [bp-016h], 007c0h                ; c7 46 ea c0 07
     mov ax, word [bp-016h]                    ; 8b 46 ea
     mov es, [bp-010h]                         ; 8e 46 f0
@@ -4899,11 +4912,11 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     mov di, word [bp-00800h]                  ; 8b be 00 f8
     mov word [es:si+00eh], di                 ; 26 89 7c 0e
     test di, di                               ; 85 ff
-    je short 03a52h                           ; 74 06
+    je short 03a67h                           ; 74 06
     cmp di, 00400h                            ; 81 ff 00 04
-    jbe short 03a58h                          ; 76 06
+    jbe short 03a6dh                          ; 76 06
     mov ax, strict word 0000ch                ; b8 0c 00
-    jmp near 03bdeh                           ; e9 86 01
+    jmp near 03bf3h                           ; e9 86 01
     mov ax, word [bp-007feh]                  ; 8b 86 02 f8
     mov dx, word [bp-007fch]                  ; 8b 96 04 f8
     mov word [es:si+008h], ax                 ; 26 89 44 08
@@ -4943,7 +4956,7 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     mov cx, strict word 00009h                ; b9 09 00
     sal ax, 1                                 ; d1 e0
     rcl di, 1                                 ; d1 d7
-    loop 03ac6h                               ; e2 fa
+    loop 03adbh                               ; e2 fa
     push di                                   ; 57
     push ax                                   ; 50
     push strict byte 00000h                   ; 6a 00
@@ -4956,47 +4969,47 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     les bx, [bp-014h]                         ; c4 5e ec
     mov word [es:bx+01ch], strict word 00000h ; 26 c7 47 1c 00 00
     test ax, ax                               ; 85 c0
-    je short 03af6h                           ; 74 06
+    je short 03b0bh                           ; 74 06
     mov ax, strict word 0000dh                ; b8 0d 00
-    jmp near 03bdeh                           ; e9 e8 00
+    jmp near 03bf3h                           ; e9 e8 00
     mov es, [bp-010h]                         ; 8e 46 f0
     mov al, byte [es:si+001h]                 ; 26 8a 44 01
     cmp AL, strict byte 002h                  ; 3c 02
-    jc short 03b0eh                           ; 72 0d
-    jbe short 03b26h                          ; 76 23
+    jc short 03b23h                           ; 72 0d
+    jbe short 03b3bh                          ; 76 23
     cmp AL, strict byte 004h                  ; 3c 04
-    je short 03b3ch                           ; 74 35
+    je short 03b51h                           ; 74 35
     cmp AL, strict byte 003h                  ; 3c 03
-    je short 03b31h                           ; 74 26
-    jmp near 03b87h                           ; e9 79 00
+    je short 03b46h                           ; 74 26
+    jmp near 03b9ch                           ; e9 79 00
     cmp AL, strict byte 001h                  ; 3c 01
-    jne short 03b87h                          ; 75 75
+    jne short 03b9ch                          ; 75 75
     mov es, [bp-010h]                         ; 8e 46 f0
     db  066h, 026h, 0c7h, 044h, 012h, 050h, 000h, 00fh, 000h
     ; mov dword [es:si+012h], strict dword 0000f0050h ; 66 26 c7 44 12 50 00 0f 00
     mov word [es:si+010h], strict word 00002h ; 26 c7 44 10 02 00
-    jmp short 03b87h                          ; eb 61
+    jmp short 03b9ch                          ; eb 61
     db  066h, 026h, 0c7h, 044h, 012h, 050h, 000h, 012h, 000h
     ; mov dword [es:si+012h], strict dword 000120050h ; 66 26 c7 44 12 50 00 12 00
-    jmp short 03b1eh                          ; eb ed
+    jmp short 03b33h                          ; eb ed
     db  066h, 026h, 0c7h, 044h, 012h, 050h, 000h, 024h, 000h
     ; mov dword [es:si+012h], strict dword 000240050h ; 66 26 c7 44 12 50 00 24 00
-    jmp short 03b1eh                          ; eb e2
+    jmp short 03b33h                          ; eb e2
     mov dx, 001c4h                            ; ba c4 01
     mov ax, word [bp-016h]                    ; 8b 46 ea
-    call 01600h                               ; e8 bb da
+    call 01600h                               ; e8 a6 da
     and AL, strict byte 03fh                  ; 24 3f
     xor ah, ah                                ; 30 e4
     mov es, [bp-010h]                         ; 8e 46 f0
     mov word [es:si+014h], ax                 ; 26 89 44 14
     mov dx, 001c4h                            ; ba c4 01
     mov ax, word [bp-016h]                    ; 8b 46 ea
-    call 01600h                               ; e8 a7 da
+    call 01600h                               ; e8 92 da
     movzx bx, al                              ; 0f b6 d8
     sal bx, 002h                              ; c1 e3 02
     mov dx, 001c5h                            ; ba c5 01
     mov ax, word [bp-016h]                    ; 8b 46 ea
-    call 01600h                               ; e8 98 da
+    call 01600h                               ; e8 83 da
     xor ah, ah                                ; 30 e4
     add ax, bx                                ; 01 d8
     inc ax                                    ; 40
@@ -5004,36 +5017,36 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     mov word [es:si+012h], ax                 ; 26 89 44 12
     mov dx, 001c3h                            ; ba c3 01
     mov ax, word [bp-016h]                    ; 8b 46 ea
-    call 01600h                               ; e8 83 da
+    call 01600h                               ; e8 6e da
     xor ah, ah                                ; 30 e4
     inc ax                                    ; 40
     mov es, [bp-010h]                         ; 8e 46 f0
     mov word [es:si+010h], ax                 ; 26 89 44 10
     mov es, [bp-010h]                         ; 8e 46 f0
     cmp byte [es:si+001h], 000h               ; 26 80 7c 01 00
-    je short 03bc5h                           ; 74 34
+    je short 03bdah                           ; 74 34
     cmp byte [es:si+002h], 000h               ; 26 80 7c 02 00
-    jne short 03baeh                          ; 75 16
+    jne short 03bc3h                          ; 75 16
     mov dx, strict word 00010h                ; ba 10 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 5f da
+    call 01600h                               ; e8 4a da
     or AL, strict byte 041h                   ; 0c 41
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00010h                ; ba 10 00
     mov ax, strict word 00040h                ; b8 40 00
-    jmp short 03bc2h                          ; eb 14
+    jmp short 03bd7h                          ; eb 14
     mov dx, 002c0h                            ; ba c0 02
     mov ax, word [bp-018h]                    ; 8b 46 e8
-    call 01600h                               ; e8 49 da
+    call 01600h                               ; e8 34 da
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     movzx bx, al                              ; 0f b6 d8
     mov dx, 002c0h                            ; ba c0 02
     mov ax, word [bp-018h]                    ; 8b 46 e8
-    call 0160eh                               ; e8 49 da
+    call 0160eh                               ; e8 34 da
     mov es, [bp-010h]                         ; 8e 46 f0
     cmp byte [es:si+001h], 000h               ; 26 80 7c 01 00
-    je short 03bd3h                           ; 74 04
+    je short 03be8h                           ; 74 04
     mov byte [es:si], 001h                    ; 26 c6 04 01
     mov es, [bp-010h]                         ; 8e 46 f0
     movzx ax, byte [es:si+002h]               ; 26 0f b6 44 02
@@ -5047,12 +5060,12 @@ cdrom_boot_:                                 ; 0xf382b LB 0x416
     pop bp                                    ; 5d
     retn                                      ; c3
     db  050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
-    db  010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0d9h, 03fh, 0e7h
-    db  03ch, 031h, 03dh, 059h, 03dh, 026h, 03dh, 059h, 03dh, 026h, 03dh, 02fh, 03fh, 00ch, 03dh, 0d9h
-    db  03fh, 0d9h, 03fh, 00ch, 03dh, 00ch, 03dh, 00ch, 03dh, 00ch, 03dh, 00ch, 03dh, 0d0h, 03fh, 00ch
-    db  03dh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h
-    db  03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh, 0d9h, 03fh
-_int13_cdemu:                                ; 0xf3c41 LB 0x434
+    db  010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0eeh, 03fh, 0fch
+    db  03ch, 046h, 03dh, 06eh, 03dh, 03bh, 03dh, 06eh, 03dh, 03bh, 03dh, 044h, 03fh, 021h, 03dh, 0eeh
+    db  03fh, 0eeh, 03fh, 021h, 03dh, 021h, 03dh, 021h, 03dh, 021h, 03dh, 021h, 03dh, 0e5h, 03fh, 021h
+    db  03dh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh
+    db  03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh, 0eeh, 03fh
+_int13_cdemu:                                ; 0xf3c56 LB 0x434
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -5060,7 +5073,7 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     sub sp, strict byte 0002ah                ; 83 ec 2a
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 ca d9
+    call 0161ch                               ; e8 b5 d9
     mov di, 00322h                            ; bf 22 03
     mov cx, ax                                ; 89 c1
     mov si, di                                ; 89 fe
@@ -5076,19 +5089,19 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 8d d9
+    call 0160eh                               ; e8 78 d9
     mov es, cx                                ; 8e c1
     cmp byte [es:di], 000h                    ; 26 80 3d 00
-    je short 03c97h                           ; 74 0e
+    je short 03cach                           ; 74 0e
     movzx dx, byte [es:di+002h]               ; 26 0f b6 55 02
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     cmp dx, ax                                ; 39 c2
-    je short 03cc0h                           ; 74 29
-    mov bx, 00da2h                            ; bb a2 0d
+    je short 03cd5h                           ; 74 29
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 2a dc
+    call 018e1h                               ; e8 2a dc
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     push ax                                   ; 50
@@ -5098,21 +5111,21 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     push 0032ch                               ; 68 2c 03
     push 00338h                               ; 68 38 03
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 53 dc
+    call 01922h                               ; e8 53 dc
     add sp, strict byte 0000ah                ; 83 c4 0a
-    jmp near 03ff9h                           ; e9 39 03
+    jmp near 0400eh                           ; e9 39 03
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     cmp ax, strict word 00050h                ; 3d 50 00
-    jnbe near 03fd9h                          ; 0f 87 0c 03
+    jnbe near 03feeh                          ; 0f 87 0c 03
     push CS                                   ; 0e
     pop ES                                    ; 07
     mov cx, strict word 0001eh                ; b9 1e 00
-    mov di, 03be8h                            ; bf e8 3b
+    mov di, 03bfdh                            ; bf fd 3b
     repne scasb                               ; f2 ae
     sal cx, 1                                 ; d1 e1
     mov di, cx                                ; 89 cf
-    mov ax, word [cs:di+03c05h]               ; 2e 8b 85 05 3c
+    mov ax, word [cs:di+03c1ah]               ; 2e 8b 85 1a 3c
     mov bx, word [bp+016h]                    ; 8b 5e 16
     xor bh, bh                                ; 30 ff
     jmp ax                                    ; ff e0
@@ -5123,14 +5136,14 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     movzx bx, byte [es:bx+01eh]               ; 26 0f b6 5f 1e
     add bx, bx                                ; 01 db
     cmp word [word bx+0006ah], strict byte 00000h ; 83 bf 6a 00 00
-    je near 03d0ch                            ; 0f 84 08 00
+    je near 03d21h                            ; 0f 84 08 00
     movzx ax, byte [bp-006h]                  ; 0f b6 46 fa
     call word [word bx+00076h]                ; ff 97 76 00
     mov byte [bp+017h], 000h                  ; c6 46 17 00
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 f3 d8
+    call 0160eh                               ; e8 de d8
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
@@ -5140,10 +5153,10 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 003h                               ; 80 cc 03
-    jmp near 04001h                           ; e9 d0 02
+    jmp near 04016h                           ; e9 d0 02
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 c6 d8
+    call 01600h                               ; e8 b1 d8
     mov cl, al                                ; 88 c1
     movzx ax, cl                              ; 0f b6 c1
     sal ax, 008h                              ; c1 e0 08
@@ -5152,10 +5165,10 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 bc d8
+    call 0160eh                               ; e8 a7 d8
     test cl, cl                               ; 84 c9
-    je short 03d10h                           ; 74 ba
-    jmp near 04015h                           ; e9 bc 02
+    je short 03d25h                           ; 74 ba
+    jmp near 0402ah                           ; e9 bc 02
     mov es, [bp-008h]                         ; 8e 46 f8
     mov di, word [es:si+014h]                 ; 26 8b 7c 14
     mov dx, word [es:si+012h]                 ; 26 8b 54 12
@@ -5179,19 +5192,19 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     xor ch, ch                                ; 30 ed
     mov word [bp-00ah], cx                    ; 89 4e f6
     test cx, cx                               ; 85 c9
-    jne short 03da6h                          ; 75 03
-    jmp near 03d0ch                           ; e9 66 ff
+    jne short 03dbbh                          ; 75 03
+    jmp near 03d21h                           ; e9 66 ff
     cmp di, word [bp-010h]                    ; 3b 7e f0
-    jc near 03ff9h                            ; 0f 82 4c 02
+    jc near 0400eh                            ; 0f 82 4c 02
     cmp ax, dx                                ; 39 d0
-    jnc near 03ff9h                           ; 0f 83 46 02
+    jnc near 0400eh                           ; 0f 83 46 02
     cmp si, bx                                ; 39 de
-    jnc near 03ff9h                           ; 0f 83 40 02
+    jnc near 0400eh                           ; 0f 83 40 02
     mov dx, word [bp+016h]                    ; 8b 56 16
     shr dx, 008h                              ; c1 ea 08
     cmp dx, strict byte 00004h                ; 83 fa 04
-    jne short 03dc7h                          ; 75 03
-    jmp near 03d0ch                           ; e9 45 ff
+    jne short 03ddch                          ; 75 03
+    jmp near 03d21h                           ; e9 45 ff
     mov dx, word [bp+010h]                    ; 8b 56 10
     shr dx, 004h                              ; c1 ea 04
     mov cx, word [bp+006h]                    ; 8b 4e 06
@@ -5202,13 +5215,13 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     mov word [bp-01ch], dx                    ; 89 56 e4
     xor dl, dl                                ; 30 d2
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 c4 55
+    call 09459h                               ; e8 5f 56
     xor bx, bx                                ; 31 db
     add ax, si                                ; 01 f0
     adc dx, bx                                ; 11 da
     mov bx, di                                ; 89 fb
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 b7 55
+    call 09459h                               ; e8 52 56
     mov bx, ax                                ; 89 c3
     mov ax, word [bp-010h]                    ; 8b 46 f0
     dec ax                                    ; 48
@@ -5243,7 +5256,7 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     mov cx, strict word 0000ch                ; b9 0c 00
     mov dx, ss                                ; 8c d2
     lea ax, [bp-02eh]                         ; 8d 46 d2
-    call 093dah                               ; e8 91 55
+    call 0948ah                               ; e8 2c 56
     mov word [bp-02eh], strict word 00028h    ; c7 46 d2 28 00
     mov ax, word [bp-014h]                    ; 8b 46 ec
     add ax, si                                ; 01 f0
@@ -5291,7 +5304,7 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     mov cx, strict word 00009h                ; b9 09 00
     sal si, 1                                 ; d1 e6
     rcl di, 1                                 ; d1 d7
-    loop 03ec9h                               ; e2 fa
+    loop 03edeh                               ; e2 fa
     push di                                   ; 57
     push si                                   ; 56
     push ax                                   ; 50
@@ -5306,11 +5319,11 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     db  066h, 026h, 0c7h, 047h, 01ah, 000h, 000h, 000h, 000h
     ; mov dword [es:bx+01ah], strict dword 000000000h ; 66 26 c7 47 1a 00 00 00 00
     test al, al                               ; 84 c0
-    je near 03d0ch                            ; 0f 84 13 fe
-    mov bx, 00da2h                            ; bb a2 0d
+    je near 03d21h                            ; 0f 84 13 fe
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 c8 d9
+    call 018e1h                               ; e8 c8 d9
     movzx ax, dl                              ; 0f b6 c2
     push ax                                   ; 50
     mov ax, word [bp+016h]                    ; 8b 46 16
@@ -5319,14 +5332,14 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     push 0032ch                               ; 68 2c 03
     push 0036eh                               ; 68 6e 03
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 f3 d9
+    call 01922h                               ; e8 f3 d9
     add sp, strict byte 0000ah                ; 83 c4 0a
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 002h                               ; 80 cc 02
     mov word [bp+016h], ax                    ; 89 46 16
     mov byte [bp+016h], 000h                  ; c6 46 16 00
-    jmp near 04004h                           ; e9 d5 00
+    jmp near 04019h                           ; e9 d5 00
     mov es, [bp-008h]                         ; 8e 46 f8
     mov di, word [es:si+014h]                 ; 26 8b 7c 14
     mov dx, word [es:si+012h]                 ; 26 8b 54 12
@@ -5365,40 +5378,40 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     mov dl, byte [es:si+001h]                 ; 26 8a 54 01
     mov word [bp+010h], ax                    ; 89 46 10
     cmp dl, 003h                              ; 80 fa 03
-    je short 03fb3h                           ; 74 1a
+    je short 03fc8h                           ; 74 1a
     cmp dl, 002h                              ; 80 fa 02
-    je short 03fafh                           ; 74 11
+    je short 03fc4h                           ; 74 11
     cmp dl, 001h                              ; 80 fa 01
-    jne short 03fb7h                          ; 75 14
+    jne short 03fcch                          ; 75 14
     mov ax, word [bp+010h]                    ; 8b 46 10
     xor al, al                                ; 30 c0
     or AL, strict byte 002h                   ; 0c 02
     mov word [bp+010h], ax                    ; 89 46 10
-    jmp short 03fb7h                          ; eb 08
+    jmp short 03fcch                          ; eb 08
     or AL, strict byte 004h                   ; 0c 04
-    jmp short 03faah                          ; eb f7
+    jmp short 03fbfh                          ; eb f7
     or AL, strict byte 005h                   ; 0c 05
-    jmp short 03faah                          ; eb f3
+    jmp short 03fbfh                          ; eb f3
     mov es, [bp-008h]                         ; 8e 46 f8
     cmp byte [es:si+001h], 004h               ; 26 80 7c 01 04
-    jnc near 03d0ch                           ; 0f 83 49 fd
+    jnc near 03d21h                           ; 0f 83 49 fd
     mov word [bp+008h], 0efc7h                ; c7 46 08 c7 ef
     mov word [bp+006h], 0f000h                ; c7 46 06 00 f0
-    jmp near 03d0ch                           ; e9 3c fd
+    jmp near 03d21h                           ; e9 3c fd
     or bh, 003h                               ; 80 cf 03
     mov word [bp+016h], bx                    ; 89 5e 16
-    jmp near 03d10h                           ; e9 37 fd
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 03d25h                           ; e9 37 fd
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 e8 d8
+    call 018e1h                               ; e8 e8 d8
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 0032ch                               ; 68 2c 03
     push 0038fh                               ; 68 8f 03
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 17 d9
+    call 01922h                               ; e8 17 d9
     add sp, strict byte 00008h                ; 83 c4 08
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
@@ -5409,16 +5422,16 @@ _int13_cdemu:                                ; 0xf3c41 LB 0x434
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 f9 d5
+    call 0160eh                               ; e8 e4 d5
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
-    jmp near 03d1fh                           ; e9 03 fd
+    jmp near 03d34h                           ; e9 03 fd
     db  050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
-    db  010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0bah, 045h, 036h
-    db  043h, 022h, 041h, 0bah, 045h, 017h, 041h, 0bah, 045h, 017h, 041h, 0bah, 045h, 036h, 043h, 0bah
-    db  045h, 0bah, 045h, 036h, 043h, 036h, 043h, 036h, 043h, 036h, 043h, 036h, 043h, 04ch, 041h, 036h
-    db  043h, 0bah, 045h, 055h, 041h, 068h, 041h, 017h, 041h, 068h, 041h, 096h, 042h, 050h, 043h, 068h
-    db  041h, 077h, 043h, 073h, 045h, 07bh, 045h, 0bah, 045h
-_int13_cdrom:                                ; 0xf4075 LB 0x562
+    db  010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0cfh, 045h, 04bh
+    db  043h, 037h, 041h, 0cfh, 045h, 02ch, 041h, 0cfh, 045h, 02ch, 041h, 0cfh, 045h, 04bh, 043h, 0cfh
+    db  045h, 0cfh, 045h, 04bh, 043h, 04bh, 043h, 04bh, 043h, 04bh, 043h, 04bh, 043h, 061h, 041h, 04bh
+    db  043h, 0cfh, 045h, 06ah, 041h, 07dh, 041h, 02ch, 041h, 07dh, 041h, 0abh, 042h, 065h, 043h, 07dh
+    db  041h, 08ch, 043h, 088h, 045h, 090h, 045h, 0cfh, 045h
+_int13_cdrom:                                ; 0xf408a LB 0x562
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -5426,20 +5439,20 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     sub sp, strict byte 00028h                ; 83 ec 28
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 96 d5
+    call 0161ch                               ; e8 81 d5
     mov word [bp-01ah], ax                    ; 89 46 e6
     mov si, 00122h                            ; be 22 01
     mov word [bp-00ch], ax                    ; 89 46 f4
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 74 d5
+    call 0160eh                               ; e8 5f d5
     mov ax, word [bp+010h]                    ; 8b 46 10
     xor ah, ah                                ; 30 e4
     cmp ax, 000e0h                            ; 3d e0 00
-    jc short 040a9h                           ; 72 05
+    jc short 040beh                           ; 72 05
     cmp ax, 000f0h                            ; 3d f0 00
-    jc short 040c7h                           ; 72 1e
+    jc short 040dch                           ; 72 1e
     mov ax, word [bp+010h]                    ; 8b 46 10
     xor ah, ah                                ; 30 e4
     push ax                                   ; 50
@@ -5449,9 +5462,9 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     push 003bfh                               ; 68 bf 03
     push 003cbh                               ; 68 cb 03
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 4c d8
+    call 01922h                               ; e8 4c d8
     add sp, strict byte 0000ah                ; 83 c4 0a
-    jmp near 04597h                           ; e9 d0 04
+    jmp near 045ach                           ; e9 d0 04
     mov ax, word [bp+010h]                    ; 8b 46 10
     xor ah, ah                                ; 30 e4
     mov es, [bp-00ch]                         ; 8e 46 f4
@@ -5460,36 +5473,36 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov dl, byte [es:bx+000d0h]               ; 26 8a 97 d0 00
     mov byte [bp-008h], dl                    ; 88 56 f8
     cmp dl, 010h                              ; 80 fa 10
-    jc short 040f0h                           ; 72 10
+    jc short 04105h                           ; 72 10
     push ax                                   ; 50
     mov ax, word [bp+018h]                    ; 8b 46 18
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 003bfh                               ; 68 bf 03
     push 003f6h                               ; 68 f6 03
-    jmp short 040bch                          ; eb cc
+    jmp short 040d1h                          ; eb cc
     mov ax, word [bp+018h]                    ; 8b 46 18
     shr ax, 008h                              ; c1 e8 08
     cmp ax, strict word 00050h                ; 3d 50 00
-    jnbe near 045bah                          ; 0f 87 bd 04
+    jnbe near 045cfh                          ; 0f 87 bd 04
     push CS                                   ; 0e
     pop ES                                    ; 07
     mov cx, strict word 0001eh                ; b9 1e 00
-    mov di, 0401ch                            ; bf 1c 40
+    mov di, 04031h                            ; bf 31 40
     repne scasb                               ; f2 ae
     sal cx, 1                                 ; d1 e1
     mov di, cx                                ; 89 cf
-    mov ax, word [cs:di+04039h]               ; 2e 8b 85 39 40
+    mov ax, word [cs:di+0404eh]               ; 2e 8b 85 4e 40
     mov bx, word [bp+018h]                    ; 8b 5e 18
     xor bh, bh                                ; 30 ff
     jmp ax                                    ; ff e0
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor ah, ah                                ; 30 e4
     or ah, 003h                               ; 80 cc 03
-    jmp near 0459fh                           ; e9 7d 04
+    jmp near 045b4h                           ; e9 7d 04
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 d5 d4
+    call 01600h                               ; e8 c0 d4
     mov cl, al                                ; 88 c1
     movzx ax, cl                              ; 0f b6 c1
     sal ax, 008h                              ; c1 e0 08
@@ -5498,18 +5511,18 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 cb d4
+    call 0160eh                               ; e8 b6 d4
     test cl, cl                               ; 84 c9
-    je near 0433ah                            ; 0f 84 f1 01
-    jmp near 045b3h                           ; e9 67 04
+    je near 0434fh                            ; 0f 84 f1 01
+    jmp near 045c8h                           ; e9 67 04
     or bh, 002h                               ; 80 cf 02
     mov word [bp+018h], bx                    ; 89 5e 18
-    jmp near 045a2h                           ; e9 4d 04
+    jmp near 045b7h                           ; e9 4d 04
     mov word [bp+012h], 0aa55h                ; c7 46 12 55 aa
     or bh, 030h                               ; 80 cf 30
     mov word [bp+018h], bx                    ; 89 5e 18
     mov word [bp+016h], strict word 00007h    ; c7 46 16 07 00
-    jmp near 0433ah                           ; e9 d2 01
+    jmp near 0434fh                           ; e9 d2 01
     mov bx, word [bp+00ch]                    ; 8b 5e 0c
     mov es, [bp+006h]                         ; 8e 46 06
     mov word [bp-014h], bx                    ; 89 5e ec
@@ -5524,16 +5537,16 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov word [bp-018h], ax                    ; 89 46 e8
     mov di, word [es:bx+00eh]                 ; 26 8b 7f 0e
     or di, ax                                 ; 09 c7
-    je short 041b0h                           ; 74 18
+    je short 041c5h                           ; 74 18
     mov ax, word [bp+018h]                    ; 8b 46 18
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 003bfh                               ; 68 bf 03
     push 00428h                               ; 68 28 04
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 63 d7
+    call 01922h                               ; e8 63 d7
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp near 04597h                           ; e9 e7 03
+    jmp near 045ach                           ; e9 e7 03
     les bx, [bp-014h]                         ; c4 5e ec
     mov ax, word [es:bx+008h]                 ; 26 8b 47 08
     mov word [bp-018h], ax                    ; 89 46 e8
@@ -5543,14 +5556,14 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     shr ax, 008h                              ; c1 e8 08
     mov word [bp-016h], ax                    ; 89 46 ea
     cmp ax, strict word 00044h                ; 3d 44 00
-    je near 04336h                            ; 0f 84 66 01
+    je near 0434bh                            ; 0f 84 66 01
     cmp ax, strict word 00047h                ; 3d 47 00
-    je near 04336h                            ; 0f 84 5f 01
+    je near 0434bh                            ; 0f 84 5f 01
     mov cx, strict word 0000ch                ; b9 0c 00
     xor bx, bx                                ; 31 db
     mov dx, ss                                ; 8c d2
     lea ax, [bp-02ch]                         ; 8d 46 d4
-    call 093dah                               ; e8 f6 51
+    call 0948ah                               ; e8 91 52
     mov word [bp-02ch], strict word 00028h    ; c7 46 d4 28 00
     mov ax, word [bp-018h]                    ; 8b 46 e8
     mov dx, di                                ; 89 fa
@@ -5578,7 +5591,7 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov cx, strict word 0000bh                ; b9 0b 00
     sal ax, 1                                 ; d1 e0
     rcl bx, 1                                 ; d1 d3
-    loop 0422eh                               ; e2 fa
+    loop 04243h                               ; e2 fa
     push bx                                   ; 53
     push ax                                   ; 50
     push strict byte 00000h                   ; 6a 00
@@ -5594,29 +5607,29 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov cx, strict word 0000bh                ; b9 0b 00
     shr di, 1                                 ; d1 ef
     rcr ax, 1                                 ; d1 d8
-    loop 04258h                               ; e2 fa
+    loop 0426dh                               ; e2 fa
     les bx, [bp-014h]                         ; c4 5e ec
     mov word [es:bx+002h], ax                 ; 26 89 47 02
     test dl, dl                               ; 84 d2
-    je near 04336h                            ; 0f 84 cb 00
-    mov bx, 00da2h                            ; bb a2 0d
+    je near 0434bh                            ; 0f 84 cb 00
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 56 d6
+    call 018e1h                               ; e8 56 d6
     movzx ax, dl                              ; 0f b6 c2
     push ax                                   ; 50
     push word [bp-016h]                       ; ff 76 ea
     push 003bfh                               ; 68 bf 03
     push 00451h                               ; 68 51 04
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 85 d6
+    call 01922h                               ; e8 85 d6
     add sp, strict byte 0000ah                ; 83 c4 0a
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor ah, ah                                ; 30 e4
     or ah, 00ch                               ; 80 cc 0c
-    jmp near 0459fh                           ; e9 09 03
+    jmp near 045b4h                           ; e9 09 03
     cmp bx, strict byte 00002h                ; 83 fb 02
-    jnbe near 04597h                          ; 0f 87 fa 02
+    jnbe near 045ach                          ; 0f 87 fa 02
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov es, [bp-00ch]                         ; 8e 46 f4
@@ -5624,20 +5637,20 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     add di, ax                                ; 01 c7
     mov al, byte [es:di+021h]                 ; 26 8a 45 21
     cmp bx, strict byte 00002h                ; 83 fb 02
-    je short 04327h                           ; 74 73
+    je short 0433ch                           ; 74 73
     cmp bx, strict byte 00001h                ; 83 fb 01
-    je short 042f4h                           ; 74 3b
+    je short 04309h                           ; 74 3b
     test bx, bx                               ; 85 db
-    jne near 04336h                           ; 0f 85 77 00
+    jne near 0434bh                           ; 0f 85 77 00
     cmp AL, strict byte 0ffh                  ; 3c ff
-    jne short 042d5h                          ; 75 12
+    jne short 042eah                          ; 75 12
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor ah, ah                                ; 30 e4
     or ah, 0b4h                               ; 80 cc b4
     mov word [bp+018h], ax                    ; 89 46 18
     xor al, al                                ; 30 c0
     or AL, strict byte 001h                   ; 0c 01
-    jmp near 0459fh                           ; e9 ca 02
+    jmp near 045b4h                           ; e9 ca 02
     movzx dx, byte [bp-008h]                  ; 0f b6 56 f8
     imul dx, dx, strict byte 00018h           ; 6b d2 18
     db  0feh, 0c0h
@@ -5649,13 +5662,13 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     xor al, al                                ; 30 c0
     or AL, strict byte 001h                   ; 0c 01
     mov word [bp+018h], ax                    ; 89 46 18
-    jmp near 04336h                           ; e9 42 00
+    jmp near 0434bh                           ; e9 42 00
     test al, al                               ; 84 c0
-    jne short 04304h                          ; 75 0c
+    jne short 04319h                          ; 75 0c
     or bh, 0b0h                               ; 80 cf b0
     mov word [bp+018h], bx                    ; 89 5e 18
     mov byte [bp+018h], al                    ; 88 46 18
-    jmp near 045a2h                           ; e9 9e 02
+    jmp near 045b7h                           ; e9 9e 02
     movzx dx, byte [bp-008h]                  ; 0f b6 56 f8
     imul dx, dx, strict byte 00018h           ; 6b d2 18
     db  0feh, 0c8h
@@ -5670,7 +5683,7 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor al, al                                ; 30 c0
     or ax, dx                                 ; 09 d0
-    jmp short 042eeh                          ; eb c7
+    jmp short 04303h                          ; eb c7
     test al, al                               ; 84 c0
     db  00fh, 095h, 0c0h
     ; setne al                                  ; 0f 95 c0
@@ -5682,7 +5695,7 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 c9 d2
+    call 0160eh                               ; e8 b4 d2
     and byte [bp+01eh], 0feh                  ; 80 66 1e fe
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
@@ -5695,14 +5708,14 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     add si, ax                                ; 01 c6
     mov al, byte [es:si+021h]                 ; 26 8a 44 21
     test al, al                               ; 84 c0
-    je short 0436ah                           ; 74 06
+    je short 0437fh                           ; 74 06
     or bh, 0b1h                               ; 80 cf b1
-    jmp near 0414fh                           ; e9 e5 fd
-    je short 04336h                           ; 74 ca
+    jmp near 04164h                           ; e9 e5 fd
+    je short 0434bh                           ; 74 ca
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor ah, ah                                ; 30 e4
     or ah, 0b1h                               ; 80 cc b1
-    jmp near 0459fh                           ; e9 28 02
+    jmp near 045b4h                           ; e9 28 02
     mov dx, word [bp+00ch]                    ; 8b 56 0c
     mov cx, word [bp+006h]                    ; 8b 4e 06
     mov bx, dx                                ; 89 d3
@@ -5712,8 +5725,8 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov ax, word [es:di]                      ; 26 8b 05
     mov word [bp-00eh], ax                    ; 89 46 f2
     cmp ax, strict word 0001ah                ; 3d 1a 00
-    jc near 04597h                            ; 0f 82 04 02
-    jc short 043e4h                           ; 72 4f
+    jc near 045ach                            ; 0f 82 04 02
+    jc short 043f9h                           ; 72 4f
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov es, [bp-00ch]                         ; 8e 46 f4
@@ -5736,7 +5749,7 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     db  066h, 026h, 0c7h, 045h, 014h, 0ffh, 0ffh, 0ffh, 0ffh
     ; mov dword [es:di+014h], strict dword 0ffffffffh ; 66 26 c7 45 14 ff ff ff ff
     cmp word [bp-00eh], strict byte 0001eh    ; 83 7e f2 1e
-    jc near 044bbh                            ; 0f 82 cf 00
+    jc near 044d0h                            ; 0f 82 cf 00
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov word [es:bx], strict word 0001eh      ; 26 c7 07 1e 00
     mov ax, word [bp-01ah]                    ; 8b 46 e6
@@ -5788,22 +5801,22 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov byte [es:si+001feh], 011h             ; 26 c6 84 fe 01 11
     xor cl, cl                                ; 30 c9
     xor ch, ch                                ; 30 ed
-    jmp short 0449eh                          ; eb 05
+    jmp short 044b3h                          ; eb 05
     cmp ch, 00fh                              ; 80 fd 0f
-    jnc short 044b1h                          ; 73 13
+    jnc short 044c6h                          ; 73 13
     movzx dx, ch                              ; 0f b6 d5
     add dx, 00312h                            ; 81 c2 12 03
     mov ax, word [bp-01ah]                    ; 8b 46 e6
-    call 01600h                               ; e8 55 d1
+    call 01600h                               ; e8 40 d1
     add cl, al                                ; 00 c1
     db  0feh, 0c5h
     ; inc ch                                    ; fe c5
-    jmp short 04499h                          ; eb e8
+    jmp short 044aeh                          ; eb e8
     neg cl                                    ; f6 d9
     mov es, [bp-00ch]                         ; 8e 46 f4
     mov byte [es:si+001ffh], cl               ; 26 88 8c ff 01
     cmp word [bp-00eh], strict byte 00042h    ; 83 7e f2 42
-    jc near 04336h                            ; 0f 82 73 fe
+    jc near 0434bh                            ; 0f 82 73 fe
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     cwd                                       ; 99
     db  02bh, 0c2h
@@ -5821,7 +5834,7 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     ; mov dword [es:bx+01eh], strict dword 00024beddh ; 66 26 c7 47 1e dd be 24 00
     mov word [es:bx+022h], strict word 00000h ; 26 c7 47 22 00 00
     test al, al                               ; 84 c0
-    jne short 04504h                          ; 75 09
+    jne short 04519h                          ; 75 09
     db  066h, 026h, 0c7h, 047h, 024h, 049h, 053h, 041h, 020h
     ; mov dword [es:bx+024h], strict dword 020415349h ; 66 26 c7 47 24 49 53 41 20
     mov es, [bp-00ah]                         ; 8e 46 f6
@@ -5830,7 +5843,7 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     db  066h, 026h, 0c7h, 047h, 02ch, 020h, 020h, 020h, 020h
     ; mov dword [es:bx+02ch], strict dword 020202020h ; 66 26 c7 47 2c 20 20 20 20
     test al, al                               ; 84 c0
-    jne short 04530h                          ; 75 13
+    jne short 04545h                          ; 75 13
     mov word [es:bx+030h], dx                 ; 26 89 57 30
     db  066h, 026h, 0c7h, 047h, 032h, 000h, 000h, 000h, 000h
     ; mov dword [es:bx+032h], strict dword 000000000h ; 66 26 c7 47 32 00 00 00 00
@@ -5845,32 +5858,32 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     mov word [es:bx+03eh], strict word 00000h ; 26 c7 47 3e 00 00
     xor al, al                                ; 30 c0
     mov AH, strict byte 01eh                  ; b4 1e
-    jmp short 04558h                          ; eb 05
+    jmp short 0456dh                          ; eb 05
     cmp ah, 040h                              ; 80 fc 40
-    jnc short 04567h                          ; 73 0f
+    jnc short 0457ch                          ; 73 0f
     movzx si, ah                              ; 0f b6 f4
     mov es, [bp-00ah]                         ; 8e 46 f6
     add si, bx                                ; 01 de
     add al, byte [es:si]                      ; 26 02 04
     db  0feh, 0c4h
     ; inc ah                                    ; fe c4
-    jmp short 04553h                          ; eb ec
+    jmp short 04568h                          ; eb ec
     neg al                                    ; f6 d8
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov byte [es:bx+041h], al                 ; 26 88 47 41
-    jmp near 04336h                           ; e9 c3 fd
+    jmp near 0434bh                           ; e9 c3 fd
     or bh, 006h                               ; 80 cf 06
     mov word [bp+018h], bx                    ; 89 5e 18
-    jmp short 045b3h                          ; eb 38
+    jmp short 045c8h                          ; eb 38
     cmp bx, strict byte 00006h                ; 83 fb 06
-    je near 04336h                            ; 0f 84 b4 fd
+    je near 0434bh                            ; 0f 84 b4 fd
     cmp bx, strict byte 00001h                ; 83 fb 01
-    jc short 04597h                           ; 72 10
-    jbe near 04336h                           ; 0f 86 ab fd
+    jc short 045ach                           ; 72 10
+    jbe near 0434bh                           ; 0f 86 ab fd
     cmp bx, strict byte 00003h                ; 83 fb 03
-    jc short 04597h                           ; 72 07
+    jc short 045ach                           ; 72 07
     cmp bx, strict byte 00004h                ; 83 fb 04
-    jbe near 04336h                           ; 0f 86 9f fd
+    jbe near 0434bh                           ; 0f 86 9f fd
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
@@ -5880,55 +5893,55 @@ _int13_cdrom:                                ; 0xf4075 LB 0x562
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 5b d0
+    call 0160eh                               ; e8 46 d0
     or byte [bp+01eh], 001h                   ; 80 4e 1e 01
-    jmp near 04349h                           ; e9 8f fd
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 0435eh                           ; e9 8f fd
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 07 d3
+    call 018e1h                               ; e8 07 d3
     mov ax, word [bp+018h]                    ; 8b 46 18
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 003bfh                               ; 68 bf 03
     push 00313h                               ; 68 13 03
     push strict byte 00004h                   ; 6a 04
-    jmp near 041a7h                           ; e9 d0 fb
-print_boot_device_:                          ; 0xf45d7 LB 0x4b
+    jmp near 041bch                           ; e9 d0 fb
+print_boot_device_:                          ; 0xf45ec LB 0x4b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
     test al, al                               ; 84 c0
-    je short 045e4h                           ; 74 05
+    je short 045f9h                           ; 74 05
     mov dx, strict word 00002h                ; ba 02 00
-    jmp short 045feh                          ; eb 1a
+    jmp short 04613h                          ; eb 1a
     test dl, dl                               ; 84 d2
-    je short 045edh                           ; 74 05
+    je short 04602h                           ; 74 05
     mov dx, strict word 00003h                ; ba 03 00
-    jmp short 045feh                          ; eb 11
+    jmp short 04613h                          ; eb 11
     test bl, 080h                             ; f6 c3 80
-    jne short 045f6h                          ; 75 04
+    jne short 0460bh                          ; 75 04
     xor dh, dh                                ; 30 f6
-    jmp short 045feh                          ; eb 08
+    jmp short 04613h                          ; eb 08
     test bl, 080h                             ; f6 c3 80
-    je short 0461ch                           ; 74 21
+    je short 04631h                           ; 74 21
     mov dx, strict word 00001h                ; ba 01 00
-    mov bx, 00da2h                            ; bb a2 0d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 c3 d2
+    call 018e1h                               ; e8 c3 d2
     imul dx, dx, strict byte 0000ah           ; 6b d2 0a
-    add dx, 00dc8h                            ; 81 c2 c8 0d
+    add dx, 00de0h                            ; 81 c2 e0 0d
     push dx                                   ; 52
     push 00474h                               ; 68 74 04
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 f4 d2
+    call 01922h                               ; e8 f4 d2
     add sp, strict byte 00006h                ; 83 c4 06
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-print_boot_failure_:                         ; 0xf4622 LB 0x93
+print_boot_failure_:                         ; 0xf4637 LB 0x93
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -5937,73 +5950,73 @@ print_boot_failure_:                         ; 0xf4622 LB 0x93
     and ah, 07fh                              ; 80 e4 7f
     movzx si, ah                              ; 0f b6 f4
     test al, al                               ; 84 c0
-    je short 0464fh                           ; 74 1b
-    mov bx, 00da2h                            ; bb a2 0d
+    je short 04664h                           ; 74 1b
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 8d d2
-    push 00ddch                               ; 68 dc 0d
+    call 018e1h                               ; e8 8d d2
+    push 00df4h                               ; 68 f4 0d
     push 00488h                               ; 68 88 04
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 c3 d2
+    call 01922h                               ; e8 c3 d2
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp short 04693h                          ; eb 44
+    jmp short 046a8h                          ; eb 44
     test dl, dl                               ; 84 d2
-    je short 04663h                           ; 74 10
-    mov bx, 00da2h                            ; bb a2 0d
+    je short 04678h                           ; 74 10
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 6e d2
-    push 00de6h                               ; 68 e6 0d
-    jmp short 04642h                          ; eb df
+    call 018e1h                               ; e8 6e d2
+    push 00dfeh                               ; 68 fe 0d
+    jmp short 04657h                          ; eb df
     test bl, 080h                             ; f6 c3 80
-    je short 04679h                           ; 74 11
-    mov bx, 00da2h                            ; bb a2 0d
+    je short 0468eh                           ; 74 11
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 59 d2
+    call 018e1h                               ; e8 59 d2
     push si                                   ; 56
-    push 00dd2h                               ; 68 d2 0d
-    jmp short 04688h                          ; eb 0f
-    mov bx, 00da2h                            ; bb a2 0d
+    push 00deah                               ; 68 ea 0d
+    jmp short 0469dh                          ; eb 0f
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 48 d2
+    call 018e1h                               ; e8 48 d2
     push si                                   ; 56
-    push 00dc8h                               ; 68 c8 0d
+    push 00de0h                               ; 68 e0 0d
     push 0049dh                               ; 68 9d 04
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 7d d2
+    call 01922h                               ; e8 7d d2
     add sp, strict byte 00008h                ; 83 c4 08
     cmp byte [bp+004h], 001h                  ; 80 7e 04 01
-    jne short 046adh                          ; 75 14
+    jne short 046c2h                          ; 75 14
     test dh, dh                               ; 84 f6
-    jne short 046a2h                          ; 75 05
+    jne short 046b7h                          ; 75 05
     push 004b5h                               ; 68 b5 04
-    jmp short 046a5h                          ; eb 03
+    jmp short 046bah                          ; eb 03
     push 004dfh                               ; 68 df 04
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 63 d2
+    call 01922h                               ; e8 63 d2
     add sp, strict byte 00004h                ; 83 c4 04
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00002h                               ; c2 02 00
-print_cdromboot_failure_:                    ; 0xf46b5 LB 0x27
+print_cdromboot_failure_:                    ; 0xf46ca LB 0x27
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
     push cx                                   ; 51
     push dx                                   ; 52
     mov dx, ax                                ; 89 c2
-    mov bx, 00da2h                            ; bb a2 0d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 04 d2
+    call 018e1h                               ; e8 04 d2
     push dx                                   ; 52
     push 00514h                               ; 68 14 05
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 3c d2
+    call 01922h                               ; e8 3c d2
     add sp, strict byte 00006h                ; 83 c4 06
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop dx                                    ; 5a
@@ -6011,7 +6024,7 @@ print_cdromboot_failure_:                    ; 0xf46b5 LB 0x27
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-_int19_function:                             ; 0xf46dc LB 0x256
+_int19_function:                             ; 0xf46f1 LB 0x256
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -6019,160 +6032,160 @@ _int19_function:                             ; 0xf46dc LB 0x256
     sub sp, strict byte 0000eh                ; 83 ec 0e
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 2f cf
+    call 0161ch                               ; e8 1a cf
     mov bx, ax                                ; 89 c3
     mov word [bp-00eh], ax                    ; 89 46 f2
     mov byte [bp-008h], 000h                  ; c6 46 f8 00
     mov ax, strict word 0003dh                ; b8 3d 00
-    call 0165ch                               ; e8 60 cf
+    call 0165ch                               ; e8 4b cf
     movzx si, al                              ; 0f b6 f0
     mov ax, strict word 00038h                ; b8 38 00
-    call 0165ch                               ; e8 57 cf
+    call 0165ch                               ; e8 42 cf
     and AL, strict byte 0f0h                  ; 24 f0
     xor ah, ah                                ; 30 e4
     sal ax, 004h                              ; c1 e0 04
     or si, ax                                 ; 09 c6
     mov ax, strict word 0003ch                ; b8 3c 00
-    call 0165ch                               ; e8 48 cf
+    call 0165ch                               ; e8 33 cf
     and AL, strict byte 00fh                  ; 24 0f
     xor ah, ah                                ; 30 e4
     sal ax, 00ch                              ; c1 e0 0c
     or si, ax                                 ; 09 c6
     mov dx, 00339h                            ; ba 39 03
     mov ax, bx                                ; 89 d8
-    call 01600h                               ; e8 db ce
+    call 01600h                               ; e8 c6 ce
     test al, al                               ; 84 c0
-    je short 04734h                           ; 74 0b
+    je short 04749h                           ; 74 0b
     mov dx, 00339h                            ; ba 39 03
     mov ax, bx                                ; 89 d8
-    call 01600h                               ; e8 cf ce
+    call 01600h                               ; e8 ba ce
     movzx si, al                              ; 0f b6 f0
     cmp byte [bp+004h], 001h                  ; 80 7e 04 01
-    jne short 0474ah                          ; 75 10
+    jne short 0475fh                          ; 75 10
     mov ax, strict word 0003ch                ; b8 3c 00
-    call 0165ch                               ; e8 1c cf
+    call 0165ch                               ; e8 07 cf
     and AL, strict byte 0f0h                  ; 24 f0
     xor ah, ah                                ; 30 e4
     sar ax, 004h                              ; c1 f8 04
-    call 07594h                               ; e8 4a 2e
+    call 075a9h                               ; e8 4a 2e
     cmp byte [bp+004h], 002h                  ; 80 7e 04 02
-    jne short 04753h                          ; 75 03
+    jne short 04768h                          ; 75 03
     shr si, 004h                              ; c1 ee 04
     cmp byte [bp+004h], 003h                  ; 80 7e 04 03
-    jne short 0475ch                          ; 75 03
+    jne short 04771h                          ; 75 03
     shr si, 008h                              ; c1 ee 08
     cmp byte [bp+004h], 004h                  ; 80 7e 04 04
-    jne short 04765h                          ; 75 03
+    jne short 0477ah                          ; 75 03
     shr si, 00ch                              ; c1 ee 0c
     cmp si, strict byte 00010h                ; 83 fe 10
-    jnc short 0476eh                          ; 73 04
+    jnc short 04783h                          ; 73 04
     mov byte [bp-008h], 001h                  ; c6 46 f8 01
     xor al, al                                ; 30 c0
     mov byte [bp-006h], al                    ; 88 46 fa
     mov byte [bp-00ah], al                    ; 88 46 f6
     mov byte [bp-00ch], al                    ; 88 46 f4
-    mov bx, 00da2h                            ; bb a2 0d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 48 d1
+    call 018e1h                               ; e8 48 d1
     push si                                   ; 56
     movzx ax, byte [bp+004h]                  ; 0f b6 46 04
     push ax                                   ; 50
     push 00534h                               ; 68 34 05
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 7b d1
+    call 01922h                               ; e8 7b d1
     add sp, strict byte 00008h                ; 83 c4 08
     and si, strict byte 0000fh                ; 83 e6 0f
     cmp si, strict byte 00002h                ; 83 fe 02
-    jc short 047abh                           ; 72 0e
-    jbe short 047bah                          ; 76 1b
+    jc short 047c0h                           ; 72 0e
+    jbe short 047cfh                          ; 76 1b
     cmp si, strict byte 00004h                ; 83 fe 04
-    je short 047d8h                           ; 74 34
+    je short 047edh                           ; 74 34
     cmp si, strict byte 00003h                ; 83 fe 03
-    je short 047ceh                           ; 74 25
-    jmp short 04805h                          ; eb 5a
+    je short 047e3h                           ; 74 25
+    jmp short 0481ah                          ; eb 5a
     cmp si, strict byte 00001h                ; 83 fe 01
-    jne short 04805h                          ; 75 55
+    jne short 0481ah                          ; 75 55
     xor al, al                                ; 30 c0
     mov byte [bp-006h], al                    ; 88 46 fa
     mov byte [bp-00ah], al                    ; 88 46 f6
-    jmp short 0481dh                          ; eb 63
+    jmp short 04832h                          ; eb 63
     mov dx, 00338h                            ; ba 38 03
     mov ax, word [bp-00eh]                    ; 8b 46 f2
-    call 01600h                               ; e8 3d ce
+    call 01600h                               ; e8 28 ce
     add AL, strict byte 080h                  ; 04 80
     mov byte [bp-006h], al                    ; 88 46 fa
     mov byte [bp-00ah], 000h                  ; c6 46 f6 00
-    jmp short 0481dh                          ; eb 4f
+    jmp short 04832h                          ; eb 4f
     mov byte [bp-006h], 000h                  ; c6 46 fa 00
     mov byte [bp-00ah], 001h                  ; c6 46 f6 01
-    jmp short 047e2h                          ; eb 0a
+    jmp short 047f7h                          ; eb 0a
     mov byte [bp-00ch], 001h                  ; c6 46 f4 01
     cmp byte [bp-00ah], 000h                  ; 80 7e f6 00
-    je short 0481dh                           ; 74 3b
-    call 0382bh                               ; e8 46 f0
+    je short 04832h                           ; 74 3b
+    call 03840h                               ; e8 46 f0
     mov bx, ax                                ; 89 c3
     test AL, strict byte 0ffh                 ; a8 ff
-    je short 0480ch                           ; 74 21
-    call 046b5h                               ; e8 c7 fe
+    je short 04821h                           ; 74 21
+    call 046cah                               ; e8 c7 fe
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     push ax                                   ; 50
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
     mov cx, strict word 00001h                ; b9 01 00
-    call 04622h                               ; e8 1d fe
+    call 04637h                               ; e8 1d fe
     xor ax, ax                                ; 31 c0
     xor dx, dx                                ; 31 d2
-    jmp near 0492bh                           ; e9 1f 01
+    jmp near 04940h                           ; e9 1f 01
     mov dx, 0032eh                            ; ba 2e 03
     mov ax, word [bp-00eh]                    ; 8b 46 f2
-    call 0161ch                               ; e8 07 ce
+    call 0161ch                               ; e8 f2 cd
     mov di, ax                                ; 89 c7
     shr bx, 008h                              ; c1 eb 08
     mov byte [bp-006h], bl                    ; 88 5e fa
     cmp byte [bp-00ch], 001h                  ; 80 7e f4 01
-    jne near 04899h                           ; 0f 85 74 00
+    jne near 048aeh                           ; 0f 85 74 00
     xor si, si                                ; 31 f6
     mov ax, 0e200h                            ; b8 00 e2
     mov es, ax                                ; 8e c0
     cmp word [es:si], 0aa55h                  ; 26 81 3c 55 aa
-    jne short 047eeh                          ; 75 bb
+    jne short 04803h                          ; 75 bb
     mov cx, ax                                ; 89 c1
     mov si, word [es:si+01ah]                 ; 26 8b 74 1a
     cmp word [es:si+002h], 0506eh             ; 26 81 7c 02 6e 50
-    jne short 047eeh                          ; 75 ad
+    jne short 04803h                          ; 75 ad
     cmp word [es:si], 05024h                  ; 26 81 3c 24 50
-    jne short 047eeh                          ; 75 a6
+    jne short 04803h                          ; 75 a6
     mov di, word [es:si+00eh]                 ; 26 8b 7c 0e
     mov dx, word [es:di]                      ; 26 8b 15
     mov ax, word [es:di+002h]                 ; 26 8b 45 02
     cmp ax, 06568h                            ; 3d 68 65
-    jne short 04877h                          ; 75 1f
+    jne short 0488ch                          ; 75 1f
     cmp dx, 07445h                            ; 81 fa 45 74
-    jne short 04877h                          ; 75 19
+    jne short 0488ch                          ; 75 19
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
-    call 045d7h                               ; e8 6a fd
+    call 045ech                               ; e8 6a fd
     mov word [bp-012h], strict word 00006h    ; c7 46 ee 06 00
     mov word [bp-010h], cx                    ; 89 4e f0
-    jmp short 04893h                          ; eb 1c
+    jmp short 048a8h                          ; eb 1c
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
-    call 045d7h                               ; e8 51 fd
+    call 045ech                               ; e8 51 fd
     sti                                       ; fb
     mov word [bp-010h], cx                    ; 89 4e f0
     mov es, cx                                ; 8e c1
     mov ax, word [es:si+01ah]                 ; 26 8b 44 1a
     mov word [bp-012h], ax                    ; 89 46 ee
     call far [bp-012h]                        ; ff 5e ee
-    jmp near 047eeh                           ; e9 55 ff
+    jmp near 04803h                           ; e9 55 ff
     cmp byte [bp-00ah], 000h                  ; 80 7e f6 00
-    jne short 048c5h                          ; 75 26
+    jne short 048dah                          ; 75 26
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    jne short 048c5h                          ; 75 20
+    jne short 048dah                          ; 75 20
     mov di, 007c0h                            ; bf c0 07
     mov es, di                                ; 8e c7
     mov dl, byte [bp-006h]                    ; 8a 56 fa
@@ -6185,40 +6198,40 @@ _int19_function:                             ; 0xf46dc LB 0x256
     mov ax, strict word 00000h                ; b8 00 00
     sbb ax, strict byte 00000h                ; 83 d8 00
     test ax, ax                               ; 85 c0
-    jne near 047eeh                           ; 0f 85 29 ff
+    jne near 04803h                           ; 0f 85 29 ff
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
     db  00fh, 094h, 0c1h
     ; sete cl                                   ; 0f 94 c1
     cmp byte [bp-00ah], 000h                  ; 80 7e f6 00
-    je short 048d4h                           ; 74 02
+    je short 048e9h                           ; 74 02
     mov CL, strict byte 001h                  ; b1 01
     xor dx, dx                                ; 31 d2
     mov ax, di                                ; 89 f8
-    call 0161ch                               ; e8 41 cd
+    call 0161ch                               ; e8 2c cd
     mov bx, ax                                ; 89 c3
     mov dx, strict word 00002h                ; ba 02 00
     mov ax, di                                ; 89 f8
-    call 0161ch                               ; e8 37 cd
+    call 0161ch                               ; e8 22 cd
     cmp bx, ax                                ; 39 c3
-    je short 048fah                           ; 74 11
+    je short 0490fh                           ; 74 11
     test cl, cl                               ; 84 c9
-    jne short 04910h                          ; 75 23
+    jne short 04925h                          ; 75 23
     mov dx, 001feh                            ; ba fe 01
     mov ax, di                                ; 89 f8
-    call 0161ch                               ; e8 27 cd
+    call 0161ch                               ; e8 12 cd
     cmp ax, 0aa55h                            ; 3d 55 aa
-    je short 04910h                           ; 74 16
+    je short 04925h                           ; 74 16
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     push ax                                   ; 50
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
     xor cx, cx                                ; 31 c9
-    jmp near 04802h                           ; e9 f2 fe
+    jmp near 04817h                           ; e9 f2 fe
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
-    call 045d7h                               ; e8 b8 fc
+    call 045ech                               ; e8 b8 fc
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     xor dx, dx                                ; 31 d2
     xor ax, ax                                ; 31 c0
@@ -6229,18 +6242,18 @@ _int19_function:                             ; 0xf46dc LB 0x256
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-keyboard_panic_:                             ; 0xf4932 LB 0x13
+keyboard_panic_:                             ; 0xf4947 LB 0x13
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push ax                                   ; 50
     push 00554h                               ; 68 54 05
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 cf cf
+    call 01922h                               ; e8 cf cf
     add sp, strict byte 00006h                ; 83 c4 06
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-_keyboard_init:                              ; 0xf4945 LB 0x27c
+_keyboard_init:                              ; 0xf495a LB 0x27c
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov AL, strict byte 0aah                  ; b0 aa
@@ -6252,44 +6265,44 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 04968h                           ; 74 0d
+    je short 0497dh                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04968h                          ; 76 08
+    jbe short 0497dh                          ; 76 08
     xor al, al                                ; 30 c0
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04951h                          ; eb e9
+    jmp short 04966h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04971h                          ; 75 05
+    jne short 04986h                          ; 75 05
     xor ax, ax                                ; 31 c0
-    call 04932h                               ; e8 c1 ff
+    call 04947h                               ; e8 c1 ff
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 0498bh                          ; 75 0d
+    jne short 049a0h                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 0498bh                          ; 76 08
+    jbe short 049a0h                          ; 76 08
     mov AL, strict byte 001h                  ; b0 01
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04974h                          ; eb e9
+    jmp short 04989h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04995h                          ; 75 06
+    jne short 049aah                          ; 75 06
     mov ax, strict word 00001h                ; b8 01 00
-    call 04932h                               ; e8 9d ff
+    call 04947h                               ; e8 9d ff
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, strict word 00055h                ; 3d 55 00
-    je short 049a6h                           ; 74 06
+    je short 049bbh                           ; 74 06
     mov ax, 003dfh                            ; b8 df 03
-    call 04932h                               ; e8 8c ff
+    call 04947h                               ; e8 8c ff
     mov AL, strict byte 0abh                  ; b0 ab
     mov dx, strict word 00064h                ; ba 64 00
     out DX, AL                                ; ee
@@ -6299,44 +6312,44 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 049c6h                           ; 74 0d
+    je short 049dbh                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 049c6h                          ; 76 08
+    jbe short 049dbh                          ; 76 08
     mov AL, strict byte 010h                  ; b0 10
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 049afh                          ; eb e9
+    jmp short 049c4h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 049d0h                          ; 75 06
+    jne short 049e5h                          ; 75 06
     mov ax, strict word 0000ah                ; b8 0a 00
-    call 04932h                               ; e8 62 ff
+    call 04947h                               ; e8 62 ff
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 049eah                          ; 75 0d
+    jne short 049ffh                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 049eah                          ; 76 08
+    jbe short 049ffh                          ; 76 08
     mov AL, strict byte 011h                  ; b0 11
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 049d3h                          ; eb e9
+    jmp short 049e8h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 049f4h                          ; 75 06
+    jne short 04a09h                          ; 75 06
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 04932h                               ; e8 3e ff
+    call 04947h                               ; e8 3e ff
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test ax, ax                               ; 85 c0
-    je short 04a04h                           ; 74 06
+    je short 04a19h                           ; 74 06
     mov ax, 003e0h                            ; b8 e0 03
-    call 04932h                               ; e8 2e ff
+    call 04947h                               ; e8 2e ff
     mov AL, strict byte 0ffh                  ; b0 ff
     mov dx, strict word 00060h                ; ba 60 00
     out DX, AL                                ; ee
@@ -6346,75 +6359,75 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 04a24h                           ; 74 0d
+    je short 04a39h                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04a24h                          ; 76 08
+    jbe short 04a39h                          ; 76 08
     mov AL, strict byte 020h                  ; b0 20
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04a0dh                          ; eb e9
+    jmp short 04a22h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04a2eh                          ; 75 06
+    jne short 04a43h                          ; 75 06
     mov ax, strict word 00014h                ; b8 14 00
-    call 04932h                               ; e8 04 ff
+    call 04947h                               ; e8 04 ff
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 04a48h                          ; 75 0d
+    jne short 04a5dh                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04a48h                          ; 76 08
+    jbe short 04a5dh                          ; 76 08
     mov AL, strict byte 021h                  ; b0 21
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04a31h                          ; eb e9
+    jmp short 04a46h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04a52h                          ; 75 06
+    jne short 04a67h                          ; 75 06
     mov ax, strict word 00015h                ; b8 15 00
-    call 04932h                               ; e8 e0 fe
+    call 04947h                               ; e8 e0 fe
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000fah                            ; 3d fa 00
-    je short 04a63h                           ; 74 06
+    je short 04a78h                           ; 74 06
     mov ax, 003e1h                            ; b8 e1 03
-    call 04932h                               ; e8 cf fe
+    call 04947h                               ; e8 cf fe
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 04a7dh                          ; 75 0d
+    jne short 04a92h                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04a7dh                          ; 76 08
+    jbe short 04a92h                          ; 76 08
     mov AL, strict byte 031h                  ; b0 31
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04a66h                          ; eb e9
+    jmp short 04a7bh                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04a87h                          ; 75 06
+    jne short 04a9ch                          ; 75 06
     mov ax, strict word 0001fh                ; b8 1f 00
-    call 04932h                               ; e8 ab fe
+    call 04947h                               ; e8 ab fe
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000aah                            ; 3d aa 00
-    je short 04aa0h                           ; 74 0e
+    je short 04ab5h                           ; 74 0e
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000aah                            ; 3d aa 00
-    je short 04aa0h                           ; 74 06
+    je short 04ab5h                           ; 74 06
     mov ax, 003e2h                            ; b8 e2 03
-    call 04932h                               ; e8 92 fe
+    call 04947h                               ; e8 92 fe
     mov AL, strict byte 0f5h                  ; b0 f5
     mov dx, strict word 00060h                ; ba 60 00
     out DX, AL                                ; ee
@@ -6424,44 +6437,44 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 04ac0h                           ; 74 0d
+    je short 04ad5h                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04ac0h                          ; 76 08
+    jbe short 04ad5h                          ; 76 08
     mov AL, strict byte 040h                  ; b0 40
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04aa9h                          ; eb e9
+    jmp short 04abeh                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04acah                          ; 75 06
+    jne short 04adfh                          ; 75 06
     mov ax, strict word 00028h                ; b8 28 00
-    call 04932h                               ; e8 68 fe
+    call 04947h                               ; e8 68 fe
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 04ae4h                          ; 75 0d
+    jne short 04af9h                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04ae4h                          ; 76 08
+    jbe short 04af9h                          ; 76 08
     mov AL, strict byte 041h                  ; b0 41
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04acdh                          ; eb e9
+    jmp short 04ae2h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04aeeh                          ; 75 06
+    jne short 04b03h                          ; 75 06
     mov ax, strict word 00029h                ; b8 29 00
-    call 04932h                               ; e8 44 fe
+    call 04947h                               ; e8 44 fe
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000fah                            ; 3d fa 00
-    je short 04affh                           ; 74 06
+    je short 04b14h                           ; 74 06
     mov ax, 003e3h                            ; b8 e3 03
-    call 04932h                               ; e8 33 fe
+    call 04947h                               ; e8 33 fe
     mov AL, strict byte 060h                  ; b0 60
     mov dx, strict word 00064h                ; ba 64 00
     out DX, AL                                ; ee
@@ -6471,18 +6484,18 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 04b1fh                           ; 74 0d
+    je short 04b34h                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04b1fh                          ; 76 08
+    jbe short 04b34h                          ; 76 08
     mov AL, strict byte 050h                  ; b0 50
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04b08h                          ; eb e9
+    jmp short 04b1dh                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04b29h                          ; 75 06
+    jne short 04b3eh                          ; 75 06
     mov ax, strict word 00032h                ; b8 32 00
-    call 04932h                               ; e8 09 fe
+    call 04947h                               ; e8 09 fe
     mov AL, strict byte 065h                  ; b0 65
     mov dx, strict word 00060h                ; ba 60 00
     out DX, AL                                ; ee
@@ -6492,18 +6505,18 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 04b49h                           ; 74 0d
+    je short 04b5eh                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04b49h                          ; 76 08
+    jbe short 04b5eh                          ; 76 08
     mov AL, strict byte 060h                  ; b0 60
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04b32h                          ; eb e9
+    jmp short 04b47h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04b53h                          ; 75 06
+    jne short 04b68h                          ; 75 06
     mov ax, strict word 0003ch                ; b8 3c 00
-    call 04932h                               ; e8 df fd
+    call 04947h                               ; e8 df fd
     mov AL, strict byte 0f4h                  ; b0 f4
     mov dx, strict word 00060h                ; ba 60 00
     out DX, AL                                ; ee
@@ -6513,53 +6526,53 @@ _keyboard_init:                              ; 0xf4945 LB 0x27c
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 04b73h                           ; 74 0d
+    je short 04b88h                           ; 74 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04b73h                          ; 76 08
+    jbe short 04b88h                          ; 76 08
     mov AL, strict byte 070h                  ; b0 70
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04b5ch                          ; eb e9
+    jmp short 04b71h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04b7dh                          ; 75 06
+    jne short 04b92h                          ; 75 06
     mov ax, strict word 00046h                ; b8 46 00
-    call 04932h                               ; e8 b5 fd
+    call 04947h                               ; e8 b5 fd
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 04b97h                          ; 75 0d
+    jne short 04bach                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 04b97h                          ; 76 08
+    jbe short 04bach                          ; 76 08
     mov AL, strict byte 071h                  ; b0 71
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 04b80h                          ; eb e9
+    jmp short 04b95h                          ; eb e9
     test bx, bx                               ; 85 db
-    jne short 04ba1h                          ; 75 06
+    jne short 04bb6h                          ; 75 06
     mov ax, strict word 00046h                ; b8 46 00
-    call 04932h                               ; e8 91 fd
+    call 04947h                               ; e8 91 fd
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000fah                            ; 3d fa 00
-    je short 04bb2h                           ; 74 06
+    je short 04bc7h                           ; 74 06
     mov ax, 003e4h                            ; b8 e4 03
-    call 04932h                               ; e8 80 fd
+    call 04947h                               ; e8 80 fd
     mov AL, strict byte 0a8h                  ; b0 a8
     mov dx, strict word 00064h                ; ba 64 00
     out DX, AL                                ; ee
     xor ax, ax                                ; 31 c0
-    call 05e2ch                               ; e8 6f 12
+    call 05e41h                               ; e8 6f 12
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-enqueue_key_:                                ; 0xf4bc1 LB 0x93
+enqueue_key_:                                ; 0xf4bd6 LB 0x93
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -6571,32 +6584,32 @@ enqueue_key_:                                ; 0xf4bc1 LB 0x93
     mov bl, dl                                ; 88 d3
     mov dx, strict word 0001ah                ; ba 1a 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 45 ca
+    call 0161ch                               ; e8 30 ca
     mov di, ax                                ; 89 c7
     mov dx, strict word 0001ch                ; ba 1c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 3a ca
+    call 0161ch                               ; e8 25 ca
     mov si, ax                                ; 89 c6
     lea cx, [si+002h]                         ; 8d 4c 02
     cmp cx, strict byte 0003eh                ; 83 f9 3e
-    jc short 04befh                           ; 72 03
+    jc short 04c04h                           ; 72 03
     mov cx, strict word 0001eh                ; b9 1e 00
     cmp cx, di                                ; 39 f9
-    jne short 04bf7h                          ; 75 04
+    jne short 04c0ch                          ; 75 04
     xor ax, ax                                ; 31 c0
-    jmp short 04c1ch                          ; eb 25
+    jmp short 04c31h                          ; eb 25
     xor bh, bh                                ; 30 ff
     mov dx, si                                ; 89 f2
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 0d ca
+    call 0160eh                               ; e8 f8 c9
     movzx bx, byte [bp-00ah]                  ; 0f b6 5e f6
     lea dx, [si+001h]                         ; 8d 54 01
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 00 ca
+    call 0160eh                               ; e8 eb c9
     mov bx, cx                                ; 89 cb
     mov dx, strict word 0001ch                ; ba 1c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 11 ca
+    call 0162ah                               ; e8 fc c9
     mov ax, strict word 00001h                ; b8 01 00
     lea sp, [bp-008h]                         ; 8d 66 f8
     pop di                                    ; 5f
@@ -6614,21 +6627,27 @@ enqueue_key_:                                ; 0xf4bc1 LB 0x93
     inc bp                                    ; 45
     cmp bh, byte [bx+si]                      ; 3a 38
     sub bl, byte [ss:di]                      ; 36 2a 1d
-    mov cs, [bp+01bh]                         ; 8e 4e 1b
-    dec bp                                    ; 4d
-    jmp far 09d4ch:0ea4ch                     ; ea 4c ea 4c 9d
+    mov word [0304eh], ax                     ; a3 4e 30
     dec bp                                    ; 4d
-    retn                                      ; c3
+    dec word [si-001h]                        ; ff 4c ff
     dec sp                                    ; 4c
-    cmovle bx, word [bp+04eh]                 ; 0f 4e 5e 4e
-    or word [bp+05ch], 0ea4dh                 ; 81 4e 5c 4d ea
+    mov DL, strict byte 04dh                  ; b2 4d
+    fmul dword [si+024h]                      ; d8 4c 24
+    dec si                                    ; 4e
+    jnc short 04ca7h                          ; 73 4e
+    xchg si, ax                               ; 96
+    dec si                                    ; 4e
+    jno short 04caah                          ; 71 4d
+    dec word [si-001h]                        ; ff 4c ff
     dec sp                                    ; 4c
-    jmp far 0dc4dh:0d64ch                     ; ea 4c d6 4d dc
+    jmp short 04cb0h                          ; eb 4d
+    db  0f1h
     dec sp                                    ; 4c
-    aas                                       ; 3f
+    push sp                                   ; 54
+    dec si                                    ; 4e
+    db  08fh
     dec si                                    ; 4e
-    jp short 04ca2h                           ; 7a 4e
-_int09_function:                             ; 0xf4c54 LB 0x35d
+_int09_function:                             ; 0xf4c69 LB 0x35d
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -6637,56 +6656,56 @@ _int09_function:                             ; 0xf4c54 LB 0x35d
     mov al, byte [bp+014h]                    ; 8a 46 14
     mov byte [bp-00ah], al                    ; 88 46 f6
     test al, al                               ; 84 c0
-    jne short 04c7fh                          ; 75 19
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 04c94h                          ; 75 19
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 5b cc
+    call 018e1h                               ; e8 5b cc
     push 00567h                               ; 68 67 05
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 94 cc
+    call 01922h                               ; e8 94 cc
     add sp, strict byte 00004h                ; 83 c4 04
-    jmp near 04faah                           ; e9 2b 03
+    jmp near 04fbfh                           ; e9 2b 03
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 78 c9
+    call 01600h                               ; e8 63 c9
     mov byte [bp-00eh], al                    ; 88 46 f2
     mov bl, al                                ; 88 c3
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 6a c9
+    call 01600h                               ; e8 55 c9
     mov byte [bp-010h], al                    ; 88 46 f0
     mov byte [bp-00ch], al                    ; 88 46 f4
     mov dx, 00096h                            ; ba 96 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 5b c9
+    call 01600h                               ; e8 46 c9
     mov byte [bp-008h], al                    ; 88 46 f8
     mov byte [bp-006h], al                    ; 88 46 fa
     mov al, byte [bp-00ah]                    ; 8a 46 f6
     push CS                                   ; 0e
     pop ES                                    ; 07
     mov cx, strict word 00010h                ; b9 10 00
-    mov di, 04c25h                            ; bf 25 4c
+    mov di, 04c3ah                            ; bf 3a 4c
     repne scasb                               ; f2 ae
     sal cx, 1                                 ; d1 e1
     mov di, cx                                ; 89 cf
-    mov ax, word [cs:di+04c34h]               ; 2e 8b 85 34 4c
+    mov ax, word [cs:di+04c49h]               ; 2e 8b 85 49 4c
     jmp ax                                    ; ff e0
     xor bl, 040h                              ; 80 f3 40
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 3d c9
+    call 0160eh                               ; e8 28 c9
     or byte [bp-00ch], 040h                   ; 80 4e f4 40
     movzx bx, byte [bp-00ch]                  ; 0f b6 5e f4
-    jmp near 04e52h                           ; e9 76 01
+    jmp near 04e67h                           ; e9 76 01
     mov al, byte [bp-010h]                    ; 8a 46 f0
     and AL, strict byte 0bfh                  ; 24 bf
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
-    jmp near 04e52h                           ; e9 68 01
+    jmp near 04e67h                           ; e9 68 01
     test byte [bp-006h], 002h                 ; f6 46 fa 02
-    jne near 04f8ch                           ; 0f 85 9a 02
+    jne near 04fa1h                           ; 0f 85 9a 02
     mov al, byte [bp-00ah]                    ; 8a 46 f6
     and AL, strict byte 07fh                  ; 24 7f
     cmp AL, strict byte 02ah                  ; 3c 2a
@@ -6695,250 +6714,250 @@ _int09_function:                             ; 0xf4c54 LB 0x35d
     xor ah, ah                                ; 30 e4
     inc ax                                    ; 40
     test byte [bp-00ah], 080h                 ; f6 46 f6 80
-    je short 04d0bh                           ; 74 06
+    je short 04d20h                           ; 74 06
     not al                                    ; f6 d0
     and bl, al                                ; 20 c3
-    jmp short 04d0dh                          ; eb 02
+    jmp short 04d22h                          ; eb 02
     or bl, al                                 ; 08 c3
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 f6 c8
-    jmp near 04f8ch                           ; e9 71 02
+    call 0160eh                               ; e8 e1 c8
+    jmp near 04fa1h                           ; e9 71 02
     test byte [bp-008h], 001h                 ; f6 46 f8 01
-    jne near 04f8ch                           ; 0f 85 69 02
+    jne near 04fa1h                           ; 0f 85 69 02
     or bl, 004h                               ; 80 cb 04
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 dd c8
+    call 0160eh                               ; e8 c8 c8
     mov al, byte [bp-008h]                    ; 8a 46 f8
     test AL, strict byte 002h                 ; a8 02
-    je short 04d45h                           ; 74 0d
+    je short 04d5ah                           ; 74 0d
     or AL, strict byte 004h                   ; 0c 04
     mov byte [bp-006h], al                    ; 88 46 fa
     movzx bx, al                              ; 0f b6 d8
     mov dx, 00096h                            ; ba 96 00
-    jmp short 04d53h                          ; eb 0e
+    jmp short 04d68h                          ; eb 0e
     mov al, byte [bp-010h]                    ; 8a 46 f0
     or AL, strict byte 001h                   ; 0c 01
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 b5 c8
-    jmp near 04f8ch                           ; e9 30 02
+    call 0160eh                               ; e8 a0 c8
+    jmp near 04fa1h                           ; e9 30 02
     test byte [bp-008h], 001h                 ; f6 46 f8 01
-    jne near 04f8ch                           ; 0f 85 28 02
+    jne near 04fa1h                           ; 0f 85 28 02
     and bl, 0fbh                              ; 80 e3 fb
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 9c c8
+    call 0160eh                               ; e8 87 c8
     mov al, byte [bp-008h]                    ; 8a 46 f8
     test AL, strict byte 002h                 ; a8 02
-    je short 04d86h                           ; 74 0d
+    je short 04d9bh                           ; 74 0d
     and AL, strict byte 0fbh                  ; 24 fb
     mov byte [bp-006h], al                    ; 88 46 fa
     movzx bx, al                              ; 0f b6 d8
     mov dx, 00096h                            ; ba 96 00
-    jmp short 04d94h                          ; eb 0e
+    jmp short 04da9h                          ; eb 0e
     mov al, byte [bp-010h]                    ; 8a 46 f0
     and AL, strict byte 0feh                  ; 24 fe
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 74 c8
-    jmp near 04f8ch                           ; e9 ef 01
+    call 0160eh                               ; e8 5f c8
+    jmp near 04fa1h                           ; e9 ef 01
     or bl, 008h                               ; 80 cb 08
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 63 c8
+    call 0160eh                               ; e8 4e c8
     mov al, byte [bp-008h]                    ; 8a 46 f8
     test AL, strict byte 002h                 ; a8 02
-    je short 04dbfh                           ; 74 0d
+    je short 04dd4h                           ; 74 0d
     or AL, strict byte 008h                   ; 0c 08
     mov byte [bp-006h], al                    ; 88 46 fa
     movzx bx, al                              ; 0f b6 d8
     mov dx, 00096h                            ; ba 96 00
-    jmp short 04dcdh                          ; eb 0e
+    jmp short 04de2h                          ; eb 0e
     mov al, byte [bp-010h]                    ; 8a 46 f0
     or AL, strict byte 002h                   ; 0c 02
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 3b c8
-    jmp near 04f8ch                           ; e9 b6 01
+    call 0160eh                               ; e8 26 c8
+    jmp near 04fa1h                           ; e9 b6 01
     and bl, 0f7h                              ; 80 e3 f7
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 2a c8
+    call 0160eh                               ; e8 15 c8
     mov al, byte [bp-008h]                    ; 8a 46 f8
     test AL, strict byte 002h                 ; a8 02
-    je short 04df8h                           ; 74 0d
+    je short 04e0dh                           ; 74 0d
     and AL, strict byte 0f7h                  ; 24 f7
     mov byte [bp-006h], al                    ; 88 46 fa
     movzx bx, al                              ; 0f b6 d8
     mov dx, 00096h                            ; ba 96 00
-    jmp short 04e06h                          ; eb 0e
+    jmp short 04e1bh                          ; eb 0e
     mov al, byte [bp-010h]                    ; 8a 46 f0
     and AL, strict byte 0fdh                  ; 24 fd
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 02 c8
-    jmp near 04f8ch                           ; e9 7d 01
+    call 0160eh                               ; e8 ed c7
+    jmp near 04fa1h                           ; e9 7d 01
     test byte [bp-008h], 003h                 ; f6 46 f8 03
-    jne near 04f8ch                           ; 0f 85 75 01
+    jne near 04fa1h                           ; 0f 85 75 01
     mov al, byte [bp-010h]                    ; 8a 46 f0
     or AL, strict byte 020h                   ; 0c 20
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 e3 c7
+    call 0160eh                               ; e8 ce c7
     mov bl, byte [bp-00eh]                    ; 8a 5e f2
     xor bl, 020h                              ; 80 f3 20
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 d2 c7
-    jmp near 04f8ch                           ; e9 4d 01
+    call 0160eh                               ; e8 bd c7
+    jmp near 04fa1h                           ; e9 4d 01
     test byte [bp-008h], 003h                 ; f6 46 f8 03
-    jne near 04f8ch                           ; 0f 85 45 01
+    jne near 04fa1h                           ; 0f 85 45 01
     mov al, byte [bp-010h]                    ; 8a 46 f0
     and AL, strict byte 0dfh                  ; 24 df
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 b3 c7
-    jmp near 04f8ch                           ; e9 2e 01
+    call 0160eh                               ; e8 9e c7
+    jmp near 04fa1h                           ; e9 2e 01
     mov al, byte [bp-010h]                    ; 8a 46 f0
     or AL, strict byte 010h                   ; 0c 10
     mov byte [bp-00ch], al                    ; 88 46 f4
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 9c c7
+    call 0160eh                               ; e8 87 c7
     mov bl, byte [bp-00eh]                    ; 8a 5e f2
     xor bl, 010h                              ; 80 f3 10
-    jmp short 04e31h                          ; eb b7
+    jmp short 04e46h                          ; eb b7
     mov al, byte [bp-010h]                    ; 8a 46 f0
     and AL, strict byte 0efh                  ; 24 ef
-    jmp short 04e4ch                          ; eb cb
+    jmp short 04e61h                          ; eb cb
     mov al, bl                                ; 88 d8
     and AL, strict byte 00ch                  ; 24 0c
     cmp AL, strict byte 00ch                  ; 3c 0c
-    jne short 04e8eh                          ; 75 05
+    jne short 04ea3h                          ; 75 05
     jmp far 0f000h:0e05bh                     ; ea 5b e0 00 f0
     test byte [bp-00ah], 080h                 ; f6 46 f6 80
-    jne near 04f8ch                           ; 0f 85 f6 00
+    jne near 04fa1h                           ; 0f 85 f6 00
     cmp byte [bp-00ah], 058h                  ; 80 7e f6 58
-    jbe short 04ebah                          ; 76 1e
-    mov bx, 00da2h                            ; bb a2 0d
+    jbe short 04ecfh                          ; 76 1e
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 25 ca
+    call 018e1h                               ; e8 25 ca
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
     push ax                                   ; 50
     push 00581h                               ; 68 81 05
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 59 ca
+    call 01922h                               ; e8 59 ca
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp near 04faah                           ; e9 f0 00
+    jmp near 04fbfh                           ; e9 f0 00
     test bl, 008h                             ; f6 c3 08
-    je short 04ed1h                           ; 74 12
+    je short 04ee6h                           ; 74 12
     movzx si, byte [bp-00ah]                  ; 0f b6 76 f6
     imul si, si, strict byte 0000ah           ; 6b f6 0a
-    mov dl, byte [si+00df6h]                  ; 8a 94 f6 0d
-    mov ax, word [si+00df6h]                  ; 8b 84 f6 0d
-    jmp near 04f5dh                           ; e9 8c 00
+    mov dl, byte [si+00e0eh]                  ; 8a 94 0e 0e
+    mov ax, word [si+00e0eh]                  ; 8b 84 0e 0e
+    jmp near 04f72h                           ; e9 8c 00
     test bl, 004h                             ; f6 c3 04
-    je short 04ee8h                           ; 74 12
+    je short 04efdh                           ; 74 12
     movzx si, byte [bp-00ah]                  ; 0f b6 76 f6
     imul si, si, strict byte 0000ah           ; 6b f6 0a
-    mov dl, byte [si+00df4h]                  ; 8a 94 f4 0d
-    mov ax, word [si+00df4h]                  ; 8b 84 f4 0d
-    jmp near 04f5dh                           ; e9 75 00
+    mov dl, byte [si+00e0ch]                  ; 8a 94 0c 0e
+    mov ax, word [si+00e0ch]                  ; 8b 84 0c 0e
+    jmp near 04f72h                           ; e9 75 00
     mov al, byte [bp-006h]                    ; 8a 46 fa
     and AL, strict byte 002h                  ; 24 02
     test al, al                               ; 84 c0
-    jbe short 04f06h                          ; 76 15
+    jbe short 04f1bh                          ; 76 15
     mov al, byte [bp-00ah]                    ; 8a 46 f6
     cmp AL, strict byte 047h                  ; 3c 47
-    jc short 04f06h                           ; 72 0e
+    jc short 04f1bh                           ; 72 0e
     cmp AL, strict byte 053h                  ; 3c 53
-    jnbe short 04f06h                         ; 77 0a
+    jnbe short 04f1bh                         ; 77 0a
     mov DL, strict byte 0e0h                  ; b2 e0
     movzx si, al                              ; 0f b6 f0
     imul si, si, strict byte 0000ah           ; 6b f6 0a
-    jmp short 04f59h                          ; eb 53
+    jmp short 04f6eh                          ; eb 53
     test bl, 003h                             ; f6 c3 03
-    je short 04f38h                           ; 74 2d
+    je short 04f4dh                           ; 74 2d
     movzx si, byte [bp-00ah]                  ; 0f b6 76 f6
     imul si, si, strict byte 0000ah           ; 6b f6 0a
-    movzx ax, byte [si+00df8h]                ; 0f b6 84 f8 0d
+    movzx ax, byte [si+00e10h]                ; 0f b6 84 10 0e
     movzx dx, bl                              ; 0f b6 d3
     test dx, ax                               ; 85 c2
-    je short 04f28h                           ; 74 0a
-    mov dl, byte [si+00df0h]                  ; 8a 94 f0 0d
-    mov ax, word [si+00df0h]                  ; 8b 84 f0 0d
-    jmp short 04f30h                          ; eb 08
-    mov dl, byte [si+00df2h]                  ; 8a 94 f2 0d
-    mov ax, word [si+00df2h]                  ; 8b 84 f2 0d
+    je short 04f3dh                           ; 74 0a
+    mov dl, byte [si+00e08h]                  ; 8a 94 08 0e
+    mov ax, word [si+00e08h]                  ; 8b 84 08 0e
+    jmp short 04f45h                          ; eb 08
+    mov dl, byte [si+00e0ah]                  ; 8a 94 0a 0e
+    mov ax, word [si+00e0ah]                  ; 8b 84 0a 0e
     shr ax, 008h                              ; c1 e8 08
     mov byte [bp-00ah], al                    ; 88 46 f6
-    jmp short 04f63h                          ; eb 2b
+    jmp short 04f78h                          ; eb 2b
     movzx si, byte [bp-00ah]                  ; 0f b6 76 f6
     imul si, si, strict byte 0000ah           ; 6b f6 0a
-    movzx ax, byte [si+00df8h]                ; 0f b6 84 f8 0d
+    movzx ax, byte [si+00e10h]                ; 0f b6 84 10 0e
     movzx dx, bl                              ; 0f b6 d3
     test dx, ax                               ; 85 c2
-    je short 04f55h                           ; 74 0a
-    mov dl, byte [si+00df2h]                  ; 8a 94 f2 0d
-    mov ax, word [si+00df2h]                  ; 8b 84 f2 0d
-    jmp short 04f5dh                          ; eb 08
-    mov dl, byte [si+00df0h]                  ; 8a 94 f0 0d
-    mov ax, word [si+00df0h]                  ; 8b 84 f0 0d
+    je short 04f6ah                           ; 74 0a
+    mov dl, byte [si+00e0ah]                  ; 8a 94 0a 0e
+    mov ax, word [si+00e0ah]                  ; 8b 84 0a 0e
+    jmp short 04f72h                          ; eb 08
+    mov dl, byte [si+00e08h]                  ; 8a 94 08 0e
+    mov ax, word [si+00e08h]                  ; 8b 84 08 0e
     shr ax, 008h                              ; c1 e8 08
     mov byte [bp-00ah], al                    ; 88 46 f6
     cmp byte [bp-00ah], 000h                  ; 80 7e f6 00
-    jne short 04f83h                          ; 75 1a
+    jne short 04f98h                          ; 75 1a
     test dl, dl                               ; 84 d2
-    jne short 04f83h                          ; 75 16
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 04f98h                          ; 75 16
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 54 c9
+    call 018e1h                               ; e8 54 c9
     push 005b8h                               ; 68 b8 05
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 8d c9
+    call 01922h                               ; e8 8d c9
     add sp, strict byte 00004h                ; 83 c4 04
     xor dh, dh                                ; 30 f6
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
-    call 04bc1h                               ; e8 35 fc
+    call 04bd6h                               ; e8 35 fc
     mov al, byte [bp-00ah]                    ; 8a 46 f6
     and AL, strict byte 07fh                  ; 24 7f
     cmp AL, strict byte 01dh                  ; 3c 1d
-    je short 04f99h                           ; 74 04
+    je short 04faeh                           ; 74 04
     and byte [bp-006h], 0feh                  ; 80 66 fa fe
     and byte [bp-006h], 0fdh                  ; 80 66 fa fd
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     mov dx, 00096h                            ; ba 96 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 64 c6
+    call 0160eh                               ; e8 4f c6
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-dequeue_key_:                                ; 0xf4fb1 LB 0x94
+dequeue_key_:                                ; 0xf4fc6 LB 0x94
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -6951,36 +6970,36 @@ dequeue_key_:                                ; 0xf4fb1 LB 0x94
     mov word [bp-008h], cx                    ; 89 4e f8
     mov dx, strict word 0001ah                ; ba 1a 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 51 c6
+    call 0161ch                               ; e8 3c c6
     mov bx, ax                                ; 89 c3
     mov dx, strict word 0001ch                ; ba 1c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 46 c6
+    call 0161ch                               ; e8 31 c6
     cmp bx, ax                                ; 39 c3
-    je short 05017h                           ; 74 3d
+    je short 0502ch                           ; 74 3d
     mov dx, bx                                ; 89 da
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 1e c6
+    call 01600h                               ; e8 09 c6
     mov cl, al                                ; 88 c1
     lea dx, [bx+001h]                         ; 8d 57 01
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 13 c6
+    call 01600h                               ; e8 fe c5
     mov es, [bp-008h]                         ; 8e 46 f8
     mov byte [es:si], cl                      ; 26 88 0c
     mov es, [bp-006h]                         ; 8e 46 fa
     mov byte [es:di], al                      ; 26 88 05
     cmp word [bp+004h], strict byte 00000h    ; 83 7e 04 00
-    je short 05012h                           ; 74 13
+    je short 05027h                           ; 74 13
     inc bx                                    ; 43
     inc bx                                    ; 43
     cmp bx, strict byte 0003eh                ; 83 fb 3e
-    jc short 05009h                           ; 72 03
+    jc short 0501eh                           ; 72 03
     mov bx, strict word 0001eh                ; bb 1e 00
     mov dx, strict word 0001ah                ; ba 1a 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 18 c6
+    call 0162ah                               ; e8 03 c6
     mov ax, strict word 00001h                ; b8 01 00
-    jmp short 05019h                          ; eb 02
+    jmp short 0502eh                          ; eb 02
     xor ax, ax                                ; 31 c0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
@@ -6991,36 +7010,37 @@ dequeue_key_:                                ; 0xf4fb1 LB 0x94
     adc word [bx+si], dx                      ; 11 10
     or cl, byte [bx+di]                       ; 0a 09
     add ax, 00102h                            ; 05 02 01
-    add bl, ah                                ; 00 e3
+    add al, bh                                ; 00 f8
     push dx                                   ; 52
-    stc                                       ; f9
-    push ax                                   ; 50
-    inc ax                                    ; 40
+    push CS                                   ; 0e
     push cx                                   ; 51
-    mov [bx+di-064h], ss                      ; 8c 51 9c
+    push bp                                   ; 55
     push cx                                   ; 51
-    db  0c6h, 051h, 0cfh, 051h
-    ; mov byte [bx+di-031h], 051h               ; c6 51 cf 51
-    inc ax                                    ; 40
+    mov ax, word [0b151h]                     ; a1 51 b1
+    push cx                                   ; 51
+    fist dword [bx+di-01ch]                   ; db 51 e4
+    push cx                                   ; 51
+    push bp                                   ; 55
+    push dx                                   ; 52
+    xchg byte [bp+si-04dh], dl                ; 86 52 b3
     push dx                                   ; 52
-    jno short 05091h                          ; 71 52
-    sahf                                      ; 9e
+    in ax, DX                                 ; ed
     push dx                                   ; 52
-    fcom dword [bp+si+026h]                   ; d8 52 26
+    db  03bh
     push bx                                   ; 53
-_int16_function:                             ; 0xf5045 LB 0x2e7
+_int16_function:                             ; 0xf505a LB 0x2e7
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push di                                   ; 57
     sub sp, strict byte 00006h                ; 83 ec 06
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 ab c5
+    call 01600h                               ; e8 96 c5
     mov cl, al                                ; 88 c1
     mov bh, al                                ; 88 c7
     mov dx, 00097h                            ; ba 97 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 9e c5
+    call 01600h                               ; e8 89 c5
     mov bl, al                                ; 88 c3
     movzx dx, cl                              ; 0f b6 d1
     sar dx, 004h                              ; c1 fa 04
@@ -7029,7 +7049,7 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     xor ah, ah                                ; 30 e4
     xor al, dl                                ; 30 d0
     test ax, ax                               ; 85 c0
-    je short 050d7h                           ; 74 60
+    je short 050ech                           ; 74 60
     cli                                       ; fa
     mov AL, strict byte 0edh                  ; b0 ed
     mov dx, strict word 00060h                ; ba 60 00
@@ -7039,17 +7059,17 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 05090h                          ; 75 08
+    jne short 050a5h                          ; 75 08
     mov AL, strict byte 021h                  ; b0 21
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 0507eh                          ; eb ee
+    jmp short 05093h                          ; eb ee
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000fah                            ; 3d fa 00
-    jne short 050d6h                          ; 75 3b
+    jne short 050ebh                          ; 75 3b
     and bl, 0f8h                              ; 80 e3 f8
     movzx ax, bh                              ; 0f b6 c7
     sar ax, 004h                              ; c1 f8 04
@@ -7065,11 +7085,11 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 050c5h                          ; 75 08
+    jne short 050dah                          ; 75 08
     mov AL, strict byte 021h                  ; b0 21
     mov dx, 00080h                            ; ba 80 00
     out DX, AL                                ; ee
-    jmp short 050b3h                          ; eb ee
+    jmp short 050c8h                          ; eb ee
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -7077,63 +7097,63 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     xor bh, bh                                ; 30 ff
     mov dx, 00097h                            ; ba 97 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 38 c5
+    call 0160eh                               ; e8 23 c5
     sti                                       ; fb
     mov ax, word [bp+012h]                    ; 8b 46 12
     shr ax, 008h                              ; c1 e8 08
     cmp ax, 000a2h                            ; 3d a2 00
-    jnbe near 052e3h                          ; 0f 87 ff 01
+    jnbe near 052f8h                          ; 0f 87 ff 01
     push CS                                   ; 0e
     pop ES                                    ; 07
     mov cx, strict word 0000ch                ; b9 0c 00
-    mov di, 05022h                            ; bf 22 50
+    mov di, 05037h                            ; bf 37 50
     repne scasb                               ; f2 ae
     sal cx, 1                                 ; d1 e1
     mov di, cx                                ; 89 cf
-    mov ax, word [cs:di+0502dh]               ; 2e 8b 85 2d 50
+    mov ax, word [cs:di+05042h]               ; 2e 8b 85 42 50
     jmp ax                                    ; ff e0
     push strict byte 00001h                   ; 6a 01
     mov cx, ss                                ; 8c d1
     lea bx, [bp-008h]                         ; 8d 5e f8
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 04fb1h                               ; e8 a9 fe
+    call 04fc6h                               ; e8 a9 fe
     test ax, ax                               ; 85 c0
-    jne short 05117h                          ; 75 0b
+    jne short 0512ch                          ; 75 0b
     push 005efh                               ; 68 ef 05
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 f9 c7
+    call 01922h                               ; e8 f9 c7
     add sp, strict byte 00004h                ; 83 c4 04
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
-    je short 05123h                           ; 74 06
+    je short 05138h                           ; 74 06
     cmp byte [bp-008h], 0f0h                  ; 80 7e f8 f0
-    je short 05129h                           ; 74 06
+    je short 0513eh                           ; 74 06
     cmp byte [bp-008h], 0e0h                  ; 80 7e f8 e0
-    jne short 0512dh                          ; 75 04
+    jne short 05142h                          ; 75 04
     mov byte [bp-008h], 000h                  ; c6 46 f8 00
     movzx dx, byte [bp-006h]                  ; 0f b6 56 fa
     sal dx, 008h                              ; c1 e2 08
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     or dx, ax                                 ; 09 c2
     mov word [bp+012h], dx                    ; 89 56 12
-    jmp near 05326h                           ; e9 e6 01
+    jmp near 0533bh                           ; e9 e6 01
     or word [bp+01ch], 00200h                 ; 81 4e 1c 00 02
     push strict byte 00000h                   ; 6a 00
     mov cx, ss                                ; 8c d1
     lea bx, [bp-008h]                         ; 8d 5e f8
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 04fb1h                               ; e8 5d fe
+    call 04fc6h                               ; e8 5d fe
     test ax, ax                               ; 85 c0
-    jne short 0515fh                          ; 75 07
+    jne short 05174h                          ; 75 07
     or word [bp+01ch], strict byte 00040h     ; 83 4e 1c 40
-    jmp near 05326h                           ; e9 c7 01
+    jmp near 0533bh                           ; e9 c7 01
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
-    je short 0516bh                           ; 74 06
+    je short 05180h                           ; 74 06
     cmp byte [bp-008h], 0f0h                  ; 80 7e f8 f0
-    je short 05171h                           ; 74 06
+    je short 05186h                           ; 74 06
     cmp byte [bp-008h], 0e0h                  ; 80 7e f8 e0
-    jne short 05175h                          ; 75 04
+    jne short 0518ah                          ; 75 04
     mov byte [bp-008h], 000h                  ; c6 46 f8 00
     movzx dx, byte [bp-006h]                  ; 0f b6 56 fa
     sal dx, 008h                              ; c1 e2 08
@@ -7141,32 +7161,32 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     or dx, ax                                 ; 09 c2
     mov word [bp+012h], dx                    ; 89 56 12
     and word [bp+01ch], strict byte 0ffbfh    ; 83 66 1c bf
-    jmp near 05326h                           ; e9 9a 01
+    jmp near 0533bh                           ; e9 9a 01
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 6b c4
+    call 01600h                               ; e8 56 c4
     mov dx, word [bp+012h]                    ; 8b 56 12
     mov dl, al                                ; 88 c2
-    jmp short 0513ah                          ; eb 9e
+    jmp short 0514fh                          ; eb 9e
     mov al, byte [bp+010h]                    ; 8a 46 10
     movzx dx, al                              ; 0f b6 d0
     mov ax, word [bp+010h]                    ; 8b 46 10
     shr ax, 008h                              ; c1 e8 08
     xor ah, ah                                ; 30 e4
-    call 04bc1h                               ; e8 14 fa
+    call 04bd6h                               ; e8 14 fa
     test ax, ax                               ; 85 c0
-    jne short 051beh                          ; 75 0d
+    jne short 051d3h                          ; 75 0d
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor al, al                                ; 30 c0
     or AL, strict byte 001h                   ; 0c 01
     mov word [bp+012h], ax                    ; 89 46 12
-    jmp near 05326h                           ; e9 68 01
+    jmp near 0533bh                           ; e9 68 01
     and word [bp+012h], 0ff00h                ; 81 66 12 00 ff
-    jmp near 05326h                           ; e9 60 01
+    jmp near 0533bh                           ; e9 60 01
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor al, al                                ; 30 c0
     or AL, strict byte 030h                   ; 0c 30
-    jmp short 051b8h                          ; eb e9
+    jmp short 051cdh                          ; eb e9
     mov byte [bp-004h], 002h                  ; c6 46 fc 02
     xor cx, cx                                ; 31 c9
     cli                                       ; fa
@@ -7179,40 +7199,40 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 051f6h                          ; 75 0d
+    jne short 0520bh                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 051f6h                          ; 76 08
+    jbe short 0520bh                          ; 76 08
     mov dx, 00080h                            ; ba 80 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
-    jmp short 051dfh                          ; eb e9
+    jmp short 051f4h                          ; eb e9
     test bx, bx                               ; 85 db
-    jbe short 0523ah                          ; 76 40
+    jbe short 0524fh                          ; 76 40
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp ax, 000fah                            ; 3d fa 00
-    jne short 0523ah                          ; 75 35
+    jne short 0524fh                          ; 75 35
     mov bx, strict word 0ffffh                ; bb ff ff
     mov dx, strict word 00064h                ; ba 64 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 0521fh                          ; 75 0d
+    jne short 05234h                          ; 75 0d
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 0521fh                          ; 76 08
+    jbe short 05234h                          ; 76 08
     mov dx, 00080h                            ; ba 80 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
-    jmp short 05208h                          ; eb e9
+    jmp short 0521dh                          ; eb e9
     test bx, bx                               ; 85 db
-    jbe short 05231h                          ; 76 0e
+    jbe short 05246h                          ; 76 0e
     shr cx, 008h                              ; c1 e9 08
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
@@ -7222,80 +7242,80 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     or cx, ax                                 ; 09 c1
     dec byte [bp-004h]                        ; fe 4e fc
     cmp byte [bp-004h], 000h                  ; 80 7e fc 00
-    jnbe short 05205h                         ; 77 cb
+    jnbe short 0521ah                         ; 77 cb
     mov word [bp+00ch], cx                    ; 89 4e 0c
-    jmp near 05326h                           ; e9 e6 00
+    jmp near 0533bh                           ; e9 e6 00
     push strict byte 00001h                   ; 6a 01
     mov cx, ss                                ; 8c d1
     lea bx, [bp-008h]                         ; 8d 5e f8
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 04fb1h                               ; e8 62 fd
+    call 04fc6h                               ; e8 62 fd
     test ax, ax                               ; 85 c0
-    jne short 0525eh                          ; 75 0b
+    jne short 05273h                          ; 75 0b
     push 005efh                               ; 68 ef 05
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 b2 c6
+    call 01922h                               ; e8 b2 c6
     add sp, strict byte 00004h                ; 83 c4 04
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
-    je near 0512dh                            ; 0f 84 c7 fe
+    je near 05142h                            ; 0f 84 c7 fe
     cmp byte [bp-008h], 0f0h                  ; 80 7e f8 f0
-    je near 05129h                            ; 0f 84 bb fe
-    jmp near 0512dh                           ; e9 bc fe
+    je near 0513eh                            ; 0f 84 bb fe
+    jmp near 05142h                           ; e9 bc fe
     or word [bp+01ch], 00200h                 ; 81 4e 1c 00 02
     push strict byte 00000h                   ; 6a 00
     mov cx, ss                                ; 8c d1
     lea bx, [bp-008h]                         ; 8d 5e f8
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 04fb1h                               ; e8 2c fd
+    call 04fc6h                               ; e8 2c fd
     test ax, ax                               ; 85 c0
-    je near 05158h                            ; 0f 84 cd fe
+    je near 0516dh                            ; 0f 84 cd fe
     cmp byte [bp-006h], 000h                  ; 80 7e fa 00
-    je near 05175h                            ; 0f 84 e2 fe
+    je near 0518ah                            ; 0f 84 e2 fe
     cmp byte [bp-008h], 0f0h                  ; 80 7e f8 f0
-    je near 05171h                            ; 0f 84 d6 fe
-    jmp near 05175h                           ; e9 d7 fe
+    je near 05186h                            ; 0f 84 d6 fe
+    jmp near 0518ah                           ; e9 d7 fe
     mov dx, strict word 00017h                ; ba 17 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 59 c3
+    call 01600h                               ; e8 44 c3
     mov dx, word [bp+012h]                    ; 8b 56 12
     mov dl, al                                ; 88 c2
     mov word [bp+012h], dx                    ; 89 56 12
     mov dx, strict word 00018h                ; ba 18 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 48 c3
+    call 01600h                               ; e8 33 c3
     mov bh, al                                ; 88 c7
     and bh, 073h                              ; 80 e7 73
     mov dx, 00096h                            ; ba 96 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 3a c3
+    call 01600h                               ; e8 25 c3
     and AL, strict byte 00ch                  ; 24 0c
     or bh, al                                 ; 08 c7
     mov dx, word [bp+012h]                    ; 8b 56 12
     xor dh, dh                                ; 30 f6
     movzx ax, bh                              ; 0f b6 c7
     sal ax, 008h                              ; c1 e0 08
-    jmp near 05138h                           ; e9 60 fe
+    jmp near 0514dh                           ; e9 60 fe
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     or ah, 080h                               ; 80 cc 80
-    jmp near 051b8h                           ; e9 d5 fe
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 051cdh                           ; e9 d5 fe
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 de c5
+    call 018e1h                               ; e8 de c5
     mov ax, word [bp+012h]                    ; 8b 46 12
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 00613h                               ; 68 13 06
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 10 c6
+    call 01922h                               ; e8 10 c6
     add sp, strict byte 00006h                ; 83 c4 06
-    mov bx, 00da2h                            ; bb a2 0d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 c1 c5
+    call 018e1h                               ; e8 c1 c5
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     push ax                                   ; 50
     mov ax, word [bp+010h]                    ; 8b 46 10
@@ -7306,13 +7326,13 @@ _int16_function:                             ; 0xf5045 LB 0x2e7
     push ax                                   ; 50
     push 0063bh                               ; 68 3b 06
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 ea c5
+    call 01922h                               ; e8 ea c5
     add sp, strict byte 0000ch                ; 83 c4 0c
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop di                                    ; 5f
     pop bp                                    ; 5d
     retn                                      ; c3
-set_geom_lba_:                               ; 0xf532c LB 0x9e
+set_geom_lba_:                               ; 0xf5341 LB 0x9e
     push si                                   ; 56
     push di                                   ; 57
     enter 00004h, 000h                        ; c8 04 00 00
@@ -7324,33 +7344,33 @@ set_geom_lba_:                               ; 0xf532c LB 0x9e
     mov dx, strict word 0007eh                ; ba 7e 00
     mov di, 000ffh                            ; bf ff 00
     xor bx, bx                                ; 31 db
-    jmp short 0534dh                          ; eb 05
+    jmp short 05362h                          ; eb 05
     cmp bx, strict byte 00004h                ; 83 fb 04
-    jnl short 05363h                          ; 7d 16
+    jnl short 05378h                          ; 7d 16
     cmp dx, word [bp-002h]                    ; 3b 56 fe
-    jnbe short 05359h                         ; 77 07
-    jne short 0535ch                          ; 75 08
+    jnbe short 0536eh                         ; 77 07
+    jne short 05371h                          ; 75 08
     cmp ax, word [bp-004h]                    ; 3b 46 fc
-    jc short 0535ch                           ; 72 03
+    jc short 05371h                           ; 72 03
     inc di                                    ; 47
     shr di, 1                                 ; d1 ef
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
     inc bx                                    ; 43
-    jmp short 05348h                          ; eb e5
+    jmp short 0535dh                          ; eb e5
     mov ax, di                                ; 89 f8
     xor dx, dx                                ; 31 d2
     mov bx, strict word 0003fh                ; bb 3f 00
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 3a 40
+    call 09459h                               ; e8 d5 40
     mov bx, ax                                ; 89 c3
     mov cx, dx                                ; 89 d1
     mov ax, word [bp-004h]                    ; 8b 46 fc
     mov dx, word [bp-002h]                    ; 8b 56 fe
-    call 09370h                               ; e8 f4 3f
+    call 09420h                               ; e8 8f 40
     mov word [es:si+002h], ax                 ; 26 89 44 02
     cmp ax, 00400h                            ; 3d 00 04
-    jbe short 0538bh                          ; 76 06
+    jbe short 053a0h                          ; 76 06
     mov word [es:si+002h], 00400h             ; 26 c7 44 02 00 04
     mov word [es:si], di                      ; 26 89 3c
     mov word [es:si+004h], strict word 0003fh ; 26 c7 44 04 3f 00
@@ -7358,65 +7378,57 @@ set_geom_lba_:                               ; 0xf532c LB 0x9e
     pop di                                    ; 5f
     pop si                                    ; 5e
     retn                                      ; c3
+    imul dx, word [si-071h], 0bc54h           ; 69 54 8f 54 bc
     push sp                                   ; 54
+    mov sp, 0bc54h                            ; bc 54 bc
     push sp                                   ; 54
-    jp short 053f0h                           ; 7a 54
-    cmpsw                                     ; a7
-    push sp                                   ; 54
-    cmpsw                                     ; a7
-    push sp                                   ; 54
-    cmpsw                                     ; a7
-    push sp                                   ; 54
-    jnle short 053fah                         ; 7f 56
-    lodsw                                     ; ad
-    push di                                   ; 57
-    lodsw                                     ; ad
-    push di                                   ; 57
-    cbw                                       ; 98
+    xchg sp, ax                               ; 94
     push si                                   ; 56
-    mov dl, byte [bx-053h]                    ; 8a 57 ad
+    retn 0c257h                               ; c2 57 c2
     push di                                   ; 57
     lodsw                                     ; ad
+    push si                                   ; 56
+    lahf                                      ; 9f
     push di                                   ; 57
-    mov dl, byte [bx-076h]                    ; 8a 57 8a
+    retn 0c257h                               ; c2 57 c2
     push di                                   ; 57
-    lodsw                                     ; ad
+    lahf                                      ; 9f
     push di                                   ; 57
-    lodsw                                     ; ad
+    lahf                                      ; 9f
     push di                                   ; 57
-    push CS                                   ; 0e
+    retn 0c257h                               ; c2 57 c2
     push di                                   ; 57
-    mov dl, byte [bx-053h]                    ; 8a 57 ad
+    and dx, word [bx-061h]                    ; 23 57 9f
     push di                                   ; 57
-    lodsw                                     ; ad
+    retn 0c257h                               ; c2 57 c2
     push di                                   ; 57
-    mov dl, byte [bx+03eh]                    ; 8a 57 3e
+    lahf                                      ; 9f
     push di                                   ; 57
-    lodsw                                     ; ad
+    push bx                                   ; 53
     push di                                   ; 57
-    lodsw                                     ; ad
+    retn 0c257h                               ; c2 57 c2
     push di                                   ; 57
-    lodsw                                     ; ad
+    db  0c2h
     push di                                   ; 57
-_int13_harddisk:                             ; 0xf53ca LB 0x441
+_int13_harddisk:                             ; 0xf53df LB 0x441
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     sub sp, strict byte 00010h                ; 83 ec 10
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 43 c2
+    call 0161ch                               ; e8 2e c2
     mov si, 00122h                            ; be 22 01
     mov word [bp-004h], ax                    ; 89 46 fc
     xor bx, bx                                ; 31 db
     mov dx, 0008eh                            ; ba 8e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 24 c2
+    call 0160eh                               ; e8 0f c2
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     xor ah, ah                                ; 30 e4
     cmp ax, 00080h                            ; 3d 80 00
-    jc short 053f9h                           ; 72 05
+    jc short 0540eh                           ; 72 05
     cmp ax, 00090h                            ; 3d 90 00
-    jc short 05417h                           ; 72 1e
+    jc short 0542ch                           ; 72 1e
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     xor ah, ah                                ; 30 e4
     push ax                                   ; 50
@@ -7426,9 +7438,9 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     push 0065eh                               ; 68 5e 06
     push 0066dh                               ; 68 6d 06
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 fc c4
+    call 01922h                               ; e8 fc c4
     add sp, strict byte 0000ah                ; 83 c4 0a
-    jmp near 057c8h                           ; e9 b1 03
+    jmp near 057ddh                           ; e9 b1 03
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     xor ah, ah                                ; 30 e4
     mov es, [bp-004h]                         ; 8e 46 fc
@@ -7437,36 +7449,36 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     mov dl, byte [es:bx+0011fh]               ; 26 8a 97 1f 01
     mov byte [bp-002h], dl                    ; 88 56 fe
     cmp dl, 010h                              ; 80 fa 10
-    jc short 05440h                           ; 72 10
+    jc short 05455h                           ; 72 10
     push ax                                   ; 50
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 0065eh                               ; 68 5e 06
     push 00698h                               ; 68 98 06
-    jmp short 0540ch                          ; eb cc
+    jmp short 05421h                          ; eb cc
     mov bx, word [bp+016h]                    ; 8b 5e 16
     shr bx, 008h                              ; c1 eb 08
     cmp bx, strict byte 00018h                ; 83 fb 18
-    jnbe near 057adh                          ; 0f 87 60 03
+    jnbe near 057c2h                          ; 0f 87 60 03
     add bx, bx                                ; 01 db
-    jmp word [cs:bx+05398h]                   ; 2e ff a7 98 53
+    jmp word [cs:bx+053adh]                   ; 2e ff a7 ad 53
     cmp byte [bp-002h], 008h                  ; 80 7e fe 08
-    jnc near 05463h                           ; 0f 83 07 00
+    jnc near 05478h                           ; 0f 83 07 00
     movzx ax, byte [bp-002h]                  ; 0f b6 46 fe
-    call 01c0ch                               ; e8 a9 c7
+    call 01c21h                               ; e8 a9 c7
     mov byte [bp+017h], 000h                  ; c6 46 17 00
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 9c c1
+    call 0160eh                               ; e8 87 c1
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 7d c1
+    call 01600h                               ; e8 68 c1
     mov cl, al                                ; 88 c1
     mov dx, word [bp+016h]                    ; 8b 56 16
     xor dh, dh                                ; 30 f6
@@ -7477,10 +7489,10 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 6e c1
+    call 0160eh                               ; e8 59 c1
     test cl, cl                               ; 84 c9
-    je short 05467h                           ; 74 c3
-    jmp near 057e4h                           ; e9 3d 03
+    je short 0547ch                           ; 74 c3
+    jmp near 057f9h                           ; e9 3d 03
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     mov word [bp-00ch], ax                    ; 89 46 f4
@@ -7500,22 +7512,22 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     mov word [bp-008h], ax                    ; 89 46 f8
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     cmp ax, 00080h                            ; 3d 80 00
-    jnbe short 054e2h                         ; 77 04
+    jnbe short 054f7h                         ; 77 04
     test ax, ax                               ; 85 c0
-    jne short 05505h                          ; 75 23
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 0551ah                          ; 75 23
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 df c3
+    call 018e1h                               ; e8 df c3
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 0065eh                               ; 68 5e 06
     push 006cah                               ; 68 ca 06
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 0e c4
+    call 01922h                               ; e8 0e c4
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp near 057c8h                           ; e9 c3 02
+    jmp near 057ddh                           ; e9 c3 02
     movzx ax, byte [bp-002h]                  ; 0f b6 46 fe
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov es, [bp-004h]                         ; 8e 46 fc
@@ -7526,16 +7538,16 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     mov dx, word [es:bx+02ah]                 ; 26 8b 57 2a
     mov word [bp-00ah], dx                    ; 89 56 f6
     cmp di, ax                                ; 39 c7
-    jnc short 05532h                          ; 73 0c
+    jnc short 05547h                          ; 73 0c
     cmp cx, word [bp-008h]                    ; 3b 4e f8
-    jbe short 05532h                          ; 76 07
+    jbe short 05547h                          ; 76 07
     mov ax, word [bp-006h]                    ; 8b 46 fa
     cmp ax, dx                                ; 39 d0
-    jbe short 05560h                          ; 76 2e
-    mov bx, 00da2h                            ; bb a2 0d
+    jbe short 05575h                          ; 76 2e
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 8f c3
+    call 018e1h                               ; e8 8f c3
     push dword [bp-008h]                      ; 66 ff 76 f8
     push di                                   ; 57
     mov ax, word [bp+012h]                    ; 8b 46 12
@@ -7547,36 +7559,36 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     push 0065eh                               ; 68 5e 06
     push 006f2h                               ; 68 f2 06
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 b3 c3
+    call 01922h                               ; e8 b3 c3
     add sp, strict byte 00010h                ; 83 c4 10
-    jmp near 057c8h                           ; e9 68 02
+    jmp near 057ddh                           ; e9 68 02
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     cmp ax, strict word 00004h                ; 3d 04 00
-    jne short 0556eh                          ; 75 03
-    jmp near 05463h                           ; e9 f5 fe
+    jne short 05583h                          ; 75 03
+    jmp near 05478h                           ; e9 f5 fe
     movzx bx, byte [bp-002h]                  ; 0f b6 5e fe
     imul bx, bx, strict byte 00018h           ; 6b db 18
     mov es, [bp-004h]                         ; 8e 46 fc
     add bx, si                                ; 01 f3
     cmp cx, word [es:bx+02ch]                 ; 26 3b 4f 2c
-    jne short 0558fh                          ; 75 0f
+    jne short 055a4h                          ; 75 0f
     mov ax, word [es:bx+030h]                 ; 26 8b 47 30
     cmp ax, word [bp-00ah]                    ; 3b 46 f6
-    jne short 0558fh                          ; 75 06
+    jne short 055a4h                          ; 75 06
     cmp byte [bp-002h], 008h                  ; 80 7e fe 08
-    jc short 055bfh                           ; 72 30
+    jc short 055d4h                           ; 72 30
     mov ax, di                                ; 89 f8
     xor dx, dx                                ; 31 d2
     mov bx, cx                                ; 89 cb
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 0f 3e
+    call 09459h                               ; e8 aa 3e
     xor bx, bx                                ; 31 db
     add ax, word [bp-008h]                    ; 03 46 f8
     adc dx, bx                                ; 11 da
     mov bx, word [bp-00ah]                    ; 8b 5e f6
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 00 3e
+    call 09459h                               ; e8 9b 3e
     xor bx, bx                                ; 31 db
     add ax, word [bp-006h]                    ; 03 46 fa
     adc dx, bx                                ; 11 da
@@ -7629,11 +7641,11 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     or bx, ax                                 ; 09 c3
     mov word [bp+016h], bx                    ; 89 5e 16
     test dl, dl                               ; 84 d2
-    je near 05463h                            ; 0f 84 13 fe
-    mov bx, 00da2h                            ; bb a2 0d
+    je near 05478h                            ; 0f 84 13 fe
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 71 c2
+    call 018e1h                               ; e8 71 c2
     movzx ax, dl                              ; 0f b6 c2
     push ax                                   ; 50
     mov ax, word [bp+016h]                    ; 8b 46 16
@@ -7642,21 +7654,21 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     push 0065eh                               ; 68 5e 06
     push 00739h                               ; 68 39 07
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 9c c2
+    call 01922h                               ; e8 9c c2
     add sp, strict byte 0000ah                ; 83 c4 0a
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 00ch                               ; 80 cc 0c
-    jmp near 057d0h                           ; e9 51 01
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 057e5h                           ; e9 51 01
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 42 c2
+    call 018e1h                               ; e8 42 c2
     push 0075ah                               ; 68 5a 07
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 7b c2
+    call 01922h                               ; e8 7b c2
     add sp, strict byte 00004h                ; 83 c4 04
-    jmp near 05463h                           ; e9 cb fd
+    jmp near 05478h                           ; e9 cb fd
     movzx ax, byte [bp-002h]                  ; 0f b6 46 fe
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov es, [bp-004h]                         ; 8e 46 fc
@@ -7699,7 +7711,7 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     or dx, ax                                 ; 09 c2
     mov word [bp+012h], dx                    ; 89 56 12
-    jmp near 05463h                           ; e9 55 fd
+    jmp near 05478h                           ; e9 55 fd
     movzx ax, byte [bp-002h]                  ; 0f b6 46 fe
     cwd                                       ; 99
     db  02bh, 0c2h
@@ -7715,12 +7727,12 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 0c0h                  ; 24 c0
     cmp AL, strict byte 040h                  ; 3c 40
-    jne short 05733h                          ; 75 03
-    jmp near 05463h                           ; e9 30 fd
+    jne short 05748h                          ; 75 03
+    jmp near 05478h                           ; e9 30 fd
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 0aah                               ; 80 cc aa
-    jmp near 057d0h                           ; e9 92 00
+    jmp near 057e5h                           ; e9 92 00
     movzx ax, byte [bp-002h]                  ; 0f b6 46 fe
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov es, [bp-004h]                         ; 8e 46 fc
@@ -7734,10 +7746,10 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     xor dx, dx                                ; 31 d2
     mov bx, word [bp-008h]                    ; 8b 5e f8
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 41 3c
+    call 09459h                               ; e8 dc 3c
     mov bx, word [bp-006h]                    ; 8b 5e fa
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 39 3c
+    call 09459h                               ; e8 d4 3c
     mov word [bp-010h], ax                    ; 89 46 f0
     mov word [bp-00eh], dx                    ; 89 56 f2
     mov word [bp+014h], dx                    ; 89 56 14
@@ -7746,30 +7758,30 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     xor ah, ah                                ; 30 e4
     or ah, 003h                               ; 80 cc 03
     mov word [bp+016h], ax                    ; 89 46 16
-    jmp near 05467h                           ; e9 dd fc
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 0547ch                           ; e9 dd fc
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 37 c1
+    call 018e1h                               ; e8 37 c1
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 0065eh                               ; 68 5e 06
     push 00774h                               ; 68 74 07
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 66 c1
+    call 01922h                               ; e8 66 c1
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp near 05463h                           ; e9 b6 fc
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 05478h                           ; e9 b6 fc
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 14 c1
+    call 018e1h                               ; e8 14 c1
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 0065eh                               ; 68 5e 06
     push 007a7h                               ; 68 a7 07
-    jmp near 054fah                           ; e9 32 fd
+    jmp near 0550fh                           ; e9 32 fd
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
@@ -7779,52 +7791,48 @@ _int13_harddisk:                             ; 0xf53ca LB 0x441
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 2a be
+    call 0160eh                               ; e8 15 be
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
-    jmp near 05476h                           ; e9 8b fc
-    cmpsb                                     ; a6
+    jmp near 0548bh                           ; e9 8b fc
+    mov bx, 0d358h                            ; bb 58 d3
     pop ax                                    ; 58
-    mov si, 0be58h                            ; be 58 be
+    rcr word [bx+si-02dh], CL                 ; d3 58 d3
     pop ax                                    ; 58
-    mov si, 06d58h                            ; be 58 6d
-    pop sp                                    ; 5c
-    add word [bp+si-042h], bx                 ; 01 5a be
-    pop ax                                    ; 58
-    pop ES                                    ; 07
+    db  082h, 05ch, 016h, 05ah
+    ; sbb byte [si+016h], 05ah                  ; 82 5c 16 5a
+    rcr word [bx+si+01ch], CL                 ; d3 58 1c
     pop dx                                    ; 5a
-    insw                                      ; 6d
-    pop sp                                    ; 5c
-    mov sp, 0bc5ch                            ; bc 5c bc
+    db  082h, 05ch, 0d1h, 05ch
+    ; sbb byte [si-02fh], 05ch                  ; 82 5c d1 5c
+    rcr word [si-02fh], 1                     ; d1 5c d1
     pop sp                                    ; 5c
-    mov sp, 0bc5ch                            ; bc 5c bc
+    rcr word [si-067h], 1                     ; d1 5c 99
     pop sp                                    ; 5c
-    test byte [si-044h], bl                   ; 84 5c bc
+    rcr word [si-02fh], 1                     ; d1 5c d1
     pop sp                                    ; 5c
-    db  0bch
-    pop sp                                    ; 5c
-_int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
+_int13_harddisk_ext:                         ; 0xf5820 LB 0x4cc
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     sub sp, strict byte 00028h                ; 83 ec 28
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 02 be
+    call 0161ch                               ; e8 ed bd
     mov word [bp-014h], ax                    ; 89 46 ec
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 f6 bd
+    call 0161ch                               ; e8 e1 bd
     mov si, 00122h                            ; be 22 01
     mov word [bp-026h], ax                    ; 89 46 da
     xor bx, bx                                ; 31 db
     mov dx, 0008eh                            ; ba 8e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 d7 bd
+    call 0160eh                               ; e8 c2 bd
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     xor ah, ah                                ; 30 e4
     cmp ax, 00080h                            ; 3d 80 00
-    jc short 05846h                           ; 72 05
+    jc short 0585bh                           ; 72 05
     cmp ax, 00090h                            ; 3d 90 00
-    jc short 05864h                           ; 72 1e
+    jc short 05879h                           ; 72 1e
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     xor ah, ah                                ; 30 e4
     push ax                                   ; 50
@@ -7834,9 +7842,9 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     push 007d5h                               ; 68 d5 07
     push 0066dh                               ; 68 6d 06
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 af c0
+    call 01922h                               ; e8 af c0
     add sp, strict byte 0000ah                ; 83 c4 0a
-    jmp near 05c9ah                           ; e9 36 04
+    jmp near 05cafh                           ; e9 36 04
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     xor ah, ah                                ; 30 e4
     mov es, [bp-026h]                         ; 8e 46 da
@@ -7844,30 +7852,30 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     add bx, ax                                ; 01 c3
     mov cl, byte [es:bx+0011fh]               ; 26 8a 8f 1f 01
     cmp cl, 010h                              ; 80 f9 10
-    jc short 0588ah                           ; 72 10
+    jc short 0589fh                           ; 72 10
     push ax                                   ; 50
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 007d5h                               ; 68 d5 07
     push 00698h                               ; 68 98 06
-    jmp short 05859h                          ; eb cf
+    jmp short 0586eh                          ; eb cf
     mov bx, word [bp+016h]                    ; 8b 5e 16
     shr bx, 008h                              ; c1 eb 08
     sub bx, strict byte 00041h                ; 83 eb 41
     cmp bx, strict byte 0000fh                ; 83 fb 0f
-    jnbe near 05cbch                          ; 0f 87 22 04
+    jnbe near 05cd1h                          ; 0f 87 22 04
     add bx, bx                                ; 01 db
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
-    jmp word [cs:bx+057ebh]                   ; 2e ff a7 eb 57
+    jmp word [cs:bx+05800h]                   ; 2e ff a7 00 58
     mov word [bp+010h], 0aa55h                ; c7 46 10 55 aa
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 030h                               ; 80 cc 30
     mov word [bp+016h], ax                    ; 89 46 16
     mov word [bp+014h], strict word 00007h    ; c7 46 14 07 00
-    jmp near 05c71h                           ; e9 b3 03
+    jmp near 05c86h                           ; e9 b3 03
     mov bx, word [bp+00ah]                    ; 8b 5e 0a
     mov es, [bp+004h]                         ; 8e 46 04
     mov di, bx                                ; 89 df
@@ -7882,14 +7890,14 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     mov word [bp-00ah], ax                    ; 89 46 f6
     mov ax, word [es:bx+00eh]                 ; 26 8b 47 0e
     or ax, word [bp-00ah]                     ; 0b 46 f6
-    je short 058ffh                           ; 74 11
+    je short 05914h                           ; 74 11
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 007d5h                               ; 68 d5 07
     push 007e8h                               ; 68 e8 07
     push strict byte 00007h                   ; 6a 07
-    jmp short 05949h                          ; eb 4a
+    jmp short 0595eh                          ; eb 4a
     mov es, [bp-010h]                         ; 8e 46 f0
     mov ax, word [es:di+008h]                 ; 26 8b 45 08
     mov word [bp-00ah], ax                    ; 89 46 f6
@@ -7901,31 +7909,31 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     add bx, dx                                ; 01 d3
     mov ch, byte [es:bx+01eh]                 ; 26 8a 6f 1e
     cmp ax, word [es:bx+034h]                 ; 26 3b 47 34
-    jnbe short 0592fh                         ; 77 0b
-    jne short 05952h                          ; 75 2c
+    jnbe short 05944h                         ; 77 0b
+    jne short 05967h                          ; 75 2c
     mov dx, word [bp-00ah]                    ; 8b 56 f6
     cmp dx, word [es:bx+032h]                 ; 26 3b 57 32
-    jc short 05952h                           ; 72 23
-    mov bx, 00da2h                            ; bb a2 0d
+    jc short 05967h                           ; 72 23
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 92 bf
+    call 018e1h                               ; e8 92 bf
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 007d5h                               ; 68 d5 07
     push 00811h                               ; 68 11 08
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 c1 bf
+    call 01922h                               ; e8 c1 bf
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp near 05c9ah                           ; e9 48 03
+    jmp near 05cafh                           ; e9 48 03
     mov dx, word [bp+016h]                    ; 8b 56 16
     shr dx, 008h                              ; c1 ea 08
     mov word [bp-00ch], dx                    ; 89 56 f4
     cmp dx, strict byte 00044h                ; 83 fa 44
-    je near 05c6dh                            ; 0f 84 0b 03
+    je near 05c82h                            ; 0f 84 0b 03
     cmp dx, strict byte 00047h                ; 83 fa 47
-    je near 05c6dh                            ; 0f 84 04 03
+    je near 05c82h                            ; 0f 84 04 03
     mov es, [bp-026h]                         ; 8e 46 da
     db  066h, 026h, 0c7h, 044h, 014h, 000h, 000h, 000h, 000h
     ; mov dword [es:si+014h], strict dword 000000000h ; 66 26 c7 44 14 00 00 00 00
@@ -7957,25 +7965,25 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     mov es, [bp-010h]                         ; 8e 46 f0
     mov word [es:di+002h], ax                 ; 26 89 45 02
     test dl, dl                               ; 84 d2
-    je near 05c6dh                            ; 0f 84 97 02
-    mov bx, 00da2h                            ; bb a2 0d
+    je near 05c82h                            ; 0f 84 97 02
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 eb be
+    call 018e1h                               ; e8 eb be
     movzx ax, dl                              ; 0f b6 c2
     push ax                                   ; 50
     push word [bp-00ch]                       ; ff 76 f4
     push 007d5h                               ; 68 d5 07
     push 00739h                               ; 68 39 07
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 1a bf
+    call 01922h                               ; e8 1a bf
     add sp, strict byte 0000ah                ; 83 c4 0a
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 00ch                               ; 80 cc 0c
-    jmp near 05ca2h                           ; e9 a1 02
+    jmp near 05cb7h                           ; e9 a1 02
     or ah, 0b2h                               ; 80 cc b2
-    jmp near 05ca2h                           ; e9 9b 02
+    jmp near 05cb7h                           ; e9 9b 02
     mov bx, word [bp+00ah]                    ; 8b 5e 0a
     mov ax, word [bp+004h]                    ; 8b 46 04
     mov word [bp-006h], ax                    ; 89 46 fa
@@ -7985,8 +7993,8 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     mov ax, word [es:di]                      ; 26 8b 05
     mov word [bp-00eh], ax                    ; 89 46 f2
     cmp ax, strict word 0001ah                ; 3d 1a 00
-    jc near 05c9ah                            ; 0f 82 76 02
-    jc near 05aabh                            ; 0f 82 83 00
+    jc near 05cafh                            ; 0f 82 76 02
+    jc near 05ac0h                            ; 0f 82 83 00
     movzx ax, cl                              ; 0f b6 c1
     imul ax, ax, strict byte 00018h           ; 6b c0 18
     mov es, [bp-026h]                         ; 8e 46 da
@@ -8024,7 +8032,7 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     db  066h, 026h, 0c7h, 045h, 014h, 000h, 000h, 000h, 000h
     ; mov dword [es:di+014h], strict dword 000000000h ; 66 26 c7 45 14 00 00 00 00
     cmp word [bp-00eh], strict byte 0001eh    ; 83 7e f2 1e
-    jc near 05bb7h                            ; 0f 82 04 01
+    jc near 05bcch                            ; 0f 82 04 01
     mov es, [bp-004h]                         ; 8e 46 fc
     mov word [es:bx], strict word 0001eh      ; 26 c7 07 1e 00
     mov ax, word [bp-014h]                    ; 8b 46 ec
@@ -8050,9 +8058,9 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     mov ah, byte [es:di+022h]                 ; 26 8a 65 22
     mov al, byte [es:di+023h]                 ; 26 8a 45 23
     test al, al                               ; 84 c0
-    jne short 05b09h                          ; 75 04
+    jne short 05b1eh                          ; 75 04
     xor dx, dx                                ; 31 d2
-    jmp short 05b0ch                          ; eb 03
+    jmp short 05b21h                          ; eb 03
     mov dx, strict word 00008h                ; ba 08 00
     or dl, 010h                               ; 80 ca 10
     mov word [bp-008h], dx                    ; 89 56 f8
@@ -8067,9 +8075,9 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     movzx dx, ah                              ; 0f b6 d4
     or word [bp-008h], dx                     ; 09 56 f8
     cmp AL, strict byte 003h                  ; 3c 03
-    jne short 05b32h                          ; 75 05
+    jne short 05b47h                          ; 75 05
     mov ax, strict word 00003h                ; b8 03 00
-    jmp short 05b34h                          ; eb 02
+    jmp short 05b49h                          ; eb 02
     xor ax, ax                                ; 31 c0
     or word [bp-008h], ax                     ; 09 46 f8
     mov ax, word [bp-01ah]                    ; 8b 46 e6
@@ -8094,21 +8102,21 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     mov byte [es:si+001feh], 011h             ; 26 c6 84 fe 01 11
     xor ch, ch                                ; 30 ed
     mov byte [bp-002h], ch                    ; 88 6e fe
-    jmp short 05b98h                          ; eb 06
+    jmp short 05badh                          ; eb 06
     cmp byte [bp-002h], 00fh                  ; 80 7e fe 0f
-    jnc short 05badh                          ; 73 15
+    jnc short 05bc2h                          ; 73 15
     movzx dx, byte [bp-002h]                  ; 0f b6 56 fe
     add dx, 00312h                            ; 81 c2 12 03
     mov ax, word [bp-014h]                    ; 8b 46 ec
-    call 01600h                               ; e8 5a ba
+    call 01600h                               ; e8 45 ba
     add ch, al                                ; 00 c5
     inc byte [bp-002h]                        ; fe 46 fe
-    jmp short 05b92h                          ; eb e5
+    jmp short 05ba7h                          ; eb e5
     neg ch                                    ; f6 dd
     mov es, [bp-026h]                         ; 8e 46 da
     mov byte [es:si+001ffh], ch               ; 26 88 ac ff 01
     cmp word [bp-00eh], strict byte 00042h    ; 83 7e f2 42
-    jc near 05c6dh                            ; 0f 82 ae 00
+    jc near 05c82h                            ; 0f 82 ae 00
     movzx ax, cl                              ; 0f b6 c1
     cwd                                       ; 99
     db  02bh, 0c2h
@@ -8126,7 +8134,7 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     ; mov dword [es:bx+01eh], strict dword 00024beddh ; 66 26 c7 47 1e dd be 24 00
     mov word [es:bx+022h], strict word 00000h ; 26 c7 47 22 00 00
     test al, al                               ; 84 c0
-    jne short 05bffh                          ; 75 09
+    jne short 05c14h                          ; 75 09
     db  066h, 026h, 0c7h, 047h, 024h, 049h, 053h, 041h, 020h
     ; mov dword [es:bx+024h], strict dword 020415349h ; 66 26 c7 47 24 49 53 41 20
     mov es, [bp-004h]                         ; 8e 46 fc
@@ -8135,7 +8143,7 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     db  066h, 026h, 0c7h, 047h, 02ch, 020h, 020h, 020h, 020h
     ; mov dword [es:bx+02ch], strict dword 020202020h ; 66 26 c7 47 2c 20 20 20 20
     test al, al                               ; 84 c0
-    jne short 05c2bh                          ; 75 13
+    jne short 05c40h                          ; 75 13
     mov word [es:bx+030h], dx                 ; 26 89 57 30
     db  066h, 026h, 0c7h, 047h, 032h, 000h, 000h, 000h, 000h
     ; mov dword [es:bx+032h], strict dword 000000000h ; 66 26 c7 47 32 00 00 00 00
@@ -8150,17 +8158,17 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     mov word [es:bx+03eh], strict word 00000h ; 26 c7 47 3e 00 00
     xor cl, cl                                ; 30 c9
     mov CH, strict byte 01eh                  ; b5 1e
-    jmp short 05c52h                          ; eb 05
+    jmp short 05c67h                          ; eb 05
     cmp ch, 040h                              ; 80 fd 40
-    jnc short 05c64h                          ; 73 12
+    jnc short 05c79h                          ; 73 12
     movzx dx, ch                              ; 0f b6 d5
     add dx, word [bp+00ah]                    ; 03 56 0a
     mov ax, word [bp+004h]                    ; 8b 46 04
-    call 01600h                               ; e8 a2 b9
+    call 01600h                               ; e8 8d b9
     add cl, al                                ; 00 c1
     db  0feh, 0c5h
     ; inc ch                                    ; fe c5
-    jmp short 05c4dh                          ; eb e9
+    jmp short 05c62h                          ; eb e9
     neg cl                                    ; f6 d9
     mov es, [bp-004h]                         ; 8e 46 fc
     mov byte [es:bx+041h], cl                 ; 26 88 4f 41
@@ -8168,20 +8176,20 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     xor bx, bx                                ; 31 db
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 92 b9
+    call 0160eh                               ; e8 7d b9
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
     cmp ax, strict word 00006h                ; 3d 06 00
-    je short 05c6dh                           ; 74 e4
+    je short 05c82h                           ; 74 e4
     cmp ax, strict word 00001h                ; 3d 01 00
-    jc short 05c9ah                           ; 72 0c
-    jbe short 05c6dh                          ; 76 dd
+    jc short 05cafh                           ; 72 0c
+    jbe short 05c82h                          ; 76 dd
     cmp ax, strict word 00003h                ; 3d 03 00
-    jc short 05c9ah                           ; 72 05
+    jc short 05cafh                           ; 72 05
     cmp ax, strict word 00004h                ; 3d 04 00
-    jbe short 05c6dh                          ; 76 d3
+    jbe short 05c82h                          ; 76 d3
     mov ax, word [bp+016h]                    ; 8b 46 16
     xor ah, ah                                ; 30 e4
     or ah, 001h                               ; 80 cc 01
@@ -8191,20 +8199,20 @@ _int13_harddisk_ext:                         ; 0xf580b LB 0x4cc
     xor bh, bh                                ; 30 ff
     mov dx, strict word 00074h                ; ba 74 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 58 b9
+    call 0160eh                               ; e8 43 b9
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
-    jmp short 05c80h                          ; eb c4
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp short 05c95h                          ; eb c4
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 05 bc
+    call 018e1h                               ; e8 05 bc
     mov ax, word [bp+016h]                    ; 8b 46 16
     shr ax, 008h                              ; c1 e8 08
     push ax                                   ; 50
     push 007d5h                               ; 68 d5 07
     push 007a7h                               ; 68 a7 07
-    jmp near 05947h                           ; e9 70 fc
-_int14_function:                             ; 0xf5cd7 LB 0x155
+    jmp near 0595ch                           ; e9 70 fc
+_int14_function:                             ; 0xf5cec LB 0x155
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -8212,29 +8220,29 @@ _int14_function:                             ; 0xf5cd7 LB 0x155
     mov dx, word [bp+00eh]                    ; 8b 56 0e
     add dx, dx                                ; 01 d2
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 35 b9
+    call 0161ch                               ; e8 20 b9
     mov si, ax                                ; 89 c6
     mov bx, ax                                ; 89 c3
     mov dx, word [bp+00eh]                    ; 8b 56 0e
     add dx, strict byte 0007ch                ; 83 c2 7c
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 09 b9
+    call 01600h                               ; e8 f4 b8
     mov cl, al                                ; 88 c1
     cmp word [bp+00eh], strict byte 00004h    ; 83 7e 0e 04
-    jnc near 05e22h                           ; 0f 83 21 01
+    jnc near 05e37h                           ; 0f 83 21 01
     test si, si                               ; 85 f6
-    jbe near 05e22h                           ; 0f 86 1b 01
+    jbe near 05e37h                           ; 0f 86 1b 01
     mov al, byte [bp+013h]                    ; 8a 46 13
     cmp AL, strict byte 001h                  ; 3c 01
-    jc short 05d1fh                           ; 72 11
-    jbe short 05d73h                          ; 76 63
+    jc short 05d34h                           ; 72 11
+    jbe short 05d88h                          ; 76 63
     cmp AL, strict byte 003h                  ; 3c 03
-    je near 05e0bh                            ; 0f 84 f5 00
+    je near 05e20h                            ; 0f 84 f5 00
     cmp AL, strict byte 002h                  ; 3c 02
-    je near 05dc1h                            ; 0f 84 a5 00
-    jmp near 05e1ch                           ; e9 fd 00
+    je near 05dd6h                            ; 0f 84 a5 00
+    jmp near 05e31h                           ; e9 fd 00
     test al, al                               ; 84 c0
-    jne near 05e1ch                           ; 0f 85 f7 00
+    jne near 05e31h                           ; 0f 85 f7 00
     lea dx, [bx+003h]                         ; 8d 57 03
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -8266,17 +8274,17 @@ _int14_function:                             ; 0xf5cd7 LB 0x155
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     mov byte [bp+012h], al                    ; 88 46 12
-    jmp near 05dfdh                           ; e9 97 00
+    jmp near 05e12h                           ; e9 97 00
     mov AL, strict byte 017h                  ; b0 17
     mov dx, bx                                ; 89 da
     out DX, AL                                ; ee
     lea dx, [bx+001h]                         ; 8d 57 01
     mov AL, strict byte 004h                  ; b0 04
     out DX, AL                                ; ee
-    jmp short 05d48h                          ; eb d5
+    jmp short 05d5dh                          ; eb d5
     mov dx, strict word 0006ch                ; ba 6c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 a0 b8
+    call 0161ch                               ; e8 8b b8
     mov si, ax                                ; 89 c6
     lea dx, [bx+005h]                         ; 8d 57 05
     in AL, DX                                 ; ec
@@ -8284,20 +8292,20 @@ _int14_function:                             ; 0xf5cd7 LB 0x155
     ; sub ah, ah                                ; 2a e4
     and ax, strict word 00060h                ; 25 60 00
     cmp ax, strict word 00060h                ; 3d 60 00
-    je short 05da3h                           ; 74 17
+    je short 05db8h                           ; 74 17
     test cl, cl                               ; 84 c9
-    je short 05da3h                           ; 74 13
+    je short 05db8h                           ; 74 13
     mov dx, strict word 0006ch                ; ba 6c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 83 b8
+    call 0161ch                               ; e8 6e b8
     cmp ax, si                                ; 39 f0
-    je short 05d7eh                           ; 74 e1
+    je short 05d93h                           ; 74 e1
     mov si, ax                                ; 89 c6
     db  0feh, 0c9h
     ; dec cl                                    ; fe c9
-    jmp short 05d7eh                          ; eb db
+    jmp short 05d93h                          ; eb db
     test cl, cl                               ; 84 c9
-    je short 05dadh                           ; 74 06
+    je short 05dc2h                           ; 74 06
     mov al, byte [bp+012h]                    ; 8a 46 12
     mov dx, bx                                ; 89 da
     out DX, AL                                ; ee
@@ -8307,33 +8315,33 @@ _int14_function:                             ; 0xf5cd7 LB 0x155
     ; sub ah, ah                                ; 2a e4
     mov byte [bp+013h], al                    ; 88 46 13
     test cl, cl                               ; 84 c9
-    jne short 05dfdh                          ; 75 43
+    jne short 05e12h                          ; 75 43
     or AL, strict byte 080h                   ; 0c 80
     mov byte [bp+013h], al                    ; 88 46 13
-    jmp short 05dfdh                          ; eb 3c
+    jmp short 05e12h                          ; eb 3c
     mov dx, strict word 0006ch                ; ba 6c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 52 b8
+    call 0161ch                               ; e8 3d b8
     mov si, ax                                ; 89 c6
     lea dx, [bx+005h]                         ; 8d 57 05
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 05dedh                          ; 75 17
+    jne short 05e02h                          ; 75 17
     test cl, cl                               ; 84 c9
-    je short 05dedh                           ; 74 13
+    je short 05e02h                           ; 74 13
     mov dx, strict word 0006ch                ; ba 6c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 39 b8
+    call 0161ch                               ; e8 24 b8
     cmp ax, si                                ; 39 f0
-    je short 05dcch                           ; 74 e5
+    je short 05de1h                           ; 74 e5
     mov si, ax                                ; 89 c6
     db  0feh, 0c9h
     ; dec cl                                    ; fe c9
-    jmp short 05dcch                          ; eb df
+    jmp short 05de1h                          ; eb df
     test cl, cl                               ; 84 c9
-    je short 05e03h                           ; 74 12
+    je short 05e18h                           ; 74 12
     mov byte [bp+013h], 000h                  ; c6 46 13 00
     mov dx, bx                                ; 89 da
     in AL, DX                                 ; ec
@@ -8341,12 +8349,12 @@ _int14_function:                             ; 0xf5cd7 LB 0x155
     ; sub ah, ah                                ; 2a e4
     mov byte [bp+012h], al                    ; 88 46 12
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
-    jmp short 05e26h                          ; eb 23
+    jmp short 05e3bh                          ; eb 23
     lea dx, [bx+005h]                         ; 8d 57 05
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
-    jmp short 05dbch                          ; eb b1
+    jmp short 05dd1h                          ; eb b1
     lea dx, [si+005h]                         ; 8d 54 05
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -8356,15 +8364,15 @@ _int14_function:                             ; 0xf5cd7 LB 0x155
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
-    jmp short 05dfah                          ; eb de
+    jmp short 05e0fh                          ; eb de
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
-    jmp short 05e26h                          ; eb 04
+    jmp short 05e3bh                          ; eb 04
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-set_enable_a20_:                             ; 0xf5e2c LB 0x2c
+set_enable_a20_:                             ; 0xf5e41 LB 0x2c
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -8377,10 +8385,10 @@ set_enable_a20_:                             ; 0xf5e2c LB 0x2c
     ; sub ah, ah                                ; 2a e4
     mov cl, al                                ; 88 c1
     test bx, bx                               ; 85 db
-    je short 05e45h                           ; 74 05
+    je short 05e5ah                           ; 74 05
     or AL, strict byte 002h                   ; 0c 02
     out DX, AL                                ; ee
-    jmp short 05e48h                          ; eb 03
+    jmp short 05e5dh                          ; eb 03
     and AL, strict byte 0fdh                  ; 24 fd
     out DX, AL                                ; ee
     test cl, 002h                             ; f6 c1 02
@@ -8393,7 +8401,7 @@ set_enable_a20_:                             ; 0xf5e2c LB 0x2c
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-set_e820_range_:                             ; 0xf5e58 LB 0x8c
+set_e820_range_:                             ; 0xf5e6d LB 0x8c
     push si                                   ; 56
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
@@ -8421,34 +8429,11 @@ set_e820_range_:                             ; 0xf5e58 LB 0x8c
     pop bp                                    ; 5d
     pop si                                    ; 5e
     retn 0000ah                               ; c2 0a 00
-    in AL, DX                                 ; ec
-    jmp near 0208bh                           ; e9 d8 c1
-    sar byte [bx-06f6fh], 089h                ; c0 bf 91 90 89
-    mov byte [bx+05283h], al                  ; 88 87 83 52
-    dec di                                    ; 4f
-    inc cx                                    ; 41
-    and AL, strict byte 000h                  ; 24 00
-    and word [bp+di+023h], strict byte 0005fh ; 83 63 23 5f
-    db  036h, 05fh
-    ; ss pop di                                 ; 36 5f
-    retf                                      ; cb
-    pop di                                    ; 5f
-    rcr word [bx-02ah], 1                     ; d1 5f d6
-    pop di                                    ; 5f
-    fistp dword [bx+07dh]                     ; db 5f 7d
-    pushaw                                    ; 60
-    sbb ah, byte [bp+si+040h]                 ; 1a 62 40
-    db  062h
-    les bx, [bx-03ch]                         ; c4 5f c4
-    pop di                                    ; 5f
-    or ax, 03563h                             ; 0d 63 35
-    arpl word [bx+si+063h], cx                ; 63 48 63
-    push di                                   ; 57
-    arpl bx, cx                               ; 63 cb
-    pop di                                    ; 5f
-    pop si                                    ; 5e
-    db  063h
-_int15_function:                             ; 0xf5ee4 LB 0x4cd
+    db  0ech, 0e9h, 0d8h, 0c1h, 0c0h, 0bfh, 091h, 090h, 089h, 088h, 087h, 083h, 052h, 04fh, 041h, 024h
+    db  000h, 098h, 063h, 038h, 05fh, 04bh, 05fh, 0e0h, 05fh, 0e6h, 05fh, 0ebh, 05fh, 0f0h, 05fh, 092h
+    db  060h, 02fh, 062h, 055h, 062h, 0d9h, 05fh, 0d9h, 05fh, 022h, 063h, 04ah, 063h, 05dh, 063h, 06ch
+    db  063h, 0e0h, 05fh, 073h, 063h
+_int15_function:                             ; 0xf5ef9 LB 0x4cd
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -8458,15 +8443,15 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     mov ax, word [bp+012h]                    ; 8b 46 12
     shr ax, 008h                              ; c1 e8 08
     cmp ax, 000ech                            ; 3d ec 00
-    jnbe near 06383h                          ; 0f 87 8b 04
+    jnbe near 06398h                          ; 0f 87 8b 04
     push CS                                   ; 0e
     pop ES                                    ; 07
     mov cx, strict word 00012h                ; b9 12 00
-    mov di, 05eafh                            ; bf af 5e
+    mov di, 05ec4h                            ; bf c4 5e
     repne scasb                               ; f2 ae
     sal cx, 1                                 ; d1 e1
     mov di, cx                                ; 89 cf
-    mov si, word [cs:di+05ec0h]               ; 2e 8b b5 c0 5e
+    mov si, word [cs:di+05ed5h]               ; 2e 8b b5 d5 5e
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     mov cx, word [bp+018h]                    ; 8b 4e 18
@@ -8479,30 +8464,30 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     cmp ax, 000c0h                            ; 3d c0 00
-    jne near 06383h                           ; 0f 85 54 04
+    jne near 06398h                           ; 0f 85 54 04
     or byte [bp+018h], 001h                   ; 80 4e 18 01
-    jmp near 0632ch                           ; e9 f6 03
+    jmp near 06341h                           ; e9 f6 03
     mov dx, ax                                ; 89 c2
     cmp ax, strict word 00001h                ; 3d 01 00
-    jc short 05f4bh                           ; 72 0e
-    jbe short 05f5fh                          ; 76 20
+    jc short 05f60h                           ; 72 0e
+    jbe short 05f74h                          ; 76 20
     cmp ax, strict word 00003h                ; 3d 03 00
-    je short 05f8ch                           ; 74 48
+    je short 05fa1h                           ; 74 48
     cmp ax, strict word 00002h                ; 3d 02 00
-    je short 05f6fh                           ; 74 26
-    jmp short 05f99h                          ; eb 4e
+    je short 05f84h                           ; 74 26
+    jmp short 05faeh                          ; eb 4e
     test ax, ax                               ; 85 c0
-    jne short 05f99h                          ; 75 4a
+    jne short 05faeh                          ; 75 4a
     xor ax, ax                                ; 31 c0
-    call 05e2ch                               ; e8 d8 fe
+    call 05e41h                               ; e8 d8 fe
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
     mov byte [bp+013h], 000h                  ; c6 46 13 00
-    jmp near 05fc4h                           ; e9 65 00
+    jmp near 05fd9h                           ; e9 65 00
     mov ax, strict word 00001h                ; b8 01 00
-    call 05e2ch                               ; e8 c7 fe
+    call 05e41h                               ; e8 c7 fe
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
     mov byte [bp+013h], dh                    ; 88 76 13
-    jmp near 05fc4h                           ; e9 55 00
+    jmp near 05fd9h                           ; e9 55 00
     mov dx, 00092h                            ; ba 92 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -8514,21 +8499,21 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     mov word [bp+012h], dx                    ; 89 56 12
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
     mov byte [bp+013h], ah                    ; 88 66 13
-    jmp near 05fc4h                           ; e9 38 00
+    jmp near 05fd9h                           ; e9 38 00
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
     mov byte [bp+013h], ah                    ; 88 66 13
     mov word [bp+00ch], ax                    ; 89 46 0c
-    jmp near 05fc4h                           ; e9 2b 00
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 05fd9h                           ; e9 2b 00
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 28 b9
+    call 018e1h                               ; e8 28 b9
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     push ax                                   ; 50
     push 00836h                               ; 68 36 08
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 5b b9
+    call 01922h                               ; e8 5b b9
     add sp, strict byte 00006h                ; 83 c4 06
     or byte [bp+018h], 001h                   ; 80 4e 18 01
     mov ax, word [bp+012h]                    ; 8b 46 12
@@ -8541,38 +8526,38 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     pop bp                                    ; 5d
     retn                                      ; c3
     mov word [bp+018h], bx                    ; 89 5e 18
-    jmp near 06077h                           ; e9 a6 00
+    jmp near 0608ch                           ; e9 a6 00
     mov word [bp+018h], bx                    ; 89 5e 18
-    jmp short 05fc4h                          ; eb ee
+    jmp short 05fd9h                          ; eb ee
     mov word [bp+018h], cx                    ; 89 4e 18
-    jmp short 05fc1h                          ; eb e6
+    jmp short 05fd6h                          ; eb e6
     test byte [bp+012h], 0ffh                 ; f6 46 12 ff
-    je short 0604dh                           ; 74 6c
+    je short 06062h                           ; 74 6c
     mov dx, 000a0h                            ; ba a0 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 16 b6
+    call 01600h                               ; e8 01 b6
     test AL, strict byte 001h                 ; a8 01
-    jne near 06323h                           ; 0f 85 33 03
+    jne near 06338h                           ; 0f 85 33 03
     mov bx, strict word 00001h                ; bb 01 00
     mov dx, 000a0h                            ; ba a0 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 12 b6
+    call 0160eh                               ; e8 fd b5
     mov bx, word [bp+014h]                    ; 8b 5e 14
     mov dx, 00098h                            ; ba 98 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 22 b6
+    call 0162ah                               ; e8 0d b6
     mov bx, word [bp+00ch]                    ; 8b 5e 0c
     mov dx, 0009ah                            ; ba 9a 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 16 b6
+    call 0162ah                               ; e8 01 b6
     mov bx, word [bp+00eh]                    ; 8b 5e 0e
     mov dx, 0009ch                            ; ba 9c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 0a b6
+    call 0162ah                               ; e8 f5 b5
     mov bx, word [bp+010h]                    ; 8b 5e 10
     mov dx, 0009eh                            ; ba 9e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0162ah                               ; e8 fe b5
+    call 0162ah                               ; e8 e9 b5
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
     mov dx, 000a1h                            ; ba a1 00
     in AL, DX                                 ; ec
@@ -8581,23 +8566,23 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     and AL, strict byte 0feh                  ; 24 fe
     out DX, AL                                ; ee
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 1d b6
+    call 0165ch                               ; e8 08 b6
     or AL, strict byte 040h                   ; 0c 40
     movzx dx, al                              ; 0f b6 d0
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 01670h                               ; e8 26 b6
-    jmp near 05fc4h                           ; e9 77 ff
+    call 01679h                               ; e8 1a b6
+    jmp near 05fd9h                           ; e9 77 ff
     cmp ax, strict word 00001h                ; 3d 01 00
-    jne short 0606bh                          ; 75 19
+    jne short 06080h                          ; 75 19
     xor bx, bx                                ; 31 db
     mov dx, 000a0h                            ; ba a0 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 b1 b5
+    call 0160eh                               ; e8 9c b5
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 f5 b5
+    call 0165ch                               ; e8 e0 b5
     and AL, strict byte 0bfh                  ; 24 bf
-    jmp short 06041h                          ; eb d6
+    jmp short 06056h                          ; eb d6
     mov word [bp+018h], bx                    ; 89 5e 18
     mov ax, dx                                ; 89 d0
     xor ah, dh                                ; 30 f4
@@ -8605,10 +8590,10 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     dec ax                                    ; 48
     or dx, ax                                 ; 09 c2
     mov word [bp+012h], dx                    ; 89 56 12
-    jmp near 05fc4h                           ; e9 47 ff
+    jmp near 05fd9h                           ; e9 47 ff
     cli                                       ; fa
     mov ax, strict word 00001h                ; b8 01 00
-    call 05e2ch                               ; e8 a8 fd
+    call 05e41h                               ; e8 a8 fd
     mov di, ax                                ; 89 c7
     mov ax, word [bp+014h]                    ; 8b 46 14
     sal ax, 004h                              ; c1 e0 04
@@ -8618,7 +8603,7 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     shr dx, 00ch                              ; c1 ea 0c
     mov byte [bp-006h], dl                    ; 88 56 fa
     cmp cx, ax                                ; 39 c1
-    jnc short 060a3h                          ; 73 05
+    jnc short 060b8h                          ; 73 05
     db  0feh, 0c2h
     ; inc dl                                    ; fe c2
     mov byte [bp-006h], dl                    ; 88 56 fa
@@ -8626,52 +8611,52 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     add dx, strict byte 00008h                ; 83 c2 08
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, strict word 0002fh                ; bb 2f 00
-    call 0162ah                               ; e8 78 b5
+    call 0162ah                               ; e8 63 b5
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0000ah                ; 83 c2 0a
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, cx                                ; 89 cb
-    call 0162ah                               ; e8 6a b5
+    call 0162ah                               ; e8 55 b5
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0000ch                ; 83 c2 0c
     mov ax, word [bp+014h]                    ; 8b 46 14
-    call 0160eh                               ; e8 3e b5
+    call 0160eh                               ; e8 29 b5
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0000dh                ; 83 c2 0d
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, 00093h                            ; bb 93 00
-    call 0160eh                               ; e8 2f b5
+    call 0160eh                               ; e8 1a b5
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0000eh                ; 83 c2 0e
     mov ax, word [bp+014h]                    ; 8b 46 14
     xor bx, bx                                ; 31 db
-    call 0162ah                               ; e8 3d b5
+    call 0162ah                               ; e8 28 b5
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 00020h                ; 83 c2 20
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, strict word 0ffffh                ; bb ff ff
-    call 0162ah                               ; e8 2e b5
+    call 0162ah                               ; e8 19 b5
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 00022h                ; 83 c2 22
     mov ax, word [bp+014h]                    ; 8b 46 14
     xor bx, bx                                ; 31 db
-    call 0162ah                               ; e8 20 b5
+    call 0162ah                               ; e8 0b b5
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 00024h                ; 83 c2 24
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, strict word 0000fh                ; bb 0f 00
-    call 0160eh                               ; e8 f5 b4
+    call 0160eh                               ; e8 e0 b4
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 00025h                ; 83 c2 25
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, 0009bh                            ; bb 9b 00
-    call 0160eh                               ; e8 e6 b4
+    call 0160eh                               ; e8 d1 b4
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 00026h                ; 83 c2 26
     mov ax, word [bp+014h]                    ; 8b 46 14
     xor bx, bx                                ; 31 db
-    call 0162ah                               ; e8 f4 b4
+    call 0162ah                               ; e8 df b4
     mov ax, ss                                ; 8c d0
     mov cx, ax                                ; 89 c1
     sal cx, 004h                              ; c1 e1 04
@@ -8681,27 +8666,27 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     add dx, strict byte 00028h                ; 83 c2 28
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, strict word 0ffffh                ; bb ff ff
-    call 0162ah                               ; e8 d8 b4
+    call 0162ah                               ; e8 c3 b4
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0002ah                ; 83 c2 2a
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, cx                                ; 89 cb
-    call 0162ah                               ; e8 ca b4
+    call 0162ah                               ; e8 b5 b4
     movzx bx, byte [bp-008h]                  ; 0f b6 5e f8
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0002ch                ; 83 c2 2c
     mov ax, word [bp+014h]                    ; 8b 46 14
-    call 0160eh                               ; e8 9e b4
+    call 0160eh                               ; e8 89 b4
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0002dh                ; 83 c2 2d
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, 00093h                            ; bb 93 00
-    call 0160eh                               ; e8 8f b4
+    call 0160eh                               ; e8 7a b4
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0002eh                ; 83 c2 2e
     mov ax, word [bp+014h]                    ; 8b 46 14
     xor bx, bx                                ; 31 db
-    call 0162ah                               ; e8 9d b4
+    call 0162ah                               ; e8 88 b4
     mov si, word [bp+006h]                    ; 8b 76 06
     mov es, [bp+014h]                         ; 8e 46 14
     mov cx, word [bp+010h]                    ; 8b 4e 10
@@ -8712,7 +8697,7 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     mov ds, ax                                ; 8e d8
     mov word [00467h], sp                     ; 89 26 67 04
     mov [00469h], ss                          ; 8c 16 69 04
-    call 061a9h                               ; e8 00 00
+    call 061beh                               ; e8 00 00
     pop di                                    ; 5f
     add di, strict byte 0001bh                ; 83 c7 1b
     push strict byte 00020h                   ; 6a 20
@@ -8735,7 +8720,7 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     ; xor di, di                                ; 33 ff
     cld                                       ; fc
     rep movsw                                 ; f3 a5
-    call 061ddh                               ; e8 00 00
+    call 061f2h                               ; e8 00 00
     pop ax                                    ; 58
     push 0f000h                               ; 68 00 f0
     add ax, strict byte 00018h                ; 83 c0 18
@@ -8756,53 +8741,53 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     pop eax                                   ; 66 58
     pop DS                                    ; 1f
     mov ax, di                                ; 89 f8
-    call 05e2ch                               ; e8 1e fc
+    call 05e41h                               ; e8 1e fc
     sti                                       ; fb
     mov byte [bp+013h], 000h                  ; c6 46 13 00
     and byte [bp+018h], 0feh                  ; 80 66 18 fe
-    jmp near 05fc4h                           ; e9 aa fd
+    jmp near 05fd9h                           ; e9 aa fd
     mov ax, strict word 00031h                ; b8 31 00
-    call 0165ch                               ; e8 3c b4
+    call 0165ch                               ; e8 27 b4
     xor ah, ah                                ; 30 e4
     mov dx, ax                                ; 89 c2
     sal dx, 008h                              ; c1 e2 08
     mov ax, strict word 00030h                ; b8 30 00
-    call 0165ch                               ; e8 2f b4
+    call 0165ch                               ; e8 1a b4
     xor ah, ah                                ; 30 e4
     or dx, ax                                 ; 09 c2
     mov word [bp+012h], dx                    ; 89 56 12
     cmp dx, strict byte 0ffc0h                ; 83 fa c0
-    jbe short 06213h                          ; 76 da
+    jbe short 06228h                          ; 76 da
     mov word [bp+012h], strict word 0ffc0h    ; c7 46 12 c0 ff
-    jmp short 06213h                          ; eb d3
+    jmp short 06228h                          ; eb d3
     cli                                       ; fa
     mov ax, strict word 00001h                ; b8 01 00
-    call 05e2ch                               ; e8 e5 fb
+    call 05e41h                               ; e8 e5 fb
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 00038h                ; 83 c2 38
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, strict word 0ffffh                ; bb ff ff
-    call 0162ah                               ; e8 d4 b3
+    call 0162ah                               ; e8 bf b3
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0003ah                ; 83 c2 3a
     mov ax, word [bp+014h]                    ; 8b 46 14
     xor bx, bx                                ; 31 db
-    call 0162ah                               ; e8 c6 b3
+    call 0162ah                               ; e8 b1 b3
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0003ch                ; 83 c2 3c
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, strict word 0000fh                ; bb 0f 00
-    call 0160eh                               ; e8 9b b3
+    call 0160eh                               ; e8 86 b3
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0003dh                ; 83 c2 3d
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov bx, 0009bh                            ; bb 9b 00
-    call 0160eh                               ; e8 8c b3
+    call 0160eh                               ; e8 77 b3
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, strict byte 0003eh                ; 83 c2 3e
     mov ax, word [bp+014h]                    ; 8b 46 14
     xor bx, bx                                ; 31 db
-    call 0162ah                               ; e8 9a b3
+    call 0162ah                               ; e8 85 b3
     mov AL, strict byte 011h                  ; b0 11
     mov dx, strict word 00020h                ; ba 20 00
     out DX, AL                                ; ee
@@ -8832,7 +8817,7 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     mov dx, 000a1h                            ; ba a1 00
     out DX, AL                                ; ee
     mov si, word [bp+006h]                    ; 8b 76 06
-    call 062d1h                               ; e8 00 00
+    call 062e6h                               ; e8 00 00
     pop di                                    ; 5f
     add di, strict byte 00018h                ; 83 c7 18
     push strict byte 00038h                   ; 6a 38
@@ -8860,67 +8845,70 @@ _int15_function:                             ; 0xf5ee4 LB 0x4cd
     push ax                                   ; 50
     push cx                                   ; 51
     retf                                      ; cb
-    jmp near 05fc4h                           ; e9 b7 fc
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 05fd9h                           ; e9 b7 fc
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 b4 b5
+    call 018e1h                               ; e8 b4 b5
     push 00876h                               ; 68 76 08
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 ed b5
+    call 01922h                               ; e8 ed b5
     add sp, strict byte 00004h                ; 83 c4 04
     or byte [bp+018h], 001h                   ; 80 4e 18 01
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     or ah, 086h                               ; 80 cc 86
     mov word [bp+012h], ax                    ; 89 46 12
-    jmp near 05fc4h                           ; e9 8f fc
+    jmp near 05fd9h                           ; e9 8f fc
     mov word [bp+018h], cx                    ; 89 4e 18
     mov word [bp+012h], ax                    ; 89 46 12
     mov word [bp+00ch], 0e6f5h                ; c7 46 0c f5 e6
     mov word [bp+014h], 0f000h                ; c7 46 14 00 f0
-    jmp near 05fc4h                           ; e9 7c fc
+    jmp near 05fd9h                           ; e9 7c fc
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 cb b2
+    call 0161ch                               ; e8 b6 b2
     mov word [bp+014h], ax                    ; 89 46 14
-    jmp near 06213h                           ; e9 bc fe
+    jmp near 06228h                           ; e9 bc fe
     push 008a5h                               ; 68 a5 08
     push strict byte 00008h                   ; 6a 08
-    jmp short 0631dh                          ; eb bf
+    jmp short 06332h                          ; eb bf
     test byte [bp+012h], 0ffh                 ; f6 46 12 ff
-    jne short 06383h                          ; 75 1f
+    jne short 06398h                          ; 75 1f
     mov word [bp+012h], ax                    ; 89 46 12
     mov ax, word [bp+00ch]                    ; 8b 46 0c
     xor ah, ah                                ; 30 e4
     cmp ax, strict word 00001h                ; 3d 01 00
-    jc short 0637ch                           ; 72 0b
+    jc short 06391h                           ; 72 0b
     cmp ax, strict word 00003h                ; 3d 03 00
-    jnbe short 0637ch                         ; 77 06
+    jnbe short 06391h                         ; 77 06
     mov word [bp+018h], cx                    ; 89 4e 18
-    jmp near 05fc4h                           ; e9 48 fc
+    jmp near 05fd9h                           ; e9 48 fc
     or byte [bp+018h], 001h                   ; 80 4e 18 01
-    jmp near 05fc4h                           ; e9 41 fc
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 05fd9h                           ; e9 41 fc
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 3e b5
+    call 018e1h                               ; e8 3e b5
     push word [bp+00ch]                       ; ff 76 0c
     push word [bp+012h]                       ; ff 76 12
     push 008bch                               ; 68 bc 08
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 71 b5
+    call 01922h                               ; e8 71 b5
     add sp, strict byte 00008h                ; 83 c4 08
-    jmp short 06323h                          ; eb 82
-    pop dx                                    ; 5a
-    db  065h, 07ch, 065h
-    ; gs jl short 0640ah                        ; 65 7c 65
-    lahf                                      ; 9f
-    sal word [gs:di-01fh], 065h               ; 65 c1 65 e1 65
-    add ah, byte [bp+041h]                    ; 02 66 41
-    insd                                      ; 66 6d
+    jmp short 06338h                          ; eb 82
+    outsw                                     ; 6f
+    db  065h, 091h
+    ; gs xchg cx, ax                            ; 65 91
+    db  065h, 0b4h, 065h
+    ; gs mov AH, strict byte 065h               ; 65 b4 65
+    db  0d6h
+    mul byte [gs:di+017h]                     ; 65 f6 65 17
+    push esi                                  ; 66 56
+    db  066h
+    db  082h
     db  066h
-_int15_function32:                           ; 0xf63b1 LB 0x37e
+_int15_function32:                           ; 0xf63c6 LB 0x37e
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -8932,11 +8920,11 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+020h]                    ; 8b 46 20
     xor ah, ah                                ; 30 e4
     cmp dx, 000e8h                            ; 81 fa e8 00
-    je near 0647eh                            ; 0f 84 ad 00
+    je near 06493h                            ; 0f 84 ad 00
     cmp dx, 000d0h                            ; 81 fa d0 00
-    je short 06419h                           ; 74 42
+    je short 0642eh                           ; 74 42
     cmp dx, 00086h                            ; 81 fa 86 00
-    jne near 066ffh                           ; 0f 85 20 03
+    jne near 06714h                           ; 0f 85 20 03
     sti                                       ; fb
     mov ax, word [bp+01ch]                    ; 8b 46 1c
     mov dx, word [bp+018h]                    ; 8b 56 18
@@ -8955,33 +8943,33 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     ; mov ah, al                                ; 8a e0
     db  066h, 00bh, 0c9h
     ; or ecx, ecx                               ; 66 0b c9
-    je near 06416h                            ; 0f 84 0e 00
+    je near 0642bh                            ; 0f 84 0e 00
     in AL, strict byte 061h                   ; e4 61
     and AL, strict byte 010h                  ; 24 10
     db  03ah, 0c4h
     ; cmp al, ah                                ; 3a c4
-    je short 06408h                           ; 74 f8
+    je short 0641dh                           ; 74 f8
     db  08ah, 0e0h
     ; mov ah, al                                ; 8a e0
     dec ecx                                   ; 66 49
-    jne short 06408h                          ; 75 f2
-    jmp near 06729h                           ; e9 10 03
+    jne short 0641dh                          ; 75 f2
+    jmp near 0673eh                           ; e9 10 03
     cmp ax, strict word 0004fh                ; 3d 4f 00
-    jne near 066ffh                           ; 0f 85 df 02
+    jne near 06714h                           ; 0f 85 df 02
     cmp word [bp+016h], 05052h                ; 81 7e 16 52 50
-    jne near 066ffh                           ; 0f 85 d6 02
+    jne near 06714h                           ; 0f 85 d6 02
     cmp word [bp+014h], 04f43h                ; 81 7e 14 43 4f
-    jne near 066ffh                           ; 0f 85 cd 02
+    jne near 06714h                           ; 0f 85 cd 02
     cmp word [bp+01eh], 04d4fh                ; 81 7e 1e 4f 4d
-    jne near 066ffh                           ; 0f 85 c4 02
+    jne near 06714h                           ; 0f 85 c4 02
     cmp word [bp+01ch], 04445h                ; 81 7e 1c 45 44
-    jne near 066ffh                           ; 0f 85 bb 02
+    jne near 06714h                           ; 0f 85 bb 02
     mov ax, word [bp+00ah]                    ; 8b 46 0a
     or ax, word [bp+008h]                     ; 0b 46 08
-    jne near 066ffh                           ; 0f 85 b1 02
+    jne near 06714h                           ; 0f 85 b1 02
     mov ax, word [bp+006h]                    ; 8b 46 06
     or ax, word [bp+004h]                     ; 0b 46 04
-    jne near 066ffh                           ; 0f 85 a7 02
+    jne near 06714h                           ; 0f 85 a7 02
     mov word [bp+028h], bx                    ; 89 5e 28
     mov ax, word [bp+014h]                    ; 8b 46 14
     mov word [bp+008h], ax                    ; 89 46 08
@@ -8992,26 +8980,26 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+01eh]                    ; 8b 46 1e
     mov word [bp+006h], ax                    ; 89 46 06
     mov dword [bp+020h], strict dword 049413332h ; 66 c7 46 20 32 33 41 49
-    jmp near 06729h                           ; e9 ab 02
+    jmp near 0673eh                           ; e9 ab 02
     cmp ax, strict word 00020h                ; 3d 20 00
-    je short 0648dh                           ; 74 0a
+    je short 064a2h                           ; 74 0a
     cmp ax, strict word 00001h                ; 3d 01 00
-    je near 066b4h                            ; 0f 84 2a 02
-    jmp near 066ffh                           ; e9 72 02
+    je near 066c9h                            ; 0f 84 2a 02
+    jmp near 06714h                           ; e9 72 02
     cmp word [bp+01ah], 0534dh                ; 81 7e 1a 4d 53
-    jne near 066ffh                           ; 0f 85 69 02
+    jne near 06714h                           ; 0f 85 69 02
     cmp word [bp+018h], 04150h                ; 81 7e 18 50 41
-    jne near 066ffh                           ; 0f 85 60 02
+    jne near 06714h                           ; 0f 85 60 02
     mov ax, strict word 00035h                ; b8 35 00
-    call 0165ch                               ; e8 b7 b1
+    call 0165ch                               ; e8 a2 b1
     movzx bx, al                              ; 0f b6 d8
     xor dx, dx                                ; 31 d2
     mov cx, strict word 00008h                ; b9 08 00
     sal bx, 1                                 ; d1 e3
     rcl dx, 1                                 ; d1 d2
-    loop 064adh                               ; e2 fa
+    loop 064c2h                               ; e2 fa
     mov ax, strict word 00034h                ; b8 34 00
-    call 0165ch                               ; e8 a3 b1
+    call 0165ch                               ; e8 8e b1
     xor ah, ah                                ; 30 e4
     mov dx, bx                                ; 89 da
     or dx, ax                                 ; 09 c2
@@ -9019,30 +9007,30 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     add bx, bx                                ; 01 db
     adc dx, 00100h                            ; 81 d2 00 01
     cmp dx, 00100h                            ; 81 fa 00 01
-    jc short 064d3h                           ; 72 06
-    jne short 06500h                          ; 75 31
+    jc short 064e8h                           ; 72 06
+    jne short 06515h                          ; 75 31
     test bx, bx                               ; 85 db
-    jnbe short 06500h                         ; 77 2d
+    jnbe short 06515h                         ; 77 2d
     mov ax, strict word 00031h                ; b8 31 00
-    call 0165ch                               ; e8 83 b1
+    call 0165ch                               ; e8 6e b1
     movzx bx, al                              ; 0f b6 d8
     xor dx, dx                                ; 31 d2
     mov cx, strict word 00008h                ; b9 08 00
     sal bx, 1                                 ; d1 e3
     rcl dx, 1                                 ; d1 d2
-    loop 064e1h                               ; e2 fa
+    loop 064f6h                               ; e2 fa
     mov ax, strict word 00030h                ; b8 30 00
-    call 0165ch                               ; e8 6f b1
+    call 0165ch                               ; e8 5a b1
     xor ah, ah                                ; 30 e4
     or bx, ax                                 ; 09 c3
     mov cx, strict word 0000ah                ; b9 0a 00
     sal bx, 1                                 ; d1 e3
     rcl dx, 1                                 ; d1 d2
-    loop 064f4h                               ; e2 fa
+    loop 06509h                               ; e2 fa
     add bx, strict byte 00000h                ; 83 c3 00
     adc dx, strict byte 00010h                ; 83 d2 10
     mov ax, strict word 00062h                ; b8 62 00
-    call 0165ch                               ; e8 56 b1
+    call 0165ch                               ; e8 41 b1
     xor ah, ah                                ; 30 e4
     mov word [bp-00ah], ax                    ; 89 46 f6
     xor al, al                                ; 30 c0
@@ -9050,28 +9038,28 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov cx, strict word 00008h                ; b9 08 00
     sal word [bp-00ah], 1                     ; d1 66 f6
     rcl word [bp-008h], 1                     ; d1 56 f8
-    loop 06513h                               ; e2 f8
+    loop 06528h                               ; e2 f8
     mov ax, strict word 00061h                ; b8 61 00
-    call 0165ch                               ; e8 3b b1
+    call 0165ch                               ; e8 26 b1
     xor ah, ah                                ; 30 e4
     or word [bp-00ah], ax                     ; 09 46 f6
     mov ax, word [bp-00ah]                    ; 8b 46 f6
     mov word [bp-008h], ax                    ; 89 46 f8
     mov word [bp-00ah], strict word 00000h    ; c7 46 f6 00 00
     mov ax, strict word 00063h                ; b8 63 00
-    call 0165ch                               ; e8 25 b1
+    call 0165ch                               ; e8 10 b1
     mov byte [bp-004h], al                    ; 88 46 fc
     mov byte [bp-006h], al                    ; 88 46 fa
     mov ax, word [bp+014h]                    ; 8b 46 14
     cmp ax, strict word 00007h                ; 3d 07 00
-    jnbe near 066ffh                          ; 0f 87 b8 01
+    jnbe near 06714h                          ; 0f 87 b8 01
     mov si, ax                                ; 89 c6
     add si, ax                                ; 01 c6
     mov cx, bx                                ; 89 d9
     add cx, strict byte 00000h                ; 83 c1 00
     mov ax, dx                                ; 89 d0
     adc ax, strict word 0ffffh                ; 15 ff ff
-    jmp word [cs:si+063a1h]                   ; 2e ff a4 a1 63
+    jmp word [cs:si+063b6h]                   ; 2e ff a4 b6 63
     push strict byte 00001h                   ; 6a 01
     push dword 000000000h                     ; 66 6a 00
     push strict byte 00009h                   ; 6a 09
@@ -9080,9 +9068,9 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     xor bx, bx                                ; 31 db
     xor cx, cx                                ; 31 c9
-    call 05e58h                               ; e8 e7 f8
+    call 05e6dh                               ; e8 e7 f8
     mov dword [bp+014h], strict dword 000000001h ; 66 c7 46 14 01 00 00 00
-    jmp near 0669eh                           ; e9 22 01
+    jmp near 066b3h                           ; e9 22 01
     push strict byte 00002h                   ; 6a 02
     push dword 000000000h                     ; 66 6a 00
     push strict byte 0000ah                   ; 6a 0a
@@ -9091,9 +9079,9 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     mov bx, 0fc00h                            ; bb 00 fc
     mov cx, strict word 00009h                ; b9 09 00
-    call 05e58h                               ; e8 c4 f8
+    call 05e6dh                               ; e8 c4 f8
     mov dword [bp+014h], strict dword 000000002h ; 66 c7 46 14 02 00 00 00
-    jmp near 0669eh                           ; e9 ff 00
+    jmp near 066b3h                           ; e9 ff 00
     push strict byte 00002h                   ; 6a 02
     push dword 000000000h                     ; 66 6a 00
     push strict byte 00010h                   ; 6a 10
@@ -9102,9 +9090,9 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     xor bx, bx                                ; 31 db
     mov cx, strict word 0000fh                ; b9 0f 00
-    call 05e58h                               ; e8 a2 f8
+    call 05e6dh                               ; e8 a2 f8
     mov dword [bp+014h], strict dword 000000003h ; 66 c7 46 14 03 00 00 00
-    jmp near 0669eh                           ; e9 dd 00
+    jmp near 066b3h                           ; e9 dd 00
     push strict byte 00001h                   ; 6a 01
     push dword 000000000h                     ; 66 6a 00
     push ax                                   ; 50
@@ -9113,9 +9101,9 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     xor bx, bx                                ; 31 db
     mov cx, strict word 00010h                ; b9 10 00
-    call 05e58h                               ; e8 82 f8
+    call 05e6dh                               ; e8 82 f8
     mov dword [bp+014h], strict dword 000000004h ; 66 c7 46 14 04 00 00 00
-    jmp near 0669eh                           ; e9 bd 00
+    jmp near 066b3h                           ; e9 bd 00
     push strict byte 00003h                   ; 6a 03
     push dword 000000000h                     ; 66 6a 00
     push dx                                   ; 52
@@ -9125,9 +9113,9 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov bx, cx                                ; 89 cb
     mov cx, ax                                ; 89 c1
     mov ax, si                                ; 89 f0
-    call 05e58h                               ; e8 61 f8
+    call 05e6dh                               ; e8 61 f8
     mov dword [bp+014h], strict dword 000000005h ; 66 c7 46 14 05 00 00 00
-    jmp near 0669eh                           ; e9 9c 00
+    jmp near 066b3h                           ; e9 9c 00
     push strict byte 00002h                   ; 6a 02
     push dword 000000000h                     ; 66 6a 00
     push dword 000000000h                     ; 66 6a 00
@@ -9135,19 +9123,19 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     xor bx, bx                                ; 31 db
     mov cx, strict word 0fffch                ; b9 fc ff
-    call 05e58h                               ; e8 40 f8
+    call 05e6dh                               ; e8 40 f8
     cmp byte [bp-004h], 000h                  ; 80 7e fc 00
-    jne short 06625h                          ; 75 07
+    jne short 0663ah                          ; 75 07
     mov ax, word [bp-008h]                    ; 8b 46 f8
     test ax, ax                               ; 85 c0
-    je short 06639h                           ; 74 14
+    je short 0664eh                           ; 74 14
     mov dword [bp+014h], strict dword 000000007h ; 66 c7 46 14 07 00 00 00
-    jmp short 0669eh                          ; eb 6f
+    jmp short 066b3h                          ; eb 6f
     mov dword [bp+014h], strict dword 000000006h ; 66 c7 46 14 06 00 00 00
-    jmp short 0669eh                          ; eb 65
+    jmp short 066b3h                          ; eb 65
     mov word [bp+014h], ax                    ; 89 46 14
     mov word [bp+016h], ax                    ; 89 46 16
-    jmp short 0669eh                          ; eb 5d
+    jmp short 066b3h                          ; eb 5d
     push strict byte 00002h                   ; 6a 02
     push dword 000000000h                     ; 66 6a 00
     push dword 000000000h                     ; 66 6a 00
@@ -9155,20 +9143,20 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     xor bx, bx                                ; 31 db
     xor cx, cx                                ; 31 c9
-    call 05e58h                               ; e8 02 f8
+    call 05e6dh                               ; e8 02 f8
     cmp byte [bp-004h], 000h                  ; 80 7e fc 00
-    jne short 06663h                          ; 75 07
+    jne short 06678h                          ; 75 07
     mov ax, word [bp-008h]                    ; 8b 46 f8
     test ax, ax                               ; 85 c0
-    je short 06665h                           ; 74 02
-    jmp short 06625h                          ; eb c0
+    je short 0667ah                           ; 74 02
+    jmp short 0663ah                          ; eb c0
     mov word [bp+014h], ax                    ; 89 46 14
     mov word [bp+016h], ax                    ; 89 46 16
-    jmp short 0669eh                          ; eb 31
+    jmp short 066b3h                          ; eb 31
     cmp byte [bp-004h], 000h                  ; 80 7e fc 00
-    jne short 06679h                          ; 75 06
+    jne short 0668eh                          ; 75 06
     cmp word [bp-008h], strict byte 00000h    ; 83 7e f8 00
-    je short 0669eh                           ; 74 25
+    je short 066b3h                           ; 74 25
     push strict byte 00001h                   ; 6a 01
     mov al, byte [bp-006h]                    ; 8a 46 fa
     db  0feh, 0c0h
@@ -9181,49 +9169,49 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     mov ax, word [bp+024h]                    ; 8b 46 24
     xor bx, bx                                ; 31 db
     xor cx, cx                                ; 31 c9
-    call 05e58h                               ; e8 c2 f7
+    call 05e6dh                               ; e8 c2 f7
     xor ax, ax                                ; 31 c0
     mov word [bp+014h], ax                    ; 89 46 14
     mov word [bp+016h], ax                    ; 89 46 16
     mov dword [bp+020h], strict dword 0534d4150h ; 66 c7 46 20 50 41 4d 53
     mov dword [bp+01ch], strict dword 000000014h ; 66 c7 46 1c 14 00 00 00
     and byte [bp+028h], 0feh                  ; 80 66 28 fe
-    jmp short 06729h                          ; eb 75
+    jmp short 0673eh                          ; eb 75
     mov word [bp+028h], bx                    ; 89 5e 28
     mov ax, strict word 00031h                ; b8 31 00
-    call 0165ch                               ; e8 9f af
+    call 0165ch                               ; e8 8a af
     movzx dx, al                              ; 0f b6 d0
     sal dx, 008h                              ; c1 e2 08
     mov ax, strict word 00030h                ; b8 30 00
-    call 0165ch                               ; e8 93 af
+    call 0165ch                               ; e8 7e af
     xor ah, ah                                ; 30 e4
     or dx, ax                                 ; 09 c2
     mov word [bp+01ch], dx                    ; 89 56 1c
     cmp dx, 03c00h                            ; 81 fa 00 3c
-    jbe short 066dbh                          ; 76 05
+    jbe short 066f0h                          ; 76 05
     mov word [bp+01ch], 03c00h                ; c7 46 1c 00 3c
     mov ax, strict word 00035h                ; b8 35 00
-    call 0165ch                               ; e8 7b af
+    call 0165ch                               ; e8 66 af
     movzx dx, al                              ; 0f b6 d0
     sal dx, 008h                              ; c1 e2 08
     mov ax, strict word 00034h                ; b8 34 00
-    call 0165ch                               ; e8 6f af
+    call 0165ch                               ; e8 5a af
     xor ah, ah                                ; 30 e4
     or dx, ax                                 ; 09 c2
     mov word [bp+018h], dx                    ; 89 56 18
     mov ax, word [bp+01ch]                    ; 8b 46 1c
     mov word [bp+020h], ax                    ; 89 46 20
     mov word [bp+014h], dx                    ; 89 56 14
-    jmp short 06729h                          ; eb 2a
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp short 0673eh                          ; eb 2a
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 c2 b1
+    call 018e1h                               ; e8 c2 b1
     push word [bp+014h]                       ; ff 76 14
     push word [bp+020h]                       ; ff 76 20
     push 008bch                               ; 68 bc 08
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 f5 b1
+    call 01922h                               ; e8 f5 b1
     add sp, strict byte 00008h                ; 83 c4 08
     or byte [bp+028h], 001h                   ; 80 4e 28 01
     mov ax, word [bp+020h]                    ; 8b 46 20
@@ -9234,7 +9222,7 @@ _int15_function32:                           ; 0xf63b1 LB 0x37e
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-_inv_op_handler:                             ; 0xf672f LB 0x195
+_inv_op_handler:                             ; 0xf6744 LB 0x195
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -9243,11 +9231,11 @@ _inv_op_handler:                             ; 0xf672f LB 0x195
     push ax                                   ; 50
     les bx, [bp+018h]                         ; c4 5e 18
     cmp byte [es:bx], 0f0h                    ; 26 80 3f f0
-    jne short 06745h                          ; 75 06
+    jne short 0675ah                          ; 75 06
     inc word [bp+018h]                        ; ff 46 18
-    jmp near 068bdh                           ; e9 78 01
+    jmp near 068d2h                           ; e9 78 01
     cmp word [es:bx], 0050fh                  ; 26 81 3f 0f 05
-    jne near 068b9h                           ; 0f 85 6b 01
+    jne near 068ceh                           ; 0f 85 6b 01
     mov si, 00800h                            ; be 00 08
     xor ax, ax                                ; 31 c0
     mov word [bp-006h], ax                    ; 89 46 fa
@@ -9275,11 +9263,11 @@ _inv_op_handler:                             ; 0xf672f LB 0x195
     mov cx, strict word 00004h                ; b9 04 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 0679eh                               ; e2 fa
+    loop 067b3h                               ; e2 fa
     cmp bx, dx                                ; 39 d3
-    jne short 067ach                          ; 75 04
+    jne short 067c1h                          ; 75 04
     cmp di, ax                                ; 39 c7
-    je short 067b1h                           ; 74 05
+    je short 067c6h                           ; 74 05
     mov word [bp-008h], strict word 00001h    ; c7 46 f8 01 00
     mov es, [bp-006h]                         ; 8e 46 fa
     movzx di, byte [es:si+04ah]               ; 26 0f b6 7c 4a
@@ -9289,11 +9277,11 @@ _inv_op_handler:                             ; 0xf672f LB 0x195
     mov cx, strict word 00004h                ; b9 04 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 067c6h                               ; e2 fa
+    loop 067dbh                               ; e2 fa
     cmp di, dx                                ; 39 d7
-    jne short 067d4h                          ; 75 04
+    jne short 067e9h                          ; 75 04
     cmp bx, ax                                ; 39 c3
-    je short 067d8h                           ; 74 04
+    je short 067edh                           ; 74 04
     or byte [bp-008h], 002h                   ; 80 4e f8 02
     push strict byte 00000h                   ; 6a 00
     push 00800h                               ; 68 00 08
@@ -9343,10 +9331,10 @@ _inv_op_handler:                             ; 0xf672f LB 0x195
     lmsw ax                                   ; 0f 01 f0
     mov ax, strict word 00008h                ; b8 08 00
     test cx, strict word 00001h               ; f7 c1 01 00
-    je near 06876h                            ; 0f 84 02 00
+    je near 0688bh                            ; 0f 84 02 00
     mov es, ax                                ; 8e c0
     test cx, strict word 00002h               ; f7 c1 02 00
-    je near 0689eh                            ; 0f 84 20 00
+    je near 068b3h                            ; 0f 84 20 00
     mov bx, word [word ss:00000h]             ; 36 8b 1e 00 00
     mov word [word ss:00008h], bx             ; 36 89 1e 08 00
     mov bx, word [word ss:00002h]             ; 36 8b 1e 02 00
@@ -9363,141 +9351,141 @@ _inv_op_handler:                             ; 0xf672f LB 0x195
     sub sp, strict byte 00006h                ; 83 ec 06
     mov ss, [word ss:00020h]                  ; 36 8e 16 20 00
     iret                                      ; cf
-    jmp short 068bdh                          ; eb 04
+    jmp short 068d2h                          ; eb 04
     sti                                       ; fb
     hlt                                       ; f4
-    jmp short 068bah                          ; eb fd
+    jmp short 068cfh                          ; eb fd
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-init_rtc_:                                   ; 0xf68c4 LB 0x28
+init_rtc_:                                   ; 0xf68d9 LB 0x28
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
     mov dx, strict word 00026h                ; ba 26 00
     mov ax, strict word 0000ah                ; b8 0a 00
-    call 01670h                               ; e8 9f ad
+    call 01679h                               ; e8 93 ad
     mov dx, strict word 00002h                ; ba 02 00
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 01670h                               ; e8 96 ad
+    call 01679h                               ; e8 8a ad
     mov ax, strict word 0000ch                ; b8 0c 00
-    call 0165ch                               ; e8 7c ad
+    call 0165ch                               ; e8 67 ad
     mov ax, strict word 0000dh                ; b8 0d 00
-    call 0165ch                               ; e8 76 ad
+    call 0165ch                               ; e8 61 ad
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-rtc_updating_:                               ; 0xf68ec LB 0x21
+rtc_updating_:                               ; 0xf6901 LB 0x21
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
     mov dx, 061a8h                            ; ba a8 61
     dec dx                                    ; 4a
-    je short 06904h                           ; 74 0e
+    je short 06919h                           ; 74 0e
     mov ax, strict word 0000ah                ; b8 0a 00
-    call 0165ch                               ; e8 60 ad
+    call 0165ch                               ; e8 4b ad
     test AL, strict byte 080h                 ; a8 80
-    jne short 068f3h                          ; 75 f3
+    jne short 06908h                          ; 75 f3
     xor ax, ax                                ; 31 c0
-    jmp short 06907h                          ; eb 03
+    jmp short 0691ch                          ; eb 03
     mov ax, strict word 00001h                ; b8 01 00
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-_int70_function:                             ; 0xf690d LB 0xbe
+_int70_function:                             ; 0xf6922 LB 0xbe
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
     push ax                                   ; 50
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 44 ad
+    call 0165ch                               ; e8 2f ad
     mov dl, al                                ; 88 c2
     mov byte [bp-004h], al                    ; 88 46 fc
     mov ax, strict word 0000ch                ; b8 0c 00
-    call 0165ch                               ; e8 39 ad
+    call 0165ch                               ; e8 24 ad
     mov dh, al                                ; 88 c6
     test dl, 060h                             ; f6 c2 60
-    je near 069b2h                            ; 0f 84 86 00
+    je near 069c7h                            ; 0f 84 86 00
     test AL, strict byte 020h                 ; a8 20
-    je short 06934h                           ; 74 04
+    je short 06949h                           ; 74 04
     sti                                       ; fb
     int 04ah                                  ; cd 4a
     cli                                       ; fa
     test dh, 040h                             ; f6 c6 40
-    je near 069b2h                            ; 0f 84 77 00
+    je near 069c7h                            ; 0f 84 77 00
     mov dx, 000a0h                            ; ba a0 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 bc ac
+    call 01600h                               ; e8 a7 ac
     test al, al                               ; 84 c0
-    je short 069b2h                           ; 74 6a
+    je short 069c7h                           ; 74 6a
     mov dx, 0009ch                            ; ba 9c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01638h                               ; e8 e7 ac
+    call 01638h                               ; e8 d2 ac
     test dx, dx                               ; 85 d2
-    jne short 0699eh                          ; 75 49
+    jne short 069b3h                          ; 75 49
     cmp ax, 003d1h                            ; 3d d1 03
-    jnc short 0699eh                          ; 73 44
+    jnc short 069b3h                          ; 73 44
     mov dx, 00098h                            ; ba 98 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 b9 ac
+    call 0161ch                               ; e8 a4 ac
     mov si, ax                                ; 89 c6
     mov dx, 0009ah                            ; ba 9a 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 ae ac
+    call 0161ch                               ; e8 99 ac
     mov cx, ax                                ; 89 c1
     xor bx, bx                                ; 31 db
     mov dx, 000a0h                            ; ba a0 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 93 ac
+    call 0160eh                               ; e8 7e ac
     mov al, byte [bp-004h]                    ; 8a 46 fc
     and AL, strict byte 037h                  ; 24 37
     movzx dx, al                              ; 0f b6 d0
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 01670h                               ; e8 e7 ac
+    call 01679h                               ; e8 db ac
     mov dx, cx                                ; 89 ca
     mov ax, si                                ; 89 f0
-    call 01600h                               ; e8 70 ac
+    call 01600h                               ; e8 5b ac
     or AL, strict byte 080h                   ; 0c 80
     movzx bx, al                              ; 0f b6 d8
     mov dx, cx                                ; 89 ca
     mov ax, si                                ; 89 f0
-    call 0160eh                               ; e8 72 ac
-    jmp short 069b2h                          ; eb 14
+    call 0160eh                               ; e8 5d ac
+    jmp short 069c7h                          ; eb 14
     mov bx, ax                                ; 89 c3
     add bx, 0fc2fh                            ; 81 c3 2f fc
     mov cx, dx                                ; 89 d1
     adc cx, strict byte 0ffffh                ; 83 d1 ff
     mov dx, 0009ch                            ; ba 9c 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0164ah                               ; e8 98 ac
-    call 0e03bh                               ; e8 86 76
+    call 0164ah                               ; e8 83 ac
+    call 0e03bh                               ; e8 71 76
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-    loop 06a26h                               ; e2 69
-    or bp, word [bp+si+030h]                  ; 0b 6a 30
-    push strict byte 00062h                   ; 6a 62
-    push strict byte 0ffb1h                   ; 6a b1
-    push strict byte 0ffe9h                   ; 6a e9
-    push strict byte 0002ch                   ; 6a 2c
+    imul word [bx+di+020h]                    ; f7 69 20
+    push strict byte 00045h                   ; 6a 45
+    push strict byte 00077h                   ; 6a 77
+    push strict byte 0ffc6h                   ; 6a c6
+    push strict byte 0fffeh                   ; 6a fe
+    push strict byte 00041h                   ; 6a 41
     db  06bh
-    db  083h
+    cbw                                       ; 98
     db  06bh
-_int1a_function:                             ; 0xf69cb LB 0x1c8
+_int1a_function:                             ; 0xf69e0 LB 0x1c8
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     sti                                       ; fb
     mov al, byte [bp+013h]                    ; 8a 46 13
     cmp AL, strict byte 007h                  ; 3c 07
-    jnbe near 06a07h                          ; 0f 87 2f 00
+    jnbe near 06a1ch                          ; 0f 87 2f 00
     movzx bx, al                              ; 0f b6 d8
     add bx, bx                                ; 01 db
-    jmp word [cs:bx+069bbh]                   ; 2e ff a7 bb 69
+    jmp word [cs:bx+069d0h]                   ; 2e ff a7 d0 69
     cli                                       ; fa
     mov bx, 0046eh                            ; bb 6e 04
     xor ax, ax                                ; 31 c0
@@ -9528,41 +9516,41 @@ _int1a_function:                             ; 0xf69cb LB 0x1c8
     mov byte [es:bx], 000h                    ; 26 c6 07 00
     sti                                       ; fb
     mov byte [bp+013h], 000h                  ; c6 46 13 00
-    jmp short 06a07h                          ; eb d7
-    call 068ech                               ; e8 b9 fe
+    jmp short 06a1ch                          ; eb d7
+    call 06901h                               ; e8 b9 fe
     test ax, ax                               ; 85 c0
-    je short 06a39h                           ; 74 02
-    jmp short 06a07h                          ; eb ce
+    je short 06a4eh                           ; 74 02
+    jmp short 06a1ch                          ; eb ce
     xor ax, ax                                ; 31 c0
-    call 0165ch                               ; e8 1e ac
+    call 0165ch                               ; e8 09 ac
     mov byte [bp+00fh], al                    ; 88 46 0f
     mov ax, strict word 00002h                ; b8 02 00
-    call 0165ch                               ; e8 15 ac
+    call 0165ch                               ; e8 00 ac
     mov byte [bp+010h], al                    ; 88 46 10
     mov ax, strict word 00004h                ; b8 04 00
-    call 0165ch                               ; e8 0c ac
+    call 0165ch                               ; e8 f7 ab
     mov bl, al                                ; 88 c3
     mov byte [bp+011h], al                    ; 88 46 11
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 01 ac
+    call 0165ch                               ; e8 ec ab
     and AL, strict byte 001h                  ; 24 01
     mov byte [bp+00eh], al                    ; 88 46 0e
-    jmp short 06aa7h                          ; eb 45
-    call 068ech                               ; e8 87 fe
+    jmp short 06abch                          ; eb 45
+    call 06901h                               ; e8 87 fe
     test ax, ax                               ; 85 c0
-    je short 06a6ch                           ; 74 03
-    call 068c4h                               ; e8 58 fe
+    je short 06a81h                           ; 74 03
+    call 068d9h                               ; e8 58 fe
     movzx dx, byte [bp+00fh]                  ; 0f b6 56 0f
     xor ax, ax                                ; 31 c0
-    call 01670h                               ; e8 fb ab
+    call 01679h                               ; e8 ef ab
     movzx dx, byte [bp+010h]                  ; 0f b6 56 10
     mov ax, strict word 00002h                ; b8 02 00
-    call 01670h                               ; e8 f1 ab
+    call 01679h                               ; e8 e5 ab
     movzx dx, byte [bp+011h]                  ; 0f b6 56 11
     mov ax, strict word 00004h                ; b8 04 00
-    call 01670h                               ; e8 e7 ab
+    call 01679h                               ; e8 db ab
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 cd ab
+    call 0165ch                               ; e8 b8 ab
     mov bl, al                                ; 88 c3
     and bl, 060h                              ; 80 e3 60
     or bl, 002h                               ; 80 cb 02
@@ -9571,71 +9559,71 @@ _int1a_function:                             ; 0xf69cb LB 0x1c8
     or bl, al                                 ; 08 c3
     movzx dx, bl                              ; 0f b6 d3
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 01670h                               ; e8 c9 ab
+    call 01679h                               ; e8 bd ab
     mov byte [bp+013h], 000h                  ; c6 46 13 00
     mov byte [bp+012h], bl                    ; 88 5e 12
-    jmp near 06a07h                           ; e9 56 ff
+    jmp near 06a1ch                           ; e9 56 ff
     mov byte [bp+013h], 000h                  ; c6 46 13 00
-    call 068ech                               ; e8 34 fe
+    call 06901h                               ; e8 34 fe
     test ax, ax                               ; 85 c0
-    je short 06abfh                           ; 74 03
-    jmp near 06a07h                           ; e9 48 ff
+    je short 06ad4h                           ; 74 03
+    jmp near 06a1ch                           ; e9 48 ff
     mov ax, strict word 00009h                ; b8 09 00
-    call 0165ch                               ; e8 97 ab
+    call 0165ch                               ; e8 82 ab
     mov byte [bp+010h], al                    ; 88 46 10
     mov ax, strict word 00008h                ; b8 08 00
-    call 0165ch                               ; e8 8e ab
+    call 0165ch                               ; e8 79 ab
     mov byte [bp+00fh], al                    ; 88 46 0f
     mov ax, strict word 00007h                ; b8 07 00
-    call 0165ch                               ; e8 85 ab
+    call 0165ch                               ; e8 70 ab
     mov byte [bp+00eh], al                    ; 88 46 0e
     mov ax, strict word 00032h                ; b8 32 00
-    call 0165ch                               ; e8 7c ab
+    call 0165ch                               ; e8 67 ab
     mov byte [bp+011h], al                    ; 88 46 11
     mov byte [bp+012h], al                    ; 88 46 12
-    jmp near 06a07h                           ; e9 1e ff
-    call 068ech                               ; e8 00 fe
+    jmp near 06a1ch                           ; e9 1e ff
+    call 06901h                               ; e8 00 fe
     test ax, ax                               ; 85 c0
-    je short 06af6h                           ; 74 06
-    call 068c4h                               ; e8 d1 fd
-    jmp near 06a07h                           ; e9 11 ff
+    je short 06b0bh                           ; 74 06
+    call 068d9h                               ; e8 d1 fd
+    jmp near 06a1ch                           ; e9 11 ff
     movzx dx, byte [bp+010h]                  ; 0f b6 56 10
     mov ax, strict word 00009h                ; b8 09 00
-    call 01670h                               ; e8 70 ab
+    call 01679h                               ; e8 64 ab
     movzx dx, byte [bp+00fh]                  ; 0f b6 56 0f
     mov ax, strict word 00008h                ; b8 08 00
-    call 01670h                               ; e8 66 ab
+    call 01679h                               ; e8 5a ab
     movzx dx, byte [bp+00eh]                  ; 0f b6 56 0e
     mov ax, strict word 00007h                ; b8 07 00
-    call 01670h                               ; e8 5c ab
+    call 01679h                               ; e8 50 ab
     movzx dx, byte [bp+011h]                  ; 0f b6 56 11
     mov ax, strict word 00032h                ; b8 32 00
-    call 01670h                               ; e8 52 ab
+    call 01679h                               ; e8 46 ab
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 38 ab
+    call 0165ch                               ; e8 23 ab
     mov bl, al                                ; 88 c3
     and bl, 07fh                              ; 80 e3 7f
-    jmp near 06a9eh                           ; e9 72 ff
+    jmp near 06ab3h                           ; e9 72 ff
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 2a ab
+    call 0165ch                               ; e8 15 ab
     mov bl, al                                ; 88 c3
     mov word [bp+012h], strict word 00000h    ; c7 46 12 00 00
     test AL, strict byte 020h                 ; a8 20
-    je short 06b40h                           ; 74 03
-    jmp near 06a07h                           ; e9 c7 fe
-    call 068ech                               ; e8 a9 fd
+    je short 06b55h                           ; 74 03
+    jmp near 06a1ch                           ; e9 c7 fe
+    call 06901h                               ; e8 a9 fd
     test ax, ax                               ; 85 c0
-    je short 06b4ah                           ; 74 03
-    call 068c4h                               ; e8 7a fd
+    je short 06b5fh                           ; 74 03
+    call 068d9h                               ; e8 7a fd
     movzx dx, byte [bp+00fh]                  ; 0f b6 56 0f
     mov ax, strict word 00001h                ; b8 01 00
-    call 01670h                               ; e8 1c ab
+    call 01679h                               ; e8 10 ab
     movzx dx, byte [bp+010h]                  ; 0f b6 56 10
     mov ax, strict word 00003h                ; b8 03 00
-    call 01670h                               ; e8 12 ab
+    call 01679h                               ; e8 06 ab
     movzx dx, byte [bp+011h]                  ; 0f b6 56 11
     mov ax, strict word 00005h                ; b8 05 00
-    call 01670h                               ; e8 08 ab
+    call 01679h                               ; e8 fc aa
     mov dx, 000a1h                            ; ba a1 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -9647,15 +9635,15 @@ _int1a_function:                             ; 0xf69cb LB 0x1c8
     or AL, strict byte 020h                   ; 0c 20
     movzx dx, al                              ; 0f b6 d0
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 01670h                               ; e8 f0 aa
-    jmp near 06a07h                           ; e9 84 fe
+    call 01679h                               ; e8 e4 aa
+    jmp near 06a1ch                           ; e9 84 fe
     mov ax, strict word 0000bh                ; b8 0b 00
-    call 0165ch                               ; e8 d3 aa
+    call 0165ch                               ; e8 be aa
     mov bl, al                                ; 88 c3
     and AL, strict byte 057h                  ; 24 57
     movzx dx, al                              ; 0f b6 d0
-    jmp near 06aa1h                           ; e9 0e ff
-send_to_mouse_ctrl_:                         ; 0xf6b93 LB 0x34
+    jmp near 06ab6h                           ; e9 0e ff
+send_to_mouse_ctrl_:                         ; 0xf6ba8 LB 0x34
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -9666,11 +9654,11 @@ send_to_mouse_ctrl_:                         ; 0xf6b93 LB 0x34
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 06bb2h                           ; 74 0e
+    je short 06bc7h                           ; 74 0e
     push 008f6h                               ; 68 f6 08
-    push 0116ah                               ; 68 6a 11
+    push 01182h                               ; 68 82 11
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 5e ad
+    call 01922h                               ; e8 5e ad
     add sp, strict byte 00006h                ; 83 c4 06
     mov AL, strict byte 0d4h                  ; b0 d4
     mov dx, strict word 00064h                ; ba 64 00
@@ -9684,7 +9672,7 @@ send_to_mouse_ctrl_:                         ; 0xf6b93 LB 0x34
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-get_mouse_data_:                             ; 0xf6bc7 LB 0x3b
+get_mouse_data_:                             ; 0xf6bdc LB 0x3b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -9698,15 +9686,15 @@ get_mouse_data_:                             ; 0xf6bc7 LB 0x3b
     ; sub ah, ah                                ; 2a e4
     and ax, strict word 00021h                ; 25 21 00
     cmp ax, strict word 00021h                ; 3d 21 00
-    je short 06be8h                           ; 74 07
+    je short 06bfdh                           ; 74 07
     test cx, cx                               ; 85 c9
-    je short 06be8h                           ; 74 03
+    je short 06bfdh                           ; 74 03
     dec cx                                    ; 49
-    jmp short 06bd3h                          ; eb eb
+    jmp short 06be8h                          ; eb eb
     test cx, cx                               ; 85 c9
-    jne short 06bf0h                          ; 75 04
+    jne short 06c05h                          ; 75 04
     mov AL, strict byte 001h                  ; b0 01
-    jmp short 06bfbh                          ; eb 0b
+    jmp short 06c10h                          ; eb 0b
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -9718,7 +9706,7 @@ get_mouse_data_:                             ; 0xf6bc7 LB 0x3b
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-set_kbd_command_byte_:                       ; 0xf6c02 LB 0x32
+set_kbd_command_byte_:                       ; 0xf6c17 LB 0x32
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -9729,11 +9717,11 @@ set_kbd_command_byte_:                       ; 0xf6c02 LB 0x32
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 002h                 ; a8 02
-    je short 06c21h                           ; 74 0e
+    je short 06c36h                           ; 74 0e
     push 00900h                               ; 68 00 09
-    push 0116ah                               ; 68 6a 11
+    push 01182h                               ; 68 82 11
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 ef ac
+    call 01922h                               ; e8 ef ac
     add sp, strict byte 00006h                ; 83 c4 06
     mov AL, strict byte 060h                  ; b0 60
     mov dx, strict word 00064h                ; ba 64 00
@@ -9746,13 +9734,13 @@ set_kbd_command_byte_:                       ; 0xf6c02 LB 0x32
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-_int74_function:                             ; 0xf6c34 LB 0xca
+_int74_function:                             ; 0xf6c49 LB 0xca
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     sub sp, strict byte 00008h                ; 83 ec 08
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 d9 a9
+    call 0161ch                               ; e8 c4 a9
     mov cx, ax                                ; 89 c1
     mov word [bp+004h], strict word 00000h    ; c7 46 04 00 00
     mov dx, strict word 00064h                ; ba 64 00
@@ -9761,7 +9749,7 @@ _int74_function:                             ; 0xf6c34 LB 0xca
     ; sub ah, ah                                ; 2a e4
     and AL, strict byte 021h                  ; 24 21
     cmp AL, strict byte 021h                  ; 3c 21
-    jne near 06ceah                           ; 0f 85 92 00
+    jne near 06cffh                           ; 0f 85 92 00
     mov dx, strict word 00060h                ; ba 60 00
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -9769,14 +9757,14 @@ _int74_function:                             ; 0xf6c34 LB 0xca
     mov bl, al                                ; 88 c3
     mov dx, strict word 00026h                ; ba 26 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 98 a9
+    call 01600h                               ; e8 83 a9
     mov byte [bp-006h], al                    ; 88 46 fa
     mov dx, strict word 00027h                ; ba 27 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 8d a9
+    call 01600h                               ; e8 78 a9
     mov byte [bp-008h], al                    ; 88 46 f8
     test AL, strict byte 080h                 ; a8 80
-    je short 06ceah                           ; 74 70
+    je short 06cffh                           ; 74 70
     mov al, byte [bp-008h]                    ; 8a 46 f8
     and AL, strict byte 007h                  ; 24 07
     mov byte [bp-002h], al                    ; 88 46 fe
@@ -9787,109 +9775,110 @@ _int74_function:                             ; 0xf6c34 LB 0xca
     movzx dx, al                              ; 0f b6 d0
     add dx, strict byte 00028h                ; 83 c2 28
     mov ax, cx                                ; 89 c8
-    call 0160eh                               ; e8 77 a9
+    call 0160eh                               ; e8 62 a9
     mov al, byte [bp-004h]                    ; 8a 46 fc
     cmp al, byte [bp-002h]                    ; 3a 46 fe
-    jc short 06cdbh                           ; 72 3c
+    jc short 06cf0h                           ; 72 3c
     mov dx, strict word 00028h                ; ba 28 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 59 a9
+    call 01600h                               ; e8 44 a9
     xor ah, ah                                ; 30 e4
     mov word [bp+00ch], ax                    ; 89 46 0c
     mov dx, strict word 00029h                ; ba 29 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 4c a9
+    call 01600h                               ; e8 37 a9
     xor ah, ah                                ; 30 e4
     mov word [bp+00ah], ax                    ; 89 46 0a
     mov dx, strict word 0002ah                ; ba 2a 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 3f a9
+    call 01600h                               ; e8 2a a9
     xor ah, ah                                ; 30 e4
     mov word [bp+008h], ax                    ; 89 46 08
     xor al, al                                ; 30 c0
     mov word [bp+006h], ax                    ; 89 46 06
     mov byte [bp-006h], ah                    ; 88 66 fa
     test byte [bp-008h], 080h                 ; f6 46 f8 80
-    je short 06cdeh                           ; 74 0a
+    je short 06cf3h                           ; 74 0a
     mov word [bp+004h], strict word 00001h    ; c7 46 04 01 00
-    jmp short 06cdeh                          ; eb 03
+    jmp short 06cf3h                          ; eb 03
     inc byte [bp-006h]                        ; fe 46 fa
     movzx bx, byte [bp-006h]                  ; 0f b6 5e fa
     mov dx, strict word 00026h                ; ba 26 00
     mov ax, cx                                ; 89 c8
-    call 0160eh                               ; e8 24 a9
+    call 0160eh                               ; e8 0f a9
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-    inc dx                                    ; 42
+    push di                                   ; 57
     insw                                      ; 6d
-    mov ax, 03b6dh                            ; b8 6d 3b
-    outsb                                     ; 6e
-    int3                                      ; cc
+    int 06dh                                  ; cd 6d
+    push ax                                   ; 50
     outsb                                     ; 6e
-    cmp ch, byte [bx-072h]                    ; 3a 6f 8e
-    insw                                      ; 6d
-    bound bp, [bx+027h]                       ; 62 6f 27
-    db  070h
-_int15_function_mouse:                       ; 0xf6cfe LB 0x38b
+    loope 06d79h                              ; e1 6e
+    dec di                                    ; 4f
+    outsw                                     ; 6f
+    mov word [0776dh], ax                     ; a3 6d 77
+    outsw                                     ; 6f
+    cmp AL, strict byte 070h                  ; 3c 70
+_int15_function_mouse:                       ; 0xf6d13 LB 0x38b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
     sub sp, strict byte 00006h                ; 83 ec 06
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 0e a9
+    call 0161ch                               ; e8 f9 a8
     mov cx, ax                                ; 89 c1
     cmp byte [bp+012h], 007h                  ; 80 7e 12 07
-    jbe short 06d21h                          ; 76 0b
+    jbe short 06d36h                          ; 76 0b
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 001h                  ; c6 46 13 01
-    jmp near 07083h                           ; e9 62 03
+    jmp near 07098h                           ; e9 62 03
     mov ax, strict word 00065h                ; b8 65 00
-    call 06c02h                               ; e8 db fe
+    call 06c17h                               ; e8 db fe
     and word [bp+018h], strict byte 0fffeh    ; 83 66 18 fe
     mov byte [bp+013h], 000h                  ; c6 46 13 00
     mov al, byte [bp+012h]                    ; 8a 46 12
     cmp AL, strict byte 007h                  ; 3c 07
-    jnbe near 0706ah                          ; 0f 87 32 03
+    jnbe near 0707fh                          ; 0f 87 32 03
     movzx si, al                              ; 0f b6 f0
     add si, si                                ; 01 f6
-    jmp word [cs:si+06ceeh]                   ; 2e ff a4 ee 6c
+    jmp word [cs:si+06d03h]                   ; 2e ff a4 03 6d
     cmp byte [bp+00dh], 001h                  ; 80 7e 0d 01
-    jnbe near 07075h                          ; 0f 87 2b 03
+    jnbe near 0708ah                          ; 0f 87 2b 03
     mov dx, strict word 00027h                ; ba 27 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 ae a8
+    call 01600h                               ; e8 99 a8
     test AL, strict byte 080h                 ; a8 80
-    jne short 06d61h                          ; 75 0b
+    jne short 06d76h                          ; 75 0b
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 005h                  ; c6 46 13 05
-    jmp near 0707dh                           ; e9 1c 03
+    jmp near 07092h                           ; e9 1c 03
     cmp byte [bp+00dh], 000h                  ; 80 7e 0d 00
     db  00fh, 094h, 0c0h
     ; sete al                                   ; 0f 94 c0
     add AL, strict byte 0f4h                  ; 04 f4
     xor ah, ah                                ; 30 e4
-    call 06b93h                               ; e8 24 fe
+    call 06ba8h                               ; e8 24 fe
     test al, al                               ; 84 c0
-    jne near 07003h                           ; 0f 85 8e 02
+    jne near 07018h                           ; 0f 85 8e 02
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 4a fe
+    call 06bdch                               ; e8 4a fe
     test al, al                               ; 84 c0
-    je near 0707dh                            ; 0f 84 fa 02
+    je near 07092h                            ; 0f 84 fa 02
     cmp byte [bp-008h], 0fah                  ; 80 7e f8 fa
-    jne near 07003h                           ; 0f 85 78 02
-    jmp near 0707dh                           ; e9 ef 02
+    jne near 07018h                           ; 0f 85 78 02
+    jmp near 07092h                           ; e9 ef 02
     mov al, byte [bp+00dh]                    ; 8a 46 0d
     cmp AL, strict byte 001h                  ; 3c 01
-    jc short 06d99h                           ; 72 04
+    jc short 06daeh                           ; 72 04
     cmp AL, strict byte 008h                  ; 3c 08
-    jbe short 06d9ch                          ; 76 03
-    jmp near 06f2fh                           ; e9 93 01
+    jbe short 06db1h                          ; 76 03
+    jmp near 06f44h                           ; e9 93 01
     mov dx, strict word 00027h                ; ba 27 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 5c a8
+    call 01600h                               ; e8 47 a8
     mov ah, byte [bp+00dh]                    ; 8a 66 0d
     db  0feh, 0cch
     ; dec ah                                    ; fe cc
@@ -9898,272 +9887,272 @@ _int15_function_mouse:                       ; 0xf6cfe LB 0x38b
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00027h                ; ba 27 00
     mov ax, cx                                ; 89 c8
-    call 0160eh                               ; e8 56 a8
+    call 0160eh                               ; e8 41 a8
     mov dx, strict word 00026h                ; ba 26 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 40 a8
+    call 01600h                               ; e8 2b a8
     and AL, strict byte 0f8h                  ; 24 f8
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00026h                ; ba 26 00
     mov ax, cx                                ; 89 c8
-    call 0160eh                               ; e8 41 a8
+    call 0160eh                               ; e8 2c a8
     mov ax, 000ffh                            ; b8 ff 00
-    call 06b93h                               ; e8 c0 fd
+    call 06ba8h                               ; e8 c0 fd
     test al, al                               ; 84 c0
-    jne near 07003h                           ; 0f 85 2a 02
+    jne near 07018h                           ; 0f 85 2a 02
     mov dx, ss                                ; 8c d2
     lea ax, [bp-004h]                         ; 8d 46 fc
-    call 06bc7h                               ; e8 e6 fd
+    call 06bdch                               ; e8 e6 fd
     mov cl, al                                ; 88 c1
     cmp byte [bp-004h], 0feh                  ; 80 7e fc fe
-    jne short 06df4h                          ; 75 0b
+    jne short 06e09h                          ; 75 0b
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 004h                  ; c6 46 13 04
-    jmp near 0707dh                           ; e9 89 02
+    jmp near 07092h                           ; e9 89 02
     cmp byte [bp-004h], 0fah                  ; 80 7e fc fa
-    je short 06e0ah                           ; 74 10
+    je short 06e1fh                           ; 74 10
     movzx ax, byte [bp-004h]                  ; 0f b6 46 fc
     push ax                                   ; 50
     push 0090bh                               ; 68 0b 09
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 06 ab
+    call 01922h                               ; e8 06 ab
     add sp, strict byte 00006h                ; 83 c4 06
     test cl, cl                               ; 84 c9
-    jne near 07003h                           ; 0f 85 f3 01
+    jne near 07018h                           ; 0f 85 f3 01
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 af fd
+    call 06bdch                               ; e8 af fd
     test al, al                               ; 84 c0
-    jne near 07003h                           ; 0f 85 e5 01
+    jne near 07018h                           ; 0f 85 e5 01
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 06bc7h                               ; e8 a1 fd
+    call 06bdch                               ; e8 a1 fd
     test al, al                               ; 84 c0
-    jne near 07003h                           ; 0f 85 d7 01
+    jne near 07018h                           ; 0f 85 d7 01
     mov al, byte [bp-008h]                    ; 8a 46 f8
     mov byte [bp+00ch], al                    ; 88 46 0c
     mov al, byte [bp-006h]                    ; 8a 46 fa
     mov byte [bp+00dh], al                    ; 88 46 0d
-    jmp near 0707dh                           ; e9 42 02
+    jmp near 07092h                           ; e9 42 02
     mov al, byte [bp+00dh]                    ; 8a 46 0d
     cmp AL, strict byte 003h                  ; 3c 03
-    jc short 06e52h                           ; 72 10
-    jbe short 06e70h                          ; 76 2c
+    jc short 06e67h                           ; 72 10
+    jbe short 06e85h                          ; 76 2c
     cmp AL, strict byte 006h                  ; 3c 06
-    je short 06e82h                           ; 74 3a
+    je short 06e97h                           ; 74 3a
     cmp AL, strict byte 005h                  ; 3c 05
-    je short 06e7ch                           ; 74 30
+    je short 06e91h                           ; 74 30
     cmp AL, strict byte 004h                  ; 3c 04
-    je short 06e76h                           ; 74 26
-    jmp short 06e88h                          ; eb 36
+    je short 06e8bh                           ; 74 26
+    jmp short 06e9dh                          ; eb 36
     cmp AL, strict byte 002h                  ; 3c 02
-    je short 06e6ah                           ; 74 14
+    je short 06e7fh                           ; 74 14
     cmp AL, strict byte 001h                  ; 3c 01
-    je short 06e64h                           ; 74 0a
+    je short 06e79h                           ; 74 0a
     test al, al                               ; 84 c0
-    jne short 06e88h                          ; 75 2a
+    jne short 06e9dh                          ; 75 2a
     mov byte [bp-008h], 00ah                  ; c6 46 f8 0a
-    jmp short 06e8ch                          ; eb 28
+    jmp short 06ea1h                          ; eb 28
     mov byte [bp-008h], 014h                  ; c6 46 f8 14
-    jmp short 06e8ch                          ; eb 22
+    jmp short 06ea1h                          ; eb 22
     mov byte [bp-008h], 028h                  ; c6 46 f8 28
-    jmp short 06e8ch                          ; eb 1c
+    jmp short 06ea1h                          ; eb 1c
     mov byte [bp-008h], 03ch                  ; c6 46 f8 3c
-    jmp short 06e8ch                          ; eb 16
+    jmp short 06ea1h                          ; eb 16
     mov byte [bp-008h], 050h                  ; c6 46 f8 50
-    jmp short 06e8ch                          ; eb 10
+    jmp short 06ea1h                          ; eb 10
     mov byte [bp-008h], 064h                  ; c6 46 f8 64
-    jmp short 06e8ch                          ; eb 0a
+    jmp short 06ea1h                          ; eb 0a
     mov byte [bp-008h], 0c8h                  ; c6 46 f8 c8
-    jmp short 06e8ch                          ; eb 04
+    jmp short 06ea1h                          ; eb 04
     mov byte [bp-008h], 000h                  ; c6 46 f8 00
     cmp byte [bp-008h], 000h                  ; 80 7e f8 00
-    jbe short 06ec1h                          ; 76 2f
+    jbe short 06ed6h                          ; 76 2f
     mov ax, 000f3h                            ; b8 f3 00
-    call 06b93h                               ; e8 fb fc
+    call 06ba8h                               ; e8 fb fc
     test al, al                               ; 84 c0
-    jne short 06eb6h                          ; 75 1a
+    jne short 06ecbh                          ; 75 1a
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 06bc7h                               ; e8 23 fd
+    call 06bdch                               ; e8 23 fd
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
-    call 06b93h                               ; e8 e8 fc
+    call 06ba8h                               ; e8 e8 fc
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 06bc7h                               ; e8 14 fd
-    jmp near 0707dh                           ; e9 c7 01
+    call 06bdch                               ; e8 14 fd
+    jmp near 07092h                           ; e9 c7 01
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 003h                  ; c6 46 13 03
-    jmp near 0707dh                           ; e9 bc 01
+    jmp near 07092h                           ; e9 bc 01
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 002h                  ; c6 46 13 02
-    jmp near 0707dh                           ; e9 b1 01
+    jmp near 07092h                           ; e9 b1 01
     cmp byte [bp+00dh], 004h                  ; 80 7e 0d 04
-    jnc short 06f2fh                          ; 73 5d
+    jnc short 06f44h                          ; 73 5d
     mov ax, 000e8h                            ; b8 e8 00
-    call 06b93h                               ; e8 bb fc
+    call 06ba8h                               ; e8 bb fc
     test al, al                               ; 84 c0
-    jne short 06f24h                          ; 75 48
+    jne short 06f39h                          ; 75 48
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 e3 fc
+    call 06bdch                               ; e8 e3 fc
     cmp byte [bp-008h], 0fah                  ; 80 7e f8 fa
-    je short 06efah                           ; 74 10
+    je short 06f0fh                           ; 74 10
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     push ax                                   ; 50
     push 00936h                               ; 68 36 09
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 16 aa
+    call 01922h                               ; e8 16 aa
     add sp, strict byte 00006h                ; 83 c4 06
     movzx ax, byte [bp+00dh]                  ; 0f b6 46 0d
-    call 06b93h                               ; e8 92 fc
+    call 06ba8h                               ; e8 92 fc
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 be fc
+    call 06bdch                               ; e8 be fc
     cmp byte [bp-008h], 0fah                  ; 80 7e f8 fa
-    je near 0707dh                            ; 0f 84 6c 01
+    je near 07092h                            ; 0f 84 6c 01
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     push ax                                   ; 50
     push 00936h                               ; 68 36 09
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 ef a9
+    call 01922h                               ; e8 ef a9
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp near 0707dh                           ; e9 59 01
+    jmp near 07092h                           ; e9 59 01
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 003h                  ; c6 46 13 03
-    jmp near 0707dh                           ; e9 4e 01
+    jmp near 07092h                           ; e9 4e 01
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 002h                  ; c6 46 13 02
-    jmp near 0707dh                           ; e9 43 01
+    jmp near 07092h                           ; e9 43 01
     mov ax, 000f2h                            ; b8 f2 00
-    call 06b93h                               ; e8 53 fc
+    call 06ba8h                               ; e8 53 fc
     test al, al                               ; 84 c0
-    jne short 06f57h                          ; 75 13
+    jne short 06f6ch                          ; 75 13
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 7b fc
+    call 06bdch                               ; e8 7b fc
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 06bc7h                               ; e8 73 fc
-    jmp near 06e32h                           ; e9 db fe
+    call 06bdch                               ; e8 73 fc
+    jmp near 06e47h                           ; e9 db fe
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 003h                  ; c6 46 13 03
-    jmp near 0707dh                           ; e9 1b 01
+    jmp near 07092h                           ; e9 1b 01
     mov al, byte [bp+00dh]                    ; 8a 46 0d
     test al, al                               ; 84 c0
-    jbe short 06f70h                          ; 76 07
+    jbe short 06f85h                          ; 76 07
     cmp AL, strict byte 002h                  ; 3c 02
-    jbe short 06fd9h                          ; 76 6c
-    jmp near 0700dh                           ; e9 9d 00
+    jbe short 06feeh                          ; 76 6c
+    jmp near 07022h                           ; e9 9d 00
     mov ax, 000e9h                            ; b8 e9 00
-    call 06b93h                               ; e8 1d fc
+    call 06ba8h                               ; e8 1d fc
     test al, al                               ; 84 c0
-    jne near 07003h                           ; 0f 85 87 00
+    jne near 07018h                           ; 0f 85 87 00
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 43 fc
+    call 06bdch                               ; e8 43 fc
     mov cl, al                                ; 88 c1
     cmp byte [bp-008h], 0fah                  ; 80 7e f8 fa
-    je short 06f9ch                           ; 74 10
+    je short 06fb1h                           ; 74 10
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     push ax                                   ; 50
     push 00936h                               ; 68 36 09
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 74 a9
+    call 01922h                               ; e8 74 a9
     add sp, strict byte 00006h                ; 83 c4 06
     test cl, cl                               ; 84 c9
-    jne short 07003h                          ; 75 63
+    jne short 07018h                          ; 75 63
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 1f fc
+    call 06bdch                               ; e8 1f fc
     test al, al                               ; 84 c0
-    jne short 07003h                          ; 75 57
+    jne short 07018h                          ; 75 57
     mov dx, ss                                ; 8c d2
     lea ax, [bp-006h]                         ; 8d 46 fa
-    call 06bc7h                               ; e8 13 fc
+    call 06bdch                               ; e8 13 fc
     test al, al                               ; 84 c0
-    jne short 07003h                          ; 75 4b
+    jne short 07018h                          ; 75 4b
     mov dx, ss                                ; 8c d2
     lea ax, [bp-004h]                         ; 8d 46 fc
-    call 06bc7h                               ; e8 07 fc
+    call 06bdch                               ; e8 07 fc
     test al, al                               ; 84 c0
-    jne short 07003h                          ; 75 3f
+    jne short 07018h                          ; 75 3f
     mov al, byte [bp-008h]                    ; 8a 46 f8
     mov byte [bp+00ch], al                    ; 88 46 0c
     mov al, byte [bp-006h]                    ; 8a 46 fa
     mov byte [bp+010h], al                    ; 88 46 10
     mov al, byte [bp-004h]                    ; 8a 46 fc
     mov byte [bp+00eh], al                    ; 88 46 0e
-    jmp near 0707dh                           ; e9 a4 00
+    jmp near 07092h                           ; e9 a4 00
     cmp AL, strict byte 001h                  ; 3c 01
-    jne short 06fe2h                          ; 75 05
+    jne short 06ff7h                          ; 75 05
     mov ax, 000e6h                            ; b8 e6 00
-    jmp short 06fe5h                          ; eb 03
+    jmp short 06ffah                          ; eb 03
     mov ax, 000e7h                            ; b8 e7 00
-    call 06b93h                               ; e8 ab fb
+    call 06ba8h                               ; e8 ab fb
     mov cl, al                                ; 88 c1
     test cl, cl                               ; 84 c9
-    jne short 06ffdh                          ; 75 0f
+    jne short 07012h                          ; 75 0f
     mov dx, ss                                ; 8c d2
     lea ax, [bp-008h]                         ; 8d 46 f8
-    call 06bc7h                               ; e8 d1 fb
+    call 06bdch                               ; e8 d1 fb
     cmp byte [bp-008h], 0fah                  ; 80 7e f8 fa
     db  00fh, 095h, 0c1h
     ; setne cl                                  ; 0f 95 c1
     test cl, cl                               ; 84 c9
-    je near 0707dh                            ; 0f 84 7a 00
+    je near 07092h                            ; 0f 84 7a 00
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 003h                  ; c6 46 13 03
-    jmp short 0707dh                          ; eb 70
+    jmp short 07092h                          ; eb 70
     movzx ax, byte [bp+00dh]                  ; 0f b6 46 0d
     push ax                                   ; 50
     push 00962h                               ; 68 62 09
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 f3 a8
+    call 01922h                               ; e8 f3 a8
     add sp, strict byte 00006h                ; 83 c4 06
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 001h                  ; c6 46 13 01
-    jmp short 0707dh                          ; eb 56
+    jmp short 07092h                          ; eb 56
     mov si, word [bp+00ch]                    ; 8b 76 0c
     mov bx, si                                ; 89 f3
     mov dx, strict word 00022h                ; ba 22 00
     mov ax, cx                                ; 89 c8
-    call 0162ah                               ; e8 f6 a5
+    call 0162ah                               ; e8 e1 a5
     mov bx, word [bp+014h]                    ; 8b 5e 14
     mov dx, strict word 00024h                ; ba 24 00
     mov ax, cx                                ; 89 c8
-    call 0162ah                               ; e8 eb a5
+    call 0162ah                               ; e8 d6 a5
     mov dx, strict word 00027h                ; ba 27 00
     mov ax, cx                                ; 89 c8
-    call 01600h                               ; e8 b9 a5
+    call 01600h                               ; e8 a4 a5
     mov ah, al                                ; 88 c4
     test si, si                               ; 85 f6
-    jne short 0705bh                          ; 75 0e
+    jne short 07070h                          ; 75 0e
     cmp word [bp+014h], strict byte 00000h    ; 83 7e 14 00
-    jne short 0705bh                          ; 75 08
+    jne short 07070h                          ; 75 08
     test AL, strict byte 080h                 ; a8 80
-    je short 0705dh                           ; 74 06
+    je short 07072h                           ; 74 06
     and AL, strict byte 07fh                  ; 24 7f
-    jmp short 0705dh                          ; eb 02
+    jmp short 07072h                          ; eb 02
     or AL, strict byte 080h                   ; 0c 80
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00027h                ; ba 27 00
     mov ax, cx                                ; 89 c8
-    call 0160eh                               ; e8 a6 a5
-    jmp short 0707dh                          ; eb 13
+    call 0160eh                               ; e8 91 a5
+    jmp short 07092h                          ; eb 13
     push 0097ch                               ; 68 7c 09
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 9b a8
+    call 01922h                               ; e8 9b a8
     add sp, strict byte 00004h                ; 83 c4 04
     or word [bp+018h], strict byte 00001h     ; 83 4e 18 01
     mov byte [bp+013h], 001h                  ; c6 46 13 01
     mov ax, strict word 00047h                ; b8 47 00
-    call 06c02h                               ; e8 7f fb
+    call 06c17h                               ; e8 7f fb
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-_int17_function:                             ; 0xf7089 LB 0xb3
+_int17_function:                             ; 0xf709e LB 0xb3
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -10173,24 +10162,24 @@ _int17_function:                             ; 0xf7089 LB 0xb3
     add dx, dx                                ; 01 d2
     add dx, strict byte 00008h                ; 83 c2 08
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 7f a5
+    call 0161ch                               ; e8 6a a5
     mov bx, ax                                ; 89 c3
     mov si, ax                                ; 89 c6
     cmp byte [bp+013h], 003h                  ; 80 7e 13 03
-    jnc near 07132h                           ; 0f 83 89 00
+    jnc near 07147h                           ; 0f 83 89 00
     mov ax, word [bp+00eh]                    ; 8b 46 0e
     cmp ax, strict word 00003h                ; 3d 03 00
-    jnc near 07132h                           ; 0f 83 7f 00
+    jnc near 07147h                           ; 0f 83 7f 00
     test bx, bx                               ; 85 db
-    jbe near 07132h                           ; 0f 86 79 00
+    jbe near 07147h                           ; 0f 86 79 00
     mov dx, ax                                ; 89 c2
     add dx, strict byte 00078h                ; 83 c2 78
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 3c a5
+    call 01600h                               ; e8 27 a5
     movzx cx, al                              ; 0f b6 c8
     sal cx, 008h                              ; c1 e1 08
     cmp byte [bp+013h], 000h                  ; 80 7e 13 00
-    jne short 070fdh                          ; 75 2d
+    jne short 07112h                          ; 75 2d
     mov al, byte [bp+012h]                    ; 8a 46 12
     mov dx, bx                                ; 89 da
     out DX, AL                                ; ee
@@ -10210,13 +10199,13 @@ _int17_function:                             ; 0xf7089 LB 0xb3
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 040h                 ; a8 40
-    je short 070fdh                           ; 74 07
+    je short 07112h                           ; 74 07
     test cx, cx                               ; 85 c9
-    je short 070fdh                           ; 74 03
+    je short 07112h                           ; 74 03
     dec cx                                    ; 49
-    jmp short 070ech                          ; eb ef
+    jmp short 07101h                          ; eb ef
     cmp byte [bp+013h], 001h                  ; 80 7e 13 01
-    jne short 07119h                          ; 75 16
+    jne short 0712eh                          ; 75 16
     lea dx, [si+002h]                         ; 8d 54 02
     in AL, DX                                 ; ec
     db  02ah, 0e4h
@@ -10235,16 +10224,16 @@ _int17_function:                             ; 0xf7089 LB 0xb3
     xor AL, strict byte 048h                  ; 34 48
     mov byte [bp+013h], al                    ; 88 46 13
     test cx, cx                               ; 85 c9
-    jne short 0712ch                          ; 75 04
+    jne short 07141h                          ; 75 04
     or byte [bp+013h], 001h                   ; 80 4e 13 01
     and byte [bp+01ch], 0feh                  ; 80 66 1c fe
-    jmp short 07136h                          ; eb 04
+    jmp short 0714bh                          ; eb 04
     or byte [bp+01ch], 001h                   ; 80 4e 1c 01
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-wait_:                                       ; 0xf713c LB 0xb2
+wait_:                                       ; 0xf7151 LB 0xb2
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -10262,28 +10251,28 @@ wait_:                                       ; 0xf713c LB 0xb2
     xor cx, cx                                ; 31 c9
     mov dx, 0046ch                            ; ba 6c 04
     xor ax, ax                                ; 31 c0
-    call 01638h                               ; e8 d9 a4
+    call 01638h                               ; e8 c4 a4
     mov word [bp-00eh], ax                    ; 89 46 f2
     mov bx, dx                                ; 89 d3
     hlt                                       ; f4
     mov dx, 0046ch                            ; ba 6c 04
     xor ax, ax                                ; 31 c0
-    call 01638h                               ; e8 cb a4
+    call 01638h                               ; e8 b6 a4
     mov word [bp-012h], ax                    ; 89 46 ee
     mov di, dx                                ; 89 d7
     cmp dx, bx                                ; 39 da
-    jnbe short 0717dh                         ; 77 07
-    jne short 07184h                          ; 75 0c
+    jnbe short 07192h                         ; 77 07
+    jne short 07199h                          ; 75 0c
     cmp ax, word [bp-00eh]                    ; 3b 46 f2
-    jbe short 07184h                          ; 76 07
+    jbe short 07199h                          ; 76 07
     sub ax, word [bp-00eh]                    ; 2b 46 f2
     sbb dx, bx                                ; 19 da
-    jmp short 0718fh                          ; eb 0b
+    jmp short 071a4h                          ; eb 0b
     cmp dx, bx                                ; 39 da
-    jc short 0718fh                           ; 72 07
-    jne short 07193h                          ; 75 09
+    jc short 071a4h                           ; 72 07
+    jne short 071a8h                          ; 75 09
     cmp ax, word [bp-00eh]                    ; 3b 46 f2
-    jnc short 07193h                          ; 73 04
+    jnc short 071a8h                          ; 73 04
     sub si, ax                                ; 29 c6
     sbb cx, dx                                ; 19 d1
     mov ax, word [bp-012h]                    ; 8b 46 ee
@@ -10291,13 +10280,13 @@ wait_:                                       ; 0xf713c LB 0xb2
     mov bx, di                                ; 89 fb
     mov ax, 00100h                            ; b8 00 01
     int 016h                                  ; cd 16
-    je near 071a9h                            ; 0f 84 05 00
+    je near 071beh                            ; 0f 84 05 00
     mov AL, strict byte 001h                  ; b0 01
-    jmp near 071abh                           ; e9 02 00
+    jmp near 071c0h                           ; e9 02 00
     db  032h, 0c0h
     ; xor al, al                                ; 32 c0
     test al, al                               ; 84 c0
-    je short 071d3h                           ; 74 24
+    je short 071e8h                           ; 74 24
     db  033h, 0c0h
     ; xor ax, ax                                ; 33 c0
     int 016h                                  ; cd 16
@@ -10308,17 +10297,17 @@ wait_:                                       ; 0xf713c LB 0xb2
     push ax                                   ; 50
     push 0099eh                               ; 68 9e 09
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 47 a7
+    call 01922h                               ; e8 47 a7
     add sp, strict byte 00006h                ; 83 c4 06
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    je short 071d3h                           ; 74 04
+    je short 071e8h                           ; 74 04
     mov al, dl                                ; 88 d0
-    jmp short 071e5h                          ; eb 12
+    jmp short 071fah                          ; eb 12
     test cx, cx                               ; 85 c9
-    jnle short 07164h                         ; 7f 8d
-    jne short 071ddh                          ; 75 04
+    jnle short 07179h                         ; 7f 8d
+    jne short 071f2h                          ; 75 04
     test si, si                               ; 85 f6
-    jnbe short 07164h                         ; 77 87
+    jnbe short 07179h                         ; 77 87
     mov ax, word [bp-010h]                    ; 8b 46 f0
     push ax                                   ; 50
     popfw                                     ; 9d
@@ -10330,7 +10319,7 @@ wait_:                                       ; 0xf713c LB 0xb2
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-read_logo_byte_:                             ; 0xf71ee LB 0x16
+read_logo_byte_:                             ; 0xf7203 LB 0x16
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
@@ -10345,7 +10334,7 @@ read_logo_byte_:                             ; 0xf71ee LB 0x16
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-read_logo_word_:                             ; 0xf7204 LB 0x14
+read_logo_word_:                             ; 0xf7219 LB 0x14
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push dx                                   ; 52
@@ -10358,7 +10347,7 @@ read_logo_word_:                             ; 0xf7204 LB 0x14
     pop dx                                    ; 5a
     pop bp                                    ; 5d
     retn                                      ; c3
-print_detected_harddisks_:                   ; 0xf7218 LB 0x130
+print_detected_harddisks_:                   ; 0xf722d LB 0x130
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -10370,77 +10359,77 @@ print_detected_harddisks_:                   ; 0xf7218 LB 0x130
     push ax                                   ; 50
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 f1 a3
+    call 0161ch                               ; e8 dc a3
     mov si, ax                                ; 89 c6
     mov byte [bp-00ch], 000h                  ; c6 46 f4 00
     xor cl, cl                                ; 30 c9
     xor ch, ch                                ; 30 ed
     mov dx, 002c0h                            ; ba c0 02
-    call 01600h                               ; e8 c5 a3
+    call 01600h                               ; e8 b0 a3
     mov byte [bp-00eh], al                    ; 88 46 f2
     xor bl, bl                                ; 30 db
     cmp bl, byte [bp-00eh]                    ; 3a 5e f2
-    jnc near 0731ah                           ; 0f 83 d3 00
+    jnc near 0732fh                           ; 0f 83 d3 00
     movzx dx, bl                              ; 0f b6 d3
     add dx, 002c1h                            ; 81 c2 c1 02
     mov ax, si                                ; 89 f0
-    call 01600h                               ; e8 ad a3
+    call 01600h                               ; e8 98 a3
     mov bh, al                                ; 88 c7
     cmp AL, strict byte 00ch                  ; 3c 0c
-    jc short 0727dh                           ; 72 24
+    jc short 07292h                           ; 72 24
     test cl, cl                               ; 84 c9
-    jne short 0726ah                          ; 75 0d
+    jne short 0727fh                          ; 75 0d
     push 009afh                               ; 68 af 09
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 a8 a6
+    call 01922h                               ; e8 a8 a6
     add sp, strict byte 00004h                ; 83 c4 04
     mov CL, strict byte 001h                  ; b1 01
     movzx ax, bl                              ; 0f b6 c3
     inc ax                                    ; 40
     push ax                                   ; 50
-    push 009c3h                               ; 68 c3 09
+    push 009c4h                               ; 68 c4 09
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 96 a6
+    call 01922h                               ; e8 96 a6
     add sp, strict byte 00006h                ; 83 c4 06
-    jmp near 07315h                           ; e9 98 00
+    jmp near 0732ah                           ; e9 98 00
     cmp AL, strict byte 008h                  ; 3c 08
-    jc short 07294h                           ; 72 13
+    jc short 072a9h                           ; 72 13
     test ch, ch                               ; 84 ed
-    jne short 07292h                          ; 75 0d
-    push 009d6h                               ; 68 d6 09
+    jne short 072a7h                          ; 75 0d
+    push 009d7h                               ; 68 d7 09
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 80 a6
+    call 01922h                               ; e8 80 a6
     add sp, strict byte 00004h                ; 83 c4 04
     mov CH, strict byte 001h                  ; b5 01
-    jmp short 0726ah                          ; eb d6
+    jmp short 0727fh                          ; eb d6
     cmp AL, strict byte 004h                  ; 3c 04
-    jnc short 072afh                          ; 73 17
+    jnc short 072c4h                          ; 73 17
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    jne short 072afh                          ; 75 11
-    push 009eah                               ; 68 ea 09
+    jne short 072c4h                          ; 75 11
+    push 009ech                               ; 68 ec 09
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 67 a6
+    call 01922h                               ; e8 67 a6
     add sp, strict byte 00004h                ; 83 c4 04
     mov byte [bp-00ch], 001h                  ; c6 46 f4 01
-    jmp short 072c5h                          ; eb 16
+    jmp short 072dah                          ; eb 16
     cmp bh, 004h                              ; 80 ff 04
-    jc short 072c5h                           ; 72 11
+    jc short 072dah                           ; 72 11
     test cl, cl                               ; 84 c9
-    jne short 072c5h                          ; 75 0d
-    push 009afh                               ; 68 af 09
+    jne short 072dah                          ; 75 0d
+    push 009feh                               ; 68 fe 09
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 4d a6
+    call 01922h                               ; e8 4d a6
     add sp, strict byte 00004h                ; 83 c4 04
     mov CL, strict byte 001h                  ; b1 01
     movzx ax, bl                              ; 0f b6 c3
     inc ax                                    ; 40
     push ax                                   ; 50
-    push 009fbh                               ; 68 fb 09
+    push 00a12h                               ; 68 12 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 3b a6
+    call 01922h                               ; e8 3b a6
     add sp, strict byte 00006h                ; 83 c4 06
     cmp bh, 004h                              ; 80 ff 04
-    jc short 072ddh                           ; 72 03
+    jc short 072f2h                           ; 72 03
     sub bh, 004h                              ; 80 ef 04
     movzx ax, bh                              ; 0f b6 c7
     cwd                                       ; 99
@@ -10448,41 +10437,41 @@ print_detected_harddisks_:                   ; 0xf7218 LB 0x130
     ; sub ax, dx                                ; 2b c2
     sar ax, 1                                 ; d1 f8
     test ax, ax                               ; 85 c0
-    je short 072eeh                           ; 74 05
-    push 00a05h                               ; 68 05 0a
-    jmp short 072f1h                          ; eb 03
-    push 00a10h                               ; 68 10 0a
+    je short 07303h                           ; 74 05
+    push 00a1ch                               ; 68 1c 0a
+    jmp short 07306h                          ; eb 03
+    push 00a27h                               ; 68 27 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 17 a6
+    call 01922h                               ; e8 17 a6
     add sp, strict byte 00004h                ; 83 c4 04
     movzx ax, bh                              ; 0f b6 c7
     mov di, strict word 00002h                ; bf 02 00
     cwd                                       ; 99
     idiv di                                   ; f7 ff
     test dx, dx                               ; 85 d2
-    je short 0730bh                           ; 74 05
-    push 00a19h                               ; 68 19 0a
-    jmp short 0730eh                          ; eb 03
-    push 00a1fh                               ; 68 1f 0a
+    je short 07320h                           ; 74 05
+    push 00a30h                               ; 68 30 0a
+    jmp short 07323h                          ; eb 03
+    push 00a36h                               ; 68 36 0a
     push di                                   ; 57
-    call 0190dh                               ; e8 fb a5
+    call 01922h                               ; e8 fb a5
     add sp, strict byte 00004h                ; 83 c4 04
     db  0feh, 0c3h
     ; inc bl                                    ; fe c3
-    jmp near 07240h                           ; e9 26 ff
+    jmp near 07255h                           ; e9 26 ff
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    jne short 07333h                          ; 75 13
+    jne short 07348h                          ; 75 13
     test cl, cl                               ; 84 c9
-    jne short 07333h                          ; 75 0f
+    jne short 07348h                          ; 75 0f
     test ch, ch                               ; 84 ed
-    jne short 07333h                          ; 75 0b
-    push 00a26h                               ; 68 26 0a
+    jne short 07348h                          ; 75 0b
+    push 00a3dh                               ; 68 3d 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 dd a5
+    call 01922h                               ; e8 dd a5
     add sp, strict byte 00004h                ; 83 c4 04
-    push 00a3ah                               ; 68 3a 0a
+    push 00a51h                               ; 68 51 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 d2 a5
+    call 01922h                               ; e8 d2 a5
     add sp, strict byte 00004h                ; 83 c4 04
     lea sp, [bp-00ah]                         ; 8d 66 f6
     pop di                                    ; 5f
@@ -10492,7 +10481,7 @@ print_detected_harddisks_:                   ; 0xf7218 LB 0x130
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-get_boot_drive_:                             ; 0xf7348 LB 0x28
+get_boot_drive_:                             ; 0xf735d LB 0x28
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -10500,12 +10489,12 @@ get_boot_drive_:                             ; 0xf7348 LB 0x28
     mov bl, al                                ; 88 c3
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 c4 a2
+    call 0161ch                               ; e8 af a2
     mov dx, 002c0h                            ; ba c0 02
-    call 01600h                               ; e8 a2 a2
+    call 01600h                               ; e8 8d a2
     sub bl, 002h                              ; 80 eb 02
     cmp bl, al                                ; 38 c3
-    jc short 07367h                           ; 72 02
+    jc short 0737ch                           ; 72 02
     mov BL, strict byte 0ffh                  ; b3 ff
     mov al, bl                                ; 88 d8
     lea sp, [bp-004h]                         ; 8d 66 fc
@@ -10513,7 +10502,7 @@ get_boot_drive_:                             ; 0xf7348 LB 0x28
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-show_logo_:                                  ; 0xf7370 LB 0x224
+show_logo_:                                  ; 0xf7385 LB 0x224
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -10524,7 +10513,7 @@ show_logo_:                                  ; 0xf7370 LB 0x224
     sub sp, strict byte 0000ch                ; 83 ec 0c
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 98 a2
+    call 0161ch                               ; e8 83 a2
     mov si, ax                                ; 89 c6
     xor cl, cl                                ; 30 c9
     xor dx, dx                                ; 31 d2
@@ -10535,9 +10524,9 @@ show_logo_:                                  ; 0xf7370 LB 0x224
     mov AL, strict byte 048h                  ; b0 48
     out strict byte 040h, AL                  ; e6 40
     movzx ax, dl                              ; 0f b6 c2
-    call 07204h                               ; e8 68 fe
+    call 07219h                               ; e8 68 fe
     cmp ax, 066bbh                            ; 3d bb 66
-    jne near 07474h                           ; 0f 85 d1 00
+    jne near 07489h                           ; 0f 85 d1 00
     push SS                                   ; 16
     pop ES                                    ; 07
     lea di, [bp-016h]                         ; 8d 7e ea
@@ -10545,119 +10534,119 @@ show_logo_:                                  ; 0xf7370 LB 0x224
     int 010h                                  ; cd 10
     mov word [es:di], bx                      ; 26 89 1d
     cmp ax, strict word 0004fh                ; 3d 4f 00
-    jne near 07474h                           ; 0f 85 bd 00
+    jne near 07489h                           ; 0f 85 bd 00
     mov al, dl                                ; 88 d0
     add AL, strict byte 004h                  ; 04 04
     xor ah, ah                                ; 30 e4
-    call 071eeh                               ; e8 2e fe
+    call 07203h                               ; e8 2e fe
     mov ch, al                                ; 88 c5
     mov byte [bp-00ch], al                    ; 88 46 f4
     mov al, dl                                ; 88 d0
     add AL, strict byte 005h                  ; 04 05
     xor ah, ah                                ; 30 e4
-    call 071eeh                               ; e8 20 fe
+    call 07203h                               ; e8 20 fe
     mov dh, al                                ; 88 c6
     mov byte [bp-010h], al                    ; 88 46 f0
     mov al, dl                                ; 88 d0
     add AL, strict byte 002h                  ; 04 02
     xor ah, ah                                ; 30 e4
-    call 07204h                               ; e8 28 fe
+    call 07219h                               ; e8 28 fe
     mov bx, ax                                ; 89 c3
     mov word [bp-014h], ax                    ; 89 46 ec
     mov al, dl                                ; 88 d0
     add AL, strict byte 006h                  ; 04 06
     xor ah, ah                                ; 30 e4
-    call 071eeh                               ; e8 04 fe
+    call 07203h                               ; e8 04 fe
     mov byte [bp-012h], al                    ; 88 46 ee
     test ch, ch                               ; 84 ed
-    jne short 073fbh                          ; 75 0a
+    jne short 07410h                          ; 75 0a
     test dh, dh                               ; 84 f6
-    jne short 073fbh                          ; 75 06
+    jne short 07410h                          ; 75 06
     test bx, bx                               ; 85 db
-    je near 07474h                            ; 0f 84 79 00
+    je near 07489h                            ; 0f 84 79 00
     mov bx, 00142h                            ; bb 42 01
     mov ax, 04f02h                            ; b8 02 4f
     int 010h                                  ; cd 10
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    je short 0742ch                           ; 74 23
+    je short 07441h                           ; 74 23
     xor bx, bx                                ; 31 db
-    jmp short 07413h                          ; eb 06
+    jmp short 07428h                          ; eb 06
     inc bx                                    ; 43
     cmp bx, strict byte 00010h                ; 83 fb 10
-    jnbe short 07433h                         ; 77 20
+    jnbe short 07448h                         ; 77 20
     mov ax, bx                                ; 89 d8
     or ah, 002h                               ; 80 cc 02
     mov dx, 003b8h                            ; ba b8 03
     out DX, ax                                ; ef
     xor dx, dx                                ; 31 d2
     mov ax, strict word 00001h                ; b8 01 00
-    call 0713ch                               ; e8 18 fd
+    call 07151h                               ; e8 18 fd
     cmp AL, strict byte 086h                  ; 3c 86
-    jne short 0740dh                          ; 75 e5
+    jne short 07422h                          ; 75 e5
     mov CL, strict byte 001h                  ; b1 01
-    jmp short 07433h                          ; eb 07
+    jmp short 07448h                          ; eb 07
     mov ax, 00210h                            ; b8 10 02
     mov dx, 003b8h                            ; ba b8 03
     out DX, ax                                ; ef
     test cl, cl                               ; 84 c9
-    jne short 07449h                          ; 75 12
+    jne short 0745eh                          ; 75 12
     mov ax, word [bp-014h]                    ; 8b 46 ec
     shr ax, 004h                              ; c1 e8 04
     mov dx, strict word 00001h                ; ba 01 00
-    call 0713ch                               ; e8 f9 fc
+    call 07151h                               ; e8 f9 fc
     cmp AL, strict byte 086h                  ; 3c 86
-    jne short 07449h                          ; 75 02
+    jne short 0745eh                          ; 75 02
     mov CL, strict byte 001h                  ; b1 01
     cmp byte [bp-010h], 000h                  ; 80 7e f0 00
-    je short 07474h                           ; 74 25
+    je short 07489h                           ; 74 25
     test cl, cl                               ; 84 c9
-    jne short 07474h                          ; 75 21
+    jne short 07489h                          ; 75 21
     mov bx, strict word 00010h                ; bb 10 00
-    jmp short 0745dh                          ; eb 05
+    jmp short 07472h                          ; eb 05
     dec bx                                    ; 4b
     test bx, bx                               ; 85 db
-    jbe short 07474h                          ; 76 17
+    jbe short 07489h                          ; 76 17
     mov ax, bx                                ; 89 d8
     or ah, 002h                               ; 80 cc 02
     mov dx, 003b8h                            ; ba b8 03
     out DX, ax                                ; ef
     xor dx, dx                                ; 31 d2
     mov ax, strict word 00001h                ; b8 01 00
-    call 0713ch                               ; e8 ce fc
+    call 07151h                               ; e8 ce fc
     cmp AL, strict byte 086h                  ; 3c 86
-    jne short 07458h                          ; 75 e6
+    jne short 0746dh                          ; 75 e6
     mov CL, strict byte 001h                  ; b1 01
     xor bx, bx                                ; 31 db
     mov dx, 00339h                            ; ba 39 03
     mov ax, si                                ; 89 f0
-    call 0160eh                               ; e8 90 a1
+    call 0160eh                               ; e8 7b a1
     mov AL, strict byte 003h                  ; b0 03
     mov AH, strict byte 000h                  ; b4 00
     int 010h                                  ; cd 10
     cmp byte [bp-012h], 000h                  ; 80 7e ee 00
-    je near 07575h                            ; 0f 84 e9 00
+    je near 0758ah                            ; 0f 84 e9 00
     cmp byte [bp-00ch], 000h                  ; 80 7e f4 00
-    jne short 074c2h                          ; 75 30
+    jne short 074d7h                          ; 75 30
     cmp byte [bp-010h], 000h                  ; 80 7e f0 00
-    jne short 074c2h                          ; 75 2a
+    jne short 074d7h                          ; 75 2a
     cmp word [bp-014h], strict byte 00000h    ; 83 7e ec 00
-    jne short 074c2h                          ; 75 24
+    jne short 074d7h                          ; 75 24
     cmp byte [bp-012h], 002h                  ; 80 7e ee 02
-    jne short 074afh                          ; 75 0b
-    push 00a3ch                               ; 68 3c 0a
+    jne short 074c4h                          ; 75 0b
+    push 00a53h                               ; 68 53 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 61 a4
+    call 01922h                               ; e8 61 a4
     add sp, strict byte 00004h                ; 83 c4 04
     test cl, cl                               ; 84 c9
-    jne short 074c2h                          ; 75 0f
+    jne short 074d7h                          ; 75 0f
     mov dx, strict word 00001h                ; ba 01 00
     mov ax, 000c0h                            ; b8 c0 00
-    call 0713ch                               ; e8 80 fc
+    call 07151h                               ; e8 80 fc
     cmp AL, strict byte 086h                  ; 3c 86
-    jne short 074c2h                          ; 75 02
+    jne short 074d7h                          ; 75 02
     mov CL, strict byte 001h                  ; b1 01
     test cl, cl                               ; 84 c9
-    je near 07575h                            ; 0f 84 ad 00
+    je near 0758ah                            ; 0f 84 ad 00
     mov byte [bp-00eh], 000h                  ; c6 46 f2 00
     mov ax, 00100h                            ; b8 00 01
     mov cx, 01000h                            ; b9 00 10
@@ -10674,56 +10663,56 @@ show_logo_:                                  ; 0xf7370 LB 0x224
     db  033h, 0d2h
     ; xor dx, dx                                ; 33 d2
     int 010h                                  ; cd 10
-    push 00a5eh                               ; 68 5e 0a
+    push 00a75h                               ; 68 75 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 1c a4
+    call 01922h                               ; e8 1c a4
     add sp, strict byte 00004h                ; 83 c4 04
-    call 07218h                               ; e8 21 fd
-    push 00aa2h                               ; 68 a2 0a
+    call 0722dh                               ; e8 21 fd
+    push 00ab9h                               ; 68 b9 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 0e a4
+    call 01922h                               ; e8 0e a4
     add sp, strict byte 00004h                ; 83 c4 04
     mov dx, strict word 00001h                ; ba 01 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0713ch                               ; e8 31 fc
+    call 07151h                               ; e8 31 fc
     mov bl, al                                ; 88 c3
     test al, al                               ; 84 c0
-    je short 07502h                           ; 74 f1
+    je short 07517h                           ; 74 f1
     cmp AL, strict byte 030h                  ; 3c 30
-    je short 07563h                           ; 74 4e
+    je short 07578h                           ; 74 4e
     cmp bl, 002h                              ; 80 fb 02
-    jc short 0753ch                           ; 72 22
+    jc short 07551h                           ; 72 22
     cmp bl, 009h                              ; 80 fb 09
-    jnbe short 0753ch                         ; 77 1d
+    jnbe short 07551h                         ; 77 1d
     movzx ax, bl                              ; 0f b6 c3
-    call 07348h                               ; e8 23 fe
+    call 0735dh                               ; e8 23 fe
     cmp AL, strict byte 0ffh                  ; 3c ff
-    jne short 0752bh                          ; 75 02
-    jmp short 07502h                          ; eb d7
+    jne short 07540h                          ; 75 02
+    jmp short 07517h                          ; eb d7
     movzx bx, al                              ; 0f b6 d8
     mov dx, 00338h                            ; ba 38 03
     mov ax, si                                ; 89 f0
-    call 0160eh                               ; e8 d8 a0
+    call 0160eh                               ; e8 c3 a0
     mov byte [bp-00eh], 002h                  ; c6 46 f2 02
-    jmp short 07563h                          ; eb 27
+    jmp short 07578h                          ; eb 27
     cmp bl, 02eh                              ; 80 fb 2e
-    je short 07551h                           ; 74 10
+    je short 07566h                           ; 74 10
     cmp bl, 026h                              ; 80 fb 26
-    je short 07557h                           ; 74 11
+    je short 0756ch                           ; 74 11
     cmp bl, 021h                              ; 80 fb 21
-    jne short 0755dh                          ; 75 12
+    jne short 07572h                          ; 75 12
     mov byte [bp-00eh], 001h                  ; c6 46 f2 01
-    jmp short 07563h                          ; eb 12
+    jmp short 07578h                          ; eb 12
     mov byte [bp-00eh], 003h                  ; c6 46 f2 03
-    jmp short 07563h                          ; eb 0c
+    jmp short 07578h                          ; eb 0c
     mov byte [bp-00eh], 004h                  ; c6 46 f2 04
-    jmp short 07563h                          ; eb 06
+    jmp short 07578h                          ; eb 06
     cmp byte [bp-00eh], 000h                  ; 80 7e f2 00
-    je short 07502h                           ; 74 9f
+    je short 07517h                           ; 74 9f
     movzx bx, byte [bp-00eh]                  ; 0f b6 5e f2
     mov dx, 00339h                            ; ba 39 03
     mov ax, si                                ; 89 f0
-    call 0160eh                               ; e8 9f a0
+    call 0160eh                               ; e8 8a a0
     mov AL, strict byte 003h                  ; b0 03
     mov AH, strict byte 000h                  ; b4 00
     int 010h                                  ; cd 10
@@ -10736,7 +10725,7 @@ show_logo_:                                  ; 0xf7370 LB 0x224
     pushad                                    ; 66 60
     push DS                                   ; 1e
     mov ds, ax                                ; 8e d8
-    call 0edbfh                               ; e8 38 78
+    call 0edbfh                               ; e8 23 78
     pop DS                                    ; 1f
     popad                                     ; 66 61
     lea sp, [bp-00ah]                         ; 8d 66 f6
@@ -10747,14 +10736,14 @@ show_logo_:                                  ; 0xf7370 LB 0x224
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-delay_boot_:                                 ; 0xf7594 LB 0x67
+delay_boot_:                                 ; 0xf75a9 LB 0x67
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
     push dx                                   ; 52
     mov dx, ax                                ; 89 c2
     test ax, ax                               ; 85 c0
-    je short 075f4h                           ; 74 55
+    je short 07609h                           ; 74 55
     mov AL, strict byte 034h                  ; b0 34
     out strict byte 043h, AL                  ; e6 43
     mov AL, strict byte 0d3h                  ; b0 d3
@@ -10762,26 +10751,26 @@ delay_boot_:                                 ; 0xf7594 LB 0x67
     mov AL, strict byte 048h                  ; b0 48
     out strict byte 040h, AL                  ; e6 40
     push dx                                   ; 52
-    push 00aech                               ; 68 ec 0a
+    push 00b03h                               ; 68 03 0b
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 59 a3
+    call 01922h                               ; e8 59 a3
     add sp, strict byte 00006h                ; 83 c4 06
     mov bx, dx                                ; 89 d3
     test bx, bx                               ; 85 db
-    jbe short 075d4h                          ; 76 17
+    jbe short 075e9h                          ; 76 17
     push bx                                   ; 53
-    push 00b0ah                               ; 68 0a 0b
+    push 00b21h                               ; 68 21 0b
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 47 a3
+    call 01922h                               ; e8 47 a3
     add sp, strict byte 00006h                ; 83 c4 06
     xor dx, dx                                ; 31 d2
     mov ax, strict word 00040h                ; b8 40 00
-    call 0713ch                               ; e8 6b fb
+    call 07151h                               ; e8 6b fb
     dec bx                                    ; 4b
-    jmp short 075b9h                          ; eb e5
-    push 00a3ah                               ; 68 3a 0a
+    jmp short 075ceh                          ; eb e5
+    push 00a51h                               ; 68 51 0a
     push strict byte 00002h                   ; 6a 02
-    call 0190dh                               ; e8 31 a3
+    call 01922h                               ; e8 31 a3
     add sp, strict byte 00004h                ; 83 c4 04
     mov AL, strict byte 034h                  ; b0 34
     out strict byte 043h, AL                  ; e6 43
@@ -10792,7 +10781,7 @@ delay_boot_:                                 ; 0xf7594 LB 0x67
     pushad                                    ; 66 60
     push DS                                   ; 1e
     mov ds, ax                                ; 8e d8
-    call 0edbfh                               ; e8 ce 77
+    call 0edbfh                               ; e8 b9 77
     pop DS                                    ; 1f
     popad                                     ; 66 61
     lea sp, [bp-004h]                         ; 8d 66 fc
@@ -10800,7 +10789,7 @@ delay_boot_:                                 ; 0xf7594 LB 0x67
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-scsi_cmd_data_in_:                           ; 0xf75fb LB 0xb2
+scsi_cmd_data_in_:                           ; 0xf7610 LB 0xb2
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -10816,13 +10805,13 @@ scsi_cmd_data_in_:                           ; 0xf75fb LB 0xb2
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 07611h                          ; 75 f7
+    jne short 07626h                          ; 75 f7
     mov ax, bx                                ; 89 d8
     mov dx, word [bp+00ch]                    ; 8b 56 0c
     mov cx, strict word 0000ch                ; b9 0c 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 07622h                               ; e2 fa
+    loop 07637h                               ; e2 fa
     and ax, 000f0h                            ; 25 f0 00
     movzx cx, byte [bp+004h]                  ; 0f b6 4e 04
     or cx, ax                                 ; 09 c1
@@ -10840,31 +10829,31 @@ scsi_cmd_data_in_:                           ; 0xf75fb LB 0xb2
     mov cx, strict word 00008h                ; b9 08 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 07648h                               ; e2 fa
+    loop 0765dh                               ; e2 fa
     mov dx, si                                ; 89 f2
     out DX, AL                                ; ee
     xor cx, cx                                ; 31 c9
     movzx ax, byte [bp+004h]                  ; 0f b6 46 04
     cmp cx, ax                                ; 39 c1
-    jnc short 07669h                          ; 73 0e
+    jnc short 0767eh                          ; 73 0e
     les di, [bp-00ah]                         ; c4 7e f6
     add di, cx                                ; 01 cf
     mov al, byte [es:di]                      ; 26 8a 05
     mov dx, si                                ; 89 f2
     out DX, AL                                ; ee
     inc cx                                    ; 41
-    jmp short 07653h                          ; eb ea
+    jmp short 07668h                          ; eb ea
     mov dx, si                                ; 89 f2
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 07669h                          ; 75 f7
+    jne short 0767eh                          ; 75 f7
     lea dx, [si+001h]                         ; 8d 54 01
     cmp word [bp+00ch], strict byte 00000h    ; 83 7e 0c 00
-    jne short 07681h                          ; 75 06
+    jne short 07696h                          ; 75 06
     cmp bx, 08000h                            ; 81 fb 00 80
-    jbe short 0769bh                          ; 76 1a
+    jbe short 076b0h                          ; 76 1a
     mov cx, 08000h                            ; b9 00 80
     les di, [bp+006h]                         ; c4 7e 06
     rep insb                                  ; f3 6c
@@ -10873,7 +10862,7 @@ scsi_cmd_data_in_:                           ; 0xf75fb LB 0xb2
     mov ax, es                                ; 8c c0
     add ax, 00800h                            ; 05 00 08
     mov word [bp+008h], ax                    ; 89 46 08
-    jmp short 07672h                          ; eb d7
+    jmp short 07687h                          ; eb d7
     mov cx, bx                                ; 89 d9
     les di, [bp+006h]                         ; c4 7e 06
     rep insb                                  ; f3 6c
@@ -10883,7 +10872,7 @@ scsi_cmd_data_in_:                           ; 0xf75fb LB 0xb2
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 0000ah                               ; c2 0a 00
-scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
+scsi_cmd_data_out_:                          ; 0xf76c2 LB 0xb4
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -10899,13 +10888,13 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 076c3h                          ; 75 f7
+    jne short 076d8h                          ; 75 f7
     mov ax, bx                                ; 89 d8
     mov dx, word [bp+00ch]                    ; 8b 56 0c
     mov cx, strict word 0000ch                ; b9 0c 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 076d4h                               ; e2 fa
+    loop 076e9h                               ; e2 fa
     and ax, 000f0h                            ; 25 f0 00
     movzx cx, byte [bp+004h]                  ; 0f b6 4e 04
     or cx, ax                                 ; 09 c1
@@ -10923,25 +10912,25 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     mov cx, strict word 00008h                ; b9 08 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 076fah                               ; e2 fa
+    loop 0770fh                               ; e2 fa
     mov dx, di                                ; 89 fa
     out DX, AL                                ; ee
     xor cx, cx                                ; 31 c9
     movzx ax, byte [bp+004h]                  ; 0f b6 46 04
     cmp cx, ax                                ; 39 c1
-    jnc short 0771bh                          ; 73 0e
+    jnc short 07730h                          ; 73 0e
     les si, [bp-00ah]                         ; c4 76 f6
     add si, cx                                ; 01 ce
     mov al, byte [es:si]                      ; 26 8a 04
     mov dx, di                                ; 89 fa
     out DX, AL                                ; ee
     inc cx                                    ; 41
-    jmp short 07705h                          ; eb ea
+    jmp short 0771ah                          ; eb ea
     lea dx, [di+001h]                         ; 8d 55 01
     cmp word [bp+00ch], strict byte 00000h    ; 83 7e 0c 00
-    jne short 0772ah                          ; 75 06
+    jne short 0773fh                          ; 75 06
     cmp bx, 08000h                            ; 81 fb 00 80
-    jbe short 07745h                          ; 76 1b
+    jbe short 0775ah                          ; 76 1b
     mov cx, 08000h                            ; b9 00 80
     les si, [bp+006h]                         ; c4 76 06
     db  0f3h, 026h, 06eh
@@ -10951,7 +10940,7 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     mov ax, es                                ; 8c c0
     add ax, 00800h                            ; 05 00 08
     mov word [bp+008h], ax                    ; 89 46 08
-    jmp short 0771bh                          ; eb d6
+    jmp short 07730h                          ; eb d6
     mov cx, bx                                ; 89 d9
     les si, [bp+006h]                         ; c4 76 06
     db  0f3h, 026h, 06eh
@@ -10961,14 +10950,14 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 0774dh                          ; 75 f7
+    jne short 07762h                          ; 75 f7
     xor ax, ax                                ; 31 c0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 0000ah                               ; c2 0a 00
- at scsi_read_sectors:                          ; 0xf7761 LB 0xb6
+ at scsi_read_sectors:                          ; 0xf7776 LB 0xb6
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -10979,12 +10968,12 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     mov bl, byte [es:si+008h]                 ; 26 8a 5c 08
     sub bl, 008h                              ; 80 eb 08
     cmp bl, 004h                              ; 80 fb 04
-    jbe short 0778ah                          ; 76 0f
+    jbe short 0779fh                          ; 76 0f
     movzx ax, bl                              ; 0f b6 c3
     push ax                                   ; 50
-    push 00b0eh                               ; 68 0e 0b
+    push 00b26h                               ; 68 26 0b
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 86 a1
+    call 01922h                               ; e8 86 a1
     add sp, strict byte 00006h                ; 83 c4 06
     mov es, [bp+006h]                         ; 8e 46 06
     mov di, word [es:si+00ah]                 ; 26 8b 7c 0a
@@ -11011,7 +11000,7 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     mov cx, strict word 00009h                ; b9 09 00
     sal word [bp-008h], 1                     ; d1 66 f8
     rcl word [bp-006h], 1                     ; d1 56 fa
-    loop 077d3h                               ; e2 f8
+    loop 077e8h                               ; e2 f8
     push dword [bp-008h]                      ; 66 ff 76 f8
     db  066h, 026h, 0ffh, 074h, 004h
     ; push dword [es:si+004h]                   ; 66 26 ff 74 04
@@ -11019,10 +11008,10 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     xor dh, dh                                ; 30 f6
     mov cx, ss                                ; 8c d1
     lea bx, [bp-012h]                         ; 8d 5e ee
-    call 075fbh                               ; e8 0b fe
+    call 07610h                               ; e8 0b fe
     mov ah, al                                ; 88 c4
     test al, al                               ; 84 c0
-    jne short 0780bh                          ; 75 15
+    jne short 07820h                          ; 75 15
     mov es, [bp+006h]                         ; 8e 46 06
     mov word [es:si+014h], di                 ; 26 89 7c 14
     mov dx, word [bp-008h]                    ; 8b 56 f8
@@ -11035,7 +11024,7 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
- at scsi_write_sectors:                         ; 0xf7817 LB 0xb6
+ at scsi_write_sectors:                         ; 0xf782c LB 0xb6
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -11046,12 +11035,12 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     mov bl, byte [es:si+008h]                 ; 26 8a 5c 08
     sub bl, 008h                              ; 80 eb 08
     cmp bl, 004h                              ; 80 fb 04
-    jbe short 07840h                          ; 76 0f
+    jbe short 07855h                          ; 76 0f
     movzx ax, bl                              ; 0f b6 c3
     push ax                                   ; 50
-    push 00b3ch                               ; 68 3c 0b
+    push 00b54h                               ; 68 54 0b
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 d0 a0
+    call 01922h                               ; e8 d0 a0
     add sp, strict byte 00006h                ; 83 c4 06
     mov es, [bp+006h]                         ; 8e 46 06
     mov di, word [es:si+00ah]                 ; 26 8b 7c 0a
@@ -11078,7 +11067,7 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     mov cx, strict word 00009h                ; b9 09 00
     sal word [bp-008h], 1                     ; d1 66 f8
     rcl word [bp-006h], 1                     ; d1 56 fa
-    loop 07889h                               ; e2 f8
+    loop 0789eh                               ; e2 f8
     push dword [bp-008h]                      ; 66 ff 76 f8
     db  066h, 026h, 0ffh, 074h, 004h
     ; push dword [es:si+004h]                   ; 66 26 ff 74 04
@@ -11086,10 +11075,10 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     xor dh, dh                                ; 30 f6
     mov cx, ss                                ; 8c d1
     lea bx, [bp-012h]                         ; 8d 5e ee
-    call 076adh                               ; e8 07 fe
+    call 076c2h                               ; e8 07 fe
     mov ah, al                                ; 88 c4
     test al, al                               ; 84 c0
-    jne short 078c1h                          ; 75 15
+    jne short 078d6h                          ; 75 15
     mov es, [bp+006h]                         ; 8e 46 06
     mov word [es:si+014h], di                 ; 26 89 7c 14
     mov dx, word [bp-008h]                    ; 8b 56 f8
@@ -11102,7 +11091,7 @@ scsi_cmd_data_out_:                          ; 0xf76ad LB 0xb4
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
-scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
+scsi_cmd_packet_:                            ; 0xf78e2 LB 0x166
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -11114,22 +11103,22 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     mov word [bp-00ah], cx                    ; 89 4e f6
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 33 9d
+    call 0161ch                               ; e8 1e 9d
     mov si, 00122h                            ; be 22 01
     mov word [bp-00eh], ax                    ; 89 46 f2
     cmp byte [bp+00ah], 002h                  ; 80 7e 0a 02
-    jne short 07914h                          ; 75 1f
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 07929h                          ; 75 1f
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 cc 9f
-    push 00b6bh                               ; 68 6b 0b
-    push 00b7bh                               ; 68 7b 0b
+    call 018e1h                               ; e8 cc 9f
+    push 00b83h                               ; 68 83 0b
+    push 00b93h                               ; 68 93 0b
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 02 a0
+    call 01922h                               ; e8 02 a0
     add sp, strict byte 00006h                ; 83 c4 06
     mov dx, strict word 00001h                ; ba 01 00
-    jmp near 07a28h                           ; e9 14 01
+    jmp near 07a3dh                           ; e9 14 01
     sub di, strict byte 00008h                ; 83 ef 08
     sal di, 002h                              ; c1 e7 02
     sub byte [bp-006h], 002h                  ; 80 6e fa 02
@@ -11143,7 +11132,7 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 07930h                          ; 75 f7
+    jne short 07945h                          ; 75 f7
     xor ax, ax                                ; 31 c0
     mov dx, word [bp+006h]                    ; 8b 56 06
     add dx, word [bp+004h]                    ; 03 56 04
@@ -11159,7 +11148,7 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     mov cx, strict word 0000ch                ; b9 0c 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 0795bh                               ; e2 fa
+    loop 07970h                               ; e2 fa
     and ax, 000f0h                            ; 25 f0 00
     movzx cx, byte [bp-006h]                  ; 0f b6 4e fa
     or cx, ax                                 ; 09 c1
@@ -11177,28 +11166,28 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     mov cx, strict word 00008h                ; b9 08 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 07982h                               ; e2 fa
+    loop 07997h                               ; e2 fa
     mov dx, bx                                ; 89 da
     out DX, AL                                ; ee
     xor cx, cx                                ; 31 c9
     movzx ax, byte [bp-006h]                  ; 0f b6 46 fa
     cmp cx, ax                                ; 39 c1
-    jnc short 079a3h                          ; 73 0e
+    jnc short 079b8h                          ; 73 0e
     les di, [bp-00ch]                         ; c4 7e f4
     add di, cx                                ; 01 cf
     mov al, byte [es:di]                      ; 26 8a 05
     mov dx, bx                                ; 89 da
     out DX, AL                                ; ee
     inc cx                                    ; 41
-    jmp short 0798dh                          ; eb ea
+    jmp short 079a2h                          ; eb ea
     mov dx, bx                                ; 89 da
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     test AL, strict byte 001h                 ; a8 01
-    jne short 079a3h                          ; 75 f7
+    jne short 079b8h                          ; 75 f7
     test AL, strict byte 002h                 ; a8 02
-    je short 079beh                           ; 74 0e
+    je short 079d3h                           ; 74 0e
     lea dx, [bx+003h]                         ; 8d 57 03
     xor al, al                                ; 30 c0
     out DX, AL                                ; ee
@@ -11206,14 +11195,14 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     mov dx, strict word 00003h                ; ba 03 00
-    jmp short 07a28h                          ; eb 6a
+    jmp short 07a3dh                          ; eb 6a
     mov ax, word [bp+004h]                    ; 8b 46 04
     test ax, ax                               ; 85 c0
-    je short 079cdh                           ; 74 08
+    je short 079e2h                           ; 74 08
     lea dx, [bx+001h]                         ; 8d 57 01
     mov cx, ax                                ; 89 c1
     in AL, DX                                 ; ec
-    loop 079cah                               ; e2 fd
+    loop 079dfh                               ; e2 fd
     mov ax, word [bp+006h]                    ; 8b 46 06
     mov es, [bp-00eh]                         ; 8e 46 f2
     mov word [es:si+016h], ax                 ; 26 89 44 16
@@ -11221,9 +11210,9 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     mov word [es:si+018h], ax                 ; 26 89 44 18
     lea ax, [bx+001h]                         ; 8d 47 01
     cmp word [bp+008h], strict byte 00000h    ; 83 7e 08 00
-    jne short 079eeh                          ; 75 07
+    jne short 07a03h                          ; 75 07
     cmp word [bp+006h], 08000h                ; 81 7e 06 00 80
-    jbe short 07a0bh                          ; 76 1d
+    jbe short 07a20h                          ; 76 1d
     mov dx, ax                                ; 89 c2
     mov cx, 08000h                            ; b9 00 80
     les di, [bp+00ch]                         ; c4 7e 0c
@@ -11233,17 +11222,17 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     mov ax, es                                ; 8c c0
     add ax, 00800h                            ; 05 00 08
     mov word [bp+00eh], ax                    ; 89 46 0e
-    jmp short 079deh                          ; eb d3
+    jmp short 079f3h                          ; eb d3
     mov dx, ax                                ; 89 c2
     mov cx, word [bp+006h]                    ; 8b 4e 06
     les di, [bp+00ch]                         ; c4 7e 0c
     rep insb                                  ; f3 6c
     mov es, [bp-00eh]                         ; 8e 46 f2
     cmp word [es:si+01ch], strict byte 00000h ; 26 83 7c 1c 00
-    je short 07a26h                           ; 74 07
+    je short 07a3bh                           ; 74 07
     mov cx, word [es:si+01ch]                 ; 26 8b 4c 1c
     in AL, DX                                 ; ec
-    loop 07a23h                               ; e2 fd
+    loop 07a38h                               ; e2 fd
     xor dx, dx                                ; 31 d2
     mov ax, dx                                ; 89 d0
     lea sp, [bp-004h]                         ; 8d 66 fc
@@ -11251,7 +11240,7 @@ scsi_cmd_packet_:                            ; 0xf78cd LB 0x166
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 0000ch                               ; c2 0c 00
-scsi_enumerate_attached_devices_:            ; 0xf7a33 LB 0x373
+scsi_enumerate_attached_devices_:            ; 0xf7a48 LB 0x3e5
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -11259,119 +11248,174 @@ scsi_enumerate_attached_devices_:            ; 0xf7a33 LB 0x373
     push dx                                   ; 52
     push si                                   ; 56
     push di                                   ; 57
-    sub sp, 0021eh                            ; 81 ec 1e 02
+    sub sp, 0021ch                            ; 81 ec 1c 02
     push ax                                   ; 50
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 d3 9b
+    call 0161ch                               ; e8 be 9b
     mov si, 00122h                            ; be 22 01
-    mov word [bp-012h], ax                    ; 89 46 ee
-    mov word [bp-014h], strict word 00000h    ; c7 46 ec 00 00
-    jmp near 07d34h                           ; e9 dd 02
-    mov es, [bp-012h]                         ; 8e 46 ee
+    mov word [bp-01ah], ax                    ; 89 46 e6
+    mov word [bp-010h], strict word 00000h    ; c7 46 f0 00 00
+    jmp near 07dbbh                           ; e9 4f 03
+    mov es, [bp-01ah]                         ; 8e 46 e6
     cmp byte [es:si+001e8h], 004h             ; 26 80 bc e8 01 04
-    jnc near 07d9ch                           ; 0f 83 38 03
+    jnc near 07e23h                           ; 0f 83 aa 03
     mov cx, strict word 0000ah                ; b9 0a 00
     xor bx, bx                                ; 31 db
     mov dx, ss                                ; 8c d2
-    lea ax, [bp-028h]                         ; 8d 46 d8
-    call 093dah                               ; e8 69 19
-    mov byte [bp-028h], 025h                  ; c6 46 d8 25
+    lea ax, [bp-026h]                         ; 8d 46 da
+    call 0948ah                               ; e8 04 1a
+    mov byte [bp-026h], 025h                  ; c6 46 da 25
     push dword 000000008h                     ; 66 6a 08
-    lea dx, [bp-00228h]                       ; 8d 96 d8 fd
+    lea dx, [bp-00226h]                       ; 8d 96 da fd
     push SS                                   ; 16
     push dx                                   ; 52
     push strict byte 0000ah                   ; 6a 0a
-    movzx dx, byte [bp-014h]                  ; 0f b6 56 ec
+    movzx dx, byte [bp-010h]                  ; 0f b6 56 f0
     mov cx, ss                                ; 8c d1
-    lea bx, [bp-028h]                         ; 8d 5e d8
-    mov ax, word [bp-0022ah]                  ; 8b 86 d6 fd
-    call 075fbh                               ; e8 6b fb
+    lea bx, [bp-026h]                         ; 8d 5e da
+    mov ax, word [bp-00228h]                  ; 8b 86 d8 fd
+    call 07610h                               ; e8 6b fb
     test al, al                               ; 84 c0
-    je short 07aa2h                           ; 74 0e
-    push 00b9bh                               ; 68 9b 0b
-    push 00bd4h                               ; 68 d4 0b
+    je short 07ab7h                           ; 74 0e
+    push 00bb3h                               ; 68 b3 0b
+    push 00bech                               ; 68 ec 0b
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 6e 9e
+    call 01922h                               ; e8 6e 9e
     add sp, strict byte 00006h                ; 83 c4 06
-    movzx dx, byte [bp-00227h]                ; 0f b6 96 d9 fd
-    movzx di, byte [bp-00228h]                ; 0f b6 be d8 fd
+    movzx ax, byte [bp-00225h]                ; 0f b6 86 db fd
+    movzx di, byte [bp-00226h]                ; 0f b6 be da fd
     sal di, 008h                              ; c1 e7 08
     xor bx, bx                                ; 31 db
-    or di, dx                                 ; 09 d7
-    movzx ax, byte [bp-00226h]                ; 0f b6 86 da fd
+    or di, ax                                 ; 09 c7
+    movzx ax, byte [bp-00224h]                ; 0f b6 86 dc fd
     xor dx, dx                                ; 31 d2
     mov cx, strict word 00008h                ; b9 08 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 07abdh                               ; e2 fa
-    or ax, bx                                 ; 09 d8
-    or di, dx                                 ; 09 d7
-    movzx dx, byte [bp-00225h]                ; 0f b6 96 db fd
-    or ax, dx                                 ; 09 d0
-    mov word [bp-010h], ax                    ; 89 46 f0
-    movzx dx, byte [bp-00224h]                ; 0f b6 96 dc fd
-    sal dx, 008h                              ; c1 e2 08
+    loop 07ad2h                               ; e2 fa
+    or bx, ax                                 ; 09 c3
+    or dx, di                                 ; 09 fa
     movzx ax, byte [bp-00223h]                ; 0f b6 86 dd fd
-    or dx, ax                                 ; 09 c2
-    mov word [bp-01eh], dx                    ; 89 56 e2
-    movzx ax, byte [bp-00222h]                ; 0f b6 86 de fd
+    or bx, ax                                 ; 09 c3
+    mov word [bp-00eh], bx                    ; 89 5e f2
+    mov word [bp-018h], dx                    ; 89 56 e8
+    movzx di, byte [bp-00222h]                ; 0f b6 be de fd
+    sal di, 008h                              ; c1 e7 08
+    movzx dx, byte [bp-00221h]                ; 0f b6 96 df fd
+    xor bx, bx                                ; 31 db
+    or di, dx                                 ; 09 d7
+    movzx ax, byte [bp-00220h]                ; 0f b6 86 e0 fd
     xor dx, dx                                ; 31 d2
     mov cx, strict word 00008h                ; b9 08 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 07aedh                               ; e2 fa
-    or bx, ax                                 ; 09 c3
-    or dx, word [bp-01eh]                     ; 0b 56 e2
-    movzx ax, byte [bp-00221h]                ; 0f b6 86 df fd
-    or bx, ax                                 ; 09 c3
-    mov word [bp-00eh], bx                    ; 89 5e f2
+    loop 07b04h                               ; e2 fa
+    or ax, bx                                 ; 09 d8
+    or dx, di                                 ; 09 fa
+    movzx bx, byte [bp-0021fh]                ; 0f b6 9e e1 fd
+    or ax, bx                                 ; 09 d8
+    mov word [bp-016h], ax                    ; 89 46 ea
     test dx, dx                               ; 85 d2
-    jne short 07b0ch                          ; 75 06
-    cmp bx, 00200h                            ; 81 fb 00 02
-    je short 07b2ch                           ; 74 20
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 07b21h                          ; 75 05
+    cmp ax, 00200h                            ; 3d 00 02
+    je short 07b41h                           ; 74 20
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 b5 9d
+    call 018e1h                               ; e8 b5 9d
     push dx                                   ; 52
-    push word [bp-00eh]                       ; ff 76 f2
-    push word [bp-014h]                       ; ff 76 ec
-    push 00bf3h                               ; 68 f3 0b
+    push word [bp-016h]                       ; ff 76 ea
+    push word [bp-010h]                       ; ff 76 f0
+    push 00c0bh                               ; 68 0b 0c
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 e7 9d
+    call 01922h                               ; e8 e7 9d
     add sp, strict byte 0000ah                ; 83 c4 0a
-    jmp near 07d2bh                           ; e9 ff 01
-    cmp di, strict byte 00040h                ; 83 ff 40
-    jnbe short 07b33h                         ; 77 02
-    jne short 07b3dh                          ; 75 0a
-    mov dword [bp-018h], strict dword 000ff003fh ; 66 c7 46 e8 3f 00 ff 00
-    jmp short 07b56h                          ; eb 19
-    cmp di, strict byte 00020h                ; 83 ff 20
-    jnbe short 07b44h                         ; 77 02
-    jne short 07b4eh                          ; 75 0a
-    mov dword [bp-018h], strict dword 000800020h ; 66 c7 46 e8 20 00 80 00
-    jmp short 07b56h                          ; eb 08
-    mov dword [bp-018h], strict dword 000400020h ; 66 c7 46 e8 20 00 40 00
-    mov bx, word [bp-016h]                    ; 8b 5e ea
-    imul bx, word [bp-018h]                   ; 0f af 5e e8
-    mov ax, word [bp-010h]                    ; 8b 46 f0
-    mov dx, di                                ; 89 fa
-    xor cx, cx                                ; 31 c9
-    call 09370h                               ; e8 09 18
-    mov word [bp-01ch], ax                    ; 89 46 e4
-    mov word [bp-01ah], dx                    ; 89 56 e6
-    mov es, [bp-012h]                         ; 8e 46 ee
+    jmp near 07db2h                           ; e9 71 02
+    mov es, [bp-01ah]                         ; 8e 46 e6
     mov al, byte [es:si+001e8h]               ; 26 8a 84 e8 01
     mov byte [bp-00ch], al                    ; 88 46 f4
-    mov dl, al                                ; 88 c2
+    cmp AL, strict byte 001h                  ; 3c 01
+    jc short 07b5ch                           ; 72 0c
+    jbe short 07b64h                          ; 76 12
+    cmp AL, strict byte 003h                  ; 3c 03
+    je short 07b6ch                           ; 74 16
+    cmp AL, strict byte 002h                  ; 3c 02
+    je short 07b68h                           ; 74 0e
+    jmp short 07bb8h                          ; eb 5c
+    test al, al                               ; 84 c0
+    jne short 07bb8h                          ; 75 58
+    mov BL, strict byte 090h                  ; b3 90
+    jmp short 07b6eh                          ; eb 0a
+    mov BL, strict byte 098h                  ; b3 98
+    jmp short 07b6eh                          ; eb 06
+    mov BL, strict byte 0a0h                  ; b3 a0
+    jmp short 07b6eh                          ; eb 02
+    mov BL, strict byte 0a8h                  ; b3 a8
+    mov al, bl                                ; 88 d8
+    add AL, strict byte 007h                  ; 04 07
+    movzx cx, al                              ; 0f b6 c8
+    mov ax, cx                                ; 89 c8
+    call 0165ch                               ; e8 e2 9a
+    test al, al                               ; 84 c0
+    je short 07bb8h                           ; 74 3a
+    mov al, bl                                ; 88 d8
+    db  0feh, 0c0h
+    ; inc al                                    ; fe c0
+    xor ah, ah                                ; 30 e4
+    call 0165ch                               ; e8 d5 9a
+    xor ah, ah                                ; 30 e4
+    mov dx, ax                                ; 89 c2
+    sal dx, 008h                              ; c1 e2 08
+    movzx ax, bl                              ; 0f b6 c3
+    call 0165ch                               ; e8 c8 9a
+    xor ah, ah                                ; 30 e4
+    add ax, dx                                ; 01 d0
+    cwd                                       ; 99
+    mov di, ax                                ; 89 c7
+    mov word [bp-012h], dx                    ; 89 56 ee
+    mov al, bl                                ; 88 d8
+    add AL, strict byte 002h                  ; 04 02
+    xor ah, ah                                ; 30 e4
+    call 0165ch                               ; e8 b5 9a
+    xor ah, ah                                ; 30 e4
+    mov word [bp-014h], ax                    ; 89 46 ec
+    mov ax, cx                                ; 89 c8
+    call 0165ch                               ; e8 ab 9a
+    xor ah, ah                                ; 30 e4
+    mov word [bp-01ch], ax                    ; 89 46 e4
+    jmp short 07bfdh                          ; eb 45
+    mov ax, word [bp-018h]                    ; 8b 46 e8
+    cmp ax, strict word 00040h                ; 3d 40 00
+    jnbe short 07bc2h                         ; 77 02
+    jne short 07bceh                          ; 75 0c
+    mov word [bp-014h], 000ffh                ; c7 46 ec ff 00
+    mov word [bp-01ch], strict word 0003fh    ; c7 46 e4 3f 00
+    jmp short 07be6h                          ; eb 18
+    cmp ax, strict word 00020h                ; 3d 20 00
+    jnbe short 07bd5h                         ; 77 02
+    jne short 07bdch                          ; 75 07
+    mov word [bp-014h], 00080h                ; c7 46 ec 80 00
+    jmp short 07be1h                          ; eb 05
+    mov word [bp-014h], strict word 00040h    ; c7 46 ec 40 00
+    mov word [bp-01ch], strict word 00020h    ; c7 46 e4 20 00
+    mov bx, word [bp-014h]                    ; 8b 5e ec
+    imul bx, word [bp-01ch]                   ; 0f af 5e e4
+    mov ax, word [bp-00eh]                    ; 8b 46 f2
+    mov dx, word [bp-018h]                    ; 8b 56 e8
+    xor cx, cx                                ; 31 c9
+    call 09420h                               ; e8 28 18
+    mov di, ax                                ; 89 c7
+    mov word [bp-012h], dx                    ; 89 56 ee
+    mov dl, byte [bp-00ch]                    ; 8a 56 f4
     add dl, 008h                              ; 80 c2 08
-    movzx bx, al                              ; 0f b6 d8
+    movzx bx, byte [bp-00ch]                  ; 0f b6 5e f4
     sal bx, 002h                              ; c1 e3 02
+    mov es, [bp-01ah]                         ; 8e 46 e6
     add bx, si                                ; 01 f3
-    mov ax, word [bp-0022ah]                  ; 8b 86 d6 fd
+    mov ax, word [bp-00228h]                  ; 8b 86 d8 fd
     mov word [es:bx+001d8h], ax               ; 26 89 87 d8 01
-    mov al, byte [bp-014h]                    ; 8a 46 ec
+    mov al, byte [bp-010h]                    ; 8a 46 f0
     mov byte [es:bx+001dah], al               ; 26 88 87 da 01
     movzx ax, dl                              ; 0f b6 c2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
@@ -11379,62 +11423,61 @@ scsi_enumerate_attached_devices_:            ; 0xf7a33 LB 0x373
     add bx, ax                                ; 01 c3
     db  066h, 026h, 0c7h, 047h, 01eh, 004h, 0ffh, 000h, 000h
     ; mov dword [es:bx+01eh], strict dword 00000ff04h ; 66 26 c7 47 1e 04 ff 00 00
-    mov ax, word [bp-00eh]                    ; 8b 46 f2
+    mov ax, word [bp-016h]                    ; 8b 46 ea
     mov word [es:bx+024h], ax                 ; 26 89 47 24
     mov byte [es:bx+023h], 001h               ; 26 c6 47 23 01
-    mov ax, word [bp-016h]                    ; 8b 46 ea
+    mov ax, word [bp-014h]                    ; 8b 46 ec
     mov word [es:bx+026h], ax                 ; 26 89 47 26
-    mov ax, word [bp-018h]                    ; 8b 46 e8
+    mov ax, word [bp-01ch]                    ; 8b 46 e4
     mov word [es:bx+02ah], ax                 ; 26 89 47 2a
-    cmp word [bp-01ah], strict byte 00000h    ; 83 7e e6 00
-    jne short 07bd0h                          ; 75 07
-    cmp word [bp-01ch], 00400h                ; 81 7e e4 00 04
-    jbe short 07bd8h                          ; 76 08
+    cmp word [bp-012h], strict byte 00000h    ; 83 7e ee 00
+    jne short 07c59h                          ; 75 06
+    cmp di, 00400h                            ; 81 ff 00 04
+    jbe short 07c61h                          ; 76 08
     mov word [es:bx+028h], 00400h             ; 26 c7 47 28 00 04
-    jmp short 07bdfh                          ; eb 07
-    mov ax, word [bp-01ch]                    ; 8b 46 e4
-    mov word [es:bx+028h], ax                 ; 26 89 47 28
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp short 07c65h                          ; eb 04
+    mov word [es:bx+028h], di                 ; 26 89 7f 28
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 e2 9c
-    push di                                   ; 57
-    push word [bp-010h]                       ; ff 76 f0
+    call 018e1h                               ; e8 71 9c
     push word [bp-018h]                       ; ff 76 e8
-    push word [bp-016h]                       ; ff 76 ea
+    push word [bp-00eh]                       ; ff 76 f2
     push word [bp-01ch]                       ; ff 76 e4
     push word [bp-014h]                       ; ff 76 ec
+    push di                                   ; 57
+    push word [bp-010h]                       ; ff 76 f0
     movzx ax, byte [bp-00ch]                  ; 0f b6 46 f4
     push ax                                   ; 50
-    push 00c21h                               ; 68 21 0c
+    push 00c39h                               ; 68 39 0c
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 06 9d
+    call 01922h                               ; e8 95 9c
     add sp, strict byte 00012h                ; 83 c4 12
     movzx ax, dl                              ; 0f b6 c2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
-    mov es, [bp-012h]                         ; 8e 46 ee
+    mov es, [bp-01ah]                         ; 8e 46 e6
     mov bx, si                                ; 89 f3
     add bx, ax                                ; 01 c3
-    mov ax, word [bp-016h]                    ; 8b 46 ea
+    mov ax, word [bp-014h]                    ; 8b 46 ec
     mov word [es:bx+02ch], ax                 ; 26 89 47 2c
-    mov ax, word [bp-018h]                    ; 8b 46 e8
+    mov ax, word [bp-01ch]                    ; 8b 46 e4
     mov word [es:bx+030h], ax                 ; 26 89 47 30
-    cmp word [bp-01ah], strict byte 00000h    ; 83 7e e6 00
-    jne short 07c32h                          ; 75 07
-    cmp word [bp-01ch], 00400h                ; 81 7e e4 00 04
-    jbe short 07c3ah                          ; 76 08
+    cmp word [bp-012h], strict byte 00000h    ; 83 7e ee 00
+    jne short 07cb7h                          ; 75 06
+    cmp di, 00400h                            ; 81 ff 00 04
+    jbe short 07cbfh                          ; 76 08
     mov word [es:bx+02eh], 00400h             ; 26 c7 47 2e 00 04
-    jmp short 07c41h                          ; eb 07
-    mov ax, word [bp-01ch]                    ; 8b 46 e4
-    mov word [es:bx+02eh], ax                 ; 26 89 47 2e
+    jmp short 07cc3h                          ; eb 04
+    mov word [es:bx+02eh], di                 ; 26 89 7f 2e
     movzx ax, dl                              ; 0f b6 c2
     imul ax, ax, strict byte 00018h           ; 6b c0 18
-    mov es, [bp-012h]                         ; 8e 46 ee
+    mov es, [bp-01ah]                         ; 8e 46 e6
     mov bx, si                                ; 89 f3
     add bx, ax                                ; 01 c3
-    mov ax, word [bp-010h]                    ; 8b 46 f0
+    mov ax, word [bp-00eh]                    ; 8b 46 f2
     mov word [es:bx+032h], ax                 ; 26 89 47 32
-    mov word [es:bx+034h], di                 ; 26 89 7f 34
+    mov ax, word [bp-018h]                    ; 8b 46 e8
+    mov word [es:bx+034h], ax                 ; 26 89 47 34
     mov al, byte [es:si+0019eh]               ; 26 8a 84 9e 01
     mov ah, byte [bp-00ch]                    ; 8a 66 f4
     add ah, 008h                              ; 80 c4 08
@@ -11446,48 +11489,49 @@ scsi_enumerate_attached_devices_:            ; 0xf7a33 LB 0x373
     mov byte [es:si+0019eh], al               ; 26 88 84 9e 01
     mov dx, strict word 00075h                ; ba 75 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 82 99
+    call 01600h                               ; e8 fd 98
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00075h                ; ba 75 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 82 99
+    call 0160eh                               ; e8 fd 98
     inc byte [bp-00ch]                        ; fe 46 f4
     mov al, byte [bp-00ch]                    ; 8a 46 f4
-    mov es, [bp-012h]                         ; 8e 46 ee
+    mov es, [bp-01ah]                         ; 8e 46 e6
     mov byte [es:si+001e8h], al               ; 26 88 84 e8 01
-    jmp near 07d2bh                           ; e9 8e 00
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp near 07db2h                           ; e9 90 00
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 24 9c
-    push word [bp-014h]                       ; ff 76 ec
+    call 018e1h                               ; e8 b4 9b
+    push word [bp-010h]                       ; ff 76 f0
     movzx ax, byte [bp-00ch]                  ; 0f b6 46 f4
     push ax                                   ; 50
-    push 00c4bh                               ; 68 4b 0c
+    push 00c63h                               ; 68 63 0c
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 55 9c
+    call 01922h                               ; e8 e5 9b
     add sp, strict byte 00008h                ; 83 c4 08
     mov dl, byte [bp-00ch]                    ; 8a 56 f4
     add dl, 008h                              ; 80 c2 08
-    test byte [bp-00227h], 080h               ; f6 86 d9 fd 80
+    test byte [bp-00225h], 080h               ; f6 86 db fd 80
     db  00fh, 095h, 0c0h
     ; setne al                                  ; 0f 95 c0
     xor ah, ah                                ; 30 e4
     mov cx, ax                                ; 89 c1
     movzx ax, byte [bp-00ch]                  ; 0f b6 46 f4
     sal ax, 002h                              ; c1 e0 02
-    mov es, [bp-012h]                         ; 8e 46 ee
+    mov es, [bp-01ah]                         ; 8e 46 e6
     mov bx, si                                ; 89 f3
     add bx, ax                                ; 01 c3
-    mov ax, word [bp-0022ah]                  ; 8b 86 d6 fd
+    mov ax, word [bp-00228h]                  ; 8b 86 d8 fd
     mov word [es:bx+001d8h], ax               ; 26 89 87 d8 01
-    mov al, byte [bp-014h]                    ; 8a 46 ec
+    mov al, byte [bp-010h]                    ; 8a 46 f0
     mov byte [es:bx+001dah], al               ; 26 88 87 da 01
-    movzx bx, dl                              ; 0f b6 da
-    imul bx, bx, strict byte 00018h           ; 6b db 18
-    add bx, si                                ; 01 f3
+    movzx ax, dl                              ; 0f b6 c2
+    imul ax, ax, strict byte 00018h           ; 6b c0 18
+    mov bx, si                                ; 89 f3
+    add bx, ax                                ; 01 c3
     mov word [es:bx+01eh], 00504h             ; 26 c7 47 1e 04 05
     mov byte [es:bx+020h], cl                 ; 26 88 4f 20
     mov word [es:bx+024h], 00800h             ; 26 c7 47 24 00 08
@@ -11503,44 +11547,44 @@ scsi_enumerate_attached_devices_:            ; 0xf7a33 LB 0x373
     inc byte [bp-00ch]                        ; fe 46 f4
     mov al, byte [bp-00ch]                    ; 8a 46 f4
     mov byte [es:si+001e8h], al               ; 26 88 84 e8 01
-    inc word [bp-014h]                        ; ff 46 ec
-    cmp word [bp-014h], strict byte 00010h    ; 83 7e ec 10
-    jnl short 07d9ch                          ; 7d 68
-    mov byte [bp-028h], 012h                  ; c6 46 d8 12
+    inc word [bp-010h]                        ; ff 46 f0
+    cmp word [bp-010h], strict byte 00010h    ; 83 7e f0 10
+    jnl short 07e23h                          ; 7d 68
+    mov byte [bp-026h], 012h                  ; c6 46 da 12
     xor al, al                                ; 30 c0
-    mov byte [bp-027h], al                    ; 88 46 d9
-    mov byte [bp-026h], al                    ; 88 46 da
     mov byte [bp-025h], al                    ; 88 46 db
-    mov byte [bp-024h], 005h                  ; c6 46 dc 05
+    mov byte [bp-024h], al                    ; 88 46 dc
     mov byte [bp-023h], al                    ; 88 46 dd
+    mov byte [bp-022h], 005h                  ; c6 46 de 05
+    mov byte [bp-021h], al                    ; 88 46 df
     push dword 000000005h                     ; 66 6a 05
-    lea dx, [bp-00228h]                       ; 8d 96 d8 fd
+    lea dx, [bp-00226h]                       ; 8d 96 da fd
     push SS                                   ; 16
     push dx                                   ; 52
     push strict byte 00006h                   ; 6a 06
-    movzx dx, byte [bp-014h]                  ; 0f b6 56 ec
+    movzx dx, byte [bp-010h]                  ; 0f b6 56 f0
     mov cx, ss                                ; 8c d1
-    lea bx, [bp-028h]                         ; 8d 5e d8
-    mov ax, word [bp-0022ah]                  ; 8b 86 d6 fd
-    call 075fbh                               ; e8 96 f8
+    lea bx, [bp-026h]                         ; 8d 5e da
+    mov ax, word [bp-00228h]                  ; 8b 86 d8 fd
+    call 07610h                               ; e8 24 f8
     test al, al                               ; 84 c0
-    je short 07d77h                           ; 74 0e
-    push 00b9bh                               ; 68 9b 0b
-    push 00bbbh                               ; 68 bb 0b
+    je short 07dfeh                           ; 74 0e
+    push 00bb3h                               ; 68 b3 0b
+    push 00bd3h                               ; 68 d3 0b
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 99 9b
+    call 01922h                               ; e8 27 9b
     add sp, strict byte 00006h                ; 83 c4 06
-    test byte [bp-00228h], 0e0h               ; f6 86 d8 fd e0
-    jne short 07d87h                          ; 75 09
-    test byte [bp-00228h], 01fh               ; f6 86 d8 fd 1f
-    je near 07a57h                            ; 0f 84 d0 fc
-    test byte [bp-00228h], 0e0h               ; f6 86 d8 fd e0
-    jne short 07d2bh                          ; 75 9d
-    mov al, byte [bp-00228h]                  ; 8a 86 d8 fd
+    test byte [bp-00226h], 0e0h               ; f6 86 da fd e0
+    jne short 07e0eh                          ; 75 09
+    test byte [bp-00226h], 01fh               ; f6 86 da fd 1f
+    je near 07a6ch                            ; 0f 84 5e fc
+    test byte [bp-00226h], 0e0h               ; f6 86 da fd e0
+    jne short 07db2h                          ; 75 9d
+    mov al, byte [bp-00226h]                  ; 8a 86 da fd
     and AL, strict byte 01fh                  ; 24 1f
     cmp AL, strict byte 005h                  ; 3c 05
-    je near 07c9dh                            ; 0f 84 03 ff
-    jmp short 07d2bh                          ; eb 8f
+    je near 07d22h                            ; 0f 84 01 ff
+    jmp short 07db2h                          ; eb 8f
     lea sp, [bp-00ah]                         ; 8d 66 f6
     pop di                                    ; 5f
     pop si                                    ; 5e
@@ -11549,12 +11593,12 @@ scsi_enumerate_attached_devices_:            ; 0xf7a33 LB 0x373
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-_scsi_init:                                  ; 0xf7da6 LB 0x66
+_scsi_init:                                  ; 0xf7e2d LB 0x66
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 6a 98
+    call 0161ch                               ; e8 e3 97
     mov bx, 00122h                            ; bb 22 01
     mov es, ax                                ; 8e c0
     mov byte [es:bx+001e8h], 000h             ; 26 c6 87 e8 01 00
@@ -11565,12 +11609,12 @@ _scsi_init:                                  ; 0xf7da6 LB 0x66
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp AL, strict byte 055h                  ; 3c 55
-    jne short 07dd6h                          ; 75 0c
+    jne short 07e5dh                          ; 75 0c
     xor al, al                                ; 30 c0
     mov dx, 00433h                            ; ba 33 04
     out DX, AL                                ; ee
     mov ax, 00430h                            ; b8 30 04
-    call 07a33h                               ; e8 5d fc
+    call 07a48h                               ; e8 eb fb
     mov AL, strict byte 055h                  ; b0 55
     mov dx, 00436h                            ; ba 36 04
     out DX, AL                                ; ee
@@ -11578,12 +11622,12 @@ _scsi_init:                                  ; 0xf7da6 LB 0x66
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp AL, strict byte 055h                  ; 3c 55
-    jne short 07defh                          ; 75 0c
+    jne short 07e76h                          ; 75 0c
     xor al, al                                ; 30 c0
     mov dx, 00437h                            ; ba 37 04
     out DX, AL                                ; ee
     mov ax, 00434h                            ; b8 34 04
-    call 07a33h                               ; e8 44 fc
+    call 07a48h                               ; e8 d2 fb
     mov AL, strict byte 055h                  ; b0 55
     mov dx, 0043ah                            ; ba 3a 04
     out DX, AL                                ; ee
@@ -11591,16 +11635,16 @@ _scsi_init:                                  ; 0xf7da6 LB 0x66
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp AL, strict byte 055h                  ; 3c 55
-    jne short 07e08h                          ; 75 0c
+    jne short 07e8fh                          ; 75 0c
     xor al, al                                ; 30 c0
     mov dx, 0043bh                            ; ba 3b 04
     out DX, AL                                ; ee
     mov ax, 00438h                            ; b8 38 04
-    call 07a33h                               ; e8 2b fc
+    call 07a48h                               ; e8 b9 fb
     mov sp, bp                                ; 89 ec
     pop bp                                    ; 5d
     retn                                      ; c3
-high_bits_save_:                             ; 0xf7e0c LB 0x17
+high_bits_save_:                             ; 0xf7e93 LB 0x17
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -11612,7 +11656,7 @@ high_bits_save_:                             ; 0xf7e0c LB 0x17
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-high_bits_restore_:                          ; 0xf7e23 LB 0x17
+high_bits_restore_:                          ; 0xf7eaa LB 0x17
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -11624,7 +11668,7 @@ high_bits_restore_:                          ; 0xf7e23 LB 0x17
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_ctrl_set_bits_:                         ; 0xf7e3a LB 0x43
+ahci_ctrl_set_bits_:                         ; 0xf7ec1 LB 0x43
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -11662,7 +11706,7 @@ ahci_ctrl_set_bits_:                         ; 0xf7e3a LB 0x43
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_ctrl_clear_bits_:                       ; 0xf7e7d LB 0x47
+ahci_ctrl_clear_bits_:                       ; 0xf7f04 LB 0x47
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -11702,7 +11746,7 @@ ahci_ctrl_clear_bits_:                       ; 0xf7e7d LB 0x47
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_ctrl_is_bit_set_:                       ; 0xf7ec4 LB 0x39
+ahci_ctrl_is_bit_set_:                       ; 0xf7f4b LB 0x39
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -11724,18 +11768,18 @@ ahci_ctrl_is_bit_set_:                       ; 0xf7ec4 LB 0x39
     shr eax, 010h                             ; 66 c1 e8 10
     xchg dx, ax                               ; 92
     test dx, di                               ; 85 fa
-    jne short 07ef0h                          ; 75 04
+    jne short 07f77h                          ; 75 04
     test ax, bx                               ; 85 d8
-    je short 07ef4h                           ; 74 04
+    je short 07f7bh                           ; 74 04
     mov AL, strict byte 001h                  ; b0 01
-    jmp short 07ef6h                          ; eb 02
+    jmp short 07f7dh                          ; eb 02
     xor al, al                                ; 30 c0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_ctrl_extract_bits_:                     ; 0xf7efd LB 0x1b
+ahci_ctrl_extract_bits_:                     ; 0xf7f84 LB 0x1b
     push si                                   ; 56
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
@@ -11743,14 +11787,14 @@ ahci_ctrl_extract_bits_:                     ; 0xf7efd LB 0x1b
     and ax, bx                                ; 21 d8
     and dx, cx                                ; 21 ca
     movzx cx, byte [bp+006h]                  ; 0f b6 4e 06
-    jcxz 07f13h                               ; e3 06
+    jcxz 07f9ah                               ; e3 06
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 07f0dh                               ; e2 fa
+    loop 07f94h                               ; e2 fa
     pop bp                                    ; 5d
     pop si                                    ; 5e
     retn 00002h                               ; c2 02 00
-ahci_addr_to_phys_:                          ; 0xf7f18 LB 0x1e
+ahci_addr_to_phys_:                          ; 0xf7f9f LB 0x1e
     push bx                                   ; 53
     push cx                                   ; 51
     push bp                                   ; 55
@@ -11761,7 +11805,7 @@ ahci_addr_to_phys_:                          ; 0xf7f18 LB 0x1e
     mov cx, strict word 00004h                ; b9 04 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 07f26h                               ; e2 fa
+    loop 07fadh                               ; e2 fa
     xor cx, cx                                ; 31 c9
     add ax, bx                                ; 01 d8
     adc dx, cx                                ; 11 ca
@@ -11769,7 +11813,7 @@ ahci_addr_to_phys_:                          ; 0xf7f18 LB 0x1e
     pop cx                                    ; 59
     pop bx                                    ; 5b
     retn                                      ; c3
-ahci_port_cmd_sync_:                         ; 0xf7f36 LB 0xd5
+ahci_port_cmd_sync_:                         ; 0xf7fbd LB 0xd5
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -11783,7 +11827,7 @@ ahci_port_cmd_sync_:                         ; 0xf7f36 LB 0xd5
     mov byte [bp-008h], al                    ; 88 46 f8
     mov di, word [es:si+00260h]               ; 26 8b bc 60 02
     cmp AL, strict byte 0ffh                  ; 3c ff
-    je near 08003h                            ; 0f 84 aa 00
+    je near 0808ah                            ; 0f 84 aa 00
     movzx cx, byte [es:si+00263h]             ; 26 0f b6 8c 63 02
     xor dx, dx                                ; 31 d2
     or dl, 080h                               ; 80 ca 80
@@ -11795,7 +11839,7 @@ ahci_port_cmd_sync_:                         ; 0xf7f36 LB 0xd5
     ; mov dword [es:si+004h], strict dword 000000000h ; 66 26 c7 44 04 00 00 00 00
     lea ax, [si+00080h]                       ; 8d 84 80 00
     mov dx, es                                ; 8c c2
-    call 07f18h                               ; e8 96 ff
+    call 07f9fh                               ; e8 96 ff
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov word [es:si+008h], ax                 ; 26 89 44 08
     mov word [es:si+00ah], dx                 ; 26 89 54 0a
@@ -11805,7 +11849,7 @@ ahci_port_cmd_sync_:                         ; 0xf7f36 LB 0xd5
     mov bx, strict word 00011h                ; bb 11 00
     xor cx, cx                                ; 31 c9
     mov ax, di                                ; 89 f8
-    call 07e3ah                               ; e8 98 fe
+    call 07ec1h                               ; e8 98 fe
     lea ax, [si+00138h]                       ; 8d 84 38 01
     cwd                                       ; 99
     mov cx, dx                                ; 89 d1
@@ -11832,27 +11876,27 @@ ahci_port_cmd_sync_:                         ; 0xf7f36 LB 0xd5
     mov cx, 04000h                            ; b9 00 40
     mov dx, si                                ; 89 f2
     mov ax, di                                ; 89 f8
-    call 07ec4h                               ; e8 e2 fe
+    call 07f4bh                               ; e8 e2 fe
     test al, al                               ; 84 c0
-    je short 07fc5h                           ; 74 df
+    je short 0804ch                           ; 74 df
     mov bx, strict word 00001h                ; bb 01 00
     xor cx, cx                                ; 31 c9
     mov dx, si                                ; 89 f2
     mov ax, di                                ; 89 f8
-    call 07e3ah                               ; e8 48 fe
+    call 07ec1h                               ; e8 48 fe
     mov dx, word [bp-00ch]                    ; 8b 56 f4
     add dx, 00118h                            ; 81 c2 18 01
     mov bx, strict word 00001h                ; bb 01 00
     xor cx, cx                                ; 31 c9
     mov ax, di                                ; 89 f8
-    call 07e7dh                               ; e8 7a fe
+    call 07f04h                               ; e8 7a fe
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
+ahci_cmd_data_:                              ; 0xf8092 LB 0x1ca
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -11876,7 +11920,7 @@ ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
     xor bx, bx                                ; 31 db
     mov ax, 00080h                            ; b8 80 00
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 093dah                               ; e8 90 13
+    call 0948ah                               ; e8 b9 13
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov word [es:si+00080h], 08027h           ; 26 c7 84 80 00 27 80
     mov al, byte [bp-008h]                    ; 8a 46 f8
@@ -11892,7 +11936,7 @@ ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
     mov cx, strict word 00008h                ; b9 08 00
     shr bx, 1                                 ; d1 eb
     rcr ax, 1                                 ; d1 d8
-    loop 0807dh                               ; e2 fa
+    loop 08104h                               ; e2 fa
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov byte [es:si+00085h], al               ; 26 88 84 85 00
     mov es, [bp-012h]                         ; 8e 46 ee
@@ -11917,7 +11961,7 @@ ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
     xor dx, dx                                ; 31 d2
     mov bx, word [bp-016h]                    ; 8b 5e ea
     xor cx, cx                                ; 31 c9
-    call 093a9h                               ; e8 c3 12
+    call 09459h                               ; e8 ec 12
     push dx                                   ; 52
     push ax                                   ; 50
     mov es, [bp-012h]                         ; 8e 46 ee
@@ -11925,7 +11969,7 @@ ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
     mov cx, word [es:di+006h]                 ; 26 8b 4d 06
     mov ax, 0026ah                            ; b8 6a 02
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 092c0h                               ; e8 c4 11
+    call 09377h                               ; e8 f4 11
     mov es, [bp-00ah]                         ; 8e 46 f6
     movzx ax, byte [es:si+00263h]             ; 26 0f b6 84 63 02
     mov dx, word [es:si+0027eh]               ; 26 8b 94 7e 02
@@ -11945,7 +11989,7 @@ ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
     inc ax                                    ; 40
     mov es, [bp-012h]                         ; 8e 46 ee
     cmp word [es:di+01ch], strict byte 00000h ; 26 83 7d 1c 00
-    je short 08175h                           ; 74 2c
+    je short 081fch                           ; 74 2c
     mov dx, word [es:di+01ch]                 ; 26 8b 55 1c
     dec dx                                    ; 4a
     mov di, ax                                ; 89 c7
@@ -11964,36 +12008,36 @@ ahci_cmd_data_:                              ; 0xf800b LB 0x1ca
     les bx, [bp-00eh]                         ; c4 5e f2
     movzx dx, byte [es:bx+00263h]             ; 26 0f b6 97 63 02
     cmp ax, dx                                ; 39 d0
-    jnc short 0818fh                          ; 73 03
+    jnc short 08216h                          ; 73 03
     inc ax                                    ; 40
-    jmp short 0817fh                          ; eb f0
+    jmp short 08206h                          ; eb f0
     mov al, byte [bp-008h]                    ; 8a 46 f8
     cmp AL, strict byte 035h                  ; 3c 35
-    jne short 0819ch                          ; 75 06
+    jne short 08223h                          ; 75 06
     mov byte [bp-008h], 040h                  ; c6 46 f8 40
-    jmp short 081b0h                          ; eb 14
+    jmp short 08237h                          ; eb 14
     cmp AL, strict byte 0a0h                  ; 3c a0
-    jne short 081ach                          ; 75 0c
+    jne short 08233h                          ; 75 0c
     or byte [bp-008h], 020h                   ; 80 4e f8 20
     or byte [es:bx+00083h], 001h              ; 26 80 8f 83 00 01
-    jmp short 081b0h                          ; eb 04
+    jmp short 08237h                          ; eb 04
     mov byte [bp-008h], 000h                  ; c6 46 f8 00
     or byte [bp-008h], 005h                   ; 80 4e f8 05
     movzx bx, byte [bp-008h]                  ; 0f b6 5e f8
     mov ax, word [bp-00eh]                    ; 8b 46 f2
     mov dx, word [bp-00ch]                    ; 8b 56 f4
-    call 07f36h                               ; e8 75 fd
+    call 07fbdh                               ; e8 75 fd
     mov ax, word [bp-00eh]                    ; 8b 46 f2
     add ax, 0026ah                            ; 05 6a 02
     mov dx, word [bp-00ch]                    ; 8b 56 f4
-    call 09339h                               ; e8 6c 11
+    call 093f0h                               ; e8 9c 11
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_port_deinit_current_:                   ; 0xf81d5 LB 0x144
+ahci_port_deinit_current_:                   ; 0xf825c LB 0x144
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -12008,14 +12052,14 @@ ahci_port_deinit_current_:                   ; 0xf81d5 LB 0x144
     mov al, byte [es:di+00262h]               ; 26 8a 85 62 02
     mov byte [bp-00ah], al                    ; 88 46 f6
     cmp AL, strict byte 0ffh                  ; 3c ff
-    je near 08310h                            ; 0f 84 17 01
+    je near 08397h                            ; 0f 84 17 01
     movzx dx, al                              ; 0f b6 d0
     sal dx, 007h                              ; c1 e2 07
     add dx, 00118h                            ; 81 c2 18 01
     mov bx, strict word 00011h                ; bb 11 00
     xor cx, cx                                ; 31 c9
     mov ax, si                                ; 89 f0
-    call 07e7dh                               ; e8 70 fc
+    call 07f04h                               ; e8 70 fc
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
     sal ax, 007h                              ; c1 e0 07
     mov word [bp-00eh], ax                    ; 89 46 f2
@@ -12024,24 +12068,24 @@ ahci_port_deinit_current_:                   ; 0xf81d5 LB 0x144
     mov bx, 0c011h                            ; bb 11 c0
     xor cx, cx                                ; 31 c9
     mov ax, si                                ; 89 f0
-    call 07ec4h                               ; e8 9d fc
+    call 07f4bh                               ; e8 9d fc
     cmp AL, strict byte 001h                  ; 3c 01
-    je short 0820dh                           ; 74 e2
+    je short 08294h                           ; 74 e2
     mov cx, strict word 00020h                ; b9 20 00
     xor bx, bx                                ; 31 db
     mov ax, di                                ; 89 f8
     mov dx, word [bp-00ch]                    ; 8b 56 f4
-    call 093dah                               ; e8 a2 11
+    call 0948ah                               ; e8 cb 11
     lea ax, [di+00080h]                       ; 8d 85 80 00
     mov cx, strict word 00040h                ; b9 40 00
     xor bx, bx                                ; 31 db
     mov dx, word [bp-00ch]                    ; 8b 56 f4
-    call 093dah                               ; e8 93 11
+    call 0948ah                               ; e8 bc 11
     lea ax, [di+00200h]                       ; 8d 85 00 02
     mov cx, strict word 00060h                ; b9 60 00
     xor bx, bx                                ; 31 db
     mov dx, word [bp-00ch]                    ; 8b 56 f4
-    call 093dah                               ; e8 84 11
+    call 0948ah                               ; e8 ad 11
     mov ax, word [bp-00eh]                    ; 8b 46 f2
     add ax, 00108h                            ; 05 08 01
     cwd                                       ; 99
@@ -12143,7 +12187,7 @@ ahci_port_deinit_current_:                   ; 0xf81d5 LB 0x144
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_port_init_:                             ; 0xf8319 LB 0x206
+ahci_port_init_:                             ; 0xf83a0 LB 0x206
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -12153,7 +12197,7 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     mov si, ax                                ; 89 c6
     mov word [bp-00ah], dx                    ; 89 56 f6
     mov byte [bp-008h], bl                    ; 88 5e f8
-    call 081d5h                               ; e8 a8 fe
+    call 0825ch                               ; e8 a8 fe
     movzx dx, bl                              ; 0f b6 d3
     sal dx, 007h                              ; c1 e2 07
     add dx, 00118h                            ; 81 c2 18 01
@@ -12161,7 +12205,7 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     mov ax, word [es:si+00260h]               ; 26 8b 84 60 02
     mov bx, strict word 00011h                ; bb 11 00
     xor cx, cx                                ; 31 c9
-    call 07e7dh                               ; e8 36 fb
+    call 07f04h                               ; e8 36 fb
     movzx di, byte [bp-008h]                  ; 0f b6 7e f8
     sal di, 007h                              ; c1 e7 07
     lea dx, [di+00118h]                       ; 8d 95 18 01
@@ -12169,26 +12213,26 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     mov ax, word [es:si+00260h]               ; 26 8b 84 60 02
     mov bx, 0c011h                            ; bb 11 c0
     xor cx, cx                                ; 31 c9
-    call 07ec4h                               ; e8 62 fb
+    call 07f4bh                               ; e8 62 fb
     cmp AL, strict byte 001h                  ; 3c 01
-    je short 08347h                           ; 74 e1
+    je short 083ceh                           ; 74 e1
     mov cx, strict word 00020h                ; b9 20 00
     xor bx, bx                                ; 31 db
     mov ax, si                                ; 89 f0
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 093dah                               ; e8 67 10
+    call 0948ah                               ; e8 90 10
     lea ax, [si+00080h]                       ; 8d 84 80 00
     mov cx, strict word 00040h                ; b9 40 00
     xor bx, bx                                ; 31 db
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 093dah                               ; e8 58 10
+    call 0948ah                               ; e8 81 10
     mov ax, si                                ; 89 f0
     add ah, 002h                              ; 80 c4 02
     mov word [bp-00ch], ax                    ; 89 46 f4
     mov cx, strict word 00060h                ; b9 60 00
     xor bx, bx                                ; 31 db
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 093dah                               ; e8 45 10
+    call 0948ah                               ; e8 6e 10
     lea ax, [di+00108h]                       ; 8d 85 08 01
     cwd                                       ; 99
     mov es, [bp-00ah]                         ; 8e 46 f6
@@ -12202,7 +12246,7 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     out DX, eax                               ; 66 ef
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 07f18h                               ; e8 60 fb
+    call 07f9fh                               ; e8 60 fb
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov bx, word [es:si+00260h]               ; 26 8b 9c 60 02
     add bx, strict byte 00004h                ; 83 c3 04
@@ -12247,7 +12291,7 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     out DX, eax                               ; 66 ef
     mov ax, si                                ; 89 f0
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 07f18h                               ; e8 f4 fa
+    call 07f9fh                               ; e8 f4 fa
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov bx, word [es:si+00260h]               ; 26 8b 9c 60 02
     add bx, strict byte 00004h                ; 83 c3 04
@@ -12352,7 +12396,7 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
- at ahci_read_sectors:                          ; 0xf851f LB 0x94
+ at ahci_read_sectors:                          ; 0xf85a6 LB 0x94
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -12361,28 +12405,28 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     movzx di, byte [es:di+008h]               ; 26 0f b6 7d 08
     sub di, strict byte 0000ch                ; 83 ef 0c
     cmp di, strict byte 00004h                ; 83 ff 04
-    jbe short 08543h                          ; 76 0f
+    jbe short 085cah                          ; 76 0f
     push di                                   ; 57
-    push 00c66h                               ; 68 66 0c
-    push 00c78h                               ; 68 78 0c
+    push 00c7eh                               ; 68 7e 0c
+    push 00c90h                               ; 68 90 0c
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 cd 93
+    call 01922h                               ; e8 5b 93
     add sp, strict byte 00008h                ; 83 c4 08
     les bx, [bp+004h]                         ; c4 5e 04
     mov dx, word [es:bx+001eeh]               ; 26 8b 97 ee 01
     xor ax, ax                                ; 31 c0
-    call 07e0ch                               ; e8 bc f8
+    call 07e93h                               ; e8 bc f8
     mov es, [bp+006h]                         ; 8e 46 06
     add di, bx                                ; 01 df
     movzx bx, byte [es:di+001e9h]             ; 26 0f b6 9d e9 01
     mov di, word [bp+004h]                    ; 8b 7e 04
     mov dx, word [es:di+001eeh]               ; 26 8b 95 ee 01
     xor ax, ax                                ; 31 c0
-    call 08319h                               ; e8 b1 fd
+    call 083a0h                               ; e8 b1 fd
     mov bx, strict word 00025h                ; bb 25 00
     mov ax, di                                ; 89 f8
     mov dx, word [bp+006h]                    ; 8b 56 06
-    call 0800bh                               ; e8 98 fa
+    call 08092h                               ; e8 98 fa
     mov es, [bp+006h]                         ; 8e 46 06
     mov bx, di                                ; 89 fb
     mov ax, word [es:bx+00ah]                 ; 26 8b 47 0a
@@ -12402,14 +12446,14 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     mov es, [bp+006h]                         ; 8e 46 06
     mov dx, word [es:bx+001eeh]               ; 26 8b 97 ee 01
     xor ax, ax                                ; 31 c0
-    call 07e23h                               ; e8 7b f8
+    call 07eaah                               ; e8 7b f8
     xor ax, ax                                ; 31 c0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
- at ahci_write_sectors:                         ; 0xf85b3 LB 0x70
+ at ahci_write_sectors:                         ; 0xf863a LB 0x70
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -12419,39 +12463,39 @@ ahci_port_init_:                             ; 0xf8319 LB 0x206
     movzx bx, byte [es:si+008h]               ; 26 0f b6 5c 08
     sub bx, strict byte 0000ch                ; 83 eb 0c
     cmp bx, strict byte 00004h                ; 83 fb 04
-    jbe short 085dbh                          ; 76 0f
+    jbe short 08662h                          ; 76 0f
     push bx                                   ; 53
-    push 00c97h                               ; 68 97 0c
-    push 00c78h                               ; 68 78 0c
+    push 00cafh                               ; 68 af 0c
+    push 00c90h                               ; 68 90 0c
     push strict byte 00007h                   ; 6a 07
-    call 0190dh                               ; e8 35 93
+    call 01922h                               ; e8 c3 92
     add sp, strict byte 00008h                ; 83 c4 08
     mov es, cx                                ; 8e c1
     mov dx, word [es:si+001eeh]               ; 26 8b 94 ee 01
     xor ax, ax                                ; 31 c0
-    call 07e0ch                               ; e8 25 f8
+    call 07e93h                               ; e8 25 f8
     mov es, cx                                ; 8e c1
     add bx, si                                ; 01 f3
     movzx bx, byte [es:bx+001e9h]             ; 26 0f b6 9f e9 01
     mov dx, word [es:si+001eeh]               ; 26 8b 94 ee 01
     xor ax, ax                                ; 31 c0
-    call 08319h                               ; e8 1e fd
+    call 083a0h                               ; e8 1e fd
     mov bx, strict word 00035h                ; bb 35 00
     mov ax, si                                ; 89 f0
     mov dx, cx                                ; 89 ca
-    call 0800bh                               ; e8 06 fa
+    call 08092h                               ; e8 06 fa
     mov es, cx                                ; 8e c1
     mov dx, word [es:si+00ah]                 ; 26 8b 54 0a
     mov word [es:si+014h], dx                 ; 26 89 54 14
     mov dx, word [es:si+001eeh]               ; 26 8b 94 ee 01
     xor ax, ax                                ; 31 c0
-    call 07e23h                               ; e8 0a f8
+    call 07eaah                               ; e8 0a f8
     xor ax, ax                                ; 31 c0
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
-ahci_cmd_packet_:                            ; 0xf8623 LB 0x173
+ahci_cmd_packet_:                            ; 0xf86aa LB 0x173
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -12463,30 +12507,30 @@ ahci_cmd_packet_:                            ; 0xf8623 LB 0x173
     mov word [bp-010h], cx                    ; 89 4e f0
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 de 8f
+    call 0161ch                               ; e8 57 8f
     mov si, 00122h                            ; be 22 01
     mov word [bp-008h], ax                    ; 89 46 f8
     cmp byte [bp+00ah], 002h                  ; 80 7e 0a 02
-    jne short 08669h                          ; 75 1f
-    mov bx, 00da2h                            ; bb a2 0d
+    jne short 086f0h                          ; 75 1f
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 77 92
-    push 00caah                               ; 68 aa 0c
-    push 00cbah                               ; 68 ba 0c
+    call 018e1h                               ; e8 05 92
+    push 00cc2h                               ; 68 c2 0c
+    push 00cd2h                               ; 68 d2 0c
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 ad 92
+    call 01922h                               ; e8 3b 92
     add sp, strict byte 00006h                ; 83 c4 06
     mov ax, strict word 00001h                ; b8 01 00
-    jmp near 0878dh                           ; e9 24 01
+    jmp near 08814h                           ; e9 24 01
     test byte [bp+004h], 001h                 ; f6 46 04 01
-    jne short 08663h                          ; 75 f4
+    jne short 086eah                          ; 75 f4
     mov ax, word [bp+006h]                    ; 8b 46 06
     mov dx, word [bp+008h]                    ; 8b 56 08
     mov cx, strict word 00008h                ; b9 08 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 08678h                               ; e2 fa
+    loop 086ffh                               ; e2 fa
     mov es, [bp-008h]                         ; 8e 46 f8
     mov word [es:si], ax                      ; 26 89 04
     mov word [es:si+002h], dx                 ; 26 89 54 02
@@ -12498,7 +12542,7 @@ ahci_cmd_packet_:                            ; 0xf8623 LB 0x173
     mov ax, word [bp+006h]                    ; 8b 46 06
     mov dx, word [bp+008h]                    ; 8b 56 08
     xor cx, cx                                ; 31 c9
-    call 09370h                               ; e8 cb 0c
+    call 09420h                               ; e8 f4 0c
     mov word [es:si+00ah], ax                 ; 26 89 44 0a
     xor di, di                                ; 31 ff
     mov ax, word [es:si+001eeh]               ; 26 8b 84 ee 01
@@ -12508,28 +12552,28 @@ ahci_cmd_packet_:                            ; 0xf8623 LB 0x173
     sub word [bp-014h], strict byte 0000ch    ; 83 6e ec 0c
     xor ax, ax                                ; 31 c0
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 07e0ch                               ; e8 47 f7
+    call 07e93h                               ; e8 47 f7
     mov es, [bp-008h]                         ; 8e 46 f8
     mov bx, word [bp-014h]                    ; 8b 5e ec
     add bx, si                                ; 01 f3
     movzx bx, byte [es:bx+001e9h]             ; 26 0f b6 9f e9 01
     mov dx, word [es:si+001eeh]               ; 26 8b 94 ee 01
     xor ax, ax                                ; 31 c0
-    call 08319h                               ; e8 3c fc
+    call 083a0h                               ; e8 3c fc
     movzx ax, byte [bp-006h]                  ; 0f b6 46 fa
     push ax                                   ; 50
     mov bx, word [bp-012h]                    ; 8b 5e ee
     mov cx, word [bp-010h]                    ; 8b 4e f0
     mov ax, 000c0h                            ; b8 c0 00
     mov dx, word [bp-00ah]                    ; 8b 56 f6
-    call 093e7h                               ; e8 f6 0c
+    call 09497h                               ; e8 1f 0d
     mov es, [bp-008h]                         ; 8e 46 f8
     mov word [es:si+014h], di                 ; 26 89 7c 14
     mov word [es:si+016h], di                 ; 26 89 7c 16
     mov word [es:si+018h], di                 ; 26 89 7c 18
     mov ax, word [es:si+01ah]                 ; 26 8b 44 1a
     test ax, ax                               ; 85 c0
-    je short 0872fh                           ; 74 27
+    je short 087b6h                           ; 74 27
     dec ax                                    ; 48
     mov es, [bp-00ah]                         ; 8e 46 f6
     mov word [es:di+0010ch], ax               ; 26 89 85 0c 01
@@ -12542,7 +12586,7 @@ ahci_cmd_packet_:                            ; 0xf8623 LB 0x173
     mov bx, 000a0h                            ; bb a0 00
     mov ax, si                                ; 89 f0
     mov dx, word [bp-008h]                    ; 8b 56 f8
-    call 0800bh                               ; e8 d1 f8
+    call 08092h                               ; e8 d1 f8
     les bx, [bp-00eh]                         ; c4 5e f2
     mov ax, word [es:bx+004h]                 ; 26 8b 47 04
     mov dx, word [es:bx+006h]                 ; 26 8b 57 06
@@ -12565,20 +12609,20 @@ ahci_cmd_packet_:                            ; 0xf8623 LB 0x173
     pop DS                                    ; 1f
     mov ax, word [bp-00eh]                    ; 8b 46 f2
     mov dx, word [bp-00ch]                    ; 8b 56 f4
-    call 07e23h                               ; e8 aa f6
+    call 07eaah                               ; e8 aa f6
     les bx, [bp-00eh]                         ; c4 5e f2
     mov ax, word [es:bx+006h]                 ; 26 8b 47 06
     or ax, word [es:bx+004h]                  ; 26 0b 47 04
-    jne short 0878bh                          ; 75 05
+    jne short 08812h                          ; 75 05
     mov ax, strict word 00004h                ; b8 04 00
-    jmp short 0878dh                          ; eb 02
+    jmp short 08814h                          ; eb 02
     xor ax, ax                                ; 31 c0
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 0000ch                               ; c2 0c 00
-ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
+ahci_port_detect_device_:                    ; 0xf881d LB 0x401
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -12587,24 +12631,24 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     sub sp, 00222h                            ; 81 ec 22 02
     mov di, ax                                ; 89 c7
     mov word [bp-010h], dx                    ; 89 56 f0
-    mov byte [bp-008h], bl                    ; 88 5e f8
+    mov byte [bp-00ch], bl                    ; 88 5e f4
     movzx cx, bl                              ; 0f b6 cb
     mov bx, cx                                ; 89 cb
-    call 08319h                               ; e8 69 fb
+    call 083a0h                               ; e8 69 fb
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 63 8e
+    call 0161ch                               ; e8 dc 8d
     mov word [bp-020h], ax                    ; 89 46 e0
     mov si, 00122h                            ; be 22 01
     mov word [bp-00eh], ax                    ; 89 46 f2
-    mov word [bp-022h], si                    ; 89 76 de
-    mov word [bp-012h], ax                    ; 89 46 ee
+    mov word [bp-012h], si                    ; 89 76 ee
+    mov word [bp-01eh], ax                    ; 89 46 e2
     sal cx, 007h                              ; c1 e1 07
-    mov word [bp-01ch], cx                    ; 89 4e e4
+    mov word [bp-016h], cx                    ; 89 4e ea
     mov ax, cx                                ; 89 c8
     add ax, 0012ch                            ; 05 2c 01
     cwd                                       ; 99
-    mov word [bp-01eh], ax                    ; 89 46 e2
+    mov word [bp-022h], ax                    ; 89 46 de
     mov bx, dx                                ; 89 d3
     mov es, [bp-010h]                         ; 8e 46 f0
     mov dx, word [es:di+00260h]               ; 26 8b 95 60 02
@@ -12626,7 +12670,7 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     out DX, eax                               ; 66 ef
     mov es, [bp-010h]                         ; 8e 46 f0
     mov dx, word [es:di+00260h]               ; 26 8b 95 60 02
-    mov ax, word [bp-01eh]                    ; 8b 46 e2
+    mov ax, word [bp-022h]                    ; 8b 46 de
     mov cx, bx                                ; 89 d9
     xchg cx, ax                               ; 91
     sal eax, 010h                             ; 66 c1 e0 10
@@ -12643,7 +12687,7 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     db  08bh, 0c1h
     ; mov ax, cx                                ; 8b c1
     out DX, eax                               ; 66 ef
-    mov ax, word [bp-01ch]                    ; 8b 46 e4
+    mov ax, word [bp-016h]                    ; 8b 46 ea
     add ax, 00128h                            ; 05 28 01
     cwd                                       ; 99
     mov es, [bp-010h]                         ; 8e 46 f0
@@ -12666,22 +12710,44 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     push strict byte 00000h                   ; 6a 00
     mov bx, strict word 0000fh                ; bb 0f 00
     xor cx, cx                                ; 31 c9
-    call 07efdh                               ; e8 90 f6
+    call 07f84h                               ; e8 90 f6
     cmp ax, strict word 00003h                ; 3d 03 00
-    jne near 08b5fh                           ; 0f 85 eb 02
+    jne near 08c16h                           ; 0f 85 1b 03
+    mov ax, word [bp-016h]                    ; 8b 46 ea
+    add ax, 00130h                            ; 05 30 01
+    cwd                                       ; 99
+    mov es, [bp-010h]                         ; 8e 46 f0
+    mov bx, word [es:di+00260h]               ; 26 8b 9d 60 02
+    mov cx, dx                                ; 89 d1
+    mov dx, bx                                ; 89 da
+    xchg cx, ax                               ; 91
+    sal eax, 010h                             ; 66 c1 e0 10
+    db  08bh, 0c1h
+    ; mov ax, cx                                ; 8b c1
+    out DX, eax                               ; 66 ef
+    mov es, [bp-010h]                         ; 8e 46 f0
+    mov dx, word [es:di+00260h]               ; 26 8b 95 60 02
+    add dx, strict byte 00004h                ; 83 c2 04
+    mov ax, strict word 0ffffh                ; b8 ff ff
+    mov cx, ax                                ; 89 c1
+    xchg cx, ax                               ; 91
+    sal eax, 010h                             ; 66 c1 e0 10
+    db  08bh, 0c1h
+    ; mov ax, cx                                ; 8b c1
+    out DX, eax                               ; 66 ef
     mov es, [bp-00eh]                         ; 8e 46 f2
     mov al, byte [es:si+001edh]               ; 26 8a 84 ed 01
-    mov byte [bp-00ah], al                    ; 88 46 f6
+    mov byte [bp-008h], al                    ; 88 46 f8
     cmp AL, strict byte 004h                  ; 3c 04
-    jnc near 08b5fh                           ; 0f 83 da 02
-    mov dx, word [bp-01ch]                    ; 8b 56 e4
+    jnc near 08c16h                           ; 0f 83 d5 02
+    mov dx, word [bp-016h]                    ; 8b 56 ea
     add dx, 00118h                            ; 81 c2 18 01
     mov es, [bp-010h]                         ; 8e 46 f0
     mov ax, word [es:di+00260h]               ; 26 8b 85 60 02
     mov bx, strict word 00010h                ; bb 10 00
     xor cx, cx                                ; 31 c9
-    call 07e3ah                               ; e8 9e f5
-    mov ax, word [bp-01ch]                    ; 8b 46 e4
+    call 07ec1h                               ; e8 69 f5
+    mov ax, word [bp-016h]                    ; 8b 46 ea
     add ax, 00124h                            ; 05 24 01
     cwd                                       ; 99
     mov es, [bp-010h]                         ; 8e 46 f0
@@ -12701,14 +12767,12 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     ; mov dx, ax                                ; 8b d0
     shr eax, 010h                             ; 66 c1 e8 10
     xchg dx, ax                               ; 92
-    mov bx, ax                                ; 89 c3
-    mov ax, dx                                ; 89 d0
-    mov cl, byte [bp-00ah]                    ; 8a 4e f6
+    mov cl, byte [bp-008h]                    ; 8a 4e f8
     add cl, 00ch                              ; 80 c1 0c
     test dx, dx                               ; 85 d2
-    jne near 08ab1h                           ; 0f 85 d5 01
-    cmp bx, 00101h                            ; 81 fb 01 01
-    jne near 08ab1h                           ; 0f 85 cd 01
+    jne near 08b68h                           ; 0f 85 d4 01
+    cmp ax, 00101h                            ; 3d 01 01
+    jne near 08b68h                           ; 0f 85 cd 01
     mov es, [bp-00eh]                         ; 8e 46 f2
     db  066h, 026h, 0c7h, 004h, 000h, 000h, 000h, 000h
     ; mov dword [es:si], strict dword 000000000h ; 66 26 c7 04 00 00 00 00
@@ -12720,36 +12784,36 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     mov bx, 000ech                            ; bb ec 00
     mov ax, si                                ; 89 f0
     mov dx, word [bp-020h]                    ; 8b 56 e0
-    call 0800bh                               ; e8 fc f6
-    mov byte [bp-00ch], cl                    ; 88 4e f4
+    call 08092h                               ; e8 cc f6
+    mov byte [bp-00ah], cl                    ; 88 4e f6
     test byte [bp-00228h], 080h               ; f6 86 d8 fd 80
     db  00fh, 095h, 0c0h
     ; setne al                                  ; 0f 95 c0
     xor ah, ah                                ; 30 e4
     mov dx, word [bp-00226h]                  ; 8b 96 da fd
-    mov word [bp-01ah], dx                    ; 89 56 e6
-    mov dx, word [bp-00222h]                  ; 8b 96 de fd
     mov word [bp-018h], dx                    ; 89 56 e8
+    mov dx, word [bp-00222h]                  ; 8b 96 de fd
+    mov word [bp-01ch], dx                    ; 89 56 e4
     mov dx, word [bp-0021ch]                  ; 8b 96 e4 fd
-    mov word [bp-016h], dx                    ; 89 56 ea
+    mov word [bp-01ah], dx                    ; 89 56 e6
     mov di, word [bp-001b0h]                  ; 8b be 50 fe
     mov dx, word [bp-001aeh]                  ; 8b 96 52 fe
     mov word [bp-014h], dx                    ; 89 56 ec
     cmp dx, 00fffh                            ; 81 fa ff 0f
-    jne short 08952h                          ; 75 10
+    jne short 08a09h                          ; 75 10
     cmp di, strict byte 0ffffh                ; 83 ff ff
-    jne short 08952h                          ; 75 0b
+    jne short 08a09h                          ; 75 0b
     mov di, word [bp-00160h]                  ; 8b be a0 fe
     mov dx, word [bp-0015eh]                  ; 8b 96 a2 fe
     mov word [bp-014h], dx                    ; 89 56 ec
-    movzx bx, byte [bp-00ah]                  ; 0f b6 5e f6
-    mov es, [bp-012h]                         ; 8e 46 ee
-    add bx, word [bp-022h]                    ; 03 5e de
-    mov ah, byte [bp-008h]                    ; 8a 66 f8
+    movzx bx, byte [bp-008h]                  ; 0f b6 5e f8
+    mov es, [bp-01eh]                         ; 8e 46 e2
+    add bx, word [bp-012h]                    ; 03 5e ee
+    mov ah, byte [bp-00ch]                    ; 8a 66 f4
     mov byte [es:bx+001e9h], ah               ; 26 88 a7 e9 01
-    movzx dx, byte [bp-00ch]                  ; 0f b6 56 f4
+    movzx dx, byte [bp-00ah]                  ; 0f b6 56 f6
     imul dx, dx, strict byte 00018h           ; 6b d2 18
-    mov si, word [bp-022h]                    ; 8b 76 de
+    mov si, word [bp-012h]                    ; 8b 76 ee
     add si, dx                                ; 01 d6
     mov word [es:si+01eh], 0ff05h             ; 26 c7 44 1e 05 ff
     mov byte [es:si+020h], al                 ; 26 88 44 20
@@ -12759,70 +12823,70 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     mov word [es:si+032h], di                 ; 26 89 7c 32
     mov ax, word [bp-014h]                    ; 8b 46 ec
     mov word [es:si+034h], ax                 ; 26 89 44 34
-    mov ax, word [bp-018h]                    ; 8b 46 e8
+    mov ax, word [bp-01ch]                    ; 8b 46 e4
     mov word [es:si+02ch], ax                 ; 26 89 44 2c
-    mov ax, word [bp-01ah]                    ; 8b 46 e6
+    mov ax, word [bp-018h]                    ; 8b 46 e8
     mov word [es:si+02eh], ax                 ; 26 89 44 2e
-    mov ax, word [bp-016h]                    ; 8b 46 ea
+    mov ax, word [bp-01ah]                    ; 8b 46 e6
     mov word [es:si+030h], ax                 ; 26 89 44 30
-    mov al, byte [bp-00ah]                    ; 8a 46 f6
+    mov al, byte [bp-008h]                    ; 8a 46 f8
     cmp AL, strict byte 001h                  ; 3c 01
-    jc short 089bdh                           ; 72 0c
-    jbe short 089c5h                          ; 76 12
+    jc short 08a74h                           ; 72 0c
+    jbe short 08a7ch                          ; 76 12
     cmp AL, strict byte 003h                  ; 3c 03
-    je short 089cdh                           ; 74 16
+    je short 08a84h                           ; 74 16
     cmp AL, strict byte 002h                  ; 3c 02
-    je short 089c9h                           ; 74 0e
-    jmp short 08a16h                          ; eb 59
+    je short 08a80h                           ; 74 0e
+    jmp short 08acdh                          ; eb 59
     test al, al                               ; 84 c0
-    jne short 08a16h                          ; 75 55
+    jne short 08acdh                          ; 75 55
     mov DL, strict byte 040h                  ; b2 40
-    jmp short 089cfh                          ; eb 0a
+    jmp short 08a86h                          ; eb 0a
     mov DL, strict byte 048h                  ; b2 48
-    jmp short 089cfh                          ; eb 06
+    jmp short 08a86h                          ; eb 06
     mov DL, strict byte 050h                  ; b2 50
-    jmp short 089cfh                          ; eb 02
+    jmp short 08a86h                          ; eb 02
     mov DL, strict byte 058h                  ; b2 58
     mov al, dl                                ; 88 d0
     add AL, strict byte 007h                  ; 04 07
     movzx bx, al                              ; 0f b6 d8
     mov ax, bx                                ; 89 d8
-    call 0165ch                               ; e8 81 8c
+    call 0165ch                               ; e8 ca 8b
     test al, al                               ; 84 c0
-    je short 08a16h                           ; 74 37
+    je short 08acdh                           ; 74 37
     mov al, dl                                ; 88 d0
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     xor ah, ah                                ; 30 e4
-    call 0165ch                               ; e8 74 8c
+    call 0165ch                               ; e8 bd 8b
     xor ah, ah                                ; 30 e4
     mov cx, ax                                ; 89 c1
     sal cx, 008h                              ; c1 e1 08
     movzx ax, dl                              ; 0f b6 c2
-    call 0165ch                               ; e8 67 8c
+    call 0165ch                               ; e8 b0 8b
     xor ah, ah                                ; 30 e4
     add ax, cx                                ; 01 c8
     mov word [bp-026h], ax                    ; 89 46 da
     mov al, dl                                ; 88 d0
     add AL, strict byte 002h                  ; 04 02
     xor ah, ah                                ; 30 e4
-    call 0165ch                               ; e8 57 8c
+    call 0165ch                               ; e8 a0 8b
     xor ah, ah                                ; 30 e4
     mov word [bp-028h], ax                    ; 89 46 d8
     mov ax, bx                                ; 89 d8
-    call 0165ch                               ; e8 4d 8c
+    call 0165ch                               ; e8 96 8b
     xor ah, ah                                ; 30 e4
     mov word [bp-024h], ax                    ; 89 46 dc
-    jmp short 08a23h                          ; eb 0d
+    jmp short 08adah                          ; eb 0d
     mov bx, di                                ; 89 fb
     mov cx, word [bp-014h]                    ; 8b 4e ec
     mov dx, ss                                ; 8c d2
     lea ax, [bp-028h]                         ; 8d 46 d8
-    call 0532ch                               ; e8 09 c9
-    mov bx, 00da2h                            ; bb a2 0d
+    call 05341h                               ; e8 67 c8
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 9e 8e
+    call 018e1h                               ; e8 fc 8d
     push word [bp-014h]                       ; ff 76 ec
     push di                                   ; 57
     mov ax, word [bp-024h]                    ; 8b 46 dc
@@ -12831,20 +12895,20 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     push ax                                   ; 50
     mov ax, word [bp-026h]                    ; 8b 46 da
     push ax                                   ; 50
-    push dword [bp-018h]                      ; 66 ff 76 e8
-    push word [bp-01ah]                       ; ff 76 e6
-    movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
+    push dword [bp-01ch]                      ; 66 ff 76 e4
+    push word [bp-018h]                       ; ff 76 e8
+    movzx ax, byte [bp-00ch]                  ; 0f b6 46 f4
     push ax                                   ; 50
-    movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
+    movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     push ax                                   ; 50
-    push 00cdah                               ; 68 da 0c
+    push 00cf2h                               ; 68 f2 0c
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 b6 8e
+    call 01922h                               ; e8 14 8e
     add sp, strict byte 00018h                ; 83 c4 18
-    movzx di, byte [bp-00ch]                  ; 0f b6 7e f4
+    movzx di, byte [bp-00ah]                  ; 0f b6 7e f6
     imul di, di, strict byte 00018h           ; 6b ff 18
-    add di, word [bp-022h]                    ; 03 7e de
-    mov es, [bp-012h]                         ; 8e 46 ee
+    add di, word [bp-012h]                    ; 03 7e ee
+    mov es, [bp-01eh]                         ; 8e 46 e2
     lea di, [di+026h]                         ; 8d 7d 26
     push DS                                   ; 1e
     push SS                                   ; 16
@@ -12854,31 +12918,31 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     movsw                                     ; a5
     movsw                                     ; a5
     pop DS                                    ; 1f
-    mov bx, word [bp-022h]                    ; 8b 5e de
+    mov bx, word [bp-012h]                    ; 8b 5e ee
     mov al, byte [es:bx+0019eh]               ; 26 8a 87 9e 01
-    mov ah, byte [bp-00ah]                    ; 8a 66 f6
+    mov ah, byte [bp-008h]                    ; 8a 66 f8
     add ah, 00ch                              ; 80 c4 0c
     movzx bx, al                              ; 0f b6 d8
-    add bx, word [bp-022h]                    ; 03 5e de
+    add bx, word [bp-012h]                    ; 03 5e ee
     mov byte [es:bx+0019fh], ah               ; 26 88 a7 9f 01
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
-    mov bx, word [bp-022h]                    ; 8b 5e de
+    mov bx, word [bp-012h]                    ; 8b 5e ee
     mov byte [es:bx+0019eh], al               ; 26 88 87 9e 01
     mov dx, strict word 00075h                ; ba 75 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 01600h                               ; e8 60 8b
+    call 01600h                               ; e8 a9 8a
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     movzx bx, al                              ; 0f b6 d8
     mov dx, strict word 00075h                ; ba 75 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0160eh                               ; e8 60 8b
-    jmp near 08b4eh                           ; e9 9d 00
+    call 0160eh                               ; e8 a9 8a
+    jmp near 08c05h                           ; e9 9d 00
     cmp dx, 0eb14h                            ; 81 fa 14 eb
-    jne near 08b4eh                           ; 0f 85 95 00
-    cmp bx, 00101h                            ; 81 fb 01 01
-    jne near 08b4eh                           ; 0f 85 8d 00
+    jne near 08c05h                           ; 0f 85 95 00
+    cmp ax, 00101h                            ; 3d 01 01
+    jne near 08c05h                           ; 0f 85 8e 00
     mov es, [bp-00eh]                         ; 8e 46 f2
     db  066h, 026h, 0c7h, 004h, 000h, 000h, 000h, 000h
     ; mov dword [es:si], strict dword 000000000h ; 66 26 c7 04 00 00 00 00
@@ -12890,26 +12954,26 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     mov bx, 000a1h                            ; bb a1 00
     mov ax, si                                ; 89 f0
     mov dx, word [bp-020h]                    ; 8b 56 e0
-    call 0800bh                               ; e8 1f f5
+    call 08092h                               ; e8 f0 f4
     test byte [bp-00228h], 080h               ; f6 86 d8 fd 80
     db  00fh, 095h, 0c0h
     ; setne al                                  ; 0f 95 c0
-    xor ah, ah                                ; 30 e4
-    movzx bx, byte [bp-00ah]                  ; 0f b6 5e f6
+    movzx dx, al                              ; 0f b6 d0
+    movzx bx, byte [bp-008h]                  ; 0f b6 5e f8
     mov es, [bp-020h]                         ; 8e 46 e0
     add bx, si                                ; 01 f3
-    mov ah, byte [bp-008h]                    ; 8a 66 f8
-    mov byte [es:bx+001e9h], ah               ; 26 88 a7 e9 01
+    mov al, byte [bp-00ch]                    ; 8a 46 f4
+    mov byte [es:bx+001e9h], al               ; 26 88 87 e9 01
     movzx si, cl                              ; 0f b6 f1
     imul si, si, strict byte 00018h           ; 6b f6 18
     add si, 00122h                            ; 81 c6 22 01
     mov word [es:si+01eh], 00505h             ; 26 c7 44 1e 05 05
-    mov byte [es:si+020h], al                 ; 26 88 44 20
+    mov byte [es:si+020h], dl                 ; 26 88 54 20
     mov word [es:si+024h], 00800h             ; 26 c7 44 24 00 08
-    mov es, [bp-012h]                         ; 8e 46 ee
-    mov bx, word [bp-022h]                    ; 8b 5e de
+    mov es, [bp-01eh]                         ; 8e 46 e2
+    mov bx, word [bp-012h]                    ; 8b 5e ee
     mov al, byte [es:bx+001afh]               ; 26 8a 87 af 01
-    mov ah, byte [bp-00ah]                    ; 8a 66 f6
+    mov ah, byte [bp-008h]                    ; 8a 66 f8
     add ah, 00ch                              ; 80 c4 0c
     movzx bx, al                              ; 0f b6 d8
     mov es, [bp-020h]                         ; 8e 46 e0
@@ -12917,13 +12981,13 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     mov byte [es:bx+001b0h], ah               ; 26 88 a7 b0 01
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
-    mov es, [bp-012h]                         ; 8e 46 ee
-    mov bx, word [bp-022h]                    ; 8b 5e de
+    mov es, [bp-01eh]                         ; 8e 46 e2
+    mov bx, word [bp-012h]                    ; 8b 5e ee
     mov byte [es:bx+001afh], al               ; 26 88 87 af 01
-    inc byte [bp-00ah]                        ; fe 46 f6
-    mov al, byte [bp-00ah]                    ; 8a 46 f6
-    mov es, [bp-012h]                         ; 8e 46 ee
-    mov bx, word [bp-022h]                    ; 8b 5e de
+    inc byte [bp-008h]                        ; fe 46 f8
+    mov al, byte [bp-008h]                    ; 8a 46 f8
+    mov es, [bp-01eh]                         ; 8e 46 e2
+    mov bx, word [bp-012h]                    ; 8b 5e ee
     mov byte [es:bx+001edh], al               ; 26 88 87 ed 01
     lea sp, [bp-006h]                         ; 8d 66 fa
     pop di                                    ; 5f
@@ -12931,7 +12995,7 @@ ahci_port_detect_device_:                    ; 0xf8796 LB 0x3d1
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_mem_alloc_:                             ; 0xf8b67 LB 0x43
+ahci_mem_alloc_:                             ; 0xf8c1e LB 0x43
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -12941,25 +13005,25 @@ ahci_mem_alloc_:                             ; 0xf8b67 LB 0x43
     push di                                   ; 57
     mov dx, 00413h                            ; ba 13 04
     xor ax, ax                                ; 31 c0
-    call 0161ch                               ; e8 a5 8a
+    call 0161ch                               ; e8 ee 89
     test ax, ax                               ; 85 c0
-    je short 08ba0h                           ; 74 25
+    je short 08c57h                           ; 74 25
     dec ax                                    ; 48
     mov bx, ax                                ; 89 c3
     xor dx, dx                                ; 31 d2
     mov cx, strict word 0000ah                ; b9 0a 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 08b83h                               ; e2 fa
+    loop 08c3ah                               ; e2 fa
     mov si, ax                                ; 89 c6
     mov di, dx                                ; 89 d7
     mov cx, strict word 00004h                ; b9 04 00
     shr di, 1                                 ; d1 ef
     rcr si, 1                                 ; d1 de
-    loop 08b90h                               ; e2 fa
+    loop 08c47h                               ; e2 fa
     mov dx, 00413h                            ; ba 13 04
     xor ax, ax                                ; 31 c0
-    call 0162ah                               ; e8 8c 8a
+    call 0162ah                               ; e8 d5 89
     mov ax, si                                ; 89 f0
     lea sp, [bp-00ah]                         ; 8d 66 f6
     pop di                                    ; 5f
@@ -12969,7 +13033,7 @@ ahci_mem_alloc_:                             ; 0xf8b67 LB 0x43
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-ahci_hba_init_:                              ; 0xf8baa LB 0x125
+ahci_hba_init_:                              ; 0xf8c61 LB 0x125
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -12981,7 +13045,7 @@ ahci_hba_init_:                              ; 0xf8baa LB 0x125
     mov si, ax                                ; 89 c6
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, strict word 00040h                ; b8 40 00
-    call 0161ch                               ; e8 5c 8a
+    call 0161ch                               ; e8 a5 89
     mov bx, 00122h                            ; bb 22 01
     mov word [bp-010h], ax                    ; 89 46 f0
     mov ax, strict word 00010h                ; b8 10 00
@@ -12998,10 +13062,10 @@ ahci_hba_init_:                              ; 0xf8baa LB 0x125
     ; mov dx, ax                                ; 8b d0
     shr eax, 010h                             ; 66 c1 e8 10
     xchg dx, ax                               ; 92
-    call 08b67h                               ; e8 82 ff
+    call 08c1eh                               ; e8 82 ff
     mov di, ax                                ; 89 c7
     test ax, ax                               ; 85 c0
-    je near 08caeh                            ; 0f 84 c1 00
+    je near 08d65h                            ; 0f 84 c1 00
     mov es, [bp-010h]                         ; 8e 46 f0
     mov word [es:bx+001eeh], di               ; 26 89 bf ee 01
     mov byte [es:bx+001edh], 000h             ; 26 c6 87 ed 01 00
@@ -13015,7 +13079,7 @@ ahci_hba_init_:                              ; 0xf8baa LB 0x125
     xor cx, cx                                ; 31 c9
     mov dx, strict word 00004h                ; ba 04 00
     mov ax, si                                ; 89 f0
-    call 07e3ah                               ; e8 19 f2
+    call 07ec1h                               ; e8 e9 f1
     mov ax, strict word 00004h                ; b8 04 00
     xor cx, cx                                ; 31 c9
     mov dx, si                                ; 89 f2
@@ -13032,7 +13096,7 @@ ahci_hba_init_:                              ; 0xf8baa LB 0x125
     shr eax, 010h                             ; 66 c1 e8 10
     xchg dx, ax                               ; 92
     test AL, strict byte 001h                 ; a8 01
-    jne short 08c21h                          ; 75 de
+    jne short 08cd8h                          ; 75 de
     xor ax, ax                                ; 31 c0
     xor cx, cx                                ; 31 c9
     mov dx, si                                ; 89 f2
@@ -13050,35 +13114,35 @@ ahci_hba_init_:                              ; 0xf8baa LB 0x125
     push strict byte 00000h                   ; 6a 00
     mov bx, strict word 0001fh                ; bb 1f 00
     xor cx, cx                                ; 31 c9
-    call 07efdh                               ; e8 96 f2
+    call 07f84h                               ; e8 66 f2
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     mov byte [bp-00eh], al                    ; 88 46 f2
     mov byte [bp-00ch], 000h                  ; c6 46 f4 00
-    jmp short 08c7bh                          ; eb 09
+    jmp short 08d32h                          ; eb 09
     inc byte [bp-00ch]                        ; fe 46 f4
     cmp byte [bp-00ch], 020h                  ; 80 7e f4 20
-    jnc short 08cach                          ; 73 31
+    jnc short 08d63h                          ; 73 31
     movzx cx, byte [bp-00ch]                  ; 0f b6 4e f4
     mov ax, strict word 00001h                ; b8 01 00
     xor dx, dx                                ; 31 d2
-    jcxz 08c8ch                               ; e3 06
+    jcxz 08d43h                               ; e3 06
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 08c86h                               ; e2 fa
+    loop 08d3dh                               ; e2 fa
     mov bx, ax                                ; 89 c3
     mov cx, dx                                ; 89 d1
     mov dx, strict word 0000ch                ; ba 0c 00
     mov ax, si                                ; 89 f0
-    call 07ec4h                               ; e8 2c f2
+    call 07f4bh                               ; e8 fc f1
     test al, al                               ; 84 c0
-    je short 08c72h                           ; 74 d6
+    je short 08d29h                           ; 74 d6
     movzx bx, byte [bp-00ch]                  ; 0f b6 5e f4
     xor ax, ax                                ; 31 c0
     mov dx, di                                ; 89 fa
-    call 08796h                               ; e8 ef fa
+    call 0881dh                               ; e8 bf fa
     dec byte [bp-00eh]                        ; fe 4e f2
-    jne short 08c72h                          ; 75 c6
+    jne short 08d29h                          ; 75 c6
     xor ax, ax                                ; 31 c0
     lea sp, [bp-00ah]                         ; 8d 66 f6
     pop di                                    ; 5f
@@ -13088,9 +13152,9 @@ ahci_hba_init_:                              ; 0xf8baa LB 0x125
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-    db  00bh, 005h, 004h, 003h, 002h, 001h, 000h, 09eh, 08dh, 07ch, 08dh, 082h, 08dh, 088h, 08dh, 08eh
-    db  08dh, 094h, 08dh, 09ah, 08dh, 09eh, 08dh
-_ahci_init:                                  ; 0xf8ccf LB 0xfe
+    db  00bh, 005h, 004h, 003h, 002h, 001h, 000h, 055h, 08eh, 033h, 08eh, 039h, 08eh, 03fh, 08eh, 045h
+    db  08eh, 04bh, 08eh, 051h, 08eh, 055h, 08eh
+_ahci_init:                                  ; 0xf8d86 LB 0xfe
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -13098,10 +13162,10 @@ _ahci_init:                                  ; 0xf8ccf LB 0xfe
     sub sp, strict byte 00006h                ; 83 ec 06
     mov ax, 00601h                            ; b8 01 06
     mov dx, strict word 00001h                ; ba 01 00
-    call 091edh                               ; e8 0d 05
+    call 092a4h                               ; e8 0d 05
     mov dx, ax                                ; 89 c2
     cmp ax, strict word 0ffffh                ; 3d ff ff
-    je near 08dc6h                            ; 0f 84 dd 00
+    je near 08e7dh                            ; 0f 84 dd 00
     xor al, al                                ; 30 c0
     shr ax, 008h                              ; c1 e8 08
     mov byte [bp-00ah], al                    ; 88 46 f6
@@ -13109,120 +13173,121 @@ _ahci_init:                                  ; 0xf8ccf LB 0xfe
     xor dh, dh                                ; 30 f6
     xor ah, ah                                ; 30 e4
     mov bx, strict word 00034h                ; bb 34 00
-    call 09218h                               ; e8 1a 05
+    call 092cfh                               ; e8 1a 05
     mov cl, al                                ; 88 c1
     test cl, cl                               ; 84 c9
-    je short 08d27h                           ; 74 23
+    je short 08ddeh                           ; 74 23
     movzx bx, cl                              ; 0f b6 d9
     movzx di, byte [bp-008h]                  ; 0f b6 7e f8
     movzx si, byte [bp-00ah]                  ; 0f b6 76 f6
     mov dx, di                                ; 89 fa
     mov ax, si                                ; 89 f0
-    call 09218h                               ; e8 02 05
+    call 092cfh                               ; e8 02 05
     cmp AL, strict byte 012h                  ; 3c 12
-    je short 08d27h                           ; 74 0d
+    je short 08ddeh                           ; 74 0d
     mov al, cl                                ; 88 c8
     db  0feh, 0c0h
     ; inc al                                    ; fe c0
     movzx bx, al                              ; 0f b6 d8
     mov dx, di                                ; 89 fa
     mov ax, si                                ; 89 f0
-    jmp short 08cfbh                          ; eb d4
+    jmp short 08db2h                          ; eb d4
     test cl, cl                               ; 84 c9
-    je near 08dc6h                            ; 0f 84 99 00
+    je near 08e7dh                            ; 0f 84 99 00
     add cl, 002h                              ; 80 c1 02
     movzx bx, cl                              ; 0f b6 d9
     movzx di, byte [bp-008h]                  ; 0f b6 7e f8
     movzx si, byte [bp-00ah]                  ; 0f b6 76 f6
     mov dx, di                                ; 89 fa
     mov ax, si                                ; 89 f0
-    call 09218h                               ; e8 d6 04
+    call 092cfh                               ; e8 d6 04
     cmp AL, strict byte 010h                  ; 3c 10
-    jne near 08dc6h                           ; 0f 85 7e 00
+    jne near 08e7dh                           ; 0f 85 7e 00
     mov byte [bp-006h], 000h                  ; c6 46 fa 00
     mov al, cl                                ; 88 c8
     add AL, strict byte 002h                  ; 04 02
     movzx bx, al                              ; 0f b6 d8
     mov dx, di                                ; 89 fa
     mov ax, si                                ; 89 f0
-    call 0923ch                               ; e8 e2 04
+    call 092f3h                               ; e8 e2 04
     mov dx, ax                                ; 89 c2
     and ax, strict word 0000fh                ; 25 0f 00
     sub ax, strict word 00004h                ; 2d 04 00
     cmp ax, strict word 0000bh                ; 3d 0b 00
-    jnbe short 08d9eh                         ; 77 37
+    jnbe short 08e55h                         ; 77 37
     push CS                                   ; 0e
     pop ES                                    ; 07
     mov cx, strict word 00008h                ; b9 08 00
-    mov di, 08cb8h                            ; bf b8 8c
+    mov di, 08d6fh                            ; bf 6f 8d
     repne scasb                               ; f2 ae
     sal cx, 1                                 ; d1 e1
     mov di, cx                                ; 89 cf
-    mov ax, word [cs:di-07341h]               ; 2e 8b 85 bf 8c
+    mov ax, word [cs:di-0728ah]               ; 2e 8b 85 76 8d
     jmp ax                                    ; ff e0
     mov byte [bp-006h], 010h                  ; c6 46 fa 10
-    jmp short 08d9eh                          ; eb 1c
+    jmp short 08e55h                          ; eb 1c
     mov byte [bp-006h], 014h                  ; c6 46 fa 14
-    jmp short 08d9eh                          ; eb 16
+    jmp short 08e55h                          ; eb 16
     mov byte [bp-006h], 018h                  ; c6 46 fa 18
-    jmp short 08d9eh                          ; eb 10
+    jmp short 08e55h                          ; eb 10
     mov byte [bp-006h], 01ch                  ; c6 46 fa 1c
-    jmp short 08d9eh                          ; eb 0a
+    jmp short 08e55h                          ; eb 0a
     mov byte [bp-006h], 020h                  ; c6 46 fa 20
-    jmp short 08d9eh                          ; eb 04
+    jmp short 08e55h                          ; eb 04
     mov byte [bp-006h], 024h                  ; c6 46 fa 24
     mov si, dx                                ; 89 d6
     shr si, 004h                              ; c1 ee 04
     sal si, 002h                              ; c1 e6 02
     mov al, byte [bp-006h]                    ; 8a 46 fa
     test al, al                               ; 84 c0
-    je short 08dc6h                           ; 74 19
+    je short 08e7dh                           ; 74 19
     movzx bx, al                              ; 0f b6 d8
     movzx dx, byte [bp-008h]                  ; 0f b6 56 f8
     movzx ax, byte [bp-00ah]                  ; 0f b6 46 f6
-    call 0925eh                               ; e8 a3 04
+    call 09315h                               ; e8 a3 04
     test AL, strict byte 001h                 ; a8 01
-    je short 08dc6h                           ; 74 07
+    je short 08e7dh                           ; 74 07
     and AL, strict byte 0f0h                  ; 24 f0
     add ax, si                                ; 01 f0
-    call 08baah                               ; e8 e4 fd
+    call 08c61h                               ; e8 e4 fd
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-apm_out_str_:                                ; 0xf8dcd LB 0x39
+apm_out_str_:                                ; 0xf8e84 LB 0x39
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
     mov bx, ax                                ; 89 c3
     cmp byte [bx], 000h                       ; 80 3f 00
-    je short 08de2h                           ; 74 0a
+    je short 08e99h                           ; 74 0a
     mov al, byte [bx]                         ; 8a 07
     out DX, AL                                ; ee
     inc bx                                    ; 43
     mov al, byte [bx]                         ; 8a 07
     db  00ah, 0c0h
     ; or al, al                                 ; 0a c0
-    jne short 08ddah                          ; 75 f8
+    jne short 08e91h                          ; 75 f8
     lea sp, [bp-002h]                         ; 8d 66 fe
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-    sub word [bp-0710bh], cx                  ; 29 8e f5 8e
-    cmp cx, word [bp-071aah]                  ; 3b 8e 56 8e
-    cmc                                       ; f5
-    mov es, [bx+di-00a72h]                    ; 8e 81 8e f5
-    mov es, [bp-03572h]                       ; 8e 86 8e ca
-    mov cs, dx                                ; 8e ca
-    mov cs, dx                                ; 8e ca
-    mov es, bp                                ; 8e c5
-    mov cs, dx                                ; 8e ca
-    mov cs, dx                                ; 8e ca
-    db  08eh
-    db  0beh
-    db  08eh
-_apm_function:                               ; 0xf8e06 LB 0xf5
+    loopne 08e2fh                             ; e0 8e
+    lodsb                                     ; ac
+    db  08fh, 0f2h
+    ; pop dx                                    ; 8f f2
+    mov cs, [di]                              ; 8e 0d
+    db  08fh, 0ach, 08fh, 038h
+    ; pop word [si+0388fh]                      ; 8f ac 8f 38
+    db  08fh, 0ach, 08fh, 03dh
+    ; pop word [si+03d8fh]                      ; 8f ac 8f 3d
+    pop word [bx+di-07e71h]                   ; 8f 81 8f 81
+    pop word [bx+di+07c8fh]                   ; 8f 81 8f 7c
+    pop word [bx+di-07e71h]                   ; 8f 81 8f 81
+    db  08fh, 075h, 08fh
+    ; pop word [di-071h]                        ; 8f 75 8f
+_apm_function:                               ; 0xf8ebd LB 0xf5
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -13230,23 +13295,23 @@ _apm_function:                               ; 0xf8e06 LB 0xf5
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
     cmp ax, strict word 0000eh                ; 3d 0e 00
-    jnbe near 08ecah                          ; 0f 87 b0 00
+    jnbe near 08f81h                          ; 0f 87 b0 00
     mov bx, ax                                ; 89 c3
     add bx, ax                                ; 01 c3
     mov dx, word [bp+018h]                    ; 8b 56 18
     or dl, 001h                               ; 80 ca 01
-    jmp word [cs:bx-07218h]                   ; 2e ff a7 e8 8d
+    jmp word [cs:bx-07161h]                   ; 2e ff a7 9f 8e
     mov word [bp+012h], 00102h                ; c7 46 12 02 01
     mov word [bp+00ch], 0504dh                ; c7 46 0c 4d 50
     mov word [bp+010h], strict word 00003h    ; c7 46 10 03 00
-    jmp near 08ef5h                           ; e9 ba 00
+    jmp near 08fach                           ; e9 ba 00
     mov word [bp+012h], 0f000h                ; c7 46 12 00 f0
-    mov word [bp+00ch], 09454h                ; c7 46 0c 54 94
+    mov word [bp+00ch], 09504h                ; c7 46 0c 04 95
     mov word [bp+010h], 0f000h                ; c7 46 10 00 f0
     mov ax, strict word 0fff0h                ; b8 f0 ff
     mov word [bp+006h], ax                    ; 89 46 06
     mov word [bp+004h], ax                    ; 89 46 04
-    jmp near 08ef5h                           ; e9 9f 00
+    jmp near 08fach                           ; e9 9f 00
     mov word [bp+012h], 0f000h                ; c7 46 12 00 f0
     mov word [bp+00ch], 0da40h                ; c7 46 0c 40 da
     mov ax, 0f000h                            ; b8 00 f0
@@ -13259,43 +13324,43 @@ _apm_function:                               ; 0xf8e06 LB 0xf5
     sal ebx, 010h                             ; 66 c1 e3 10
     mov si, ax                                ; 89 c6
     sal esi, 010h                             ; 66 c1 e6 10
-    jmp near 08ef5h                           ; e9 74 00
+    jmp near 08fach                           ; e9 74 00
     sti                                       ; fb
     hlt                                       ; f4
-    jmp near 08ef5h                           ; e9 6f 00
+    jmp near 08fach                           ; e9 6f 00
     cmp word [bp+010h], strict byte 00003h    ; 83 7e 10 03
-    je short 08eabh                           ; 74 1f
+    je short 08f62h                           ; 74 1f
     cmp word [bp+010h], strict byte 00002h    ; 83 7e 10 02
-    je short 08ea3h                           ; 74 11
+    je short 08f5ah                           ; 74 11
     cmp word [bp+010h], strict byte 00001h    ; 83 7e 10 01
-    jne short 08eb3h                          ; 75 1b
+    jne short 08f6ah                          ; 75 1b
     mov dx, 08900h                            ; ba 00 89
-    mov ax, 00d12h                            ; b8 12 0d
-    call 08dcdh                               ; e8 2c ff
-    jmp short 08ef5h                          ; eb 52
+    mov ax, 00d2ah                            ; b8 2a 0d
+    call 08e84h                               ; e8 2c ff
+    jmp short 08fach                          ; eb 52
     mov dx, 08900h                            ; ba 00 89
-    mov ax, 00d1ah                            ; b8 1a 0d
-    jmp short 08e9eh                          ; eb f3
+    mov ax, 00d32h                            ; b8 32 0d
+    jmp short 08f55h                          ; eb f3
     mov dx, 08900h                            ; ba 00 89
-    mov ax, 00d22h                            ; b8 22 0d
-    jmp short 08e9eh                          ; eb eb
+    mov ax, 00d3ah                            ; b8 3a 0d
+    jmp short 08f55h                          ; eb eb
     or ah, 00ah                               ; 80 cc 0a
     mov word [bp+012h], ax                    ; 89 46 12
     mov word [bp+018h], dx                    ; 89 56 18
-    jmp short 08ef5h                          ; eb 37
+    jmp short 08fach                          ; eb 37
     mov word [bp+012h], 00102h                ; c7 46 12 02 01
-    jmp short 08ef5h                          ; eb 30
+    jmp short 08fach                          ; eb 30
     or ah, 080h                               ; 80 cc 80
-    jmp short 08eb6h                          ; eb ec
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp short 08f6dh                          ; eb ec
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 f7 89
+    call 018e1h                               ; e8 55 89
     push word [bp+00ch]                       ; ff 76 0c
     push word [bp+012h]                       ; ff 76 12
-    push 00d2bh                               ; 68 2b 0d
+    push 00d43h                               ; 68 43 0d
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 2a 8a
+    call 01922h                               ; e8 88 89
     add sp, strict byte 00008h                ; 83 c4 08
     mov ax, word [bp+012h]                    ; 8b 46 12
     xor ah, ah                                ; 30 e4
@@ -13306,7 +13371,7 @@ _apm_function:                               ; 0xf8e06 LB 0xf5
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-pci16_select_reg_:                           ; 0xf8efb LB 0x24
+pci16_select_reg_:                           ; 0xf8fb2 LB 0x24
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -13323,7 +13388,7 @@ pci16_select_reg_:                           ; 0xf8efb LB 0x24
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-pci16_find_device_:                          ; 0xf8f1f LB 0xf7
+pci16_find_device_:                          ; 0xf8fd6 LB 0xf7
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -13337,49 +13402,49 @@ pci16_find_device_:                          ; 0xf8f1f LB 0xf7
     xor bx, bx                                ; 31 db
     mov byte [bp-008h], 000h                  ; c6 46 f8 00
     test bl, 007h                             ; f6 c3 07
-    jne short 08f67h                          ; 75 2d
+    jne short 0901eh                          ; 75 2d
     mov dx, strict word 0000eh                ; ba 0e 00
     mov ax, bx                                ; 89 d8
-    call 08efbh                               ; e8 b9 ff
+    call 08fb2h                               ; e8 b9 ff
     mov dx, 00cfeh                            ; ba fe 0c
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     mov byte [bp-006h], al                    ; 88 46 fa
     cmp AL, strict byte 0ffh                  ; 3c ff
-    jne short 08f55h                          ; 75 06
+    jne short 0900ch                          ; 75 06
     add bx, strict byte 00008h                ; 83 c3 08
-    jmp near 08fe8h                           ; e9 93 00
+    jmp near 0909fh                           ; e9 93 00
     test byte [bp-006h], 080h                 ; f6 46 fa 80
-    je short 08f62h                           ; 74 07
+    je short 09019h                           ; 74 07
     mov word [bp-00ah], strict word 00001h    ; c7 46 f6 01 00
-    jmp short 08f67h                          ; eb 05
+    jmp short 0901eh                          ; eb 05
     mov word [bp-00ah], strict word 00008h    ; c7 46 f6 08 00
     mov al, byte [bp-006h]                    ; 8a 46 fa
     and AL, strict byte 007h                  ; 24 07
     cmp AL, strict byte 001h                  ; 3c 01
-    jne short 08f8fh                          ; 75 1f
+    jne short 09046h                          ; 75 1f
     mov ax, bx                                ; 89 d8
     shr ax, 008h                              ; c1 e8 08
     test ax, ax                               ; 85 c0
-    jne short 08f8fh                          ; 75 16
+    jne short 09046h                          ; 75 16
     mov dx, strict word 0001ah                ; ba 1a 00
     mov ax, bx                                ; 89 d8
-    call 08efbh                               ; e8 7a ff
+    call 08fb2h                               ; e8 7a ff
     mov dx, 00cfeh                            ; ba fe 0c
     in AL, DX                                 ; ec
     db  02ah, 0e4h
     ; sub ah, ah                                ; 2a e4
     cmp al, byte [bp-008h]                    ; 3a 46 f8
-    jbe short 08f8fh                          ; 76 03
+    jbe short 09046h                          ; 76 03
     mov byte [bp-008h], al                    ; 88 46 f8
     test di, di                               ; 85 ff
-    je short 08f98h                           ; 74 05
+    je short 0904fh                           ; 74 05
     mov dx, strict word 00008h                ; ba 08 00
-    jmp short 08f9ah                          ; eb 02
+    jmp short 09051h                          ; eb 02
     xor dx, dx                                ; 31 d2
     mov ax, bx                                ; 89 d8
-    call 08efbh                               ; e8 5c ff
+    call 08fb2h                               ; e8 5c ff
     mov dx, 00cfch                            ; ba fc 0c
     in eax, DX                                ; 66 ed
     db  08bh, 0d0h
@@ -13390,47 +13455,49 @@ pci16_find_device_:                          ; 0xf8f1f LB 0xf7
     mov word [bp-00ch], dx                    ; 89 56 f4
     mov word [bp-010h], strict word 00000h    ; c7 46 f0 00 00
     test di, di                               ; 85 ff
-    je short 08fc9h                           ; 74 0f
+    je short 09080h                           ; 74 0f
     mov cx, strict word 00008h                ; b9 08 00
     shr dx, 1                                 ; d1 ea
     rcr ax, 1                                 ; d1 d8
-    loop 08fbdh                               ; e2 fa
+    loop 09074h                               ; e2 fa
     mov word [bp-00eh], ax                    ; 89 46 f2
     mov word [bp-00ch], dx                    ; 89 56 f4
     mov ax, word [bp-00ch]                    ; 8b 46 f4
     cmp ax, word [bp-014h]                    ; 3b 46 ec
-    jne short 08fd9h                          ; 75 08
+    jne short 09090h                          ; 75 08
     mov ax, word [bp-00eh]                    ; 8b 46 f2
     cmp ax, word [bp-012h]                    ; 3b 46 ee
-    je short 08fdfh                           ; 74 06
+    je short 09096h                           ; 74 06
     cmp word [bp-010h], strict byte 00000h    ; 83 7e f0 00
-    je short 08fe5h                           ; 74 06
+    je short 0909ch                           ; 74 06
     dec si                                    ; 4e
     cmp si, strict byte 0ffffh                ; 83 fe ff
-    je short 08ff7h                           ; 74 12
+    je short 090aeh                           ; 74 12
     add bx, word [bp-00ah]                    ; 03 5e f6
     mov dx, bx                                ; 89 da
     shr dx, 008h                              ; c1 ea 08
     movzx ax, byte [bp-008h]                  ; 0f b6 46 f8
     cmp dx, ax                                ; 39 c2
-    jbe near 08f35h                           ; 0f 86 3e ff
+    jbe near 08fech                           ; 0f 86 3e ff
     cmp si, strict byte 0ffffh                ; 83 fe ff
-    jne short 09000h                          ; 75 04
+    jne short 090b7h                          ; 75 04
     mov ax, bx                                ; 89 d8
-    jmp short 09003h                          ; eb 03
+    jmp short 090bah                          ; eb 03
     mov ax, strict word 0ffffh                ; b8 ff ff
     lea sp, [bp-004h]                         ; 8d 66 fc
     pop di                                    ; 5f
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-    clc                                       ; f8
-    nop                                       ; 90
-    adc dl, byte [bx+di-06edbh]               ; 12 91 25 91
-    cmp dl, byte [bx+di-06eb3h]               ; 3a 91 4d 91
-    pushaw                                    ; 60
+    scasw                                     ; af
     xchg cx, ax                               ; 91
-_pci16_function:                             ; 0xf9016 LB 0x1d7
+    leave                                     ; c9
+    xchg cx, ax                               ; 91
+    fcom qword [bx+di-06e0fh]                 ; dc 91 f1 91
+    add AL, strict byte 092h                  ; 04 92
+    pop SS                                    ; 17
+    xchg dx, ax                               ; 92
+_pci16_function:                             ; 0xf90cd LB 0x1d7
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -13444,69 +13511,69 @@ _pci16_function:                             ; 0xf9016 LB 0x1d7
     mov ax, word [bp+020h]                    ; 8b 46 20
     xor ah, ah                                ; 30 e4
     cmp bx, strict byte 00003h                ; 83 fb 03
-    jc short 0904fh                           ; 72 1a
-    jbe short 090a7h                          ; 76 70
+    jc short 09106h                           ; 72 1a
+    jbe short 0915eh                          ; 76 70
     cmp bx, strict byte 0000eh                ; 83 fb 0e
-    je near 09174h                            ; 0f 84 36 01
+    je near 0922bh                            ; 0f 84 36 01
     cmp bx, strict byte 00008h                ; 83 fb 08
-    jc near 091b9h                            ; 0f 82 74 01
+    jc near 09270h                            ; 0f 82 74 01
     cmp bx, strict byte 0000dh                ; 83 fb 0d
-    jbe near 090cch                           ; 0f 86 80 00
-    jmp near 091b9h                           ; e9 6a 01
+    jbe near 09183h                           ; 0f 86 80 00
+    jmp near 09270h                           ; e9 6a 01
     cmp bx, strict byte 00002h                ; 83 fb 02
-    je short 09077h                           ; 74 23
+    je short 0912eh                           ; 74 23
     cmp bx, strict byte 00001h                ; 83 fb 01
-    jne near 091b9h                           ; 0f 85 5e 01
+    jne near 09270h                           ; 0f 85 5e 01
     mov word [bp+020h], strict word 00001h    ; c7 46 20 01 00
     mov word [bp+014h], 00210h                ; c7 46 14 10 02
     mov word [bp+01ch], strict word 00000h    ; c7 46 1c 00 00
     mov word [bp+018h], 04350h                ; c7 46 18 50 43
     mov word [bp+01ah], 02049h                ; c7 46 1a 49 20
-    jmp near 091e6h                           ; e9 6f 01
+    jmp near 0929dh                           ; e9 6f 01
     cmp word [bp+018h], strict byte 0ffffh    ; 83 7e 18 ff
-    jne short 09083h                          ; 75 06
+    jne short 0913ah                          ; 75 06
     or ah, 083h                               ; 80 cc 83
-    jmp near 091dfh                           ; e9 5c 01
+    jmp near 09296h                           ; e9 5c 01
     mov bx, word [bp+008h]                    ; 8b 5e 08
     mov dx, word [bp+01ch]                    ; 8b 56 1c
     mov ax, word [bp+018h]                    ; 8b 46 18
     xor cx, cx                                ; 31 c9
-    call 08f1fh                               ; e8 8e fe
+    call 08fd6h                               ; e8 8e fe
     cmp ax, strict word 0ffffh                ; 3d ff ff
-    jne short 090a1h                          ; 75 0b
+    jne short 09158h                          ; 75 0b
     mov ax, word [bp+020h]                    ; 8b 46 20
     xor ah, ah                                ; 30 e4
     or ah, 086h                               ; 80 cc 86
-    jmp near 091dfh                           ; e9 3e 01
+    jmp near 09296h                           ; e9 3e 01
     mov word [bp+014h], ax                    ; 89 46 14
-    jmp near 091e6h                           ; e9 3f 01
+    jmp near 0929dh                           ; e9 3f 01
     mov bx, word [bp+008h]                    ; 8b 5e 08
     mov ax, word [bp+01ch]                    ; 8b 46 1c
     mov dx, word [bp+01eh]                    ; 8b 56 1e
     mov cx, strict word 00001h                ; b9 01 00
-    call 08f1fh                               ; e8 69 fe
+    call 08fd6h                               ; e8 69 fe
     cmp ax, strict word 0ffffh                ; 3d ff ff
-    jne short 090c6h                          ; 75 0b
+    jne short 0917dh                          ; 75 0b
     mov ax, word [bp+020h]                    ; 8b 46 20
     xor ah, ah                                ; 30 e4
     or ah, 086h                               ; 80 cc 86
-    jmp near 091dfh                           ; e9 19 01
+    jmp near 09296h                           ; e9 19 01
     mov word [bp+014h], ax                    ; 89 46 14
-    jmp near 091e6h                           ; e9 1a 01
+    jmp near 0929dh                           ; e9 1a 01
     cmp word [bp+004h], 00100h                ; 81 7e 04 00 01
-    jc short 090d9h                           ; 72 06
+    jc short 09190h                           ; 72 06
     or ah, 087h                               ; 80 cc 87
-    jmp near 091dfh                           ; e9 06 01
+    jmp near 09296h                           ; e9 06 01
     mov dx, word [bp+004h]                    ; 8b 56 04
     mov ax, word [bp+014h]                    ; 8b 46 14
-    call 08efbh                               ; e8 19 fe
+    call 08fb2h                               ; e8 19 fe
     mov bx, word [bp+020h]                    ; 8b 5e 20
     xor bh, bh                                ; 30 ff
     sub bx, strict byte 00008h                ; 83 eb 08
     cmp bx, strict byte 00005h                ; 83 fb 05
-    jnbe near 091e6h                          ; 0f 87 f5 00
+    jnbe near 0929dh                          ; 0f 87 f5 00
     add bx, bx                                ; 01 db
-    jmp word [cs:bx-06ff6h]                   ; 2e ff a7 0a 90
+    jmp word [cs:bx-06f3fh]                   ; 2e ff a7 c1 90
     mov bx, word [bp+01ch]                    ; 8b 5e 1c
     xor bl, bl                                ; 30 db
     mov dx, word [bp+004h]                    ; 8b 56 04
@@ -13517,14 +13584,14 @@ _pci16_function:                             ; 0xf9016 LB 0x1d7
     ; sub ah, ah                                ; 2a e4
     or bx, ax                                 ; 09 c3
     mov word [bp+01ch], bx                    ; 89 5e 1c
-    jmp near 091e6h                           ; e9 d4 00
+    jmp near 0929dh                           ; e9 d4 00
     mov dx, word [bp+004h]                    ; 8b 56 04
     xor dh, dh                                ; 30 f6
     and dl, 002h                              ; 80 e2 02
     add dx, 00cfch                            ; 81 c2 fc 0c
     in ax, DX                                 ; ed
     mov word [bp+01ch], ax                    ; 89 46 1c
-    jmp near 091e6h                           ; e9 c1 00
+    jmp near 0929dh                           ; e9 c1 00
     mov dx, 00cfch                            ; ba fc 0c
     in eax, DX                                ; 66 ed
     db  08bh, 0d0h
@@ -13533,21 +13600,21 @@ _pci16_function:                             ; 0xf9016 LB 0x1d7
     xchg dx, ax                               ; 92
     mov word [bp+01ch], ax                    ; 89 46 1c
     mov word [bp+01eh], dx                    ; 89 56 1e
-    jmp near 091e6h                           ; e9 ac 00
+    jmp near 0929dh                           ; e9 ac 00
     mov ax, word [bp+01ch]                    ; 8b 46 1c
     mov dx, word [bp+004h]                    ; 8b 56 04
     xor dh, dh                                ; 30 f6
     and dl, 003h                              ; 80 e2 03
     add dx, 00cfch                            ; 81 c2 fc 0c
     out DX, AL                                ; ee
-    jmp near 091e6h                           ; e9 99 00
+    jmp near 0929dh                           ; e9 99 00
     mov ax, word [bp+01ch]                    ; 8b 46 1c
     mov dx, word [bp+004h]                    ; 8b 56 04
     xor dh, dh                                ; 30 f6
     and dl, 002h                              ; 80 e2 02
     add dx, 00cfch                            ; 81 c2 fc 0c
     out DX, ax                                ; ef
-    jmp near 091e6h                           ; e9 86 00
+    jmp near 0929dh                           ; e9 86 00
     mov ax, word [bp+01ch]                    ; 8b 46 1c
     mov cx, word [bp+01eh]                    ; 8b 4e 1e
     mov dx, 00cfch                            ; ba fc 0c
@@ -13556,20 +13623,20 @@ _pci16_function:                             ; 0xf9016 LB 0x1d7
     db  08bh, 0c1h
     ; mov ax, cx                                ; 8b c1
     out DX, eax                               ; 66 ef
-    jmp short 091e6h                          ; eb 72
+    jmp short 0929dh                          ; eb 72
     mov bx, word [bp+004h]                    ; 8b 5e 04
     mov es, [bp+026h]                         ; 8e 46 26
     mov word [bp-008h], bx                    ; 89 5e f8
     mov [bp-006h], es                         ; 8c 46 fa
     mov cx, word [0f4a0h]                     ; 8b 0e a0 f4
     cmp cx, word [es:bx]                      ; 26 3b 0f
-    jbe short 0919ah                          ; 76 11
+    jbe short 09251h                          ; 76 11
     mov ax, word [bp+020h]                    ; 8b 46 20
     xor ah, ah                                ; 30 e4
     or ah, 089h                               ; 80 cc 89
     mov word [bp+020h], ax                    ; 89 46 20
     or word [bp+02ch], strict byte 00001h     ; 83 4e 2c 01
-    jmp short 091aeh                          ; eb 14
+    jmp short 09265h                          ; eb 14
     les di, [es:bx+002h]                      ; 26 c4 7f 02
     mov si, 0f2c0h                            ; be c0 f2
     mov dx, ds                                ; 8c da
@@ -13581,18 +13648,18 @@ _pci16_function:                             ; 0xf9016 LB 0x1d7
     mov ax, word [0f4a0h]                     ; a1 a0 f4
     les bx, [bp-008h]                         ; c4 5e f8
     mov word [es:bx], ax                      ; 26 89 07
-    jmp short 091e6h                          ; eb 2d
-    mov bx, 00da2h                            ; bb a2 0d
+    jmp short 0929dh                          ; eb 2d
+    mov bx, 00dbah                            ; bb ba 0d
     mov cx, ds                                ; 8c d9
     mov ax, strict word 00004h                ; b8 04 00
-    call 018cch                               ; e8 08 87
+    call 018e1h                               ; e8 66 86
     mov ax, word [bp+014h]                    ; 8b 46 14
     push ax                                   ; 50
     mov ax, word [bp+020h]                    ; 8b 46 20
     push ax                                   ; 50
-    push 00d5eh                               ; 68 5e 0d
+    push 00d76h                               ; 68 76 0d
     push strict byte 00004h                   ; 6a 04
-    call 0190dh                               ; e8 39 87
+    call 01922h                               ; e8 97 86
     add sp, strict byte 00008h                ; 83 c4 08
     mov ax, word [bp+020h]                    ; 8b 46 20
     xor ah, ah                                ; 30 e4
@@ -13604,7 +13671,7 @@ _pci16_function:                             ; 0xf9016 LB 0x1d7
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn                                      ; c3
-pci_find_classcode_:                         ; 0xf91ed LB 0x2b
+pci_find_classcode_:                         ; 0xf92a4 LB 0x2b
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
@@ -13619,7 +13686,7 @@ pci_find_classcode_:                         ; 0xf91ed LB 0x2b
     ; mov cx, dx                                ; 8b ca
     int 01ah                                  ; cd 1a
     cmp ah, 000h                              ; 80 fc 00
-    je near 0920eh                            ; 0f 84 03 00
+    je near 092c5h                            ; 0f 84 03 00
     mov bx, strict word 0ffffh                ; bb ff ff
     mov ax, bx                                ; 89 d8
     lea sp, [bp-006h]                         ; 8d 66 fa
@@ -13628,7 +13695,7 @@ pci_find_classcode_:                         ; 0xf91ed LB 0x2b
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-pci_read_config_byte_:                       ; 0xf9218 LB 0x24
+pci_read_config_byte_:                       ; 0xf92cf LB 0x24
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -13647,7 +13714,7 @@ pci_read_config_byte_:                       ; 0xf9218 LB 0x24
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-pci_read_config_word_:                       ; 0xf923c LB 0x22
+pci_read_config_word_:                       ; 0xf92f3 LB 0x22
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -13666,7 +13733,7 @@ pci_read_config_word_:                       ; 0xf923c LB 0x22
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-pci_read_config_dword_:                      ; 0xf925e LB 0x27
+pci_read_config_dword_:                      ; 0xf9315 LB 0x27
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push cx                                   ; 51
@@ -13687,7 +13754,7 @@ pci_read_config_dword_:                      ; 0xf925e LB 0x27
     pop cx                                    ; 59
     pop bp                                    ; 5d
     retn                                      ; c3
-vds_is_present_:                             ; 0xf9285 LB 0x1d
+vds_is_present_:                             ; 0xf933c LB 0x1d
     push bx                                   ; 53
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
@@ -13695,7 +13762,7 @@ vds_is_present_:                             ; 0xf9285 LB 0x1d
     mov ax, strict word 00040h                ; b8 40 00
     mov es, ax                                ; 8e c0
     test byte [es:bx], 020h                   ; 26 f6 07 20
-    je short 0929dh                           ; 74 06
+    je short 09354h                           ; 74 06
     mov ax, strict word 00001h                ; b8 01 00
     pop bp                                    ; 5d
     pop bx                                    ; 5b
@@ -13704,7 +13771,7 @@ vds_is_present_:                             ; 0xf9285 LB 0x1d
     pop bp                                    ; 5d
     pop bx                                    ; 5b
     retn                                      ; c3
-vds_real_to_lin_:                            ; 0xf92a2 LB 0x1e
+vds_real_to_lin_:                            ; 0xf9359 LB 0x1e
     push bx                                   ; 53
     push cx                                   ; 51
     push bp                                   ; 55
@@ -13715,7 +13782,7 @@ vds_real_to_lin_:                            ; 0xf92a2 LB 0x1e
     mov cx, strict word 00004h                ; b9 04 00
     sal ax, 1                                 ; d1 e0
     rcl dx, 1                                 ; d1 d2
-    loop 092b0h                               ; e2 fa
+    loop 09367h                               ; e2 fa
     xor cx, cx                                ; 31 c9
     add ax, bx                                ; 01 d8
     adc dx, cx                                ; 11 ca
@@ -13723,7 +13790,7 @@ vds_real_to_lin_:                            ; 0xf92a2 LB 0x1e
     pop cx                                    ; 59
     pop bx                                    ; 5b
     retn                                      ; c3
-vds_build_sg_list_:                          ; 0xf92c0 LB 0x79
+vds_build_sg_list_:                          ; 0xf9377 LB 0x79
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push si                                   ; 56
@@ -13737,23 +13804,23 @@ vds_build_sg_list_:                          ; 0xf92c0 LB 0x79
     mov word [es:di], bx                      ; 26 89 1d
     mov bx, word [bp+006h]                    ; 8b 5e 06
     mov word [es:di+002h], bx                 ; 26 89 5d 02
-    call 092a2h                               ; e8 c3 ff
+    call 09359h                               ; e8 c3 ff
     mov es, si                                ; 8e c6
     mov word [es:di+004h], ax                 ; 26 89 45 04
     mov word [es:di+006h], dx                 ; 26 89 55 06
     mov word [es:di+008h], strict word 00000h ; 26 c7 45 08 00 00
-    call 09285h                               ; e8 93 ff
+    call 0933ch                               ; e8 93 ff
     test ax, ax                               ; 85 c0
-    je short 09309h                           ; 74 13
+    je short 093c0h                           ; 74 13
     mov es, si                                ; 8e c6
     mov ax, 08105h                            ; b8 05 81
     mov dx, strict word 00000h                ; ba 00 00
     int 04bh                                  ; cd 4b
-    jc near 09306h                            ; 0f 82 02 00
+    jc near 093bdh                            ; 0f 82 02 00
     db  032h, 0c0h
     ; xor al, al                                ; 32 c0
     cbw                                       ; 98
-    jmp short 09330h                          ; eb 27
+    jmp short 093e7h                          ; eb 27
     mov es, si                                ; 8e c6
     mov word [es:di+00eh], strict word 00001h ; 26 c7 45 0e 01 00
     mov dx, word [es:di+004h]                 ; 26 8b 55 04
@@ -13770,21 +13837,21 @@ vds_build_sg_list_:                          ; 0xf92c0 LB 0x79
     pop si                                    ; 5e
     pop bp                                    ; 5d
     retn 00004h                               ; c2 04 00
-vds_free_sg_list_:                           ; 0xf9339 LB 0x37
+vds_free_sg_list_:                           ; 0xf93f0 LB 0x30
     push bp                                   ; 55
     mov bp, sp                                ; 89 e5
     push bx                                   ; 53
     push di                                   ; 57
     mov bx, ax                                ; 89 c3
-    call 09285h                               ; e8 42 ff
+    call 0933ch                               ; e8 42 ff
     test ax, ax                               ; 85 c0
-    je short 0935ah                           ; 74 13
+    je short 09411h                           ; 74 13
     mov di, bx                                ; 89 df
     mov es, dx                                ; 8e c2
     mov ax, 08106h                            ; b8 06 81
     mov dx, strict word 00000h                ; ba 00 00
     int 04bh                                  ; cd 4b
-    jc near 09359h                            ; 0f 82 02 00
+    jc near 09410h                            ; 0f 82 02 00
     db  032h, 0c0h
     ; xor al, al                                ; 32 c0
     cbw                                       ; 98
@@ -13795,8 +13862,7 @@ vds_free_sg_list_:                           ; 0xf9339 LB 0x37
     pop bx                                    ; 5b
     pop bp                                    ; 5d
     retn                                      ; c3
-    times 0x7 db 0
-__U4D:                                       ; 0xf9370 LB 0x39
+__U4D:                                       ; 0xf9420 LB 0x39
     pushfw                                    ; 9c
     push eax                                  ; 66 50
     push edx                                  ; 66 52
@@ -13826,7 +13892,7 @@ __U4D:                                       ; 0xf9370 LB 0x39
     rol eax, 010h                             ; 66 c1 c0 10
     popfw                                     ; 9d
     retn                                      ; c3
-__U4M:                                       ; 0xf93a9 LB 0x31
+__U4M:                                       ; 0xf9459 LB 0x31
     pushfw                                    ; 9c
     push eax                                  ; 66 50
     push edx                                  ; 66 52
@@ -13851,7 +13917,7 @@ __U4M:                                       ; 0xf93a9 LB 0x31
     rol eax, 010h                             ; 66 c1 c0 10
     popfw                                     ; 9d
     retn                                      ; c3
-_fmemset_:                                   ; 0xf93da LB 0xd
+_fmemset_:                                   ; 0xf948a LB 0xd
     push di                                   ; 57
     mov es, dx                                ; 8e c2
     db  08bh, 0f8h
@@ -13861,7 +13927,7 @@ _fmemset_:                                   ; 0xf93da LB 0xd
     xchg al, bl                               ; 86 d8
     pop di                                    ; 5f
     retn                                      ; c3
-_fmemcpy_:                                   ; 0xf93e7 LB 0x33
+_fmemcpy_:                                   ; 0xf9497 LB 0x33
     push bp                                   ; 55
     db  08bh, 0ech
     ; mov bp, sp                                ; 8b ec
@@ -13881,24 +13947,9 @@ _fmemcpy_:                                   ; 0xf93e7 LB 0x33
     pop di                                    ; 5f
     leave                                     ; c9
     retn                                      ; c3
-    add byte [bx+si], dh                      ; 00 30
-    xchg sp, ax                               ; 94
-    xor dl, byte [si-06bcah]                  ; 32 94 36 94
-    db  036h, 094h
-    ; ss xchg sp, ax                            ; 36 94
-    db  036h, 094h
-    ; ss xchg sp, ax                            ; 36 94
-    cmp byte [si-06bc8h], dl                  ; 38 94 38 94
-    cmp dl, byte [si-06bc2h]                  ; 3a 94 3e 94
-    db  03eh, 094h
-    ; ds xchg sp, ax                            ; 3e 94
-    inc ax                                    ; 40
-    xchg sp, ax                               ; 94
-    inc bp                                    ; 45
-    xchg sp, ax                               ; 94
-    inc di                                    ; 47
-    xchg sp, ax                               ; 94
-apm_worker:                                  ; 0xf941a LB 0x3a
+    db  000h, 0e0h, 094h, 0e2h, 094h, 0e6h, 094h, 0e6h, 094h, 0e6h, 094h, 0e8h, 094h, 0e8h, 094h, 0eah
+    db  094h, 0eeh, 094h, 0eeh, 094h, 0f0h, 094h, 0f5h, 094h, 0f7h, 094h
+apm_worker:                                  ; 0xf94ca LB 0x3a
     sti                                       ; fb
     push ax                                   ; 50
     db  032h, 0e4h
@@ -13910,29 +13961,29 @@ apm_worker:                                  ; 0xf941a LB 0x3a
     cmp AL, strict byte 00dh                  ; 3c 0d
     pop ax                                    ; 58
     mov AH, strict byte 053h                  ; b4 53
-    jnc short 09450h                          ; 73 25
-    jmp word [cs:bp-06c00h]                   ; 2e ff a6 00 94
-    jmp short 0944eh                          ; eb 1c
+    jnc short 09500h                          ; 73 25
+    jmp word [cs:bp-06b50h]                   ; 2e ff a6 b0 94
+    jmp short 094feh                          ; eb 1c
     sti                                       ; fb
     hlt                                       ; f4
-    jmp short 0944eh                          ; eb 18
-    jmp short 0944eh                          ; eb 16
-    jmp short 09450h                          ; eb 16
+    jmp short 094feh                          ; eb 18
+    jmp short 094feh                          ; eb 16
+    jmp short 09500h                          ; eb 16
     mov AH, strict byte 080h                  ; b4 80
-    jmp short 09452h                          ; eb 14
-    jmp short 09450h                          ; eb 10
+    jmp short 09502h                          ; eb 14
+    jmp short 09500h                          ; eb 10
     mov ax, 00102h                            ; b8 02 01
-    jmp short 0944eh                          ; eb 09
-    jmp short 0944eh                          ; eb 07
+    jmp short 094feh                          ; eb 09
+    jmp short 094feh                          ; eb 07
     mov BL, strict byte 000h                  ; b3 00
     mov cx, strict word 00000h                ; b9 00 00
-    jmp short 0944eh                          ; eb 00
+    jmp short 094feh                          ; eb 00
     clc                                       ; f8
     retn                                      ; c3
     mov AH, strict byte 009h                  ; b4 09
     stc                                       ; f9
     retn                                      ; c3
-apm_pm16_entry:                              ; 0xf9454 LB 0x11
+apm_pm16_entry:                              ; 0xf9504 LB 0x11
     mov AH, strict byte 002h                  ; b4 02
     push DS                                   ; 1e
     push bp                                   ; 55
@@ -13940,13 +13991,13 @@ apm_pm16_entry:                              ; 0xf9454 LB 0x11
     pop bp                                    ; 5d
     add bp, strict byte 00008h                ; 83 c5 08
     mov ds, bp                                ; 8e dd
-    call 0941ah                               ; e8 b8 ff
+    call 094cah                               ; e8 b8 ff
     pop bp                                    ; 5d
     pop DS                                    ; 1f
     retf                                      ; cb
 
-  ; Padding 0x459b bytes at 0xf9465
-  times 17819 db 0
+  ; Padding 0x44eb bytes at 0xf9515
+  times 17643 db 0
 
 section BIOS32 progbits vstart=0xda00 align=1 ; size=0x3cb class=CODE group=AUTO
 bios32_service:                              ; 0xfda00 LB 0x26
@@ -13993,7 +14044,7 @@ apm_pm32_entry:                              ; 0xfda40 LB 0x21
     pop bp                                    ; 5d
     add bp, strict byte 00008h                ; 83 c5 08
     push ebp                                  ; 66 55
-    mov bp, 09456h                            ; bd 56 94
+    mov bp, 09506h                            ; bd 06 95
     add byte [bx+si], al                      ; 00 00
     push ebp                                  ; 66 55
     mov AH, strict byte 003h                  ; b4 03
@@ -14485,7 +14536,7 @@ normal_post:                                 ; 0xfe0a7 LB 0x21c
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 01712h                               ; e8 27 36
+    call 01727h                               ; e8 3c 36
     call 0e8e0h                               ; e8 f2 07
     db  033h, 0dbh
     ; xor bx, bx                                ; 33 db
@@ -14569,7 +14620,7 @@ normal_post:                                 ; 0xfe0a7 LB 0x21c
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 04945h                               ; e8 72 67
+    call 0495ah                               ; e8 87 67
     pop DS                                    ; 1f
     mov AL, strict byte 014h                  ; b0 14
     out strict byte 070h, AL                  ; e6 70
@@ -14660,7 +14711,7 @@ nmi:                                         ; 0xfe2c3 LB 0x7
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 016eeh                               ; e8 25 34
+    call 01703h                               ; e8 3a 34
     iret                                      ; cf
 int75_handler:                               ; 0xfe2ca LB 0x8
     out strict byte 0f0h, AL                  ; e6 f0
@@ -14698,17 +14749,17 @@ hard_drive_post:                             ; 0xfe2d2 LB 0x12c
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 01b48h                               ; e8 27 38
-    call 01f42h                               ; e8 1e 3c
-    call 08ccfh                               ; e8 a8 a9
-    call 07da6h                               ; e8 7c 9a
+    call 01b5dh                               ; e8 3c 38
+    call 01f57h                               ; e8 33 3c
+    call 08d86h                               ; e8 5f aa
+    call 07e2dh                               ; e8 03 9b
     call 0ed2fh                               ; e8 02 0a
     call 0e2d2h                               ; e8 a2 ff
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 01732h                               ; e8 fc 33
-    call 03629h                               ; e8 f0 52
+    call 01747h                               ; e8 11 34
+    call 0363eh                               ; e8 05 53
     sti                                       ; fb
     int 019h                                  ; cd 19
     sti                                       ; fb
@@ -14806,7 +14857,7 @@ int19_handler:                               ; 0xfe6f2 LB 0x61
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 05cd7h                               ; e8 95 75
+    call 05cech                               ; e8 aa 75
     popaw                                     ; 61
     pop ES                                    ; 07
     pop DS                                    ; 1f
@@ -14817,7 +14868,7 @@ int19_handler:                               ; 0xfe6f2 LB 0x61
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 01683h                               ; e8 34 2f
+    call 01698h                               ; e8 49 2f
     popaw                                     ; 61
     pop ES                                    ; 07
     pop DS                                    ; 1f
@@ -14922,7 +14973,7 @@ ebda_post:                                   ; 0xfe7c0 LB 0xa4
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 05045h                               ; e8 03 68
+    call 0505ah                               ; e8 18 68
     popaw                                     ; 61
     pop DS                                    ; 1f
     pop ES                                    ; 07
@@ -14939,7 +14990,7 @@ ebda_post:                                   ; 0xfe7c0 LB 0xa4
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 05045h                               ; e8 e5 67
+    call 0505ah                               ; e8 fa 67
     popaw                                     ; 61
     pop DS                                    ; 1f
     pop ES                                    ; 07
@@ -15038,7 +15089,7 @@ pmode_setup:                                 ; 0xfe8e0 LB 0x37b
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 04c54h                               ; e8 85 62
+    call 04c69h                               ; e8 9a 62
     pop ES                                    ; 07
     popaw                                     ; 61
     pop DS                                    ; 1f
@@ -15054,7 +15105,7 @@ pmode_setup:                                 ; 0xfe8e0 LB 0x37b
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 0672fh                               ; e8 4a 7d
+    call 06744h                               ; e8 5f 7d
     pop DS                                    ; 1f
     pop ES                                    ; 07
     popaw                                     ; 61
@@ -15075,16 +15126,16 @@ int13_relocated:                             ; 0xfec5b LB 0x55
     pop DS                                    ; 1f
     cld                                       ; fc
     push 0ece9h                               ; 68 e9 ec
-    jmp near 0366dh                           ; e9 fc 49
+    jmp near 03682h                           ; e9 11 4a
     push ES                                   ; 06
     push ax                                   ; 50
     push bx                                   ; 53
     push cx                                   ; 51
     push dx                                   ; 52
-    call 03641h                               ; e8 c8 49
+    call 03656h                               ; e8 dd 49
     cmp AL, strict byte 000h                  ; 3c 00
     je short 0ecabh                           ; 74 2e
-    call 03657h                               ; e8 d7 49
+    call 0366ch                               ; e8 ec 49
     pop dx                                    ; 5a
     push dx                                   ; 52
     db  03ah, 0c2h
@@ -15102,7 +15153,7 @@ int13_relocated:                             ; 0xfec5b LB 0x55
     pop DS                                    ; 1f
     cld                                       ; fc
     push 0ece9h                               ; 68 e9 ec
-    jmp near 03c41h                           ; e9 aa 4f
+    jmp near 03c56h                           ; e9 bf 4f
     and dl, 0e0h                              ; 80 e2 e0
     db  03ah, 0c2h
     ; cmp al, dl                                ; 3a c2
@@ -15142,22 +15193,22 @@ int13_legacy:                                ; 0xfecb4 LB 0x14
     test dl, 080h                             ; f6 c2 80
     jne short 0ecc8h                          ; 75 06
     push 0ece9h                               ; 68 e9 ec
-    jmp near 02ec9h                           ; e9 01 42
+    jmp near 02edeh                           ; e9 16 42
 int13_notfloppy:                             ; 0xfecc8 LB 0x14
     cmp dl, 0e0h                              ; 80 fa e0
     jc short 0ecdch                           ; 72 0f
     shr ebx, 010h                             ; 66 c1 eb 10
     push bx                                   ; 53
-    call 04075h                               ; e8 a0 53
+    call 0408ah                               ; e8 b5 53
     pop bx                                    ; 5b
     sal ebx, 010h                             ; 66 c1 e3 10
     jmp short 0ece9h                          ; eb 0d
 int13_disk:                                  ; 0xfecdc LB 0xd
     cmp ah, 040h                              ; 80 fc 40
     jnbe short 0ece6h                         ; 77 05
-    call 053cah                               ; e8 e6 66
+    call 053dfh                               ; e8 fb 66
     jmp short 0ece9h                          ; eb 03
-    call 0580bh                               ; e8 22 6b
+    call 05820h                               ; e8 37 6b
 int13_out:                                   ; 0xfece9 LB 0x4
     pop DS                                    ; 1f
     pop ES                                    ; 07
@@ -15370,7 +15421,7 @@ int17_handler:                               ; 0xfefd4 LB 0xd
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 07089h                               ; e8 ac 80
+    call 0709eh                               ; e8 c1 80
     popaw                                     ; 61
     pop ES                                    ; 07
     pop DS                                    ; 1f
@@ -15395,7 +15446,7 @@ int10_handler:                               ; 0xff065 LB 0x47
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 01700h                               ; e8 56 26
+    call 01715h                               ; e8 6b 26
     hlt                                       ; f4
     iret                                      ; cf
 int19_relocated:                             ; 0xff0ac LB 0x90
@@ -15418,28 +15469,28 @@ int19_relocated:                             ; 0xff0ac LB 0x90
     ; mov bp, sp                                ; 8b ec
     mov ax, strict word 00001h                ; b8 01 00
     push ax                                   ; 50
-    call 046dch                               ; e8 0c 56
+    call 046f1h                               ; e8 21 56
     inc sp                                    ; 44
     inc sp                                    ; 44
     test ax, ax                               ; 85 c0
     jne short 0f0feh                          ; 75 28
     mov ax, strict word 00002h                ; b8 02 00
     push ax                                   ; 50
-    call 046dch                               ; e8 ff 55
+    call 046f1h                               ; e8 14 56
     inc sp                                    ; 44
     inc sp                                    ; 44
     test ax, ax                               ; 85 c0
     jne short 0f0feh                          ; 75 1b
     mov ax, strict word 00003h                ; b8 03 00
     push strict byte 00003h                   ; 6a 03
-    call 046dch                               ; e8 f1 55
+    call 046f1h                               ; e8 06 56
     inc sp                                    ; 44
     inc sp                                    ; 44
     test ax, ax                               ; 85 c0
     jne short 0f0feh                          ; 75 0d
     mov ax, strict word 00004h                ; b8 04 00
     push ax                                   ; 50
-    call 046dch                               ; e8 e4 55
+    call 046f1h                               ; e8 f9 55
     inc sp                                    ; 44
     inc sp                                    ; 44
     test ax, ax                               ; 85 c0
@@ -15730,20 +15781,20 @@ int15_handler:                               ; 0xff859 LB 0x2e
     je short 0f882h                           ; 74 0e
     cmp ah, 0c2h                              ; 80 fc c2
     je short 0f887h                           ; 74 0e
-    call 05ee4h                               ; e8 68 66
+    call 05ef9h                               ; e8 7d 66
     popaw                                     ; 61
     pop ES                                    ; 07
     pop DS                                    ; 1f
     popfw                                     ; 9d
     jmp short 0f895h                          ; eb 13
-    call 08e06h                               ; e8 81 95
+    call 08ebdh                               ; e8 38 96
     jmp short 0f87ch                          ; eb f5
 int15_handler_mouse:                         ; 0xff887 LB 0x5
-    call 06cfeh                               ; e8 74 74
+    call 06d13h                               ; e8 89 74
     jmp short 0f87ch                          ; eb f0
 int15_handler32:                             ; 0xff88c LB 0x9
     pushad                                    ; 66 60
-    call 063b1h                               ; e8 20 6b
+    call 063c6h                               ; e8 35 6b
     popad                                     ; 66 61
     jmp short 0f87dh                          ; eb e8
 iret_modify_cf:                              ; 0xff895 LB 0x14
@@ -15773,7 +15824,7 @@ int74_handler:                               ; 0xff8a9 LB 0x2e
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 06c34h                               ; e8 77 73
+    call 06c49h                               ; e8 8c 73
     pop cx                                    ; 59
     jcxz 0f8cch                               ; e3 0c
     push strict byte 00000h                   ; 6a 00
@@ -15865,8 +15916,8 @@ font8x8:                                     ; 0xffa6e LB 0x421
     db  000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h
     db  018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h
     db  076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h
-    db  080h, 0fch, 0b1h, 075h, 00fh, 006h, 01eh, 00eh, 01fh, 0fch, 066h, 060h, 0e8h, 099h, 091h, 066h
-    db  061h, 01fh, 007h, 0cfh, 006h, 01eh, 060h, 00eh, 01fh, 0fch, 0e8h, 040h, 06bh, 061h, 01fh, 007h
+    db  080h, 0fch, 0b1h, 075h, 00fh, 006h, 01eh, 00eh, 01fh, 0fch, 066h, 060h, 0e8h, 050h, 092h, 066h
+    db  061h, 01fh, 007h, 0cfh, 006h, 01eh, 060h, 00eh, 01fh, 0fch, 0e8h, 055h, 06bh, 061h, 01fh, 007h
     db  0cfh
 int70_handler:                               ; 0xffe8f LB 0x16
     push ES                                   ; 06
@@ -15875,7 +15926,7 @@ int70_handler:                               ; 0xffe8f LB 0x16
     push CS                                   ; 0e
     pop DS                                    ; 1f
     cld                                       ; fc
-    call 0690dh                               ; e8 75 6a
+    call 06922h                               ; e8 8a 6a
     popaw                                     ; 61
     pop DS                                    ; 1f
     pop ES                                    ; 07
@@ -15974,4 +16025,4 @@ dummy_iret:                                  ; 0xfff53 LB 0x9d
     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, 0bch
+    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 04fh
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum
index a73fe10..d8860ac 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum
@@ -1 +1 @@
-1e94033e74f4e723b1d8e9bd22396dcc *VBoxPcBios.rom
+57043783b40423d82ef1605eae6b1822 *VBoxPcBios.rom
diff --git a/src/VBox/Devices/PC/BIOS/ahci.c b/src/VBox/Devices/PC/BIOS/ahci.c
index ea4fa1d..7a571ba 100644
--- a/src/VBox/Devices/PC/BIOS/ahci.c
+++ b/src/VBox/Devices/PC/BIOS/ahci.c
@@ -633,6 +633,9 @@ void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
         uint8_t     cdcount;
         uint8_t     removable;
 
+        /* Clear all errors after the reset. */
+        VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SERR, 0xffffffff);
+
         devcount_ahci = bios_dsk->ahci_devcnt;
 
         DBG_AHCI("AHCI: Device detected on port %d\n", u8Port);
diff --git a/src/VBox/Devices/PC/BIOS/bios.c b/src/VBox/Devices/PC/BIOS/bios.c
index 4ba2034..66bf8dd 100644
--- a/src/VBox/Devices/PC/BIOS/bios.c
+++ b/src/VBox/Devices/PC/BIOS/bios.c
@@ -80,14 +80,22 @@ void write_dword(uint16_t seg, uint16_t offset, uint32_t data)
 
 uint8_t inb_cmos(uint8_t cmos_reg)
 {
-    outb(0x70, cmos_reg);
-    return inb(0x71);
+    uint8_t     cmos_port = 0x70;
+
+    if (cmos_reg >= 0x80)
+        cmos_port += 2;
+    outb(cmos_port, cmos_reg);
+    return inb(cmos_port + 1);
 }
 
 void outb_cmos(uint8_t cmos_reg, uint8_t val)
 {
-    outb(0x70, cmos_reg);
-    outb(0x71, val);
+    uint8_t     cmos_port = 0x70;
+
+    if (cmos_reg >= 0x80)
+        cmos_port += 2;
+    outb(cmos_port, cmos_reg);
+    outb(cmos_port + 1, val);
 }
 
 void BIOSCALL dummy_isr_function(pusha_regs_t regs, uint16_t es,
diff --git a/src/VBox/Devices/PC/BIOS/logo.c b/src/VBox/Devices/PC/BIOS/logo.c
index 73f9ccf..1fd30bc 100644
--- a/src/VBox/Devices/PC/BIOS/logo.c
+++ b/src/VBox/Devices/PC/BIOS/logo.c
@@ -234,7 +234,7 @@ void print_detected_harddisks(void)
         {
             if (sata_ctrl_printed == 0)
             {
-                printf("\n\nAHCI controller:\n");
+                printf("\n\n  AHCI controller:");
                 sata_ctrl_printed = 1;
             }
 
@@ -248,7 +248,7 @@ void print_detected_harddisks(void)
         {
             if (scsi_ctrl_printed == 0)
             {
-                printf("\n\nSCSI controller:\n");
+                printf("\n\n  SCSI controller:");
                 scsi_ctrl_printed = 1;
             }
 
@@ -261,7 +261,7 @@ void print_detected_harddisks(void)
 
             if ((device < 4) && (ide_ctrl_printed == 0))
             {
-                printf("IDE controller:\n");
+                printf("  IDE controller:");
                 ide_ctrl_printed = 1;
             }
             else if ((device >= 4) && (sata_ctrl_printed == 0))
diff --git a/src/VBox/Devices/PC/BIOS/scsi.c b/src/VBox/Devices/PC/BIOS/scsi.c
index 59ddbb3..b40255e 100644
--- a/src/VBox/Devices/PC/BIOS/scsi.c
+++ b/src/VBox/Devices/PC/BIOS/scsi.c
@@ -410,6 +410,7 @@ void scsi_enumerate_attached_devices(uint16_t io_base)
                 uint32_t    sectors, sector_size, cylinders;
                 uint16_t    heads, sectors_per_track;
                 uint8_t     hdcount;
+                uint8_t     cmos_base;
 
                 /* Issue a read capacity command now. */
                 _fmemset(aCDB, 0, sizeof(aCDB));
@@ -439,26 +440,56 @@ void scsi_enumerate_attached_devices(uint16_t io_base)
                     continue;
                 }
 
-                /* We need to calculate the geometry for the disk. From
-                 * the BusLogic driver in the Linux kernel.
-                 */
-                if (sectors >= (uint32_t)4 * 1024 * 1024)
+                devcount_scsi = bios_dsk->scsi_devcount;
+
+                /* Get logical CHS geometry. */
+                switch (devcount_scsi)
                 {
-                    heads = 255;
-                    sectors_per_track = 63;
+                    case 0:
+                        cmos_base = 0x90;
+                        break;
+                    case 1:
+                        cmos_base = 0x98;
+                        break;
+                    case 2:
+                        cmos_base = 0xA0;
+                        break;
+                    case 3:
+                        cmos_base = 0xA8;
+                        break;
+                    default:
+                        cmos_base = 0;
                 }
-                else if (sectors >= (uint32_t)2 * 1024 * 1024)
+
+                if (cmos_base && inb_cmos(cmos_base + 7))
                 {
-                    heads = 128;
-                    sectors_per_track = 32;
+                    /* If provided, grab the logical geometry from CMOS. */
+                    cylinders         = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
+                    heads             = inb_cmos(cmos_base + 2);
+                    sectors_per_track = inb_cmos(cmos_base + 7);
                 }
                 else
                 {
-                    heads = 64;
-                    sectors_per_track = 32;
+                    /* Calculate default logical geometry. NB: Very different
+                     * from default ATA/SATA logical geometry!
+                     */
+                    if (sectors >= (uint32_t)4 * 1024 * 1024)
+                    {
+                        heads = 255;
+                        sectors_per_track = 63;
+                    }
+                    else if (sectors >= (uint32_t)2 * 1024 * 1024)
+                    {
+                        heads = 128;
+                        sectors_per_track = 32;
+                    }
+                    else
+                    {
+                        heads = 64;
+                        sectors_per_track = 32;
+                    }
+                    cylinders = (uint32_t)(sectors / (heads * sectors_per_track));
                 }
-                cylinders = (uint32_t)(sectors / (heads * sectors_per_track));
-                devcount_scsi = bios_dsk->scsi_devcount;
 
                 /* Calculate index into the generic disk table. */
                 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
diff --git a/src/VBox/Devices/PC/DevPcBios.cpp b/src/VBox/Devices/PC/DevPcBios.cpp
index 9705bba..d34dce5 100644
--- a/src/VBox/Devices/PC/DevPcBios.cpp
+++ b/src/VBox/Devices/PC/DevPcBios.cpp
@@ -106,6 +106,15 @@
          0x82 - 0x83
     Second to third net boot devices:
          0x84 - 0x89
+    First SCSI HDD:
+         0x90 - 0x97
+    Second SCSI HDD:
+         0x98 - 0x9f
+    Third SCSI HDD:
+         0xa0 - 0xa7
+    Fourth SCSI HDD:
+         0xa8 - 0xaf
+
 @endverbatim
  *
  * @todo Mark which bits are compatible with which BIOSes and
@@ -151,8 +160,12 @@ typedef struct DEVPCBIOS
     char           *pszHDDevice;
     /** Sata harddisk device. */
     char           *pszSataDevice;
-    /** LUN of the four harddisks which are emulated as IDE. */
+    /** LUNs of the four BIOS-accessible SATA disks. */
     uint32_t        iSataHDLUN[4];
+    /** SCSI harddisk device. */
+    char           *pszScsiDevice;
+    /** LUNs of the four BIOS-accessible SCSI disks. */
+    uint32_t        iScsiHDLUN[4];
     /** Bios message buffer. */
     char            szMsg[256];
     /** Bios message buffer index. */
@@ -461,6 +474,40 @@ static int setLogicalDiskGeometry(PPDMIBASE pBase, PPDMIBLOCKBIOS pHardDisk, PPD
 
 
 /**
+ * Get logical CHS geometry for a hard disk, intended for SCSI/SAS drives
+ * with no physical geometry.
+ *
+ * @returns VBox status code.
+ * @param   pHardDisk     The hard disk.
+ * @param   pLCHSGeometry Where to store the geometry settings.
+ */
+static int getLogicalDiskGeometry(PPDMIBLOCKBIOS pHardDisk, PPDMMEDIAGEOMETRY pLCHSGeometry)
+{
+    PDMMEDIAGEOMETRY LCHSGeometry;
+    int rc = VINF_SUCCESS;
+
+    rc = pHardDisk->pfnGetLCHSGeometry(pHardDisk, &LCHSGeometry);
+    if (   rc == VERR_PDM_GEOMETRY_NOT_SET
+        || LCHSGeometry.cCylinders == 0
+        || LCHSGeometry.cHeads == 0
+        || LCHSGeometry.cHeads > 255
+        || LCHSGeometry.cSectors == 0
+        || LCHSGeometry.cSectors > 63)
+    {
+        /* Unlike the ATA case, if the image does not provide valid logical
+         * geometry, we leave things alone and let the BIOS decide what the
+         * logical geometry should be.
+         */
+        rc = VERR_PDM_GEOMETRY_NOT_SET;
+    }
+    else
+        *pLCHSGeometry = LCHSGeometry;
+
+    return rc;
+}
+
+
+/**
  * Get BIOS boot code from enmBootDevice in order
  *
  * @todo r=bird: This is a rather silly function since the conversion is 1:1.
@@ -627,7 +674,7 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns)
     pcbiosCmosWrite(pDevIns, 0x14, u32);                                        /* 14h - Equipment Byte */
 
     /*
-     * Harddisks.
+     * IDE harddisks.
      */
     for (i = 0; i < RT_ELEMENTS(apHDs); i++)
     {
@@ -682,11 +729,11 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns)
     pcbiosCmosWrite(pDevIns, 0x12, u32);
 
     /*
-     * Sata Harddisks.
+     * SATA harddisks.
      */
     if (pThis->pszSataDevice)
     {
-        /* Clear pointers to IDE controller. */
+        /* Clear pointers to the block devices. */
         for (i = 0; i < RT_ELEMENTS(apHDs); i++)
             apHDs[i] = NULL;
 
@@ -735,6 +782,62 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns)
         }
     }
 
+    /*
+     * SCSI harddisks. Not handled quite the same as SATA.
+     */
+    if (pThis->pszScsiDevice)
+    {
+        /* Clear pointers to the block devices. */
+        for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+            apHDs[i] = NULL;
+
+        for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+        {
+            PPDMIBASE pBase;
+            int rc = PDMR3QueryLun(pUVM, pThis->pszScsiDevice, 0, pThis->iScsiHDLUN[i], &pBase);
+            if (RT_SUCCESS(rc))
+                apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIBLOCKBIOS);
+            if (   apHDs[i]
+                && (   apHDs[i]->pfnGetType(apHDs[i]) != PDMBLOCKTYPE_HARD_DISK
+                    || !apHDs[i]->pfnIsVisible(apHDs[i])))
+                apHDs[i] = NULL;
+            if (apHDs[i])
+            {
+                PDMMEDIAGEOMETRY LCHSGeometry;
+                rc = getLogicalDiskGeometry(apHDs[i], &LCHSGeometry);
+
+                if (i < 4 && RT_SUCCESS(rc))
+                {
+                    /* Extended drive information (for SCSI disks).
+                     * Used by the BIOS for setting the logical geometry, but
+                     * only if the image provided valid data.
+                     */
+                    int offInfo;
+                    switch (i)
+                    {
+                        case 0:
+                            offInfo = 0x90;
+                            break;
+                        case 1:
+                            offInfo = 0x98;
+                            break;
+                        case 2:
+                            offInfo = 0xa0;
+                            break;
+                        case 3:
+                        default:
+                            offInfo = 0xa8;
+                            break;
+                    }
+                    pcbiosCmosInitHardDisk(pDevIns, 0x00, offInfo, &LCHSGeometry);
+                    LogRel(("DevPcBios: SCSI LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
+                }
+                else
+                    LogRel(("DevPcBios: SCSI LUN#%d LCHS not provided\n", i));
+            }
+        }
+    }
+
     /* Calculate and store AT-style CMOS checksum. */
     uint16_t    cksum = 0;
     for (i = 0x10; i < 0x2e; ++i)
@@ -848,6 +951,12 @@ static DECLCALLBACK(int) pcbiosDestruct(PPDMDEVINS pDevIns)
         pThis->pszSataDevice = NULL;
     }
 
+    if (pThis->pszScsiDevice)
+    {
+        MMR3HeapFree(pThis->pszScsiDevice);
+        pThis->pszScsiDevice = NULL;
+    }
+
     return VINF_SUCCESS;
 }
 
@@ -917,6 +1026,11 @@ static DECLCALLBACK(int)  pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF
                               "SataLUN2\0"
                               "SataLUN3\0"
                               "SataLUN4\0"
+                              "ScsiHardDiskDevice\0"
+                              "ScsiLUN1\0"
+                              "ScsiLUN2\0"
+                              "ScsiLUN3\0"
+                              "ScsiLUN4\0"
                               "FloppyDevice\0"
                               "DelayBoot\0"
                               "BiosRom\0"
@@ -1040,6 +1154,32 @@ static DECLCALLBACK(int)  pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF
                                            N_("Configuration error: Querying \"%s\" as a string failed"), s_apszSataDisks);
         }
     }
+
+    /* Repeat the exercise for SCSI drives. */
+    rc = CFGMR3QueryStringAlloc(pCfg, "ScsiHardDiskDevice", &pThis->pszScsiDevice);
+    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+        pThis->pszScsiDevice = NULL;
+    else if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Querying \"ScsiHardDiskDevice\" as a string failed"));
+
+    if (pThis->pszScsiDevice)
+    {
+        static const char * const s_apszScsiDisks[] =
+            { "ScsiLUN1", "ScsiLUN2", "ScsiLUN3", "ScsiLUN4" };
+        Assert(RT_ELEMENTS(s_apszScsiDisks) == RT_ELEMENTS(pThis->iScsiHDLUN));
+        for (unsigned i = 0; i < RT_ELEMENTS(pThis->iScsiHDLUN); i++)
+        {
+            rc = CFGMR3QueryU32(pCfg, s_apszScsiDisks[i], &pThis->iScsiHDLUN[i]);
+            if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+                pThis->iScsiHDLUN[i] = i;
+            else if (RT_FAILURE(rc))
+                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+                                           N_("Configuration error: Querying \"%s\" as a string failed"), s_apszScsiDisks);
+        }
+    }
+
+
     /*
      * Register I/O Ports and PC BIOS.
      */
diff --git a/src/VBox/Devices/Storage/DevAHCI.cpp b/src/VBox/Devices/Storage/DevAHCI.cpp
index e05f7f4..50b0ca8 100644
--- a/src/VBox/Devices/Storage/DevAHCI.cpp
+++ b/src/VBox/Devices/Storage/DevAHCI.cpp
@@ -445,8 +445,6 @@ typedef struct AHCIPort
     bool                            fAsyncInterface;
     /** Flag if we are in a device reset. */
     bool                            fResetDevice;
-    /** Flag whether the I/O thread idles. */
-    volatile bool                   fAsyncIOThreadIdle;
     /** Flag whether the port is in redo task mode. */
     volatile bool                   fRedo;
     /** Flag whether the worker thread is sleeping. */
@@ -479,13 +477,15 @@ typedef struct AHCIPort
     volatile uint32_t               u32QueuedTasksFinished;
     /** Bitmap for new queued tasks (Guest -> R3). */
     volatile uint32_t               u32TasksNew;
+    /** Bitmap of tasks which must be redone because of a non fatal error. */
+    volatile uint32_t               u32TasksRedo;
 
     /** Current command slot processed.
      * Accessed by the guest by reading the CMD register.
      * Holds the command slot of the command processed at the moment. */
     volatile uint32_t               u32CurrentCommandSlot;
 
-#if HC_ARCH_BITS == 32
+#if HC_ARCH_BITS == 64
     uint32_t                        u32Alignment2;
 #endif
 
@@ -674,6 +674,8 @@ typedef struct AHCI
 
     /** Bitmask of ports which asserted an interrupt. */
     volatile uint32_t               u32PortsInterrupted;
+    /** Number of I/O threads currently active - used for async controller reset handling. */
+    volatile uint32_t               cThreadsActive;
     /** Device is in a reset state. */
     bool                            fReset;
     /** Supports 64bit addressing */
@@ -698,6 +700,10 @@ typedef struct AHCI
     /** Flag whether we have written the first 4bytes in an 8byte MMIO write successfully. */
     volatile bool                   f8ByteMMIO4BytesWrittenSuccessfully;
 
+#if HC_ARCH_BITS == 64
+    uint32_t                        Alignment7;
+#endif
+
     /** The support driver session handle. */
     R3R0PTRTYPE(PSUPDRVSESSION)     pSupDrvSession;
 } AHCI;
@@ -1284,7 +1290,7 @@ static int PortTaskFileData_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, ui
  */
 static int PortCmd_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
 {
-    ahciLog(("%s: read regCMD=%#010x\n", __FUNCTION__, pAhciPort->regCMD));
+    ahciLog(("%s: read regCMD=%#010x\n", __FUNCTION__, pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot)));
     ahciLog(("%s: ICC=%d ASP=%d ALPE=%d DLAE=%d ATAPI=%d CPD=%d ISP=%d HPCP=%d PMA=%d CPS=%d CR=%d FR=%d ISS=%d CCS=%d FRE=%d CLO=%d POD=%d SUD=%d ST=%d\n",
              __FUNCTION__, (pAhciPort->regCMD & AHCI_PORT_CMD_ICC) >> 28, (pAhciPort->regCMD & AHCI_PORT_CMD_ASP) >> 27,
              (pAhciPort->regCMD & AHCI_PORT_CMD_ALPE) >> 26, (pAhciPort->regCMD & AHCI_PORT_CMD_DLAE) >> 25,
@@ -1319,6 +1325,9 @@ static int PortCmd_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u3
              (u32Value & AHCI_PORT_CMD_POD) >> 2, (u32Value & AHCI_PORT_CMD_SUD) >> 1,
              (u32Value & AHCI_PORT_CMD_ST)));
 
+    /* The PxCMD.CCS bits are R/O and maintained separately. */
+    u32Value &= ~AHCI_PORT_CMD_CCS;
+
     if (pAhciPort->fPoweredOn && pAhciPort->fSpunUp)
     {
         if (u32Value & AHCI_PORT_CMD_CLO)
@@ -1331,11 +1340,36 @@ static int PortCmd_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u3
 
         if (u32Value & AHCI_PORT_CMD_ST)
         {
-            ahciLog(("%s: Engine starts\n", __FUNCTION__));
-
-            /* Set engine state to running if there is a device attached. */
-            if (pAhciPort->pDrvBase)
+            /*
+             * Set engine state to running if there is a device attached and
+             * IS.PCS is clear.
+             */
+            if (   pAhciPort->pDrvBase
+                && !(pAhciPort->regIS & AHCI_PORT_IS_PCS))
+            {
+                ahciLog(("%s: Engine starts\n", __FUNCTION__));
                 u32Value |= AHCI_PORT_CMD_CR;
+
+                /* If there is something in CI, kick the I/O thread. */
+                if (   pAhciPort->regCI > 0
+                    && ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
+                {
+                    ASMAtomicOrU32(&pAhciPort->u32TasksNew, pAhciPort->regCI);
+#ifdef IN_RC
+                    PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue));
+                    AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
+
+                    pItem->iPort = pAhciPort->iLUN;
+                    PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
+#else
+                    LogFlowFunc(("Signal event semaphore\n"));
+                    int rc = SUPSemEventSignal(ahci->pSupDrvSession, pAhciPort->hEvtProcess);
+                    AssertRC(rc);
+#endif
+                }
+            }
+            else
+                u32Value &= ~AHCI_PORT_CMD_CR;
         }
         else
         {
@@ -1734,9 +1768,22 @@ static int HbaControl_w(PAHCI ahci, uint32_t iReg, uint32_t u32Value)
 #ifndef IN_RING3
     return VINF_IOM_R3_MMIO_WRITE;
 #else
-    ahci->regHbaCtrl = (u32Value & AHCI_HBA_CTRL_RW_MASK) | AHCI_HBA_CTRL_AE;
-    if (ahci->regHbaCtrl & AHCI_HBA_CTRL_HR)
+    /*
+     * Increase the active thread counter because we might set the host controller
+     * reset bit.
+     */
+    ASMAtomicIncU32(&ahci->cThreadsActive);
+    ASMAtomicWriteU32(&ahci->regHbaCtrl, (u32Value & AHCI_HBA_CTRL_RW_MASK) | AHCI_HBA_CTRL_AE);
+
+    /*
+     * Do the HBA reset if requested and there is no other active thread at the moment,
+     * the work is deferred to the last active thread otherwise.
+     */
+    uint32_t cThreadsActive = ASMAtomicDecU32(&ahci->cThreadsActive);
+    if (   (u32Value & AHCI_HBA_CTRL_HR)
+        && !cThreadsActive)
         ahciHBAReset(ahci);
+
     return VINF_SUCCESS;
 #endif
 }
@@ -1951,6 +1998,7 @@ static void ahciPortSwReset(PAHCIPort pAhciPort)
     pAhciPort->uATATransferMode = ATA_MODE_UDMA | 6;
 
     pAhciPort->u32TasksNew = 0;
+    pAhciPort->u32TasksRedo = 0;
     pAhciPort->u32TasksFinished = 0;
     pAhciPort->u32QueuedTasksFinished = 0;
     pAhciPort->u32CurrentCommandSlot = 0;
@@ -2391,6 +2439,8 @@ PDMBOTHCBDECL(int) ahciIdxDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Po
             rc = ahciRegisterRead(pAhci, pAhci->regIdx, pu32, cb);
             if (rc == VINF_IOM_R3_MMIO_READ)
                 rc = VINF_IOM_R3_IOPORT_READ;
+            else if (rc == VINF_IOM_MMIO_UNUSED_00)
+                rc = VERR_IOM_IOPORT_UNUSED;
         }
     }
     else
@@ -4112,41 +4162,41 @@ static int atapiReadDVDStructureSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_
                 switch (format)
                 {
                     case 0x0: /* Physical format information */
-                        {
-                            int layer = pAhciReq->aATAPICmd[6];
-                            uint64_t total_sectors;
+                    {
+                        int layer = pAhciReq->aATAPICmd[6];
+                        uint64_t total_sectors;
 
-                            if (layer != 0)
-                            {
-                                uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
-                                break;
-                            }
+                        if (layer != 0)
+                        {
+                            uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
+                            break;
+                        }
 
-                            total_sectors = pAhciPort->cTotalSectors;
-                            total_sectors >>= 2;
-                            if (total_sectors == 0)
-                            {
-                                uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
-                                break;
-                            }
+                        total_sectors = pAhciPort->cTotalSectors;
+                        total_sectors >>= 2;
+                        if (total_sectors == 0)
+                        {
+                            uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
+                            break;
+                        }
 
-                            buf[4] = 1;   /* DVD-ROM, part version 1 */
-                            buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
-                            buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
-                            buf[7] = 0;   /* default densities */
+                        buf[4] = 1;   /* DVD-ROM, part version 1 */
+                        buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
+                        buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
+                        buf[7] = 0;   /* default densities */
 
-                            /* FIXME: 0x30000 per spec? */
-                            ataH2BE_U32(buf + 8, 0); /* start sector */
-                            ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
-                            ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
+                        /* FIXME: 0x30000 per spec? */
+                        ataH2BE_U32(buf + 8, 0); /* start sector */
+                        ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
+                        ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
 
-                            /* Size of buffer, not including 2 byte size field */
-                            ataH2BE_U32(&buf[0], 2048 + 2);
+                        /* Size of buffer, not including 2 byte size field */
+                        ataH2BE_U32(&buf[0], 2048 + 2);
 
-                            /* 2k data + 4 byte header */
-                            uASC = (2048 + 4);
-                        }
+                        /* 2k data + 4 byte header */
+                        uASC = (2048 + 4);
                         break;
+                    }
                     case 0x01: /* DVD copyright information */
                         buf[4] = 0; /* no copyright data */
                         buf[5] = 0; /* no region restrictions */
@@ -4316,7 +4366,7 @@ static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t iAT
 
 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
 {
-    AHCITXDIR rc = AHCITXDIR_NONE;
+    AHCITXDIR enmTxDir = AHCITXDIR_NONE;
     const uint8_t *pbPacket;
     uint32_t cbMax;
 
@@ -4344,37 +4394,37 @@ static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciRe
             atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
             break;
         case SCSI_MODE_SENSE_10:
+        {
+            uint8_t uPageControl, uPageCode;
+            cbMax = ataBE2H_U16(pbPacket + 7);
+            uPageControl = pbPacket[2] >> 6;
+            uPageCode = pbPacket[2] & 0x3f;
+            switch (uPageControl)
             {
-                uint8_t uPageControl, uPageCode;
-                cbMax = ataBE2H_U16(pbPacket + 7);
-                uPageControl = pbPacket[2] >> 6;
-                uPageCode = pbPacket[2] & 0x3f;
-                switch (uPageControl)
-                {
-                    case SCSI_PAGECONTROL_CURRENT:
-                        switch (uPageCode)
-                        {
-                            case SCSI_MODEPAGE_ERROR_RECOVERY:
-                                atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
-                                break;
-                            case SCSI_MODEPAGE_CD_STATUS:
-                                atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
-                                break;
-                            default:
-                                goto error_cmd;
-                        }
-                        break;
-                    case SCSI_PAGECONTROL_CHANGEABLE:
-                        goto error_cmd;
-                    case SCSI_PAGECONTROL_DEFAULT:
-                        goto error_cmd;
-                    default:
-                    case SCSI_PAGECONTROL_SAVED:
-                        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
-                        break;
-                }
+                case SCSI_PAGECONTROL_CURRENT:
+                    switch (uPageCode)
+                    {
+                        case SCSI_MODEPAGE_ERROR_RECOVERY:
+                            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
+                            break;
+                        case SCSI_MODEPAGE_CD_STATUS:
+                            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
+                            break;
+                        default:
+                            goto error_cmd;
+                    }
+                    break;
+                case SCSI_PAGECONTROL_CHANGEABLE:
+                    goto error_cmd;
+                case SCSI_PAGECONTROL_DEFAULT:
+                    goto error_cmd;
+                default:
+                case SCSI_PAGECONTROL_SAVED:
+                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
+                    break;
             }
             break;
+        }
         case SCSI_REQUEST_SENSE:
             cbMax = pbPacket[4];
             atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_REQUEST_SENSE);
@@ -4393,224 +4443,224 @@ static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciRe
             break;
         case SCSI_READ_10:
         case SCSI_READ_12:
-            {
-                uint32_t cSectors, iATAPILBA;
+        {
+            uint32_t cSectors, iATAPILBA;
 
-                if (pAhciPort->cNotifiedMediaChange > 0)
-                {
-                    pAhciPort->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
-                    break;
-                }
-                if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
-                {
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
-                    break;
-                }
-                if (pbPacket[0] == SCSI_READ_10)
-                    cSectors = ataBE2H_U16(pbPacket + 7);
-                else
-                    cSectors = ataBE2H_U32(pbPacket + 6);
-                iATAPILBA = ataBE2H_U32(pbPacket + 2);
-                if (cSectors == 0)
-                {
-                    atapiCmdOK(pAhciPort, pAhciReq);
-                    break;
-                }
-                if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
+            if (pAhciPort->cNotifiedMediaChange > 0)
+            {
+                pAhciPort->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
+            {
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            if (pbPacket[0] == SCSI_READ_10)
+                cSectors = ataBE2H_U16(pbPacket + 7);
+            else
+                cSectors = ataBE2H_U32(pbPacket + 6);
+            iATAPILBA = ataBE2H_U32(pbPacket + 2);
+            if (cSectors == 0)
+            {
+                atapiCmdOK(pAhciPort, pAhciReq);
+                break;
+            }
+            if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
+            {
+                /* Rate limited logging, one log line per second. For
+                 * guests that insist on reading from places outside the
+                 * valid area this often generates too many release log
+                 * entries otherwise. */
+                static uint64_t s_uLastLogTS = 0;
+                if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
                 {
-                    /* Rate limited logging, one log line per second. For
-                     * guests that insist on reading from places outside the
-                     * valid area this often generates too many release log
-                     * entries otherwise. */
-                    static uint64_t s_uLastLogTS = 0;
-                    if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
-                    {
-                        LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
-                        s_uLastLogTS = RTTimeMilliTS();
-                    }
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
-                    break;
+                    LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
+                    s_uLastLogTS = RTTimeMilliTS();
                 }
-                atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
-                rc = AHCITXDIR_READ;
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                break;
             }
+            atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
+            enmTxDir = AHCITXDIR_READ;
             break;
+        }
         case SCSI_READ_CD:
-            {
-                uint32_t cSectors, iATAPILBA;
+        {
+            uint32_t cSectors, iATAPILBA;
 
-                if (pAhciPort->cNotifiedMediaChange > 0)
-                {
-                    pAhciPort->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
-                    break;
-                }
-                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
+            if (pAhciPort->cNotifiedMediaChange > 0)
+            {
+                pAhciPort->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
+            {
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
+            iATAPILBA = ataBE2H_U32(pbPacket + 2);
+            if (cSectors == 0)
+            {
+                atapiCmdOK(pAhciPort, pAhciReq);
+                break;
+            }
+            if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
+            {
+                /* Rate limited logging, one log line per second. For
+                 * guests that insist on reading from places outside the
+                 * valid area this often generates too many release log
+                 * entries otherwise. */
+                static uint64_t s_uLastLogTS = 0;
+                if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
                 {
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
-                    break;
+                    LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
+                    s_uLastLogTS = RTTimeMilliTS();
                 }
-                cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
-                iATAPILBA = ataBE2H_U32(pbPacket + 2);
-                if (cSectors == 0)
-                {
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                break;
+            }
+            switch (pbPacket[9] & 0xf8)
+            {
+                case 0x00:
+                    /* nothing */
                     atapiCmdOK(pAhciPort, pAhciReq);
                     break;
-                }
-                if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
-                {
-                    /* Rate limited logging, one log line per second. For
-                     * guests that insist on reading from places outside the
-                     * valid area this often generates too many release log
-                     * entries otherwise. */
-                    static uint64_t s_uLastLogTS = 0;
-                    if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
-                    {
-                        LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
-                        s_uLastLogTS = RTTimeMilliTS();
-                    }
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                case 0x10:
+                    /* normal read */
+                    atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
+                    enmTxDir = AHCITXDIR_READ;
+                    break;
+                case 0xf8:
+                    /* read all data */
+                    atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
+                    enmTxDir = AHCITXDIR_READ;
+                    break;
+                default:
+                    LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
+                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
                     break;
-                }
-                switch (pbPacket[9] & 0xf8)
-                {
-                    case 0x00:
-                        /* nothing */
-                        atapiCmdOK(pAhciPort, pAhciReq);
-                        break;
-                    case 0x10:
-                        /* normal read */
-                        atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
-                        rc = AHCITXDIR_READ;
-                        break;
-                    case 0xf8:
-                        /* read all data */
-                        atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
-                        rc = AHCITXDIR_READ;
-                        break;
-                    default:
-                        LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
-                        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
-                        break;
-                }
             }
             break;
+        }
         case SCSI_SEEK_10:
+        {
+            uint32_t iATAPILBA;
+            if (pAhciPort->cNotifiedMediaChange > 0)
             {
-                uint32_t iATAPILBA;
-                if (pAhciPort->cNotifiedMediaChange > 0)
-                {
-                    pAhciPort->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
-                    break;
-                }
-                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
-                {
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
-                    break;
-                }
-                iATAPILBA = ataBE2H_U32(pbPacket + 2);
-                if (iATAPILBA > pAhciPort->cTotalSectors)
+                pAhciPort->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
+            {
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            iATAPILBA = ataBE2H_U32(pbPacket + 2);
+            if (iATAPILBA > pAhciPort->cTotalSectors)
+            {
+                /* Rate limited logging, one log line per second. For
+                 * guests that insist on seeking to places outside the
+                 * valid area this often generates too many release log
+                 * entries otherwise. */
+                static uint64_t s_uLastLogTS = 0;
+                if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
                 {
-                    /* Rate limited logging, one log line per second. For
-                     * guests that insist on seeking to places outside the
-                     * valid area this often generates too many release log
-                     * entries otherwise. */
-                    static uint64_t s_uLastLogTS = 0;
-                    if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
-                    {
-                        LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA));
-                        s_uLastLogTS = RTTimeMilliTS();
-                    }
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
-                    break;
+                    LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA));
+                    s_uLastLogTS = RTTimeMilliTS();
                 }
-                atapiCmdOK(pAhciPort, pAhciReq);
-                pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                break;
             }
+            atapiCmdOK(pAhciPort, pAhciReq);
+            pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
             break;
+        }
         case SCSI_START_STOP_UNIT:
+        {
+            int rc = VINF_SUCCESS;
+            switch (pbPacket[4] & 3)
             {
-                int rc2 = VINF_SUCCESS;
-                switch (pbPacket[4] & 3)
+                case 0: /* 00 - Stop motor */
+                case 1: /* 01 - Start motor */
+                    break;
+                case 2: /* 10 - Eject media */
                 {
-                    case 0: /* 00 - Stop motor */
-                    case 1: /* 01 - Start motor */
-                        break;
-                    case 2: /* 10 - Eject media */
+                    /* This must be done from EMT. */
+                    PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
+                    PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
+
+                    rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
+                                                 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
+                                                 pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/);
+                    Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc == VERR_PDM_MEDIA_NOT_MOUNTED);
+                    if (RT_SUCCESS(rc) && pAhci->pMediaNotify)
                     {
-                        /* This must be done from EMT. */
-                        PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
-                        PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
-
-                        rc2 = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
-                                                      (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
-                                                      pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/);
-                        Assert(RT_SUCCESS(rc2) || (rc2 == VERR_PDM_MEDIA_LOCKED) || (rc2 = VERR_PDM_MEDIA_NOT_MOUNTED));
-                        if (RT_SUCCESS(rc) && pAhci->pMediaNotify)
-                        {
-                            rc2 = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
-                                                    (PFNRT)pAhci->pMediaNotify->pfnEjected, 2,
-                                                    pAhci->pMediaNotify, pAhciPort->iLUN);
-                            AssertRC(rc);
-                        }
-                        break;
+                        rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
+                                               (PFNRT)pAhci->pMediaNotify->pfnEjected, 2,
+                                               pAhci->pMediaNotify, pAhciPort->iLUN);
+                        AssertRC(rc);
                     }
-                    case 3: /* 11 - Load media */
-                        /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
-                        break;
+                    break;
                 }
-                if (RT_SUCCESS(rc2))
-                    atapiCmdOK(pAhciPort, pAhciReq);
-                else
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
+                case 3: /* 11 - Load media */
+                    /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
+                    break;
             }
+            if (RT_SUCCESS(rc))
+                atapiCmdOK(pAhciPort, pAhciReq);
+            else
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
             break;
+        }
         case SCSI_MECHANISM_STATUS:
-            {
-                cbMax = ataBE2H_U16(pbPacket + 8);
-                atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
-            }
+        {
+            cbMax = ataBE2H_U16(pbPacket + 8);
+            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
             break;
+        }
         case SCSI_READ_TOC_PMA_ATIP:
-            {
-                uint8_t format;
+        {
+            uint8_t format;
 
-                if (pAhciPort->cNotifiedMediaChange > 0)
-                {
-                    pAhciPort->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+            if (pAhciPort->cNotifiedMediaChange > 0)
+            {
+                pAhciPort->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
+            {
+                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            cbMax = ataBE2H_U16(pbPacket + 7);
+            /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
+             * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
+             * the other field is clear... */
+            format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
+            switch (format)
+            {
+                case 0:
+                    atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
                     break;
-                }
-                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
-                {
-                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                case 1:
+                    atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
+                    break;
+                case 2:
+                    atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
+                    break;
+                default:
+                  error_cmd:
+                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
                     break;
-                }
-                cbMax = ataBE2H_U16(pbPacket + 7);
-                /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
-                 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
-                 * the other field is clear... */
-                format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
-                switch (format)
-                {
-                    case 0:
-                        atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
-                        break;
-                    case 1:
-                        atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
-                        break;
-                    case 2:
-                        atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
-                        break;
-                    default:
-                    error_cmd:
-                        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
-                        break;
-                }
             }
             break;
+        }
         case SCSI_READ_CAPACITY:
             if (pAhciPort->cNotifiedMediaChange > 0)
             {
@@ -4673,7 +4723,7 @@ static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciRe
             break;
     }
 
-    return rc;
+    return enmTxDir;
 }
 
 /*
@@ -5896,7 +5946,7 @@ static bool ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcR
                 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
             }
             else
-                ASMAtomicOrU32(&pAhciPort->u32TasksNew, RT_BIT_32(pAhciReq->uTag));
+                ASMAtomicOrU32(&pAhciPort->u32TasksRedo, RT_BIT_32(pAhciReq->uTag));
         }
         else
         {
@@ -5996,6 +6046,9 @@ static bool ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcR
             RTMemFree(pAhciReq);
     }
 
+    if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
+        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
+
     return fCanceled;
 }
 
@@ -6015,11 +6068,9 @@ static DECLCALLBACK(int) ahciR3TransferCompleteNotify(PPDMIBLOCKASYNCPORT pInter
     ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",
              __FUNCTION__, pInterface, pvUser, pAhciReq->uTag));
 
-    int rc = ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true);
+    ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true);
 
-    if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
-        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
-    return rc;
+    return VINF_SUCCESS;
 }
 
 /**
@@ -6030,7 +6081,7 @@ static DECLCALLBACK(int) ahciR3TransferCompleteNotify(PPDMIBLOCKASYNCPORT pInter
  */
 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
 {
-    AHCITXDIR rc = AHCITXDIR_NONE;
+    AHCITXDIR enmTxDir = AHCITXDIR_NONE;
     bool fLBA48 = false;
     CmdHdr   *pCmdHdr = &pAhciReq->cmdHdr;
 
@@ -6080,10 +6131,11 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
                     pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
                     break;
                 case 0x82: /* write cache disable */
-                    rc = AHCITXDIR_FLUSH;
+                    enmTxDir = AHCITXDIR_FLUSH;
                     break;
                 case 0x03:
-                { /* set transfer mode */
+                {
+                    /* set transfer mode */
                     Log2(("%s: transfer mode %#04x\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
                     switch (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8)
                     {
@@ -6121,7 +6173,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
         }
         case ATA_FLUSH_CACHE_EXT:
         case ATA_FLUSH_CACHE:
-            rc = AHCITXDIR_FLUSH;
+            enmTxDir = AHCITXDIR_FLUSH;
             break;
         case ATA_PACKET:
             if (!pAhciPort->fATAPI)
@@ -6130,7 +6182,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
                 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
             }
             else
-                rc = atapiParseCmd(pAhciPort, pAhciReq);
+                enmTxDir = atapiParseCmd(pAhciPort, pAhciReq);
             break;
         case ATA_IDENTIFY_PACKET_DEVICE:
             if (!pAhciPort->fATAPI)
@@ -6185,7 +6237,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
         {
             pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
             pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
-            rc = AHCITXDIR_READ;
+            enmTxDir = AHCITXDIR_READ;
             break;
         }
         case ATA_WRITE_DMA_EXT:
@@ -6194,7 +6246,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
         {
             pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
             pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
-            rc = AHCITXDIR_WRITE;
+            enmTxDir = AHCITXDIR_WRITE;
             break;
         }
         case ATA_READ_FPDMA_QUEUED:
@@ -6202,7 +6254,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
             pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
             pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
             pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
-            rc = AHCITXDIR_READ;
+            enmTxDir = AHCITXDIR_READ;
             break;
         }
         case ATA_WRITE_FPDMA_QUEUED:
@@ -6210,7 +6262,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
             pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
             pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
             pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
-            rc = AHCITXDIR_WRITE;
+            enmTxDir = AHCITXDIR_WRITE;
             break;
         }
         case ATA_READ_LOG_EXT:
@@ -6291,7 +6343,7 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
                     pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
                 }
                 else
-                    rc = AHCITXDIR_TRIM;
+                    enmTxDir = AHCITXDIR_TRIM;
                 break;
             }
             /* else: fall through and report error to the guest. */
@@ -6310,20 +6362,22 @@ static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t
             pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     }
 
-    return rc;
+    return enmTxDir;
 }
 
 /**
  * Retrieve a command FIS from guest memory.
  *
- * @returns nothing
+ * @returns whether the H2D FIS was successfully read from the guest memory.
  * @param pAhciReq The state of the actual task.
  */
-static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
+static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
 {
     RTGCPHYS  GCPhysAddrCmdTbl;
 
-    AssertMsg(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb, ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__));
+    AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb,
+                    ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__),
+                    false);
 
     /*
      * First we are reading the command header pointed to by regCLB.
@@ -6342,13 +6396,18 @@ static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
 
     GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr);
 
-    AssertMsg((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
-              ("This is not a command FIS!!\n"));
+    AssertMsgReturn((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
+                    ("This is not a command FIS!!\n"),
+                    false);
 
     /* Read the command Fis. */
     LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdTbl=%RGp cbCmdFis=%u\n", __FUNCTION__, GCPhysAddrCmdTbl, AHCI_CMDFIS_TYPE_H2D_SIZE));
     PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
 
+    AssertMsgReturn(pAhciReq->cmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D,
+                    ("This is not a command FIS\n"),
+                    false);
+
     /* Set transfer direction. */
     pAhciReq->enmTxDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;
 
@@ -6394,6 +6453,8 @@ static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
         GCPhysPrdtl += sizeof(SGLEntry);
     }
 #endif
+
+    return true;
 }
 
 /**
@@ -6441,6 +6502,7 @@ static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     {
         unsigned idx = 0;
         uint32_t u32Tasks = 0;
+        uint32_t u32RegHbaCtrl = 0;
 
         ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, true);
         u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
@@ -6456,9 +6518,24 @@ static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
         }
 
         ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, false);
+        ASMAtomicIncU32(&pAhci->cThreadsActive);
+
+        /*
+         * Check whether the global host controller bit is set and go to sleep immediately again
+         * if it is set.
+         */
+        u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl);
+        if (   u32RegHbaCtrl & AHCI_HBA_CTRL_HR
+            && !ASMAtomicDecU32(&pAhci->cThreadsActive))
+        {
+            ahciHBAReset(pAhci);
+            continue;
+        }
+
         idx = ASMBitFirstSetU32(u32Tasks);
         while (idx)
         {
+            bool fReqCanceled = false;
             AHCITXDIR enmTxDir;
             PAHCIREQ pAhciReq;
 
@@ -6493,7 +6570,23 @@ static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
             pAhciReq->uTag = idx;
             ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
 
-            ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
+            bool fFisRead = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
+            if (RT_UNLIKELY(!fFisRead))
+            {
+                /*
+                 * Couldn't find anything in either the AHCI or SATA spec which
+                 * indicates what should be done if the FIS is not read successfully.
+                 * The closest thing is in the state machine, stating that the device
+                 * should go into idle state again (SATA spec 1.0 chapter 8.7.1).
+                 * Do the same here and ignore any corrupt FIS types, after all
+                 * the guest messed up everything and this behavior is undefined.
+                 */
+                ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
+                Assert(fXchg);
+                u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */
+                idx = ASMBitFirstSetU32(u32Tasks);
+                continue;
+            }
 
             /* Mark the task as processed by the HBA if this is a queued task so that it doesn't occur in the CI register anymore. */
             if (pAhciPort->regSACT & (1 << idx))
@@ -6510,21 +6603,15 @@ static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                     ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
                     pAhciPort->fResetDevice = true;
                     ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
-
-                    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
-                    AssertMsg(fXchg, ("Task is not active\n"));
-                    break;
                 }
                 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
-                {
                     ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
-
-                    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
-                    AssertMsg(fXchg, ("Task is not active\n"));
-                    break;
-                }
                 else /* We are not in a reset state update the control registers. */
                     AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__));
+
+                ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
+                AssertMsg(fXchg, ("Task is not active\n"));
+                break;
             }
             else
             {
@@ -6585,9 +6672,9 @@ static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                                                                               pAhciReq);
                             }
                             if (rc == VINF_VD_ASYNC_IO_FINISHED)
-                                rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
+                                fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
                             else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
-                                rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
+                                fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
                         }
                         else
                         {
@@ -6620,17 +6707,34 @@ static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
                                                                     pAhciReq->cbTransfer);
                                 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
                             }
-                            rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
+                            fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
                         }
                     }
                 }
                 else
-                    rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
+                    fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
             } /* Command */
 
+            /*
+             * Don't process other requests if the last one was canceled,
+             * the others are not valid anymore.
+             */
+            if (fReqCanceled)
+                break;
+
             u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */
             idx = ASMBitFirstSetU32(u32Tasks);
         } /* while tasks available */
+
+        /*
+         * Check whether a host controller reset is pending and execute the reset
+         * if this is the last active thread.
+         */
+        u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl);
+        uint32_t cThreadsActive = ASMAtomicDecU32(&pAhci->cThreadsActive);
+        if (   (u32RegHbaCtrl & AHCI_HBA_CTRL_HR)
+            && !cThreadsActive)
+            ahciHBAReset(pAhci);
     } /* While running */
 
     ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN));
@@ -6720,7 +6824,6 @@ static DECLCALLBACK(void) ahciR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, con
         pHlp->pfnPrintf(pHlp, "PortATAPI=%RTbool\n", pThisPort->fATAPI);
         pHlp->pfnPrintf(pHlp, "PortTasksFinished=%#x\n", pThisPort->u32TasksFinished);
         pHlp->pfnPrintf(pHlp, "PortQueuedTasksFinished=%#x\n", pThisPort->u32QueuedTasksFinished);
-        pHlp->pfnPrintf(pHlp, "PortAsyncIoThreadIdle=%RTbool\n", pThisPort->fAsyncIOThreadIdle);
         pHlp->pfnPrintf(pHlp, "\n");
     }
 }
@@ -6740,17 +6843,16 @@ static bool ahciR3AllAsyncIOIsFinished(PPDMDEVINS pDevIns)
 {
     PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
 
+    if (pThis->cThreadsActive)
+        return false;
+
     for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ahciPort); i++)
     {
         PAHCIPort pThisPort = &pThis->ahciPort[i];
         if (pThisPort->pDrvBase)
         {
-            bool fFinished;
-            if (pThisPort->fAsyncInterface)
-                fFinished = (pThisPort->cTasksActive == 0);
-            else
-                fFinished = ((pThisPort->cTasksActive == 0) && (pThisPort->fAsyncIOThreadIdle));
-            if (!fFinished)
+            if (   (pThisPort->cTasksActive != 0)
+                || (pThisPort->u32TasksNew != 0))
                return false;
         }
     }
@@ -7421,11 +7523,14 @@ static DECLCALLBACK(void) ahciR3Resume(PPDMDEVINS pDevIns)
     {
         PAHCIPort pAhciPort = &pAhci->ahciPort[i];
 
-        if (pAhciPort->u32TasksNew)
+        if (pAhciPort->u32TasksRedo)
         {
             PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue));
             AssertMsg(pItem, ("Allocating item for queue failed\n"));
 
+            pAhciPort->u32TasksNew |= pAhciPort->u32TasksRedo;
+            pAhciPort->u32TasksRedo = 0;
+
             Assert(pAhciPort->fRedo);
             pAhciPort->fRedo = false;
 
@@ -7597,13 +7702,14 @@ static DECLCALLBACK(void) ahciR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32
          * Inform the guest about the removed device.
          */
         pAhciPort->regSSTS = 0;
+        pAhciPort->regSIG = 0;
         /*
          * Clear CR bit too to prevent submission of new commands when CI is written
          * (AHCI Spec 1.2: 7.4 Interaction of the Command List and Port Change Status).
          */
         ASMAtomicAndU32(&pAhciPort->regCMD, ~(AHCI_PORT_CMD_CPS | AHCI_PORT_CMD_CR));
-        ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS);
-        ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_N);
+        ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
+        ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
         if (   (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
             || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
             || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
@@ -7967,6 +8073,8 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
     PCIDevSetWord(&pThis->dev, 0xaa, 0x0010);      /* Revision */
     PCIDevSetDWord(&pThis->dev, 0xac, 0x00000028); /* SATA Capability Register 1 */
 
+    pThis->cThreadsActive = 0;
+
     /* Initialize port members. */
     for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
     {
@@ -8124,7 +8232,6 @@ static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFG
         pAhciPort->IPort.pfnQueryDeviceLocation         = ahciR3PortQueryDeviceLocation;
         pAhciPort->IMountNotify.pfnMountNotify          = ahciR3MountNotify;
         pAhciPort->IMountNotify.pfnUnmountNotify        = ahciR3UnmountNotify;
-        pAhciPort->fAsyncIOThreadIdle                   = true;
 
         /*
          * Attach the block driver
diff --git a/src/VBox/Devices/Storage/DevATA.cpp b/src/VBox/Devices/Storage/DevATA.cpp
index 8187854..b87bdc2 100644
--- a/src/VBox/Devices/Storage/DevATA.cpp
+++ b/src/VBox/Devices/Storage/DevATA.cpp
@@ -1861,36 +1861,36 @@ static bool atapiReadSS(ATADevState *s)
             rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)s->iATAPILBA * s->cbATAPISector, s->CTX_SUFF(pbIOBuffer), s->cbATAPISector * cSectors);
             break;
         case 2352:
-            {
-                uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer);
+        {
+            uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer);
 
-                for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++)
-                {
-                    /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
-                    *pbBuf++ = 0x00;
-                    memset(pbBuf, 0xff, 10);
-                    pbBuf += 10;
-                    *pbBuf++ = 0x00;
-                    /* MSF */
-                    ataLBA2MSF(pbBuf, i);
-                    pbBuf += 3;
-                    *pbBuf++ = 0x01; /* mode 1 data */
-                    /* data */
-                    rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048);
-                    if (RT_FAILURE(rc))
-                        break;
-                    pbBuf += 2048;
-                    /**
-                     * @todo: maybe compute ECC and parity, layout is:
-                     * 2072 4   EDC
-                     * 2076 172 P parity symbols
-                     * 2248 104 Q parity symbols
-                     */
-                    memset(pbBuf, 0, 280);
-                    pbBuf += 280;
-                }
+            for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++)
+            {
+                /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
+                *pbBuf++ = 0x00;
+                memset(pbBuf, 0xff, 10);
+                pbBuf += 10;
+                *pbBuf++ = 0x00;
+                /* MSF */
+                ataLBA2MSF(pbBuf, i);
+                pbBuf += 3;
+                *pbBuf++ = 0x01; /* mode 1 data */
+                /* data */
+                rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048);
+                if (RT_FAILURE(rc))
+                    break;
+                pbBuf += 2048;
+                /**
+                 * @todo: maybe compute ECC and parity, layout is:
+                 * 2072 4   EDC
+                 * 2076 172 P parity symbols
+                 * 2248 104 Q parity symbols
+                 */
+                memset(pbBuf, 0, 280);
+                pbBuf += 280;
             }
             break;
+        }
         default:
             break;
     }
@@ -2270,41 +2270,41 @@ static bool atapiReadDVDStructureSS(ATADevState *s)
                 switch (format)
                 {
                     case 0x0: /* Physical format information */
+                    {
+                        int layer = s->aATAPICmd[6];
+                        uint64_t total_sectors;
+
+                        if (layer != 0)
+                        {
+                            uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
+                            break;
+                        }
+
+                        total_sectors = s->cTotalSectors;
+                        total_sectors >>= 2;
+                        if (total_sectors == 0)
                         {
-                            int layer = s->aATAPICmd[6];
-                            uint64_t total_sectors;
-
-                            if (layer != 0)
-                            {
-                                uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
-                                break;
-                            }
-
-                            total_sectors = s->cTotalSectors;
-                            total_sectors >>= 2;
-                            if (total_sectors == 0)
-                            {
-                                uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
-                                break;
-                            }
-
-                            buf[4] = 1;   /* DVD-ROM, part version 1 */
-                            buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
-                            buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
-                            buf[7] = 0;   /* default densities */
-
-                            /* FIXME: 0x30000 per spec? */
-                            ataH2BE_U32(buf + 8, 0); /* start sector */
-                            ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
-                            ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
-
-                            /* Size of buffer, not including 2 byte size field */
-                            ataH2BE_U32(&buf[0], 2048 + 2);
-
-                            /* 2k data + 4 byte header */
-                            uASC = (2048 + 4);
+                            uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
+                            break;
                         }
+
+                        buf[4] = 1;   /* DVD-ROM, part version 1 */
+                        buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
+                        buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
+                        buf[7] = 0;   /* default densities */
+
+                        /* FIXME: 0x30000 per spec? */
+                        ataH2BE_U32(buf + 8, 0); /* start sector */
+                        ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
+                        ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
+
+                        /* Size of buffer, not including 2 byte size field */
+                        ataH2BE_U32(&buf[0], 2048 + 2);
+
+                        /* 2k data + 4 byte header */
+                        uASC = (2048 + 4);
                         break;
+                    }
                     case 0x01: /* DVD copyright information */
                         buf[4] = 0; /* no copyright data */
                         buf[5] = 0; /* no region restrictions */
@@ -3069,37 +3069,37 @@ static void atapiParseCmdVirtualATAPI(ATADevState *s)
             ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
             break;
         case SCSI_MODE_SENSE_10:
+        {
+            uint8_t uPageControl, uPageCode;
+            cbMax = ataBE2H_U16(pbPacket + 7);
+            uPageControl = pbPacket[2] >> 6;
+            uPageCode = pbPacket[2] & 0x3f;
+            switch (uPageControl)
             {
-                uint8_t uPageControl, uPageCode;
-                cbMax = ataBE2H_U16(pbPacket + 7);
-                uPageControl = pbPacket[2] >> 6;
-                uPageCode = pbPacket[2] & 0x3f;
-                switch (uPageControl)
-                {
-                    case SCSI_PAGECONTROL_CURRENT:
-                        switch (uPageCode)
-                        {
-                            case SCSI_MODEPAGE_ERROR_RECOVERY:
-                                ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
-                                break;
-                            case SCSI_MODEPAGE_CD_STATUS:
-                                ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
-                                break;
-                            default:
-                                goto error_cmd;
-                        }
-                        break;
-                    case SCSI_PAGECONTROL_CHANGEABLE:
-                        goto error_cmd;
-                    case SCSI_PAGECONTROL_DEFAULT:
-                        goto error_cmd;
-                    default:
-                    case SCSI_PAGECONTROL_SAVED:
-                        atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
-                        break;
-                }
+                case SCSI_PAGECONTROL_CURRENT:
+                    switch (uPageCode)
+                    {
+                        case SCSI_MODEPAGE_ERROR_RECOVERY:
+                            ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
+                            break;
+                        case SCSI_MODEPAGE_CD_STATUS:
+                            ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
+                            break;
+                        default:
+                            goto error_cmd;
+                    }
+                    break;
+                case SCSI_PAGECONTROL_CHANGEABLE:
+                    goto error_cmd;
+                case SCSI_PAGECONTROL_DEFAULT:
+                    goto error_cmd;
+                default:
+                case SCSI_PAGECONTROL_SAVED:
+                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
+                    break;
             }
             break;
+        }
         case SCSI_REQUEST_SENSE:
             cbMax = pbPacket[4];
             ataStartTransfer(s, RT_MIN(cbMax, 18), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
@@ -3118,228 +3118,228 @@ static void atapiParseCmdVirtualATAPI(ATADevState *s)
             break;
         case SCSI_READ_10:
         case SCSI_READ_12:
-            {
-                uint32_t cSectors, iATAPILBA;
+        {
+            uint32_t cSectors, iATAPILBA;
 
-                if (s->cNotifiedMediaChange > 0)
-                {
-                    s->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
-                    break;
-                }
-                else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
-                {
-                    atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
-                    break;
-                }
-                if (pbPacket[0] == SCSI_READ_10)
-                    cSectors = ataBE2H_U16(pbPacket + 7);
-                else
-                    cSectors = ataBE2H_U32(pbPacket + 6);
-                iATAPILBA = ataBE2H_U32(pbPacket + 2);
-                if (cSectors == 0)
-                {
-                    atapiCmdOK(s);
-                    break;
-                }
-                if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
+            if (s->cNotifiedMediaChange > 0)
+            {
+                s->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
+            {
+                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            if (pbPacket[0] == SCSI_READ_10)
+                cSectors = ataBE2H_U16(pbPacket + 7);
+            else
+                cSectors = ataBE2H_U32(pbPacket + 6);
+            iATAPILBA = ataBE2H_U32(pbPacket + 2);
+            if (cSectors == 0)
+            {
+                atapiCmdOK(s);
+                break;
+            }
+            if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
+            {
+                /* Rate limited logging, one log line per second. For
+                 * guests that insist on reading from places outside the
+                 * valid area this often generates too many release log
+                 * entries otherwise. */
+                static uint64_t uLastLogTS = 0;
+                if (RTTimeMilliTS() >= uLastLogTS + 1000)
                 {
-                    /* Rate limited logging, one log line per second. For
-                     * guests that insist on reading from places outside the
-                     * valid area this often generates too many release log
-                     * entries otherwise. */
-                    static uint64_t uLastLogTS = 0;
-                    if (RTTimeMilliTS() >= uLastLogTS + 1000)
-                    {
-                        LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
-                        uLastLogTS = RTTimeMilliTS();
-                    }
-                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
-                    break;
+                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
+                    uLastLogTS = RTTimeMilliTS();
                 }
-                atapiReadSectors(s, iATAPILBA, cSectors, 2048);
+                atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                break;
             }
+            atapiReadSectors(s, iATAPILBA, cSectors, 2048);
             break;
+        }
         case SCSI_READ_CD:
-            {
-                uint32_t cSectors, iATAPILBA;
+        {
+            uint32_t cSectors, iATAPILBA;
 
-                if (s->cNotifiedMediaChange > 0)
-                {
-                    s->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
-                    break;
-                }
-                else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
+            if (s->cNotifiedMediaChange > 0)
+            {
+                s->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
+            {
+                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
+            iATAPILBA = ataBE2H_U32(pbPacket + 2);
+            if (cSectors == 0)
+            {
+                atapiCmdOK(s);
+                break;
+            }
+            if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
+            {
+                /* Rate limited logging, one log line per second. For
+                 * guests that insist on reading from places outside the
+                 * valid area this often generates too many release log
+                 * entries otherwise. */
+                static uint64_t uLastLogTS = 0;
+                if (RTTimeMilliTS() >= uLastLogTS + 1000)
                 {
-                    atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
-                    break;
+                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
+                    uLastLogTS = RTTimeMilliTS();
                 }
-                cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
-                iATAPILBA = ataBE2H_U32(pbPacket + 2);
-                if (cSectors == 0)
-                {
+                atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                break;
+            }
+            switch (pbPacket[9] & 0xf8)
+            {
+                case 0x00:
+                    /* nothing */
                     atapiCmdOK(s);
                     break;
-                }
-                if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
-                {
-                    /* Rate limited logging, one log line per second. For
-                     * guests that insist on reading from places outside the
-                     * valid area this often generates too many release log
-                     * entries otherwise. */
-                    static uint64_t uLastLogTS = 0;
-                    if (RTTimeMilliTS() >= uLastLogTS + 1000)
-                    {
-                        LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
-                        uLastLogTS = RTTimeMilliTS();
-                    }
-                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                case 0x10:
+                    /* normal read */
+                    atapiReadSectors(s, iATAPILBA, cSectors, 2048);
+                    break;
+                case 0xf8:
+                    /* read all data */
+                    atapiReadSectors(s, iATAPILBA, cSectors, 2352);
+                    break;
+                default:
+                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8));
+                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
                     break;
-                }
-                switch (pbPacket[9] & 0xf8)
-                {
-                    case 0x00:
-                        /* nothing */
-                        atapiCmdOK(s);
-                        break;
-                    case 0x10:
-                        /* normal read */
-                        atapiReadSectors(s, iATAPILBA, cSectors, 2048);
-                        break;
-                    case 0xf8:
-                        /* read all data */
-                        atapiReadSectors(s, iATAPILBA, cSectors, 2352);
-                        break;
-                    default:
-                        LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8));
-                        atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
-                        break;
-                }
             }
             break;
+        }
         case SCSI_SEEK_10:
+        {
+            uint32_t iATAPILBA;
+            if (s->cNotifiedMediaChange > 0)
             {
-                uint32_t iATAPILBA;
-                if (s->cNotifiedMediaChange > 0)
-                {
-                    s->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
-                    break;
-                }
-                else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
-                {
-                    atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
-                    break;
-                }
-                iATAPILBA = ataBE2H_U32(pbPacket + 2);
-                if (iATAPILBA > s->cTotalSectors)
+                s->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
+            {
+                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            iATAPILBA = ataBE2H_U32(pbPacket + 2);
+            if (iATAPILBA > s->cTotalSectors)
+            {
+                /* Rate limited logging, one log line per second. For
+                 * guests that insist on seeking to places outside the
+                 * valid area this often generates too many release log
+                 * entries otherwise. */
+                static uint64_t uLastLogTS = 0;
+                if (RTTimeMilliTS() >= uLastLogTS + 1000)
                 {
-                    /* Rate limited logging, one log line per second. For
-                     * guests that insist on seeking to places outside the
-                     * valid area this often generates too many release log
-                     * entries otherwise. */
-                    static uint64_t uLastLogTS = 0;
-                    if (RTTimeMilliTS() >= uLastLogTS + 1000)
-                    {
-                        LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
-                        uLastLogTS = RTTimeMilliTS();
-                    }
-                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
-                    break;
+                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
+                    uLastLogTS = RTTimeMilliTS();
                 }
-                atapiCmdOK(s);
-                ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */
+                atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
+                break;
             }
+            atapiCmdOK(s);
+            ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */
             break;
+        }
         case SCSI_START_STOP_UNIT:
+        {
+            int rc = VINF_SUCCESS;
+            switch (pbPacket[4] & 3)
             {
-                int rc = VINF_SUCCESS;
-                switch (pbPacket[4] & 3)
+                case 0: /* 00 - Stop motor */
+                case 1: /* 01 - Start motor */
+                    break;
+                case 2: /* 10 - Eject media */
                 {
-                    case 0: /* 00 - Stop motor */
-                    case 1: /* 01 - Start motor */
-                        break;
-                    case 2: /* 10 - Eject media */
+                    /* This must be done from EMT. */
+                    PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
+                    PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
+                    PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
+
+                    PDMCritSectLeave(&pCtl->lock);
+                    rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
+                                                 (PFNRT)s->pDrvMount->pfnUnmount, 3,
+                                                 s->pDrvMount, false /*=fForce*/, true /*=fEject*/);
+                    Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc == VERR_PDM_MEDIA_NOT_MOUNTED);
+                    if (RT_SUCCESS(rc) && pThis->pMediaNotify)
                     {
-                        /* This must be done from EMT. */
-                        PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
-                        PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
-                        PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
-
-                        PDMCritSectLeave(&pCtl->lock);
-                        rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
-                                                     (PFNRT)s->pDrvMount->pfnUnmount, 3,
-                                                     s->pDrvMount, false /*=fForce*/, true /*=fEject*/);
-                        Assert(RT_SUCCESS(rc) || (rc == VERR_PDM_MEDIA_LOCKED) || (rc = VERR_PDM_MEDIA_NOT_MOUNTED));
-                        if (RT_SUCCESS(rc) && pThis->pMediaNotify)
-                        {
-                            rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
-                                                   (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
-                                                   pThis->pMediaNotify, s->iLUN);
-                            AssertRC(rc);
-                        }
-                        {
-                            STAM_PROFILE_START(&pCtl->StatLockWait, a);
-                            PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
-                            STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
-                        }
-                        break;
+                        rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
+                                               (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
+                                               pThis->pMediaNotify, s->iLUN);
+                        AssertRC(rc);
                     }
-                    case 3: /* 11 - Load media */
-                        /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
-                        break;
+                    {
+                        STAM_PROFILE_START(&pCtl->StatLockWait, a);
+                        PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
+                        STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
+                    }
+                    break;
                 }
-                if (RT_SUCCESS(rc))
-                    atapiCmdOK(s);
-                else
-                    atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
+                case 3: /* 11 - Load media */
+                    /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
+                    break;
             }
+            if (RT_SUCCESS(rc))
+                atapiCmdOK(s);
+            else
+                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
             break;
+        }
         case SCSI_MECHANISM_STATUS:
-            {
-                cbMax = ataBE2H_U16(pbPacket + 8);
-                ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
-            }
+        {
+            cbMax = ataBE2H_U16(pbPacket + 8);
+            ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
             break;
+        }
         case SCSI_READ_TOC_PMA_ATIP:
-            {
-                uint8_t format;
+        {
+            uint8_t format;
 
-                if (s->cNotifiedMediaChange > 0)
-                {
-                    s->cNotifiedMediaChange-- ;
-                    atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+            if (s->cNotifiedMediaChange > 0)
+            {
+                s->cNotifiedMediaChange-- ;
+                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
+                break;
+            }
+            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
+            {
+                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            cbMax = ataBE2H_U16(pbPacket + 7);
+            /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
+             * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
+             * the other field is clear... */
+            format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
+            switch (format)
+            {
+                case 0:
+                    ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
                     break;
-                }
-                else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
-                {
-                    atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
+                case 1:
+                    ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
+                    break;
+                case 2:
+                    ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
+                    break;
+                default:
+                  error_cmd:
+                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
                     break;
-                }
-                cbMax = ataBE2H_U16(pbPacket + 7);
-                /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
-                 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
-                 * the other field is clear... */
-                format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
-                switch (format)
-                {
-                    case 0:
-                        ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
-                        break;
-                    case 1:
-                        ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
-                        break;
-                    case 2:
-                        ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
-                        break;
-                    default:
-                    error_cmd:
-                        atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
-                        break;
-                }
             }
             break;
+        }
         case SCSI_READ_CAPACITY:
             if (s->cNotifiedMediaChange > 0)
             {
diff --git a/src/VBox/Devices/Storage/DrvSCSI.cpp b/src/VBox/Devices/Storage/DrvSCSI.cpp
index e7faa97..1b0ce17 100644
--- a/src/VBox/Devices/Storage/DrvSCSI.cpp
+++ b/src/VBox/Devices/Storage/DrvSCSI.cpp
@@ -657,6 +657,7 @@ static DECLCALLBACK(void *)  drvscsiQueryInterface(PPDMIBASE pInterface, const c
     PDRVSCSI    pThis   = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
 
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNT, pThis->pDrvMount);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKBIOS, pThis->pDrvBlockBios);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSICONNECTOR, &pThis->ISCSIConnector);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKPORT, &pThis->IPort);
diff --git a/src/VBox/Devices/USB/VUSBReadAhead.cpp b/src/VBox/Devices/USB/VUSBReadAhead.cpp
index cc91d30..8c16dc4 100644
--- a/src/VBox/Devices/USB/VUSBReadAhead.cpp
+++ b/src/VBox/Devices/USB/VUSBReadAhead.cpp
@@ -173,7 +173,8 @@ static DECLCALLBACK(int) vusbDevReadAheadThread(RTTHREAD Thread, void *pvUser)
     /* The previous read-ahead thread could be still running (vusbReadAheadStop sets only
      * fTerminate to true and returns immediately). Therefore we have to wait until the
      * previous thread is done and all submitted URBs are completed. */
-    while (pPipe->cSubmitted > 0)
+    while (   pPipe->cSubmitted > 0
+           && pPipe->cBuffered > 0)
     {
         Log2(("vusbDevReadAheadThread: still %u packets submitted, waiting before starting...\n", pPipe->cSubmitted));
         RTThreadSleep(1);
@@ -245,6 +246,22 @@ static DECLCALLBACK(int) vusbDevReadAheadThread(RTTHREAD Thread, void *pvUser)
         RTThreadSleep(1);
     }
 
+    /*
+     * Free all still buffered URBs because another endpoint with a different packet size
+     * and complete different data formats might be served later.
+     */
+    int cFree = 0;
+    while (pPipe->pBuffUrbHead)
+    {
+        PVUSBURB pBufferedUrb = pPipe->pBuffUrbHead;
+
+        pPipe->pBuffUrbHead = pBufferedUrb->Hci.pNext;
+        pBufferedUrb->VUsb.pfnFree(pBufferedUrb);
+        cFree++;
+    }
+
+    pPipe->pBuffUrbTail = NULL;
+    pPipe->cBuffered = 0;
     RTMemTmpFree(pArgs);
 
     return rc;
diff --git a/src/VBox/Devices/testcase/Makefile.kmk b/src/VBox/Devices/testcase/Makefile.kmk
index 774d44d..606c233 100644
--- a/src/VBox/Devices/testcase/Makefile.kmk
+++ b/src/VBox/Devices/testcase/Makefile.kmk
@@ -41,7 +41,8 @@ VBOX_DEVICES_TESTS_FEATURES = \
 	$(if $(VBOX_WITH_VDMA),VBOX_WITH_VDMA,) \
 	$(if $(VBOX_WITH_WDDM),VBOX_WITH_WDDM,) \
 	$(if $(VBOX_WITH_VIDEOHWACCEL),VBOX_WITH_VIDEOHWACCEL,) \
-	$(if $(VBOX_WITH_PCI_PASSTHROUGH_IMPL),VBOX_WITH_PCI_PASSTHROUGH_IMPL,)
+	$(if $(VBOX_WITH_PCI_PASSTHROUGH_IMPL),VBOX_WITH_PCI_PASSTHROUGH_IMPL,) \
+	$(if $(VBOX_WITH_VMSVGA),VBOX_WITH_VMSVGA,)
 
 
 #
diff --git a/src/VBox/Devices/testcase/tstDeviceStructSize.cpp b/src/VBox/Devices/testcase/tstDeviceStructSize.cpp
index 8b9027d..ad40741 100644
--- a/src/VBox/Devices/testcase/tstDeviceStructSize.cpp
+++ b/src/VBox/Devices/testcase/tstDeviceStructSize.cpp
@@ -323,6 +323,10 @@ int main()
 #endif
     CHECK_MEMBER_ALIGNMENT(PITSTATE, StatPITIrq, 8);
     CHECK_MEMBER_ALIGNMENT(SerialState, CritSect, 8);
+#ifdef VBOX_WITH_VMSVGA
+    CHECK_MEMBER_ALIGNMENT(VGASTATE, svga.u64HostWindowId, 8);
+#endif
+    CHECK_MEMBER_ALIGNMENT(VGASTATE, GCPhysVRAM, 8);
     CHECK_MEMBER_ALIGNMENT(VGASTATE, Dev, 8);
     CHECK_MEMBER_ALIGNMENT(VGASTATE, CritSect, 8);
     CHECK_MEMBER_ALIGNMENT(VGASTATE, StatRZMemoryRead, 8);
diff --git a/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp b/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
index a185563..2ea62c3 100644
--- a/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
+++ b/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
@@ -303,6 +303,22 @@ int main()
     GEN_CHECK_OFF(VGASTATE, pDrv);
     GEN_CHECK_OFF(VGASTATE, RefreshTimer);
     GEN_CHECK_OFF(VGASTATE, pDevInsR0);
+#ifdef VBOX_WITH_VMSVGA
+    GEN_CHECK_OFF(VGASTATE, svga.u64HostWindowId);
+    GEN_CHECK_OFF(VGASTATE, svga.pFIFOR3);
+    GEN_CHECK_OFF(VGASTATE, svga.pFIFOR0);
+    GEN_CHECK_OFF(VGASTATE, svga.pSVGAState);
+    GEN_CHECK_OFF(VGASTATE, svga.p3dState);
+    GEN_CHECK_OFF(VGASTATE, svga.pFrameBufferBackup);
+    GEN_CHECK_OFF(VGASTATE, svga.GCPhysFIFO);
+    GEN_CHECK_OFF(VGASTATE, svga.cbFIFO);
+    GEN_CHECK_OFF(VGASTATE, svga.BasePort);
+    GEN_CHECK_OFF(VGASTATE, svga.pFIFOIOThread);
+    GEN_CHECK_OFF(VGASTATE, svga.iWidth);
+    GEN_CHECK_OFF(VGASTATE, svga.u32ActionFlags);
+    GEN_CHECK_OFF(VGASTATE, svga.f3DEnabled);
+    GEN_CHECK_OFF(VGASTATE, svga.fVRAMTracking);
+#endif
     GEN_CHECK_OFF(VGASTATE, cMonitors);
     GEN_CHECK_OFF(VGASTATE, cMilliesRefreshInterval);
     GEN_CHECK_OFF(VGASTATE, au32DirtyBitmap);
@@ -1181,7 +1197,6 @@ int main()
     GEN_CHECK_OFF(AHCIPort, fPortReset);
     GEN_CHECK_OFF(AHCIPort, fAsyncInterface);
     GEN_CHECK_OFF(AHCIPort, fResetDevice);
-    GEN_CHECK_OFF(AHCIPort, fAsyncIOThreadIdle);
     GEN_CHECK_OFF(AHCIPort, fRedo);
     GEN_CHECK_OFF(AHCIPort, fWrkThreadSleeping);
     GEN_CHECK_OFF(AHCIPort, cTotalSectors);
@@ -1197,6 +1212,7 @@ int main()
     GEN_CHECK_OFF(AHCIPort, u32TasksFinished);
     GEN_CHECK_OFF(AHCIPort, u32QueuedTasksFinished);
     GEN_CHECK_OFF(AHCIPort, u32TasksNew);
+    GEN_CHECK_OFF(AHCIPort, u32TasksRedo);
     GEN_CHECK_OFF(AHCIPort, u32CurrentCommandSlot);
     GEN_CHECK_OFF(AHCIPort, pDrvBase);
     GEN_CHECK_OFF(AHCIPort, pDrvBlock);
@@ -1223,7 +1239,6 @@ int main()
     GEN_CHECK_OFF(AHCIPort, StatProfileProcessTime);
     GEN_CHECK_OFF(AHCIPort, StatProfileReadWrite);
 #endif
-    GEN_CHECK_OFF(AHCIPort, fAsyncIOThreadIdle);
     GEN_CHECK_OFF(AHCIPort, szSerialNumber);
     GEN_CHECK_OFF(AHCIPort, szSerialNumber[AHCI_SERIAL_NUMBER_LENGTH]); /* One additional byte for the termination.*/
     GEN_CHECK_OFF(AHCIPort, szFirmwareRevision);
@@ -1269,6 +1284,7 @@ int main()
     GEN_CHECK_OFF(AHCI, ahciPort[AHCI_MAX_NR_PORTS_IMPL-1]);
     GEN_CHECK_OFF(AHCI, lock);
     GEN_CHECK_OFF(AHCI, u32PortsInterrupted);
+    GEN_CHECK_OFF(AHCI, cThreadsActive);
     GEN_CHECK_OFF(AHCI, fReset);
     GEN_CHECK_OFF(AHCI, f64BitAddr);
     GEN_CHECK_OFF(AHCI, fGCEnabled);
diff --git a/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp b/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
index 40b31b8..bca3b24 100644
--- a/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
+++ b/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
@@ -533,7 +533,12 @@ static void parse_environ(unsigned long *pulFrameWidth, unsigned long *pulFrameH
                           unsigned long *pulBitRate, const char **ppszFileName)
 {
     const char *pszEnvTemp;
-
+/** @todo r=bird: This isn't up to scratch. The life time of an RTEnvGet
+ *        return value is only up to the next RTEnv*, *getenv, *putenv,
+ *        setenv call in _any_ process in the system and the it has known and
+ *        documented code page issues.
+ *
+ *        Use RTEnvGetEx instead! */
     if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREWIDTH")) != 0)
     {
         errno = 0;
@@ -649,18 +654,18 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
     unsigned fPATM  = ~0U;
     unsigned fCSAM  = ~0U;
 #ifdef VBOX_WITH_VIDEO_REC
-    unsigned fVIDEOREC = 0;
+    bool fVideoRec = 0;
     unsigned long ulFrameWidth = 800;
     unsigned long ulFrameHeight = 600;
-    unsigned long ulBitRate = 300000;
-    char pszMPEGFile[RTPATH_MAX];
+    unsigned long ulBitRate = 300000; /** @todo r=bird: The COM type ULONG isn't unsigned long, it's 32-bit unsigned int. */
+    char szMpegFile[RTPATH_MAX];
     const char *pszFileNameParam = "VBox-%d.vob";
 #endif /* VBOX_WITH_VIDEO_REC */
 
-    LogFlow (("VBoxHeadless STARTED.\n"));
-    RTPrintf (VBOX_PRODUCT " Headless Interface " VBOX_VERSION_STRING "\n"
-              "(C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
-              "All rights reserved.\n\n");
+    LogFlow(("VBoxHeadless STARTED.\n"));
+    RTPrintf(VBOX_PRODUCT " Headless Interface " VBOX_VERSION_STRING "\n"
+             "(C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
+             "All rights reserved.\n\n");
 
 #ifdef VBOX_WITH_VIDEO_REC
     /* Parse the environment */
@@ -791,7 +796,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
                 break;
 #ifdef VBOX_WITH_VIDEO_REC
             case 'c':
-                fVIDEOREC = true;
+                fVideoRec = true;
                 break;
             case 'w':
                 ulFrameWidth = ValueUnion.u32;
@@ -855,7 +860,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
         LogError("VBoxHeadless: ERROR: Only one format modifier is allowed in the capture file name.", -1);
         return 1;
     }
-    RTStrPrintf(&pszMPEGFile[0], RTPATH_MAX, pszFileNameParam, RTProcSelf());
+    RTStrPrintf(&szMpegFile[0], RTPATH_MAX, pszFileNameParam, RTProcSelf());
 #endif /* defined VBOX_WITH_VIDEO_REC */
 
     if (!pcszNameOrUUID)
@@ -970,7 +975,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
         RTLDRMOD hLdrVideoRecFB;
         PFNREGISTERVIDEORECFB pfnRegisterVideoRecFB;
 
-        if (fVIDEOREC)
+        if (fVideoRec)
         {
             HRESULT         rcc = S_OK;
             int             rrc = VINF_SUCCESS;
@@ -994,7 +999,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
             {
                 Log2(("VBoxHeadless: calling pfnRegisterVideoRecFB\n"));
                 rcc = pfnRegisterVideoRecFB(ulFrameWidth, ulFrameHeight, ulBitRate,
-                                         pszMPEGFile, &pFramebuffer);
+                                         szMpegFile, &pFramebuffer);
                 if (rcc != S_OK)
                     LogError("Failed to initialise video capturing - make sure that the file format\n"
                              "you wish to use is supported on your system\n", rcc);
@@ -1020,7 +1025,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
         for (uScreenId = 0; uScreenId < cMonitors; uScreenId++)
         {
 # ifdef VBOX_WITH_VIDEO_REC
-            if (fVIDEOREC && uScreenId == 0)
+            if (fVideoRec && uScreenId == 0)
             {
                 /* Already registered. */
                 continue;
diff --git a/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp b/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp
index 2156d88..3e40a75 100644
--- a/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp
+++ b/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -21,7 +21,6 @@
 #include <VBox/com/Guid.h>
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
 
 #include <VBox/com/VirtualBox.h>
 
@@ -37,7 +36,7 @@ using namespace com;
 /**
  *  Entry point.
  */
-int main (int argc, char **argv)
+int main(int argc, char **argv)
 {
     // initialize VBox Runtime
     RTR3InitExe(argc, &argv, 0);
@@ -55,18 +54,18 @@ int main (int argc, char **argv)
 
     if (!name || !operation)
     {
-        RTPrintf ("\nUsage:\n\n"
-                  "%s <machine_name> [on|off|pause|resume]\n\n",
-                  argv [0]);
+        RTPrintf("\nUsage:\n\n"
+                 "%s <machine_name> [on|off|pause|resume]\n\n",
+                 argv [0]);
         return 0;
     }
 
-    RTPrintf ("\n");
-    RTPrintf ("tstHeadless STARTED.\n");
+    RTPrintf("\n");
+    RTPrintf("tstHeadless STARTED.\n");
 
-    RTPrintf ("VM name   : {%s}\n"
-              "Operation : %s\n\n",
-              name, operation);
+    RTPrintf("VM name   : {%s}\n"
+             "Operation : %s\n\n",
+             name, operation);
 
     HRESULT rc;
 
@@ -82,8 +81,8 @@ int main (int argc, char **argv)
         ComPtr <IVirtualBox> virtualBox;
         ComPtr <ISession> session;
 
-        RTPrintf ("Creating VirtualBox object...\n");
-        rc = virtualBox.createLocalObject (CLSID_VirtualBox);
+        RTPrintf("Creating VirtualBox object...\n");
+        rc = virtualBox.createLocalObject(CLSID_VirtualBox);
         if (FAILED(rc))
             RTPrintf("ERROR: failed to create the VirtualBox object!\n");
         else
@@ -93,7 +92,7 @@ int main (int argc, char **argv)
                 RTPrintf("ERROR: failed to create a session object!\n");
         }
 
-        if (FAILED (rc))
+        if (FAILED(rc))
         {
             com::ErrorInfo info;
             if (!info.isFullAvailable() && !info.isBasicAvailable())
@@ -106,11 +105,6 @@ int main (int argc, char **argv)
             break;
         }
 
-        // create the event queue
-        // (here it is necessary only to process remaining XPCOM/IPC events
-        // after the session is closed)
-        EventQueue eventQ;
-
         ComPtr <IMachine> m;
 
         // find ID by name
@@ -120,78 +114,78 @@ int main (int argc, char **argv)
         if (!strcmp(operation, "on"))
         {
             ComPtr <IProgress> progress;
-            RTPrintf ("Opening a new (remote) session...\n");
-            CHECK_ERROR_BREAK (m,
-                               LaunchVMProcess(session, Bstr("vrdp").raw(),
-                                               NULL, progress.asOutParam()));
+            RTPrintf("Opening a new (remote) session...\n");
+            CHECK_ERROR_BREAK(m,
+                              LaunchVMProcess(session, Bstr("vrdp").raw(),
+                                              NULL, progress.asOutParam()));
 
-            RTPrintf ("Waiting for the remote session to open...\n");
-            CHECK_ERROR_BREAK (progress, WaitForCompletion (-1));
+            RTPrintf("Waiting for the remote session to open...\n");
+            CHECK_ERROR_BREAK(progress, WaitForCompletion(-1));
 
             BOOL completed;
-            CHECK_ERROR_BREAK (progress, COMGETTER(Completed) (&completed));
-            ASSERT (completed);
+            CHECK_ERROR_BREAK(progress, COMGETTER(Completed)(&completed));
+            ASSERT(completed);
 
             LONG resultCode;
-            CHECK_ERROR_BREAK (progress, COMGETTER(ResultCode) (&resultCode));
-            if (FAILED (resultCode))
+            CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&resultCode));
+            if (FAILED(resultCode))
             {
                 ProgressErrorInfo info(progress);
                 com::GluePrintErrorInfo(info);
             }
             else
             {
-                RTPrintf ("Remote session has been successfully opened.\n");
+                RTPrintf("Remote session has been successfully opened.\n");
             }
         }
         else
         {
-            RTPrintf ("Opening an existing session...\n");
+            RTPrintf("Opening an existing session...\n");
             CHECK_ERROR_BREAK(m, LockMachine(session, LockType_Shared));
 
             ComPtr <IConsole> console;
             CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
 
-            if (!strcmp (operation, "off"))
+            if (!strcmp(operation, "off"))
             {
                 ComPtr <IProgress> progress;
-                RTPrintf ("Powering the VM off...\n");
-                CHECK_ERROR_BREAK (console, PowerDown(progress.asOutParam()));
+                RTPrintf("Powering the VM off...\n");
+                CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
 
-                RTPrintf ("Waiting for the VM to power down...\n");
-                CHECK_ERROR_BREAK (progress, WaitForCompletion (-1));
+                RTPrintf("Waiting for the VM to power down...\n");
+                CHECK_ERROR_BREAK(progress, WaitForCompletion(-1));
 
                 BOOL completed;
-                CHECK_ERROR_BREAK (progress, COMGETTER(Completed) (&completed));
-                ASSERT (completed);
+                CHECK_ERROR_BREAK(progress, COMGETTER(Completed)(&completed));
+                ASSERT(completed);
 
                 LONG resultCode;
-                CHECK_ERROR_BREAK (progress, COMGETTER(ResultCode) (&resultCode));
-                if (FAILED (resultCode))
+                CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&resultCode));
+                if (FAILED(resultCode))
                 {
                     ProgressErrorInfo info(progress);
                     com::GluePrintErrorInfo(info);
                 }
                 else
                 {
-                    RTPrintf ("VM is powered down.\n");
+                    RTPrintf("VM is powered down.\n");
                 }
             }
             else
-            if (!strcmp (operation, "pause"))
+            if (!strcmp(operation, "pause"))
             {
-                RTPrintf ("Pausing the VM...\n");
-                CHECK_ERROR_BREAK (console, Pause());
+                RTPrintf("Pausing the VM...\n");
+                CHECK_ERROR_BREAK(console, Pause());
             }
             else
-            if (!strcmp (operation, "resume"))
+            if (!strcmp(operation, "resume"))
             {
-                RTPrintf ("Resuming the VM...\n");
-                CHECK_ERROR_BREAK (console, Resume());
+                RTPrintf("Resuming the VM...\n");
+                CHECK_ERROR_BREAK(console, Resume());
             }
             else
             {
-                RTPrintf ("Invalid operation!\n");
+                RTPrintf("Invalid operation!\n");
             }
         }
 
@@ -199,11 +193,11 @@ int main (int argc, char **argv)
         CHECK_ERROR(session, UnlockMachine());
     }
     while (0);
-    RTPrintf ("\n");
+    RTPrintf("\n");
 
     com::Shutdown();
 
-    RTPrintf ("tstHeadless FINISHED.\n");
+    RTPrintf("tstHeadless FINISHED.\n");
 
     return rc;
 }
diff --git a/src/VBox/Frontends/VBoxManage/Makefile.kmk b/src/VBox/Frontends/VBoxManage/Makefile.kmk
index 9957b3e..ae33599 100644
--- a/src/VBox/Frontends/VBoxManage/Makefile.kmk
+++ b/src/VBox/Frontends/VBoxManage/Makefile.kmk
@@ -82,7 +82,8 @@ VBoxManage_DEFS      += \
 	$(if $(VBOX_WITH_USB_CARDREADER),VBOX_WITH_USB_CARDREADER) \
 	$(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH) \
 	$(if $(VBOX_WITH_VPX),VBOX_WITH_VPX) \
-	$(if $(VBOX_WITH_NAT_SERVICE),VBOX_WITH_NAT_SERVICE)
+	$(if $(VBOX_WITH_NAT_SERVICE),VBOX_WITH_NAT_SERVICE) \
+	$(if $(VBOX_WITH_VMSVGA),VBOX_WITH_VMSVGA)
 
 # VBoxNetPortForwardString.h
 VBoxManageNATNetwork.cpp_INCS += ../../NetworkServices/NetLib/
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
index 3399f10..279bd44 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2009-2013 Oracle Corporation
+ * Copyright (C) 2009-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -374,13 +374,13 @@ int handleImportAppliance(HandlerArg *arg)
                 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
                 com::SafeArray<BSTR> aRefs;
                 com::SafeArray<BSTR> aOvfValues;
-                com::SafeArray<BSTR> aVboxValues;
+                com::SafeArray<BSTR> aVBoxValues;
                 com::SafeArray<BSTR> aExtraConfigValues;
                 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
                                   GetDescription(ComSafeArrayAsOutParam(retTypes),
                                                  ComSafeArrayAsOutParam(aRefs),
                                                  ComSafeArrayAsOutParam(aOvfValues),
-                                                 ComSafeArrayAsOutParam(aVboxValues),
+                                                 ComSafeArrayAsOutParam(aVBoxValues),
                                                  ComSafeArrayAsOutParam(aExtraConfigValues)));
 
                 RTPrintf("Virtual system %u:\n", i);
@@ -401,7 +401,7 @@ int handleImportAppliance(HandlerArg *arg)
 
                     Utf8Str strOverride;
 
-                    Bstr bstrFinalValue = aVboxValues[a];
+                    Bstr bstrFinalValue = aVBoxValues[a];
 
                     bool fIgnoreThis = mapIgnoresMapsPerVsys[i][a];
 
@@ -437,27 +437,27 @@ int handleImportAppliance(HandlerArg *arg)
 
                         case VirtualSystemDescriptionType_Product:
                             RTPrintf("%2u: Product (ignored): %ls\n",
-                                     a, aVboxValues[a]);
+                                     a, aVBoxValues[a]);
                         break;
 
                         case VirtualSystemDescriptionType_ProductUrl:
                             RTPrintf("%2u: ProductUrl (ignored): %ls\n",
-                                     a, aVboxValues[a]);
+                                     a, aVBoxValues[a]);
                         break;
 
                         case VirtualSystemDescriptionType_Vendor:
                             RTPrintf("%2u: Vendor (ignored): %ls\n",
-                                     a, aVboxValues[a]);
+                                     a, aVBoxValues[a]);
                         break;
 
                         case VirtualSystemDescriptionType_VendorUrl:
                             RTPrintf("%2u: VendorUrl (ignored): %ls\n",
-                                     a, aVboxValues[a]);
+                                     a, aVBoxValues[a]);
                         break;
 
                         case VirtualSystemDescriptionType_Version:
                             RTPrintf("%2u: Version (ignored): %ls\n",
-                                     a, aVboxValues[a]);
+                                     a, aVBoxValues[a]);
                         break;
 
                         case VirtualSystemDescriptionType_Description:
@@ -550,14 +550,14 @@ int handleImportAppliance(HandlerArg *arg)
                             {
                                 RTPrintf("%2u: IDE controller, type %ls -- disabled\n",
                                          a,
-                                         aVboxValues[a]);
+                                         aVBoxValues[a]);
                                 aEnabled[a] = false;
                             }
                             else
                                 RTPrintf("%2u: IDE controller, type %ls"
                                          "\n    (disable with \"--vsys %u --unit %u --ignore\")\n",
                                          a,
-                                         aVboxValues[a],
+                                         aVBoxValues[a],
                                          i, a);
                         break;
 
@@ -566,14 +566,14 @@ int handleImportAppliance(HandlerArg *arg)
                             {
                                 RTPrintf("%2u: SATA controller, type %ls -- disabled\n",
                                          a,
-                                         aVboxValues[a]);
+                                         aVBoxValues[a]);
                                 aEnabled[a] = false;
                             }
                             else
                                 RTPrintf("%2u: SATA controller, type %ls"
                                         "\n    (disable with \"--vsys %u --unit %u --ignore\")\n",
                                         a,
-                                        aVboxValues[a],
+                                        aVBoxValues[a],
                                         i, a);
                         break;
 
@@ -582,14 +582,14 @@ int handleImportAppliance(HandlerArg *arg)
                             {
                                 RTPrintf("%2u: SAS controller, type %ls -- disabled\n",
                                          a,
-                                         aVboxValues[a]);
+                                         aVBoxValues[a]);
                                 aEnabled[a] = false;
                             }
                             else
                                 RTPrintf("%2u: SAS controller, type %ls"
                                         "\n    (disable with \"--vsys %u --unit %u --ignore\")\n",
                                         a,
-                                        aVboxValues[a],
+                                        aVBoxValues[a],
                                         i, a);
                         break;
 
@@ -598,7 +598,7 @@ int handleImportAppliance(HandlerArg *arg)
                             {
                                 RTPrintf("%2u: SCSI controller, type %ls -- disabled\n",
                                          a,
-                                         aVboxValues[a]);
+                                         aVBoxValues[a]);
                                 aEnabled[a] = false;
                             }
                             else
@@ -617,7 +617,7 @@ int handleImportAppliance(HandlerArg *arg)
                                             "\n    (change with \"--vsys %u --unit %u --scsitype {BusLogic|LsiLogic}\";"
                                             "\n    disable with \"--vsys %u --unit %u --ignore\")\n",
                                             a,
-                                            aVboxValues[a],
+                                            aVBoxValues[a],
                                             i, a, i, a);
                             }
                         break;
@@ -671,7 +671,7 @@ int handleImportAppliance(HandlerArg *arg)
                                     RTPrintf("%2u: Hard disk image: source image=%ls, target path=%ls, %ls\n",
                                             a,
                                             aOvfValues[a],
-                                            aVboxValues[a],
+                                            aVBoxValues[a],
                                             aExtraConfigValues[a]);
                                 }
 #endif
@@ -681,7 +681,7 @@ int handleImportAppliance(HandlerArg *arg)
                                             "\n    disable with \"--vsys %u --unit %u --ignore\")\n",
                                             a,
                                             aOvfValues[a],
-                                            aVboxValues[a],
+                                            aVBoxValues[a],
                                             aExtraConfigValues[a],
                                             i, a, i, a);
                             }
@@ -717,7 +717,7 @@ int handleImportAppliance(HandlerArg *arg)
                             RTPrintf("%2u: Network adapter: orig %ls, config %ls, extra %ls\n",   // @todo implement once we have a plan for the back-end
                                      a,
                                      aOvfValues[a],
-                                     aVboxValues[a],
+                                     aVBoxValues[a],
                                      aExtraConfigValues[a]);
                         break;
 
@@ -787,25 +787,67 @@ int handleImportAppliance(HandlerArg *arg)
     return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
 }
 
-static const RTGETOPTDEF g_aExportOptions[]
-    = {
-        { "--output",             'o', RTGETOPT_REQ_STRING },
-        { "--legacy09",           'l', RTGETOPT_REQ_NOTHING },
-        { "--ovf09",              'l', RTGETOPT_REQ_NOTHING },
-        { "--ovf10",              '1', RTGETOPT_REQ_NOTHING },
-        { "--ovf20",              '2', RTGETOPT_REQ_NOTHING },
-        { "--manifest",           'm', RTGETOPT_REQ_NOTHING },
-        { "--iso",                'I', RTGETOPT_REQ_NOTHING },
-        { "--vsys",               's', RTGETOPT_REQ_UINT32 },
-        { "--product",            'p', RTGETOPT_REQ_STRING },
-        { "--producturl",         'P', RTGETOPT_REQ_STRING },
-        { "--vendor",             'n', RTGETOPT_REQ_STRING },
-        { "--vendorurl",          'N', RTGETOPT_REQ_STRING },
-        { "--version",            'v', RTGETOPT_REQ_STRING },
-        { "--description",        'd', RTGETOPT_REQ_STRING },
-        { "--eula",               'e', RTGETOPT_REQ_STRING },
-        { "--eulafile",           'E', RTGETOPT_REQ_STRING },
-      };
+static int parseExportOptions(const char *psz, com::SafeArray<ExportOptions_T> *options)
+{
+    int rc = VINF_SUCCESS;
+    while (psz && *psz && RT_SUCCESS(rc))
+    {
+        size_t len;
+        const char *pszComma = strchr(psz, ',');
+        if (pszComma)
+            len = pszComma - psz;
+        else
+            len = strlen(psz);
+        if (len > 0)
+        {
+            if (!RTStrNICmp(psz, "CreateManifest", len))
+                options->push_back(ExportOptions_CreateManifest);
+            else if (!RTStrNICmp(psz, "manifest", len))
+                options->push_back(ExportOptions_CreateManifest);
+            else if (!RTStrNICmp(psz, "ExportDVDImages", len))
+                options->push_back(ExportOptions_ExportDVDImages);
+            else if (!RTStrNICmp(psz, "iso", len))
+                options->push_back(ExportOptions_ExportDVDImages);
+            else if (!RTStrNICmp(psz, "StripAllMACs", len))
+                options->push_back(ExportOptions_StripAllMACs);
+            else if (!RTStrNICmp(psz, "nomacs", len))
+                options->push_back(ExportOptions_StripAllMACs);
+            else if (!RTStrNICmp(psz, "StripAllNonNATMACs", len))
+                options->push_back(ExportOptions_StripAllNonNATMACs);
+            else if (!RTStrNICmp(psz, "nomacsbutnat", len))
+                options->push_back(ExportOptions_StripAllNonNATMACs);
+            else
+                rc = VERR_PARSE_ERROR;
+        }
+        if (pszComma)
+            psz += len + 1;
+        else
+            psz += len;
+    }
+
+    return rc;
+}
+
+static const RTGETOPTDEF g_aExportOptions[] =
+{
+    { "--output",               'o', RTGETOPT_REQ_STRING },
+    { "--legacy09",             'l', RTGETOPT_REQ_NOTHING },
+    { "--ovf09",                'l', RTGETOPT_REQ_NOTHING },
+    { "--ovf10",                '1', RTGETOPT_REQ_NOTHING },
+    { "--ovf20",                '2', RTGETOPT_REQ_NOTHING },
+    { "--manifest",             'm', RTGETOPT_REQ_NOTHING },    // obsoleted by --options
+    { "--iso",                  'I', RTGETOPT_REQ_NOTHING },    // obsoleted by --options
+    { "--vsys",                 's', RTGETOPT_REQ_UINT32 },
+    { "--product",              'p', RTGETOPT_REQ_STRING },
+    { "--producturl",           'P', RTGETOPT_REQ_STRING },
+    { "--vendor",               'n', RTGETOPT_REQ_STRING },
+    { "--vendorurl",            'N', RTGETOPT_REQ_STRING },
+    { "--version",              'v', RTGETOPT_REQ_STRING },
+    { "--description",          'd', RTGETOPT_REQ_STRING },
+    { "--eula",                 'e', RTGETOPT_REQ_STRING },
+    { "--eulafile",             'E', RTGETOPT_REQ_STRING },
+    { "--options",              'O', RTGETOPT_REQ_STRING },
+};
 
 int handleExportAppliance(HandlerArg *a)
 {
@@ -815,6 +857,7 @@ int handleExportAppliance(HandlerArg *a)
     Utf8Str strOvfFormat("ovf-1.0"); // the default export version
     bool fManifest = false; // the default
     bool fExportISOImages = false; // the default
+    com::SafeArray<ExportOptions_T> options;
     std::list< ComPtr<IMachine> > llMachines;
 
     uint32_t ulCurVsys = (uint32_t)-1;
@@ -843,76 +886,81 @@ int handleExportAppliance(HandlerArg *a)
                     break;
 
                 case 'l':   // --legacy09/--ovf09
-                     strOvfFormat = "ovf-0.9";
-                     break;
+                    strOvfFormat = "ovf-0.9";
+                    break;
 
                 case '1':   // --ovf10
-                     strOvfFormat = "ovf-1.0";
-                     break;
+                    strOvfFormat = "ovf-1.0";
+                    break;
 
                 case '2':   // --ovf20
-                     strOvfFormat = "ovf-2.0";
-                     break;
+                    strOvfFormat = "ovf-2.0";
+                    break;
 
                 case 'I':   // --iso
-                     fExportISOImages = true;
-                     break;
+                    fExportISOImages = true;
+                    break;
 
                 case 'm':   // --manifest
-                     fManifest = true;
-                     break;
+                    fManifest = true;
+                    break;
 
                 case 's':   // --vsys
-                     ulCurVsys = ValueUnion.u32;
-                     break;
+                    ulCurVsys = ValueUnion.u32;
+                    break;
 
                 case 'p':   // --product
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["product"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["product"] = ValueUnion.psz;
+                    break;
 
                 case 'P':   // --producturl
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["producturl"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["producturl"] = ValueUnion.psz;
+                    break;
 
                 case 'n':   // --vendor
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["vendor"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["vendor"] = ValueUnion.psz;
+                    break;
 
                 case 'N':   // --vendorurl
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["vendorurl"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["vendorurl"] = ValueUnion.psz;
+                    break;
 
                 case 'v':   // --version
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["version"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["version"] = ValueUnion.psz;
+                    break;
 
                 case 'd':   // --description
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz;
+                    break;
 
                 case 'e':   // --eula
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz;
+                    break;
 
                 case 'E':   // --eulafile
-                     if (ulCurVsys == (uint32_t)-1)
-                         return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
-                     mapArgsMapsPerVsys[ulCurVsys]["eulafile"] = ValueUnion.psz;
-                     break;
+                    if (ulCurVsys == (uint32_t)-1)
+                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
+                    mapArgsMapsPerVsys[ulCurVsys]["eulafile"] = ValueUnion.psz;
+                    break;
+
+                case 'O':   // --options
+                    if (RT_FAILURE(parseExportOptions(ValueUnion.psz, &options)))
+                        return errorArgument("Invalid export options '%s'\n", ValueUnion.psz);
+                    break;
 
                 case VINF_GETOPT_NOT_OPTION:
                 {
@@ -1056,7 +1104,6 @@ int handleExportAppliance(HandlerArg *a)
         if (FAILED(rc))
             break;
 
-        com::SafeArray<ExportOptions_T> options;
         if (fManifest)
             options.push_back(ExportOptions_CreateManifest);
 
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp
index 46cf199..2765372 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp
@@ -107,6 +107,12 @@ static RTEXITCODE handleBandwidthControlAdd(HandlerArg *a, ComPtr<IBandwidthCont
 
 
     Bstr name(a->argv[2]);
+    if (name.isEmpty())
+    {
+        errorArgument("Bandwidth group name must not be empty!\n");
+        return RTEXITCODE_FAILURE;
+    }
+
     const char *pszType  = NULL;
     int64_t cMaxBytesPerSec = INT64_MAX;
 
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
index 187fd45..cc3ab44 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -196,7 +196,11 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
                      "                            [--unplugcpu <id>]\n"
                      "                            [--cpuexecutioncap <1-100>]\n"
                      "                            [--rtcuseutc on|off]\n"
+#ifdef VBOX_WITH_VMSVGA
+                     "                            [--graphicscontroller none|vboxvga|vmsvga]\n"
+#else
                      "                            [--graphicscontroller none|vboxvga]\n"
+#endif
                      "                            [--monitorcount <number>]\n"
                      "                            [--accelerate3d on|off]\n"
 #ifdef VBOX_WITH_VIDEOHWACCEL
@@ -344,7 +348,7 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
                      "                            [--teleporterport <port>]\n"
                      "                            [--teleporteraddress <address|empty>\n"
                      "                            [--teleporterpassword <password>]\n"
-                     "                            [--teleporterpasswordfile  <file>|stdin]\n"
+                     "                            [--teleporterpasswordfile <file>|stdin]\n"
                      "                            [--tracing-enabled on|off]\n"
                      "                            [--tracing-config <config-string>]\n"
                      "                            [--tracing-allow-vm-access on|off]\n"
@@ -377,7 +381,7 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
                      "                            [--vcprate <rate>]\n"
                      "                            [--vcpfps <fps>]\n"
 #endif
-                     "                            [--defaultfrontend default|<name]\n"
+                     "                            [--defaultfrontend default|<name>]\n"
                      "\n");
     }
 
@@ -410,6 +414,7 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
                      "                            [--legacy09|--ovf09|--ovf10|--ovf20]\n"
                      "                            [--manifest]\n"
                      "                            [--iso]\n"
+                     "                            [--options manifest|iso|nomacs|nomacsbutnat]\n"
                      "                            [--vsys <number of virtual system>]\n"
                      "                                    [--product <product name>]\n"
                      "                                    [--producturl <product url>]\n"
@@ -757,7 +762,7 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
     {
         RTStrmPrintf(pStrm,
                            "%s natnetwork %s      add --netname <name>\n"
-                     "                            --network <network\n"
+                     "                            --network <network>\n"
                      "                            [--enable|--disable]\n"
                      "                            [--dhcp on|off]\n"
                      "                            [--port-forward-4 <rule>]\n"
@@ -767,7 +772,7 @@ void printUsage(USAGECATEGORY fCategory, uint32_t fSubCategory, PRTSTREAM pStrm)
                      "                            [--loopback-6 <rule>]\n\n"
                            "%s natnetwork %s      remove --netname <name>\n\n"
                            "%s natnetwork %s      modify --netname <name>\n"
-                     "                            [--network <network]\n"
+                     "                            [--network <network>]\n"
                      "                            [--enable|--disable]\n"
                      "                            [--dhcp on|off]\n"
                      "                            [--port-forward-4 <rule>]\n"
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
index 7e00e39..d7515fc 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
@@ -734,6 +734,11 @@ int handleModifyVM(HandlerArg *a)
                          || !RTStrICmp(ValueUnion.psz, "vga")
                          || !RTStrICmp(ValueUnion.psz, "vesa"))
                     CHECK_ERROR(machine, COMSETTER(GraphicsControllerType)(GraphicsControllerType_VBoxVGA));
+#ifdef VBOX_WITH_VMSVGA
+                else if (   !RTStrICmp(ValueUnion.psz, "vmsvga")
+                         || !RTStrICmp(ValueUnion.psz, "vmware"))
+                    CHECK_ERROR(machine, COMSETTER(GraphicsControllerType)(GraphicsControllerType_VMSVGA));
+#endif
                 else
                 {
                     errorArgument("Invalid --graphicscontroller argument '%s'", ValueUnion.psz);
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp
index afd0fc5..08f0d43 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -27,17 +27,6 @@
 
 #include <iprt/asm.h>
 
-/* missing XPCOM <-> COM wrappers */
-#ifndef STDMETHOD_
-# define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
-#endif
-#ifndef NS_GET_IID
-# define NS_GET_IID(I) IID_##I
-#endif
-#ifndef RT_OS_WINDOWS
-#define IUnknown nsISupports
-#endif
-
 using namespace com;
 
 /**
@@ -70,13 +59,13 @@ public:
     STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)
     {
         Guid guid(iid);
-        if (guid == Guid(NS_GET_IID(IUnknown)))
+        if (guid == Guid(COM_IIDOF(IUnknown)))
             *ppvObject = (IUnknown *)this;
 #ifdef RT_OS_WINDOWS
-        else if (guid == Guid(NS_GET_IID(IDispatch)))
+        else if (guid == Guid(COM_IIDOF(IDispatch)))
             *ppvObject = (IDispatch *)this;
 #endif
-        else if (guid == Guid(NS_GET_IID(IUSBDevice)))
+        else if (guid == Guid(COM_IIDOF(IUSBDevice)))
             *ppvObject = (IUSBDevice *)this;
         else
             return E_NOINTERFACE;
diff --git a/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp b/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp
index 063ae37..00b80ab 100644
--- a/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp
+++ b/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp
@@ -167,7 +167,7 @@ bool VBoxSDLFB::init(bool fShowSDLConfig)
 
 #ifdef RT_OS_WINDOWS
     /* default to DirectX if nothing else set */
-    if (!RTEnvGet("SDL_VIDEODRIVER"))
+    if (!RTEnvExist("SDL_VIDEODRIVER"))
     {
         _putenv("SDL_VIDEODRIVER=directx");
 //        _putenv("SDL_VIDEODRIVER=windib");
diff --git a/src/VBox/Frontends/VBoxShell/vboxshell.py b/src/VBox/Frontends/VBoxShell/vboxshell.py
index 75ab887..92a0354 100755
--- a/src/VBox/Frontends/VBoxShell/vboxshell.py
+++ b/src/VBox/Frontends/VBoxShell/vboxshell.py
@@ -30,7 +30,7 @@ Foundation, in version 2 as it comes in the "COPYING" file of the
 VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 """
-__version__ = "$Revision: 90995 $"
+__version__ = "$Revision: 92173 $"
 
 
 import os, sys
@@ -177,7 +177,7 @@ def autoCompletion(cmds, ctx):
         readline.parse_and_bind ("bind ^W ed-delete-prev-word")
         # Doesn't work well
         # readline.parse_and_bind ("bind ^R em-inc-search-prev")
-        readline.parse_and_bind("tab: complete")
+    readline.parse_and_bind("tab: complete")
 
 
 g_fVerbose = False
diff --git a/src/VBox/Frontends/VirtualBox/Makefile.kmk b/src/VBox/Frontends/VirtualBox/Makefile.kmk
index fa7b872..a1c3a0f 100644
--- a/src/VBox/Frontends/VirtualBox/Makefile.kmk
+++ b/src/VBox/Frontends/VirtualBox/Makefile.kmk
@@ -730,7 +730,8 @@ endif
 VirtualBox_SOURCES.win += \
 	src/platform/win/VirtualBox.rc \
 	src/platform/win/UIDesktopServices_win.cpp \
-	src/platform/win/VBoxUtils-win.cpp
+	src/platform/win/VBoxUtils-win.cpp \
+	src/platform/win/WinKeyboard.cpp
 
 VirtualBox_DEFS.darwin += VBOX_DARWIN_USE_NATIVE_CONTROLS
 VirtualBox_SOURCES.darwin += \
@@ -849,6 +850,7 @@ VirtualBox_BLDDIRS       += $(VBOX_VIRTUALBOX4_OUT_DIR)
 VirtualBox_CLEAN         += $(VBOX_VIRTUALBOX4_OUT_DIR)/VirtualBoxBrand.qrc
 $(VBOX_VIRTUALBOX4_OUT_DIR)/VirtualBoxBrand.qrc: \
 		$(VBOX_VIRTUALBOX4_SRC)/VirtualBoxBrand.qrc \
+		$(PATH_ROOT)/Config.kmk \
 		| $$(dir $$@)
 	$(call MSG_GENERATE,VirtualBox,$<,$@)
 	$(QUIET)$(SED) \
@@ -861,6 +863,7 @@ $(VBOX_VIRTUALBOX4_OUT_DIR)/VirtualBoxBrand.qrc: \
 		-e 's;@VBOX_VBOX_48PX_PNG@;$(VBOX_BRAND_GUI_VBOX_48PX_PNG);g' \
 		-e 's;@VBOX_VBOX_64PX_PNG@;$(VBOX_BRAND_GUI_VBOX_64PX_PNG);g' \
 		-e 's;@VBOX_CUBE_42PX_PNG@;$(VBOX_BRAND_GUI_CUBE_42PX_PNG);g' \
+		-e 's;@VBOX_CUBE_SVG@;$(VBOX_BRAND_GUI_VBOX_SVG);g' \
 		--output $@ \
 		$<
 
diff --git a/src/VBox/Frontends/VirtualBox/VirtualBox1.qrc b/src/VBox/Frontends/VirtualBox/VirtualBox1.qrc
index cda79ed..de5e27d 100644
--- a/src/VBox/Frontends/VirtualBox/VirtualBox1.qrc
+++ b/src/VBox/Frontends/VirtualBox/VirtualBox1.qrc
@@ -256,6 +256,7 @@
         <file alias="minimize_16px.png">images/minimize_16px.png</file>
         <file alias="restore_16px.png">images/restore_16px.png</file>
         <file alias="close_16px.png">images/close_16px.png</file>
+        <file alias="close_popup_16px.png">images/close_popup_16px.png</file>
         <file alias="ok_16px.png">images/ok_16px.png</file>
         <file alias="cancel_16px.png">images/cancel_16px.png</file>
         <file alias="vm_save_state_16px.png">images/vm_save_state_16px.png</file>
diff --git a/src/VBox/Frontends/VirtualBox/VirtualBoxBrand.qrc b/src/VBox/Frontends/VirtualBox/VirtualBoxBrand.qrc
index b445b8c..37e2c58 100644
--- a/src/VBox/Frontends/VirtualBox/VirtualBoxBrand.qrc
+++ b/src/VBox/Frontends/VirtualBox/VirtualBoxBrand.qrc
@@ -8,5 +8,6 @@
     <file alias="VirtualBox_40px.png">@VBOX_VBOX_40PX_PNG@</file>
     <file alias="VirtualBox_48px.png">@VBOX_VBOX_48PX_PNG@</file>
     <file alias="VirtualBox_64px.png">@VBOX_VBOX_64PX_PNG@</file>
+    <file alias="VirtualBox.svg">@VBOX_CUBE_SVG@</file>
  </qresource>
  </RCC>
diff --git a/src/VBox/Frontends/VirtualBox/images/close_popup_16px.png b/src/VBox/Frontends/VirtualBox/images/close_popup_16px.png
new file mode 100644
index 0000000..b48491d
Binary files /dev/null and b/src/VBox/Frontends/VirtualBox/images/close_popup_16px.png differ
diff --git a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
index a2f1d6a..aafb878 100644
--- a/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
+++ b/src/VBox/Frontends/VirtualBox/nls/VirtualBox_de.ts
@@ -708,6 +708,10 @@
         <source>&Webcams</source>
         <translation>&Webcams</translation>
     </message>
+    <message>
+        <source>Network</source>
+        <translation>Netzwerk</translation>
+    </message>
 </context>
 <context>
     <name>UIApplianceEditorWidget</name>
@@ -2249,6 +2253,14 @@
         <source>No supported webcams connected to the host PC</source>
         <translation>Keine unterstützten Webcams mit dem PC verbunden</translation>
     </message>
+    <message>
+        <source>Connect Network Adapter</source>
+        <translation>Netzwerkadapter verbinden</translation>
+    </message>
+    <message>
+        <source>Connect Network Adapter %1</source>
+        <translation>Netzwerkadapter %1 verbinden</translation>
+    </message>
 </context>
 <context>
     <name>UIMachineSettingsAudio</name>
@@ -2502,6 +2514,11 @@
         <source>Enable video recording for screen %1.</source>
         <translation>Videoaufzeichnung für Bildschirm %1 aktivieren.</translation>
     </message>
+    <message>
+        <source>Remote Display is currently enabled for this virtual machine. However, this requires the <b>%1</b> to be installed. Please install the Extension Pack from the VirtualBox download site as otherwise your VM will be started with Remote Display disabled.</source>
+        <translatorcomment>Die Fernsteu</translatorcomment>
+        <translation>Die Fernsteuerung per Remote Desktop Protocol wurde für diese virtuelle Maschine aktiviert. Dafür ist allerdings die Installation des <b>%1</b> notwendig. Bitte installieren Sie dieses Zusatzpaket von der VirtualBox-Webseite, sonst wird die virtuelle Maschine mit deaktivierter Fernsteuerung gestartet.</translation>
+    </message>
 </context>
 <context>
     <name>UIMachineSettingsGeneral</name>
diff --git a/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h b/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h
index 3ffc49f..0425bf1 100644
--- a/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h
+++ b/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h
@@ -60,6 +60,16 @@ template<class X> X fromInternalString(const QString & /* strData */) { Assert(0
 template<> bool canConvert<SizeSuffix>();
 template<> bool canConvert<StorageSlot>();
 template<> bool canConvert<RuntimeMenuType>();
+#ifdef Q_WS_MAC
+template<> bool canConvert<RuntimeMenuApplicationActionType>();
+#endif /* Q_WS_MAC */
+template<> bool canConvert<RuntimeMenuMachineActionType>();
+template<> bool canConvert<RuntimeMenuViewActionType>();
+template<> bool canConvert<RuntimeMenuDevicesActionType>();
+#ifdef VBOX_WITH_DEBUGGER_GUI
+template<> bool canConvert<RuntimeMenuDebuggerActionType>();
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+template<> bool canConvert<RuntimeMenuHelpActionType>();
 template<> bool canConvert<UIVisualStateType>();
 template<> bool canConvert<DetailsElementType>();
 template<> bool canConvert<GlobalSettingsPageType>();
@@ -97,6 +107,22 @@ template<> QString toString(const StorageSlot &storageSlot);
 template<> StorageSlot fromString<StorageSlot>(const QString &strStorageSlot);
 template<> QString toInternalString(const RuntimeMenuType &runtimeMenuType);
 template<> RuntimeMenuType fromInternalString<RuntimeMenuType>(const QString &strRuntimeMenuType);
+#ifdef Q_WS_MAC
+template<> QString toInternalString(const RuntimeMenuApplicationActionType &runtimeMenuApplicationActionType);
+template<> RuntimeMenuApplicationActionType fromInternalString<RuntimeMenuApplicationActionType>(const QString &strRuntimeMenuApplicationActionType);
+#endif /* Q_WS_MAC */
+template<> QString toInternalString(const RuntimeMenuMachineActionType &runtimeMenuMachineActionType);
+template<> RuntimeMenuMachineActionType fromInternalString<RuntimeMenuMachineActionType>(const QString &strRuntimeMenuMachineActionType);
+template<> QString toInternalString(const RuntimeMenuViewActionType &runtimeMenuViewActionType);
+template<> RuntimeMenuViewActionType fromInternalString<RuntimeMenuViewActionType>(const QString &strRuntimeMenuViewActionType);
+template<> QString toInternalString(const RuntimeMenuDevicesActionType &runtimeMenuDevicesActionType);
+template<> RuntimeMenuDevicesActionType fromInternalString<RuntimeMenuDevicesActionType>(const QString &strRuntimeMenuDevicesActionType);
+#ifdef VBOX_WITH_DEBUGGER_GUI
+template<> QString toInternalString(const RuntimeMenuDebuggerActionType &runtimeMenuDebuggerActionType);
+template<> RuntimeMenuDebuggerActionType fromInternalString<RuntimeMenuDebuggerActionType>(const QString &strRuntimeMenuDebuggerActionType);
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+template<> QString toInternalString(const RuntimeMenuHelpActionType &runtimeMenuHelpActionType);
+template<> RuntimeMenuHelpActionType fromInternalString<RuntimeMenuHelpActionType>(const QString &strRuntimeMenuHelpActionType);
 template<> QString toInternalString(const UIVisualStateType &visualStateType);
 template<> UIVisualStateType fromInternalString<UIVisualStateType>(const QString &strVisualStateType);
 template<> QString toString(const DetailsElementType &detailsElementType);
diff --git a/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp b/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp
index b833336..0ff5300 100644
--- a/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp
@@ -33,6 +33,16 @@
 template<> bool canConvert<SizeSuffix>() { return true; }
 template<> bool canConvert<StorageSlot>() { return true; }
 template<> bool canConvert<RuntimeMenuType>() { return true; }
+#ifdef Q_WS_MAC
+template<> bool canConvert<RuntimeMenuApplicationActionType>() { return true; }
+#endif /* Q_WS_MAC */
+template<> bool canConvert<RuntimeMenuMachineActionType>() { return true; }
+template<> bool canConvert<RuntimeMenuViewActionType>() { return true; }
+template<> bool canConvert<RuntimeMenuDevicesActionType>() { return true; }
+#ifdef VBOX_WITH_DEBUGGER_GUI
+template<> bool canConvert<RuntimeMenuDebuggerActionType>() { return true; }
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+template<> bool canConvert<RuntimeMenuHelpActionType>() { return true; }
 template<> bool canConvert<UIVisualStateType>() { return true; }
 template<> bool canConvert<DetailsElementType>() { return true; }
 template<> bool canConvert<GlobalSettingsPageType>() { return true; }
@@ -346,6 +356,286 @@ template<> RuntimeMenuType fromInternalString<RuntimeMenuType>(const QString &st
     return values.at(keys.indexOf(QRegExp(strRuntimeMenuType, Qt::CaseInsensitive)));
 }
 
+#ifdef Q_WS_MAC
+/* QString <= RuntimeMenuApplicationActionType: */
+template<> QString toInternalString(const RuntimeMenuApplicationActionType &runtimeMenuApplicationActionType)
+{
+    QString strResult;
+    switch (runtimeMenuApplicationActionType)
+    {
+        case RuntimeMenuApplicationActionType_About: strResult = "About"; break;
+        case RuntimeMenuApplicationActionType_All:   strResult = "All"; break;
+        default:
+        {
+            AssertMsgFailed(("No text for action type=%d", runtimeMenuApplicationActionType));
+            break;
+        }
+    }
+    return strResult;
+}
+
+/* RuntimeMenuApplicationActionType <= QString: */
+template<> RuntimeMenuApplicationActionType fromInternalString<RuntimeMenuApplicationActionType>(const QString &strRuntimeMenuApplicationActionType)
+{
+    /* Here we have some fancy stuff allowing us
+     * to search through the keys using 'case-insensitive' rule: */
+    QStringList keys; QList<RuntimeMenuApplicationActionType> values;
+    keys << "About";  values << RuntimeMenuApplicationActionType_About;
+    keys << "All";    values << RuntimeMenuApplicationActionType_All;
+    /* Invalid type for unknown words: */
+    if (!keys.contains(strRuntimeMenuApplicationActionType, Qt::CaseInsensitive))
+        return RuntimeMenuApplicationActionType_Invalid;
+    /* Corresponding type for known words: */
+    return values.at(keys.indexOf(QRegExp(strRuntimeMenuApplicationActionType, Qt::CaseInsensitive)));
+}
+#endif /* Q_WS_MAC */
+
+/* QString <= RuntimeMenuMachineActionType: */
+template<> QString toInternalString(const RuntimeMenuMachineActionType &runtimeMenuMachineActionType)
+{
+    QString strResult;
+    switch (runtimeMenuMachineActionType)
+    {
+        case RuntimeMenuMachineActionType_SettingsDialog:    strResult = "SettingsDialog"; break;
+        case RuntimeMenuMachineActionType_TakeSnapshot:      strResult = "TakeSnapshot"; break;
+        case RuntimeMenuMachineActionType_TakeScreenshot:    strResult = "TakeScreenshot"; break;
+        case RuntimeMenuMachineActionType_InformationDialog: strResult = "InformationDialog"; break;
+        case RuntimeMenuMachineActionType_MouseIntegration:  strResult = "MouseIntegration"; break;
+        case RuntimeMenuMachineActionType_TypeCAD:           strResult = "TypeCAD"; break;
+#ifdef Q_WS_X11
+        case RuntimeMenuMachineActionType_TypeCABS:          strResult = "TypeCABS"; break;
+#endif /* Q_WS_X11 */
+        case RuntimeMenuMachineActionType_Pause:             strResult = "Pause"; break;
+        case RuntimeMenuMachineActionType_Reset:             strResult = "Reset"; break;
+        case RuntimeMenuMachineActionType_SaveState:         strResult = "SaveState"; break;
+        case RuntimeMenuMachineActionType_Shutdown:          strResult = "Shutdown"; break;
+        case RuntimeMenuMachineActionType_PowerOff:          strResult = "PowerOff"; break;
+#ifndef Q_WS_MAC
+        case RuntimeMenuMachineActionType_Close:             strResult = "Close"; break;
+#endif /* !Q_WS_MAC */
+        case RuntimeMenuMachineActionType_All:               strResult = "All"; break;
+        default:
+        {
+            AssertMsgFailed(("No text for action type=%d", runtimeMenuMachineActionType));
+            break;
+        }
+    }
+    return strResult;
+}
+
+/* RuntimeMenuMachineActionType <= QString: */
+template<> RuntimeMenuMachineActionType fromInternalString<RuntimeMenuMachineActionType>(const QString &strRuntimeMenuMachineActionType)
+{
+    /* Here we have some fancy stuff allowing us
+     * to search through the keys using 'case-insensitive' rule: */
+    QStringList keys;            QList<RuntimeMenuMachineActionType> values;
+    keys << "SettingsDialog";    values << RuntimeMenuMachineActionType_SettingsDialog;
+    keys << "TakeSnapshot";      values << RuntimeMenuMachineActionType_TakeSnapshot;
+    keys << "TakeScreenshot";    values << RuntimeMenuMachineActionType_TakeScreenshot;
+    keys << "InformationDialog"; values << RuntimeMenuMachineActionType_InformationDialog;
+    keys << "MouseIntegration";  values << RuntimeMenuMachineActionType_MouseIntegration;
+    keys << "TypeCAD";           values << RuntimeMenuMachineActionType_TypeCAD;
+#ifdef Q_WS_X11
+    keys << "TypeCABS";          values << RuntimeMenuMachineActionType_TypeCABS;
+#endif /* Q_WS_X11 */
+    keys << "Pause";             values << RuntimeMenuMachineActionType_Pause;
+    keys << "Reset";             values << RuntimeMenuMachineActionType_Reset;
+    keys << "SaveState";         values << RuntimeMenuMachineActionType_SaveState;
+    keys << "Shutdown";          values << RuntimeMenuMachineActionType_Shutdown;
+    keys << "PowerOff";          values << RuntimeMenuMachineActionType_PowerOff;
+#ifndef Q_WS_MAC
+    keys << "Close";             values << RuntimeMenuMachineActionType_Close;
+#endif /* !Q_WS_MAC */
+    keys << "All";               values << RuntimeMenuMachineActionType_All;
+    /* Invalid type for unknown words: */
+    if (!keys.contains(strRuntimeMenuMachineActionType, Qt::CaseInsensitive))
+        return RuntimeMenuMachineActionType_Invalid;
+    /* Corresponding type for known words: */
+    return values.at(keys.indexOf(QRegExp(strRuntimeMenuMachineActionType, Qt::CaseInsensitive)));
+}
+
+/* QString <= RuntimeMenuViewActionType: */
+template<> QString toInternalString(const RuntimeMenuViewActionType &runtimeMenuViewActionType)
+{
+    QString strResult;
+    switch (runtimeMenuViewActionType)
+    {
+        case RuntimeMenuViewActionType_Fullscreen:      strResult = "Fullscreen"; break;
+        case RuntimeMenuViewActionType_Seamless:        strResult = "Seamless"; break;
+        case RuntimeMenuViewActionType_Scale:           strResult = "Scale"; break;
+        case RuntimeMenuViewActionType_GuestAutoresize: strResult = "GuestAutoresize"; break;
+        case RuntimeMenuViewActionType_AdjustWindow:    strResult = "AdjustWindow"; break;
+        case RuntimeMenuViewActionType_Multiscreen:     strResult = "Multiscreen"; break;
+        case RuntimeMenuViewActionType_All:             strResult = "All"; break;
+        default:
+        {
+            AssertMsgFailed(("No text for action type=%d", runtimeMenuViewActionType));
+            break;
+        }
+    }
+    return strResult;
+}
+
+/* RuntimeMenuViewActionType <= QString: */
+template<> RuntimeMenuViewActionType fromInternalString<RuntimeMenuViewActionType>(const QString &strRuntimeMenuViewActionType)
+{
+    /* Here we have some fancy stuff allowing us
+     * to search through the keys using 'case-insensitive' rule: */
+    QStringList keys;          QList<RuntimeMenuViewActionType> values;
+    keys << "Fullscreen";      values << RuntimeMenuViewActionType_Fullscreen;
+    keys << "Seamless";        values << RuntimeMenuViewActionType_Seamless;
+    keys << "Scale";           values << RuntimeMenuViewActionType_Scale;
+    keys << "GuestAutoresize"; values << RuntimeMenuViewActionType_GuestAutoresize;
+    keys << "AdjustWindow";    values << RuntimeMenuViewActionType_AdjustWindow;
+    keys << "Multiscreen";     values << RuntimeMenuViewActionType_Multiscreen;
+    keys << "All";             values << RuntimeMenuViewActionType_All;
+    /* Invalid type for unknown words: */
+    if (!keys.contains(strRuntimeMenuViewActionType, Qt::CaseInsensitive))
+        return RuntimeMenuViewActionType_Invalid;
+    /* Corresponding type for known words: */
+    return values.at(keys.indexOf(QRegExp(strRuntimeMenuViewActionType, Qt::CaseInsensitive)));
+}
+
+/* QString <= RuntimeMenuDevicesActionType: */
+template<> QString toInternalString(const RuntimeMenuDevicesActionType &runtimeMenuDevicesActionType)
+{
+    QString strResult;
+    switch (runtimeMenuDevicesActionType)
+    {
+        case RuntimeMenuDevicesActionType_OpticalDevices:        strResult = "OpticalDevices"; break;
+        case RuntimeMenuDevicesActionType_FloppyDevices:         strResult = "FloppyDevices"; break;
+        case RuntimeMenuDevicesActionType_USBDevices:            strResult = "USBDevices"; break;
+        case RuntimeMenuDevicesActionType_WebCams:               strResult = "WebCams"; break;
+        case RuntimeMenuDevicesActionType_SharedClipboard:       strResult = "SharedClipboard"; break;
+        case RuntimeMenuDevicesActionType_DragAndDrop:           strResult = "DragAndDrop"; break;
+        case RuntimeMenuDevicesActionType_NetworkSettings:       strResult = "NetworkSettings"; break;
+        case RuntimeMenuDevicesActionType_SharedFoldersSettings: strResult = "SharedFoldersSettings"; break;
+        case RuntimeMenuDevicesActionType_VRDEServer:            strResult = "VRDEServer"; break;
+        case RuntimeMenuDevicesActionType_VideoCapture:          strResult = "VideoCapture"; break;
+        case RuntimeMenuDevicesActionType_InstallGuestTools:     strResult = "InstallGuestTools"; break;
+        case RuntimeMenuDevicesActionType_All:                   strResult = "All"; break;
+        default:
+        {
+            AssertMsgFailed(("No text for action type=%d", runtimeMenuDevicesActionType));
+            break;
+        }
+    }
+    return strResult;
+}
+
+/* RuntimeMenuDevicesActionType <= QString: */
+template<> RuntimeMenuDevicesActionType fromInternalString<RuntimeMenuDevicesActionType>(const QString &strRuntimeMenuDevicesActionType)
+{
+    /* Here we have some fancy stuff allowing us
+     * to search through the keys using 'case-insensitive' rule: */
+    QStringList keys;                QList<RuntimeMenuDevicesActionType> values;
+    keys << "OpticalDevices";        values << RuntimeMenuDevicesActionType_OpticalDevices;
+    keys << "FloppyDevices";         values << RuntimeMenuDevicesActionType_FloppyDevices;
+    keys << "USBDevices";            values << RuntimeMenuDevicesActionType_USBDevices;
+    keys << "WebCams";               values << RuntimeMenuDevicesActionType_WebCams;
+    keys << "SharedClipboard";       values << RuntimeMenuDevicesActionType_SharedClipboard;
+    keys << "DragAndDrop";           values << RuntimeMenuDevicesActionType_DragAndDrop;
+    keys << "NetworkSettings";       values << RuntimeMenuDevicesActionType_NetworkSettings;
+    keys << "SharedFoldersSettings"; values << RuntimeMenuDevicesActionType_SharedFoldersSettings;
+    keys << "VRDEServer";            values << RuntimeMenuDevicesActionType_VRDEServer;
+    keys << "VideoCapture";          values << RuntimeMenuDevicesActionType_VideoCapture;
+    keys << "InstallGuestTools";     values << RuntimeMenuDevicesActionType_InstallGuestTools;
+    keys << "All";                   values << RuntimeMenuDevicesActionType_All;
+    /* Invalid type for unknown words: */
+    if (!keys.contains(strRuntimeMenuDevicesActionType, Qt::CaseInsensitive))
+        return RuntimeMenuDevicesActionType_Invalid;
+    /* Corresponding type for known words: */
+    return values.at(keys.indexOf(QRegExp(strRuntimeMenuDevicesActionType, Qt::CaseInsensitive)));
+}
+
+#ifdef VBOX_WITH_DEBUGGER_GUI
+/* QString <= RuntimeMenuDebuggerActionType: */
+template<> QString toInternalString(const RuntimeMenuDebuggerActionType &runtimeMenuDebuggerActionType)
+{
+    QString strResult;
+    switch (runtimeMenuDebuggerActionType)
+    {
+        case RuntimeMenuDebuggerActionType_Statistics:  strResult = "Statistics"; break;
+        case RuntimeMenuDebuggerActionType_CommandLine: strResult = "CommandLine"; break;
+        case RuntimeMenuDebuggerActionType_Logging:     strResult = "Logging"; break;
+        case RuntimeMenuDebuggerActionType_LogDialog:   strResult = "LogDialog"; break;
+        case RuntimeMenuDebuggerActionType_All:         strResult = "All"; break;
+        default:
+        {
+            AssertMsgFailed(("No text for action type=%d", runtimeMenuDebuggerActionType));
+            break;
+        }
+    }
+    return strResult;
+}
+
+/* RuntimeMenuDebuggerActionType <= QString: */
+template<> RuntimeMenuDebuggerActionType fromInternalString<RuntimeMenuDebuggerActionType>(const QString &strRuntimeMenuDebuggerActionType)
+{
+    /* Here we have some fancy stuff allowing us
+     * to search through the keys using 'case-insensitive' rule: */
+    QStringList keys;      QList<RuntimeMenuDebuggerActionType> values;
+    keys << "Statistics";  values << RuntimeMenuDebuggerActionType_Statistics;
+    keys << "CommandLine"; values << RuntimeMenuDebuggerActionType_CommandLine;
+    keys << "Logging";     values << RuntimeMenuDebuggerActionType_Logging;
+    keys << "LogDialog";   values << RuntimeMenuDebuggerActionType_LogDialog;
+    keys << "All";         values << RuntimeMenuDebuggerActionType_All;
+    /* Invalid type for unknown words: */
+    if (!keys.contains(strRuntimeMenuDebuggerActionType, Qt::CaseInsensitive))
+        return RuntimeMenuDebuggerActionType_Invalid;
+    /* Corresponding type for known words: */
+    return values.at(keys.indexOf(QRegExp(strRuntimeMenuDebuggerActionType, Qt::CaseInsensitive)));
+}
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+
+/* QString <= RuntimeMenuHelpActionType: */
+template<> QString toInternalString(const RuntimeMenuHelpActionType &runtimeMenuHelpActionType)
+{
+    QString strResult;
+    switch (runtimeMenuHelpActionType)
+    {
+        case RuntimeMenuHelpActionType_Contents:             strResult = "Contents"; break;
+        case RuntimeMenuHelpActionType_WebSite:              strResult = "WebSite"; break;
+        case RuntimeMenuHelpActionType_ResetWarnings:        strResult = "ResetWarnings"; break;
+#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
+        case RuntimeMenuHelpActionType_NetworkAccessManager: strResult = "NetworkAccessManager"; break;
+#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
+#ifndef Q_WS_MAC
+        case RuntimeMenuHelpActionType_About:                strResult = "About"; break;
+#endif /* !Q_WS_MAC */
+        case RuntimeMenuHelpActionType_All:                  strResult = "All"; break;
+        default:
+        {
+            AssertMsgFailed(("No text for action type=%d", runtimeMenuHelpActionType));
+            break;
+        }
+    }
+    return strResult;
+}
+
+/* RuntimeMenuHelpActionType <= QString: */
+template<> RuntimeMenuHelpActionType fromInternalString<RuntimeMenuHelpActionType>(const QString &strRuntimeMenuHelpActionType)
+{
+    /* Here we have some fancy stuff allowing us
+     * to search through the keys using 'case-insensitive' rule: */
+    QStringList keys;               QList<RuntimeMenuHelpActionType> values;
+    keys << "Contents";             values << RuntimeMenuHelpActionType_Contents;
+    keys << "WebSite";              values << RuntimeMenuHelpActionType_WebSite;
+    keys << "ResetWarnings";        values << RuntimeMenuHelpActionType_ResetWarnings;
+#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
+    keys << "NetworkAccessManager"; values << RuntimeMenuHelpActionType_NetworkAccessManager;
+#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
+#ifndef Q_WS_MAC
+    keys << "About";                values << RuntimeMenuHelpActionType_About;
+#endif /* !Q_WS_MAC */
+    keys << "All";                  values << RuntimeMenuHelpActionType_All;
+    /* Invalid type for unknown words: */
+    if (!keys.contains(strRuntimeMenuHelpActionType, Qt::CaseInsensitive))
+        return RuntimeMenuHelpActionType_Invalid;
+    /* Corresponding type for known words: */
+    return values.at(keys.indexOf(QRegExp(strRuntimeMenuHelpActionType, Qt::CaseInsensitive)));
+}
+
 /* QString <= UIVisualStateType: */
 template<> QString toInternalString(const UIVisualStateType &visualStateType)
 {
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.h b/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.h
index 5321dd6..483d48d 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.h
+++ b/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.h
@@ -9,7 +9,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -48,18 +48,18 @@
 
     // ...
 
-    QVector <LONG> in (3);
-    in [0] = -1;
-    in [1] = -2;
-    in [2] = -3;
+    QVector<LONG> in(3);
+    in[0] = -1;
+    in[1] = -2;
+    in[2] = -3;
 
-    QVector <LONG> out;
-    QVector <LONG> ret;
+    QVector<LONG> out;
+    QVector<LONG> ret;
 
-    ret = component.TestArrays (in, out);
+    ret = component.TestArrays(in, out);
 
     for (size_t i = 0; i < ret.size(); ++ i)
-        LogFlow (("*** ret[%u]=%d\n", i, ret [i]));
+        LogFlow(("*** ret[%u]=%d\n", i, ret[i]));
 
  * @endcode
  * @}
@@ -87,9 +87,9 @@
  * Additional COM / XPCOM defines and includes
  */
 
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
 #include <nsXPCOM.h>
 #include <nsMemory.h>
@@ -97,15 +97,15 @@
 
 class XPCOMEventQSocketListener;
 
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
 
 /* VirtualBox interfaces declarations */
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
     #include <VirtualBox.h>
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
     #include <VirtualBox_XPCOM.h>
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -169,7 +169,7 @@ private:
 
     void fetchFromCurrentThread(IUnknown *callee, const GUID *calleeIID);
 
-    static QString getInterfaceNameFromIID (const QUuid &id);
+    static QString getInterfaceNameFromIID(const QUuid &id);
 
     bool mIsNull : 1;
     bool mIsBasicAvailable : 1;
@@ -209,151 +209,151 @@ public:
      */
     HRESULT lastRC() const { return mRC; }
 
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
 
     /** Converts a GUID value to QUuid */
-    static QUuid ToQUuid (const GUID &id)
+    static QUuid ToQUuid(const GUID &id)
     {
-        return QUuid (id.Data1, id.Data2, id.Data3,
-                      id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
-                      id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
+        return QUuid(id.Data1, id.Data2, id.Data3,
+                     id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
+                     id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
     }
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
     /** Converts a GUID value to QUuid */
-    static QUuid ToQUuid (const nsID &id)
+    static QUuid ToQUuid(const nsID &id)
     {
-        return QUuid (id.m0, id.m1, id.m2,
-                      id.m3[0], id.m3[1], id.m3[2], id.m3[3],
-                      id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
+        return QUuid(id.m0, id.m1, id.m2,
+                     id.m3[0], id.m3[1], id.m3[2], id.m3[3],
+                     id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
     }
 
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
     /* Arrays of arbitrary types */
 
     template <typename QT, typename CT>
-    static void ToSafeArray (const QVector <QT> &aVec, com::SafeArray <CT> &aArr)
+    static void ToSafeArray(const QVector<QT> &aVec, com::SafeArray<CT> &aArr)
     {
-        aArr.reset (aVec.size());
+        aArr.reset(aVec.size());
         for (int i = 0; i < aVec.size(); ++i)
-            aArr [i] = static_cast<CT> (aVec.at (i));
+            aArr[i] = static_cast<CT>(aVec.at(i));
     }
 
     template <typename CT, typename QT>
-    static void FromSafeArray (const com::SafeArray <CT> &aArr, QVector <QT> &aVec)
+    static void FromSafeArray(const com::SafeArray<CT> &aArr, QVector<QT> &aVec)
     {
-        aVec.resize (static_cast<int> (aArr.size()));
+        aVec.resize(static_cast<int>(aArr.size()));
         for (int i = 0; i < aVec.size(); ++i)
-            aVec [i] = static_cast<QT> (aArr [i]);
+            aVec[i] = static_cast<QT>(aArr[i]);
     }
 
     template <typename QT, typename CT>
-    static void ToSafeArray (const QVector <QT *> &aVec, com::SafeArray <CT *> &aArr)
+    static void ToSafeArray(const QVector<QT *> &aVec, com::SafeArray<CT *> &aArr)
     {
-        Q_UNUSED (aVec);
-        Q_UNUSED (aArr);
-        AssertMsgFailedReturnVoid (("No conversion!\n"));
+        Q_UNUSED(aVec);
+        Q_UNUSED(aArr);
+        AssertMsgFailedReturnVoid(("No conversion!\n"));
     }
 
     template <typename CT, typename QT>
-    static void FromSafeArray (const com::SafeArray <CT *> &aArr, QVector <QT *> &aVec)
+    static void FromSafeArray(const com::SafeArray<CT *> &aArr, QVector<QT *> &aVec)
     {
-        Q_UNUSED (aArr);
-        Q_UNUSED (aVec);
-        AssertMsgFailedReturnVoid (("No conversion!\n"));
+        Q_UNUSED(aArr);
+        Q_UNUSED(aVec);
+        AssertMsgFailedReturnVoid(("No conversion!\n"));
     }
 
     /* Arrays of equal types */
 
     template <typename T>
-    static void ToSafeArray (const QVector <T> &aVec, com::SafeArray <T> &aArr)
+    static void ToSafeArray(const QVector<T> &aVec, com::SafeArray<T> &aArr)
     {
-        aArr.reset (aVec.size());
+        aArr.reset(aVec.size());
         for (int i = 0; i < aVec.size(); ++i)
-            aArr [i] = aVec.at (i);
+            aArr[i] = aVec.at(i);
     }
 
     template <typename T>
-    static void FromSafeArray (const com::SafeArray <T> &aArr, QVector <T> &aVec)
+    static void FromSafeArray(const com::SafeArray<T> &aArr, QVector<T> &aVec)
     {
-        aVec.resize (static_cast<int> (aArr.size()));
+        aVec.resize(static_cast<int>(aArr.size()));
         for (int i = 0; i < aVec.size(); ++i)
-            aVec [i] = aArr [i];
+            aVec[i] = aArr[i];
     }
 
     /* Arrays of strings */
 
-    static void ToSafeArray (const QVector <QString> &aVec,
-                             com::SafeArray <BSTR> &aArr);
-    static void FromSafeArray (const com::SafeArray <BSTR> &aArr,
-                               QVector <QString> &aVec);
+    static void ToSafeArray(const QVector<QString> &aVec,
+                            com::SafeArray<BSTR> &aArr);
+    static void FromSafeArray(const com::SafeArray<BSTR> &aArr,
+                              QVector<QString> &aVec);
 
     /* Arrays of GUID */
 
-    static void ToSafeArray (const QVector <QUuid> &aVec,
-                             com::SafeGUIDArray &aArr);
-    static void FromSafeArray (const com::SafeGUIDArray &aArr,
-                               QVector <QUuid> &aVec);
+    static void ToSafeArray(const QVector<QUuid> &aVec,
+                            com::SafeGUIDArray &aArr);
+    static void FromSafeArray(const com::SafeGUIDArray &aArr,
+                              QVector<QUuid> &aVec);
 
     /* Arrays of enums. Does a cast similar to what ENUMOut does. */
 
     template <typename QE, typename CE>
-    static void ToSafeArray (const QVector <QE> &aVec,
-                             com::SafeIfaceArray <CE> &aArr)
+    static void ToSafeArray(const QVector<QE> &aVec,
+                            com::SafeIfaceArray<CE> &aArr)
     {
-        aArr.reset (static_cast <int> (aVec.size()));
+        aArr.reset(static_cast<int>(aVec.size()));
         for (int i = 0; i < aVec.size(); ++i)
-            aArr [i] = static_cast <CE> (aVec.at (i));
+            aArr[i] = static_cast<CE>(aVec.at(i));
     }
 
     template <typename CE, typename QE>
-    static void FromSafeArray (const com::SafeIfaceArray <CE> &aArr,
-                               QVector <QE> &aVec)
+    static void FromSafeArray(const com::SafeIfaceArray<CE> &aArr,
+                              QVector<QE> &aVec)
     {
-        aVec.resize (static_cast <int> (aArr.size()));
+        aVec.resize(static_cast<int>(aArr.size()));
         for (int i = 0; i < aVec.size(); ++i)
-            aVec [i] = static_cast <QE> (aArr [i]);
+            aVec[i] = static_cast<QE>(aArr[i]);
     }
 
     /* Arrays of interface pointers. Note: we need a separate pair of names
      * only because the MSVC8 template matching algorithm is poor and tries to
-     * instantiate a com::SafeIfaceArray <BSTR> (!!!) template otherwise for
+     * instantiate a com::SafeIfaceArray<BSTR> (!!!) template otherwise for
      * *no* reason and fails. Note that it's also not possible to choose the
      * correct function by specifying template arguments explicitly because then
-     * it starts to try to instantiate the com::SafeArray <I> template for
+     * it starts to try to instantiate the com::SafeArray<I> template for
      * *no* reason again and fails too. Definitely, broken. Works in GCC like a
      * charm. */
 
     template <class CI, class I>
-    static void ToSafeIfaceArray (const QVector <CI> &aVec,
-                                  com::SafeIfaceArray <I> &aArr)
+    static void ToSafeIfaceArray(const QVector<CI> &aVec,
+                                 com::SafeIfaceArray<I> &aArr)
     {
-        aArr.reset (static_cast<int> (aVec.size()));
+        aArr.reset(static_cast<int>(aVec.size()));
         for (int i = 0; i < aVec.size(); ++i)
         {
-            aArr [i] = aVec.at (i).raw();
-            if (aArr [i])
-                aArr [i]->AddRef();
+            aArr[i] = aVec.at(i).raw();
+            if (aArr[i])
+                aArr[i]->AddRef();
         }
     }
 
     template <class I, class CI>
-    static void FromSafeIfaceArray (const com::SafeIfaceArray <I> &aArr,
-                                    QVector <CI> &aVec)
+    static void FromSafeIfaceArray(const com::SafeIfaceArray<I> &aArr,
+                                   QVector<CI> &aVec)
     {
-        aVec.resize (static_cast<int> (aArr.size()));
+        aVec.resize(static_cast<int>(aArr.size()));
         for (int i = 0; i < aVec.size(); ++i)
-            aVec [i].attach (aArr [i]);
+            aVec[i].attach(aArr[i]);
     }
 
 protected:
 
     /* no arbitrary instance creations */
-    COMBase() : mRC (S_OK) {}
+    COMBase() : mRC(S_OK) {}
 
-#if defined (VBOX_WITH_XPCOM)
+#if defined(VBOX_WITH_XPCOM)
     static XPCOMEventQSocketListener *sSocketListener;
 #endif
 
@@ -362,13 +362,13 @@ protected:
     {
     public:
 
-        BSTRIn (const QString &s) : bstr (SysAllocString ((const OLECHAR *)
+        BSTRIn(const QString &s) : bstr(SysAllocString((const OLECHAR *)
             (s.isNull() ? 0 : s.utf16()))) {}
 
         ~BSTRIn()
         {
             if (bstr)
-                SysFreeString (bstr);
+                SysFreeString(bstr);
         }
 
         operator BSTR() const { return bstr; }
@@ -383,13 +383,13 @@ protected:
     {
     public:
 
-        BSTROut (QString &s) : str (s), bstr (0) {}
+        BSTROut(QString &s) : str(s), bstr(0) {}
 
         ~BSTROut()
         {
             if (bstr) {
-                str = QString::fromUtf16 (bstr);
-                SysFreeString (bstr);
+                str = QString::fromUtf16(bstr);
+                SysFreeString(bstr);
             }
         }
 
@@ -412,8 +412,8 @@ protected:
     {
     public:
 
-        ENUMOut (QE &e) : qe (e), ce ((CE) 0) {}
-        ~ENUMOut() { qe = (QE) ce; }
+        ENUMOut(QE &e) : qe(e), ce((CE)0) {}
+        ~ENUMOut() { qe = (QE)ce; }
         operator CE *() { return &ce; }
 
     private:
@@ -422,24 +422,24 @@ protected:
         CE ce;
     };
 
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
 
     /** Adapter to pass QUuid as input GUID params */
-    static GUID GUIDIn (const QUuid &uuid) { return uuid; }
+    static GUID GUIDIn(const QUuid &uuid) { return uuid; }
 
     /** Adapter to pass QUuid as output GUID params */
     class GUIDOut
     {
     public:
 
-        GUIDOut (QUuid &id) : uuid (id)
+        GUIDOut(QUuid &id) : uuid(id)
         {
-            ::memset (&guid, 0, sizeof (GUID));
+            ::memset(&guid, 0, sizeof(GUID));
         }
 
         ~GUIDOut()
         {
-            uuid = QUuid (
+            uuid = QUuid(
                 guid.Data1, guid.Data2, guid.Data3,
                 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
                 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
@@ -453,10 +453,10 @@ protected:
         GUID guid;
     };
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
     /** Adapter to pass QUuid as input GUID params */
-    static const nsID &GUIDIn (const QUuid &uuid)
+    static const nsID &GUIDIn(const QUuid &uuid)
     {
         return *(const nsID *) &uuid;
     }
@@ -466,17 +466,17 @@ protected:
     {
     public:
 
-        GUIDOut (QUuid &id) : uuid (id), nsid (0) {}
+        GUIDOut(QUuid &id) : uuid(id), nsid(0) {}
 
         ~GUIDOut()
         {
             if (nsid)
             {
-                uuid = QUuid (
+                uuid = QUuid(
                     nsid->m0, nsid->m1, nsid->m2,
                     nsid->m3[0], nsid->m3[1], nsid->m3[2], nsid->m3[3],
                     nsid->m3[4], nsid->m3[5], nsid->m3[6], nsid->m3[7]);
-                nsMemory::Free (nsid);
+                nsMemory::Free(nsid);
             }
         }
 
@@ -488,10 +488,10 @@ protected:
         nsID *nsid;
     };
 
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
-    static void addref (IUnknown *aIface) { if (aIface) aIface->AddRef(); }
-    static void release (IUnknown *aIface) { if (aIface) aIface->Release(); }
+    static void addref(IUnknown *aIface) { if (aIface) aIface->AddRef(); }
+    static void release(IUnknown *aIface) { if (aIface) aIface->Release(); }
 
 protected:
 
@@ -522,13 +522,13 @@ public:
 protected:
 
     /* no arbitrary instance creation */
-    COMBaseWithEI() : COMBase () {};
+    COMBaseWithEI() : COMBase() {};
 
-    void setErrorInfo (const COMErrorInfo &aErrInfo) { mErrInfo = aErrInfo; }
+    void setErrorInfo(const COMErrorInfo &aErrInfo) { mErrInfo = aErrInfo; }
 
-    void fetchErrorInfo (IUnknown *aCallee, const GUID *aCalleeIID) const
+    void fetchErrorInfo(IUnknown *aCallee, const GUID *aCalleeIID) const
     {
-        mErrInfo.fetchFromCurrentThread (aCallee, aCalleeIID);
+        mErrInfo.fetchFromCurrentThread(aCallee, aCalleeIID);
     }
 
     mutable COMErrorInfo mErrInfo;
@@ -543,13 +543,13 @@ class COMResult
 {
 public:
 
-    COMResult() : mRC (S_OK) {}
+    COMResult() : mRC(S_OK) {}
 
     /**
      * Queries the current result code from the given component.
      */
-    explicit COMResult (const COMBase &aComponent)
-        : mRC (aComponent.lastRC()) {}
+    explicit COMResult(const COMBase &aComponent)
+        : mRC(aComponent.lastRC()) {}
 
     /**
      * Queries the current result code and error info from the given component.
@@ -562,7 +562,7 @@ public:
     /**
      * Queries the current result code from the given component.
      */
-    COMResult &operator= (const COMBase &aComponent)
+    COMResult &operator=(const COMBase &aComponent)
     {
         mRC = aComponent.lastRC();
         return *this;
@@ -571,7 +571,7 @@ public:
     /**
      * Queries the current result code and error info from the given component.
      */
-    COMResult &operator= (const COMBaseWithEI &aComponent)
+    COMResult &operator=(const COMBaseWithEI &aComponent)
     {
         mRC = aComponent.lastRC();
         mErrInfo = aComponent.errorInfo();
@@ -584,13 +584,13 @@ public:
      * Returns @c true if the result code represents success (with or without
      * warnings).
      */
-    bool isOk() const { return SUCCEEDED (mRC); }
+    bool isOk() const { return SUCCEEDED(mRC); }
 
     /**
      * Returns @c true if the result code represents success with one or more
      * warnings.
      */
-    bool isWarning() const { return SUCCEEDED_WARNING (mRC); }
+    bool isWarning() const { return SUCCEEDED_WARNING(mRC); }
 
     /**
      * Returns @c true if the result code represents success with no warnings.
@@ -634,18 +634,18 @@ public:
         clear();
     }
 
-    CInterface (const CInterface &that) : B (that)
+    CInterface(const CInterface &that) : B(that)
     {
         clear();
         mIface = that.mIface;
         this->addref(ptr());
     }
 
-    CInterface (I *aIface)
+    CInterface(I *aIface)
     {
         clear();
-        setPtr (aIface);
-        this->addref (aIface);
+        setPtr(aIface);
+        this->addref(aIface);
     }
 
     virtual ~CInterface()
@@ -657,24 +657,24 @@ public:
     }
 
     // utility methods
-    void createInstance (const CLSID &aClsId)
+    void createInstance(const CLSID &aClsId)
     {
-        AssertMsg (ptr() == NULL, ("Instance is already non-NULL\n"));
+        AssertMsg(ptr() == NULL, ("Instance is already non-NULL\n"));
         if (ptr() == NULL)
         {
             I* pObj = NULL;
-#if !defined (VBOX_WITH_XPCOM)
-            B::mRC = CoCreateInstance (aClsId, NULL, CLSCTX_ALL,
-                                       _ATL_IIDOF (I), (void **) &pObj);
+#if !defined(VBOX_WITH_XPCOM)
+            B::mRC = CoCreateInstance(aClsId, NULL, CLSCTX_ALL,
+                                      _ATL_IIDOF(I), (void **)&pObj);
 #else
-            nsCOMPtr <nsIComponentManager> manager;
-            B::mRC = NS_GetComponentManager (getter_AddRefs (manager));
-            if (SUCCEEDED (B::mRC))
-                B::mRC = manager->CreateInstance (aClsId, nsnull, NS_GET_IID (I),
-                                                  (void **) &pObj);
+            nsCOMPtr<nsIComponentManager> manager;
+            B::mRC = NS_GetComponentManager(getter_AddRefs(manager));
+            if (SUCCEEDED(B::mRC))
+                B::mRC = manager->CreateInstance(aClsId, nsnull, NS_GET_IID(I),
+                                                 (void **)&pObj);
 #endif
 
-            if (SUCCEEDED (B::mRC))
+            if (SUCCEEDED(B::mRC))
                setPtr(pObj);
             else
                setPtr(NULL);
@@ -682,7 +682,7 @@ public:
             /* fetch error info, but don't assert if it's missing -- many other
              * reasons can lead to an error (w/o providing error info), not only
              * the instance initialization code (that should always provide it) */
-            B::fetchErrorInfo (NULL, NULL);
+            B::fetchErrorInfo(NULL, NULL);
          }
     }
 
@@ -691,20 +691,20 @@ public:
      * interface on it. The operation may fail.
      */
     template <class OI>
-    void attach (OI *aIface)
+    void attach(OI *aIface)
     {
 #ifdef DEBUG
         Assert(!mDead);
 #endif
         /* be aware of self assignment */
         I* amIface = ptr();
-        this->addref (aIface);
-        this->release (amIface);
+        this->addref(aIface);
+        this->release(amIface);
         if (aIface)
         {
             amIface = NULL;
-            B::mRC = aIface->QueryInterface (COM_IIDOF (I), (void **) &amIface);
-            this->release (aIface);
+            B::mRC = aIface->QueryInterface(COM_IIDOF(I), (void **)&amIface);
+            this->release(aIface);
             setPtr(amIface);
         }
         else
@@ -715,14 +715,14 @@ public:
     };
 
     /** Specialization of attach() for our own interface I. Never fails. */
-    void attach (I *aIface)
+    void attach(I *aIface)
     {
 #ifdef DEBUG
         Assert(!mDead);
 #endif
         /* be aware of self assignment */
-        this->addref (aIface);
-        this->release (ptr());
+        this->addref(aIface);
+        this->release(ptr());
         setPtr(aIface);
         B::mRC = S_OK;
     };
@@ -733,7 +733,7 @@ public:
 #ifdef DEBUG
        Assert(!mDead);
 #endif
-       this->release (ptr());
+       this->release(ptr());
        setPtr(NULL);
     }
 
@@ -750,13 +750,13 @@ public:
      * Returns @c true if the result code represents success (with or without
      * warnings).
      */
-    bool isOk() const { return !isNull() && SUCCEEDED (B::mRC); }
+    bool isOk() const { return !isNull() && SUCCEEDED(B::mRC); }
 
     /**
      * Returns @c true if the result code represents success with one or more
      * warnings.
      */
-    bool isWarning() const { return !isNull() && SUCCEEDED_WARNING (B::mRC); }
+    bool isWarning() const { return !isNull() && SUCCEEDED_WARNING(B::mRC); }
 
     /**
      * Returns @c true if the result code represents success with no warnings.
@@ -765,16 +765,16 @@ public:
 
     // utility operators
 
-    CInterface &operator= (const CInterface &that)
+    CInterface &operator=(const CInterface &that)
     {
-        attach (that.ptr());
-        B::operator= (that);
+        attach(that.ptr());
+        B::operator=(that);
         return *this;
     }
 
-    CInterface &operator= (I *aIface)
+    CInterface &operator=(I *aIface)
     {
-        attach (aIface);
+        attach(aIface);
         return *this;
     }
 
@@ -787,8 +787,8 @@ public:
        return ptr();
     }
 
-    bool operator== (const CInterface &that) const { return ptr() == that.ptr(); }
-    bool operator!= (const CInterface &that) const { return ptr() != that.ptr(); }
+    bool operator==(const CInterface &that) const { return ptr() == that.ptr(); }
+    bool operator!=(const CInterface &that) const { return ptr() != that.ptr(); }
 
     I* ptr() const
     {
@@ -824,73 +824,73 @@ private:
 
 /////////////////////////////////////////////////////////////////////////////
 
-class CUnknown : public CInterface <IUnknown, COMBaseWithEI>
+class CUnknown : public CInterface<IUnknown, COMBaseWithEI>
 {
 public:
 
-    typedef CInterface <IUnknown, COMBaseWithEI> Base;
+    typedef CInterface<IUnknown, COMBaseWithEI> Base;
 
     CUnknown() {}
 
     /** Creates an instance given another CInterface-based instance. */
     template <class OI, class OB>
-    explicit CUnknown (const CInterface <OI, OB> &that)
+    explicit CUnknown(const CInterface<OI, OB> &that)
     {
-        attach (that.ptr());
-        if (SUCCEEDED (mRC))
+        attach(that.ptr());
+        if (SUCCEEDED(mRC))
         {
             /* preserve old error info if any */
             mRC = that.lastRC();
-            setErrorInfo (that.errorInfo());
+            setErrorInfo(that.errorInfo());
         }
     }
 
     /** Constructor specialization for IUnknown. */
-    CUnknown (const CUnknown &that) : Base (that) {}
+    CUnknown(const CUnknown &that) : Base(that) {}
 
     /** Creates an instance given a foreign interface pointer. */
     template <class OI>
-    explicit CUnknown (OI *aIface)
+    explicit CUnknown(OI *aIface)
     {
-        attach (aIface);
+        attach(aIface);
     }
 
     /** Constructor specialization for IUnknown. */
-    explicit CUnknown (IUnknown *aIface) : Base (aIface) {}
+    explicit CUnknown(IUnknown *aIface) : Base(aIface) {}
 
     /** Assigns from another CInterface-based instance. */
     template <class OI, class OB>
-    CUnknown &operator= (const CInterface <OI, OB> &that)
+    CUnknown &operator=(const CInterface<OI, OB> &that)
     {
-        attach (that.ptr());
-        if (SUCCEEDED (mRC))
+        attach(that.ptr());
+        if (SUCCEEDED(mRC))
         {
             /* preserve old error info if any */
             mRC = that.lastRC();
-            setErrorInfo (that.errorInfo());
+            setErrorInfo(that.errorInfo());
         }
         return *this;
     }
 
     /** Assignment specialization for CUnknown. */
-    CUnknown &operator= (const CUnknown &that)
+    CUnknown &operator=(const CUnknown &that)
     {
-        Base::operator= (that);
+        Base::operator=(that);
         return *this;
     }
 
     /** Assigns from a foreign interface pointer. */
     template <class OI>
-    CUnknown &operator= (OI *aIface)
+    CUnknown &operator=(OI *aIface)
     {
-        attach (aIface);
+        attach(aIface);
         return *this;
     }
 
     /** Assignment specialization for IUnknown. */
-    CUnknown &operator= (IUnknown *aIface)
+    CUnknown &operator=(IUnknown *aIface)
     {
-        Base::operator= (aIface);
+        Base::operator=(aIface);
         return *this;
     }
 };
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.cpp b/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.cpp
index 1fad0f0..b4c4cf8 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.cpp
@@ -51,6 +51,16 @@ const char* UIDefs::GUI_HideDetails = "GUI/HideDetails";
 
 /* Machine-window definitions: */
 const char* UIDefs::GUI_RestrictedRuntimeMenus = "GUI/RestrictedRuntimeMenus";
+#ifdef Q_WS_MAC
+const char* UIDefs::GUI_RestrictedRuntimeApplicationMenuActions = "GUI/RestrictedRuntimeApplicationMenuActions";
+#endif /* Q_WS_MAC */
+const char* UIDefs::GUI_RestrictedRuntimeMachineMenuActions = "GUI/RestrictedRuntimeMachineMenuActions";
+const char* UIDefs::GUI_RestrictedRuntimeViewMenuActions = "GUI/RestrictedRuntimeViewMenuActions";
+const char* UIDefs::GUI_RestrictedRuntimeDevicesMenuActions = "GUI/RestrictedRuntimeDevicesMenuActions";
+#ifdef VBOX_WITH_DEBUGGER_GUI
+const char* UIDefs::GUI_RestrictedRuntimeDebuggerMenuActions = "GUI/RestrictedRuntimeDebuggerMenuActions";
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+const char* UIDefs::GUI_RestrictedRuntimeHelpMenuActions = "GUI/RestrictedRuntimeHelpMenuActions";
 const char* UIDefs::GUI_RestrictedVisualStates = "GUI/RestrictedVisualStates";
 const char* UIDefs::GUI_Input_MachineShortcuts = "GUI/Input/MachineShortcuts";
 const char* UIDefs::GUI_LastNormalWindowPosition = "GUI/LastNormalWindowPosition";
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.h b/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.h
index 4136179..9f6b479 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.h
+++ b/src/VBox/Frontends/VirtualBox/src/globals/UIDefs.h
@@ -120,6 +120,16 @@ namespace UIDefs
 
     /* Machine-window declarations: */
     extern const char* GUI_RestrictedRuntimeMenus;
+#ifdef Q_WS_MAC
+    extern const char* GUI_RestrictedRuntimeApplicationMenuActions;
+#endif /* Q_WS_MAC */
+    extern const char* GUI_RestrictedRuntimeMachineMenuActions;
+    extern const char* GUI_RestrictedRuntimeViewMenuActions;
+    extern const char* GUI_RestrictedRuntimeDevicesMenuActions;
+#ifdef VBOX_WITH_DEBUGGER_GUI
+    extern const char* GUI_RestrictedRuntimeDebuggerMenuActions;
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+    extern const char* GUI_RestrictedRuntimeHelpMenuActions;
     extern const char* GUI_RestrictedVisualStates;
     extern const char* GUI_Input_MachineShortcuts;
     extern const char* GUI_LastNormalWindowPosition;
@@ -264,6 +274,100 @@ enum RuntimeMenuType
     RuntimeMenuType_All     = 0xFF
 };
 
+#ifdef Q_WS_MAC
+/** Runtime UI: Application menu: Action types. */
+enum RuntimeMenuApplicationActionType
+{
+    RuntimeMenuApplicationActionType_Invalid = 0,
+    RuntimeMenuApplicationActionType_About   = RT_BIT(0),
+    RuntimeMenuApplicationActionType_All     = 0xFFFF
+};
+#endif /* Q_WS_MAC */
+
+/** Runtime UI: Machine menu: Action types. */
+enum RuntimeMenuMachineActionType
+{
+    RuntimeMenuMachineActionType_Invalid           = 0,
+    RuntimeMenuMachineActionType_SettingsDialog    = RT_BIT(0),
+    RuntimeMenuMachineActionType_TakeSnapshot      = RT_BIT(1),
+    RuntimeMenuMachineActionType_TakeScreenshot    = RT_BIT(2),
+    RuntimeMenuMachineActionType_InformationDialog = RT_BIT(3),
+    RuntimeMenuMachineActionType_MouseIntegration  = RT_BIT(4),
+    RuntimeMenuMachineActionType_TypeCAD           = RT_BIT(5),
+#ifdef Q_WS_X11
+    RuntimeMenuMachineActionType_TypeCABS          = RT_BIT(6),
+#endif /* Q_WS_X11 */
+    RuntimeMenuMachineActionType_Pause             = RT_BIT(7),
+    RuntimeMenuMachineActionType_Reset             = RT_BIT(8),
+    RuntimeMenuMachineActionType_SaveState         = RT_BIT(9),
+    RuntimeMenuMachineActionType_Shutdown          = RT_BIT(10),
+    RuntimeMenuMachineActionType_PowerOff          = RT_BIT(11),
+#ifndef Q_WS_MAC
+    RuntimeMenuMachineActionType_Close             = RT_BIT(12),
+#endif /* !Q_WS_MAC */
+    RuntimeMenuMachineActionType_All               = 0xFFFF
+};
+
+/** Runtime UI: View menu: Action types. */
+enum RuntimeMenuViewActionType
+{
+    RuntimeMenuViewActionType_Invalid         = 0,
+    RuntimeMenuViewActionType_Fullscreen      = RT_BIT(0),
+    RuntimeMenuViewActionType_Seamless        = RT_BIT(1),
+    RuntimeMenuViewActionType_Scale           = RT_BIT(2),
+    RuntimeMenuViewActionType_GuestAutoresize = RT_BIT(3),
+    RuntimeMenuViewActionType_AdjustWindow    = RT_BIT(4),
+    RuntimeMenuViewActionType_Multiscreen     = RT_BIT(5),
+    RuntimeMenuViewActionType_All             = 0xFFFF
+};
+
+/** Runtime UI: Devices menu: Action types. */
+enum RuntimeMenuDevicesActionType
+{
+    RuntimeMenuDevicesActionType_Invalid               = 0,
+    RuntimeMenuDevicesActionType_OpticalDevices        = RT_BIT(0),
+    RuntimeMenuDevicesActionType_FloppyDevices         = RT_BIT(1),
+    RuntimeMenuDevicesActionType_USBDevices            = RT_BIT(2),
+    RuntimeMenuDevicesActionType_WebCams               = RT_BIT(3),
+    RuntimeMenuDevicesActionType_SharedClipboard       = RT_BIT(4),
+    RuntimeMenuDevicesActionType_DragAndDrop           = RT_BIT(5),
+    RuntimeMenuDevicesActionType_NetworkSettings       = RT_BIT(6),
+    RuntimeMenuDevicesActionType_SharedFoldersSettings = RT_BIT(7),
+    RuntimeMenuDevicesActionType_VRDEServer            = RT_BIT(8),
+    RuntimeMenuDevicesActionType_VideoCapture          = RT_BIT(9),
+    RuntimeMenuDevicesActionType_InstallGuestTools     = RT_BIT(10),
+    RuntimeMenuDevicesActionType_All                   = 0xFFFF
+};
+
+#ifdef VBOX_WITH_DEBUGGER_GUI
+/** Runtime UI: Debugger menu: Action types. */
+enum RuntimeMenuDebuggerActionType
+{
+    RuntimeMenuDebuggerActionType_Invalid     = 0,
+    RuntimeMenuDebuggerActionType_Statistics  = RT_BIT(0),
+    RuntimeMenuDebuggerActionType_CommandLine = RT_BIT(1),
+    RuntimeMenuDebuggerActionType_Logging     = RT_BIT(2),
+    RuntimeMenuDebuggerActionType_LogDialog   = RT_BIT(3),
+    RuntimeMenuDebuggerActionType_All         = 0xFFFF
+};
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+
+/** Runtime UI: Help menu: Action types. */
+enum RuntimeMenuHelpActionType
+{
+    RuntimeMenuHelpActionType_Invalid              = 0,
+    RuntimeMenuHelpActionType_Contents             = RT_BIT(0),
+    RuntimeMenuHelpActionType_WebSite              = RT_BIT(1),
+    RuntimeMenuHelpActionType_ResetWarnings        = RT_BIT(2),
+#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
+    RuntimeMenuHelpActionType_NetworkAccessManager = RT_BIT(3),
+#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
+#ifndef Q_WS_MAC
+    RuntimeMenuHelpActionType_About                = RT_BIT(4),
+#endif /* !Q_WS_MAC */
+    RuntimeMenuHelpActionType_All                  = 0xFFFF
+};
+
 /* Runtime UI visual-state types: */
 enum UIVisualStateType
 {
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp b/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp
index 4bf679b..852b63c 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp
@@ -294,9 +294,10 @@ void UIPopupCenter::showPopupPane(QWidget *pParent, const QString &strPopupPaneI
             buttonDescriptions[iButton1] = strButtonText1;
         if (iButton2 != 0)
             buttonDescriptions[iButton2] = strButtonText2;
+        if (fProposeAutoConfirmation)
+            buttonDescriptions[AlertButton_Cancel | AlertOption_AutoConfirmed] = QString();
         /* Create new one: */
-        pPopupStack->createPopupPane(strPopupPaneID, strMessage, strDetails,
-                                     buttonDescriptions, fProposeAutoConfirmation);
+        pPopupStack->createPopupPane(strPopupPaneID, strMessage, strDetails, buttonDescriptions);
     }
 
     /* Show popup-stack: */
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp b/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
index b2ea408..7a450d2 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
@@ -3557,6 +3557,124 @@ RuntimeMenuType VBoxGlobal::restrictedRuntimeMenuTypes(CMachine &machine)
     return result;
 }
 
+#ifdef Q_WS_MAC
+/* static */
+RuntimeMenuApplicationActionType VBoxGlobal::restrictedRuntimeMenuApplicationActionTypes(CMachine &machine)
+{
+    /* Prepare result: */
+    RuntimeMenuApplicationActionType result = RuntimeMenuApplicationActionType_Invalid;
+    /* Load restricted runtime-application-menu action-types: */
+    QString strList(machine.GetExtraData(GUI_RestrictedRuntimeApplicationMenuActions));
+    QStringList list = strList.split(',');
+    /* Convert list into appropriate values: */
+    foreach (const QString &strValue, list)
+    {
+        RuntimeMenuApplicationActionType value = gpConverter->fromInternalString<RuntimeMenuApplicationActionType>(strValue);
+        if (value != RuntimeMenuApplicationActionType_Invalid)
+            result = static_cast<RuntimeMenuApplicationActionType>(result | value);
+    }
+    /* Return result: */
+    return result;
+}
+#endif /* Q_WS_MAC */
+
+/* static */
+RuntimeMenuMachineActionType VBoxGlobal::restrictedRuntimeMenuMachineActionTypes(CMachine &machine)
+{
+    /* Prepare result: */
+    RuntimeMenuMachineActionType result = RuntimeMenuMachineActionType_Invalid;
+    /* Load restricted runtime-machine-menu action-types: */
+    QString strList(machine.GetExtraData(GUI_RestrictedRuntimeMachineMenuActions));
+    QStringList list = strList.split(',');
+    /* Convert list into appropriate values: */
+    foreach (const QString &strValue, list)
+    {
+        RuntimeMenuMachineActionType value = gpConverter->fromInternalString<RuntimeMenuMachineActionType>(strValue);
+        if (value != RuntimeMenuMachineActionType_Invalid)
+            result = static_cast<RuntimeMenuMachineActionType>(result | value);
+    }
+    /* Return result: */
+    return result;
+}
+
+/* static */
+RuntimeMenuViewActionType VBoxGlobal::restrictedRuntimeMenuViewActionTypes(CMachine &machine)
+{
+    /* Prepare result: */
+    RuntimeMenuViewActionType result = RuntimeMenuViewActionType_Invalid;
+    /* Load restricted runtime-view-menu action-types: */
+    QString strList(machine.GetExtraData(GUI_RestrictedRuntimeViewMenuActions));
+    QStringList list = strList.split(',');
+    /* Convert list into appropriate values: */
+    foreach (const QString &strValue, list)
+    {
+        RuntimeMenuViewActionType value = gpConverter->fromInternalString<RuntimeMenuViewActionType>(strValue);
+        if (value != RuntimeMenuViewActionType_Invalid)
+            result = static_cast<RuntimeMenuViewActionType>(result | value);
+    }
+    /* Return result: */
+    return result;
+}
+
+/* static */
+RuntimeMenuDevicesActionType VBoxGlobal::restrictedRuntimeMenuDevicesActionTypes(CMachine &machine)
+{
+    /* Prepare result: */
+    RuntimeMenuDevicesActionType result = RuntimeMenuDevicesActionType_Invalid;
+    /* Load restricted runtime-devices-menu action-types: */
+    QString strList(machine.GetExtraData(GUI_RestrictedRuntimeDevicesMenuActions));
+    QStringList list = strList.split(',');
+    /* Convert list into appropriate values: */
+    foreach (const QString &strValue, list)
+    {
+        RuntimeMenuDevicesActionType value = gpConverter->fromInternalString<RuntimeMenuDevicesActionType>(strValue);
+        if (value != RuntimeMenuDevicesActionType_Invalid)
+            result = static_cast<RuntimeMenuDevicesActionType>(result | value);
+    }
+    /* Return result: */
+    return result;
+}
+
+#ifdef VBOX_WITH_DEBUGGER_GUI
+/* static */
+RuntimeMenuDebuggerActionType VBoxGlobal::restrictedRuntimeMenuDebuggerActionTypes(CMachine &machine)
+{
+    /* Prepare result: */
+    RuntimeMenuDebuggerActionType result = RuntimeMenuDebuggerActionType_Invalid;
+    /* Load restricted runtime-debugger-menu action-types: */
+    QString strList(machine.GetExtraData(GUI_RestrictedRuntimeDebuggerMenuActions));
+    QStringList list = strList.split(',');
+    /* Convert list into appropriate values: */
+    foreach (const QString &strValue, list)
+    {
+        RuntimeMenuDebuggerActionType value = gpConverter->fromInternalString<RuntimeMenuDebuggerActionType>(strValue);
+        if (value != RuntimeMenuDebuggerActionType_Invalid)
+            result = static_cast<RuntimeMenuDebuggerActionType>(result | value);
+    }
+    /* Return result: */
+    return result;
+}
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+
+/* static */
+RuntimeMenuHelpActionType VBoxGlobal::restrictedRuntimeMenuHelpActionTypes(CMachine &machine)
+{
+    /* Prepare result: */
+    RuntimeMenuHelpActionType result = RuntimeMenuHelpActionType_Invalid;
+    /* Load restricted runtime-help-menu action-types: */
+    QString strList(machine.GetExtraData(GUI_RestrictedRuntimeHelpMenuActions));
+    QStringList list = strList.split(',');
+    /* Convert list into appropriate values: */
+    foreach (const QString &strValue, list)
+    {
+        RuntimeMenuHelpActionType value = gpConverter->fromInternalString<RuntimeMenuHelpActionType>(strValue);
+        if (value != RuntimeMenuHelpActionType_Invalid)
+            result = static_cast<RuntimeMenuHelpActionType>(result | value);
+    }
+    /* Return result: */
+    return result;
+}
+
 /* static */
 UIVisualStateType VBoxGlobal::restrictedVisualStateTypes(CMachine &machine)
 {
diff --git a/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h b/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h
index 791c17c..7a0a22a 100644
--- a/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h
+++ b/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h
@@ -363,6 +363,16 @@ public:
     static bool shouldWeAllowSnapshotOperations(CMachine &machine, bool fIncludingSanityCheck = true);
     static MachineCloseAction defaultMachineCloseAction(CMachine &machine);
     static RuntimeMenuType restrictedRuntimeMenuTypes(CMachine &machine);
+#ifdef Q_WS_MAC
+    static RuntimeMenuApplicationActionType restrictedRuntimeMenuApplicationActionTypes(CMachine &machine);
+#endif /* Q_WS_MAC */
+    static RuntimeMenuMachineActionType restrictedRuntimeMenuMachineActionTypes(CMachine &machine);
+    static RuntimeMenuViewActionType restrictedRuntimeMenuViewActionTypes(CMachine &machine);
+    static RuntimeMenuDevicesActionType restrictedRuntimeMenuDevicesActionTypes(CMachine &machine);
+#ifdef VBOX_WITH_DEBUGGER_GUI
+    static RuntimeMenuDebuggerActionType restrictedRuntimeMenuDebuggerActionTypes(CMachine &machine);
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+    static RuntimeMenuHelpActionType restrictedRuntimeMenuHelpActionTypes(CMachine &machine);
     static UIVisualStateType restrictedVisualStateTypes(CMachine &machine);
     static QList<IndicatorType> restrictedStatusBarIndicators(CMachine &machine);
     static MachineCloseAction restrictedMachineCloseActions(CMachine &machine);
diff --git a/src/VBox/Frontends/VirtualBox/src/medium/UIMediumEnumerator.cpp b/src/VBox/Frontends/VirtualBox/src/medium/UIMediumEnumerator.cpp
index 05b8aa6..3a6645a 100644
--- a/src/VBox/Frontends/VirtualBox/src/medium/UIMediumEnumerator.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/medium/UIMediumEnumerator.cpp
@@ -430,7 +430,11 @@ void UIMediumEnumerator::calculateActualUsage(const QString &strMachineID, CMedi
 {
     /* Search for corresponding machine: */
     CMachine machine = vboxGlobal().virtualBox().FindMachine(strMachineID);
-    AssertReturnVoid(!machine.isNull());
+    if (machine.isNull())
+    {
+        /* Usually means the machine is already gone, not harmful. */
+        return;
+    }
 
     /* Calculate actual usage starting from root-snapshot if necessary: */
     if (!fTakeIntoAccountCurrentStateOnly)
diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp b/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp
index ba26fe3..52a124e 100644
--- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp
@@ -1580,12 +1580,12 @@ static void darwinHidInputCbKeyUp(VBoxKbdState_t *pKbd, uint32_t iKeyCode, VBoxH
              * should not be triggered for this event at all. Threfore, event should be removed from queue. */
             if (!darwinKbdCapsEventMatches(pEvent, pHidState->guestState.fCapsLockOn))
             {
-                free(pEvent);
                 CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iQueue);
 
                 LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard. Key-Down event was triggered %llu ms "
                     "ago. Carbon event should not be triggered, removed from queue\n", (int)pKbd->idxPosition,
                     RTTimeSystemMilliTS() - pEvent->tsKeyDown));
+                free(pEvent);
             }
             else
             {
diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h
index 1628bce..c9b785a 100644
--- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h
+++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h
@@ -34,7 +34,6 @@ class UICocoaApplication
 {
 public:
     static UICocoaApplication* instance();
-    void hide();
     ~UICocoaApplication();
 
     void registerForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser);
diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm
index a7d8727..c451471 100644
--- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm
+++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm
@@ -173,11 +173,6 @@ UICocoaApplication* UICocoaApplication::instance()
     return m_pInstance;
 }
 
-void UICocoaApplication::hide()
-{
-    [m_pNative hide:m_pNative];
-}
-
 UICocoaApplication::UICocoaApplication()
 {
     /* Make sure our private NSApplication object is created */
diff --git a/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.cpp b/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.cpp
new file mode 100644
index 0000000..68fb913
--- /dev/null
+++ b/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.cpp
@@ -0,0 +1,173 @@
+/* $Id: WinKeyboard.cpp $ */
+/** @file
+ *
+ * VBox frontends: Qt GUI ("VirtualBox"):
+ * Windows keyboard handling.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#define LOG_GROUP LOG_GROUP_GUI
+ 
+#include "WinKeyboard.h"
+#include <iprt/assert.h>
+#include <VBox/log.h>
+
+#include <stdio.h>
+
+/* Beautification of log output */
+#define VBOX_BOOL_TO_STR_STATE(x)   (x) ? "ON" : "OFF"
+#define VBOX_CONTROL_TO_STR_NAME(x) ((x == VK_CAPITAL) ? "CAPS" : (x == VK_SCROLL ? "SCROLL" : ((x == VK_NUMLOCK) ? "NUM" : "UNKNOWN")))
+
+/* A structure that contains internal control state representation */
+typedef struct VBoxModifiersState_t {
+    bool fNumLockOn;                        /** A state of NUM LOCK */
+    bool fCapsLockOn;                       /** A state of CAPS LOCK */
+    bool fScrollLockOn;                     /** A state of SCROLL LOCK */
+} VBoxModifiersState_t;
+
+/**
+ * Get current state of a keyboard modifier.
+ *
+ * @param   idModifier        Modifier to examine (VK_CAPITAL, VK_SCROLL or VK_NUMLOCK)
+ *
+ * @returns modifier state or asserts if wrong modifier is specified.
+ */
+static bool winGetModifierState(int idModifier)
+{
+    AssertReturn((idModifier == VK_CAPITAL) || (idModifier == VK_SCROLL) || (idModifier == VK_NUMLOCK), false);
+    return (GetKeyState(idModifier) & 0x0001) != 0;
+}
+
+/**
+ * Set current state of a keyboard modifier.
+ *
+ * @param   idModifier        Modifier to set (VK_CAPITAL, VK_SCROLL or VK_NUMLOCK)
+ * @param   fState            State to set
+ */
+static void winSetModifierState(int idModifier, bool fState)
+{
+    AssertReturnVoid((idModifier == VK_CAPITAL) || (idModifier == VK_SCROLL) || (idModifier == VK_NUMLOCK));
+
+    /* If the modifier is already in desired state, just do nothing. Otherwise, toggle it. */
+    if (winGetModifierState(idModifier) != fState)
+    {
+        /* Simulate KeyUp+KeyDown keystroke */
+        keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY, 0);
+        keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+
+        LogRel2(("HID LEDs sync: setting %s state to %s (0x%X).\n",
+                 VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC)));
+    }
+    else
+    {
+        LogRel2(("HID LEDs sync: setting %s state: skipped: state is already %s (0x%X).\n",
+                 VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC)));
+    }
+}
+
+/** Set all HID LEDs at once. */
+static bool winSetHidLeds(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)
+{
+    winSetModifierState(VK_NUMLOCK, fNumLockOn);
+    winSetModifierState(VK_CAPITAL, fCapsLockOn);
+    winSetModifierState(VK_SCROLL,  fScrollLockOn);
+    return true;
+}
+
+/** Check if specified LED states correspond to the system modifier states. */
+bool winHidLedsInSync(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)
+{
+    if (winGetModifierState(VK_NUMLOCK) != fNumLockOn)
+        return false;
+
+    if (winGetModifierState(VK_CAPITAL) != fCapsLockOn)
+        return false;
+
+    if (winGetModifierState(VK_SCROLL) != fScrollLockOn)
+        return false;
+
+    return true;
+}
+
+/**
+ * Allocate memory and store modifier states there.
+ *
+ * @returns allocated memory witch contains modifier states or NULL.
+ */
+void * WinHidDevicesKeepLedsState(void)
+{
+    VBoxModifiersState_t *pState;
+
+    pState = (VBoxModifiersState_t *)malloc(sizeof(VBoxModifiersState_t));
+    if (pState)
+    {
+        pState->fNumLockOn    = winGetModifierState(VK_NUMLOCK);
+        pState->fCapsLockOn   = winGetModifierState(VK_CAPITAL);
+        pState->fScrollLockOn = winGetModifierState(VK_SCROLL);
+
+        LogRel2(("HID LEDs sync: host state captured: NUM(%s) CAPS(%s) SCROLL(%s)\n",
+                 VBOX_BOOL_TO_STR_STATE(pState->fNumLockOn),
+                 VBOX_BOOL_TO_STR_STATE(pState->fCapsLockOn),
+                 VBOX_BOOL_TO_STR_STATE(pState->fScrollLockOn)));
+
+        return (void *)pState;
+    }
+
+    LogRel2(("HID LEDs sync: unable to allocate memory for HID LEDs synchronization data. LEDs sync will be disabled.\n"));
+
+    return NULL;
+}
+
+/**
+ * Restore host modifier states and free memory.
+ */
+void WinHidDevicesApplyAndReleaseLedsState(void *pData)
+{
+    VBoxModifiersState_t *pState = (VBoxModifiersState_t *)pData;
+
+    if (pState)
+    {
+        LogRel2(("HID LEDs sync: attempt to restore host state: NUM(%s) CAPS(%s) SCROLL(%s)\n",
+                 VBOX_BOOL_TO_STR_STATE(pState->fNumLockOn),
+                 VBOX_BOOL_TO_STR_STATE(pState->fCapsLockOn),
+                 VBOX_BOOL_TO_STR_STATE(pState->fScrollLockOn)));
+
+        if (winSetHidLeds(pState->fNumLockOn, pState->fCapsLockOn, pState->fScrollLockOn))
+            LogRel2(("HID LEDs sync: host state restored\n"));
+        else
+            LogRel2(("HID LEDs sync: host state restore failed\n"));
+
+        free(pState);
+    }
+}
+
+/**
+ * Broadcast HID modifier states.
+ *
+ * @param   fNumLockOn        NUM LOCK state
+ * @param   fCapsLockOn       CAPS LOCK state
+ * @param   fScrollLockOn     SCROLL LOCK state
+ */
+void WinHidDevicesBroadcastLeds(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)
+{
+    LogRel2(("HID LEDs sync: start broadcast guest modifier states: NUM(%s) CAPS(%s) SCROLL(%s)\n",
+             VBOX_BOOL_TO_STR_STATE(fNumLockOn),
+             VBOX_BOOL_TO_STR_STATE(fCapsLockOn),
+             VBOX_BOOL_TO_STR_STATE(fScrollLockOn)));
+
+    if (winSetHidLeds(fNumLockOn, fCapsLockOn, fScrollLockOn))
+        LogRel2(("HID LEDs sync: broadcast completed\n"));
+    else
+        LogRel2(("HID LEDs sync: broadcast failed\n"));
+}
diff --git a/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.h b/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.h
new file mode 100644
index 0000000..4c33025
--- /dev/null
+++ b/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.h
@@ -0,0 +1,33 @@
+/* $Id: WinKeyboard.h $ */
+/** @file
+ *
+ * VBox frontends: Qt GUI ("VirtualBox"):
+ * Windows keyboard handling.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __WinKeyboard_h__
+#define __WinKeyboard_h__
+
+/* Platform includes: */
+#include "Windows.h"
+
+void * WinHidDevicesKeepLedsState(void);
+void   WinHidDevicesApplyAndReleaseLedsState(void *pData);
+void   WinHidDevicesBroadcastLeds(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn);
+
+bool winHidLedsInSync(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn);
+
+#endif /* __WinKeyboard_h__ */
+
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIActionPoolRuntime.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIActionPoolRuntime.cpp
index 7c31084..7808704 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIActionPoolRuntime.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIActionPoolRuntime.cpp
@@ -797,14 +797,17 @@ class UIActionMenuNetworkAdapters : public UIActionMenu
 public:
 
     UIActionMenuNetworkAdapters(UIActionPool *pParent)
-        : UIActionMenu(pParent)
+        : UIActionMenu(pParent, ":/nw_16px.png", ":/nw_disabled_16px.png")
     {
         retranslateUi();
     }
 
 protected:
 
-    void retranslateUi() {}
+    void retranslateUi()
+    {
+        setName(QApplication::translate("UIActionPool", "Network"));
+    }
 };
 
 class UIActionSimpleShowNetworkSettingsDialog : public UIActionSimple
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp
index 24f2abb..d2c546e 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp
@@ -500,6 +500,14 @@ STDMETHODIMP UIFrameBuffer::Notify3DEvent(ULONG uType, BYTE *pData)
             /* Confirm Notify3DEvent: */
             return S_OK;
         }
+
+        case VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL:
+        {
+            HRESULT hr = m_fIsMarkedAsUnused ? E_FAIL : S_OK;
+            unlock();
+            return hr;
+        }
+
         default:
             break;
     }
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBufferQImage.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBufferQImage.cpp
index b326585..e9426dd 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBufferQImage.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBufferQImage.cpp
@@ -166,6 +166,7 @@ void UIFrameBufferQImage::paintEvent(QPaintEvent *pEvent)
         && machineState != KMachineState_Running
         && machineState != KMachineState_Teleporting
         && machineState != KMachineState_LiveSnapshotting
+        && machineState != KMachineState_DeletingSnapshotOnline
         /* paused */
         && machineState != KMachineState_Paused
         && machineState != KMachineState_TeleportingPausedVM
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
index 21901d1..9688241 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
@@ -355,6 +355,12 @@ void UIKeyboardHandler::setDebuggerActive(bool aActive /* = true*/)
 #endif /* VBOX_WITH_DEBUGGER_GUI */
 
 #if defined(Q_WS_WIN)
+/** Tell keyboard event handler to skip host keyboard events. Used for HID LEDs sync
+ * when on Windows host a keyboard event is generated in order to change corresponding LED. */
+void UIKeyboardHandler::winSkipKeyboardEvents(bool fSkip)
+{
+    m_fSkipKeyboardEvents = fSkip;
+}
 
 bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId)
 {
@@ -362,6 +368,11 @@ bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId)
      * Returning 'true' means filtering-out,
      * Returning 'false' means passing event to Qt. */
     bool fResult = false; /* Pass to Qt by default: */
+
+    /* Skip this event if m_fSkipKeyboardEvents is set by winSkipKeyboardEvents(). */
+    if (m_fSkipKeyboardEvents)
+        return false;
+
     switch (pMsg->message)
     {
         case WM_KEYDOWN:
@@ -680,6 +691,7 @@ UIKeyboardHandler::UIKeyboardHandler(UIMachineLogic *pMachineLogic)
 #if defined(Q_WS_WIN)
     , m_bIsHostkeyInCapture(false)
     , m_iKeyboardHookViewIndex(-1)
+    , m_fSkipKeyboardEvents(false)
 #elif defined(Q_WS_MAC)
     , m_darwinKeyModifiers(0)
     , m_fKeyboardGrabbed(false)
@@ -1203,7 +1215,7 @@ bool UIKeyboardHandler::keyEventHandleNormal(int iKey, uint8_t uScan, int fFlags
         /* Check if the guest has the same view on the modifier keys
          * (NumLock, CapsLock, ScrollLock) as the X server.
          * If not, send KeyPress events to synchronize the state: */
-#if !defined(Q_WS_MAC)
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
         if (fFlags & KeyPressed)
             fixModifierState(pCodes, puCodesCount);
 #endif
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h b/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h
index 38ad16f..347f6af 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h
@@ -83,6 +83,7 @@ public:
     /* External event-filters: */
 #if defined(Q_WS_WIN)
     bool winEventFilter(MSG *pMsg, ulong uScreenId);
+    void winSkipKeyboardEvents(bool fSkip);
 #elif defined(Q_WS_X11)
     bool x11EventFilter(XEvent *pEvent, ulong uScreenId);
 #endif
@@ -182,6 +183,8 @@ protected:
     static UIKeyboardHandler *m_spKeyboardHandler;
     HHOOK m_keyboardHook;
     int m_iKeyboardHookViewIndex;
+    /* A flag that used to tell kbd event filter to ignore keyboard events */
+    bool m_fSkipKeyboardEvents;
 #elif defined(Q_WS_MAC)
     /* The current modifier key mask. Used to figure out which modifier
      * key was pressed when we get a kEventRawKeyModifiersChanged event. */
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
index 3a46c3e..e7ced6d 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
@@ -73,6 +73,7 @@
 #include "CSystemProperties.h"
 #include "CHostVideoInputDevice.h"
 #include "CEmulatedUSB.h"
+#include "CNetworkAdapter.h"
 #ifdef Q_WS_MAC
 # include "CGuest.h"
 #endif /* Q_WS_MAC */
@@ -85,6 +86,9 @@
 #ifdef Q_WS_MAC
 # include "DarwinKeyboard.h"
 #endif
+#ifdef Q_WS_WIN
+# include "WinKeyboard.h"
+#endif
 
 /* External includes: */
 #ifdef Q_WS_X11
@@ -514,9 +518,19 @@ void UIMachineLogic::sltKeyboardLedsChanged()
     if (!isHidLedsSyncEnabled())
         return;
 
-#ifdef Q_WS_MAC
-    LogRelFlow(("UIMachineLogic::sltKeyboardLedsChanged: Updating host LED lock states.\n"));
+#if defined(Q_WS_MAC)
     DarwinHidDevicesBroadcastLeds(m_pHostLedsState, uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
+#elif defined(Q_WS_WIN)
+    if (!winHidLedsInSync(uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock()))
+    {
+        keyboardHandler()->winSkipKeyboardEvents(true);
+        WinHidDevicesBroadcastLeds(uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
+        keyboardHandler()->winSkipKeyboardEvents(false);
+    }
+    else
+        LogRel2(("HID LEDs Sync: already in sync\n"));
+#else
+    LogRelFlow(("UIMachineLogic::sltKeyboardLedsChanged: Updating host LED lock states does not supported on this platform.\n"));
 #endif
 }
 
@@ -602,8 +616,8 @@ UIMachineLogic::UIMachineLogic(QObject *pParent, UISession *pSession, UIVisualSt
     , m_pDockIconPreview(0)
     , m_pDockPreviewSelectMonitorGroup(0)
     , m_DockIconPreviewMonitor(0)
-    , m_pHostLedsState(NULL)
 #endif /* Q_WS_MAC */
+    , m_pHostLedsState(NULL)
 {
 }
 
@@ -881,6 +895,8 @@ void UIMachineLogic::prepareActionConnections()
             this, SLOT(sltPrepareSharedClipboardMenu()));
     connect(gActionPool->action(UIActionIndexRuntime_Menu_DragAndDrop)->menu(), SIGNAL(aboutToShow()),
             this, SLOT(sltPrepareDragAndDropMenu()));
+    connect(gActionPool->action(UIActionIndexRuntime_Menu_Network)->menu(), SIGNAL(aboutToShow()),
+            this, SLOT(sltPrepareNetworkMenu()));
     connect(gActionPool->action(UIActionIndexRuntime_Simple_NetworkSettings), SIGNAL(triggered()),
             this, SLOT(sltOpenNetworkAdaptersDialog()));
     connect(gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersSettings), SIGNAL(triggered()),
@@ -1079,14 +1095,25 @@ bool UIMachineLogic::eventFilter(QObject *pWatched, QEvent *pEvent)
                 /* Handle *window activated* event: */
                 case QEvent::WindowActivate:
                 {
+#ifdef Q_WS_WIN
                     /* We should save current lock states as *previous* and
                      * set current lock states to guest values we have,
                      * As we have no ipc between threads of different VMs
-                     * we are using 300ms timer as lazy sync timout: */
-                    //QTimer::singleShot(300, this, SLOT(sltSwitchKeyboardLedsToGuestLeds()));
+                     * we are using 100ms timer as lazy sync timout: */
 
+                    /* On Windows host we should do that only in case if sync
+                     * is enabled. Otherwise, keyboardHandler()->winSkipKeyboardEvents(false)
+                     * won't be called in sltSwitchKeyboardLedsToGuestLeds() and guest
+                     * will loose keyboard input forever. */
+                    if (isHidLedsSyncEnabled())
+                    {
+                        keyboardHandler()->winSkipKeyboardEvents(true);
+                        QTimer::singleShot(100, this, SLOT(sltSwitchKeyboardLedsToGuestLeds()));
+                    }
+#else /* Q_WS_WIN */
                     /* Trigger callback synchronously for now! */
                     sltSwitchKeyboardLedsToGuestLeds();
+#endif /* !Q_WS_WIN */
                     break;
                 }
                 /* Handle *window deactivated* event: */
@@ -2049,6 +2076,81 @@ void UIMachineLogic::sltPrepareDragAndDropMenu()
                 pAction->setChecked(true);
 }
 
+/** Prepares menu content when user hovers <b>Network</b> submenu of the <b>Devices</b> menu. */
+void UIMachineLogic::sltPrepareNetworkMenu()
+{
+    /* Get and check 'the sender' menu object: */
+    QMenu *pMenu = qobject_cast<QMenu*>(sender());
+    QMenu *pNetworkMenu = gActionPool->action(UIActionIndexRuntime_Menu_Network)->menu();
+    AssertReturnVoid(pMenu == pNetworkMenu);
+    Q_UNUSED(pNetworkMenu);
+
+    /* Get and check current machine: */
+    const CMachine &machine = session().GetMachine();
+    AssertReturnVoid(!machine.isNull());
+
+    /* Determine how many adapters we should display: */
+    KChipsetType chipsetType = machine.GetChipsetType();
+    ULONG uCount = qMin((ULONG)4, vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(chipsetType));
+
+    /* Enumerate existing network adapters: */
+    QMap<int, bool> adapterData;
+    for (ULONG uSlot = 0; uSlot < uCount; ++uSlot)
+    {
+        /* Get and check iterated adapter: */
+        const CNetworkAdapter &adapter = machine.GetNetworkAdapter(uSlot);
+        AssertReturnVoid(machine.isOk());
+        Assert(!adapter.isNull());
+        if (adapter.isNull())
+            continue;
+
+        /* Remember adapter data if it is enabled: */
+        if (adapter.GetEnabled())
+            adapterData.insert((int)uSlot, (bool)adapter.GetCableConnected());
+    }
+    AssertReturnVoid(!adapterData.isEmpty());
+
+    /* Delete all "temporary" actions: */
+    QList<QAction*> actions = pMenu->actions();
+    foreach (QAction *pAction, actions)
+        if (pAction->property("temporary").toBool())
+            delete pAction;
+
+    /* Add new "temporary" actions: */
+    foreach (int iSlot, adapterData.keys())
+    {
+        QAction *pAction = pMenu->addAction(QIcon(adapterData[iSlot] ? ":/connect_16px.png": ":/disconnect_16px.png"),
+                                            adapterData.size() == 1 ? tr("Connect Network Adapter") : tr("Connect Network Adapter %1").arg(iSlot + 1),
+                                            this, SLOT(sltToggleNetworkAdapterConnection()));
+        pAction->setProperty("temporary", true);
+        pAction->setProperty("slot", iSlot);
+        pAction->setCheckable(true);
+        pAction->setChecked(adapterData[iSlot]);
+    }
+}
+
+/** Toggles network adapter's <i>Cable Connected</i> state. */
+void UIMachineLogic::sltToggleNetworkAdapterConnection()
+{
+    /* Get and check 'the sender' action object: */
+    QAction *pAction = qobject_cast<QAction*>(sender());
+    AssertReturnVoid(pAction);
+
+    /* Get and check current machine: */
+    CMachine machine = session().GetMachine();
+    AssertReturnVoid(!machine.isNull());
+
+    /* Get operation target: */
+    CNetworkAdapter adapter = machine.GetNetworkAdapter((ULONG)pAction->property("slot").toInt());
+    AssertReturnVoid(machine.isOk() && !adapter.isNull());
+
+    /* Connect/disconnect cable to/from target: */
+    adapter.SetCableConnected(!adapter.GetCableConnected());
+    machine.SaveSettings();
+    if (!machine.isOk())
+        msgCenter().cannotSaveMachineSettings(machine);
+}
+
 void UIMachineLogic::sltChangeDragAndDropType(QAction *pAction)
 {
     /* Assign new mode (without save): */
@@ -2318,12 +2420,19 @@ void UIMachineLogic::sltSwitchKeyboardLedsToGuestLeds()
     if (!isHidLedsSyncEnabled())
         return;
 
-#ifdef Q_WS_MAC
-    LogRelFlow(("UIMachineLogic::sltSwitchKeyboardLedsToGuestLeds: keep host LED lock states and broadcast guest's ones.\n"));
+#if defined(Q_WS_MAC)
     if (m_pHostLedsState == NULL)
         m_pHostLedsState = DarwinHidDevicesKeepLedsState();
     DarwinHidDevicesBroadcastLeds(m_pHostLedsState, uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
-#endif /* Q_WS_MAC */
+#elif defined(Q_WS_WIN)
+    if (m_pHostLedsState == NULL)
+        m_pHostLedsState = WinHidDevicesKeepLedsState();
+    keyboardHandler()->winSkipKeyboardEvents(true);
+    WinHidDevicesBroadcastLeds(uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
+    keyboardHandler()->winSkipKeyboardEvents(false);
+#else
+    LogRelFlow(("UIMachineLogic::sltSwitchKeyboardLedsToGuestLeds: keep host LED lock states and broadcast guest's ones does not supported on this platform.\n"));
+#endif
 }
 
 void UIMachineLogic::sltSwitchKeyboardLedsToPreviousLeds()
@@ -2338,15 +2447,19 @@ void UIMachineLogic::sltSwitchKeyboardLedsToPreviousLeds()
         return;
 
     /* Here we have to restore host LED lock states. */
-#ifdef Q_WS_MAC
-    LogRelFlow(("UIMachineLogic::sltSwitchKeyboardLedsToPreviousLeds: restore host LED lock states.\n"));
-
     if (m_pHostLedsState)
     {
-        DarwinHidDevicesApplyAndReleaseLedsState(m_pHostLedsState);
+#if defined(Q_WS_MAC)
+    	DarwinHidDevicesApplyAndReleaseLedsState(m_pHostLedsState);
+#elif defined(Q_WS_WIN)
+        keyboardHandler()->winSkipKeyboardEvents(true);
+        WinHidDevicesApplyAndReleaseLedsState(m_pHostLedsState);
+        keyboardHandler()->winSkipKeyboardEvents(false);
+#else
+        LogRelFlow(("UIMachineLogic::sltSwitchKeyboardLedsToPreviousLeds: restore host LED lock states does not supported on this platform.\n"));
+#endif
         m_pHostLedsState = NULL;
-    }
-#endif /* Q_WS_MAC */
+	}
 }
 
 int UIMachineLogic::searchMaxSnapshotIndex(const CMachine &machine,
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
index 130c5ef..d8b7104 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
@@ -208,6 +208,8 @@ private slots:
     void sltPrepareSharedClipboardMenu();
     void sltChangeSharedClipboardType(QAction *pAction);
     void sltPrepareDragAndDropMenu();
+    void sltPrepareNetworkMenu();
+    void sltToggleNetworkAdapterConnection();
     void sltChangeDragAndDropType(QAction *pAction);
     void sltToggleVRDE(bool fEnabled);
     void sltToggleVideoCapture(bool fEnabled);
@@ -272,9 +274,10 @@ private:
     UIDockIconPreview *m_pDockIconPreview;
     QActionGroup *m_pDockPreviewSelectMonitorGroup;
     int m_DockIconPreviewMonitor;
-    void *m_pHostLedsState;
 #endif /* Q_WS_MAC */
 
+    void *m_pHostLedsState;
+
     /* Friend classes: */
     friend class UIMachineWindow;
 };
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineMenuBar.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineMenuBar.cpp
index d1f00f0..68fd87f 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineMenuBar.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineMenuBar.cpp
@@ -203,28 +203,135 @@ void UIMachineMenuBar::prepareMenuMachine(QMenu *pMenu)
     if (!pMenu->isEmpty())
         return;
 
-    /* Machine submenu: */
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SettingsDialog));
-    if (m_pSession->isSnapshotOperationsAllowed())
+
+    /* Separator #1? */
+    bool fSeparator1 = false;
+
+    /* Settings Dialog action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_SettingsDialog)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SettingsDialog));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_SettingsDialog)->setEnabled(false);
+    /* Take Snapshot action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_TakeSnapshot &&
+        m_pSession->isSnapshotOperationsAllowed())
+    {
         pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TakeSnapshot));
+        fSeparator1 = true;
+    }
     else
         gActionPool->action(UIActionIndexRuntime_Simple_TakeSnapshot)->setEnabled(false);
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TakeScreenshot));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InformationDialog));
-    pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration));
-    pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCAD));
+    /* Take Screenshot action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_TakeScreenshot)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TakeScreenshot));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_TakeScreenshot)->setEnabled(false);
+    /* Information Dialog action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_InformationDialog)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InformationDialog));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_InformationDialog)->setEnabled(false);
+
+    /* Separator #1: */
+    if (fSeparator1)
+        pMenu->addSeparator();
+
+
+    /* Separator #2? */
+    bool fSeparator2 = false;
+
+    /* Mouse Integration action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_MouseIntegration)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration));
+        fSeparator2 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration)->setEnabled(false);
+
+    /* Separator #2: */
+    if (fSeparator2)
+        pMenu->addSeparator();
+
+
+    /* Separator #3? */
+    bool fSeparator3 = false;
+
+    /* Type CAD action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_TypeCAD)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCAD));
+        fSeparator3 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_TypeCAD)->setEnabled(false);
 #ifdef Q_WS_X11
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCABS));
+    /* Type CABS action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_TypeCABS)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCABS));
+        fSeparator3 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_TypeCABS)->setEnabled(false);
 #endif /* Q_WS_X11 */
-    pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Pause));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Reset));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Shutdown));
+
+    /* Separator #3: */
+    if (fSeparator3)
+        pMenu->addSeparator();
+
+
+    /* Separator #4? */
+    bool fSeparator4 = false;
+
+    /* Pause action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_Pause)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Pause));
+        fSeparator4 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Toggle_Pause)->setEnabled(false);
+    /* Reset action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_Reset)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Reset));
+        fSeparator4 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_Reset)->setEnabled(false);
+    /* SaveState action: */
+    if (!(m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_SaveState))
+        gActionPool->action(UIActionIndexRuntime_Simple_Save)->setEnabled(false);
+    /* Shutdown action: */
+    if (m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_Shutdown)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Shutdown));
+        fSeparator4 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_Shutdown)->setEnabled(false);
+    /* PowerOff action: */
+    if (!(m_pSession->allowedActionsMenuMachine() & RuntimeMenuMachineActionType_PowerOff))
+        gActionPool->action(UIActionIndexRuntime_Simple_PowerOff)->setEnabled(false);
+
 #ifndef Q_WS_MAC
-    pMenu->addSeparator();
+    /* Separator #3: */
+    if (fSeparator4)
+        pMenu->addSeparator();
 #endif /* !Q_WS_MAC */
+
+
+    /* Close action: */
     pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Close));
     if (m_pSession->isAllCloseActionsRestricted())
         gActionPool->action(UIActionIndexRuntime_Simple_Close)->setEnabled(false);
@@ -236,23 +343,46 @@ void UIMachineMenuBar::prepareMenuView(QMenu *pMenu)
     if (!pMenu->isEmpty())
         return;
 
-    /* View submenu: */
-    bool fIsAllowedFullscreen = m_pSession->isVisualStateAllowedFullscreen();
-    bool fIsAllowedSeamless = m_pSession->isVisualStateAllowedSeamless();
-    bool fIsAllowedScale = m_pSession->isVisualStateAllowedScale();
+
+    /* Mode flags: */
+    bool fIsAllowedFullscreen = m_pSession->isVisualStateAllowedFullscreen() &&
+                                (m_pSession->allowedActionsMenuView() & RuntimeMenuViewActionType_Fullscreen);
+    bool fIsAllowedSeamless = m_pSession->isVisualStateAllowedSeamless() &&
+                              (m_pSession->allowedActionsMenuView() & RuntimeMenuViewActionType_Seamless);
+    bool fIsAllowedScale = m_pSession->isVisualStateAllowedScale() &&
+                           (m_pSession->allowedActionsMenuView() & RuntimeMenuViewActionType_Scale);
+
+    /* Fullscreen action: */
     gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen)->setEnabled(fIsAllowedFullscreen);
     if (fIsAllowedFullscreen)
         pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen));
+
+    /* Seamless action: */
     gActionPool->action(UIActionIndexRuntime_Toggle_Seamless)->setEnabled(fIsAllowedSeamless);
     if (fIsAllowedSeamless)
         pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless));
+
+    /* Scale action: */
     gActionPool->action(UIActionIndexRuntime_Toggle_Scale)->setEnabled(fIsAllowedScale);
     if (fIsAllowedScale)
         pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Scale));
+
+    /* Mode separator: */
     if (fIsAllowedFullscreen || fIsAllowedSeamless || fIsAllowedScale)
         pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_AdjustWindow));
+
+
+    /* Guest Autoresize action: */
+    if (m_pSession->allowedActionsMenuView() & RuntimeMenuViewActionType_GuestAutoresize)
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize));
+    else
+        gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize)->setEnabled(false);
+
+    /* Adjust Window action: */
+    if (m_pSession->allowedActionsMenuView() & RuntimeMenuViewActionType_AdjustWindow)
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_AdjustWindow));
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_AdjustWindow)->setEnabled(false);
 }
 
 void UIMachineMenuBar::prepareMenuDevices(QMenu *pMenu)
@@ -261,20 +391,116 @@ void UIMachineMenuBar::prepareMenuDevices(QMenu *pMenu)
     if (!pMenu->isEmpty())
         return;
 
-    /* Devices submenu: */
-    pMenu->addMenu(gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices)->menu());
-    pMenu->addMenu(gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices)->menu());
-    pMenu->addMenu(gActionPool->action(UIActionIndexRuntime_Menu_USBDevices)->menu());
-    pMenu->addMenu(gActionPool->action(UIActionIndexRuntime_Menu_WebCams)->menu());
-    pMenu->addMenu(gActionPool->action(UIActionIndexRuntime_Menu_SharedClipboard)->menu());
-    pMenu->addMenu(gActionPool->action(UIActionIndexRuntime_Menu_DragAndDrop)->menu());
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_NetworkSettings));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersSettings));
-    pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VideoCapture));
-    pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InstallGuestTools));
+
+    /* Separator #1? */
+    bool fSeparator1 = false;
+
+    /* Optical Devices submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_OpticalDevices)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices)->setEnabled(false);
+    /* Floppy Devices submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_FloppyDevices)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices)->setEnabled(false);
+    /* USB Devices submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_USBDevices)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_USBDevices));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Menu_USBDevices)->setEnabled(false);
+    /* Web Cams submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_WebCams)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_WebCams));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Menu_WebCams)->setEnabled(false);
+    /* Shared Clipboard submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_SharedClipboard)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_SharedClipboard));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Menu_SharedClipboard)->setEnabled(false);
+    /* Drag&Drop submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_DragAndDrop)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_DragAndDrop));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Menu_DragAndDrop)->setEnabled(false);
+    /* Network submenu: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_NetworkSettings)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Menu_Network));
+        gActionPool->action(UIActionIndexRuntime_Menu_Network)->menu()->addAction(gActionPool->action(UIActionIndexRuntime_Simple_NetworkSettings));
+        fSeparator1 = true;
+    }
+    else
+    {
+        gActionPool->action(UIActionIndexRuntime_Menu_Network)->setEnabled(false);
+        gActionPool->action(UIActionIndexRuntime_Simple_NetworkSettings)->setEnabled(false);
+    }
+    /* Shared Folders Settings action: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_SharedFoldersSettings)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersSettings));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersSettings)->setEnabled(false);
+
+    /* Separator #1: */
+    if (fSeparator1)
+        pMenu->addSeparator();
+
+
+    /* Separator #2? */
+    bool fSeparator2 = false;
+
+    /* VRDE Server action: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_VRDEServer)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer));
+        if (!m_pSession->isExtensionPackUsable())
+            gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer)->setEnabled(false);
+        fSeparator2 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer)->setEnabled(false);
+    /* Video Capture action: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_VideoCapture)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VideoCapture));
+        fSeparator2 = true;
+    }
+    else
+        gActionPool->action(UIActionIndexRuntime_Toggle_VideoCapture)->setEnabled(false);
+
+    /* Separator #2: */
+    if (fSeparator2)
+        pMenu->addSeparator();
+
+
+    /* Install Guest Tools action: */
+    if (m_pSession->allowedActionsMenuDevices() & RuntimeMenuDevicesActionType_InstallGuestTools)
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InstallGuestTools));
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_InstallGuestTools)->setEnabled(false);
 }
 
 #ifdef VBOX_WITH_DEBUGGER_GUI
@@ -284,11 +510,26 @@ void UIMachineMenuBar::prepareMenuDebug(QMenu *pMenu)
     if (!pMenu->isEmpty())
         return;
 
-    /* Debug submenu: */
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Statistics));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_CommandLine));
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Logging));
-    pMenu->addAction(gActionPool->action(UIActionIndex_Simple_LogDialog));
+    /* Statistics action: */
+    if (m_pSession->allowedActionsMenuDebugger() & RuntimeMenuDebuggerActionType_Statistics)
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Statistics));
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_Statistics)->setEnabled(false);
+    /* Command Line action: */
+    if (m_pSession->allowedActionsMenuDebugger() & RuntimeMenuDebuggerActionType_CommandLine)
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_CommandLine));
+    else
+        gActionPool->action(UIActionIndexRuntime_Simple_CommandLine)->setEnabled(false);
+    /* Logging action: */
+    if (m_pSession->allowedActionsMenuDebugger() & RuntimeMenuDebuggerActionType_Logging)
+        pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Logging));
+    else
+        gActionPool->action(UIActionIndexRuntime_Toggle_Logging)->setEnabled(false);
+    /* Log Dialog action: */
+    if (m_pSession->allowedActionsMenuDebugger() & RuntimeMenuDebuggerActionType_LogDialog)
+        pMenu->addAction(gActionPool->action(UIActionIndex_Simple_LogDialog));
+    else
+        gActionPool->action(UIActionIndex_Simple_LogDialog)->setEnabled(false);
 }
 #endif /* VBOX_WITH_DEBUGGER_GUI */
 
@@ -298,33 +539,95 @@ void UIMachineMenuBar::prepareMenuHelp(QMenu *pMenu)
     if (!pMenu->isEmpty())
         return;
 
-    /* Help submenu: */
-    pMenu->addAction(gActionPool->action(UIActionIndex_Simple_Contents));
-    pMenu->addAction(gActionPool->action(UIActionIndex_Simple_WebSite));
-    pMenu->addSeparator();
-    pMenu->addAction(gActionPool->action(UIActionIndex_Simple_ResetWarnings));
-    pMenu->addSeparator();
-#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
-    pMenu->addAction(gActionPool->action(UIActionIndex_Simple_NetworkAccessManager));
-#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
-#ifndef Q_WS_MAC
-    pMenu->addSeparator();
-#endif /* !Q_WS_MAC */
-    pMenu->addAction(gActionPool->action(UIActionIndex_Simple_About));
-
-    /* Prepare connections: */
-    VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_Contents), SIGNAL(triggered()),
-                        &msgCenter(), SLOT(sltShowHelpHelpDialog()));
-    VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_WebSite), SIGNAL(triggered()),
-                        &msgCenter(), SLOT(sltShowHelpWebDialog()));
-    VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_ResetWarnings), SIGNAL(triggered()),
-                        &msgCenter(), SLOT(sltResetSuppressedMessages()));
+
+    /* Separator #1? */
+    bool fSeparator1 = false;
+
+    /* Contents action: */
+    if (m_pSession->allowedActionsMenuHelp() & RuntimeMenuHelpActionType_Contents)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndex_Simple_Contents));
+        VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_Contents), SIGNAL(triggered()),
+                            &msgCenter(), SLOT(sltShowHelpHelpDialog()));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(UIActionIndex_Simple_Contents)->setEnabled(false);
+    /* Web Site action: */
+    if (m_pSession->allowedActionsMenuHelp() & RuntimeMenuHelpActionType_WebSite)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndex_Simple_WebSite));
+        VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_WebSite), SIGNAL(triggered()),
+                            &msgCenter(), SLOT(sltShowHelpWebDialog()));
+        fSeparator1 = true;
+    }
+    else
+        gActionPool->action(RuntimeMenuHelpActionType_WebSite)->setEnabled(false);
+
+    /* Separator #1: */
+    if (fSeparator1)
+        pMenu->addSeparator();
+
+
+    /* Separator #2? */
+    bool fSeparator2 = false;
+
+    /* Reset Warnings action: */
+    if (m_pSession->allowedActionsMenuHelp() & RuntimeMenuHelpActionType_ResetWarnings)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndex_Simple_ResetWarnings));
+        VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_ResetWarnings), SIGNAL(triggered()),
+                            &msgCenter(), SLOT(sltResetSuppressedMessages()));
+        fSeparator2 = true;
+    }
+    else
+        gActionPool->action(UIActionIndex_Simple_ResetWarnings)->setEnabled(false);
+
+    /* Separator #2: */
+    if (fSeparator2)
+        pMenu->addSeparator();
+
+
 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER
-    VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_NetworkAccessManager), SIGNAL(triggered()),
-                        gNetworkManager, SLOT(show()));
+# ifndef Q_WS_MAC
+    /* Separator #3? */
+    bool fSeparator3 = false;
+# endif /* !Q_WS_MAC */
+
+    /* Reset Warnings action: */
+    if (m_pSession->allowedActionsMenuHelp() & RuntimeMenuHelpActionType_NetworkAccessManager)
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndex_Simple_NetworkAccessManager));
+        VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_NetworkAccessManager), SIGNAL(triggered()),
+                            gNetworkManager, SLOT(show()));
+# ifndef Q_WS_MAC
+        fSeparator3 = true;
+# endif /* !Q_WS_MAC */
+    }
+    else
+        gActionPool->action(UIActionIndex_Simple_NetworkAccessManager)->setEnabled(false);
+
+# ifndef Q_WS_MAC
+    /* Separator #3: */
+    if (fSeparator3)
+        pMenu->addSeparator();
+# endif /* !Q_WS_MAC */
 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
-    VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_About), SIGNAL(triggered()),
-                        &msgCenter(), SLOT(sltShowHelpAboutDialog()));
+
+
+    /* About action: */
+#ifdef Q_WS_MAC
+    if (m_pSession->allowedActionsMenuApplication() & RuntimeMenuApplicationActionType_About)
+#else /* !Q_WS_MAC */
+    if (m_pSession->allowedActionsMenuHelp() & RuntimeMenuHelpActionType_About)
+#endif /* Q_WS_MAC */
+    {
+        pMenu->addAction(gActionPool->action(UIActionIndex_Simple_About));
+        VBoxGlobal::connect(gActionPool->action(UIActionIndex_Simple_About), SIGNAL(triggered()),
+                            &msgCenter(), SLOT(sltShowHelpAboutDialog()));
+    }
+    else
+        gActionPool->action(UIActionIndex_Simple_About)->setEnabled(false);
 }
 
 #include "UIMachineMenuBar.moc"
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
index 24851df..5eb78a0 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
@@ -881,8 +881,8 @@ void UIMachineView::scrollContentsBy(int dx, int dy)
     session().GetConsole().GetDisplay().ViewportChanged(screenId(),
                             contentsX(),
                             contentsY(),
-                            contentsWidth(),
-                            contentsHeight());
+                            visibleWidth(),
+                            visibleHeight());
 }
 
 
@@ -1005,8 +1005,8 @@ bool UIMachineView::eventFilter(QObject *pWatched, QEvent *pEvent)
                 session().GetConsole().GetDisplay().ViewportChanged(screenId(),
                         contentsX(),
                         contentsY(),
-                        contentsWidth(),
-                        contentsHeight());
+                        visibleWidth(),
+                        visibleHeight());
                 break;
             }
             default:
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp
index db528ac..08fa1b1 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp
@@ -443,11 +443,21 @@ void UIMachineWindow::cleanupMachineView()
 
 void UIMachineWindow::handleScreenCountChange()
 {
+    /* Ignore if window is minimized: */
+    if (isMinimized())
+        return;
+
+    /* Make sure window is in necessary mode: */
     showInNecessaryMode();
 }
 
 void UIMachineWindow::handleScreenGeometryChange()
 {
+    /* Ignore if window is minimized: */
+    if (isMinimized())
+        return;
+
+    /* Make sure window is in necessary mode: */
     showInNecessaryMode();
 }
 
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp
index ed5e27f..e336f57 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMultiScreenLayout.cpp
@@ -359,6 +359,10 @@ void UIMultiScreenLayout::cleanupViewMenu()
 
 void UIMultiScreenLayout::updateMenuActions(bool fWithSave)
 {
+    /* Make sure view-menu was set: */
+    if (!m_pViewMenu)
+        return;
+
     /* Get the list of all view-menu actions: */
     QList<QAction*> viewMenuActions = gActionPool->action(UIActionIndexRuntime_Menu_View)->menu()->actions();
     /* Get the list of all view related actions: */
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
index 89debb9..fcfffe0 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
@@ -76,6 +76,8 @@
 #include "CHostVideoInputDevice.h"
 #include "CSnapshot.h"
 #include "CMedium.h"
+#include "CExtPack.h"
+#include "CExtPackManager.h"
 
 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
 static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *);
@@ -127,6 +129,7 @@ UISession::UISession(UIMachine *pMachine, CSession &sessionReference)
     , m_pMenuPool(0)
     , m_machineStatePrevious(KMachineState_Null)
     , m_machineState(session().GetMachine().GetState())
+    , m_fIsExtensionPackUsable(false)
     , m_requestedVisualStateType(UIVisualStateType_Invalid)
 #ifdef Q_WS_WIN
     , m_alphaCursor(0)
@@ -1106,6 +1109,34 @@ void UISession::loadSessionSettings()
 
     /* Load extra-data settings: */
     {
+        /* Extension pack stuff: */
+        CExtPack extPack = vboxGlobal().virtualBox().GetExtensionPackManager().Find(GUI_ExtPackName);
+        m_fIsExtensionPackUsable = !extPack.isNull() && extPack.GetUsable();
+
+        /* Runtime menu settings: */
+#ifdef Q_WS_MAC
+        m_allowedActionsMenuApplication = (RuntimeMenuApplicationActionType)
+                                          (vboxGlobal().restrictedRuntimeMenuApplicationActionTypes(machine) ^
+                                           RuntimeMenuApplicationActionType_All);
+#endif /* Q_WS_MAC */
+        m_allowedActionsMenuMachine     = (RuntimeMenuMachineActionType)
+                                          (vboxGlobal().restrictedRuntimeMenuMachineActionTypes(machine) ^
+                                           RuntimeMenuMachineActionType_All);
+        m_allowedActionsMenuView        = (RuntimeMenuViewActionType)
+                                          (vboxGlobal().restrictedRuntimeMenuViewActionTypes(machine) ^
+                                           RuntimeMenuViewActionType_All);
+        m_allowedActionsMenuDevices     = (RuntimeMenuDevicesActionType)
+                                          (vboxGlobal().restrictedRuntimeMenuDevicesActionTypes(machine) ^
+                                           RuntimeMenuDevicesActionType_All);
+#ifdef VBOX_WITH_DEBUGGER_GUI
+        m_allowedActionsMenuDebugger    = (RuntimeMenuDebuggerActionType)
+                                          (vboxGlobal().restrictedRuntimeMenuDebuggerActionTypes(machine) ^
+                                           RuntimeMenuDebuggerActionType_All);
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+        m_allowedActionsMenuHelp        = (RuntimeMenuHelpActionType)
+                                          (vboxGlobal().restrictedRuntimeMenuHelpActionTypes(machine) ^
+                                           RuntimeMenuHelpActionType_All);
+
         /* Temporary: */
         QString strSettings;
 
@@ -1507,8 +1538,8 @@ void UISession::reinitMenuPool()
             }
         }
 
-        /* Show/Hide Network Adapters action depending on overall adapters activity status: */
-        gActionPool->action(UIActionIndexRuntime_Simple_NetworkSettings)->setVisible(fAtLeastOneAdapterActive);
+        /* Show/Hide Network sub-menu depending on overall adapters activity status: */
+        gActionPool->action(UIActionIndexRuntime_Menu_Network)->setVisible(fAtLeastOneAdapterActive);
     }
 
     /* USB stuff: */
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h
index 15e2906..6543c13 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h
@@ -93,6 +93,32 @@ public:
     QMenuBar* newMenuBar(RuntimeMenuType fOptions = RuntimeMenuType_All);
     QCursor cursor() const { return m_cursor; }
 
+    /** @name Extension Pack stuff.
+     ** @{ */
+    /** Determines whether extension pack installed and usable. */
+    bool isExtensionPackUsable() const { return m_fIsExtensionPackUsable; }
+    /** @} */
+
+    /** @name Runtime menus configuration stuff.
+     ** @{ */
+#ifdef Q_WS_MAC
+    /** Determines Application menu allowed actions. */
+    RuntimeMenuApplicationActionType allowedActionsMenuApplication() const { return m_allowedActionsMenuApplication; }
+#endif /* Q_WS_MAC */
+    /** Determines Machine menu allowed actions. */
+    RuntimeMenuMachineActionType allowedActionsMenuMachine() const { return m_allowedActionsMenuMachine; }
+    /** Determines View menu allowed actions. */
+    RuntimeMenuViewActionType allowedActionsMenuView() const { return m_allowedActionsMenuView; }
+    /** Determines Devices menu allowed actions. */
+    RuntimeMenuDevicesActionType allowedActionsMenuDevices() const { return m_allowedActionsMenuDevices; }
+#ifdef VBOX_WITH_DEBUGGER_GUI
+    /** Determines Debugger menu allowed actions. */
+    RuntimeMenuDebuggerActionType allowedActionsMenuDebugger() const { return m_allowedActionsMenuDebugger; }
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+    /** Determines Help menu allowed actions. */
+    RuntimeMenuHelpActionType allowedActionsMenuHelp() const { return m_allowedActionsMenuHelp; }
+    /** @} */
+
     /** @name Application Close configuration stuff.
      * @{ */
     /** Returns default close action. */
@@ -312,6 +338,32 @@ private:
     KMachineState m_machineState;
     QCursor m_cursor;
 
+    /** @name Extension Pack variables.
+     ** @{ */
+    /** Determines whether extension pack installed and usable. */
+    bool m_fIsExtensionPackUsable;
+    /** @} */
+
+    /** @name Runtime menus configuration variables.
+     ** @{ */
+#ifdef Q_WS_MAC
+    /** Determines Application menu allowed actions. */
+    RuntimeMenuApplicationActionType m_allowedActionsMenuApplication;
+#endif /* Q_WS_MAC */
+    /** Determines Machine menu allowed actions. */
+    RuntimeMenuMachineActionType m_allowedActionsMenuMachine;
+    /** Determines View menu allowed actions. */
+    RuntimeMenuViewActionType m_allowedActionsMenuView;
+    /** Determines Devices menu allowed actions. */
+    RuntimeMenuDevicesActionType m_allowedActionsMenuDevices;
+#ifdef VBOX_WITH_DEBUGGER_GUI
+    /** Determines Debugger menu allowed actions. */
+    RuntimeMenuDebuggerActionType m_allowedActionsMenuDebugger;
+#endif /* VBOX_WITH_DEBUGGER_GUI */
+    /** Determines Help menu allowed actions. */
+    RuntimeMenuHelpActionType m_allowedActionsMenuHelp;
+    /** @} */
+
     /** @name Visual-state configuration variables.
      ** @{ */
     /** Determines which visual-state should be entered when possible. */
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp
index 71934b7..3fffc3c 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp
@@ -238,8 +238,9 @@ void UIMachineLogicFullscreen::prepareMenu()
     /* Call to base-class: */
     UIMachineLogic::prepareMenu();
 
-    /* Finally update view-menu: */
-    m_pScreenLayout->setViewMenu(gActionPool->action(UIActionIndexRuntime_Menu_View)->menu());
+    /* Finally update view-menu, if necessary: */
+    if (uisession()->allowedActionsMenuView() & RuntimeMenuViewActionType_Multiscreen)
+        m_pScreenLayout->setViewMenu(gActionPool->action(UIActionIndexRuntime_Menu_View)->menu());
 }
 
 void UIMachineLogicFullscreen::cleanupMachineWindows()
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp
index f8102f0..040c6d8 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp
@@ -66,14 +66,6 @@ void UIMachineLogicNormal::sltCheckForRequestedVisualStateType()
     }
 }
 
-void UIMachineLogicNormal::sltPrepareNetworkAdaptersMenu()
-{
-    QMenu *menu = qobject_cast<QMenu*>(sender());
-    AssertMsg(menu, ("This slot should be called only on Network Adapters menu show!\n"));
-    menu->clear();
-    menu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_NetworkSettings));
-}
-
 void UIMachineLogicNormal::sltPrepareSharedFoldersMenu()
 {
     QMenu *menu = qobject_cast<QMenu*>(sender());
@@ -87,8 +79,8 @@ void UIMachineLogicNormal::sltPrepareVideoCaptureMenu()
     QMenu *pMenu = qobject_cast<QMenu*>(sender());
     AssertMsg(pMenu, ("This slot should be called only on Video Capture menu show!\n"));
     pMenu->clear();
-    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VideoCapture));
     pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Simple_VideoCaptureSettings));
+    pMenu->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VideoCapture));
 }
 
 void UIMachineLogicNormal::sltPrepareMouseIntegrationMenu()
@@ -113,8 +105,6 @@ void UIMachineLogicNormal::prepareActionConnections()
             uisession(), SLOT(sltChangeVisualStateToScale()));
 
     /* "Device" actions connections: */
-    connect(gActionPool->action(UIActionIndexRuntime_Menu_Network)->menu(), SIGNAL(aboutToShow()),
-            this, SLOT(sltPrepareNetworkAdaptersMenu()));
     connect(gActionPool->action(UIActionIndexRuntime_Menu_SharedFolders)->menu(), SIGNAL(aboutToShow()),
             this, SLOT(sltPrepareSharedFoldersMenu()));
     connect(gActionPool->action(UIActionIndexRuntime_Menu_VideoCapture)->menu(), SIGNAL(aboutToShow()),
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.h b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.h
index 880a685..24b1980 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.h
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.h
@@ -39,7 +39,6 @@ private slots:
     void sltCheckForRequestedVisualStateType();
 
     /* Windowed mode functionality: */
-    void sltPrepareNetworkAdaptersMenu();
     void sltPrepareSharedFoldersMenu();
     void sltPrepareVideoCaptureMenu();
     void sltPrepareMouseIntegrationMenu();
diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp
index 714da24..9987050 100644
--- a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp
@@ -239,8 +239,9 @@ void UIMachineLogicSeamless::prepareMenu()
     /* Call to base-class: */
     UIMachineLogic::prepareMenu();
 
-    /* Finally update view-menu: */
-    m_pScreenLayout->setViewMenu(gActionPool->action(UIActionIndexRuntime_Menu_View)->menu());
+    /* Finally update view-menu, if necessary: */
+    if (uisession()->allowedActionsMenuView() & RuntimeMenuViewActionType_Multiscreen)
+        m_pScreenLayout->setViewMenu(gActionPool->action(UIActionIndexRuntime_Menu_View)->menu());
 }
 
 void UIMachineLogicSeamless::cleanupMachineWindows()
diff --git a/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp b/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp
index 0844c34..20ad4b9 100644
--- a/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp
@@ -65,9 +65,6 @@
 # include "VBoxUtils.h"
 # include "UIWindowMenuManager.h"
 # include "UIImageTools.h"
-# if 0  /* disabled until #7112 resolved */
-#  include "UICocoaApplication.h"
-# endif /* disabled until #7112 resolved */
 #endif /* Q_WS_MAC */
 
 /* Other VBox stuff: */
@@ -337,11 +334,7 @@ void UISelectorWindow::sltShowPreferencesDialog()
 
 void UISelectorWindow::sltPerformExit()
 {
-#if 0  /* disabled until #7112 resolved */
-    QApplication::quit();
-#else  /* disabled until #7112 resolved */
     close();
-#endif /* disabled until #7112 resolved */
 }
 
 void UISelectorWindow::sltShowAddMachineDialog(const QString &strFileName /* = QString() */)
@@ -1062,23 +1055,8 @@ void UISelectorWindow::polishEvent(QShowEvent*)
 }
 
 #ifdef Q_WS_MAC
-# if 0  /* disabled until #7112 resolved */
-/** MacOS X host: Hides VM selector UI instead of closing. */
-void UISelectorWindow::closeEvent(QCloseEvent *pEvent)
-{
-    pEvent->ignore();
-    UICocoaApplication::instance()->hide();
-}
-# endif /* disabled until #7112 resolved */
-
 bool UISelectorWindow::eventFilter(QObject *pObject, QEvent *pEvent)
 {
-# if 0  /* disabled until #7112 resolved */
-    /* If we got broadcast qApp close-event, quit app.. */
-    if (pObject == qApp && pEvent->type() == QEvent::Close)
-        return true;
-# endif /* disabled until #7112 resolved */
-
     /* Ignore for non-active window: */
     if (!isActiveWindow())
         return QIWithRetranslateUI2<QMainWindow>::eventFilter(pObject, pEvent);
@@ -1110,9 +1088,13 @@ void UISelectorWindow::prepareIcon()
 {
     /* Prepare application icon: */
 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC))
-    /* On Win32, it's built-in to the executable.
-     * On Mac OS X the icon referenced in info.plist is used. */
-    setWindowIcon(QIcon(":/VirtualBox_48px.png"));
+    /* On Win host it's built-in to the executable.
+     * On Mac OS X the icon referenced in info.plist is used.
+     * On X11 we will provide as much icons as we can.. */
+    QIcon icon(":/VirtualBox.svg");
+    icon.addFile(":/VirtualBox_48px.png");
+    icon.addFile(":/VirtualBox_64px.png");
+    setWindowIcon(icon);
 #endif
 }
 
diff --git a/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.h b/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.h
index 64b05ba..c908768 100644
--- a/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.h
+++ b/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.h
@@ -110,9 +110,6 @@ private:
     void showEvent(QShowEvent *pEvent);
     void polishEvent(QShowEvent *pEvent);
 #ifdef Q_WS_MAC
-# if 0  /* disabled until #7112 resolved */
-    void closeEvent(QCloseEvent *pEvent);
-# endif /* disabled until #7112 resolved */
     bool eventFilter(QObject *pObject, QEvent *pEvent);
 #endif /* Q_WS_MAC */
 
diff --git a/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp b/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp
index ab558ce..f7ac883 100644
--- a/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp
@@ -29,6 +29,8 @@
 
 /* COM includes: */
 #include "CVRDEServer.h"
+#include "CExtPackManager.h"
+#include "CExtPack.h"
 
 UIMachineSettingsDisplay::UIMachineSettingsDisplay()
     : m_iMinVRAM(0)
@@ -388,6 +390,18 @@ bool UIMachineSettingsDisplay::validate(QList<UIValidationMessage> &messages)
         UIValidationMessage message;
         message.first = VBoxGlobal::removeAccelMark(m_pTabWidget->tabText(1));
 
+#ifdef VBOX_WITH_EXTPACK
+        CExtPack extPack = vboxGlobal().virtualBox().GetExtensionPackManager().Find(GUI_ExtPackName);
+        if (m_pCheckboxRemoteDisplay->isChecked() && (extPack.isNull() || !extPack.GetUsable()))
+        {
+            message.second << tr("Remote Display is currently enabled for this virtual machine. "
+                                 "However, this requires the <b>%1</b> to be installed. "
+                                 "Please install the Extension Pack from the VirtualBox download site as "
+                                 "otherwise your VM will be started with Remote Display disabled.")
+                                 .arg(GUI_ExtPackName);
+        }
+#endif /* VBOX_WITH_EXTPACK */
+
         /* Check VRDE server port: */
         if (m_pEditorRemoteDisplayPort->text().trimmed().isEmpty())
         {
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIApplianceImportEditorWidget.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIApplianceImportEditorWidget.cpp
index 51e69ce..3a0a1cd 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIApplianceImportEditorWidget.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIApplianceImportEditorWidget.cpp
@@ -114,9 +114,9 @@ bool UIApplianceImportEditorWidget::setFile(const QString& strFile)
         }
         if (!fResult)
         {
-            if (progress.isNull())
+            if (!m_pAppliance->isOk())
                 msgCenter().cannotImportAppliance(*m_pAppliance, this);
-            else
+            else if (!progress.isNull() && (!progress.isOk() || progress.GetResultCode() != 0))
                 msgCenter().cannotImportAppliance(progress, m_pAppliance->GetPath(), this);
             /* Delete the appliance in a case of an error */
             delete m_pAppliance;
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp
index b2f44db..7183eee 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp
@@ -27,6 +27,8 @@
 /* GUI includes: */
 #include "UIHostComboEditor.h"
 #include "VBoxGlobal.h"
+#include "QIToolButton.h"
+#include "UIIconPool.h"
 
 #ifdef Q_WS_WIN
 # undef LOWORD
@@ -313,13 +315,71 @@ bool UIHostCombo::isValidKeyCombo(const QString &strKeyCombo)
 
 
 UIHostComboEditor::UIHostComboEditor(QWidget *pParent)
-    : QLineEdit(pParent)
-    , m_pReleaseTimer(0)
+    : QIWithRetranslateUI<QWidget>(pParent)
+{
+    /* Prepare: */
+    prepare();
+}
+
+void UIHostComboEditor::prepare()
+{
+    /* Configure self: */
+    setAutoFillBackground(true);
+    /* Create layout: */
+    QHBoxLayout *pLayout = new QHBoxLayout(this);
+    {
+        /* Configure layout: */
+        pLayout->setSpacing(4);
+        pLayout->setContentsMargins(0, 0, 0, 0);
+        /* Create UIHostComboEditorPrivate instance: */
+        m_pEditor = new UIHostComboEditorPrivate;
+        {
+            /* Configure UIHostComboEditorPrivate instance: */
+            setFocusProxy(m_pEditor);
+        }
+        /* Create 'clear' tool-button: */
+        m_pButtonClear = new QIToolButton;
+        {
+            /* Configure 'clear' tool-button: */
+            m_pButtonClear->removeBorder();
+            m_pButtonClear->setIcon(UIIconPool::iconSet(":/eraser_16px.png"));
+            connect(m_pButtonClear, SIGNAL(clicked(bool)), m_pEditor, SLOT(sltClear()));
+        }
+        /* Add widgets to layout: */
+        pLayout->addWidget(m_pEditor);
+        pLayout->addWidget(m_pButtonClear);
+    }
+    /* Translate finally: */
+    retranslateUi();
+}
+
+void UIHostComboEditor::retranslateUi()
+{
+    /* Translate 'clear' tool-button: */
+    m_pButtonClear->setToolTip(QApplication::translate("UIHotKeyEditor", "Unset shortcut"));
+}
+
+void UIHostComboEditor::setCombo(const UIHostComboWrapper &strCombo)
+{
+    /* Pass combo to child: */
+    m_pEditor->setCombo(strCombo);
+}
+
+UIHostComboWrapper UIHostComboEditor::combo() const
+{
+    /* Acquire combo from child: */
+    return m_pEditor->combo();
+}
+
+
+UIHostComboEditorPrivate::UIHostComboEditorPrivate()
+    : m_pReleaseTimer(0)
     , m_fStartNewSequence(true)
 {
     /* Configure widget: */
     setAttribute(Qt::WA_NativeWindow);
     setContextMenuPolicy(Qt::NoContextMenu);
+    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
     connect(this, SIGNAL(selectionChanged()), this, SLOT(sltDeselect()));
 
     /* Setup release-pending-keys timer: */
@@ -334,20 +394,20 @@ UIHostComboEditor::UIHostComboEditor(QWidget *pParent)
 
 #ifdef Q_WS_MAC
     m_uDarwinKeyModifiers = 0;
-    UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditor::darwinEventHandlerProc, this);
+    UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
     ::DarwinGrabKeyboard(false /* just modifiers */);
 #endif /* Q_WS_MAC */
 }
 
-UIHostComboEditor::~UIHostComboEditor()
+UIHostComboEditorPrivate::~UIHostComboEditorPrivate()
 {
 #ifdef Q_WS_MAC
     ::DarwinReleaseKeyboard();
-    UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditor::darwinEventHandlerProc, this);
+    UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
 #endif /* Q_WS_MAC */
 }
 
-void UIHostComboEditor::setCombo(const UIHostComboWrapper &strCombo)
+void UIHostComboEditorPrivate::setCombo(const UIHostComboWrapper &strCombo)
 {
     /* Cleanup old combo: */
     m_shownKeys.clear();
@@ -360,7 +420,7 @@ void UIHostComboEditor::setCombo(const UIHostComboWrapper &strCombo)
     updateText();
 }
 
-UIHostComboWrapper UIHostComboEditor::combo() const
+UIHostComboWrapper UIHostComboEditorPrivate::combo() const
 {
     /* Compose current combination: */
     QStringList keyCodeStringList;
@@ -371,15 +431,19 @@ UIHostComboWrapper UIHostComboEditor::combo() const
     return keyCodeStringList.isEmpty() ? "0" : keyCodeStringList.join(",");
 }
 
-void UIHostComboEditor::sltDeselect()
+void UIHostComboEditorPrivate::sltDeselect()
 {
     deselect();
 }
 
-void UIHostComboEditor::sltClear()
+void UIHostComboEditorPrivate::sltClear()
 {
+    /* Cleanup combo: */
     m_shownKeys.clear();
+    /* Update text: */
     updateText();
+    /* Move the focus to text-field: */
+    setFocus();
 }
 
 #ifdef Q_WS_WIN
@@ -452,7 +516,7 @@ static bool isSyntheticLCtrl(MSG *pMsg)
     return true;
 }
 
-bool UIHostComboEditor::winEvent(MSG *pMsg, long* /* pResult */)
+bool UIHostComboEditorPrivate::winEvent(MSG *pMsg, long* /* pResult */)
 {
     switch (pMsg->message)
     {
@@ -483,7 +547,7 @@ bool UIHostComboEditor::winEvent(MSG *pMsg, long* /* pResult */)
 #ifdef Q_WS_X11
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-bool UIHostComboEditor::x11Event(XEvent *pEvent)
+bool UIHostComboEditorPrivate::x11Event(XEvent *pEvent)
 {
     switch (pEvent->type)
     {
@@ -510,9 +574,9 @@ bool UIHostComboEditor::x11Event(XEvent *pEvent)
 
 #ifdef Q_WS_MAC
 /* static */
-bool UIHostComboEditor::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
+bool UIHostComboEditorPrivate::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
 {
-    UIHostComboEditor *pEditor = static_cast<UIHostComboEditor*>(pvUser);
+    UIHostComboEditorPrivate *pEditor = static_cast<UIHostComboEditorPrivate*>(pvUser);
     EventRef inEvent = (EventRef)pvCarbonEvent;
     UInt32 EventClass = ::GetEventClass(inEvent);
     if (EventClass == kEventClassKeyboard)
@@ -520,7 +584,7 @@ bool UIHostComboEditor::darwinEventHandlerProc(const void *pvCocoaEvent, const v
     return false;
 }
 
-bool UIHostComboEditor::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
+bool UIHostComboEditorPrivate::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
 {
     /* Ignore key changes unless we're the focus widget: */
     if (!hasFocus())
@@ -566,11 +630,13 @@ bool UIHostComboEditor::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef i
 }
 #endif /* Q_WS_MAC */
 
-void UIHostComboEditor::keyPressEvent(QKeyEvent *pEvent)
+void UIHostComboEditorPrivate::keyPressEvent(QKeyEvent *pEvent)
 {
     /* Ignore most of key presses... */
     switch (pEvent->key())
     {
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
         case Qt::Key_Tab:
         case Qt::Key_Backtab:
         case Qt::Key_Escape:
@@ -586,7 +652,7 @@ void UIHostComboEditor::keyPressEvent(QKeyEvent *pEvent)
     }
 }
 
-void UIHostComboEditor::keyReleaseEvent(QKeyEvent *pEvent)
+void UIHostComboEditorPrivate::keyReleaseEvent(QKeyEvent *pEvent)
 {
     /* Ignore most of key presses... */
     switch (pEvent->key())
@@ -606,19 +672,19 @@ void UIHostComboEditor::keyReleaseEvent(QKeyEvent *pEvent)
     }
 }
 
-void UIHostComboEditor::mousePressEvent(QMouseEvent *pEvent)
+void UIHostComboEditorPrivate::mousePressEvent(QMouseEvent *pEvent)
 {
     /* Handle like for usual QWidget: */
     QWidget::mousePressEvent(pEvent);
 }
 
-void UIHostComboEditor::mouseReleaseEvent(QMouseEvent *pEvent)
+void UIHostComboEditorPrivate::mouseReleaseEvent(QMouseEvent *pEvent)
 {
     /* Handle like for usual QWidget: */
     QWidget::mouseReleaseEvent(pEvent);
 }
 
-void UIHostComboEditor::sltReleasePendingKeys()
+void UIHostComboEditorPrivate::sltReleasePendingKeys()
 {
     /* Stop the timer, we process all pending keys at once: */
     m_pReleaseTimer->stop();
@@ -641,7 +707,7 @@ void UIHostComboEditor::sltReleasePendingKeys()
     updateText();
 }
 
-bool UIHostComboEditor::processKeyEvent(int iKeyCode, bool fKeyPress)
+bool UIHostComboEditorPrivate::processKeyEvent(int iKeyCode, bool fKeyPress)
 {
     /* Check if symbol is valid else pass it to Qt: */
     if (!UINativeHotKey::isValidKey(iKeyCode))
@@ -694,9 +760,9 @@ bool UIHostComboEditor::processKeyEvent(int iKeyCode, bool fKeyPress)
     return true;
 }
 
-void UIHostComboEditor::updateText()
+void UIHostComboEditorPrivate::updateText()
 {
     QStringList shownKeyNames(m_shownKeys.values());
-    setText(shownKeyNames.isEmpty() ? tr("None") : shownKeyNames.join(" + "));
+    setText(shownKeyNames.isEmpty() ? UIHostComboEditor::tr("None") : shownKeyNames.join(" + "));
 }
 
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h
index ac40dd2..cac1fd5 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h
@@ -25,6 +25,13 @@
 #include <QMap>
 #include <QSet>
 
+/* GUI includes: */
+#include "QIWithRetranslateUI.h"
+
+/* Forward declarations: */
+class UIHostComboEditorPrivate;
+class QIToolButton;
+
 /* Native hot-key namespace to unify
  * all the related hot-key processing stuff: */
 namespace UINativeHotKey
@@ -68,16 +75,45 @@ private:
 };
 Q_DECLARE_METATYPE(UIHostComboWrapper);
 
-/* Host-combo editor widget: */
-class UIHostComboEditor : public QLineEdit
+/** Host-combo editor widget. */
+class UIHostComboEditor : public QIWithRetranslateUI<QWidget>
 {
     Q_OBJECT;
     Q_PROPERTY(UIHostComboWrapper combo READ combo WRITE setCombo USER true);
 
 public:
 
+    /** Constructs host-combo editor for passed @a pParent. */
     UIHostComboEditor(QWidget *pParent);
-    ~UIHostComboEditor();
+
+private:
+
+    /** Prepares widget content. */
+    void prepare();
+
+    /** Translates widget content. */
+    void retranslateUi();
+
+    /** Defines host-combo sequence. */
+    void setCombo(const UIHostComboWrapper &strCombo);
+    /** Returns host-combo sequence. */
+    UIHostComboWrapper combo() const;
+
+    /** UIHostComboEditorPrivate instance. */
+    UIHostComboEditorPrivate *m_pEditor;
+    /** <b>Clear</b> QIToolButton instance. */
+    QIToolButton *m_pButtonClear;
+};
+
+/* Host-combo editor widget private stuff: */
+class UIHostComboEditorPrivate : public QLineEdit
+{
+    Q_OBJECT;
+
+public:
+
+    UIHostComboEditorPrivate();
+    ~UIHostComboEditorPrivate();
 
     void setCombo(const UIHostComboWrapper &strCombo);
     UIHostComboWrapper combo() const;
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UINameAndSystemEditor.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UINameAndSystemEditor.cpp
index 4d0c6a5..1735d1f 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UINameAndSystemEditor.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UINameAndSystemEditor.cpp
@@ -196,14 +196,20 @@ void UINameAndSystemEditor::sltFamilyChanged(int iIndex)
     /* Or select WinXP item for Windows family as default: */
     else if (strFamilyId == "Windows")
     {
-        int iIndexWinXP = m_pTypeCombo->findData("WindowsXP", TypeID);
+        QString strDefaultID = "WindowsXP";
+        if (ARCH_BITS == 64 && m_fSupportsHWVirtEx && m_fSupportsLongMode)
+            strDefaultID += "_64";
+        int iIndexWinXP = m_pTypeCombo->findData(strDefaultID, TypeID);
         if (iIndexWinXP != -1)
             m_pTypeCombo->setCurrentIndex(iIndexWinXP);
     }
     /* Or select Ubuntu item for Linux family as default: */
     else if (strFamilyId == "Linux")
     {
-        int iIndexUbuntu = m_pTypeCombo->findData("Ubuntu", TypeID);
+        QString strDefaultID = "Ubuntu";
+        if (ARCH_BITS == 64 && m_fSupportsHWVirtEx && m_fSupportsLongMode)
+            strDefaultID += "_64";
+        int iIndexUbuntu = m_pTypeCombo->findData(strDefaultID, TypeID);
         if (iIndexUbuntu != -1)
             m_pTypeCombo->setCurrentIndex(iIndexUbuntu);
     }
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.cpp
index 35ea9ed..571fd2b 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.cpp
@@ -29,13 +29,11 @@
 
 UIPopupPane::UIPopupPane(QWidget *pParent,
                          const QString &strMessage, const QString &strDetails,
-                         const QMap<int, QString> &buttonDescriptions,
-                         bool fProposeAutoConfirmation)
+                         const QMap<int, QString> &buttonDescriptions)
     : QIWithRetranslateUI<QWidget>(pParent)
     , m_fPolished(false)
     , m_iLayoutMargin(10), m_iLayoutSpacing(5)
     , m_strMessage(strMessage), m_strDetails(strDetails)
-    , m_fProposeAutoConfirmation(fProposeAutoConfirmation)
     , m_buttonDescriptions(buttonDescriptions)
     , m_fShown(false)
     , m_pShowAnimation(0)
@@ -78,17 +76,6 @@ void UIPopupPane::setDetails(const QString &strDetails)
     m_strDetails = strDetails;
 }
 
-void UIPopupPane::setProposeAutoConfirmation(bool fPropose)
-{
-    /* Make sure the auto-confirmation-proposal has changed: */
-    if (m_fProposeAutoConfirmation == fPropose)
-        return;
-
-    /* Fetch new auto-confirmation-proposal: */
-    m_fProposeAutoConfirmation = fPropose;
-    m_pTextPane->setProposeAutoConfirmation(m_fProposeAutoConfirmation);
-}
-
 void UIPopupPane::setMinimumSizeHint(const QSize &minimumSizeHint)
 {
     /* Make sure the size-hint has changed: */
@@ -198,7 +185,7 @@ void UIPopupPane::sltUpdateSizeHint()
 void UIPopupPane::sltButtonClicked(int iButtonID)
 {
     /* Complete popup with corresponding code: */
-    done(iButtonID & AlertButtonMask);
+    done(iButtonID);
 }
 
 void UIPopupPane::prepare()
@@ -227,7 +214,7 @@ void UIPopupPane::prepareBackground()
 void UIPopupPane::prepareContent()
 {
     /* Create message-label: */
-    m_pTextPane = new UIPopupPaneTextPane(this, m_strMessage, m_fProposeAutoConfirmation, m_fFocused);
+    m_pTextPane = new UIPopupPaneTextPane(this, m_strMessage, m_fFocused);
     {
         /* Prepare label: */
         connect(this, SIGNAL(sigProposeTextPaneWidth(int)), m_pTextPane, SLOT(sltHandleProposalForWidth(int)));
@@ -447,10 +434,6 @@ void UIPopupPane::paintFrame(QPainter &painter)
 
 void UIPopupPane::done(int iResultCode)
 {
-    /* Was the popup auto-confirmed? */
-    if (m_pTextPane->isAutoConfirmed())
-        iResultCode |= AlertOption_AutoConfirmed;
-
     /* Notify listeners: */
     emit sigDone(iResultCode);
 }
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.h
index 6156c62..b538fb9 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.h
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.h
@@ -70,8 +70,7 @@ public:
     /* Constructor: */
     UIPopupPane(QWidget *pParent,
                 const QString &strMessage, const QString &strDetails,
-                const QMap<int, QString> &buttonDescriptions,
-                bool fProposeAutoConfirmation);
+                const QMap<int, QString> &buttonDescriptions);
 
     /* API: Recall stuff: */
     void recall();
@@ -80,9 +79,6 @@ public:
     void setMessage(const QString &strMessage);
     void setDetails(const QString &strDetails);
 
-    /* API: Auto-confirmation stuff: */
-    void setProposeAutoConfirmation(bool fPropose);
-
     /* API: Layout stuff: */
     QSize minimumSizeHint() const { return m_minimumSizeHint; }
     void setMinimumSizeHint(const QSize &minimumSizeHint);
@@ -148,9 +144,6 @@ private:
     /* Variables: Text stuff: */
     QString m_strMessage, m_strDetails;
 
-    /* Variables: Auto-confirmation stuff: */
-    bool m_fProposeAutoConfirmation;
-
     /* Variables: Button stuff: */
     QMap<int, QString> m_buttonDescriptions;
 
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneButtonPane.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneButtonPane.cpp
index 84d02bf..c23bfe2 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneButtonPane.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneButtonPane.cpp
@@ -18,6 +18,7 @@
  */
 
 /* Qt includes: */
+#include <QApplication>
 #include <QHBoxLayout>
 #include <QVBoxLayout>
 #include <QKeyEvent>
@@ -172,11 +173,19 @@ QString UIPopupPaneButtonPane::defaultToolTip(int iButtonID)
     QString strToolTip;
     switch (iButtonID & AlertButtonMask)
     {
-        case AlertButton_Ok:      strToolTip = QIMessageBox::tr("OK");     break;
-        case AlertButton_Cancel:  strToolTip = QIMessageBox::tr("Cancel"); break;
-        case AlertButton_Choice1: strToolTip = QIMessageBox::tr("Yes");    break;
-        case AlertButton_Choice2: strToolTip = QIMessageBox::tr("No");     break;
-        default:                  strToolTip = QString();                  break;
+        case AlertButton_Ok: strToolTip = QIMessageBox::tr("OK"); break;
+        case AlertButton_Cancel:
+        {
+            switch (iButtonID & AlertOptionMask)
+            {
+                case AlertOption_AutoConfirmed: strToolTip = QApplication::translate("UIMessageCenter", "Do not show this message again"); break;
+                default: strToolTip = QIMessageBox::tr("Cancel"); break;
+            }
+            break;
+        }
+        case AlertButton_Choice1: strToolTip = QIMessageBox::tr("Yes"); break;
+        case AlertButton_Choice2: strToolTip = QIMessageBox::tr("No"); break;
+        default: strToolTip = QString(); break;
     }
     return strToolTip;
 }
@@ -187,11 +196,19 @@ QIcon UIPopupPaneButtonPane::defaultIcon(int iButtonID)
     QIcon icon;
     switch (iButtonID & AlertButtonMask)
     {
-        case AlertButton_Ok:      icon = UIIconPool::iconSet(":/ok_16px.png"); break;
-        case AlertButton_Cancel:  icon = UIIconPool::iconSet(":/cancel_16px.png"); break;
+        case AlertButton_Ok: icon = UIIconPool::iconSet(":/ok_16px.png"); break;
+        case AlertButton_Cancel:
+        {
+            switch (iButtonID & AlertOptionMask)
+            {
+                case AlertOption_AutoConfirmed: icon = UIIconPool::iconSet(":/close_popup_16px.png"); break;
+                default: icon = UIIconPool::iconSet(":/cancel_16px.png"); break;
+            }
+            break;
+        }
         case AlertButton_Choice1: break;
         case AlertButton_Choice2: break;
-        default:                  break;
+        default: break;
     }
     return icon;
 }
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.cpp
index f9b9b54..a412c4a 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.cpp
@@ -25,16 +25,13 @@
 #include "UIPopupPaneTextPane.h"
 #include "UIAnimationFramework.h"
 
-UIPopupPaneTextPane::UIPopupPaneTextPane(QWidget *pParent, const QString &strText,
-                                         bool fProposeAutoConfirmation, bool fFocused)
-    : QIWithRetranslateUI<QWidget>(pParent)
+UIPopupPaneTextPane::UIPopupPaneTextPane(QWidget *pParent, const QString &strText, bool fFocused)
+    : QWidget(pParent)
     , m_iLayoutMargin(0)
     , m_iLayoutSpacing(10)
     , m_strText(strText)
     , m_pLabel(0)
     , m_iDesiredLabelWidth(-1)
-    , m_pAutoConfirmCheckBox(0)
-    , m_fProposeAutoConfirmation(fProposeAutoConfirmation)
     , m_fFocused(fFocused)
     , m_pAnimation(0)
 {
@@ -56,31 +53,6 @@ void UIPopupPaneTextPane::setText(const QString &strText)
     updateSizeHint();
 }
 
-void UIPopupPaneTextPane::setProposeAutoConfirmation(bool fPropose)
-{
-    /* Make sure the auto-confirmation-proposal has changed: */
-    if (m_fProposeAutoConfirmation == fPropose)
-        return;
-
-    /* Fetch new auto-confirmation-proposal: */
-    m_fProposeAutoConfirmation = fPropose;
-
-    /* Update size-hint: */
-    updateSizeHint();
-}
-
-bool UIPopupPaneTextPane::autoConfirmationProposed() const
-{
-    return m_fProposeAutoConfirmation;
-}
-
-bool UIPopupPaneTextPane::isAutoConfirmed() const
-{
-    return autoConfirmationProposed() &&
-           m_pAutoConfirmCheckBox &&
-           m_pAutoConfirmCheckBox->isChecked();
-}
-
 QSize UIPopupPaneTextPane::minimumSizeHint() const
 {
     /* Check if desired-width set: */
@@ -115,27 +87,6 @@ void UIPopupPaneTextPane::layoutContent()
     /* Label: */
     m_pLabel->move(m_iLayoutMargin, m_iLayoutMargin);
     m_pLabel->resize(qMin(iWidth, iLabelWidth), qMin(iHeight, iLabelHeight));
-
-    /* Check-box: */
-    if (m_fProposeAutoConfirmation)
-    {
-        /* Variables: */
-        const int iCheckBoxWidth = m_checkBoxSizeHint.width();
-        const int iCheckBoxHeight = m_checkBoxSizeHint.height();
-        const int iCheckBoxY = m_iLayoutMargin + iLabelHeight + m_iLayoutSpacing;
-        /* Layout check-box: */
-        if (iHeight - m_iLayoutMargin - iCheckBoxHeight - iCheckBoxY >= 0)
-        {
-            m_pAutoConfirmCheckBox->move(m_iLayoutMargin, iCheckBoxY);
-            m_pAutoConfirmCheckBox->resize(iCheckBoxWidth, iCheckBoxHeight);
-            if (m_pAutoConfirmCheckBox->isHidden())
-                m_pAutoConfirmCheckBox->show();
-        }
-        else if (!m_pAutoConfirmCheckBox->isHidden())
-            m_pAutoConfirmCheckBox->hide();
-    }
-    else if (!m_pAutoConfirmCheckBox->isHidden())
-        m_pAutoConfirmCheckBox->hide();
 }
 
 void UIPopupPaneTextPane::sltHandleProposalForWidth(int iWidth)
@@ -199,17 +150,6 @@ void UIPopupPaneTextPane::prepareContent()
         m_pLabel->setFocusPolicy(Qt::NoFocus);
         m_pLabel->setText(m_strText);
     }
-
-    /* Create check-box: */
-    m_pAutoConfirmCheckBox = new QCheckBox(this);
-    {
-        /* Prepare check-box: */
-        m_pAutoConfirmCheckBox->setFont(tuneFont(m_pAutoConfirmCheckBox->font()));
-        m_pAutoConfirmCheckBox->setFocusPolicy(Qt::NoFocus);
-    }
-
-    /* Translate UI finally: */
-    retranslateUi();
 }
 
 void UIPopupPaneTextPane::prepareAnimation()
@@ -222,12 +162,6 @@ void UIPopupPaneTextPane::prepareAnimation()
                                                          SIGNAL(sigFocusEnter()), SIGNAL(sigFocusLeave()), m_fFocused);
 }
 
-void UIPopupPaneTextPane::retranslateUi()
-{
-    /* Translate auto-confirm check-box: */
-    m_pAutoConfirmCheckBox->setText(QApplication::translate("UIMessageCenter", "Do not show this message again"));
-}
-
 void UIPopupPaneTextPane::updateSizeHint()
 {
     /* Recalculate collapsed size-hint: */
@@ -241,16 +175,8 @@ void UIPopupPaneTextPane::updateSizeHint()
     {
         /* Recalculate label size-hint: */
         m_labelSizeHint = QSize(m_iDesiredLabelWidth, m_pLabel->heightForWidth(m_iDesiredLabelWidth));
-        /* Recalculate check-box size-hint: */
-        m_checkBoxSizeHint = m_fProposeAutoConfirmation ? m_pAutoConfirmCheckBox->sizeHint() : QSize();
         /* Expanded size-hint contains full-size label: */
         m_expandedSizeHint = m_labelSizeHint;
-        /* Expanded size-hint can contain check-box: */
-        if (m_checkBoxSizeHint.isValid())
-        {
-            m_expandedSizeHint.setWidth(qMax(m_expandedSizeHint.width(), m_checkBoxSizeHint.width()));
-            m_expandedSizeHint.setHeight(m_expandedSizeHint.height() + m_iLayoutSpacing + m_checkBoxSizeHint.height());
-        }
     }
 
     /* Update current size-hint: */
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.h
index 70bbc4e..4f234ec 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.h
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPaneTextPane.h
@@ -22,16 +22,12 @@
 /* Qt includes: */
 #include <QWidget>
 
-/* GUI includes: */
-#include "QIWithRetranslateUI.h"
-
 /* Forward declarations: */
 class QLabel;
-class QCheckBox;
 class UIAnimation;
 
 /* Popup-pane text-pane prototype class: */
-class UIPopupPaneTextPane : public QIWithRetranslateUI<QWidget>
+class UIPopupPaneTextPane : public QWidget
 {
     Q_OBJECT;
     Q_PROPERTY(QSize collapsedSizeHint READ collapsedSizeHint);
@@ -50,17 +46,11 @@ signals:
 public:
 
     /* Constructor: */
-    UIPopupPaneTextPane(QWidget *pParent, const QString &strText,
-                        bool fProposeAutoConfirmation, bool fFocused);
+    UIPopupPaneTextPane(QWidget *pParent, const QString &strText, bool fFocused);
 
     /* API: Text stuff: */
     void setText(const QString &strText);
 
-    /* API: Auto-confirmation stuff: */
-    void setProposeAutoConfirmation(bool fPropose);
-    bool autoConfirmationProposed() const;
-    bool isAutoConfirmed() const;
-
     /* API: Layout stuff: */
     QSize minimumSizeHint() const;
     void setMinimumSizeHint(const QSize &minimumSizeHint);
@@ -82,9 +72,6 @@ private:
     void prepareContent();
     void prepareAnimation();
 
-    /* Helper: Translate stuff: */
-    void retranslateUi();
-
     /* Helper: Layout stuff: */
     void updateSizeHint();
 
@@ -99,7 +86,6 @@ private:
     const int m_iLayoutMargin;
     const int m_iLayoutSpacing;
     QSize m_labelSizeHint;
-    QSize m_checkBoxSizeHint;
     QSize m_collapsedSizeHint;
     QSize m_expandedSizeHint;
     QSize m_minimumSizeHint;
@@ -108,8 +94,6 @@ private:
     QString m_strText;
     QLabel *m_pLabel;
     int m_iDesiredLabelWidth;
-    QCheckBox *m_pAutoConfirmCheckBox;
-    bool m_fProposeAutoConfirmation;
 
     /* Variables: Focus stuff: */
     bool m_fFocused;
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.cpp
index 2f4317b..a075451 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.cpp
@@ -49,14 +49,12 @@ bool UIPopupStack::exists(const QString &strPopupPaneID) const
 
 void UIPopupStack::createPopupPane(const QString &strPopupPaneID,
                                    const QString &strMessage, const QString &strDetails,
-                                   const QMap<int, QString> &buttonDescriptions,
-                                   bool fProposeAutoConfirmation)
+                                   const QMap<int, QString> &buttonDescriptions)
 {
     /* Redirect request to viewport: */
     m_pScrollViewport->createPopupPane(strPopupPaneID,
                                        strMessage, strDetails,
-                                       buttonDescriptions,
-                                       fProposeAutoConfirmation);
+                                       buttonDescriptions);
 
     /* Propagate width: */
     propagateWidth();
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.h
index 037c086..e4635c1 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.h
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.h
@@ -56,8 +56,7 @@ public:
     bool exists(const QString &strPopupPaneID) const;
     void createPopupPane(const QString &strPopupPaneID,
                          const QString &strMessage, const QString &strDetails,
-                         const QMap<int, QString> &buttonDescriptions,
-                         bool fProposeAutoConfirmation);
+                         const QMap<int, QString> &buttonDescriptions);
     void updatePopupPane(const QString &strPopupPaneID,
                          const QString &strMessage, const QString &strDetails);
     void recallPopupPane(const QString &strPopupPaneID);
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.cpp
index 694f995..ba917d4 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.cpp
@@ -38,8 +38,7 @@ bool UIPopupStackViewport::exists(const QString &strPopupPaneID) const
 
 void UIPopupStackViewport::createPopupPane(const QString &strPopupPaneID,
                                            const QString &strMessage, const QString &strDetails,
-                                           const QMap<int, QString> &buttonDescriptions,
-                                           bool fProposeAutoConfirmation)
+                                           const QMap<int, QString> &buttonDescriptions)
 {
     /* Make sure there is no such popup-pane already: */
     if (m_panes.contains(strPopupPaneID))
@@ -51,8 +50,7 @@ void UIPopupStackViewport::createPopupPane(const QString &strPopupPaneID,
     /* Create new popup-pane: */
     UIPopupPane *pPopupPane = m_panes[strPopupPaneID] = new UIPopupPane(this,
                                                                         strMessage, strDetails,
-                                                                        buttonDescriptions,
-                                                                        fProposeAutoConfirmation);
+                                                                        buttonDescriptions);
 
     /* Attach popup-pane connection: */
     connect(this, SIGNAL(sigProposePopupPaneWidth(int)), pPopupPane, SLOT(sltHandleProposalForWidth(int)));
diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.h
index 3862e28..a472a14 100644
--- a/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.h
+++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStackViewport.h
@@ -51,8 +51,7 @@ public:
     bool exists(const QString &strPopupPaneID) const;
     void createPopupPane(const QString &strPopupPaneID,
                          const QString &strMessage, const QString &strDetails,
-                         const QMap<int, QString> &buttonDescriptions,
-                         bool fProposeAutoConfirmation);
+                         const QMap<int, QString> &buttonDescriptions);
     void updatePopupPane(const QString &strPopupPaneID,
                          const QString &strMessage, const QString &strDetails);
     void recallPopupPane(const QString &strPopupPaneID);
diff --git a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp
index 46ddf46..40d264b 100644
--- a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp
@@ -48,120 +48,127 @@ static const osTypePattern gs_OSTypePattern[] =
     { QRegExp("DOS", Qt::CaseInsensitive), "DOS" },
 
     /* Windows: */
-    { QRegExp("Wi.*98", Qt::CaseInsensitive), "Windows98" },
-    { QRegExp("Wi.*95", Qt::CaseInsensitive), "Windows95" },
-    { QRegExp("Wi.*Me", Qt::CaseInsensitive), "WindowsMe" },
-    { QRegExp("(Wi.*NT)|(NT4)", Qt::CaseInsensitive), "WindowsNT4" },
-    { QRegExp("((Wi.*XP)|(\\bXP\\b)).*64", Qt::CaseInsensitive), "WindowsXP_64" },
-    { QRegExp("(Wi.*XP)|(\\bXP\\b)", Qt::CaseInsensitive), "WindowsXP" },
+    { QRegExp(  "Wi.*98",                         Qt::CaseInsensitive), "Windows98" },
+    { QRegExp(  "Wi.*95",                         Qt::CaseInsensitive), "Windows95" },
+    { QRegExp(  "Wi.*Me",                         Qt::CaseInsensitive), "WindowsMe" },
+    { QRegExp( "(Wi.*NT)|(NT4)",                  Qt::CaseInsensitive), "WindowsNT4" },
+    { QRegExp("((Wi.*XP)|(\\bXP\\b)).*64",        Qt::CaseInsensitive), "WindowsXP_64" },
+    { QRegExp("((Wi.*XP)|(\\bXP\\b)).*32",        Qt::CaseInsensitive), "WindowsXP" },
     { QRegExp("((Wi.*2003)|(W2K3)|(Win2K3)).*64", Qt::CaseInsensitive), "Windows2003_64" },
-    { QRegExp("(Wi.*2003)|(W2K3)|(Win2K3)", Qt::CaseInsensitive), "Windows2003" },
-    { QRegExp("((Wi.*V)|(Vista)).*64", Qt::CaseInsensitive), "WindowsVista_64" },
-    { QRegExp("(Wi.*V)|(Vista)", Qt::CaseInsensitive), "WindowsVista" },
-    { QRegExp("(Wi.*2012)|(W2K12)|(Win2K12)", Qt::CaseInsensitive), "Windows2012_64" },
+    { QRegExp("((Wi.*2003)|(W2K3)|(Win2K3)).*32", Qt::CaseInsensitive), "Windows2003" },
+    { QRegExp("((Wi.*V)|(Vista)).*64",            Qt::CaseInsensitive), "WindowsVista_64" },
+    { QRegExp("((Wi.*V)|(Vista)).*32",            Qt::CaseInsensitive), "WindowsVista" },
+    { QRegExp( "(Wi.*2012)|(W2K12)|(Win2K12)",    Qt::CaseInsensitive), "Windows2012_64" },
     { QRegExp("((Wi.*2008)|(W2K8)|(Win2k8)).*64", Qt::CaseInsensitive), "Windows2008_64" },
-    { QRegExp("(Wi.*2008)|(W2K8)|(Win2K8)", Qt::CaseInsensitive), "Windows2008" },
-    { QRegExp("(Wi.*2000)|(W2K)|(Win2K)", Qt::CaseInsensitive), "Windows2000" },
-    { QRegExp("(Wi.*7.*64)|(W7.*64)", Qt::CaseInsensitive), "Windows7_64" },
-    { QRegExp("(Wi.*7)|(W7)", Qt::CaseInsensitive), "Windows7" },
-    { QRegExp("(Wi.*8.*1.*64)|(W8.*64)", Qt::CaseInsensitive), "Windows81_64" },
-    { QRegExp("(Wi.*8.*1)|(W8)", Qt::CaseInsensitive), "Windows81" },
-    { QRegExp("(Wi.*8.*64)|(W8.*64)", Qt::CaseInsensitive), "Windows8_64" },
-    { QRegExp("(Wi.*8)|(W8)", Qt::CaseInsensitive), "Windows8" },
-    { QRegExp("Wi.*3", Qt::CaseInsensitive), "Windows31" },
-    { QRegExp("Wi", Qt::CaseInsensitive), "WindowsXP" },
+    { QRegExp("((Wi.*2008)|(W2K8)|(Win2K8)).*32", Qt::CaseInsensitive), "Windows2008" },
+    { QRegExp( "(Wi.*2000)|(W2K)|(Win2K)",        Qt::CaseInsensitive), "Windows2000" },
+    { QRegExp( "(Wi.*7.*64)|(W7.*64)",            Qt::CaseInsensitive), "Windows7_64" },
+    { QRegExp( "(Wi.*7.*32)|(W7.*32)",            Qt::CaseInsensitive), "Windows7" },
+    { QRegExp( "(Wi.*8.*1.*64)|(W8.*64)",         Qt::CaseInsensitive), "Windows81_64" },
+    { QRegExp( "(Wi.*8.*1.*32)|(W8.*32)",         Qt::CaseInsensitive), "Windows81" },
+    { QRegExp( "(Wi.*8.*64)|(W8.*64)",            Qt::CaseInsensitive), "Windows8_64" },
+    { QRegExp( "(Wi.*8.*32)|(W8.*32)",            Qt::CaseInsensitive), "Windows8" },
+    { QRegExp(  "Wi.*3.*1",                       Qt::CaseInsensitive), "Windows31" },
+    { QRegExp(  "Wi.*64",                         Qt::CaseInsensitive), "WindowsXP_64" },
+    { QRegExp(  "Wi.*32",                         Qt::CaseInsensitive), "WindowsXP" },
 
     /* Solaris: */
-    { QRegExp("So.*11", Qt::CaseInsensitive), "Solaris11_64" },
+    { QRegExp("So.*11",                                                 Qt::CaseInsensitive), "Solaris11_64" },
     { QRegExp("((Op.*So)|(os20[01][0-9])|(So.*10)|(India)|(Neva)).*64", Qt::CaseInsensitive), "OpenSolaris_64" },
-    { QRegExp("(Op.*So)|(os20[01][0-9])|(So.*10)|(India)|(Neva)", Qt::CaseInsensitive), "OpenSolaris" },
-    { QRegExp("So.*64", Qt::CaseInsensitive), "Solaris_64" },
-    { QRegExp("So", Qt::CaseInsensitive), "Solaris" },
+    { QRegExp("((Op.*So)|(os20[01][0-9])|(So.*10)|(India)|(Neva)).*32", Qt::CaseInsensitive), "OpenSolaris" },
+    { QRegExp("So.*64",                                                 Qt::CaseInsensitive), "Solaris_64" },
+    { QRegExp("So.*32",                                                 Qt::CaseInsensitive), "Solaris" },
 
     /* OS/2: */
-    { QRegExp("OS[/|!-]{,1}2.*W.*4.?5", Qt::CaseInsensitive), "OS2Warp45" },
-    { QRegExp("OS[/|!-]{,1}2.*W.*4", Qt::CaseInsensitive), "OS2Warp4" },
-    { QRegExp("OS[/|!-]{,1}2.*W", Qt::CaseInsensitive), "OS2Warp3" },
+    { QRegExp( "OS[/|!-]{,1}2.*W.*4.?5",    Qt::CaseInsensitive), "OS2Warp45" },
+    { QRegExp( "OS[/|!-]{,1}2.*W.*4",       Qt::CaseInsensitive), "OS2Warp4" },
+    { QRegExp( "OS[/|!-]{,1}2.*W",          Qt::CaseInsensitive), "OS2Warp3" },
     { QRegExp("(OS[/|!-]{,1}2.*e)|(eCS.*)", Qt::CaseInsensitive), "OS2eCS" },
-    { QRegExp("OS[/|!-]{,1}2", Qt::CaseInsensitive), "OS2" },
+    { QRegExp( "OS[/|!-]{,1}2",             Qt::CaseInsensitive), "OS2" },
 
-    /* Other: must come before Ubuntu/Maverick and before Linux ??? */
+    /* Other: Must come before Ubuntu/Maverick and before Linux??? */
     { QRegExp("QN", Qt::CaseInsensitive), "QNX" },
 
-    /* Mac OS X: must come before Ubuntu/Maverick and before Linux */
+    /* Mac OS X: Must come before Ubuntu/Maverick and before Linux: */
     { QRegExp("((mac.*10[.,]{0,1}4)|(os.*x.*10[.,]{0,1}4)|(mac.*ti)|(os.*x.*ti)|(Tig)).64",     Qt::CaseInsensitive), "MacOS_64" },
-    { QRegExp( "(mac.*10[.,]{0,1}4)|(os.*x.*10[.,]{0,1}4)|(mac.*ti)|(os.*x.*ti)|(Tig)",         Qt::CaseInsensitive), "MacOS" },
+    { QRegExp("((mac.*10[.,]{0,1}4)|(os.*x.*10[.,]{0,1}4)|(mac.*ti)|(os.*x.*ti)|(Tig)).32",     Qt::CaseInsensitive), "MacOS" },
     { QRegExp("((mac.*10[.,]{0,1}5)|(os.*x.*10[.,]{0,1}5)|(mac.*leo)|(os.*x.*leo)|(Leop)).*64", Qt::CaseInsensitive), "MacOS_64" },
-    { QRegExp( "(mac.*10[.,]{0,1}5)|(os.*x.*10[.,]{0,1}5)|(mac.*leo)|(os.*x.*leo)|(Leop)",      Qt::CaseInsensitive), "MacOS" },
+    { QRegExp("((mac.*10[.,]{0,1}5)|(os.*x.*10[.,]{0,1}5)|(mac.*leo)|(os.*x.*leo)|(Leop)).*32", Qt::CaseInsensitive), "MacOS" },
     { QRegExp("((mac.*10[.,]{0,1}6)|(os.*x.*10[.,]{0,1}6)|(mac.*SL)|(os.*x.*SL)|(Snow L)).*64", Qt::CaseInsensitive), "MacOS106_64" },
-    { QRegExp( "(mac.*10[.,]{0,1}6)|(os.*x.*10[.,]{0,1}6)|(mac.*SL)|(os.*x.*SL)|(Snow L)",      Qt::CaseInsensitive), "MacOS106" },
+    { QRegExp("((mac.*10[.,]{0,1}6)|(os.*x.*10[.,]{0,1}6)|(mac.*SL)|(os.*x.*SL)|(Snow L)).*32", Qt::CaseInsensitive), "MacOS106" },
     { QRegExp( "(mac.*10[.,]{0,1}7)|(os.*x.*10[.,]{0,1}7)|(mac.*ML)|(os.*x.*ML)|(Mount)",       Qt::CaseInsensitive), "MacOS108_64" },
     { QRegExp( "(mac.*10[.,]{0,1}8)|(os.*x.*10[.,]{0,1}8)|(Lion)",                              Qt::CaseInsensitive), "MacOS107_64" },
     { QRegExp( "(mac.*10[.,]{0,1}9)|(os.*x.*10[.,]{0,1}9)|(mac.*mav)|(os.*x.*mav)|(Mavericks)", Qt::CaseInsensitive), "MacOS109_64" },
-    { QRegExp("((Mac)|(Tig)|(Leop)|(os[ ]*x)).*64", Qt::CaseInsensitive), "MacOS_64" },
-    { QRegExp("(Mac)|(Tig)|(Leop)|(os[ ]*x)", Qt::CaseInsensitive), "MacOS" },
+    { QRegExp("((Mac)|(Tig)|(Leop)|(os[ ]*x)).*64",                                             Qt::CaseInsensitive), "MacOS_64" },
+    { QRegExp("((Mac)|(Tig)|(Leop)|(os[ ]*x)).*32",                                             Qt::CaseInsensitive), "MacOS" },
 
     /* Code names for Linux distributions: */
-    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)).*64", Qt::CaseInsensitive), "Ubuntu_64" },
-    { QRegExp("(edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)", Qt::CaseInsensitive), "Ubuntu" },
-    { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(sid)).*64", Qt::CaseInsensitive), "Debian_64" },
-    { QRegExp("(sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(sid)", Qt::CaseInsensitive), "Debian" },
+    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)).*64",    Qt::CaseInsensitive), "Ubuntu_64" },
+    { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)).*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("((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)", Qt::CaseInsensitive), "Fedora" },
+    { QRegExp("((moonshine)|(werewolf)|(sulphur)|(cambridge)|(leonidas)|(constantine)|(goddard)|(laughlin)|(lovelock)|(verne)|(beefy)|(spherical)).*32", Qt::CaseInsensitive), "Fedora" },
 
     /* Regular names of Linux distributions: */
-    { QRegExp("Arc.*64", Qt::CaseInsensitive), "ArchLinux_64" },
-    { QRegExp("Arc", Qt::CaseInsensitive), "ArchLinux" },
-    { QRegExp("Deb.*64", Qt::CaseInsensitive), "Debian_64" },
-    { QRegExp("Deb", Qt::CaseInsensitive), "Debian" },
-    { QRegExp("((SU)|(Nov)|(SLE)).*64", Qt::CaseInsensitive), "OpenSUSE_64" },
-    { QRegExp("(SU)|(Nov)|(SLE)", Qt::CaseInsensitive), "OpenSUSE" },
-    { QRegExp("Fe.*64", Qt::CaseInsensitive), "Fedora_64" },
-    { QRegExp("Fe", Qt::CaseInsensitive), "Fedora" },
-    { QRegExp("((Gen)|(Sab)).*64", Qt::CaseInsensitive), "Gentoo_64" },
-    { QRegExp("(Gen)|(Sab)", Qt::CaseInsensitive), "Gentoo" },
-    { QRegExp("((Man)|(Mag)).*64", Qt::CaseInsensitive), "Mandriva_64" },
-    { QRegExp("((Man)|(Mag))", Qt::CaseInsensitive), "Mandriva" },
-    { QRegExp("((Red)|(rhel)|(cen)).*64", Qt::CaseInsensitive), "RedHat_64" },
-    { QRegExp("(Red)|(rhel)|(cen)", Qt::CaseInsensitive), "RedHat" },
-    { QRegExp("Tur.*64", Qt::CaseInsensitive), "Turbolinux_64" },
-    { QRegExp("Tur", Qt::CaseInsensitive), "Turbolinux" },
-    { QRegExp("Ub.*64", Qt::CaseInsensitive), "Ubuntu_64" },
-    { QRegExp("Ub", Qt::CaseInsensitive), "Ubuntu" },
-    { QRegExp("Xa.*64", Qt::CaseInsensitive), "Xandros_64" },
-    { QRegExp("Xa", Qt::CaseInsensitive), "Xandros" },
-    { QRegExp("((Or)|(oel)).*64", Qt::CaseInsensitive), "Oracle_64" },
-    { QRegExp("(Or)|(oel)", Qt::CaseInsensitive), "Oracle" },
-    { QRegExp("Knoppix", Qt::CaseInsensitive), "Linux26" },
-    { QRegExp("Dsl", Qt::CaseInsensitive), "Linux24" },
-    { QRegExp("((Lin)|(lnx)).*2.?2", Qt::CaseInsensitive), "Linux22" },
-    { QRegExp("((Lin)|(lnx)).*2.?4.*64", Qt::CaseInsensitive), "Linux24_64" },
-    { QRegExp("((Lin)|(lnx)).*2.?4", Qt::CaseInsensitive), "Linux24" },
+    { QRegExp("Arc.*64",                           Qt::CaseInsensitive), "ArchLinux_64" },
+    { QRegExp("Arc.*32",                           Qt::CaseInsensitive), "ArchLinux" },
+    { QRegExp("Deb.*64",                           Qt::CaseInsensitive), "Debian_64" },
+    { QRegExp("Deb.*32",                           Qt::CaseInsensitive), "Debian" },
+    { QRegExp("((SU)|(Nov)|(SLE)).*64",            Qt::CaseInsensitive), "OpenSUSE_64" },
+    { QRegExp("((SU)|(Nov)|(SLE)).*32",            Qt::CaseInsensitive), "OpenSUSE" },
+    { QRegExp("Fe.*64",                            Qt::CaseInsensitive), "Fedora_64" },
+    { QRegExp("Fe.*32",                            Qt::CaseInsensitive), "Fedora" },
+    { QRegExp("((Gen)|(Sab)).*64",                 Qt::CaseInsensitive), "Gentoo_64" },
+    { QRegExp("((Gen)|(Sab)).*32",                 Qt::CaseInsensitive), "Gentoo" },
+    { QRegExp("((Man)|(Mag)).*64",                 Qt::CaseInsensitive), "Mandriva_64" },
+    { QRegExp("((Man)|(Mag)).*32",                 Qt::CaseInsensitive), "Mandriva" },
+    { QRegExp("((Red)|(rhel)|(cen)).*64",          Qt::CaseInsensitive), "RedHat_64" },
+    { QRegExp("((Red)|(rhel)|(cen)).*32",          Qt::CaseInsensitive), "RedHat" },
+    { QRegExp("Tur.*64",                           Qt::CaseInsensitive), "Turbolinux_64" },
+    { QRegExp("Tur.*32",                           Qt::CaseInsensitive), "Turbolinux" },
+    { QRegExp("Ub.*64",                            Qt::CaseInsensitive), "Ubuntu_64" },
+    { QRegExp("Ub.*32",                            Qt::CaseInsensitive), "Ubuntu" },
+    { QRegExp("Xa.*64",                            Qt::CaseInsensitive), "Xandros_64" },
+    { QRegExp("Xa.*32",                            Qt::CaseInsensitive), "Xandros" },
+    { QRegExp("((Or)|(oel)).*64",                  Qt::CaseInsensitive), "Oracle_64" },
+    { QRegExp("((Or)|(oel)).*32",                  Qt::CaseInsensitive), "Oracle" },
+    { QRegExp("Knoppix",                           Qt::CaseInsensitive), "Linux26" },
+    { QRegExp("Dsl",                               Qt::CaseInsensitive), "Linux24" },
+    { QRegExp("((Lin)|(lnx)).*2.?2",               Qt::CaseInsensitive), "Linux22" },
+    { QRegExp("((Lin)|(lnx)).*2.?4.*64",           Qt::CaseInsensitive), "Linux24_64" },
+    { QRegExp("((Lin)|(lnx)).*2.?4.*32",           Qt::CaseInsensitive), "Linux24" },
     { QRegExp("((((Lin)|(lnx)).*2.?6)|(LFS)).*64", Qt::CaseInsensitive), "Linux26_64" },
-    { QRegExp("(((Lin)|(lnx)).*2.?6)|(LFS)", Qt::CaseInsensitive), "Linux26" },
-    { QRegExp("((Lin)|(lnx)).*64", Qt::CaseInsensitive), "Linux26_64" },
-    { QRegExp("(Lin)|(lnx)", Qt::CaseInsensitive), "Linux26" },
+    { QRegExp("((((Lin)|(lnx)).*2.?6)|(LFS)).*32", Qt::CaseInsensitive), "Linux26" },
+    { QRegExp("((Lin)|(lnx)).*64",                 Qt::CaseInsensitive), "Linux26_64" },
+    { QRegExp("((Lin)|(lnx)).*32",                 Qt::CaseInsensitive), "Linux26" },
 
     /* Other: */
-    { QRegExp("L4", Qt::CaseInsensitive), "L4" },
+    { QRegExp("L4",                   Qt::CaseInsensitive), "L4" },
     { QRegExp("((Fr.*B)|(fbsd)).*64", Qt::CaseInsensitive), "FreeBSD_64" },
-    { QRegExp("(Fr.*B)|(fbsd)", Qt::CaseInsensitive), "FreeBSD" },
-    { QRegExp("Op.*B.*64", Qt::CaseInsensitive), "OpenBSD_64" },
-    { QRegExp("Op.*B", Qt::CaseInsensitive), "OpenBSD" },
-    { QRegExp("Ne.*B.*64", Qt::CaseInsensitive), "NetBSD_64" },
-    { QRegExp("Ne.*B", Qt::CaseInsensitive), "NetBSD" },
-    { QRegExp("Net", Qt::CaseInsensitive), "Netware" },
-    { QRegExp("Rocki", Qt::CaseInsensitive), "JRockitVE" },
-    { QRegExp("Ot", Qt::CaseInsensitive), "Other" },
+    { QRegExp("((Fr.*B)|(fbsd)).*32", Qt::CaseInsensitive), "FreeBSD" },
+    { QRegExp("Op.*B.*64",            Qt::CaseInsensitive), "OpenBSD_64" },
+    { QRegExp("Op.*B.*32",            Qt::CaseInsensitive), "OpenBSD" },
+    { QRegExp("Ne.*B.*64",            Qt::CaseInsensitive), "NetBSD_64" },
+    { QRegExp("Ne.*B.*32",            Qt::CaseInsensitive), "NetBSD" },
+    { QRegExp("Net",                  Qt::CaseInsensitive), "Netware" },
+    { QRegExp("Rocki",                Qt::CaseInsensitive), "JRockitVE" },
+    { QRegExp("Ot",                   Qt::CaseInsensitive), "Other" },
 };
 
 UIWizardNewVMPage1::UIWizardNewVMPage1(const QString &strGroup)
     : m_strGroup(strGroup)
 {
+    CHost host = vboxGlobal().host();
+    m_fSupportsHWVirtEx = host.GetProcessorFeature(KProcessorFeature_HWVirtEx);
+    m_fSupportsLongMode = host.GetProcessorFeature(KProcessorFeature_LongMode);
 }
 
-void UIWizardNewVMPage1::onNameChanged(const QString &strNewName)
+void UIWizardNewVMPage1::onNameChanged(QString strNewName)
 {
+    /* Do not forget about achitecture bits: */
+    strNewName += ARCH_BITS == 64 && m_fSupportsHWVirtEx && m_fSupportsLongMode ? "64" : "32";
+
     /* Search for a matching OS type based on the string the user typed already. */
     for (size_t i = 0; i < RT_ELEMENTS(gs_OSTypePattern); ++i)
         if (strNewName.contains(gs_OSTypePattern[i].pattern))
diff --git a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.h b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.h
index 3733ed1..547dcd7 100644
--- a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.h
+++ b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.h
@@ -35,7 +35,7 @@ protected:
     UIWizardNewVMPage1(const QString &strGroup);
 
     /* Handlers: */
-    void onNameChanged(const QString &strNewName);
+    void onNameChanged(QString strNewName);
     void onOsTypeChanged();
 
     /* Helping stuff: */
@@ -60,6 +60,8 @@ protected:
 
     /* Variables: */
     QString m_strGroup;
+    bool m_fSupportsHWVirtEx;
+    bool m_fSupportsLongMode;
 };
 
 /* 1st page of the New Virtual Machine wizard (basic extension): */
diff --git a/src/VBox/GuestHost/OpenGL/Makefile.kmk b/src/VBox/GuestHost/OpenGL/Makefile.kmk
index d1ba272..2a1d1da 100644
--- a/src/VBox/GuestHost/OpenGL/Makefile.kmk
+++ b/src/VBox/GuestHost/OpenGL/Makefile.kmk
@@ -42,29 +42,6 @@ ifndef VBOX_ONLY_ADDITIONS
  LIBRARIES += VBoxOGLhostcrpacker VBoxOGLhostspuload VBoxOGLhostcrstate
 endif
 
-VBOX_OGL_X86_COMMON_DLLS = \
-    VBoxOGLcrutil-x86 \
-    VBoxOGLerrorspu-x86
-VBOX_OGL_X86_COMMON_LIBS = \
-    VBoxOGLcrpacker-x86 \
-    VBoxOGLspuload-x86 \
-    VBoxOGLcrstate-x86
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
- DLLS.win.amd64 += $(VBOX_OGL_X86_COMMON_DLLS)
-endif
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
- LIBRARIES.win.amd64 += $(VBOX_OGL_X86_COMMON_LIBS)
-endif
-# 32-bit version for the 64-bit Linux Additions
-ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),linux.amd64)
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  LIBRARIES += $(VBOX_OGL_X86_COMMON_LIBS)
-  DLLS += $(VBOX_OGL_X86_COMMON_DLLS)
-  $(foreach i,$(VBOX_OGL_X86_COMMON_DLLS),$(eval $(i)_INST = $(INST_ADDITIONS)/32/))
-  $(foreach i,$(VBOX_OGL_X86_COMMON_DLLS),$(eval $(i)_NAME = $(subst -x86,,$(i))))
- endif
-endif
-
 #
 # VBoxOGLcrutil
 #
@@ -107,6 +84,9 @@ VBoxOGLcrutil_SOURCES       = \
 	util/warp.c \
 	util/vreg.cpp \
 	util/blitter.cpp \
+	util/compositor.cpp \
+	util/htable.cpp \
+	util/bmpscale.cpp \
 	util/vboxhgcm.c \
 	$(VBOX_PATH_CROGL_GENFILES)/debug_opcodes.c
 VBoxOGLcrutil_SOURCES.win.x86 = \
@@ -141,9 +121,11 @@ VBoxOGLcrutil_CLEAN = \
 VBoxOGLcrutil_pixel.c_CFLAGS.win.x86     += -Od
 VBoxOGLhostcrutil_pixel.c_CFLAGS.win.x86 += -Od
 
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
 #
 # VBoxOGLcrutil-x86 - x86 VBoxOGLcrutil version built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGLcrutil-x86
 VBoxOGLcrutil-x86_TEMPLATE      = VBOXCROGLR3GUESTDLL
 VBoxOGLcrutil-x86_EXTENDS = VBoxOGLcrutil
 VBoxOGLcrutil-x86_BLD_TRG_ARCH = x86
@@ -165,6 +147,7 @@ endif
 # vc7 hangs during compilation of this file when optimizations are enabled.
 VBoxOGLcrutil-x86_pixel.c_CFLAGS += -Od
 VBoxOGLcrutil-x86_pixel.c_CFLAGS += -Od
+endif
 
 #
 # VBoxOGLhostcrutil
@@ -196,7 +179,7 @@ $(VBOX_PATH_CROGL_GENFILES)/debug_opcodes.c: $(PATH_SUB_CURRENT)/util/debug_opco
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI)
 
 ifdef VBOX_WITH_CRDUMPER
-$(VBOX_PATH_CROGL_GENFILES)/dump_gen.cpp: $(PATH_SUB_CURRENT)/state_tracker/dump_gen.py $(PATH_ROOT)/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py  $(PATH_ROOT)/src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_isenabled.txt state_extensions_isenabled.txt) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+$(VBOX_PATH_CROGL_GENFILES)/dump_gen.cpp: $(PATH_SUB_CURRENT)/state_tracker/dump_gen.py $(PATH_ROOT)/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_isenabled.txt state_extensions_isenabled.txt) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D)
 endif
@@ -299,13 +282,16 @@ ifdef VBOX_WITH_WDDM
 VBoxOGLcrpacker_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
 #
 # VBoxOGLcrpacker-x86 - x86 VBoxOGLcrpacker version built for amd64 build
 #
+LIBRARIES.win.amd64 += VBoxOGLcrpacker-x86
 VBoxOGLcrpacker-x86_TEMPLATE = VBOXCROGLR3GUESTLIB
 VBoxOGLcrpacker-x86_EXTENDS = VBoxOGLcrpacker
 VBoxOGLcrpacker-x86_BLD_TRG_ARCH = x86
 VBoxOGLcrpacker-x86_DEFS = $(VBoxOGLcrpacker_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # VBoxOGLhostcrpacker
@@ -380,13 +366,16 @@ ifdef VBOX_WITH_WDDM
 VBoxOGLspuload_DEFS.win   += VBOX_WITH_WDDM
 endif
 
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
 #
 # VBoxOGLspuload-x86 - x86 VBoxOGLspuload version built for amd64 build
 #
+LIBRARIES.win.amd64 += VBoxOGLspuload-x86
 VBoxOGLspuload-x86_TEMPLATE = VBOXCROGLR3GUESTLIB
 VBoxOGLspuload-x86_EXTENDS = VBoxOGLspuload
 VBoxOGLspuload-x86_BLD_TRG_ARCH = x86
 VBoxOGLspuload-x86_DEFS = $(VBoxOGLspuload_DEFS) VBOX_WDDM_WOW64
+endif
 
 
 #
@@ -477,7 +466,6 @@ VBoxOGLcrstate_SOURCES = \
 	$(VBOX_PATH_CROGL_GENFILES)/state_lighting_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_line_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_multisample_gen.c \
-	$(VBOX_PATH_CROGL_GENFILES)/state_point_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_polygon_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_regcombiner_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_viewport_gen.c \
@@ -496,7 +484,6 @@ VBoxOGLcrstate_CLEAN = \
 	$(VBOX_PATH_CROGL_GENFILES)/state_lighting_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_line_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_multisample_gen.c \
-	$(VBOX_PATH_CROGL_GENFILES)/state_point_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_polygon_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_regcombiner_gen.c \
 	$(VBOX_PATH_CROGL_GENFILES)/state_viewport_gen.c \
@@ -526,13 +513,16 @@ VBoxOGLcrstate_DEFS        += VBOX_WITH_CRDUMPER
     $(PATH_STAGE_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB)
 endif
 
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
 #
 # VBoxOGLcrstate-x86 - x86 VBoxOGLcrstate version built for amd64 build
 #
+LIBRARIES.win.amd64 += VBoxOGLcrstate-x86
 VBoxOGLcrstate-x86_TEMPLATE = VBOXCROGLR3GUESTLIB
 VBoxOGLcrstate-x86_EXTENDS = VBoxOGLcrstate
 VBoxOGLcrstate-x86_BLD_TRG_ARCH = x86
 VBoxOGLcrstate-x86_DEFS = $(VBoxOGLcrstate_DEFS) VBOX_WDDM_WOW64
+endif
 
 
 #
@@ -581,10 +571,6 @@ $(VBOX_PATH_CROGL_GENFILES)/state_multisample_gen.c: $(addprefix $(PATH_SUB_CURR
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py multisample Multisample $(<D)
 
-$(VBOX_PATH_CROGL_GENFILES)/state_point_gen.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_point.txt gendiffcode.py) | $$(dir $$@)
-	$(call MSG_GENERATE,python,$@,$<)
-	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py point Point $(<D)
-
 $(VBOX_PATH_CROGL_GENFILES)/state_polygon_gen.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_polygon.txt gendiffcode.py) | $$(dir $$@)
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py polygon Polygon $(<D)
@@ -597,7 +583,7 @@ $(VBOX_PATH_CROGL_GENFILES)/state_viewport_gen.c: $(addprefix $(PATH_SUB_CURRENT
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py viewport Viewport $(<D)
 
-$(VBOX_PATH_CROGL_GENFILES)/state_get.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_get.py state_get.txt state_extensions_get.txt) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+$(VBOX_PATH_CROGL_GENFILES)/state_get.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_get.py state_get.txt state_extensions_get.txt get_components.py) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/state_get.py $(VBOX_PATH_CROGL_GLAPI) $(<D)
 
@@ -648,15 +634,18 @@ VBoxOGLerrorspu_DEFS.win   += VBOX_WITH_WDDM
 endif
 
 
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
 #
 # VBoxOGLerrorspu-x86 - x86 VBoxOGLerrorspu version built for amd64 build
 #
+DLLS.win.amd64 += VBoxOGLerrorspu-x86
 VBoxOGLerrorspu-x86_TEMPLATE = VBOXCROGLR3GUESTDLL
 VBoxOGLerrorspu-x86_EXTENDS = VBoxOGLerrorspu
 VBoxOGLerrorspu-x86_BLD_TRG_ARCH = x86
 VBoxOGLerrorspu-x86_LIBS = \
 	$(VBOX_LIB_OGL_CRUTIL_X86)
 VBoxOGLerrorspu-x86_DEFS = $(VBoxOGLerrorspu_DEFS) VBOX_WDDM_WOW64
+endif
 
 #
 # VBoxOGLhosterrorspu
diff --git a/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt b/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt
index 8354205..3df1d92 100644
--- a/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt
+++ b/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt
@@ -8594,8 +8594,8 @@ chromium    nopack
 name        VBoxPresentComposition
 return      void
 param       win              GLint
-param       pCompositor      struct VBOXVR_SCR_COMPOSITOR *
-param       pChangedEntry    struct VBOXVR_SCR_COMPOSITOR_ENTRY *
+param       pCompositor      const struct VBOXVR_SCR_COMPOSITOR *
+param       pChangedEntry    const struct VBOXVR_SCR_COMPOSITOR_ENTRY *
 category    VBox
 chromium    nopack
 
@@ -9754,7 +9754,7 @@ chromium    nopack
 # GL_ARB_shader_objects
 
 name        GetHandleARB
-return      GLhandleARB
+return      VBoxGLhandleARB
 param       pname           GLenum
 paramprop   pname           GL_PROGRAM_OBJECT_ARB
 category    GL_ARB_shader_objects
@@ -9763,7 +9763,7 @@ chromium    extpack serverdependent
 
 name        DeleteObjectARB
 return      void
-param       obj             GLhandleARB
+param       obj             VBoxGLhandleARB
 category    GL_ARB_shader_objects
 props       nolist
 chromium    extpack
@@ -9771,14 +9771,14 @@ chromium    extpack
 name        DetachObjectARB
 alias       DetachShader
 return      void
-param       containerObj    GLhandleARB
-param       attachedObj     GLhandleARB
+param       containerObj    VBoxGLhandleARB
+param       attachedObj     VBoxGLhandleARB
 category    GL_ARB_shader_objects
 chromium    extpack
 
 name        CreateShaderObjectARB
 alias       CreateShader
-return      GLhandleARB
+return      VBoxGLhandleARB
 param       shaderType      GLenum
 paramprop   shaderType      GL_FRAGMENT_SHADER_ARB GL_VERTEX_SHADER_ARB
 category    GL_ARB_shader_objects
@@ -9788,7 +9788,7 @@ chromium    nopack
 name        ShaderSourceARB
 alias       ShaderSource
 return      void
-param       shaderObj   GLhandleARB
+param       shaderObj   VBoxGLhandleARB
 param       count       GLsizei
 param       string      const GLcharARB **
 param       length      const GLint *
@@ -9798,13 +9798,13 @@ chromium    nopack
 name        CompileShaderARB
 alias       CompileShader
 return      void
-param       shaderObj   GLhandleARB
+param       shaderObj   VBoxGLhandleARB
 category    GL_ARB_shader_objects
 chromium    nopack
 
 name        CreateProgramObjectARB
 alias       CreateProgram
-return      GLhandleARB
+return      VBoxGLhandleARB
 category    GL_ARB_shader_objects
 props       get
 chromium    nopack
@@ -9812,29 +9812,29 @@ chromium    nopack
 name        AttachObjectARB
 alias       AttachShader
 return      void
-param       containerObj    GLhandleARB
-param       obj             GLhandleARB
+param       containerObj    VBoxGLhandleARB
+param       obj             VBoxGLhandleARB
 category    GL_ARB_shader_objects
 chromium    extpack
 
 name        LinkProgramARB
 alias       LinkProgram
 return      void
-param       programObj      GLhandleARB
+param       programObj      VBoxGLhandleARB
 category    GL_ARB_shader_objects
 chromium    nopack
 
 name        UseProgramObjectARB
 alias       UseProgram
 return      void
-param       programObj      GLhandleARB
+param       programObj      VBoxGLhandleARB
 category    GL_ARB_shader_objects
 chromium    nopack
 
 name        ValidateProgramARB
 alias       ValidateProgram
 return      void
-param       programObj      GLhandleARB
+param       programObj      VBoxGLhandleARB
 category    GL_ARB_shader_objects
 chromium    nopack
 
@@ -10018,7 +10018,7 @@ chromium    nopack
 
 name        GetObjectParameterfvARB
 return      void
-param       obj         GLhandleARB
+param       obj         VBoxGLhandleARB
 param       pname       GLenum
 paramprop   pname       GL_OBJECT_TYPE_ARB GL_OBJECT_SUBTYPE_ARB GL_OBJECT_DELETE_STATUS_ARB GL_OBJECT_COMPILE_STATUS_ARB GL_OBJECT_LINK_STATUS_ARB GL_OBJECT_VALIDATE_STATUS_ARB GL_OBJECT_INFO_LOG_LENGTH_ARB GL_OBJECT_ATTACHED_OBJECTS_ARB GL_OBJECT_ACTIVE_UNIFORMS_ARB GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB GL_OBJECT_SHADER_SOURCE_LENGTH_ARB
 param       params      GLfloat *
@@ -10028,7 +10028,7 @@ chromium    extpack
 
 name        GetObjectParameterivARB
 return      void
-param       obj         GLhandleARB
+param       obj         VBoxGLhandleARB
 param       pname       GLenum
 paramprop   pname       GL_OBJECT_TYPE_ARB GL_OBJECT_SUBTYPE_ARB GL_OBJECT_DELETE_STATUS_ARB GL_OBJECT_COMPILE_STATUS_ARB GL_OBJECT_LINK_STATUS_ARB GL_OBJECT_VALIDATE_STATUS_ARB GL_OBJECT_INFO_LOG_LENGTH_ARB GL_OBJECT_ATTACHED_OBJECTS_ARB GL_OBJECT_ACTIVE_UNIFORMS_ARB GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB GL_OBJECT_SHADER_SOURCE_LENGTH_ARB
 param       params      GLint *
@@ -10038,7 +10038,7 @@ chromium    extpack
 
 name        GetInfoLogARB
 return      void
-param       obj         GLhandleARB
+param       obj         VBoxGLhandleARB
 param       maxLength   GLsizei
 param       length      GLsizei *
 param       infoLog     GLcharARB *
@@ -10048,10 +10048,10 @@ chromium    extpack
 
 name        GetAttachedObjectsARB
 return      void
-param       containerObj    GLhandleARB
+param       containerObj    VBoxGLhandleARB
 param       maxCount        GLsizei
 param       count           GLsizei *
-param       obj             GLhandleARB *
+param       obj             VBoxGLhandleARB *
 category    GL_ARB_shader_objects
 props       get
 chromium    extpack
@@ -10059,7 +10059,7 @@ chromium    extpack
 name        GetUniformLocationARB
 alias       GetUniformLocation
 return      GLint
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       name        const GLcharARB *
 category    GL_ARB_shader_objects
 props       get
@@ -10068,7 +10068,7 @@ chromium    nopack
 name        GetActiveUniformARB
 alias       GetActiveUniform
 return      void
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       index       GLuint
 param       maxLength   GLsizei
 param       length      GLsizei *
@@ -10082,7 +10082,7 @@ chromium    nopack
 name        GetShaderSourceARB
 alias       GetShaderSource
 return      void
-param       obj         GLhandleARB
+param       obj         VBoxGLhandleARB
 param       maxLength   GLsizei
 param       length      GLsizei *
 param       source      GLcharARB *
@@ -10093,7 +10093,7 @@ chromium    nopack
 name        GetUniformfvARB
 alias       GetUniformfv
 return      void
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       location    GLint
 param       params      GLfloat *
 category    GL_ARB_shader_objects
@@ -10103,7 +10103,7 @@ chromium    nopack
 name        GetUniformivARB
 alias       GetUniformiv
 return      void
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       location    GLint
 param       params      GLint *
 category    GL_ARB_shader_objects
@@ -10115,7 +10115,7 @@ chromium    nopack
 name        GetActiveAttribARB
 alias       GetActiveAttrib
 return      void
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       index       GLuint
 param       maxLength   GLsizei
 param       length      GLsizei *
@@ -10129,7 +10129,7 @@ chromium    nopack
 name        GetAttribLocationARB
 alias       GetAttribLocation
 return      GLint
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       name        const GLcharARB *
 category    GL_ARB_vertex_shader
 props       get
@@ -10138,7 +10138,7 @@ chromium    nopack
 name        BindAttribLocationARB
 alias       BindAttribLocation
 return      void
-param       programObj  GLhandleARB
+param       programObj  VBoxGLhandleARB
 param       index       GLuint
 param       name        const GLcharARB *
 category    GL_ARB_vertex_shader
diff --git a/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py b/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
index 0d65136..bce38f1 100755
--- a/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
+++ b/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
@@ -646,7 +646,7 @@ __lengths = {
 	'int': 4,
 	'GLintptrARB': 4,   # XXX or 8 bytes?
 	'GLsizeiptrARB': 4, # XXX or 8 bytes?
-	'GLhandleARB': 4,
+	'VBoxGLhandleARB': 4,
 	'GLcharARB': 1,
 	'uintptr_t': 4
 }
diff --git a/src/VBox/GuestHost/OpenGL/include/GL/glext.h b/src/VBox/GuestHost/OpenGL/include/GL/glext.h
index 90cd2c0..7f75454 100644
--- a/src/VBox/GuestHost/OpenGL/include/GL/glext.h
+++ b/src/VBox/GuestHost/OpenGL/include/GL/glext.h
@@ -3722,29 +3722,17 @@ typedef ptrdiff_t GLintptrARB;
 typedef ptrdiff_t GLsizeiptrARB;
 #endif
 
-/* VBox: HACK ALERT! When building the host side against Mac OS X 10.7 headers,
-   /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/OpenGL.framework/Headers/gltypes.h
-   is included and it typedefs GLhandleARB differently.  In 10.6 and earlier,
-   gl.h was included instead of gltypes.h (new file) avoiding the conflicting
-   typedef in Headers/glext.h.
-
-   Since sizeof the gltypes.h typedef is 64-bit on 64-bit platforms, we're in
-   trouble if the type is used for anything important.  Fortunately, the
-   conflict only occurs in three files: renderspu_config.c, renderspu_cocoa.c
-   and renderspu_cocoa_helper.m. */
-#ifdef RT_OS_DARWIN
-# ifndef MAC_OS_X_VERSION_MIN_REQUIRED
-#  error "MAC_OS_X_VERSION_MIN_REQUIRED is not defined"
-# endif
-# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 && defined(__gltypes_h_)
-#  define GLhandleARB VBoxGLhandleARB
-# endif
-#endif
-
 #ifndef GL_ARB_shader_objects
 /* GL types for handling shader object handles and program/shader text */
 typedef char GLcharARB;		/* native character */
-typedef unsigned int GLhandleARB;	/* shader object handle */
+typedef unsigned int VBoxGLhandleARB;	/* shader object handle */
+# ifdef RT_OS_DARWIN
+typedef void* GLhandleARB;   /* shader object handle */
+# else
+typedef unsigned int GLhandleARB;   /* native shader object handle */
+# endif
+#else
+# error "GL_ARB_shader_objects should NOT be defined here!!"
 #endif
 
 /* GL types for "half" precision (s10e5) float data in host memory */
@@ -4770,17 +4758,17 @@ typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname,
 #ifndef GL_ARB_shader_objects
 #define GL_ARB_shader_objects 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB);
-GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum);
-GLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB);
-GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);
-GLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
-GLAPI void APIENTRY glCompileShaderARB (GLhandleARB);
-GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
-GLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB);
-GLAPI void APIENTRY glLinkProgramARB (GLhandleARB);
-GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB);
-GLAPI void APIENTRY glValidateProgramARB (GLhandleARB);
+GLAPI void APIENTRY glDeleteObjectARB (VBoxGLhandleARB);
+GLAPI VBoxGLhandleARB APIENTRY glGetHandleARB (GLenum);
+GLAPI void APIENTRY glDetachObjectARB (VBoxGLhandleARB, VBoxGLhandleARB);
+GLAPI VBoxGLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);
+GLAPI void APIENTRY glShaderSourceARB (VBoxGLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
+GLAPI void APIENTRY glCompileShaderARB (VBoxGLhandleARB);
+GLAPI VBoxGLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (VBoxGLhandleARB, VBoxGLhandleARB);
+GLAPI void APIENTRY glLinkProgramARB (VBoxGLhandleARB);
+GLAPI void APIENTRY glUseProgramObjectARB (VBoxGLhandleARB);
+GLAPI void APIENTRY glValidateProgramARB (VBoxGLhandleARB);
 GLAPI void APIENTRY glUniform1fARB (GLint, GLfloat);
 GLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat);
 GLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat);
@@ -4800,27 +4788,27 @@ GLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *);
 GLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
 GLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
 GLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
-GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);
-GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *);
-GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
-GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);
-GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *);
-GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
-GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *);
-GLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *);
-GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
-#endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
-typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
-typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
-typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
-typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
-typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
-typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
-typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
-typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
-typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
-typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+GLAPI void APIENTRY glGetObjectParameterfvARB (VBoxGLhandleARB, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetObjectParameterivARB (VBoxGLhandleARB, GLenum, GLint *);
+GLAPI void APIENTRY glGetInfoLogARB (VBoxGLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+GLAPI void APIENTRY glGetAttachedObjectsARB (VBoxGLhandleARB, GLsizei, GLsizei *, VBoxGLhandleARB *);
+GLAPI GLint APIENTRY glGetUniformLocationARB (VBoxGLhandleARB, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveUniformARB (VBoxGLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI void APIENTRY glGetUniformfvARB (VBoxGLhandleARB, GLint, GLfloat *);
+GLAPI void APIENTRY glGetUniformivARB (VBoxGLhandleARB, GLint, GLint *);
+GLAPI void APIENTRY glGetShaderSourceARB (VBoxGLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (VBoxGLhandleARB obj);
+typedef VBoxGLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (VBoxGLhandleARB containerObj, VBoxGLhandleARB attachedObj);
+typedef VBoxGLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (VBoxGLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (VBoxGLhandleARB shaderObj);
+typedef VBoxGLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (VBoxGLhandleARB containerObj, VBoxGLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (VBoxGLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (VBoxGLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (VBoxGLhandleARB programObj);
 typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
 typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
 typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
@@ -4840,27 +4828,27 @@ typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count,
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
-typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
-typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
-typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
-typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
-typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
-typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
-typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (VBoxGLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (VBoxGLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (VBoxGLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei *count, VBoxGLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (VBoxGLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (VBoxGLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (VBoxGLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (VBoxGLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (VBoxGLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
 #endif
 
 #ifndef GL_ARB_vertex_shader
 #define GL_ARB_vertex_shader 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);
-GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
-GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *);
+GLAPI void APIENTRY glBindAttribLocationARB (VBoxGLhandleARB, GLuint, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveAttribARB (VBoxGLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI GLint APIENTRY glGetAttribLocationARB (VBoxGLhandleARB, const GLcharARB *);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
-typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
-typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (VBoxGLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (VBoxGLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (VBoxGLhandleARB programObj, const GLcharARB *name);
 #endif
 
 #ifndef GL_ARB_fragment_shader
diff --git a/src/VBox/GuestHost/OpenGL/include/chromium.h b/src/VBox/GuestHost/OpenGL/include/chromium.h
index 8950c1e..4e1ed62 100644
--- a/src/VBox/GuestHost/OpenGL/include/chromium.h
+++ b/src/VBox/GuestHost/OpenGL/include/chromium.h
@@ -21,24 +21,24 @@
 #include "cr_compiler.h"
 
 #ifdef IN_RING0
-#include <common/VBoxMPUtils.h>
-#define WINGDIAPI
+# include <common/VBoxMPUtils.h>
+# define WINGDIAPI
 #endif
 /*
  * We effectively wrap gl.h, glu.h, etc, just like GLUT
  */
 
 #ifndef GL_GLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES
+# define GL_GLEXT_PROTOTYPES
 #endif
 
 #if defined(WINDOWS)
 # ifdef IN_RING0
 #  error "should not happen!"
 # endif
-#define WIN32_LEAN_AND_MEAN
-#define WGL_APIENTRY __stdcall
-#include <windows.h>
+# define WIN32_LEAN_AND_MEAN
+# define WGL_APIENTRY __stdcall
+# include <windows.h>
 #elif defined(DARWIN)
 /* nothing */
 #else
@@ -55,23 +55,23 @@
 
 
 #ifdef GLX
-#ifndef GLX_GLXEXT_PROTOTYPES
-#define GLX_GLXEXT_PROTOTYPES
-#endif
-#include <GL/glx.h>
+# ifndef GLX_GLXEXT_PROTOTYPES
+#  define GLX_GLXEXT_PROTOTYPES
+# endif
+# include <GL/glx.h>
 #endif
 
 #ifdef USE_OSMESA
-#include <GL/osmesa.h>
+# include <GL/osmesa.h>
 #endif
 
 #ifdef DARWIN
-#include <stddef.h>
+# include <stddef.h>
 #elif !defined(FreeBSD)
-#include <malloc.h>  /* to get ptrdiff_t used below */
+#  include <malloc.h>  /* to get ptrdiff_t used below */
 #endif
 
-#include <GL/glext.h>
+#include "cr_glext.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -726,6 +726,8 @@ extern void APIENTRY glZPixCR(GLsizei width, GLsizei height, GLenum format,
 /* Tells renderspu the default context id being used by the crserver */
 #define GL_HH_SET_DEFAULT_SHARED_CTX  0x8B2D
 
+#define GL_HH_SET_TMPCTX_MAKE_CURRENT 0x8B2E
+
 /**********************************************************************/
 /*****                Chromium-specific API                       *****/
 /**********************************************************************/
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_blitter.h b/src/VBox/GuestHost/OpenGL/include/cr_blitter.h
index 82ad026..2a01d3b 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_blitter.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_blitter.h
@@ -1,193 +1,323 @@
-/* $Id$ */
-
-/** @file
- * Blitter API
- */
-/*
- * Copyright (C) 2013 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-#ifndef ___cr_blitter_h__
-#define ___cr_blitter_h__
-
-#include <iprt/cdefs.h>
-#include "cr_spu.h"
-#include "cr_vreg.h"
-
-#ifndef IN_RING0
-# define VBOXBLITTERDECL(_type) DECLEXPORT(_type)
-#else
-# define VBOXBLITTERDECL(_type) RTDECL(_type)
-#endif
-
-RT_C_DECLS_BEGIN
-/* GLSL Cache */
-typedef struct CR_GLSL_CACHE
-{
-    int iGlVersion;
-    GLuint uNoAlpha2DProg;
-    GLuint uNoAlpha2DRectProg;
-    SPUDispatchTable *pDispatch;
-} CR_GLSL_CACHE;
-
-DECLINLINE(void) CrGlslInit(CR_GLSL_CACHE *pCache, SPUDispatchTable *pDispatch)
-{
-    memset(pCache, 0, sizeof (*pCache));
-    pCache->pDispatch = pDispatch;
-}
-
-DECLINLINE(bool) CrGlslIsInited(const CR_GLSL_CACHE *pCache)
-{
-    return !!pCache->pDispatch;
-}
-
-/* clients should set proper context before calling these funcs */
-VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache);
-VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache);
-VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
-VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
-VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
-VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache);
-VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache);
-VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache);
-VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache);
-
-/* BLITTER */
-typedef struct CR_BLITTER_BUFFER
-{
-    GLuint cbBuffer;
-    GLvoid * pvBuffer;
-} CR_BLITTER_BUFFER, *PCR_BLITTER_BUFFER;
-
-typedef union CR_BLITTER_FLAGS
-{
-    struct
-    {
-        uint32_t Initialized         : 1;
-        uint32_t CtxCreated          : 1;
-        uint32_t SupportsFBO         : 1;
-        uint32_t CurrentMuralChanged : 1;
-        uint32_t LastWasFBODraw      : 1;
-        uint32_t ForceDrawBlit       : 1;
-        uint32_t ShadersGloal        : 1;
-        uint32_t Reserved            : 25;
-    };
-    uint32_t Value;
-} CR_BLITTER_FLAGS, *PCR_BLITTER_FLAGS;
-
-struct CR_BLITTER;
-
-typedef DECLCALLBACK(int) FNCRBLT_BLITTER(struct CR_BLITTER *pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags);
-typedef FNCRBLT_BLITTER *PFNCRBLT_BLITTER;
-
-typedef struct CR_BLITTER_SPUITEM
-{
-    int id;
-    GLint visualBits;
-} CR_BLITTER_SPUITEM, *PCR_BLITTER_SPUITEM;
-
-typedef struct CR_BLITTER_CONTEXT
-{
-    CR_BLITTER_SPUITEM Base;
-} CR_BLITTER_CONTEXT, *PCR_BLITTER_CONTEXT;
-
-typedef struct CR_BLITTER_WINDOW
-{
-    CR_BLITTER_SPUITEM Base;
-    GLuint width, height;
-} CR_BLITTER_WINDOW, *PCR_BLITTER_WINDOW;
-
-typedef struct CR_BLITTER_IMG
-{
-    void *pvData;
-    GLuint cbData;
-    GLenum enmFormat;
-    GLuint width, height;
-    GLuint bpp;
-    GLuint pitch;
-} CR_BLITTER_IMG, *PCR_BLITTER_IMG;
-
-typedef struct CR_BLITTER
-{
-    GLuint idFBO;
-    CR_BLITTER_FLAGS Flags;
-    PFNCRBLT_BLITTER pfnBlt;
-    CR_BLITTER_BUFFER Verticies;
-    CR_BLITTER_BUFFER Indicies;
-    RTRECTSIZE CurrentSetSize;
-    CR_BLITTER_WINDOW CurrentMural;
-    CR_BLITTER_CONTEXT CtxInfo;
-    const CR_BLITTER_CONTEXT *pRestoreCtxInfo;
-    const CR_BLITTER_WINDOW *pRestoreMural;
-    int32_t i32MakeCurrentUserData;
-    SPUDispatchTable *pDispatch;
-    const CR_GLSL_CACHE *pGlslCache;
-    CR_GLSL_CACHE LocalGlslCache;
-} CR_BLITTER, *PCR_BLITTER;
-
-DECLINLINE(GLboolean) CrBltIsInitialized(PCR_BLITTER pBlitter)
-{
-    return !!pBlitter->pDispatch;
-}
-
-VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch);
-
-VBOXBLITTERDECL(void) CrBltTerm(PCR_BLITTER pBlitter);
-
-VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural);
-
-DECLINLINE(GLboolean) CrBltSupportsTexTex(PCR_BLITTER pBlitter)
-{
-    return pBlitter->Flags.SupportsFBO;
-}
-
-DECLINLINE(GLboolean) CrBltIsEntered(PCR_BLITTER pBlitter)
-{
-    return !!pBlitter->pRestoreCtxInfo;
-}
-
-DECLINLINE(GLint) CrBltGetVisBits(PCR_BLITTER pBlitter)
-{
-    return pBlitter->CtxInfo.Base.visualBits;
-}
-
-
-DECLINLINE(GLboolean) CrBltIsEverEntered(PCR_BLITTER pBlitter)
-{
-    return !!pBlitter->Flags.Initialized;
-}
-
-DECLINLINE(void) CrBltSetMakeCurrentUserData(PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
-{
-    pBlitter->i32MakeCurrentUserData = i32MakeCurrentUserData;
-}
-
-VBOXBLITTERDECL(int) CrBltMuralSetCurrent(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural);
-DECLINLINE(const CR_BLITTER_WINDOW *) CrBltMuralGetCurrentInfo(PCR_BLITTER pBlitter)
-{
-    return &pBlitter->CurrentMural;
-}
-
-VBOXBLITTERDECL(void) CrBltCheckUpdateViewport(PCR_BLITTER pBlitter);
-
-VBOXBLITTERDECL(void) CrBltLeave(PCR_BLITTER pBlitter);
-VBOXBLITTERDECL(int) CrBltEnter(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural);
-VBOXBLITTERDECL(void) CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags);
-VBOXBLITTERDECL(void) CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags);
-VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst);
-
-VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst);
-VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst);
-VBOXBLITTERDECL(void) CrBltPresent(PCR_BLITTER pBlitter);
-/* */
-
-RT_C_DECLS_END
-
-#endif /* #ifndef ___cr_blitter_h__ */
+/* $Id$ */
+
+/** @file
+ * Blitter API
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_blitter_h__
+#define ___cr_blitter_h__
+
+#include <iprt/cdefs.h>
+#include <iprt/asm.h>
+#include "cr_spu.h"
+#include "cr_vreg.h"
+
+#ifndef IN_RING0
+# define VBOXBLITTERDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXBLITTERDECL(_type) RTDECL(_type)
+#endif
+
+RT_C_DECLS_BEGIN
+/* GLSL Cache */
+typedef struct CR_GLSL_CACHE
+{
+    int iGlVersion;
+    GLuint uNoAlpha2DProg;
+    GLuint uNoAlpha2DRectProg;
+    SPUDispatchTable *pDispatch;
+} CR_GLSL_CACHE;
+
+DECLINLINE(void) CrGlslInit(CR_GLSL_CACHE *pCache, SPUDispatchTable *pDispatch)
+{
+    memset(pCache, 0, sizeof (*pCache));
+    pCache->pDispatch = pDispatch;
+}
+
+DECLINLINE(bool) CrGlslIsInited(const CR_GLSL_CACHE *pCache)
+{
+    return !!pCache->pDispatch;
+}
+
+/* clients should set proper context before calling these funcs */
+VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
+VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
+VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
+VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache);
+
+/* BLITTER */
+typedef struct CR_BLITTER_BUFFER
+{
+    GLuint cbBuffer;
+    GLvoid * pvBuffer;
+} CR_BLITTER_BUFFER, *PCR_BLITTER_BUFFER;
+
+typedef union CR_BLITTER_FLAGS
+{
+    struct
+    {
+        uint32_t Initialized         : 1;
+        uint32_t CtxCreated          : 1;
+        uint32_t SupportsFBO         : 1;
+        uint32_t SupportsPBO         : 1;
+        uint32_t CurrentMuralChanged : 1;
+        uint32_t LastWasFBODraw      : 1;
+        uint32_t ForceDrawBlit       : 1;
+        uint32_t ShadersGloal        : 1;
+        uint32_t Reserved            : 24;
+    };
+    uint32_t Value;
+} CR_BLITTER_FLAGS, *PCR_BLITTER_FLAGS;
+
+struct CR_BLITTER;
+
+typedef DECLCALLBACK(int) FNCRBLT_BLITTER(struct CR_BLITTER *pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags);
+typedef FNCRBLT_BLITTER *PFNCRBLT_BLITTER;
+
+typedef struct CR_BLITTER_SPUITEM
+{
+    int id;
+    GLint visualBits;
+} CR_BLITTER_SPUITEM, *PCR_BLITTER_SPUITEM;
+
+typedef struct CR_BLITTER_CONTEXT
+{
+    CR_BLITTER_SPUITEM Base;
+} CR_BLITTER_CONTEXT, *PCR_BLITTER_CONTEXT;
+
+typedef struct CR_BLITTER_WINDOW
+{
+    CR_BLITTER_SPUITEM Base;
+    GLuint width, height;
+} CR_BLITTER_WINDOW, *PCR_BLITTER_WINDOW;
+
+typedef struct CR_BLITTER_IMG
+{
+    void *pvData;
+    GLuint cbData;
+    GLenum enmFormat;
+    GLuint width, height;
+    GLuint bpp;
+    GLuint pitch;
+} CR_BLITTER_IMG, *PCR_BLITTER_IMG;
+
+typedef struct CR_BLITTER
+{
+    GLuint idFBO;
+    CR_BLITTER_FLAGS Flags;
+    uint32_t cEnters;
+    PFNCRBLT_BLITTER pfnBlt;
+    CR_BLITTER_BUFFER Verticies;
+    CR_BLITTER_BUFFER Indicies;
+    RTRECTSIZE CurrentSetSize;
+    CR_BLITTER_WINDOW CurrentMural;
+    CR_BLITTER_CONTEXT CtxInfo;
+    int32_t i32MakeCurrentUserData;
+    SPUDispatchTable *pDispatch;
+    const CR_GLSL_CACHE *pGlslCache;
+    CR_GLSL_CACHE LocalGlslCache;
+} CR_BLITTER, *PCR_BLITTER;
+
+DECLINLINE(GLboolean) CrBltIsInitialized(PCR_BLITTER pBlitter)
+{
+    return !!pBlitter->pDispatch;
+}
+
+VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch);
+
+VBOXBLITTERDECL(void) CrBltTerm(PCR_BLITTER pBlitter);
+
+VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter);
+
+DECLINLINE(GLboolean) CrBltSupportsTexTex(PCR_BLITTER pBlitter)
+{
+    return pBlitter->Flags.SupportsFBO;
+}
+
+DECLINLINE(GLboolean) CrBltIsEntered(PCR_BLITTER pBlitter)
+{
+    return !!pBlitter->cEnters;
+}
+
+DECLINLINE(GLint) CrBltGetVisBits(PCR_BLITTER pBlitter)
+{
+    return pBlitter->CtxInfo.Base.visualBits;
+}
+
+
+DECLINLINE(GLboolean) CrBltIsEverEntered(PCR_BLITTER pBlitter)
+{
+    return !!pBlitter->Flags.Initialized;
+}
+
+DECLINLINE(void) CrBltSetMakeCurrentUserData(PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
+{
+    pBlitter->i32MakeCurrentUserData = i32MakeCurrentUserData;
+}
+
+VBOXBLITTERDECL(int) CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural);
+DECLINLINE(const CR_BLITTER_WINDOW *) CrBltMuralGetCurrentInfo(PCR_BLITTER pBlitter)
+{
+    return &pBlitter->CurrentMural;
+}
+
+VBOXBLITTERDECL(void) CrBltCheckUpdateViewport(PCR_BLITTER pBlitter);
+
+VBOXBLITTERDECL(void) CrBltLeave(PCR_BLITTER pBlitter);
+VBOXBLITTERDECL(int) CrBltEnter(PCR_BLITTER pBlitter);
+VBOXBLITTERDECL(void) CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags);
+VBOXBLITTERDECL(void) CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags);
+VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst);
+
+VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst);
+VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst);
+VBOXBLITTERDECL(void) CrBltPresent(PCR_BLITTER pBlitter);
+/* */
+struct CR_TEXDATA;
+
+typedef DECLCALLBACK(void) FNCRTEXDATA_RELEASED(struct CR_TEXDATA *pTexture);
+typedef FNCRTEXDATA_RELEASED *PFNCRTEXDATA_RELEASED;
+
+typedef union CR_TEXDATA_FLAGS
+{
+    struct
+    {
+        uint32_t DataValid           : 1;
+        uint32_t DataAcquired        : 1;
+        uint32_t DataInverted        : 1;
+        uint32_t Entered             : 1;
+        uint32_t Reserved            : 28;
+    };
+    uint32_t Value;
+} CR_TEXDATA_FLAGS, *PCR_TEXDATA_FLAGS;
+
+
+typedef struct CR_TEXDATA
+{
+    VBOXVR_TEXTURE Tex;
+    volatile uint32_t cRefs;
+    /* fields specific to texture data download */
+    uint32_t idInvertTex;
+    uint32_t idPBO;
+    CR_TEXDATA_FLAGS Flags;
+    PCR_BLITTER pBlitter;
+    CR_BLITTER_IMG Img;
+    /*dtor*/
+    PFNCRTEXDATA_RELEASED pfnTextureReleased;
+    struct CR_TEXDATA *pScaledCache;
+} CR_TEXDATA, *PCR_TEXDATA;
+
+DECLINLINE(void) CrTdInit(PCR_TEXDATA pTex, const VBOXVR_TEXTURE *pVrTex, PCR_BLITTER pBlitter, PFNCRTEXDATA_RELEASED pfnTextureReleased)
+{
+    memset(pTex, 0, sizeof (*pTex));
+    pTex->Tex = *pVrTex;
+    pTex->cRefs = 1;
+    pTex->pBlitter = pBlitter;
+    pTex->pfnTextureReleased = pfnTextureReleased;
+}
+
+DECLINLINE(const VBOXVR_TEXTURE*) CrTdTexGet(const CR_TEXDATA *pTex)
+{
+    return &pTex->Tex;
+}
+
+DECLINLINE(PCR_BLITTER) CrTdBlitterGet(CR_TEXDATA *pTex)
+{
+    return pTex->pBlitter;
+}
+
+DECLINLINE(int) CrTdBltEnter(PCR_TEXDATA pTex)
+{
+    int rc;
+	if (pTex->Flags.Entered)
+		return VERR_INVALID_STATE;
+	rc = CrBltEnter(pTex->pBlitter);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrBltEnter failed rc %d", rc));
+        return rc;
+    }
+	pTex->Flags.Entered = 1;
+	return VINF_SUCCESS;
+}
+
+DECLINLINE(bool) CrTdBltIsEntered(PCR_TEXDATA pTex)
+{
+	return pTex->Flags.Entered;
+}
+
+DECLINLINE(void) CrTdBltLeave(PCR_TEXDATA pTex)
+{
+	if (!pTex->Flags.Entered)
+	{
+		WARN(("invalid Blt Leave"));
+		return;
+	}
+
+	CrBltLeave(pTex->pBlitter);
+
+	pTex->Flags.Entered = 0;
+}
+
+/* the CrTdBltXxx calls are done with the entered blitter */
+/* acquire the texture data, returns the cached data in case it is cached.
+ * the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup.
+ * */
+VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg);
+
+VBOXBLITTERDECL(int) CrTdBltDataAcquireScaled(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, uint32_t width, uint32_t height, const CR_BLITTER_IMG**ppImg);
+
+VBOXBLITTERDECL(int) CrTdBltDataReleaseScaled(PCR_TEXDATA pTex, const CR_BLITTER_IMG *pImg);
+
+VBOXBLITTERDECL(void) CrTdBltScaleCacheMoveTo(PCR_TEXDATA pTex, PCR_TEXDATA pDstTex);
+
+/* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup */
+VBOXBLITTERDECL(int) CrTdBltDataRelease(PCR_TEXDATA pTex);
+/* discard the texture data cached with previous CrTdBltDataAcquire.
+ * Must be called wit data released (CrTdBltDataRelease) */
+VBOXBLITTERDECL(int) CrTdBltDataFree(PCR_TEXDATA pTex);
+VBOXBLITTERDECL(int) CrTdBltDataFreeNe(PCR_TEXDATA pTex);
+VBOXBLITTERDECL(void) CrTdBltDataInvalidateNe(PCR_TEXDATA pTex);
+/* does same as CrTdBltDataFree, and in addition cleans up.
+ * this is kind of a texture destructor, which clients should call on texture object destruction, e.g. from the PFNCRTEXDATA_RELEASED callback */
+VBOXBLITTERDECL(int) CrTdBltDataCleanup(PCR_TEXDATA pTex);
+
+VBOXBLITTERDECL(int) CrTdBltDataCleanupNe(PCR_TEXDATA pTex);
+
+DECLINLINE(uint32_t) CrTdAddRef(PCR_TEXDATA pTex)
+{
+    return ASMAtomicIncU32(&pTex->cRefs);
+}
+
+DECLINLINE(uint32_t) CrTdRelease(PCR_TEXDATA pTex)
+{
+    uint32_t cRefs = ASMAtomicDecU32(&pTex->cRefs);
+    if (!cRefs)
+    {
+        if (pTex->pfnTextureReleased)
+            pTex->pfnTextureReleased(pTex);
+        else
+            CrTdBltDataCleanupNe(pTex);
+	}
+
+    return cRefs;
+}
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_blitter_h__ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h b/src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h
new file mode 100644
index 0000000..fda56ba
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h
@@ -0,0 +1,25 @@
+#ifndef ___cr_bmpscale_h__
+#define ___cr_bmpscale_h__
+
+#include <iprt/types.h>
+#include <iprt/cdefs.h>
+
+
+RT_C_DECLS_BEGIN
+
+#ifndef IN_RING0
+# define VBOXBMPSCALEDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXBLITTERDECL(_type) RTDECL(_type)
+#endif
+
+VBOXBMPSCALEDECL(void) CrBmpScale32 (uint8_t *dst,
+                        int iDstDeltaLine,
+                        int dstW, int dstH,
+                        const uint8_t *src,
+                        int iSrcDeltaLine,
+                        int srcW, int srcH);
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_bmpscale_h__ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_compositor.h b/src/VBox/GuestHost/OpenGL/include/cr_compositor.h
new file mode 100644
index 0000000..4ad5693
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_compositor.h
@@ -0,0 +1,233 @@
+/* $Id: cr_compositor.h $ */
+
+/** @file
+ * uint32_t compositor API
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_compositor_h_
+#define ___cr_compositor_h_
+#include <cr_vreg.h>
+#include <cr_blitter.h>
+
+/* Compositor with Stretching & Cached Rectangles info */
+
+RT_C_DECLS_BEGIN
+
+struct VBOXVR_SCR_COMPOSITOR_ENTRY;
+struct VBOXVR_SCR_COMPOSITOR;
+
+typedef DECLCALLBACK(void) FNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry);
+typedef FNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED *PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED;
+
+
+typedef struct VBOXVR_SCR_COMPOSITOR_ENTRY
+{
+    VBOXVR_COMPOSITOR_ENTRY Ce;
+    RTRECT Rect;
+    uint32_t fChanged;
+    uint32_t fFlags;
+    uint32_t cRects;
+    PRTRECT paSrcRects;
+    PRTRECT paDstRects;
+    PRTRECT paDstUnstretchedRects;
+    PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased;
+    PCR_TEXDATA pTex;
+} VBOXVR_SCR_COMPOSITOR_ENTRY, *PVBOXVR_SCR_COMPOSITOR_ENTRY;
+
+typedef struct VBOXVR_SCR_COMPOSITOR
+{
+    VBOXVR_COMPOSITOR Compositor;
+    RTRECT Rect;
+#ifndef IN_RING0
+    float StretchX;
+    float StretchY;
+#endif
+    uint32_t fFlags;
+    uint32_t cRects;
+    uint32_t cRectsBuffer;
+    PRTRECT paSrcRects;
+    PRTRECT paDstRects;
+    PRTRECT paDstUnstretchedRects;
+} VBOXVR_SCR_COMPOSITOR, *PVBOXVR_SCR_COMPOSITOR;
+
+
+typedef DECLCALLBACK(bool) FNVBOXVRSCRCOMPOSITOR_VISITOR(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, void *pvVisitor);
+typedef FNVBOXVRSCRCOMPOSITOR_VISITOR *PFNVBOXVRSCRCOMPOSITOR_VISITOR;
+
+DECLINLINE(void) CrVrScrCompositorEntryInit(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect, CR_TEXDATA *pTex, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
+{
+    memset(pEntry, 0, sizeof (*pEntry));
+    VBoxVrCompositorEntryInit(&pEntry->Ce);
+    pEntry->Rect = *pRect;
+    pEntry->pfnEntryReleased = pfnEntryReleased;
+    if (pTex)
+    {
+        CrTdAddRef(pTex);
+        pEntry->pTex = pTex;
+    }
+}
+
+DECLINLINE(void) CrVrScrCompositorEntryCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+    if (pEntry->pTex)
+    {
+        CrTdRelease(pEntry->pTex);
+        pEntry->pTex = NULL;
+    }
+}
+
+DECLINLINE(bool) CrVrScrCompositorEntryIsUsed(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return VBoxVrCompositorEntryIsInList(&pEntry->Ce);
+}
+
+DECLINLINE(void) CrVrScrCompositorEntrySetChanged(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool fChanged)
+{
+    pEntry->fChanged = !!fChanged;
+}
+
+DECLINLINE(void) CrVrScrCompositorEntryTexSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex)
+{
+    if (pEntry->pTex)
+        CrTdRelease(pEntry->pTex);
+
+    if (pTex)
+        CrTdAddRef(pTex);
+
+    pEntry->pTex = pTex;
+}
+
+DECLINLINE(CR_TEXDATA *) CrVrScrCompositorEntryTexGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return pEntry->pTex;
+}
+
+DECLINLINE(bool) CrVrScrCompositorEntryIsChanged(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return !!pEntry->fChanged;
+}
+
+DECLINLINE(bool) CrVrScrCompositorIsEmpty(const VBOXVR_SCR_COMPOSITOR *pCompositor)
+{
+    return VBoxVrCompositorIsEmpty(&pCompositor->Compositor);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect);
+VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex);
+VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor);
+VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged);
+DECLINLINE(bool) CrVrScrCompositorEntryIsInList(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return VBoxVrCompositorEntryIsInList(&pEntry->Ce);
+}
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos);
+DECLINLINE(const RTRECT*) CrVrScrCompositorEntryRectGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return &pEntry->Rect;
+}
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry);
+VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry);
+VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags);
+VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry);
+DECLINLINE(uint32_t) CrVrScrCompositorEntryFlagsGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return pEntry->fFlags;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect);
+VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect, bool *pfChanged);
+DECLINLINE(const RTRECT*) CrVrScrCompositorRectGet(const VBOXVR_SCR_COMPOSITOR *pCompositor)
+{
+    return &pCompositor->Rect;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor);
+VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged);
+
+typedef DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) FNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext);
+typedef FNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR *PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR;
+
+VBOXVREGDECL(int) CrVrScrCompositorClone(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor);
+VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged);
+#ifndef IN_RING0
+VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY);
+DECLINLINE(void) CrVrScrCompositorGetStretching(const VBOXVR_SCR_COMPOSITOR *pCompositor, float *pStretchX, float *pStretchY)
+{
+    if (pStretchX)
+        *pStretchX = pCompositor->StretchX;
+
+    if (pStretchY)
+        *pStretchY = pCompositor->StretchY;
+}
+#endif
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects);
+
+#define VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(_p) ((PVBOXVR_SCR_COMPOSITOR_ENTRY)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR_ENTRY, Ce)))
+#define VBOXVR_SCR_COMPOSITOR_CONST_ENTRY_FROM_ENTRY(_p) ((const VBOXVR_SCR_COMPOSITOR_ENTRY*)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR_ENTRY, Ce)))
+#define VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(_p) ((PVBOXVR_SCR_COMPOSITOR)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR, Compositor)))
+
+typedef struct VBOXVR_SCR_COMPOSITOR_ITERATOR
+{
+    VBOXVR_COMPOSITOR_ITERATOR Base;
+} VBOXVR_SCR_COMPOSITOR_ITERATOR ,*PVBOXVR_SCR_COMPOSITOR_ITERATOR;
+
+typedef struct VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR
+{
+    VBOXVR_COMPOSITOR_CONST_ITERATOR Base;
+} VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR ,*PVBOXVR_SCR_COMPOSITOR_CONST_ITERATOR;
+
+DECLINLINE(void) CrVrScrCompositorIterInit(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ITERATOR pIter)
+{
+    VBoxVrCompositorIterInit(&pCompositor->Compositor, &pIter->Base);
+}
+
+DECLINLINE(void) CrVrScrCompositorConstIterInit(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+    VBoxVrCompositorConstIterInit(&pCompositor->Compositor, &pIter->Base);
+}
+
+DECLINLINE(PVBOXVR_SCR_COMPOSITOR_ENTRY) CrVrScrCompositorIterNext(PVBOXVR_SCR_COMPOSITOR_ITERATOR pIter)
+{
+    PVBOXVR_COMPOSITOR_ENTRY pCe = VBoxVrCompositorIterNext(&pIter->Base);
+    if (pCe)
+    {
+        return VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCe);
+    }
+    return NULL;
+}
+
+DECLINLINE(const VBOXVR_SCR_COMPOSITOR_ENTRY*) CrVrScrCompositorConstIterNext(PVBOXVR_SCR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+    const VBOXVR_COMPOSITOR_ENTRY *pCe = VBoxVrCompositorConstIterNext(&pIter->Base);
+    if (pCe)
+    {
+        return VBOXVR_SCR_COMPOSITOR_CONST_ENTRY_FROM_ENTRY(pCe);
+    }
+    return NULL;
+}
+
+RT_C_DECLS_END
+
+#endif /* ___cr_compositor_h_ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_dump.h b/src/VBox/GuestHost/OpenGL/include/cr_dump.h
index 9796578..0946f56 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_dump.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_dump.h
@@ -109,7 +109,11 @@ typedef struct CR_HTML_DUMPER
     uint32_t cImg;
 } CR_HTML_DUMPER;
 
+DECLEXPORT(bool) crDmpHtmlIsInited(struct CR_HTML_DUMPER * pDumper);
+DECLEXPORT(void) crDmpHtmlTerm(struct CR_HTML_DUMPER * pDumper);
 DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile);
+DECLEXPORT(int) crDmpHtmlInitV(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, va_list pArgList);
+DECLEXPORT(int) crDmpHtmlInitF(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, ...);
 
 #ifdef RT_OS_WINDOWS
 DECLINLINE(void) crDmpDbgPrintInit(CR_DBGPRINT_DUMPER *pDumper)
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_error.h b/src/VBox/GuestHost/OpenGL/include/cr_error.h
index 12b74fb..ca472d2 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_error.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_error.h
@@ -24,10 +24,22 @@ extern "C" {
 #define PRINTF
 #endif
 
+#ifndef WARN
+# ifndef IN_RING0
+#  define LOG(_m) do { crDebug _m ; } while (0)
+#  define LOGREL(_m) do { crDebug _m ; } while (0)
+#  define WARN(_m) do { crWarning _m ; AssertMsgFailed(_m); } while (0)
+# else
+#  define LOG(_m) do { } while (0)
+#  define LOGREL(_m) do { } while (0)
+#  define WARN(_m) do { AssertMsgFailed(_m); } while (0)
+# endif
+#endif
+
 DECLEXPORT(void) crEnableWarnings(int onOff);
 
 DECLEXPORT(void) crDebug(const char *format, ... ) PRINTF;
-#ifdef DEBUG_misha
+#if defined(DEBUG_misha) && defined(RT_OS_WINDOWS)
 typedef void FNCRDEBUG(const char *format, ... ) PRINTF;
 typedef FNCRDEBUG *PFNCRDEBUG;
 DECLINLINE(PFNCRDEBUG) crGetDebug() {return crDebug;}
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_glext.h b/src/VBox/GuestHost/OpenGL/include/cr_glext.h
new file mode 100644
index 0000000..429e218
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_glext.h
@@ -0,0 +1,34 @@
+/* $Id: cr_glext.h $ */
+
+/** @file
+ * GL chromium platform specifics
+ */
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_glext_h__
+#define ___cr_glext_h__
+
+#include <iprt/assert.h>
+
+#ifndef __glext_h_
+/* glext NOT included yet */
+# include "GL/glext.h"
+#else
+/* glext IS included yet */
+# ifndef RT_OS_DARWIN
+typedef unsigned int VBoxGLhandleARB;   /* shader object handle */
+AssertCompile(sizeof (VBoxGLhandleARB) == sizeof (GLhandleARB));
+# else
+#  error "patched glext is required for OSX!"
+# endif
+#endif
+#endif /*___cr_glext_h__*/
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_glstate.h b/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
index 53b985b..95b3477 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
@@ -235,6 +235,8 @@ DECLEXPORT(void) crStateSetExtensionString( CRContext *ctx, const GLubyte *exten
 DECLEXPORT(void) crStateDiffContext( CRContext *from, CRContext *to );
 DECLEXPORT(void) crStateSwitchContext( CRContext *from, CRContext *to );
 
+DECLEXPORT(unsigned int) crStateHlpComponentsCount( GLenum pname );
+
 typedef struct CRFBDataElement
 {
     /* FBO, can be NULL */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_htable.h b/src/VBox/GuestHost/OpenGL/include/cr_htable.h
new file mode 100644
index 0000000..26c8bff
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_htable.h
@@ -0,0 +1,120 @@
+/* $Id: cr_htable.h $ */
+
+/** @file
+ * uint32_t handle to void simple table API
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_htable_h_
+#define ___cr_htable_h_
+
+#include <iprt/types.h>
+#include <iprt/cdefs.h>
+
+#include <cr_error.h>
+
+#ifndef IN_RING0
+# define VBOXHTABLEDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXHTABLEDECL(_type) RTDECL(_type)
+#endif
+
+
+
+RT_C_DECLS_BEGIN
+
+typedef uint32_t CRHTABLE_HANDLE;
+#define CRHTABLE_HANDLE_INVALID 0UL
+
+typedef struct CRHTABLE
+{
+    uint32_t cData;
+    uint32_t iNext2Search;
+    uint32_t cSize;
+    void **paData;
+} CRHTABLE, *PCRHTABLE;
+
+typedef struct CRHTABLE_ITERATOR
+{
+    PCRHTABLE pTbl;
+    uint32_t iCur;
+    uint32_t cLeft;
+} VCRHTABLE_ITERATOR, *PCRHTABLE_ITERATOR;
+
+/*private stuff, not to be used directly */
+DECLINLINE(CRHTABLE_HANDLE) crHTableIndex2Handle(uint32_t iIndex)
+{
+    return iIndex+1;
+}
+
+DECLINLINE(uint32_t) crHTableHandle2Index(CRHTABLE_HANDLE hHandle)
+{
+    return hHandle-1;
+}
+
+/* public API */
+DECLINLINE(void) CrHTableIterInit(PCRHTABLE pTbl, PCRHTABLE_ITERATOR pIter)
+{
+    pIter->pTbl = pTbl;
+    pIter->iCur = 0;
+    pIter->cLeft = pTbl->cData;
+}
+
+DECLINLINE(void*) CrHTableIterNext(PCRHTABLE_ITERATOR pIter, CRHTABLE_HANDLE *phHandle)
+{
+    PCRHTABLE pTbl;
+    uint32_t i;
+    if (!pIter->cLeft)
+    {
+        if (phHandle)
+            *phHandle = 0;
+        return NULL;
+    }
+
+    pTbl = pIter->pTbl;
+
+    for (i = pIter->iCur; i < pTbl->cSize; ++i)
+    {
+        if (pTbl->paData[i])
+        {
+            pIter->iCur = i+1;
+            --(pIter->cLeft);
+            if (phHandle)
+                *phHandle = crHTableIndex2Handle(i);
+            return pTbl->paData[i];
+        }
+    }
+
+    crWarning("interator concurent modification!");
+    return NULL;
+}
+
+VBOXHTABLEDECL(int) CrHTableCreate(PCRHTABLE pTbl, uint32_t cSize);
+DECLINLINE(void) CrHTableMoveTo(PCRHTABLE pSrcTbl, PCRHTABLE pDstTbl)
+{
+    *pDstTbl = *pSrcTbl;
+    CrHTableCreate(pSrcTbl, 0);
+}
+VBOXHTABLEDECL(void) CrHTableEmpty(PCRHTABLE pTbl);
+VBOXHTABLEDECL(void) CrHTableDestroy(PCRHTABLE pTbl);
+VBOXHTABLEDECL(int) CrHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize);
+VBOXHTABLEDECL(CRHTABLE_HANDLE) CrHTablePut(PCRHTABLE pTbl, void *pvData);
+VBOXHTABLEDECL(int) CrHTablePutToSlot(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle, void* pvData);
+
+/* note: can be called for the element returned with CrHTableIterNext w/o corrupting the iterator */
+VBOXHTABLEDECL(void*) CrHTableRemove(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle);
+VBOXHTABLEDECL(void*) CrHTableGet(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle);
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_htable_h_*/
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_protocol.h b/src/VBox/GuestHost/OpenGL/include/cr_protocol.h
index 038fea6..1bf785b 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_protocol.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_protocol.h
@@ -7,6 +7,7 @@
 #ifndef CR_PROTOCOL_H
 #define CR_PROTOCOL_H
 
+#include <iprt/types.h>
 #include <iprt/cdefs.h>
 #ifdef DEBUG_misha
 #include "cr_error.h"
@@ -23,8 +24,8 @@ extern "C" {
 
 /* new TexPresent mechanism is available */
 #define CR_VBOX_CAP_TEX_PRESENT    0x00000001
-/* no DWM support available, required for Win8 guests to switch to display-only mode gracefully */
-#define CR_VBOX_CAP_NO_DWM_SUPPORT 0x00000002
+/* vbva command submission mechanism supported */
+#define CR_VBOX_CAP_CMDVBVA        0x00000002
 
 
 #define CR_PRESENT_SCREEN_MASK 0xffff
@@ -68,7 +69,7 @@ typedef union {
     /* unsigned int  junk[512]; */
 } CRNetworkPointer;
 
-#ifdef DEBUG_misha
+#if 0 //def DEBUG_misha
 #define CRDBGPTR_SETZ(_p) crMemset((_p), 0, sizeof (CRNetworkPointer))
 #define CRDBGPTR_CHECKZ(_p) do { \
         CRNetworkPointer _ptr = {0}; \
@@ -97,26 +98,32 @@ typedef union {
 
 #ifdef VBOX_WITH_CRHGSMI
 typedef struct CRVBOXHGSMI_CMDDATA {
-    struct VBOXVDMACMD_CHROMIUM_CMD *pCmd;
+    union
+    {
+        struct VBOXVDMACMD_CHROMIUM_CMD *pHgsmiCmd;
+        struct VBOXCMDVBVA_CRCMD_CMD *pVbvaCmd;
+        void *pvCmd;
+    };
     int          *pCmdRc;
     char         *pWriteback;
     unsigned int *pcbWriteback;
     unsigned int cbWriteback;
+    bool fHgsmiCmd;
 } CRVBOXHGSMI_CMDDATA, *PCRVBOXHGSMI_CMDDATA;
 
 #ifdef DEBUG
 # define CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(_pData)  do { \
-        CRASSERT(!(_pData)->pCmd == !(_pData)->pCmdRc); \
+        CRASSERT(!(_pData)->pvCmd == !(_pData)->pCmdRc); \
         CRASSERT(!(_pData)->pWriteback == !(_pData)->pcbWriteback); \
         CRASSERT(!(_pData)->pWriteback == !(_pData)->cbWriteback); \
         if ((_pData)->pWriteback) \
         { \
-            CRASSERT((_pData)->pCmd); \
+            CRASSERT((_pData)->pvCmd); \
         } \
     } while (0)
 
 # define CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(_pData)  do { \
-        CRASSERT(!(_pData)->pCmd); \
+        CRASSERT(!(_pData)->pvCmd); \
         CRASSERT(!(_pData)->pCmdRc); \
         CRASSERT(!(_pData)->pWriteback); \
         CRASSERT(!(_pData)->pcbWriteback); \
@@ -139,7 +146,8 @@ typedef struct CRVBOXHGSMI_CMDDATA {
 # define CRVBOXHGSMI_CMDDATA_ASSERT_ISSETWB(_pData)  do { } while (0)
 #endif
 
-#define CRVBOXHGSMI_CMDDATA_IS_SET(_pData) (!!(_pData)->pCmd)
+#define CRVBOXHGSMI_CMDDATA_IS_HGSMICMD(_pData) (!!(_pData)->fHgsmiCmd)
+#define CRVBOXHGSMI_CMDDATA_IS_SET(_pData) (!!(_pData)->pvCmd)
 #define CRVBOXHGSMI_CMDDATA_IS_SETWB(_pData) (!!(_pData)->pWriteback)
 
 #define CRVBOXHGSMI_CMDDATA_CLEANUP(_pData) do { \
@@ -148,15 +156,16 @@ typedef struct CRVBOXHGSMI_CMDDATA {
         CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(_pData); \
     } while (0)
 
-#define CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr) do { \
+#define CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr, _fHgsmiCmd) do { \
         CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(_pData); \
-        (_pData)->pCmd = (_pCmd); \
+        (_pData)->pvCmd = (_pCmd); \
         (_pData)->pCmdRc = &(_pHdr)->result; \
+        (_pData)->fHgsmiCmd = (_fHgsmiCmd); \
         CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(_pData); \
     } while (0)
 
-#define CRVBOXHGSMI_CMDDATA_SETWB(_pData, _pCmd, _pHdr, _pWb, _cbWb, _pcbWb) do { \
-        CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr); \
+#define CRVBOXHGSMI_CMDDATA_SETWB(_pData, _pCmd, _pHdr, _pWb, _cbWb, _pcbWb, _fHgsmiCmd) do { \
+        CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr, _fHgsmiCmd); \
         (_pData)->pWriteback = (_pWb); \
         (_pData)->pcbWriteback = (_pcbWb); \
         (_pData)->cbWriteback = (_cbWb); \
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_server.h b/src/VBox/GuestHost/OpenGL/include/cr_server.h
index 12ad7bc..8efdef5 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_server.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_server.h
@@ -26,15 +26,13 @@
 #include <iprt/thread.h>
 #include <iprt/critsect.h>
 #include <iprt/semaphore.h>
+#include <iprt/memcache.h>
 
 #include <VBox/vmm/ssm.h>
 
-#ifdef VBOX_WITH_CRHGSMI
-# include <VBox/VBoxVideo.h>
-#endif
+#include <VBox/VBoxVideo.h>
 #include <VBox/Hardware/VBoxVideoVBE.h>
-
-#include "cr_vreg.h"
+#include <VBox/VBoxVideo3D.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -91,6 +89,12 @@ typedef struct {
     int32_t externalID;
 } CRCreateInfo_t;
 
+typedef struct {
+    char   *pszDpyName;
+    int32_t externalID;
+    GLint   requestedVisualBits;
+    GLint   realVisualBits;
+} CRCreateInfoEx_t;
 
 /* VRAM->RAM worker thread */
 
@@ -202,18 +206,17 @@ typedef struct CR_SERVER_RPW {
 } CR_SERVER_RPW;
 /* */
 
-/* DISPLAY */
-/* define display entry early so it can be used in MuralInfo */
-typedef struct CR_DISPLAY_ENTRY
-{
-    VBOXVR_SCR_COMPOSITOR_ENTRY CEntry;
-    VBOXVR_SCR_COMPOSITOR_ENTRY RootVrCEntry;
-    void *pvORInstance;
-    GLuint idPBO;
-    GLuint idInvertTex;
-} CR_DISPLAY_ENTRY, *PCR_DISPLAY_ENTRY;
-/**/
+/* FRAMEBUFFER */
+typedef struct CR_FRAMEBUFFER *HCR_FRAMEBUFFER;
+typedef struct CR_FRAMEBUFFER_ENTRY *HCR_FRAMEBUFFER_ENTRY;
+/* */
 
+typedef struct CR_FBDATA
+{
+    HCR_FRAMEBUFFER hFb;
+    HCR_FRAMEBUFFER_ENTRY hFbEntry;
+    CR_TEXDATA* apTexDatas[2];
+} CR_FBDATA;
 /**
  * Mural info
  */
@@ -229,7 +232,7 @@ typedef struct {
     GLboolean bVisible;      /*guest window is visible*/
     GLubyte   u8Unused;       /*redirect to FBO instead of real host window*/
     GLboolean bFbDraw;       /*GL_FRONT buffer is drawn to directly*/
-    GLboolean fDataPresented;
+    GLboolean fReserved;
 
     GLint       cVisibleRects;    /*count of visible rects*/
     GLint      *pVisibleRects;    /*visible rects left, top, right, bottom*/
@@ -242,7 +245,7 @@ typedef struct {
 
     void *pvReserved;
 
-    CRCreateInfo_t CreateInfo;
+    CRCreateInfoEx_t CreateInfo;
 
     /* to avoid saved state breakage we need to keep RT_OFFSETOF(CRMuralInfo, CreateInfo) intact
      * this is why we place some FBO stuff to the tail
@@ -253,28 +256,18 @@ typedef struct {
     GLuint idDepthStencilRB;
     GLuint fboWidth, fboHeight;
 
-    GLuint cDisabled;
-
-    GLuint   fPresentMode;       /*redirect to FBO instead of real host window*/
-
     GLboolean fHasParentWindow;
 
-    GLboolean fRootVrOn;
+    GLboolean fRedirected;
     GLboolean fForcePresentState;
     GLboolean fOrPresentOnReenable;
 
-    GLboolean fUseDefaultDEntry;
-
     GLboolean fIsVisible;
 
-    CR_DISPLAY_ENTRY DefaultDEntry;
-
-    VBOXVR_SCR_COMPOSITOR Compositor;
-
-    /* if root Visible regions are set, these two contain actual regions being passed to render spu */
-    VBOXVR_SCR_COMPOSITOR RootVrCompositor;
-
-    CR_SERVER_RPW_ENTRY RpwEntry;
+    CR_TEXDATA aTexs[2];
+    uint32_t cUsedFBDatas;
+    CR_FBDATA *apUsedFBDatas[CR_MAX_GUEST_MONITORS];
+    CR_FBDATA aFBDatas[CR_MAX_GUEST_MONITORS];
 
     /* bitfield representing contexts the mural has been ever current with
      * we just reuse CR_STATE_SHAREDOBJ_USAGE_XXX API here for simplicity */
@@ -284,7 +277,7 @@ typedef struct {
 typedef struct {
     CRContext *pContext;
     int SpuContext;
-    CRCreateInfo_t CreateInfo;
+    CRCreateInfoEx_t CreateInfo;
     CRMuralInfo * currentMural;
 } CRContextInfo;
 
@@ -342,52 +335,9 @@ typedef struct {
 } CRScreenInfo;
 
 typedef struct {
-    int32_t    x, y;
-    uint32_t   w, h;
+    RTRECT Rect;
 } CRScreenViewportInfo;
 
-
-/* DISPLAY */
-
-#define CR_DENTRY_FROM_CENTRY(_pCentry) ((CR_DISPLAY_ENTRY*)((uint8_t*)(_pCentry) - RT_OFFSETOF(CR_DISPLAY_ENTRY, CEntry)))
-
-
-/* @todo:
- * 1. use compositor stored inside mural to use current MuralFBO and window-related API
- * 2. CR_SERVER_REDIR_F_NONE and CR_SERVER_REDIR_F_FBO should be trated identically for presented window
- *    since we just need to blit the given textures to it if we are NOT in CR_SERVER_REDIR_F_FBO_RAM mode */
-typedef struct CR_DISPLAY
-{
-    CRMuralInfo Mural;
-    GLboolean fForcePresent;
-} CR_DISPLAY, *PCR_DISPLAY;
-
-
-typedef struct CR_DISPLAY_ENTRY_MAP
-{
-    CRHashTable * pTexIdToDemInfoMap;
-    uint32_t cEntered;
-    RTLISTNODE ReleasedList;
-} CR_DISPLAY_ENTRY_MAP, *PCR_DISPLAY_ENTRY_MAP;
-
-
-typedef struct CRWinVisibilityInfo
-{
-    uint32_t cVisibleWindows        : 30;
-    uint32_t fLastReportedVisible   : 1;
-    uint32_t fVisibleChanged        : 1;
-} CRWinVisibilityInfo;
-
-/* */
-
-/* helpers */
-
-void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData);
-void* CrHlpGetTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLuint idPBO, GLenum enmFormat);
-void CrHlpPutTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLenum enmFormat, void *pvData);
-
-/* */
-
 /* BFB (BlitFramebuffer Blitter) flags
  * so far only CR_SERVER_BFB_ON_ALWAIS is supported and is alwais used if any flag is set */
 #define CR_SERVER_BFB_DISABLED 0
@@ -456,6 +406,8 @@ typedef struct {
     uint32_t fBlitterMode;
     CR_BLITTER Blitter;
 
+    VBOXCRCMD_CLTINFO CltInfo;
+
     CR_SERVER_RPW RpwWorker;
 
     /** configuration options */
@@ -513,13 +465,10 @@ typedef struct {
     GLuint currentSerialNo;
 
     PFNCRSERVERPRESENTFBO pfnPresentFBO;
-    GLuint                fPresentMode; /*Force server to render 3d data offscreen
-                                                     *using callback above to update vbox framebuffers*/
-    GLuint                fPresentModeDefault; /*can be set with CR_SERVER_DEFAULT_RENDER_TYPE*/
-    GLuint                fVramPresentModeDefault;
+
+    GLuint                fVisualBitsDefault;
     GLboolean             bUsePBOForReadback;       /*Use PBO's for data readback*/
 
-    GLboolean             bUseOutputRedirect;       /* Whether the output redirect was set. */
     CROutputRedirect      outputRedirect;
 
     GLboolean             bUseMultipleContexts;
@@ -532,9 +481,6 @@ typedef struct {
      * that the TexPresent mechanism is available and enabled */
     uint32_t              u32Caps;
 
-    uint32_t cDisableEvents;
-    CRWinVisibilityInfo  aWinVisibilityInfos[CR_MAX_GUEST_MONITORS];
-
     PFNCRSERVERNOTIFYEVENT pfnNotifyEventCB;
 
     SPUDispatchTable TmpCtxDispatch;
@@ -549,12 +495,6 @@ typedef struct {
 
     int RcToGuest;
     int RcToGuestOnce;
-
-    /* @todo: should we use just one blitter?
-     * we use two currently because the drawable attribs can differ*/
-    CR_DISPLAY_ENTRY_MAP  PresentTexturepMap;
-    uint32_t              DisplaysInitMap[(CR_MAX_GUEST_MONITORS + 31)/32];
-    CR_DISPLAY            aDispplays[CR_MAX_GUEST_MONITORS];
 } CRServer;
 
 
@@ -578,10 +518,24 @@ extern DECLEXPORT(int32_t) crVBoxServerClientSetPID(uint32_t u32ClientID, uint64
 extern DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM);
 extern DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version);
 
+typedef struct
+{
+    CR_BLITTER_IMG Img;
+    uint32_t u32Screen;
+    uint32_t fDataAllocated;
+} CR_SCREENSHOT;
+
+extern DECLEXPORT(int) crServerVBoxWindowsShow(bool fShow);
+extern DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, uint32_t height, uint32_t pitch, void *pvBuffer, CR_SCREENSHOT *pScreenshot);
+extern DECLEXPORT(void) crServerVBoxScreenshotRelease(CR_SCREENSHOT *pScreenshot);
+
+extern DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable);
 extern DECLEXPORT(int32_t) crVBoxServerSetScreenCount(int sCount);
 extern DECLEXPORT(int32_t) crVBoxServerUnmapScreen(int sIndex);
 extern DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h, uint64_t winID);
 extern DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable);
+struct VBVAINFOSCREEN;
+extern DECLEXPORT(int) crVBoxServerNotifyResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM);
 extern DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, const RTRECT *pRects);
 
 extern DECLEXPORT(void) crVBoxServerSetPresentFBOCB(PFNCRSERVERPRESENTFBO pfnPresentFBO);
@@ -610,6 +564,8 @@ extern DECLEXPORT(void) crServerVBoxSetNotifyEventCB(PFNCRSERVERNOTIFYEVENT pfnC
  * */
 extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t cbCmd);
 extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl);
+
+extern DECLEXPORT(int32_t) crVBoxServerCrCmdNotifyCmds();
 #endif
 
 #ifdef __cplusplus
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_version.h b/src/VBox/GuestHost/OpenGL/include/cr_version.h
index 3c930e8..6b6a7c5 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_version.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_version.h
@@ -38,7 +38,9 @@
 #define SHCROGL_SSM_VERSION_WITH_FIXED_DUMMYIDS                     39
 #define SHCROGL_SSM_VERSION_WITH_SCREEN_INFO                        40
 #define SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS                     41
-#define SHCROGL_SSM_VERSION                                         41
+#define SHCROGL_SSM_VERSION_WITH_FB_INFO                            42
+#define SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS                         42
+#define SHCROGL_SSM_VERSION                                         43
 
 /* These define the Chromium release number.
  * Alpha Release = 0.1.0, Beta Release = 0.2.0
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_vreg.h b/src/VBox/GuestHost/OpenGL/include/cr_vreg.h
index e00e9e5..353178d 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_vreg.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_vreg.h
@@ -24,6 +24,7 @@
 #include <iprt/string.h>
 #include <iprt/assert.h>
 #include <iprt/critsect.h>
+#include <iprt/asm.h>
 
 #ifndef IN_RING0
 # define VBOXVREGDECL(_type) DECLEXPORT(_type)
@@ -47,18 +48,20 @@ DECLINLINE(int) VBoxRectCmp(const RTRECT * pRect1, const RTRECT * pRect2)
 }
 
 #ifndef IN_RING0
-DECLINLINE(void) VBoxRectStretch(PRTRECT pRect, float xStretch, float yStretch)
+#define CR_FLOAT_RCAST(_t, _v) ((_t)((float)(_v) + 0.5))
+
+DECLINLINE(void) VBoxRectScale(PRTRECT pRect, float xScale, float yScale)
 {
-    pRect->xLeft = pRect->xLeft * xStretch;
-    pRect->yTop = pRect->yTop * yStretch;
-    pRect->xRight = pRect->xRight * xStretch;
-    pRect->yBottom = pRect->yBottom * yStretch;
+    pRect->xLeft = CR_FLOAT_RCAST(int32_t, pRect->xLeft * xScale);
+    pRect->yTop = CR_FLOAT_RCAST(int32_t, pRect->yTop * yScale);
+    pRect->xRight = CR_FLOAT_RCAST(int32_t, pRect->xRight * xScale);
+    pRect->yBottom = CR_FLOAT_RCAST(int32_t, pRect->yBottom * yScale);
 }
 
-DECLINLINE(void) VBoxRectStretched(const RTRECT *pRect, float xStretch, float yStretch, PRTRECT pResult)
+DECLINLINE(void) VBoxRectScaled(const RTRECT *pRect, float xScale, float yScale, PRTRECT pResult)
 {
     *pResult = *pRect;
-    VBoxRectStretch(pResult, xStretch, yStretch);
+    VBoxRectScale(pResult, xScale, yScale);
 }
 #endif
 
@@ -93,6 +96,19 @@ DECLINLINE(void) VBoxRectTranslated(const RTRECT * pRect, int32_t x, int32_t y,
     VBoxRectTranslate(pResult, x, y);
 }
 
+DECLINLINE(void) VBoxRectInvertY(RTRECT * pRect)
+{
+    int32_t y = pRect->yTop;
+    pRect->yTop = pRect->yBottom;
+    pRect->yBottom = y;
+}
+
+DECLINLINE(void) VBoxRectInvertedY(const RTRECT * pRect, RTRECT * pResult)
+{
+    *pResult = *pRect;
+    VBoxRectInvertY(pResult);
+}
+
 DECLINLINE(void) VBoxRectMove(RTRECT * pRect, int32_t x, int32_t y)
 {
     int32_t w = pRect->xRight - pRect->xLeft;
@@ -109,7 +125,7 @@ DECLINLINE(void) VBoxRectMoved(const RTRECT * pRect, int32_t x, int32_t y, RTREC
     VBoxRectMove(pResult, x, y);
 }
 
-DECLINLINE(bool) VBoxRectIsCoveres(const RTRECT *pRect, const RTRECT *pCovered)
+DECLINLINE(bool) VBoxRectCovers(const RTRECT *pRect, const RTRECT *pCovered)
 {
     Assert(pRect);
     Assert(pCovered);
@@ -289,13 +305,26 @@ typedef struct VBOXVR_COMPOSITOR_ITERATOR
     PRTLISTNODE pNextEntry;
 } VBOXVR_COMPOSITOR_ITERATOR ,*PVBOXVR_COMPOSITOR_ITERATOR;
 
+typedef struct VBOXVR_COMPOSITOR_CONST_ITERATOR
+{
+    const VBOXVR_COMPOSITOR *pCompositor;
+    const RTLISTNODE *pNextEntry;
+} VBOXVR_COMPOSITOR_CONST_ITERATOR ,*PVBOXVR_COMPOSITOR_CONST_ITERATOR;
+
 DECLINLINE(void) VBoxVrCompositorIterInit(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ITERATOR pIter)
 {
     pIter->pCompositor = pCompositor;
     pIter->pNextEntry = pCompositor->List.pNext;
 }
 
+DECLINLINE(void) VBoxVrCompositorConstIterInit(const VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+    pIter->pCompositor = pCompositor;
+    pIter->pNextEntry = pCompositor->List.pNext;
+}
+
 #define VBOXVR_COMPOSITOR_ENTRY_FROM_NODE(_p) ((PVBOXVR_COMPOSITOR_ENTRY)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_COMPOSITOR_ENTRY, Node)))
+#define VBOXVR_COMPOSITOR_CONST_ENTRY_FROM_NODE(_p) ((const VBOXVR_COMPOSITOR_ENTRY*)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_COMPOSITOR_ENTRY, Node)))
 
 DECLINLINE(PVBOXVR_COMPOSITOR_ENTRY) VBoxVrCompositorIterNext(PVBOXVR_COMPOSITOR_ITERATOR pIter)
 {
@@ -309,7 +338,17 @@ DECLINLINE(PVBOXVR_COMPOSITOR_ENTRY) VBoxVrCompositorIterNext(PVBOXVR_COMPOSITOR
     return NULL;
 }
 
-/* Compositor with Stretching & Cached Rectangles info */
+DECLINLINE(const VBOXVR_COMPOSITOR_ENTRY*) VBoxVrCompositorConstIterNext(PVBOXVR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+    const RTLISTNODE *pNextEntry = pIter->pNextEntry;
+    if (pNextEntry != &pIter->pCompositor->List)
+    {
+        const VBOXVR_COMPOSITOR_ENTRY *pEntry = VBOXVR_COMPOSITOR_CONST_ENTRY_FROM_NODE(pNextEntry);
+        pIter->pNextEntry = pNextEntry->pNext;
+        return pEntry;
+    }
+    return NULL;
+}
 
 typedef struct VBOXVR_TEXTURE
 {
@@ -319,162 +358,6 @@ typedef struct VBOXVR_TEXTURE
     uint32_t hwid;
 } VBOXVR_TEXTURE, *PVBOXVR_TEXTURE;
 
-struct VBOXVR_SCR_COMPOSITOR_ENTRY;
-struct VBOXVR_SCR_COMPOSITOR;
-
-typedef DECLCALLBACK(void) FNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry);
-typedef FNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED *PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED;
-
-
-typedef struct VBOXVR_SCR_COMPOSITOR_ENTRY
-{
-    VBOXVR_COMPOSITOR_ENTRY Ce;
-    VBOXVR_TEXTURE Tex;
-    RTPOINT Pos;
-    uint32_t fChanged;
-    uint32_t fFlags;
-    uint32_t cRects;
-    PRTRECT paSrcRects;
-    PRTRECT paDstRects;
-    PRTRECT paDstUnstretchedRects;
-    PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased;
-} VBOXVR_SCR_COMPOSITOR_ENTRY, *PVBOXVR_SCR_COMPOSITOR_ENTRY;
-
-typedef struct VBOXVR_SCR_COMPOSITOR
-{
-    VBOXVR_COMPOSITOR Compositor;
-#ifndef IN_RING0
-    float StretchX;
-    float StretchY;
-#endif
-    uint32_t fFlags;
-    uint32_t cRects;
-    uint32_t cRectsBuffer;
-    PRTRECT paSrcRects;
-    PRTRECT paDstRects;
-    PRTRECT paDstUnstretchedRects;
-} VBOXVR_SCR_COMPOSITOR, *PVBOXVR_SCR_COMPOSITOR;
-
-
-typedef DECLCALLBACK(bool) FNVBOXVRSCRCOMPOSITOR_VISITOR(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, void *pvVisitor);
-typedef FNVBOXVRSCRCOMPOSITOR_VISITOR *PFNVBOXVRSCRCOMPOSITOR_VISITOR;
-
-DECLINLINE(void) CrVrScrCompositorEntryInit(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_TEXTURE *pTex, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
-{
-    VBoxVrCompositorEntryInit(&pEntry->Ce);
-    pEntry->Tex = *pTex;
-    memset(&pEntry->Pos, 0, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR_ENTRY, Pos));
-    pEntry->pfnEntryReleased = pfnEntryReleased;
-}
-
-DECLINLINE(bool) CrVrScrCompositorEntryIsUsed(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
-{
-    return VBoxVrCompositorEntryIsInList(&pEntry->Ce);
-}
-
-DECLINLINE(void) CrVrScrCompositorEntrySetChanged(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool fChanged)
-{
-    pEntry->fChanged = !!fChanged;
-}
-
-DECLINLINE(void) CrVrScrCompositorEntryTexNameUpdate(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t hwid)
-{
-    pEntry->Tex.hwid = hwid;
-    CrVrScrCompositorEntrySetChanged(pEntry, true);
-}
-
-DECLINLINE(const VBOXVR_TEXTURE *) CrVrScrCompositorEntryTexGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
-{
-    return &pEntry->Tex;
-}
-
-DECLINLINE(bool) CrVrScrCompositorEntryIsChanged(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
-{
-    return !!pEntry->fChanged;
-}
-
-DECLINLINE(bool) CrVrScrCompositorIsEmpty(const VBOXVR_SCR_COMPOSITOR *pCompositor)
-{
-    return VBoxVrCompositorIsEmpty(&pCompositor->Compositor);
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryTexUpdate(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_TEXTURE *pTex);
-VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor);
-VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged);
-DECLINLINE(bool) CrVrScrCompositorEntryIsInList(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
-{
-    return VBoxVrCompositorEntryIsInList(&pEntry->Ce);
-}
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags);
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged);
-VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged);
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
-VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged);
-VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos);
-DECLINLINE(const RTPOINT*) CrVrScrCompositorEntryPosGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
-{
-    return &pEntry->Pos;
-}
-
-/* regions are valid until the next CrVrScrCompositor call */
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects);
-VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry);
-VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry);
-VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags);
-VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry);
-DECLINLINE(uint32_t) CrVrScrCompositorEntryFlagsGet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
-{
-    return pEntry->fFlags;
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor);
-VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor);
-VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged);
-
-typedef DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) FNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR(VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext);
-typedef FNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR *PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR;
-
-VBOXVREGDECL(int) CrVrScrCompositorClone(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor);
-VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged);
-VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged);
-#ifndef IN_RING0
-VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY);
-DECLINLINE(void) CrVrScrCompositorGetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float *pStretchX, float *pStretchY)
-{
-    if (pStretchX)
-        *pStretchX = pCompositor->StretchX;
-
-    if (pStretchY)
-        *pStretchY = pCompositor->StretchY;
-}
-#endif
-/* regions are valid until the next CrVrScrCompositor call */
-VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects);
-
-#define VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(_p) ((PVBOXVR_SCR_COMPOSITOR_ENTRY)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR_ENTRY, Ce)))
-#define VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(_p) ((PVBOXVR_SCR_COMPOSITOR)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR, Compositor)))
-
-typedef struct VBOXVR_SCR_COMPOSITOR_ITERATOR
-{
-    VBOXVR_COMPOSITOR_ITERATOR Base;
-} VBOXVR_SCR_COMPOSITOR_ITERATOR ,*PVBOXVR_SCR_COMPOSITOR_ITERATOR;
-
-DECLINLINE(void) CrVrScrCompositorIterInit(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ITERATOR pIter)
-{
-    VBoxVrCompositorIterInit(&pCompositor->Compositor, &pIter->Base);
-}
-
-DECLINLINE(PVBOXVR_SCR_COMPOSITOR_ENTRY) CrVrScrCompositorIterNext(PVBOXVR_SCR_COMPOSITOR_ITERATOR pIter)
-{
-    PVBOXVR_COMPOSITOR_ENTRY pCe = VBoxVrCompositorIterNext(&pIter->Base);
-    if (pCe)
-    {
-        return VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCe);
-    }
-    return NULL;
-}
-
 RT_C_DECLS_END
 
 #endif /* #ifndef ___cr_vreg_h_ */
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h b/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h
index b5dde7a..81ed568 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h
@@ -99,7 +99,7 @@ DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type);
 
 DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint id, GLenum type);
 DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint id);
-DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( GLhandleARB obj );
+DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj );
 
 DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program);
 
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c b/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c
index 14b86a9..a8ae7fc 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c
@@ -6,8 +6,6 @@
 
 #include "packer.h"
 
-#include <GL/glext.h>
-
 int __packTexParameterNumParams( GLenum param )
 {
     switch( param )
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c b/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c
index c84b657..b788bd4 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c
@@ -468,7 +468,7 @@ void PACK_APIENTRY crPackGetAttachedShaders(GLuint program, GLsizei maxCount, GL
     CR_UNLOCK_PACKER_CONTEXT(pc);
 }
 
-void PACK_APIENTRY crPackGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj, int * writeback)
+void PACK_APIENTRY crPackGetAttachedObjectsARB(VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * count, VBoxGLhandleARB * obj, int * writeback)
 {
 	CR_GET_PACKER_CONTEXT(pc);
 	unsigned char *data_ptr;
@@ -476,7 +476,7 @@ void PACK_APIENTRY crPackGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei
 	CR_GET_BUFFERED_POINTER(pc, 32);
 	WRITE_DATA(0, GLint, 32);
 	WRITE_DATA(4, GLenum, CR_GETATTACHEDOBJECTSARB_EXTEND_OPCODE);
-	WRITE_DATA(8, GLhandleARB, containerObj);
+	WRITE_DATA(8, VBoxGLhandleARB, containerObj);
 	WRITE_DATA(12, GLsizei, maxCount);
 	WRITE_NETWORK_POINTER(16, (void *) count);
 	WRITE_NETWORK_POINTER(24, (void *) writeback);
@@ -484,7 +484,7 @@ void PACK_APIENTRY crPackGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei
     CR_UNLOCK_PACKER_CONTEXT(pc);
 }
 
-void PACK_APIENTRY crPackGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog, int * writeback)
+void PACK_APIENTRY crPackGetInfoLogARB(VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog, int * writeback)
 {
 	CR_GET_PACKER_CONTEXT(pc);
 	unsigned char *data_ptr;
@@ -492,7 +492,7 @@ void PACK_APIENTRY crPackGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsiz
 	CR_GET_BUFFERED_POINTER(pc, 32);
 	WRITE_DATA(0, GLint, 32);
 	WRITE_DATA(4, GLenum, CR_GETINFOLOGARB_EXTEND_OPCODE);
-	WRITE_DATA(8, GLhandleARB, obj);
+	WRITE_DATA(8, VBoxGLhandleARB, obj);
 	WRITE_DATA(12, GLsizei, maxLength);
 	WRITE_NETWORK_POINTER(16, (void *) length);
 	WRITE_NETWORK_POINTER(24, (void *) writeback);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
index 7f171c3..8132d9f 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
@@ -336,7 +336,7 @@ VBOXDUMPDECL(void) crRecDumpVertAttrF(CR_RECORDER *pRec, CRContext *ctx, const c
     va_end(pArgList);
 }
 
-void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex)
+void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex)
 {
     GLenum texTarget = 0;
     GLint hwBuf = 0, hwDrawBuf = 0;
@@ -411,7 +411,7 @@ void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCur
 
         pTl = &pTobj->level[0][hwTexLevel];
 
-        rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
+        rc = CrBltEnter(pRec->pBlitter);
         if (!RT_SUCCESS(rc))
         {
             crWarning("CrBltEnter failed, rc %d", rc);
@@ -446,7 +446,7 @@ void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCur
         width = pRedirTex->width;
         height = pRedirTex->height;
 
-        rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
+        rc = CrBltEnter(pRec->pBlitter);
         if (!RT_SUCCESS(rc))
         {
             crWarning("CrBltEnter failed, rc %d", rc);
@@ -729,7 +729,7 @@ void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
 
     crRecDumpLog(pRec, hwid);
 
-    GLhandleARB *pShaders = (GLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
+    VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
     if (!pShaders)
     {
         crWarning("crCalloc failed");
@@ -740,7 +740,10 @@ void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
     pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
     for (GLint i = 0; i < cShaders; ++i)
     {
-        crRecDumpShader(pRec, ctx, 0, pShaders[i]);
+        if (pShaders[i])
+            crRecDumpShader(pRec, ctx, 0, pShaders[i]);
+        else
+            crDmpStrF(pRec->pDumper, "WARNING: Shader[%d] is null", i);
     }
 
     crFree(pShaders);
@@ -847,7 +850,7 @@ void crRecRecompileProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hw
 
     crDmpStrF(pRec->pDumper, "==RECOMPILE PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d)==", ctx->id, id, hwid, linkStatus, cShaders);
 
-    GLhandleARB *pShaders = (GLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
+    VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
     if (!pShaders)
     {
         crWarning("crCalloc failed");
@@ -1334,10 +1337,10 @@ void crRecAlphaImgDestroy(CR_BLITTER_IMG *pImg)
     pImg->pvData = NULL;
 }
 
-void crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, va_list pArgList)
+void crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, va_list pArgList)
 {
     CR_BLITTER_IMG Img = {0};
-    int rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
+    int rc = CrBltEnter(pRec->pBlitter);
     if (RT_SUCCESS(rc))
     {
         rc = CrBltImgGetTex(pRec->pBlitter, pTex, GL_BGRA, &Img);
@@ -1372,15 +1375,15 @@ void crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, CR_BLITTER
     }
 }
 
-void crRecDumpTextureF(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, ...)
+void crRecDumpTextureF(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, ...)
 {
     va_list pArgList;
     va_start(pArgList, pszStr);
-    crRecDumpTextureV(pRec, pTex, pCurCtx, pCurWin, pszStr, pArgList);
+    crRecDumpTextureV(pRec, pTex, pszStr, pArgList);
     va_end(pArgList);
 }
 
-void crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, va_list pArgList)
+void crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, va_list pArgList)
 {
     CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, id);
     if (!pTobj)
@@ -1402,18 +1405,18 @@ void crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, CR_BLITT
         return;
     }
 
-    crRecDumpTextureV(pRec, &Tex, pCurCtx, pCurWin, pszStr, pArgList);
+    crRecDumpTextureV(pRec, &Tex, pszStr, pArgList);
 }
 
-void crRecDumpTextureByIdF(CR_RECORDER *pRec, CRContext *ctx, GLint id, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, ...)
+void crRecDumpTextureByIdF(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, ...)
 {
     va_list pArgList;
     va_start(pArgList, pszStr);
-    crRecDumpTextureByIdV(pRec, ctx, id, pCurCtx, pCurWin, pszStr, pArgList);
+    crRecDumpTextureByIdV(pRec, ctx, id, pszStr, pArgList);
     va_end(pArgList);
 }
 
-void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin)
+void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx)
 {
     GLint maxUnits = 0;
     GLint curTexUnit = 0;
@@ -1506,7 +1509,7 @@ void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pC
                     crRecDumpTexGen(pRec, ctx);
                 }
 
-                crRecDumpTextureF(pRec, &Tex, pCurCtx, pCurWin, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d), width(%d), height(%d)", ctx, i, pTobj->id, pTobj->hwid, width, height);
+                crRecDumpTextureF(pRec, &Tex, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d), width(%d), height(%d)", ctx, i, pTobj->id, pTobj->hwid, width, height);
             }
 //            else
 //            {
@@ -1554,7 +1557,7 @@ void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pC
                 Tex.target = GL_TEXTURE_RECTANGLE_NV;
                 Tex.hwid = hwTex;
 
-                rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
+                rc = CrBltEnter(pRec->pBlitter);
                 if (RT_SUCCESS(rc))
                 {
                     rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
@@ -1664,6 +1667,18 @@ static void crDmpHtmlPrintFooter(struct CR_HTML_DUMPER * pDumper)
     fflush(pDumper->pFile);
 }
 
+DECLEXPORT(bool) crDmpHtmlIsInited(struct CR_HTML_DUMPER * pDumper)
+{
+    return !!pDumper->pFile;
+}
+
+DECLEXPORT(void) crDmpHtmlTerm(struct CR_HTML_DUMPER * pDumper)
+{
+    crDmpHtmlPrintFooter(pDumper);
+    fclose (pDumper->pFile);
+    pDumper->pFile = NULL;
+}
+
 DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile)
 {
     int rc = VERR_NO_MEMORY;
@@ -1706,4 +1721,21 @@ DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDi
     return rc;
 }
 
+DECLEXPORT(int) crDmpHtmlInitV(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, va_list pArgList)
+{
+    char szBuffer[4096] = {0};
+    vsprintf_s(szBuffer, sizeof (szBuffer), pszFile, pArgList);
+    return crDmpHtmlInit(pDumper, pszDir, szBuffer);
+}
+
+DECLEXPORT(int) crDmpHtmlInitF(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, ...)
+{
+    int rc;
+    va_list pArgList;
+    va_start(pArgList, pszFile);
+    rc = crDmpHtmlInitV(pDumper, pszDir, pszFile, pArgList);
+    va_end(pArgList);
+    return rc;
+}
+
 #endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
index db2cafe..7103ed4 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
@@ -128,8 +128,6 @@ print """
 #endif
 """
 
-from get_components import *;
-
 texenv_mappings = {
     'GL_TEXTURE_ENV' : [
         'GL_TEXTURE_ENV_MODE',
@@ -194,7 +192,7 @@ void crRecDumpTexParam(CR_RECORDER *pRec, CRContext *ctx, GLenum enmTarget)
     crDmpStrF(pRec->pDumper, "==TEX_PARAM for target(0x%x)==", enmTarget);
 """
 for pname in texparam_names:
-    print "\tcComponents = lookupComponents(%s);" % pname
+    print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
     print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
     print "\tmemset(afBuf, 0, sizeof (afBuf));"
     print "\tpRec->pDispatch->GetTexParameterfv(enmTarget, %s, afBuf);" % pname
@@ -221,7 +219,7 @@ for target in keys:
     print "\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % target
     values = texenv_mappings[target]
     for pname in values:
-        print "\tcComponents = lookupComponents(%s);" % pname
+        print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
         print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
         print "\tmemset(afBuf, 0, sizeof (afBuf));"
         print "\tpRec->pDispatch->GetTexEnvfv(%s, %s, afBuf);" % (target, pname)
@@ -246,7 +244,7 @@ void crRecDumpTexGen(CR_RECORDER *pRec, CRContext *ctx)
 for coord in texgen_coords:
     print "\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % coord
     for pname in texgen_names:
-        print "\tcComponents = lookupComponents(%s);" % pname
+        print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
         print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
         print "\tmemset(afBuf, 0, sizeof (afBuf));"
         print "\tpRec->pDispatch->GetTexGendv(%s, %s, afBuf);" % (coord, pname)
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
similarity index 97%
rename from src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py
rename to src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
index e1909d7..c9a3245 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
@@ -113,7 +113,7 @@ num_extended_components = {
 	'GL_COORD_REPLACE_ARB': (1, 'CR_ARB_point_sprite'),
 }
 
-print """static unsigned int lookupComponents( GLenum pname )
+print """unsigned int crStateHlpComponentsCount( GLenum pname )
 {
 	switch( pname )
 	{
@@ -133,7 +133,7 @@ for comp in comps:
 
 print """
 		default:
-			crError( "Unknown parameter name in lookupComponents: %d", (int) pname );
+			crError( "Unknown parameter name in crStateHlpComponentsCount: %d", (int) pname );
 			break;
 	}
 	/* NOTREACHED */
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
index 674eb6b..759c30d 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
@@ -233,3 +233,5 @@ for rettype in types:
 	print '\t\t\treturn;'
 	print '\t}'
 	print '}'
+
+from get_components import *
\ No newline at end of file
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
index 3814f40..48d5a7e 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
@@ -258,7 +258,7 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
     return parms.id;
 }
 
-DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( GLhandleARB obj )
+DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj )
 {
     GLuint hwId = crStateGetProgramHWID(obj);
     if (hwId)
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
index 22599b7..de40c08 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
@@ -200,3 +200,248 @@ void STATE_APIENTRY crStatePointParameteriv(GLenum pname, const GLint *params)
 	GLfloat f_param = (GLfloat) (*params);
 	crStatePointParameterfvARB( pname, &f_param );
 }
+
+void crStatePointDiff(CRPointBits *b, CRbitvalue *bitID,
+        CRContext *fromCtx, CRContext *toCtx)
+{
+    CRPointState *from = &(fromCtx->point);
+    CRPointState *to = &(toCtx->point);
+    unsigned int j, i;
+    CRbitvalue nbitID[CR_MAX_BITARRAY];
+    Assert(0);
+    for (j=0;j<CR_MAX_BITARRAY;j++)
+        nbitID[j] = ~bitID[j];
+    i = 0; /* silence compiler */
+    if (CHECKDIRTY(b->enableSmooth, bitID))
+    {
+        glAble able[2];
+        able[0] = diff_api.Disable;
+        able[1] = diff_api.Enable;
+        if (from->pointSmooth != to->pointSmooth)
+        {
+            able[to->pointSmooth](GL_POINT_SMOOTH);
+            from->pointSmooth = to->pointSmooth;
+        }
+        CLEARDIRTY(b->enableSmooth, nbitID);
+    }
+    if (CHECKDIRTY(b->size, bitID))
+    {
+        if (from->pointSize != to->pointSize)
+        {
+            diff_api.PointSize (to->pointSize);
+            from->pointSize = to->pointSize;
+        }
+        CLEARDIRTY(b->size, nbitID);
+    }
+    if (CHECKDIRTY(b->minSize, bitID))
+    {
+        if (from->minSize != to->minSize)
+        {
+            diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize);
+            from->minSize = to->minSize;
+        }
+        CLEARDIRTY(b->minSize, nbitID);
+    }
+    if (CHECKDIRTY(b->maxSize, bitID))
+    {
+        if (from->maxSize != to->maxSize)
+        {
+            diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize);
+            from->maxSize = to->maxSize;
+        }
+        CLEARDIRTY(b->maxSize, nbitID);
+    }
+    if (CHECKDIRTY(b->fadeThresholdSize, bitID))
+    {
+        if (from->fadeThresholdSize != to->fadeThresholdSize)
+        {
+            diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize);
+            from->fadeThresholdSize = to->fadeThresholdSize;
+        }
+        CLEARDIRTY(b->fadeThresholdSize, nbitID);
+    }
+    if (CHECKDIRTY(b->spriteCoordOrigin, bitID))
+    {
+        if (from->spriteCoordOrigin != to->spriteCoordOrigin)
+        {
+            diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin);
+            from->spriteCoordOrigin = to->spriteCoordOrigin;
+        }
+        CLEARDIRTY(b->spriteCoordOrigin, nbitID);
+    }
+    if (CHECKDIRTY(b->distanceAttenuation, bitID))
+    {
+        if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
+            diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
+            from->distanceAttenuation[0] = to->distanceAttenuation[0];
+            from->distanceAttenuation[1] = to->distanceAttenuation[1];
+            from->distanceAttenuation[2] = to->distanceAttenuation[2];
+        }
+        CLEARDIRTY(b->distanceAttenuation, nbitID);
+    }
+    if (CHECKDIRTY(b->enableSprite, bitID))
+    {
+        glAble able[2];
+        able[0] = diff_api.Disable;
+        able[1] = diff_api.Enable;
+        if (from->pointSprite != to->pointSprite)
+        {
+            able[to->pointSprite](GL_POINT_SPRITE_ARB);
+            from->pointSprite = to->pointSprite;
+        }
+        CLEARDIRTY(b->enableSprite, nbitID);
+    }
+    {
+        unsigned int activeUnit = (unsigned int) -1;
+        for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+            if (CHECKDIRTY(b->coordReplacement[i], bitID))
+            {
+                GLint replacement = to->coordReplacement[i];
+                if (activeUnit != i) {
+                     diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+                     activeUnit = i;
+                }
+                diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
+                from->coordReplacement[i] = to->coordReplacement[i];
+                CLEARDIRTY(b->coordReplacement[i], nbitID);
+            }
+        }
+        if (activeUnit != toCtx->texture.curTextureUnit)
+           diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+    }
+    CLEARDIRTY(b->dirty, nbitID);
+}
+
+void crStatePointSwitch(CRPointBits *b, CRbitvalue *bitID,
+        CRContext *fromCtx, CRContext *toCtx)
+{
+    CRPointState *from = &(fromCtx->point);
+    CRPointState *to = &(toCtx->point);
+    unsigned int j, i;
+    GLboolean fEnabled;
+    CRbitvalue nbitID[CR_MAX_BITARRAY];
+    for (j=0;j<CR_MAX_BITARRAY;j++)
+        nbitID[j] = ~bitID[j];
+    i = 0; /* silence compiler */
+    if (CHECKDIRTY(b->enableSmooth, bitID))
+    {
+        glAble able[2];
+        able[0] = diff_api.Disable;
+        able[1] = diff_api.Enable;
+        if (from->pointSmooth != to->pointSmooth)
+        {
+            able[to->pointSmooth](GL_POINT_SMOOTH);
+            FILLDIRTY(b->enableSmooth);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->enableSmooth, nbitID);
+    }
+    if (CHECKDIRTY(b->size, bitID))
+    {
+        if (from->pointSize != to->pointSize)
+        {
+            diff_api.PointSize (to->pointSize);
+            FILLDIRTY(b->size);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->size, nbitID);
+    }
+    if (CHECKDIRTY(b->minSize, bitID))
+    {
+        if (from->minSize != to->minSize)
+        {
+            diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize);
+            FILLDIRTY(b->minSize);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->minSize, nbitID);
+    }
+    if (CHECKDIRTY(b->maxSize, bitID))
+    {
+        if (from->maxSize != to->maxSize)
+        {
+            diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize);
+            FILLDIRTY(b->maxSize);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->maxSize, nbitID);
+    }
+    if (CHECKDIRTY(b->fadeThresholdSize, bitID))
+    {
+        if (from->fadeThresholdSize != to->fadeThresholdSize)
+        {
+            diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize);
+            FILLDIRTY(b->fadeThresholdSize);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->fadeThresholdSize, nbitID);
+    }
+    if (CHECKDIRTY(b->spriteCoordOrigin, bitID))
+    {
+        if (from->spriteCoordOrigin != to->spriteCoordOrigin)
+        {
+            diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin);
+            FILLDIRTY(b->spriteCoordOrigin);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->spriteCoordOrigin, nbitID);
+    }
+    if (CHECKDIRTY(b->distanceAttenuation, bitID))
+    {
+        if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
+            diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
+            FILLDIRTY(b->distanceAttenuation);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->distanceAttenuation, nbitID);
+    }
+    fEnabled = from->pointSprite;
+    {
+        unsigned int activeUnit = (unsigned int) -1;
+        for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+            if (CHECKDIRTY(b->coordReplacement[i], bitID))
+            {
+                if (!fEnabled)
+                {
+                    diff_api.Enable(GL_POINT_SPRITE_ARB);
+                    fEnabled = GL_TRUE;
+                }
+#if 0
+                /*don't set coord replacement, it will be set just before drawing points when necessary,
+                 * to work around gpu driver bugs
+                 * See crServerDispatch[Begin|End|Draw*] */
+                GLint replacement = to->coordReplacement[i];
+                if (activeUnit != i) {
+                     diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+                     activeUnit = i;
+                }
+                diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
+#endif
+                CLEARDIRTY(b->coordReplacement[i], nbitID);
+            }
+        }
+        if (activeUnit != toCtx->texture.curTextureUnit)
+           diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+    }
+    if (CHECKDIRTY(b->enableSprite, bitID))
+    {
+        glAble able[2];
+        able[0] = diff_api.Disable;
+        able[1] = diff_api.Enable;
+        if (fEnabled != to->pointSprite)
+        {
+            able[to->pointSprite](GL_POINT_SPRITE_ARB);
+            FILLDIRTY(b->enableSprite);
+            FILLDIRTY(b->dirty);
+        }
+        CLEARDIRTY(b->enableSprite, nbitID);
+    }
+    else if (fEnabled != to->pointSprite)
+    {
+        glAble able[2];
+        able[0] = diff_api.Disable;
+        able[1] = diff_api.Enable;
+        able[to->pointSprite](GL_POINT_SPRITE_ARB);
+    }
+    CLEARDIRTY(b->dirty, nbitID);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
index e30d104..6b2a5ba 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
@@ -1426,7 +1426,7 @@ static int32_t crStateSaveKeys(CRHashTable *pHash, PSSMHANDLE pSSM)
     return VINF_SUCCESS;
 }
 
-static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM)
+static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM, uint32_t u32Version)
 {
     uint32_t u32Key, u32Count, i;
     int rc;
@@ -1443,10 +1443,15 @@ static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM)
 
         CRASSERT(u32Count);
 
-        for (i = u32Key; i < u32Count + u32Key; ++i)
+        if (u32Version > SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS)
         {
-            GLboolean fIsNew = crHashtableAllocRegisterKey(pHash, i);
-            CRASSERT(fIsNew);
+            for (i = u32Key; i < u32Count + u32Key; ++i)
+            {
+                GLboolean fIsNew = crHashtableAllocRegisterKey(pHash, i);
+#if 0 //def DEBUG_misha
+                CRASSERT(fIsNew);
+#endif
+            }
         }
     }
 
@@ -2231,7 +2236,7 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
 
         if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
         {
-            rc = crStateLoadKeys(pContext->shared->buffersTable, pSSM);
+            rc = crStateLoadKeys(pContext->shared->buffersTable, pSSM, u32Version);
             AssertRCReturn(rc, rc);
         }
 
@@ -2341,7 +2346,7 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
     {
         if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
         {
-            rc = crStateLoadKeys(pContext->shared->textureTable, pSSM);
+            rc = crStateLoadKeys(pContext->shared->textureTable, pSSM, u32Version);
             AssertRCReturn(rc, rc);
         }
     }
@@ -2470,7 +2475,7 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
     {
         if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
         {
-            rc = crStateLoadKeys(pContext->shared->fbTable, pSSM);
+            rc = crStateLoadKeys(pContext->shared->fbTable, pSSM, u32Version);
             AssertRCReturn(rc, rc);
         }
 
@@ -2495,7 +2500,7 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
 
         if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
         {
-            rc = crStateLoadKeys(pContext->shared->rbTable, pSSM);
+            rc = crStateLoadKeys(pContext->shared->rbTable, pSSM, u32Version);
             AssertRCReturn(rc, rc);
         }
 
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
index 03fe069..5da2739 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
@@ -3259,10 +3259,28 @@ void STATE_APIENTRY
 crStatePrioritizeTextures(GLsizei n, const GLuint *textures,
                                                     const GLclampf *priorities) 
 {
-    UNUSED(n);
-    UNUSED(textures);
+    CRContext *g = GetCurrentContext();
+    CRTextureObj *tobj;
+    GLsizei i;
     UNUSED(priorities);
-    /* TODO: */
+
+    for (i = 0; i < n; ++i)
+    {
+        GLuint tex = textures[i];
+        GET_TOBJ(tobj, g, tex);
+        if (!tobj)
+        {
+            Assert(crHashtableIsKeyUsed(g->shared->textureTable, tex));
+            tobj = crStateTextureAllocate_t(g, tex);
+        }
+
+        /* so far the code just ensures the tex object is created to make
+         * the crserverlib code be able to pass it to host ogl */
+
+        /* TODO: store texture priorities in the state data to be able to restore it properly
+         * on save state load */
+    }
+
     return;
 }
 
diff --git a/src/VBox/GuestHost/OpenGL/util/blitter.cpp b/src/VBox/GuestHost/OpenGL/util/blitter.cpp
index 94ebaff..8dcf1cb 100644
--- a/src/VBox/GuestHost/OpenGL/util/blitter.cpp
+++ b/src/VBox/GuestHost/OpenGL/util/blitter.cpp
@@ -1,1135 +1,1751 @@
-/* $Id$ */
-
-/** @file
- * Blitter API implementation
- */
-/*
- * Copyright (C) 2013 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-#include "cr_blitter.h"
-#include "cr_spu.h"
-#include "chromium.h"
-#include "cr_error.h"
-#include "cr_net.h"
-#include "cr_rand.h"
-#include "cr_mem.h"
-#include "cr_string.h"
-
-#include <iprt/cdefs.h>
-#include <iprt/types.h>
-#include <iprt/mem.h>
-
-/* @param pCtxBase      - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
- * @param fCreateNewCtx - if true  - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
- *                                   its id field is used to specified the shared context id to be used for blitter context.
- *                                   The id can be null to specify no shared context is needed
- *                        if false - if pCtxBase is NOT null AND its id field is NOT null -
- *                                     specified the blitter context to be used
- *                                     blitter treats it as if it has default ogl state.
- *                                   otherwise -
- *                                     the blitter works in a "no-context" mode, i.e. a caller is responsible
- *                                     to making a proper context current before calling the blitter.
- *                                     Note that BltEnter/Leave MUST still be called, but the proper context
- *                                     must be set before doing BltEnter, and ResoreContext info is ignored in that case.
- *                                     Also note that blitter caches the current window info, and assumes the current context's values are preserved
- *                                     wrt that window before the calls, so if one uses different contexts for one blitter,
- *                                     the blitter current window values must be explicitly reset by doing CrBltMuralSetCurrent(pBlitter, NULL)
- * @param fForceDrawBlt - if true  - forces the blitter to always use glDrawXxx-based blits even if GL_EXT_framebuffer_blit.
- *                                   This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
- */
-VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch)
-{
-    if (pCtxBase && pCtxBase->Base.id < 0)
-    {
-        crWarning("Default share context not initialized!");
-        return VERR_INVALID_PARAMETER;
-    }
-
-    if (!pCtxBase && fCreateNewCtx)
-    {
-        crWarning("pCtxBase is zero while fCreateNewCtx is set!");
-        return VERR_INVALID_PARAMETER;
-    }
-
-    memset(pBlitter, 0, sizeof (*pBlitter));
-
-    pBlitter->pDispatch = pDispatch;
-    if (pCtxBase)
-        pBlitter->CtxInfo = *pCtxBase;
-
-    pBlitter->Flags.ForceDrawBlit = fForceDrawBlt;
-
-    if (fCreateNewCtx)
-    {
-        pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
-        if (!pBlitter->CtxInfo.Base.id)
-        {
-            memset(pBlitter, 0, sizeof (*pBlitter));
-            crWarning("CreateContext failed!");
-            return VERR_GENERAL_FAILURE;
-        }
-        pBlitter->Flags.CtxCreated = 1;
-    }
-
-    if (pShaders)
-    {
-        pBlitter->pGlslCache = pShaders;
-        pBlitter->Flags.ShadersGloal = 1;
-    }
-    else
-    {
-        CrGlslInit(&pBlitter->LocalGlslCache, pDispatch);
-        pBlitter->pGlslCache = &pBlitter->LocalGlslCache;
-    }
-
-    return VINF_SUCCESS;
-}
-
-VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
-{
-    if (CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltBlitTexTex: blitter is entered");
-        return VERR_INVALID_STATE;
-    }
-
-    if (pBlitter->Flags.ShadersGloal || !CrGlslNeedsCleanup(&pBlitter->LocalGlslCache))
-        return VINF_SUCCESS;
-
-    int rc = CrBltEnter(pBlitter, pRestoreCtxInfo, pRestoreMural);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrBltEnter failed, rc %d", rc);
-        return rc;
-    }
-
-    CrGlslCleanup(&pBlitter->LocalGlslCache);
-
-    CrBltLeave(pBlitter);
-
-    return VINF_SUCCESS;
-}
-
-void CrBltTerm(PCR_BLITTER pBlitter)
-{
-    if (pBlitter->Flags.CtxCreated)
-        pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
-    memset(pBlitter, 0, sizeof (*pBlitter));
-}
-
-int CrBltMuralSetCurrent(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
-{
-    if (pMural)
-    {
-        if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
-            return VINF_SUCCESS;
-        memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
-    }
-    else
-    {
-        if (CrBltIsEntered(pBlitter))
-        {
-            crWarning("can not set null mural for entered bleater");
-            return VERR_INVALID_STATE;
-        }
-        if (!pBlitter->CurrentMural.Base.id)
-            return VINF_SUCCESS;
-        pBlitter->CurrentMural.Base.id = 0;
-    }
-
-    pBlitter->Flags.CurrentMuralChanged = 1;
-
-    if (!CrBltIsEntered(pBlitter))
-        return VINF_SUCCESS;
-    else if (!pBlitter->CtxInfo.Base.id)
-    {
-        crWarning("setting current mural for entered no-context blitter");
-        return VERR_INVALID_STATE;
-    }
-
-    crWarning("changing mural for entered blitter, is is somewhat expected?");
-
-    pBlitter->pDispatch->Flush();
-
-    pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
-
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) crBltBlitTexBufImplFbo(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
-{
-    GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
-    pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
-    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
-    pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
-
-    for (uint32_t i = 0; i < cRects; ++i)
-    {
-        const RTRECT * pSrcRect = &paSrcRect[i];
-        const RTRECT * pDstRect = &paDstRect[i];
-        int32_t srcY1;
-        int32_t srcY2;
-        int32_t dstY1;
-        int32_t dstY2;
-        int32_t srcX1 = pSrcRect->xLeft;
-        int32_t srcX2 = pSrcRect->xRight;
-        int32_t dstX1 = pDstRect->xLeft;
-        int32_t dstX2 = pDstRect->xRight;
-
-        if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
-        {
-            srcY1 = pSrc->height - pSrcRect->yTop;
-            srcY2 = pSrc->height - pSrcRect->yBottom;
-        }
-        else
-        {
-            srcY1 = pSrcRect->yTop;
-            srcY2 = pSrcRect->yBottom;
-        }
-
-        if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
-        {
-            dstY1 = pDstSize->cy - pDstRect->yTop;
-            dstY2 = pDstSize->cy - pDstRect->yBottom;
-        }
-        else
-        {
-            dstY1 = pDstRect->yTop;
-            dstY2 = pDstRect->yBottom;
-        }
-
-        if (srcY1 > srcY2)
-        {
-            if (dstY1 > dstY2)
-            {
-                /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
-                int32_t tmp = srcY1;
-                srcY1 = srcY2;
-                srcY2 = tmp;
-                tmp = dstY1;
-                dstY1 = dstY2;
-                dstY2 = tmp;
-            }
-        }
-
-        if (srcX1 > srcX2)
-        {
-            if (dstX1 > dstX2)
-            {
-                /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
-                int32_t tmp = srcX1;
-                srcX1 = srcX2;
-                srcX2 = tmp;
-                tmp = dstX1;
-                dstX1 = dstX2;
-                dstX2 = tmp;
-            }
-        }
-
-        pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
-                    dstX1, dstY1, dstX2, dstY2,
-                    GL_COLOR_BUFFER_BIT, filter);
-    }
-
-    return VINF_SUCCESS;
-}
-
-/* GL_TRIANGLE_FAN */
-DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
-{
-    /* going ccw:
-     * 1. (left;top)        4. (right;top)
-     *        |                    ^
-     *        >                    |
-     * 2. (left;bottom)  -> 3. (right;bottom) */
-    /* xLeft yTop */
-    pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
-    pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
-
-    /* xLeft yBottom */
-    pBuff[2] = pBuff[0];
-    pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
-
-    /* xRight yBottom */
-    pBuff[4] = ((float)pRect->xRight)/((float)normalX);
-    pBuff[5] = pBuff[3];
-
-    /* xRight yTop */
-    pBuff[6] = pBuff[4];
-    pBuff[7] = pBuff[1];
-    return &pBuff[8];
-}
-
-DECLINLINE(GLfloat*) crBltVtRectsTFNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
-{
-    for (uint32_t i = 0; i < cRects; ++i)
-    {
-        pBuff = crBltVtRectTFNormalized(&paRects[i], normalX, normalY, pBuff, height);
-    }
-    return pBuff;
-}
-
-DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
-{
-    /* xLeft yTop */
-    pBuff[0] = pRect->xLeft;
-    pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
-
-    /* xLeft yBottom */
-    pBuff[2] = pBuff[0];
-    pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
-
-    /* xRight yBottom */
-    pBuff[4] = pRect->xRight;
-    pBuff[5] = pBuff[3];
-
-    /* xRight yTop */
-    pBuff[6] = pBuff[4];
-    pBuff[7] = pBuff[1];
-    return &pBuff[8];
-}
-
-DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
-{
-    GLubyte iBase = *piBase;
-    /* triangle 1 */
-    pIndex[0] = iBase;
-    pIndex[1] = iBase + 1;
-    pIndex[2] = iBase + 2;
-
-    /* triangle 2 */
-    pIndex[3] = iBase;
-    pIndex[4] = iBase + 2;
-    pIndex[5] = iBase + 3;
-    *piBase = iBase + 4;
-    return pIndex + 6;
-}
-
-/* Indexed GL_TRIANGLES */
-DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
-{
-    GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
-    return ret;
-}
-
-DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
-{
-    GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
-
-    if (ppIndex)
-        *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
-
-    return ret;
-}
-
-DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
-{
-    return cRects * 4;
-}
-
-#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
-
-DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
-{
-    return 6 * cRects;
-}
-
-
-static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
-{
-    uint32_t i;
-    for (i = 0; i < cRects; ++i)
-    {
-        pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
-    }
-
-
-    if (ppIndex)
-    {
-        GLubyte *pIndex = (GLubyte*)pBuff;
-        *ppIndex = pIndex;
-        for (i = 0; i < cRects; ++i)
-        {
-            pIndex = crBltVtFillRectIndicies(pIndex, piBase);
-        }
-        pBuff = (GLfloat*)pIndex;
-    }
-
-    return pBuff;
-}
-
-static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
-{
-    if (pBuffer->cbBuffer < cbBuffer)
-    {
-        if (pBuffer->pvBuffer)
-        {
-            RTMemFree(pBuffer->pvBuffer);
-        }
-
-#ifndef DEBUG_misha
-        /* debugging: ensure we calculate proper buffer size */
-        cbBuffer += 16;
-#endif
-
-        pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
-        if (pBuffer->pvBuffer)
-            pBuffer->cbBuffer = cbBuffer;
-        else
-        {
-            crWarning("failed to allocate buffer of size %d", cbBuffer);
-            pBuffer->cbBuffer = 0;
-        }
-    }
-    return pBuffer->pvBuffer;
-}
-
-static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
-{
-    bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
-    if (pBlitter->CurrentSetSize.cx != pDstSize->cx
-            || pBlitter->CurrentSetSize.cy != pDstSize->cy)
-    {
-        pBlitter->CurrentSetSize = *pDstSize;
-        pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
-        pBlitter->pDispatch->LoadIdentity();
-        pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
-        fUpdateViewport = true;
-    }
-
-    if (fUpdateViewport)
-    {
-        pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
-        pBlitter->Flags.CurrentMuralChanged = 0;
-    }
-
-    pBlitter->Flags.LastWasFBODraw = fFBODraw;
-}
-
-static DECLCALLBACK(int) crBltBlitTexBufImplDraw2D(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
-{
-    GLuint normalX, normalY;
-    uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
-    uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
-
-    switch (pSrc->target)
-    {
-        case GL_TEXTURE_2D:
-        {
-            normalX = pSrc->width;
-            normalY = pSrc->height;
-            break;
-        }
-
-        case GL_TEXTURE_RECTANGLE_ARB:
-        {
-            normalX = 1;
-            normalY = 1;
-            break;
-        }
-
-        default:
-        {
-            crWarning("Unsupported texture target 0x%x", pSrc->target);
-            return VERR_INVALID_PARAMETER;
-        }
-    }
-
-    Assert(pSrc->hwid);
-
-    pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
-
-    if (cRects == 1)
-    {
-        /* just optimization to draw a single rect with GL_TRIANGLE_FAN */
-        GLfloat *pVerticies;
-        GLfloat *pTexCoords;
-        GLuint cElements = crBltVtGetNumVerticiesTF(cRects);
-
-        pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
-        pTexCoords = crBltVtRectsTFNormalized(paDstRect, cRects, 1, 1, pVerticies, dstHeight);
-        crBltVtRectsTFNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, srcHeight);
-
-        pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
-        pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
-
-        pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
-        pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
-
-        pBlitter->pDispatch->Enable(pSrc->target);
-
-        pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
-
-        pBlitter->pDispatch->Disable(pSrc->target);
-
-        pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
-        pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
-    }
-    else
-    {
-        GLfloat *pVerticies;
-        GLfloat *pTexCoords;
-        GLubyte *pIndicies;
-        GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
-        GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
-        GLubyte iIdxBase = 0;
-
-        pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
-        pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
-        crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
-
-        pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
-        pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
-
-        pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
-        pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
-
-        pBlitter->pDispatch->Enable(pSrc->target);
-
-        pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
-
-        pBlitter->pDispatch->Disable(pSrc->target);
-
-        pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
-        pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
-    }
-
-    pBlitter->pDispatch->BindTexture(pSrc->target, 0);
-
-    return VINF_SUCCESS;
-}
-
-static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
-{
-    const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
-    if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
-    {
-        pBlitter->Flags.SupportsFBO = 1;
-        pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
-        Assert(pBlitter->idFBO);
-    }
-    else
-        crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
-
-    /* BlitFramebuffer seems to be buggy on Intel, 
-     * try always glDrawXxx for now */
-    if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
-    {
-        pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
-    }
-    else
-    {
-//        crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
-        pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
-    }
-
-    /* defaults. but just in case */
-    pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
-    pBlitter->pDispatch->LoadIdentity();
-    pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
-    pBlitter->pDispatch->LoadIdentity();
-
-    return VINF_SUCCESS;
-}
-
-void CrBltLeave(PCR_BLITTER pBlitter)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltLeave: blitter not entered");
-        return;
-    }
-
-    if (pBlitter->Flags.SupportsFBO)
-    {
-        pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
-        pBlitter->pDispatch->DrawBuffer(GL_BACK);
-        pBlitter->pDispatch->ReadBuffer(GL_BACK);
-    }
-
-    pBlitter->pDispatch->Flush();
-
-    if (pBlitter->CtxInfo.Base.id)
-    {
-        if (pBlitter->pRestoreCtxInfo != &pBlitter->CtxInfo)
-        {
-            pBlitter->pDispatch->MakeCurrent(pBlitter->pRestoreMural->Base.id, 0, pBlitter->pRestoreCtxInfo->Base.id);
-        }
-        else
-        {
-            pBlitter->pDispatch->MakeCurrent(0, 0, 0);
-        }
-    }
-
-    pBlitter->pRestoreCtxInfo = NULL;
-}
-
-int CrBltEnter(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
-{
-    if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
-    {
-        crWarning("current mural not initialized!");
-        return VERR_INVALID_STATE;
-    }
-
-    if (CrBltIsEntered(pBlitter))
-    {
-        crWarning("blitter is entered already!");
-        return VERR_INVALID_STATE;
-    }
-
-    if (pBlitter->CurrentMural.Base.id) /* <- pBlitter->CurrentMural.Base.id can be null if the blitter is in a "no-context" mode (see comments to BltInit for detail)*/
-    {
-        if (pRestoreCtxInfo)
-            pBlitter->pDispatch->Flush();
-        pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
-    }
-    else
-    {
-        if (pRestoreCtxInfo)
-        {
-            crWarning("pRestoreCtxInfo is not NULL for \"no-context\" blitter");
-            pRestoreCtxInfo = NULL;
-        }
-    }
-
-    if (pRestoreCtxInfo)
-    {
-        pBlitter->pRestoreCtxInfo = pRestoreCtxInfo;
-        pBlitter->pRestoreMural = pRestoreMural;
-    }
-    else
-    {
-        pBlitter->pRestoreCtxInfo = &pBlitter->CtxInfo;
-    }
-
-    if (pBlitter->Flags.Initialized)
-        return VINF_SUCCESS;
-
-    int rc = crBltInitOnMakeCurent(pBlitter);
-    if (RT_SUCCESS(rc))
-    {
-        pBlitter->Flags.Initialized = 1;
-        return VINF_SUCCESS;
-    }
-
-    crWarning("crBltInitOnMakeCurent failed, rc %d", rc);
-    CrBltLeave(pBlitter);
-    return rc;
-}
-
-static void crBltBlitTexBuf(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, GLenum enmDstBuff, const RTRECTSIZE *pDstSize, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
-{
-    pBlitter->pDispatch->DrawBuffer(enmDstBuff);
-
-    crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
-
-    if (!(fFlags & CRBLT_F_NOALPHA))
-        pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
-    else
-    {
-        int rc = pBlitter->Flags.ShadersGloal ?
-                CrGlslProgUseNoAlpha(pBlitter->pGlslCache, pSrc->target)
-                :
-                CrGlslProgUseGenNoAlpha(&pBlitter->LocalGlslCache, pSrc->target);
-
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("Failed to use no-alpha program rc %d!, falling back to default blit", rc);
-            pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
-            return;
-        }
-
-        /* since we use shaders, we need to use draw commands rather than framebuffer blits.
-         * force using draw-based blitting */
-        crBltBlitTexBufImplDraw2D(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
-
-        Assert(pBlitter->Flags.ShadersGloal || &pBlitter->LocalGlslCache == pBlitter->pGlslCache);
-
-        CrGlslProgClear(pBlitter->pGlslCache);
-    }
-}
-
-void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
-{
-    RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
-    crBltCheckSetupViewport(pBlitter, &DstSize, false);
-}
-
-void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltBlitTexMural: blitter not entered");
-        return;
-    }
-
-    RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
-
-    pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
-
-    crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
-}
-
-void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltBlitTexTex: blitter not entered");
-        return;
-    }
-
-    RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
-
-    pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
-
-    /* TODO: mag/min filters ? */
-
-    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
-
-//    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
-//    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
-
-    crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
-
-    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
-}
-
-void CrBltPresent(PCR_BLITTER pBlitter)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltPresent: blitter not entered");
-        return;
-    }
-
-    if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
-        pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
-    else
-        pBlitter->pDispatch->Flush();
-}
-
-static int crBltImgCreateForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
-{
-    memset(pDst, 0, sizeof (*pDst));
-    if (enmFormat != GL_RGBA
-            && enmFormat != GL_BGRA)
-    {
-        crWarning("unsupported format 0x%x", enmFormat);
-        return VERR_NOT_IMPLEMENTED;
-    }
-
-    uint32_t bpp = 32;
-
-    uint32_t pitch = ((bpp * pSrc->width) + 7) >> 3;
-    uint32_t cbData = pitch * pSrc->height;
-    pDst->pvData = RTMemAllocZ(cbData);
-    if (!pDst->pvData)
-    {
-        crWarning("RTMemAlloc failed");
-        return VERR_NO_MEMORY;
-    }
-
-#ifdef DEBUG_misha
-    {
-        char *pTmp = (char*)pDst->pvData;
-        for (uint32_t i = 0; i < cbData; ++i)
-        {
-            pTmp[i] = (char)((1 << i) % 255);
-        }
-    }
-#endif
-
-    pDst->cbData = cbData;
-    pDst->enmFormat = enmFormat;
-    pDst->width = pSrc->width;
-    pDst->height = pSrc->height;
-    pDst->bpp = bpp;
-    pDst->pitch = pitch;
-    return VINF_SUCCESS;
-}
-
-VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltImgGetTex: blitter not entered");
-        return VERR_INVALID_STATE;
-    }
-
-    int rc = crBltImgCreateForTex(pSrc, pDst, enmFormat);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("crBltImgCreateForTex failed, rc %d", rc);
-        return rc;
-    }
-    pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
-
-#ifdef DEBUG_misha
-    {
-        GLint width = 0, height = 0, depth = 0;
-        pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_WIDTH, &width);
-        pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_HEIGHT, &height);
-        pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_DEPTH, &depth);
-
-        Assert(width == pSrc->width);
-        Assert(height == pSrc->height);
-//        Assert(depth == pSrc->depth);
-    }
-#endif
-
-    pBlitter->pDispatch->GetTexImage(pSrc->target, 0, enmFormat, GL_UNSIGNED_BYTE, pDst->pvData);
-
-    pBlitter->pDispatch->BindTexture(pSrc->target, 0);
-    return VINF_SUCCESS;
-}
-
-VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltImgGetMural: blitter not entered");
-        return VERR_INVALID_STATE;
-    }
-
-    crWarning("NOT IMPLEMENTED");
-    return VERR_NOT_IMPLEMENTED;
-}
-
-VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst)
-{
-    if (!CrBltIsEntered(pBlitter))
-    {
-        crWarning("CrBltImgFree: blitter not entered");
-        return;
-    }
-
-    if (pDst->pvData)
-    {
-        RTMemFree(pDst->pvData);
-        pDst->pvData = NULL;
-    }
-}
-
-
-VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache)
-{
-    if (pCache->iGlVersion == 0)
-    {
-        const char * pszStr = (const char*)pCache->pDispatch->GetString(GL_VERSION);
-        pCache->iGlVersion = crStrParseGlVersion(pszStr);
-        if (pCache->iGlVersion <= 0)
-        {
-            crWarning("crStrParseGlVersion returned %d", pCache->iGlVersion);
-            pCache->iGlVersion = -1;
-        }
-    }
-
-    if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
-        return true;
-
-    crWarning("GLSL unsuported, gl version %d", pCache->iGlVersion);
-
-    /* @todo: we could also check for GL_ARB_shader_objects and GL_ARB_fragment_shader,
-     * but seems like chromium does not support properly gl*Object versions of shader functions used with those extensions */
-    return false;
-}
-
-#define CR_GLSL_STR_V_120 "#version 120\n"
-#define CR_GLSL_STR_EXT_TR "#extension GL_ARB_texture_rectangle : enable\n"
-#define CR_GLSL_STR_2D "2D"
-#define CR_GLSL_STR_2DRECT "2DRect"
-
-#define CR_GLSL_PATTERN_FS_NOALPHA(_ver, _ext, _tex) \
-        _ver \
-        _ext \
-        "uniform sampler" _tex " sampler0;\n" \
-        "void main()\n" \
-        "{\n" \
-            "vec2 srcCoord = vec2(gl_TexCoord[0]);\n" \
-            "gl_FragData[0].xyz = (texture" _tex "(sampler0, srcCoord).xyz);\n" \
-            "gl_FragData[0].w = 1.0;\n" \
-        "}\n"
-
-static const char* crGlslGetFsStringNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
-{
-    if (!CrGlslIsSupported(pCache))
-    {
-        crWarning("CrGlslIsSupported is false");
-        return NULL;
-    }
-
-    if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 1, 0))
-    {
-        if (enmTexTarget == GL_TEXTURE_2D)
-            return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, "", CR_GLSL_STR_2D);
-        else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
-            return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
-
-        crWarning("invalid enmTexTarget %#x", enmTexTarget);
-        return NULL;
-    }
-    else if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
-    {
-        if (enmTexTarget == GL_TEXTURE_2D)
-            return CR_GLSL_PATTERN_FS_NOALPHA("", "", CR_GLSL_STR_2D);
-        else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
-            return CR_GLSL_PATTERN_FS_NOALPHA("", CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
-
-        crWarning("invalid enmTexTarget %#x", enmTexTarget);
-        return NULL;
-    }
-
-    crError("crGlslGetFsStringNoAlpha: we should not be here!");
-    return NULL;
-}
-
-static int crGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget, GLuint *puiProgram)
-{
-    *puiProgram = 0;
-
-    const char*pStrFsShader = crGlslGetFsStringNoAlpha(pCache, enmTexTarget);
-    if (!pStrFsShader)
-    {
-        crWarning("crGlslGetFsStringNoAlpha failed");
-        return VERR_NOT_SUPPORTED;
-    }
-
-    int rc = VINF_SUCCESS;
-    GLchar * pBuf = NULL;
-    GLuint uiProgram = 0;
-    GLint iUniform = -1;
-    GLuint uiShader = pCache->pDispatch->CreateShader(GL_FRAGMENT_SHADER);
-    if (!uiShader)
-    {
-        crWarning("CreateShader failed");
-        return VERR_NOT_SUPPORTED;
-    }
-
-    pCache->pDispatch->ShaderSource(uiShader, 1, &pStrFsShader, NULL);
-
-    pCache->pDispatch->CompileShader(uiShader);
-
-    GLint compiled = 0;
-    pCache->pDispatch->GetShaderiv(uiShader, GL_COMPILE_STATUS, &compiled);
-
-#ifndef DEBUG_misha
-    if(!compiled)
-#endif
-    {
-        if (!pBuf)
-            pBuf = (GLchar *)RTMemAlloc(16300);
-        pCache->pDispatch->GetShaderInfoLog(uiShader, 16300, NULL, pBuf);
-#ifdef DEBUG_misha
-        if (compiled)
-            crDebug("compile success:\n-------------------\n%s\n--------\n", pBuf);
-        else
-#endif
-        {
-            crWarning("compile FAILURE:\n-------------------\n%s\n--------\n", pBuf);
-            rc = VERR_NOT_SUPPORTED;
-            goto end;
-        }
-    }
-
-    Assert(compiled);
-
-    uiProgram = pCache->pDispatch->CreateProgram();
-    if (!uiProgram)
-    {
-        rc = VERR_NOT_SUPPORTED;
-        goto end;
-    }
-
-    pCache->pDispatch->AttachShader(uiProgram, uiShader);
-
-    pCache->pDispatch->LinkProgram(uiProgram);
-
-    GLint linked;
-    pCache->pDispatch->GetProgramiv(uiProgram, GL_LINK_STATUS, &linked);
-#ifndef DEBUG_misha
-    if(!linked)
-#endif
-    {
-        if (!pBuf)
-            pBuf = (GLchar *)RTMemAlloc(16300);
-        pCache->pDispatch->GetProgramInfoLog(uiProgram, 16300, NULL, pBuf);
-#ifdef DEBUG_misha
-        if (linked)
-            crDebug("link success:\n-------------------\n%s\n--------\n", pBuf);
-        else
-#endif
-        {
-            crWarning("link FAILURE:\n-------------------\n%s\n--------\n", pBuf);
-            rc = VERR_NOT_SUPPORTED;
-            goto end;
-        }
-    }
-
-    Assert(linked);
-
-    iUniform = pCache->pDispatch->GetUniformLocation(uiProgram, "sampler0");
-    if (iUniform == -1)
-    {
-        crWarning("GetUniformLocation failed for sampler0");
-    }
-    else
-    {
-        pCache->pDispatch->Uniform1i(iUniform, 0);
-    }
-
-    *puiProgram = uiProgram;
-
-    /* avoid end finalizer from cleaning it */
-    uiProgram = 0;
-
-    end:
-    if (uiShader)
-        pCache->pDispatch->DeleteShader(uiShader);
-    if (uiProgram)
-        pCache->pDispatch->DeleteProgram(uiProgram);
-    if (pBuf)
-        RTMemFree(pBuf);
-    return rc;
-}
-
-DECLINLINE(GLuint) crGlslProgGetNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
-{
-    switch (enmTexTarget)
-    {
-        case GL_TEXTURE_2D:
-            return  pCache->uNoAlpha2DProg;
-        case GL_TEXTURE_RECTANGLE_ARB:
-            return pCache->uNoAlpha2DRectProg;
-        default:
-            crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
-            return 0;
-    }
-}
-
-DECLINLINE(GLuint*) crGlslProgGetNoAlphaPtr(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
-{
-    switch (enmTexTarget)
-    {
-        case GL_TEXTURE_2D:
-            return  &pCache->uNoAlpha2DProg;
-        case GL_TEXTURE_RECTANGLE_ARB:
-            return &pCache->uNoAlpha2DRectProg;
-        default:
-            crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
-            return NULL;
-    }
-}
-
-VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
-{
-    GLuint*puiProgram = crGlslProgGetNoAlphaPtr(pCache, enmTexTarget);
-    if (!puiProgram)
-        return VERR_INVALID_PARAMETER;
-
-    if (*puiProgram)
-        return VINF_SUCCESS;
-
-    return crGlslProgGenNoAlpha(pCache, enmTexTarget, puiProgram);
-}
-
-VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache)
-{
-    int rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_2D);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_2D failed rc %d", rc);
-        return rc;
-    }
-
-    rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_RECTANGLE_ARB);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_RECTANGLE failed rc %d", rc);
-        return rc;
-    }
-
-    return VINF_SUCCESS;
-}
-
-VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache)
-{
-    pCache->pDispatch->UseProgram(0);
-}
-
-VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
-{
-    GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
-    if (!uiProg)
-    {
-        crWarning("request to use inexistent program!");
-        return VERR_INVALID_STATE;
-    }
-
-    Assert(uiProg);
-
-    pCache->pDispatch->UseProgram(uiProg);
-
-    return VINF_SUCCESS;
-}
-
-VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
-{
-    GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
-    if (!uiProg)
-    {
-        int rc = CrGlslProgGenNoAlpha(pCache, enmTexTarget);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("CrGlslProgGenNoAlpha failed, rc %d", rc);
-            return rc;
-        }
-
-        uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
-        CRASSERT(uiProg);
-    }
-
-    Assert(uiProg);
-
-    pCache->pDispatch->UseProgram(uiProg);
-
-    return VINF_SUCCESS;
-}
-
-VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache)
-{
-    return pCache->uNoAlpha2DProg || pCache->uNoAlpha2DRectProg;
-}
-
-VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache)
-{
-    if (pCache->uNoAlpha2DProg)
-    {
-        pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DProg);
-        pCache->uNoAlpha2DProg = 0;
-    }
-
-    if (pCache->uNoAlpha2DRectProg)
-    {
-        pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DRectProg);
-        pCache->uNoAlpha2DRectProg = 0;
-    }
-}
-
-VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache)
-{
-    CRASSERT(!CrGlslNeedsCleanup(pCache));
-
-    CrGlslCleanup(pCache);
-
-    /* sanity */
-    memset(pCache, 0, sizeof (*pCache));
-}
+/* $Id$ */
+
+/** @file
+ * Blitter API implementation
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "cr_blitter.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+
+/* @param pCtxBase      - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
+ * @param fCreateNewCtx - if true  - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
+ *                                   its id field is used to specified the shared context id to be used for blitter context.
+ *                                   The id can be null to specify no shared context is needed
+ *                        if false - if pCtxBase is NOT null AND its id field is NOT null -
+ *                                     specified the blitter context to be used
+ *                                     blitter treats it as if it has default ogl state.
+ *                                   otherwise -
+ *                                     the blitter works in a "no-context" mode, i.e. a caller is responsible
+ *                                     to making a proper context current before calling the blitter.
+ *                                     Note that BltEnter/Leave MUST still be called, but the proper context
+ *                                     must be set before doing BltEnter, and ResoreContext info is ignored in that case.
+ *                                     Also note that blitter caches the current window info, and assumes the current context's values are preserved
+ *                                     wrt that window before the calls, so if one uses different contexts for one blitter,
+ *                                     the blitter current window values must be explicitly reset by doing CrBltMuralSetCurrentInfo(pBlitter, NULL)
+ * @param fForceDrawBlt - if true  - forces the blitter to always use glDrawXxx-based blits even if GL_EXT_framebuffer_blit.
+ *                                   This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
+ */
+VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch)
+{
+    if (pCtxBase && pCtxBase->Base.id < 0)
+    {
+        crWarning("Default share context not initialized!");
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (!pCtxBase && fCreateNewCtx)
+    {
+        crWarning("pCtxBase is zero while fCreateNewCtx is set!");
+        return VERR_INVALID_PARAMETER;
+    }
+
+    memset(pBlitter, 0, sizeof (*pBlitter));
+
+    pBlitter->pDispatch = pDispatch;
+    if (pCtxBase)
+        pBlitter->CtxInfo = *pCtxBase;
+
+    pBlitter->Flags.ForceDrawBlit = fForceDrawBlt;
+
+    if (fCreateNewCtx)
+    {
+        pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
+        if (!pBlitter->CtxInfo.Base.id)
+        {
+            memset(pBlitter, 0, sizeof (*pBlitter));
+            crWarning("CreateContext failed!");
+            return VERR_GENERAL_FAILURE;
+        }
+        pBlitter->Flags.CtxCreated = 1;
+    }
+
+    if (pShaders)
+    {
+        pBlitter->pGlslCache = pShaders;
+        pBlitter->Flags.ShadersGloal = 1;
+    }
+    else
+    {
+        CrGlslInit(&pBlitter->LocalGlslCache, pDispatch);
+        pBlitter->pGlslCache = &pBlitter->LocalGlslCache;
+    }
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter)
+{
+    if (CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltBlitTexTex: blitter is entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    if (pBlitter->Flags.ShadersGloal || !CrGlslNeedsCleanup(&pBlitter->LocalGlslCache))
+        return VINF_SUCCESS;
+
+    int rc = CrBltEnter(pBlitter);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrBltEnter failed, rc %d", rc));
+        return rc;
+    }
+
+    CrGlslCleanup(&pBlitter->LocalGlslCache);
+
+    CrBltLeave(pBlitter);
+
+    return VINF_SUCCESS;
+}
+
+void CrBltTerm(PCR_BLITTER pBlitter)
+{
+    if (pBlitter->Flags.CtxCreated)
+        pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
+    memset(pBlitter, 0, sizeof (*pBlitter));
+}
+
+int CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
+{
+    if (pMural)
+    {
+        if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
+            return VINF_SUCCESS;
+        memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
+    }
+    else
+    {
+        if (CrBltIsEntered(pBlitter))
+        {
+            WARN(("can not set null mural for entered bleater"));
+            return VERR_INVALID_STATE;
+        }
+        if (!pBlitter->CurrentMural.Base.id)
+            return VINF_SUCCESS;
+        pBlitter->CurrentMural.Base.id = 0;
+    }
+
+    pBlitter->Flags.CurrentMuralChanged = 1;
+
+    if (!CrBltIsEntered(pBlitter))
+        return VINF_SUCCESS;
+    else if (!pBlitter->CtxInfo.Base.id)
+    {
+        WARN(("setting current mural for entered no-context blitter"));
+        return VERR_INVALID_STATE;
+    }
+
+    WARN(("changing mural for entered blitter, is is somewhat expected?"));
+
+    pBlitter->pDispatch->Flush();
+
+    pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
+
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) crBltBlitTexBufImplFbo(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
+{
+    GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
+    pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
+    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
+    pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
+
+    for (uint32_t i = 0; i < cRects; ++i)
+    {
+        const RTRECT * pSrcRect = &paSrcRect[i];
+        const RTRECT * pDstRect = &paDstRect[i];
+        int32_t srcY1;
+        int32_t srcY2;
+        int32_t dstY1;
+        int32_t dstY2;
+        int32_t srcX1 = pSrcRect->xLeft;
+        int32_t srcX2 = pSrcRect->xRight;
+        int32_t dstX1 = pDstRect->xLeft;
+        int32_t dstX2 = pDstRect->xRight;
+
+        if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
+        {
+            srcY1 = pSrc->height - pSrcRect->yTop;
+            srcY2 = pSrc->height - pSrcRect->yBottom;
+        }
+        else
+        {
+            srcY1 = pSrcRect->yTop;
+            srcY2 = pSrcRect->yBottom;
+        }
+
+        if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
+        {
+            dstY1 = pDstSize->cy - pDstRect->yTop;
+            dstY2 = pDstSize->cy - pDstRect->yBottom;
+        }
+        else
+        {
+            dstY1 = pDstRect->yTop;
+            dstY2 = pDstRect->yBottom;
+        }
+
+        if (srcY1 > srcY2)
+        {
+            if (dstY1 > dstY2)
+            {
+                /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
+                int32_t tmp = srcY1;
+                srcY1 = srcY2;
+                srcY2 = tmp;
+                tmp = dstY1;
+                dstY1 = dstY2;
+                dstY2 = tmp;
+            }
+        }
+
+        if (srcX1 > srcX2)
+        {
+            if (dstX1 > dstX2)
+            {
+                /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
+                int32_t tmp = srcX1;
+                srcX1 = srcX2;
+                srcX2 = tmp;
+                tmp = dstX1;
+                dstX1 = dstX2;
+                dstX2 = tmp;
+            }
+        }
+
+        pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
+                    dstX1, dstY1, dstX2, dstY2,
+                    GL_COLOR_BUFFER_BIT, filter);
+    }
+
+    return VINF_SUCCESS;
+}
+
+/* GL_TRIANGLE_FAN */
+DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
+{
+    /* going ccw:
+     * 1. (left;top)        4. (right;top)
+     *        |                    ^
+     *        >                    |
+     * 2. (left;bottom)  -> 3. (right;bottom) */
+    /* xLeft yTop */
+    pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
+    pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
+
+    /* xLeft yBottom */
+    pBuff[2] = pBuff[0];
+    pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
+
+    /* xRight yBottom */
+    pBuff[4] = ((float)pRect->xRight)/((float)normalX);
+    pBuff[5] = pBuff[3];
+
+    /* xRight yTop */
+    pBuff[6] = pBuff[4];
+    pBuff[7] = pBuff[1];
+    return &pBuff[8];
+}
+
+DECLINLINE(GLfloat*) crBltVtRectsTFNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
+{
+    for (uint32_t i = 0; i < cRects; ++i)
+    {
+        pBuff = crBltVtRectTFNormalized(&paRects[i], normalX, normalY, pBuff, height);
+    }
+    return pBuff;
+}
+
+DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
+{
+    /* xLeft yTop */
+    pBuff[0] = pRect->xLeft;
+    pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
+
+    /* xLeft yBottom */
+    pBuff[2] = pBuff[0];
+    pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
+
+    /* xRight yBottom */
+    pBuff[4] = pRect->xRight;
+    pBuff[5] = pBuff[3];
+
+    /* xRight yTop */
+    pBuff[6] = pBuff[4];
+    pBuff[7] = pBuff[1];
+    return &pBuff[8];
+}
+
+DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
+{
+    GLubyte iBase = *piBase;
+    /* triangle 1 */
+    pIndex[0] = iBase;
+    pIndex[1] = iBase + 1;
+    pIndex[2] = iBase + 2;
+
+    /* triangle 2 */
+    pIndex[3] = iBase;
+    pIndex[4] = iBase + 2;
+    pIndex[5] = iBase + 3;
+    *piBase = iBase + 4;
+    return pIndex + 6;
+}
+
+/* Indexed GL_TRIANGLES */
+DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
+{
+    GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
+    return ret;
+}
+
+DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
+{
+    GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
+
+    if (ppIndex)
+        *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
+
+    return ret;
+}
+
+DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
+{
+    return cRects * 4;
+}
+
+#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
+
+DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
+{
+    return 6 * cRects;
+}
+
+
+static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
+{
+    uint32_t i;
+    for (i = 0; i < cRects; ++i)
+    {
+        pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
+    }
+
+
+    if (ppIndex)
+    {
+        GLubyte *pIndex = (GLubyte*)pBuff;
+        *ppIndex = pIndex;
+        for (i = 0; i < cRects; ++i)
+        {
+            pIndex = crBltVtFillRectIndicies(pIndex, piBase);
+        }
+        pBuff = (GLfloat*)pIndex;
+    }
+
+    return pBuff;
+}
+
+static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
+{
+    if (pBuffer->cbBuffer < cbBuffer)
+    {
+        if (pBuffer->pvBuffer)
+        {
+            RTMemFree(pBuffer->pvBuffer);
+        }
+
+#ifndef DEBUG_misha
+        /* debugging: ensure we calculate proper buffer size */
+        cbBuffer += 16;
+#endif
+
+        pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
+        if (pBuffer->pvBuffer)
+            pBuffer->cbBuffer = cbBuffer;
+        else
+        {
+            crWarning("failed to allocate buffer of size %d", cbBuffer);
+            pBuffer->cbBuffer = 0;
+        }
+    }
+    return pBuffer->pvBuffer;
+}
+
+static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
+{
+    bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
+    if (pBlitter->CurrentSetSize.cx != pDstSize->cx
+            || pBlitter->CurrentSetSize.cy != pDstSize->cy)
+    {
+        pBlitter->CurrentSetSize = *pDstSize;
+        pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
+        pBlitter->pDispatch->LoadIdentity();
+        pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
+        fUpdateViewport = true;
+    }
+
+    if (fUpdateViewport)
+    {
+        pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
+        pBlitter->Flags.CurrentMuralChanged = 0;
+    }
+
+    pBlitter->Flags.LastWasFBODraw = fFBODraw;
+}
+
+static DECLCALLBACK(int) crBltBlitTexBufImplDraw2D(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
+{
+    GLuint normalX, normalY;
+    uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
+    uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
+
+    switch (pSrc->target)
+    {
+        case GL_TEXTURE_2D:
+        {
+            normalX = pSrc->width;
+            normalY = pSrc->height;
+            break;
+        }
+
+        case GL_TEXTURE_RECTANGLE_ARB:
+        {
+            normalX = 1;
+            normalY = 1;
+            break;
+        }
+
+        default:
+        {
+            crWarning("Unsupported texture target 0x%x", pSrc->target);
+            return VERR_INVALID_PARAMETER;
+        }
+    }
+
+    Assert(pSrc->hwid);
+
+    pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
+
+    if (cRects == 1)
+    {
+        /* just optimization to draw a single rect with GL_TRIANGLE_FAN */
+        GLfloat *pVerticies;
+        GLfloat *pTexCoords;
+        GLuint cElements = crBltVtGetNumVerticiesTF(cRects);
+
+        pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
+        pTexCoords = crBltVtRectsTFNormalized(paDstRect, cRects, 1, 1, pVerticies, dstHeight);
+        crBltVtRectsTFNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, srcHeight);
+
+        pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
+        pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
+
+        pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
+        pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
+
+        pBlitter->pDispatch->Enable(pSrc->target);
+
+        pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
+
+        pBlitter->pDispatch->Disable(pSrc->target);
+
+        pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
+        pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
+    }
+    else
+    {
+        GLfloat *pVerticies;
+        GLfloat *pTexCoords;
+        GLubyte *pIndicies;
+        GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
+        GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
+        GLubyte iIdxBase = 0;
+
+        pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
+        pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
+        crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
+
+        pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
+        pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
+
+        pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
+        pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
+
+        pBlitter->pDispatch->Enable(pSrc->target);
+
+        pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
+
+        pBlitter->pDispatch->Disable(pSrc->target);
+
+        pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
+        pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
+    }
+
+    pBlitter->pDispatch->BindTexture(pSrc->target, 0);
+
+    return VINF_SUCCESS;
+}
+
+static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
+{
+    const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
+    if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
+    {
+        pBlitter->Flags.SupportsFBO = 1;
+        pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
+        Assert(pBlitter->idFBO);
+    }
+    else
+        crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
+
+    if (crStrstr(pszExtension, "GL_ARB_pixel_buffer_object"))
+        pBlitter->Flags.SupportsPBO = 1;
+    else
+        crWarning("GL_ARB_pixel_buffer_object not supported");
+
+    /* BlitFramebuffer seems to be buggy on Intel, 
+     * try always glDrawXxx for now */
+    if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
+    {
+        pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
+    }
+    else
+    {
+//        crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
+        pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
+    }
+
+    /* defaults. but just in case */
+    pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
+    pBlitter->pDispatch->LoadIdentity();
+    pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
+    pBlitter->pDispatch->LoadIdentity();
+
+    return VINF_SUCCESS;
+}
+
+void CrBltLeave(PCR_BLITTER pBlitter)
+{
+    if (!pBlitter->cEnters)
+    {
+        WARN(("blitter not entered!"));
+        return;
+    }
+
+    if (--pBlitter->cEnters)
+        return;
+
+    if (pBlitter->Flags.SupportsFBO)
+    {
+        pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
+        pBlitter->pDispatch->DrawBuffer(GL_BACK);
+        pBlitter->pDispatch->ReadBuffer(GL_BACK);
+    }
+
+    pBlitter->pDispatch->Flush();
+
+    if (pBlitter->CtxInfo.Base.id)
+        pBlitter->pDispatch->MakeCurrent(0, 0, 0);
+}
+
+int CrBltEnter(PCR_BLITTER pBlitter)
+{
+    if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
+    {
+        WARN(("current mural not initialized!"));
+        return VERR_INVALID_STATE;
+    }
+
+    if (pBlitter->cEnters++)
+        return VINF_SUCCESS;
+
+    if (pBlitter->CurrentMural.Base.id) /* <- pBlitter->CurrentMural.Base.id can be null if the blitter is in a "no-context" mode (see comments to BltInit for detail)*/
+    {
+        pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
+    }
+
+    if (pBlitter->Flags.Initialized)
+        return VINF_SUCCESS;
+
+    int rc = crBltInitOnMakeCurent(pBlitter);
+    if (RT_SUCCESS(rc))
+    {
+        pBlitter->Flags.Initialized = 1;
+        return VINF_SUCCESS;
+    }
+
+    WARN(("crBltInitOnMakeCurent failed, rc %d", rc));
+    CrBltLeave(pBlitter);
+    return rc;
+}
+
+static void crBltBlitTexBuf(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, GLenum enmDstBuff, const RTRECTSIZE *pDstSize, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
+{
+    pBlitter->pDispatch->DrawBuffer(enmDstBuff);
+
+    crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
+
+    if (!(fFlags & CRBLT_F_NOALPHA))
+        pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
+    else
+    {
+        int rc = pBlitter->Flags.ShadersGloal ?
+                CrGlslProgUseNoAlpha(pBlitter->pGlslCache, pSrc->target)
+                :
+                CrGlslProgUseGenNoAlpha(&pBlitter->LocalGlslCache, pSrc->target);
+
+        if (!RT_SUCCESS(rc))
+        {
+            crWarning("Failed to use no-alpha program rc %d!, falling back to default blit", rc);
+            pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
+            return;
+        }
+
+        /* since we use shaders, we need to use draw commands rather than framebuffer blits.
+         * force using draw-based blitting */
+        crBltBlitTexBufImplDraw2D(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
+
+        Assert(pBlitter->Flags.ShadersGloal || &pBlitter->LocalGlslCache == pBlitter->pGlslCache);
+
+        CrGlslProgClear(pBlitter->pGlslCache);
+    }
+}
+
+void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
+{
+    RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
+    crBltCheckSetupViewport(pBlitter, &DstSize, false);
+}
+
+void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
+{
+    if (!CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltBlitTexMural: blitter not entered"));
+        return;
+    }
+
+    RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
+
+    pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+
+    crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
+}
+
+void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
+{
+    if (!CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltBlitTexTex: blitter not entered"));
+        return;
+    }
+
+    RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
+
+    pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
+
+    /* TODO: mag/min filters ? */
+
+    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
+
+//    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+//    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+
+    crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
+
+    pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
+}
+
+void CrBltPresent(PCR_BLITTER pBlitter)
+{
+    if (!CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltPresent: blitter not entered"));
+        return;
+    }
+
+    if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
+        pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
+    else
+        pBlitter->pDispatch->Flush();
+}
+
+static int crBltImgInitBaseForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
+{
+    memset(pDst, 0, sizeof (*pDst));
+    if (enmFormat != GL_RGBA
+            && enmFormat != GL_BGRA)
+    {
+        WARN(("unsupported format 0x%x", enmFormat));
+        return VERR_NOT_IMPLEMENTED;
+    }
+
+    uint32_t bpp = 32;
+
+    uint32_t pitch = ((bpp * pSrc->width) + 7) >> 3;
+    uint32_t cbData = pitch * pSrc->height;
+    pDst->cbData = cbData;
+    pDst->enmFormat = enmFormat;
+    pDst->width = pSrc->width;
+    pDst->height = pSrc->height;
+    pDst->bpp = bpp;
+    pDst->pitch = pitch;
+    return VINF_SUCCESS;
+}
+
+static int crBltImgCreateForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
+{
+    int rc = crBltImgInitBaseForTex(pSrc, pDst, enmFormat);
+    if (!RT_SUCCESS(rc))
+    {
+        crWarning("crBltImgInitBaseForTex failed rc %d", rc);
+        return rc;
+    }
+
+    uint32_t cbData = pDst->cbData;
+    pDst->pvData = RTMemAllocZ(cbData);
+    if (!pDst->pvData)
+    {
+        crWarning("RTMemAlloc failed");
+        return VERR_NO_MEMORY;
+    }
+
+#ifdef DEBUG_misha
+    {
+        char *pTmp = (char*)pDst->pvData;
+        for (uint32_t i = 0; i < cbData; ++i)
+        {
+            pTmp[i] = (char)((1 << i) % 255);
+        }
+    }
+#endif
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
+{
+    if (!CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltImgGetTex: blitter not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    int rc = crBltImgCreateForTex(pSrc, pDst, enmFormat);
+    if (!RT_SUCCESS(rc))
+    {
+        crWarning("crBltImgCreateForTex failed, rc %d", rc);
+        return rc;
+    }
+    pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
+
+#ifdef DEBUG_misha
+    {
+        GLint width = 0, height = 0, depth = 0;
+        pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_WIDTH, &width);
+        pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_HEIGHT, &height);
+        pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_DEPTH, &depth);
+
+        Assert(width == pSrc->width);
+        Assert(height == pSrc->height);
+//        Assert(depth == pSrc->depth);
+    }
+#endif
+
+    pBlitter->pDispatch->GetTexImage(pSrc->target, 0, enmFormat, GL_UNSIGNED_BYTE, pDst->pvData);
+
+    pBlitter->pDispatch->BindTexture(pSrc->target, 0);
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst)
+{
+    if (!CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltImgGetMural: blitter not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    crWarning("NOT IMPLEMENTED");
+    return VERR_NOT_IMPLEMENTED;
+}
+
+VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst)
+{
+    if (!CrBltIsEntered(pBlitter))
+    {
+        WARN(("CrBltImgFree: blitter not entered"));
+        return;
+    }
+
+    if (pDst->pvData)
+    {
+        RTMemFree(pDst->pvData);
+        pDst->pvData = NULL;
+    }
+}
+
+
+VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache)
+{
+    if (pCache->iGlVersion == 0)
+    {
+        const char * pszStr = (const char*)pCache->pDispatch->GetString(GL_VERSION);
+        pCache->iGlVersion = crStrParseGlVersion(pszStr);
+        if (pCache->iGlVersion <= 0)
+        {
+            crWarning("crStrParseGlVersion returned %d", pCache->iGlVersion);
+            pCache->iGlVersion = -1;
+        }
+    }
+
+    if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
+        return true;
+
+    crWarning("GLSL unsuported, gl version %d", pCache->iGlVersion);
+
+    /* @todo: we could also check for GL_ARB_shader_objects and GL_ARB_fragment_shader,
+     * but seems like chromium does not support properly gl*Object versions of shader functions used with those extensions */
+    return false;
+}
+
+#define CR_GLSL_STR_V_120 "#version 120\n"
+#define CR_GLSL_STR_EXT_TR "#extension GL_ARB_texture_rectangle : enable\n"
+#define CR_GLSL_STR_2D "2D"
+#define CR_GLSL_STR_2DRECT "2DRect"
+
+#define CR_GLSL_PATTERN_FS_NOALPHA(_ver, _ext, _tex) \
+        _ver \
+        _ext \
+        "uniform sampler" _tex " sampler0;\n" \
+        "void main()\n" \
+        "{\n" \
+            "vec2 srcCoord = vec2(gl_TexCoord[0]);\n" \
+            "gl_FragData[0].xyz = (texture" _tex "(sampler0, srcCoord).xyz);\n" \
+            "gl_FragData[0].w = 1.0;\n" \
+        "}\n"
+
+static const char* crGlslGetFsStringNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+    if (!CrGlslIsSupported(pCache))
+    {
+        crWarning("CrGlslIsSupported is false");
+        return NULL;
+    }
+
+    if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 1, 0))
+    {
+        if (enmTexTarget == GL_TEXTURE_2D)
+            return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, "", CR_GLSL_STR_2D);
+        else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
+            return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
+
+        crWarning("invalid enmTexTarget %#x", enmTexTarget);
+        return NULL;
+    }
+    else if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
+    {
+        if (enmTexTarget == GL_TEXTURE_2D)
+            return CR_GLSL_PATTERN_FS_NOALPHA("", "", CR_GLSL_STR_2D);
+        else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
+            return CR_GLSL_PATTERN_FS_NOALPHA("", CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
+
+        crWarning("invalid enmTexTarget %#x", enmTexTarget);
+        return NULL;
+    }
+
+    crError("crGlslGetFsStringNoAlpha: we should not be here!");
+    return NULL;
+}
+
+static int crGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget, GLuint *puiProgram)
+{
+    *puiProgram = 0;
+
+    const char*pStrFsShader = crGlslGetFsStringNoAlpha(pCache, enmTexTarget);
+    if (!pStrFsShader)
+    {
+        crWarning("crGlslGetFsStringNoAlpha failed");
+        return VERR_NOT_SUPPORTED;
+    }
+
+    int rc = VINF_SUCCESS;
+    GLchar * pBuf = NULL;
+    GLuint uiProgram = 0;
+    GLint iUniform = -1;
+    GLuint uiShader = pCache->pDispatch->CreateShader(GL_FRAGMENT_SHADER);
+    if (!uiShader)
+    {
+        crWarning("CreateShader failed");
+        return VERR_NOT_SUPPORTED;
+    }
+
+    pCache->pDispatch->ShaderSource(uiShader, 1, &pStrFsShader, NULL);
+
+    pCache->pDispatch->CompileShader(uiShader);
+
+    GLint compiled = 0;
+    pCache->pDispatch->GetShaderiv(uiShader, GL_COMPILE_STATUS, &compiled);
+
+#ifndef DEBUG_misha
+    if(!compiled)
+#endif
+    {
+        if (!pBuf)
+            pBuf = (GLchar *)RTMemAlloc(16300);
+        pCache->pDispatch->GetShaderInfoLog(uiShader, 16300, NULL, pBuf);
+#ifdef DEBUG_misha
+        if (compiled)
+            crDebug("compile success:\n-------------------\n%s\n--------\n", pBuf);
+        else
+#endif
+        {
+            crWarning("compile FAILURE:\n-------------------\n%s\n--------\n", pBuf);
+            rc = VERR_NOT_SUPPORTED;
+            goto end;
+        }
+    }
+
+    Assert(compiled);
+
+    uiProgram = pCache->pDispatch->CreateProgram();
+    if (!uiProgram)
+    {
+        rc = VERR_NOT_SUPPORTED;
+        goto end;
+    }
+
+    pCache->pDispatch->AttachShader(uiProgram, uiShader);
+
+    pCache->pDispatch->LinkProgram(uiProgram);
+
+    GLint linked;
+    pCache->pDispatch->GetProgramiv(uiProgram, GL_LINK_STATUS, &linked);
+#ifndef DEBUG_misha
+    if(!linked)
+#endif
+    {
+        if (!pBuf)
+            pBuf = (GLchar *)RTMemAlloc(16300);
+        pCache->pDispatch->GetProgramInfoLog(uiProgram, 16300, NULL, pBuf);
+#ifdef DEBUG_misha
+        if (linked)
+            crDebug("link success:\n-------------------\n%s\n--------\n", pBuf);
+        else
+#endif
+        {
+            crWarning("link FAILURE:\n-------------------\n%s\n--------\n", pBuf);
+            rc = VERR_NOT_SUPPORTED;
+            goto end;
+        }
+    }
+
+    Assert(linked);
+
+    iUniform = pCache->pDispatch->GetUniformLocation(uiProgram, "sampler0");
+    if (iUniform == -1)
+    {
+        crWarning("GetUniformLocation failed for sampler0");
+    }
+    else
+    {
+        pCache->pDispatch->Uniform1i(iUniform, 0);
+    }
+
+    *puiProgram = uiProgram;
+
+    /* avoid end finalizer from cleaning it */
+    uiProgram = 0;
+
+    end:
+    if (uiShader)
+        pCache->pDispatch->DeleteShader(uiShader);
+    if (uiProgram)
+        pCache->pDispatch->DeleteProgram(uiProgram);
+    if (pBuf)
+        RTMemFree(pBuf);
+    return rc;
+}
+
+DECLINLINE(GLuint) crGlslProgGetNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+    switch (enmTexTarget)
+    {
+        case GL_TEXTURE_2D:
+            return  pCache->uNoAlpha2DProg;
+        case GL_TEXTURE_RECTANGLE_ARB:
+            return pCache->uNoAlpha2DRectProg;
+        default:
+            crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
+            return 0;
+    }
+}
+
+DECLINLINE(GLuint*) crGlslProgGetNoAlphaPtr(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+    switch (enmTexTarget)
+    {
+        case GL_TEXTURE_2D:
+            return  &pCache->uNoAlpha2DProg;
+        case GL_TEXTURE_RECTANGLE_ARB:
+            return &pCache->uNoAlpha2DRectProg;
+        default:
+            crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
+            return NULL;
+    }
+}
+
+VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+    GLuint*puiProgram = crGlslProgGetNoAlphaPtr(pCache, enmTexTarget);
+    if (!puiProgram)
+        return VERR_INVALID_PARAMETER;
+
+    if (*puiProgram)
+        return VINF_SUCCESS;
+
+    return crGlslProgGenNoAlpha(pCache, enmTexTarget, puiProgram);
+}
+
+VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache)
+{
+    int rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_2D);
+    if (!RT_SUCCESS(rc))
+    {
+        crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_2D failed rc %d", rc);
+        return rc;
+    }
+
+    rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_RECTANGLE_ARB);
+    if (!RT_SUCCESS(rc))
+    {
+        crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_RECTANGLE failed rc %d", rc);
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache)
+{
+    pCache->pDispatch->UseProgram(0);
+}
+
+VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+    GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
+    if (!uiProg)
+    {
+        crWarning("request to use inexistent program!");
+        return VERR_INVALID_STATE;
+    }
+
+    Assert(uiProg);
+
+    pCache->pDispatch->UseProgram(uiProg);
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+    GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
+    if (!uiProg)
+    {
+        int rc = CrGlslProgGenNoAlpha(pCache, enmTexTarget);
+        if (!RT_SUCCESS(rc))
+        {
+            crWarning("CrGlslProgGenNoAlpha failed, rc %d", rc);
+            return rc;
+        }
+
+        uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
+        CRASSERT(uiProg);
+    }
+
+    Assert(uiProg);
+
+    pCache->pDispatch->UseProgram(uiProg);
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache)
+{
+    return pCache->uNoAlpha2DProg || pCache->uNoAlpha2DRectProg;
+}
+
+VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache)
+{
+    if (pCache->uNoAlpha2DProg)
+    {
+        pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DProg);
+        pCache->uNoAlpha2DProg = 0;
+    }
+
+    if (pCache->uNoAlpha2DRectProg)
+    {
+        pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DRectProg);
+        pCache->uNoAlpha2DRectProg = 0;
+    }
+}
+
+VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache)
+{
+    CRASSERT(!CrGlslNeedsCleanup(pCache));
+
+    CrGlslCleanup(pCache);
+
+    /* sanity */
+    memset(pCache, 0, sizeof (*pCache));
+}
+
+
+/*TdBlt*/
+static void crTdBltCheckPBO(PCR_TEXDATA pTex)
+{
+    if (pTex->idPBO)
+        return;
+
+    PCR_BLITTER pBlitter = pTex->pBlitter;
+
+    if (!pBlitter->Flags.SupportsPBO)
+        return;
+
+    pBlitter->pDispatch->GenBuffersARB(1, &pTex->idPBO);
+    if (!pTex->idPBO)
+    {
+        crWarning("PBO create failed");
+        return;
+    }
+
+    pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
+    pBlitter->pDispatch->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
+                pTex->Tex.width*pTex->Tex.height*4,
+                0, GL_STREAM_READ_ARB);
+    pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+}
+
+static uint32_t crTdBltTexCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height, GLenum enmTarget)
+{
+    uint32_t tex = 0;
+    pBlitter->pDispatch->GenTextures(1, &tex);
+    if (!tex)
+    {
+        crWarning("Tex create failed");
+        return 0;
+    }
+
+    pBlitter->pDispatch->BindTexture(enmTarget, tex);
+    pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
+    pBlitter->pDispatch->TexImage2D(enmTarget, 0, GL_RGBA8,
+            width, height,
+            0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+
+    /*Restore gl state*/
+    pBlitter->pDispatch->BindTexture(enmTarget, 0);
+
+    return tex;
+}
+
+int crTdBltCheckInvertTex(PCR_TEXDATA pTex)
+{
+    if (pTex->idInvertTex)
+        return VINF_SUCCESS;
+
+    pTex->idInvertTex = crTdBltTexCreate(pTex->pBlitter, pTex->Tex.width, pTex->Tex.height, pTex->Tex.target);
+    if (!pTex->idInvertTex)
+    {
+        crWarning("Invert Tex create failed");
+        return VERR_GENERAL_FAILURE;
+    }
+    return VINF_SUCCESS;
+}
+
+void crTdBltImgRelease(PCR_TEXDATA pTex)
+{
+    pTex->Flags.DataValid = 0;
+}
+
+void crTdBltImgFree(PCR_TEXDATA pTex)
+{
+    if (!pTex->Img.pvData)
+    {
+        Assert(!pTex->Flags.DataValid);
+        return;
+    }
+
+    crTdBltImgRelease(pTex);
+
+    Assert(!pTex->Flags.DataValid);
+
+
+    if (pTex->idPBO)
+    {
+        PCR_BLITTER pBlitter = pTex->pBlitter;
+
+        Assert(CrBltIsEntered(pBlitter));
+        pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
+        pBlitter->pDispatch->UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
+        pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+    }
+    else
+    {
+        Assert(pTex->Img.pvData);
+        RTMemFree(pTex->Img.pvData);
+    }
+
+    pTex->Img.pvData = NULL;
+}
+
+int crTdBltImgAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted)
+{
+    void *pvData = pTex->Img.pvData;
+    Assert(!pTex->Flags.DataValid);
+    int rc = crBltImgInitBaseForTex(&pTex->Tex, &pTex->Img, enmFormat);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crBltImgInitBaseForTex failed rc %d", rc));
+        return rc;
+    }
+
+    PCR_BLITTER pBlitter = pTex->pBlitter;
+    Assert(CrBltIsEntered(pBlitter));
+    pBlitter->pDispatch->BindTexture(pTex->Tex.target, fInverted ? pTex->idInvertTex : pTex->Tex.hwid);
+
+    pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
+
+    if (pvData)
+    {
+        if (pTex->idPBO)
+        {
+            pBlitter->pDispatch->UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
+            pvData = NULL;
+
+        }
+    }
+    else
+    {
+        if (!pTex->idPBO)
+        {
+            pvData = RTMemAlloc(4*pTex->Tex.width*pTex->Tex.height);
+            if (!pvData)
+            {
+                WARN(("Out of memory in crTdBltImgAcquire"));
+                pBlitter->pDispatch->BindTexture(pTex->Tex.target, 0);
+                return VERR_NO_MEMORY;
+            }
+        }
+    }
+
+    Assert(!pvData == !!pTex->idPBO);
+
+    /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
+    pBlitter->pDispatch->GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
+
+    /*restore gl state*/
+    pBlitter->pDispatch->BindTexture(pTex->Tex.target, 0);
+
+    if (pTex->idPBO)
+    {
+        pvData = pBlitter->pDispatch->MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
+        if (!pvData)
+        {
+            WARN(("Failed to MapBuffer in CrHlpGetTexImage"));
+            return VERR_GENERAL_FAILURE;
+        }
+
+        pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+    }
+
+    Assert(pvData);
+    pTex->Img.pvData = pvData;
+    pTex->Flags.DataValid = 1;
+    pTex->Flags.DataInverted = fInverted;
+    return VINF_SUCCESS;
+}
+
+/* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataInvalidateNe or CrTdBltDataCleanup */
+VBOXBLITTERDECL(int) CrTdBltDataRelease(PCR_TEXDATA pTex)
+{
+    if (!pTex->Flags.Entered)
+    {
+        WARN(("tex not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    if (!pTex->Flags.DataAcquired)
+    {
+        WARN(("Data NOT acquired"));
+        return VERR_INVALID_STATE;
+    }
+
+    Assert(pTex->Img.pvData);
+    Assert(pTex->Flags.DataValid);
+
+    pTex->Flags.DataAcquired = 0;
+
+    return VINF_SUCCESS;
+}
+
+static void crTdBltDataFree(PCR_TEXDATA pTex)
+{
+    crTdBltImgFree(pTex);
+
+    if (pTex->pScaledCache)
+        CrTdBltDataFreeNe(pTex->pScaledCache);
+}
+
+/* discard the texture data cached with previous CrTdBltDataAcquire.
+ * Must be called wit data released (CrTdBltDataRelease) */
+VBOXBLITTERDECL(int) CrTdBltDataFree(PCR_TEXDATA pTex)
+{
+    if (!pTex->Flags.Entered)
+    {
+        WARN(("tex not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    crTdBltDataFree(pTex);
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(void) CrTdBltDataInvalidateNe(PCR_TEXDATA pTex)
+{
+    crTdBltImgRelease(pTex);
+
+    if (pTex->pScaledCache)
+        CrTdBltDataInvalidateNe(pTex->pScaledCache);
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataFreeNe(PCR_TEXDATA pTex)
+{
+    if (!pTex->Img.pvData)
+        return VINF_SUCCESS;
+
+    bool fEntered = false;
+    if (pTex->idPBO)
+    {
+        int rc = CrTdBltEnter(pTex);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        fEntered = true;
+    }
+
+    crTdBltDataFree(pTex);
+
+    if (fEntered)
+        CrTdBltLeave(pTex);
+
+    return VINF_SUCCESS;
+}
+
+static void crTdBltSdCleanupCacheNe(PCR_TEXDATA pTex)
+{
+    if (pTex->pScaledCache)
+    {
+        CrTdBltDataCleanupNe(pTex->pScaledCache);
+        CrTdRelease(pTex->pScaledCache);
+        pTex->pScaledCache = NULL;
+    }
+}
+
+static void crTdBltDataCleanup(PCR_TEXDATA pTex)
+{
+    crTdBltImgFree(pTex);
+
+    PCR_BLITTER pBlitter = pTex->pBlitter;
+
+    if (pTex->idPBO)
+    {
+        Assert(CrBltIsEntered(pBlitter));
+        pBlitter->pDispatch->DeleteBuffersARB(1, &pTex->idPBO);
+        pTex->idPBO = 0;
+    }
+
+    if (pTex->idInvertTex)
+    {
+        Assert(CrBltIsEntered(pBlitter));
+        pBlitter->pDispatch->DeleteTextures(1, &pTex->idInvertTex);
+        pTex->idInvertTex = 0;
+    }
+
+    crTdBltSdCleanupCacheNe(pTex);
+}
+
+/* does same as CrTdBltDataFree, and in addition cleans up */
+VBOXBLITTERDECL(int) CrTdBltDataCleanup(PCR_TEXDATA pTex)
+{
+    if (!pTex->Flags.Entered)
+    {
+        WARN(("tex not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    crTdBltDataCleanup(pTex);
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataCleanupNe(PCR_TEXDATA pTex)
+{
+    bool fEntered = false;
+    if (pTex->idPBO || pTex->idInvertTex)
+    {
+        int rc = CrTdBltEnter(pTex);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        fEntered = true;
+    }
+
+    crTdBltDataCleanup(pTex);
+
+    if (fEntered)
+        CrTdBltLeave(pTex);
+
+    return VINF_SUCCESS;
+}
+
+/* acquire the texture data, returns the cached data in case it is cached.
+ * the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup.
+ * */
+VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg)
+{
+    if (!pTex->Flags.Entered)
+    {
+        WARN(("tex not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    if (pTex->Flags.DataAcquired)
+    {
+        WARN(("Data acquired already"));
+        return VERR_INVALID_STATE;
+    }
+
+    if (pTex->Flags.DataValid && pTex->Img.enmFormat == enmFormat && !pTex->Flags.DataInverted == !fInverted)
+    {
+        Assert(pTex->Img.pvData);
+        *ppImg = &pTex->Img;
+        pTex->Flags.DataAcquired = 1;
+        return VINF_SUCCESS;
+    }
+
+    crTdBltImgRelease(pTex);
+
+    crTdBltCheckPBO(pTex);
+
+    int rc;
+
+    if (fInverted)
+    {
+        rc = crTdBltCheckInvertTex(pTex);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crTdBltCheckInvertTex failed rc %d", rc));
+            return rc;
+        }
+
+        RTRECT SrcRect, DstRect;
+        VBOXVR_TEXTURE InvertTex;
+
+        InvertTex = pTex->Tex;
+        InvertTex.hwid = pTex->idInvertTex;
+
+        SrcRect.xLeft = 0;
+        SrcRect.yTop = InvertTex.height;
+        SrcRect.xRight = InvertTex.width;
+        SrcRect.yBottom = 0;
+
+        DstRect.xLeft = 0;
+        DstRect.yTop = 0;
+        DstRect.xRight = InvertTex.width;
+        DstRect.yBottom = InvertTex.height;
+
+        CrBltBlitTexTex(pTex->pBlitter, &pTex->Tex, &SrcRect, &InvertTex, &DstRect, 1, 0);
+    }
+
+    rc = crTdBltImgAcquire(pTex, enmFormat, fInverted);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crTdBltImgAcquire failed rc %d", rc));
+        return rc;
+    }
+
+    Assert(pTex->Img.pvData);
+    *ppImg = &pTex->Img;
+    pTex->Flags.DataAcquired = 1;
+
+    return VINF_SUCCESS;
+}
+
+DECLINLINE(void) crTdResize(PCR_TEXDATA pTex, const VBOXVR_TEXTURE *pVrTex)
+{
+    crTdBltDataCleanup(pTex);
+
+    pTex->Tex = *pVrTex;
+}
+
+static DECLCALLBACK(void) ctTdBltSdReleased(struct CR_TEXDATA *pTexture)
+{
+    PCR_BLITTER pBlitter = pTexture->pBlitter;
+
+    int rc = CrBltEnter(pBlitter);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrBltEnter failed, rc %d", rc));
+        return;
+    }
+
+    CrTdBltDataCleanupNe(pTexture);
+
+    pBlitter->pDispatch->DeleteTextures(1, &pTexture->Tex.hwid);
+
+    CrBltLeave(pBlitter);
+
+    RTMemFree(pTexture);
+}
+
+static int ctTdBltSdCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height, GLenum enmTarget, PCR_TEXDATA *ppScaledCache)
+{
+    PCR_TEXDATA pScaledCache;
+
+    Assert(CrBltIsEntered(pBlitter));
+
+    *ppScaledCache = NULL;
+
+    pScaledCache = (PCR_TEXDATA)RTMemAlloc(sizeof (*pScaledCache));
+    if (!pScaledCache)
+    {
+        WARN(("RTMemAlloc failed"));
+        return VERR_NO_MEMORY;
+    }
+
+    VBOXVR_TEXTURE Tex;
+    Tex.width = width;
+    Tex.height = height;
+    Tex.target = enmTarget;
+    Tex.hwid = crTdBltTexCreate(pBlitter, width, height, enmTarget);
+    if (!Tex.hwid)
+    {
+        WARN(("Tex create failed"));
+        RTMemFree(pScaledCache);
+        return VERR_GENERAL_FAILURE;
+    }
+
+    CrTdInit(pScaledCache, &Tex, pBlitter, ctTdBltSdReleased);
+
+    *ppScaledCache = pScaledCache;
+
+    return VINF_SUCCESS;
+}
+
+static int ctTdBltSdGet(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache)
+{
+    Assert(pTex->Flags.Entered);
+
+    PCR_TEXDATA pScaledCache;
+
+    *ppScaledCache = NULL;
+
+    if (!pTex->pScaledCache)
+    {
+        int rc = ctTdBltSdCreate(pTex->pBlitter, width, height, pTex->Tex.target, &pScaledCache);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("ctTdBltSdCreate failed %d", rc));
+            return rc;
+        }
+
+        pTex->pScaledCache = pScaledCache;
+    }
+    else
+    {
+        int cmp = pTex->pScaledCache->Tex.width - width;
+        if (cmp <= 0)
+            cmp = pTex->pScaledCache->Tex.height - height;
+
+        if (!cmp)
+            pScaledCache = pTex->pScaledCache;
+        else if (cmp < 0) /* current cache is "less" than the requested */
+        {
+            int rc = ctTdBltSdCreate(pTex->pBlitter, width, height, pTex->Tex.target, &pScaledCache);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("ctTdBltSdCreate failed %d", rc));
+                return rc;
+            }
+
+            pScaledCache->pScaledCache = pTex->pScaledCache;
+            pTex->pScaledCache = pScaledCache;
+        }
+        else /* cmp > 0 */
+        {
+            int rc = ctTdBltSdGet(pTex->pScaledCache, width, height, &pScaledCache);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("ctTdBltSdGet failed %d", rc));
+                return rc;
+            }
+        }
+    }
+
+    Assert(pScaledCache);
+
+#if 0
+    {
+        VBOXVR_TEXTURE Tex;
+        Tex.width = width;
+        Tex.height = height;
+        Tex.target = pTex->Tex.target;
+        Tex.hwid = crTdBltTexCreate(pTex, width, height);
+        if (!Tex.hwid)
+        {
+            WARN(("Tex create failed"));
+            return VERR_GENERAL_FAILURE;
+        }
+
+        pTex->pBlitter->pDispatch->DeleteTextures(1, &pTex->pScaledCache->Tex.hwid);
+
+        crTdResize(pTex->pScaledCache, &Tex);
+    }
+#endif
+
+    *ppScaledCache = pScaledCache;
+    return VINF_SUCCESS;
+}
+
+static int ctTdBltSdGetUpdated(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache)
+{
+    PCR_TEXDATA pScaledCache;
+
+    *ppScaledCache = NULL;
+    int rc = ctTdBltSdGet(pTex, width, height, &pScaledCache);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("ctTdBltSdGet failed %d", rc));
+        return rc;
+    }
+
+    Assert(width == pScaledCache->Tex.width);
+    Assert(height == pScaledCache->Tex.height);
+
+    if (!pScaledCache->Flags.DataValid)
+    {
+        RTRECT SrcRect, DstRect;
+
+        SrcRect.xLeft = 0;
+        SrcRect.yTop = 0;
+        SrcRect.xRight = pTex->Tex.width;
+        SrcRect.yBottom = pTex->Tex.height;
+
+        DstRect.xLeft = 0;
+        DstRect.yTop = 0;
+        DstRect.xRight = width;
+        DstRect.yBottom = height;
+
+        CrBltBlitTexTex(pTex->pBlitter, &pTex->Tex, &SrcRect, &pScaledCache->Tex, &DstRect, 1, 0);
+    }
+
+    *ppScaledCache = pScaledCache;
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataAcquireScaled(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, uint32_t width, uint32_t height, const CR_BLITTER_IMG**ppImg)
+{
+    if (pTex->Tex.width == width && pTex->Tex.height == height)
+        return CrTdBltDataAcquire(pTex, enmFormat, fInverted, ppImg);
+
+    if (!pTex->Flags.Entered)
+    {
+        WARN(("tex not entered"));
+        return VERR_INVALID_STATE;
+    }
+
+    PCR_TEXDATA pScaledCache;
+
+    int rc = ctTdBltSdGetUpdated(pTex, width, height, &pScaledCache);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("ctTdBltSdGetUpdated failed rc %d", rc));
+        return rc;
+    }
+
+    rc = CrTdBltEnter(pScaledCache);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrTdBltEnter failed rc %d", rc));
+        return rc;
+    }
+
+    rc = CrTdBltDataAcquire(pScaledCache, enmFormat, fInverted, ppImg);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrTdBltDataAcquire failed rc %d", rc));
+        CrTdBltLeave(pTex->pScaledCache);
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataReleaseScaled(PCR_TEXDATA pTex, const CR_BLITTER_IMG *pImg)
+{
+    PCR_TEXDATA pScaledCache = RT_FROM_MEMBER(pImg, CR_TEXDATA, Img);
+    int rc = CrTdBltDataRelease(pScaledCache);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrTdBltDataRelease failed rc %d", rc));
+        return rc;
+    }
+
+    if (pScaledCache != pTex)
+        CrTdBltLeave(pScaledCache);
+
+    return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(void) CrTdBltScaleCacheMoveTo(PCR_TEXDATA pTex, PCR_TEXDATA pDstTex)
+{
+    if (!pTex->pScaledCache)
+        return;
+
+    crTdBltSdCleanupCacheNe(pDstTex);
+
+    pDstTex->pScaledCache = pTex->pScaledCache;
+    pTex->pScaledCache = NULL;
+}
diff --git a/src/VBox/GuestHost/OpenGL/util/bmpscale.cpp b/src/VBox/GuestHost/OpenGL/util/bmpscale.cpp
new file mode 100644
index 0000000..1b32487
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/bmpscale.cpp
@@ -0,0 +1,319 @@
+/** @file
+ * Image resampling code, used for snapshot thumbnails.
+ */
+
+/*
+ * Copyright (C) 2009-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*
+ * Based on gdImageCopyResampled from libgd.
+ * Original copyright notice follows:
+
+     Portions copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+     Pierre-Alain Joye (pierre at libgd.org).
+
+     Permission has been granted to copy, distribute and modify gd in
+     any context without fee, including a commercial application,
+     provided that this notice is present in user-accessible supporting
+     documentation.
+
+     This does not affect your ownership of the derived work itself, and
+     the intent is to assure proper credit for the authors of gd, not to
+     interfere with your productive use of gd. If you have questions,
+     ask. "Derived works" includes all programs that utilize the
+     library. Credit must be given in user-accessible documentation.
+
+     This software is provided "AS IS." The copyright holders disclaim
+     all warranties, either express or implied, including but not
+     limited to implied warranties of merchantability and fitness for a
+     particular purpose, with respect to this code and accompanying
+     documentation.
+ */
+
+/*
+ *
+ * @todo Simplify: Offsets of images are 0,0 => no dstX, dstY, srcX, srcY;
+ *             Screenshot has no alpha channel => no processing of alpha byte.
+ */
+
+#include <cr_bmpscale.h>
+
+/* 2.0.10: cast instead of floor() yields 35% performance improvement.
+    Thanks to John Buckman. */
+
+#define floor2(exp) ((long) exp)
+/*#define floor2(exp) floor(exp)*/
+
+typedef uint8_t *gdImagePtr;
+
+DECLINLINE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y, int w)
+{
+    return *(int32_t *)(im + y * w * 4 + x * 4);
+}
+
+DECLINLINE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color, int cbLine)
+{
+    *(int32_t *)(im + y * cbLine + x * 4) = color;
+}
+
+#define gdAlphaMax 127
+#define gdAlphaOpaque 0
+#define gdAlphaTransparent 127
+#define gdRedMax 255
+#define gdGreenMax 255
+#define gdBlueMax 255
+#define gdTrueColorGetAlpha(c) (((c) & 0x7F000000) >> 24)
+#define gdTrueColorGetRed(c) (((c) & 0xFF0000) >> 16)
+#define gdTrueColorGetGreen(c) (((c) & 0x00FF00) >> 8)
+#define gdTrueColorGetBlue(c) ((c) & 0x0000FF)
+#define gdTrueColorAlpha(r, g, b, a) (((a) << 24) + \
+    ((r) << 16) + \
+    ((g) << 8) + \
+    (b))
+
+void gdImageCopyResampled (uint8_t *dst,
+              uint8_t *src,
+              int dstX, int dstY,
+              int srcX, int srcY,
+              int dstW, int dstH, int srcW, int srcH)
+{
+  int x, y;
+  double sy1, sy2, sx1, sx2;
+  for (y = dstY; (y < dstY + dstH); y++)
+    {
+      sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
+      sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
+    (double) dstH;
+      for (x = dstX; (x < dstX + dstW); x++)
+    {
+      double sx, sy;
+      double spixels = 0;
+      double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
+      sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
+      sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
+      sy = sy1;
+      do
+        {
+          double yportion;
+          if (floor2 (sy) == floor2 (sy1))
+        {
+          yportion = 1.0 - (sy - floor2 (sy));
+          if (yportion > sy2 - sy1)
+            {
+              yportion = sy2 - sy1;
+            }
+          sy = floor2 (sy);
+        }
+          else if (sy == floor2 (sy2))
+        {
+          yportion = sy2 - floor2 (sy2);
+        }
+          else
+        {
+          yportion = 1.0;
+        }
+          sx = sx1;
+          do
+        {
+          double xportion;
+          double pcontribution;
+          int p;
+          if (floor2 (sx) == floor2 (sx1))
+            {
+              xportion = 1.0 - (sx - floor2 (sx));
+              if (xportion > sx2 - sx1)
+            {
+              xportion = sx2 - sx1;
+            }
+              sx = floor2 (sx);
+            }
+          else if (sx == floor2 (sx2))
+            {
+              xportion = sx2 - floor2 (sx2);
+            }
+          else
+            {
+              xportion = 1.0;
+            }
+          pcontribution = xportion * yportion;
+          /* 2.08: previously srcX and srcY were ignored.
+             Andrew Pattison */
+          p = gdImageGetTrueColorPixel (src,
+                        (int) sx + srcX,
+                        (int) sy + srcY, srcW);
+          red += gdTrueColorGetRed (p) * pcontribution;
+          green += gdTrueColorGetGreen (p) * pcontribution;
+          blue += gdTrueColorGetBlue (p) * pcontribution;
+          alpha += gdTrueColorGetAlpha (p) * pcontribution;
+          spixels += xportion * yportion;
+          sx += 1.0;
+        }
+          while (sx < sx2);
+          sy += 1.0;
+        }
+      while (sy < sy2);
+      if (spixels != 0.0)
+        {
+          red /= spixels;
+          green /= spixels;
+          blue /= spixels;
+          alpha /= spixels;
+        }
+      /* Clamping to allow for rounding errors above */
+      if (red > 255.0)
+        {
+          red = 255.0;
+        }
+      if (green > 255.0)
+        {
+          green = 255.0;
+        }
+      if (blue > 255.0)
+        {
+          blue = 255.0;
+        }
+      if (alpha > gdAlphaMax)
+        {
+          alpha = gdAlphaMax;
+        }
+      gdImageSetPixel (dst,
+               x, y,
+               gdTrueColorAlpha ((int) red,
+                         (int) green,
+                         (int) blue, (int) alpha), dstW * 4);
+    }
+    }
+}
+
+/* Fast integer implementation for 32 bpp bitmap scaling.
+ * Use fixed point values * 16.
+ */
+typedef int32_t FIXEDPOINT;
+#define INT_TO_FIXEDPOINT(i) (FIXEDPOINT)((i) << 4)
+#define FIXEDPOINT_TO_INT(v) (int)((v) >> 4)
+#define FIXEDPOINT_FLOOR(v) ((v) & ~0xF)
+#define FIXEDPOINT_FRACTION(v) ((v) & 0xF)
+
+/* For 32 bit source only. */
+VBOXBMPSCALEDECL(void) CrBmpScale32 (uint8_t *dst,
+                        int iDstDeltaLine,
+                        int dstW, int dstH,
+                        const uint8_t *src,
+                        int iSrcDeltaLine,
+                        int srcW, int srcH)
+{
+    int x, y;
+
+    for (y = 0; y < dstH; y++)
+    {
+        FIXEDPOINT sy1 = INT_TO_FIXEDPOINT(y * srcH) / dstH;
+        FIXEDPOINT sy2 = INT_TO_FIXEDPOINT((y + 1) * srcH) / dstH;
+
+        for (x = 0; x < dstW; x++)
+        {
+            FIXEDPOINT red = 0, green = 0, blue = 0;
+
+            FIXEDPOINT sx1 = INT_TO_FIXEDPOINT(x * srcW) / dstW;
+            FIXEDPOINT sx2 = INT_TO_FIXEDPOINT((x + 1) * srcW) / dstW;
+
+            FIXEDPOINT spixels = (sx2 - sx1) * (sy2 - sy1);
+
+            FIXEDPOINT sy = sy1;
+
+            do
+            {
+                FIXEDPOINT yportion;
+                if (FIXEDPOINT_FLOOR (sy) == FIXEDPOINT_FLOOR (sy1))
+                {
+                    yportion = INT_TO_FIXEDPOINT(1) - FIXEDPOINT_FRACTION(sy);
+                    if (yportion > sy2 - sy1)
+                    {
+                        yportion = sy2 - sy1;
+                    }
+                    sy = FIXEDPOINT_FLOOR (sy);
+                }
+                else if (sy == FIXEDPOINT_FLOOR (sy2))
+                {
+                    yportion = FIXEDPOINT_FRACTION(sy2);
+                }
+                else
+                {
+                    yportion = INT_TO_FIXEDPOINT(1);
+                }
+
+                const uint8_t *pu8SrcLine = src + iSrcDeltaLine * FIXEDPOINT_TO_INT(sy);
+                FIXEDPOINT sx = sx1;
+                do
+                {
+                    FIXEDPOINT xportion;
+                    FIXEDPOINT pcontribution;
+                    int p;
+                    if (FIXEDPOINT_FLOOR (sx) == FIXEDPOINT_FLOOR (sx1))
+                    {
+                        xportion = INT_TO_FIXEDPOINT(1) - FIXEDPOINT_FRACTION(sx);
+                        if (xportion > sx2 - sx1)
+                        {
+                            xportion = sx2 - sx1;
+                        }
+                        pcontribution = xportion * yportion;
+                        sx = FIXEDPOINT_FLOOR (sx);
+                    }
+                    else if (sx == FIXEDPOINT_FLOOR (sx2))
+                    {
+                        xportion = FIXEDPOINT_FRACTION(sx2);
+                        pcontribution = xportion * yportion;
+                    }
+                    else
+                    {
+                        xportion = INT_TO_FIXEDPOINT(1);
+                        pcontribution = xportion * yportion;
+                    }
+                    /* Color depth specific code begin */
+                    p = *(uint32_t *)(pu8SrcLine + FIXEDPOINT_TO_INT(sx) * 4);
+                    /* Color depth specific code end */
+                    red += gdTrueColorGetRed (p) * pcontribution;
+                    green += gdTrueColorGetGreen (p) * pcontribution;
+                    blue += gdTrueColorGetBlue (p) * pcontribution;
+
+                    sx += INT_TO_FIXEDPOINT(1);
+                } while (sx < sx2);
+
+                sy += INT_TO_FIXEDPOINT(1);
+            } while (sy < sy2);
+
+            if (spixels != 0)
+            {
+                red /= spixels;
+                green /= spixels;
+                blue /= spixels;
+            }
+            /* Clamping to allow for rounding errors above */
+            if (red > 255)
+            {
+                red = 255;
+            }
+            if (green > 255)
+            {
+                green = 255;
+            }
+            if (blue > 255)
+            {
+                blue = 255;
+            }
+            gdImageSetPixel (dst,
+                             x, y,
+                             ( ((int) red) << 16) + (((int) green) << 8) + ((int) blue),
+                             iDstDeltaLine);
+        }
+    }
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/util/compositor.cpp b/src/VBox/GuestHost/OpenGL/util/compositor.cpp
new file mode 100644
index 0000000..f7c50bc
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/compositor.cpp
@@ -0,0 +1,1015 @@
+/* $Id: compositor.cpp $ */
+
+/** @file
+ * Compositor impl
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include <cr_compositor.h>
+
+#define VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED UINT32_MAX
+
+
+static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects)
+{
+    Assert(cRects);
+
+    if (pCompositor->cRectsBuffer >= cRects)
+    {
+        pCompositor->cRects = cRects;
+        return VINF_SUCCESS;
+    }
+
+    if (pCompositor->cRectsBuffer)
+    {
+        Assert(pCompositor->paSrcRects);
+        RTMemFree(pCompositor->paSrcRects);
+        pCompositor->paSrcRects = NULL;
+        Assert(pCompositor->paDstRects);
+        RTMemFree(pCompositor->paDstRects);
+        pCompositor->paDstRects = NULL;
+        Assert(pCompositor->paDstUnstretchedRects);
+        RTMemFree(pCompositor->paDstUnstretchedRects);
+        pCompositor->paDstUnstretchedRects = NULL;
+    }
+    else
+    {
+        Assert(!pCompositor->paSrcRects);
+        Assert(!pCompositor->paDstRects);
+        Assert(!pCompositor->paDstUnstretchedRects);
+    }
+
+    pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paSrcRects) * cRects);
+    if (pCompositor->paSrcRects)
+    {
+        pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstRects) * cRects);
+        if (pCompositor->paDstRects)
+        {
+            pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstUnstretchedRects) * cRects);
+            if (pCompositor->paDstUnstretchedRects)
+            {
+                pCompositor->cRects = cRects;
+                pCompositor->cRectsBuffer = cRects;
+                return VINF_SUCCESS;
+            }
+
+            RTMemFree(pCompositor->paDstRects);
+            pCompositor->paDstRects = NULL;
+        }
+        else
+        {
+            WARN(("RTMemAlloc failed!"));
+        }
+        RTMemFree(pCompositor->paSrcRects);
+        pCompositor->paSrcRects = NULL;
+    }
+    else
+    {
+        WARN(("RTMemAlloc failed!"));
+    }
+
+    pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
+    pCompositor->cRectsBuffer = 0;
+
+    return VERR_NO_MEMORY;
+}
+
+static void crVrScrCompositorRectsInvalidate(PVBOXVR_SCR_COMPOSITOR pCompositor)
+{
+    pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
+}
+
+static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor)
+{
+    uint32_t* pCounter = (uint32_t*)pvVisitor;
+    Assert(VBoxVrListRectsCount(&pEntry->Vr));
+    *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
+    return true;
+}
+
+typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
+{
+    PRTRECT paSrcRects;
+    PRTRECT paDstRects;
+    PRTRECT paDstUnstretchedRects;
+    uint32_t cRects;
+} VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER, *PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER;
+
+static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
+{
+    PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER pData = (PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER)pvVisitor;
+    PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
+    pEntry->paSrcRects = pData->paSrcRects;
+    pEntry->paDstRects = pData->paDstRects;
+    pEntry->paDstUnstretchedRects = pData->paDstUnstretchedRects;
+    uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
+    Assert(cRects);
+    Assert(cRects <= pData->cRects);
+    int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstUnstretchedRects);
+    AssertRC(rc);
+
+    if (!pEntry->Rect.xLeft && !pEntry->Rect.yTop)
+    {
+        memcpy(pEntry->paSrcRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paSrcRects));
+    }
+    else
+    {
+        for (uint32_t i = 0; i < cRects; ++i)
+        {
+            pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstUnstretchedRects[i].xLeft - pEntry->Rect.xLeft));
+            pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstUnstretchedRects[i].yTop - pEntry->Rect.yTop));
+            pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Rect.xLeft));
+            pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Rect.yTop));
+        }
+    }
+
+#ifndef IN_RING0
+    if (pCompositor->StretchX != 1. || pCompositor->StretchY != 1.)
+    {
+        for (uint32_t i = 0; i < cRects; ++i)
+        {
+            if (pCompositor->StretchX != 1.)
+            {
+                pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
+                pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
+            }
+            if (pCompositor->StretchY != 1.)
+            {
+                pEntry->paDstRects[i].yTop = (int32_t)(pEntry->paDstUnstretchedRects[i].yTop * pCompositor->StretchY);
+                pEntry->paDstRects[i].yBottom = (int32_t)(pEntry->paDstUnstretchedRects[i].yBottom * pCompositor->StretchY);
+            }
+        }
+    }
+    else
+#endif
+    {
+        memcpy(pEntry->paDstRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paDstUnstretchedRects));
+    }
+
+#if 0//ndef IN_RING0
+    bool canZeroX = (pCompositor->StretchX < 1.);
+    bool canZeroY = (pCompositor->StretchY < 1.);
+    if (canZeroX && canZeroY)
+    {
+        /* filter out zero rectangles*/
+        uint32_t iOrig, iNew;
+        for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
+        {
+            PRTRECT pOrigRect = &pEntry->paDstRects[iOrig];
+            if (pOrigRect->xLeft != pOrigRect->xRight
+                    && pOrigRect->yTop != pOrigRect->yBottom)
+                continue;
+
+            if (iNew != iOrig)
+            {
+                PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
+                *pNewRect = *pOrigRect;
+            }
+
+            ++iNew;
+        }
+
+        Assert(iNew <= iOrig);
+
+        uint32_t cDiff = iOrig - iNew;
+
+        if (cDiff)
+        {
+            pCompositor->cRects -= cDiff;
+            cRects -= cDiff;
+        }
+    }
+#endif
+
+    pEntry->cRects = cRects;
+    pData->paDstRects += cRects;
+    pData->paSrcRects += cRects;
+    pData->paDstUnstretchedRects += cRects;
+    pData->cRects -= cRects;
+    return true;
+}
+
+static int crVrScrCompositorRectsCheckInit(const VBOXVR_SCR_COMPOSITOR *pcCompositor)
+{
+    VBOXVR_SCR_COMPOSITOR *pCompositor = const_cast<VBOXVR_SCR_COMPOSITOR*>(pcCompositor);
+
+    if (pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED)
+        return VINF_SUCCESS;
+
+    uint32_t cRects = 0;
+    VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsCounterCb, &cRects);
+
+    if (!cRects)
+    {
+        pCompositor->cRects = 0;
+        return VINF_SUCCESS;
+    }
+
+    int rc = crVrScrCompositorRectsAssignBuffer(pCompositor, cRects);
+    if (!RT_SUCCESS(rc))
+        return rc;
+
+    VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER AssignerData;
+    AssignerData.paSrcRects = pCompositor->paSrcRects;
+    AssignerData.paDstRects = pCompositor->paDstRects;
+    AssignerData.paDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
+    AssignerData.cRects = pCompositor->cRects;
+    VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsAssignerCb, &AssignerData);
+    Assert(!AssignerData.cRects);
+    return VINF_SUCCESS;
+}
+
+
+static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangedFlags)
+{
+    uint32_t fChangedFlags = 0;
+    PVBOXVR_COMPOSITOR_ENTRY pReplacedEntry;
+    int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions, paRegions, &pReplacedEntry, &fChangedFlags);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
+        return rc;
+    }
+
+    VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
+
+    if (fChangedFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
+    {
+        crVrScrCompositorRectsInvalidate(pCompositor);
+    }
+    else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+    {
+        Assert(pReplacedScrEntry);
+    }
+
+    if (fChangedFlags & VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED)
+    {
+        CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+    }
+    else if ((fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED) && pEntry)
+    {
+        CrVrScrCompositorEntrySetChanged(pEntry, true);
+    }
+
+    if (pfChangedFlags)
+        *pfChangedFlags = fChangedFlags;
+
+    if (ppReplacedScrEntry)
+        *ppReplacedScrEntry = pReplacedScrEntry;
+
+    return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+    bool fChanged;
+    int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc));
+        return rc;
+    }
+
+    if (fChanged)
+    {
+        CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+        if (!CrVrScrCompositorEntryIsInList(pEntry))
+        {
+            pEntry->cRects = 0;
+            pEntry->paSrcRects = NULL;
+            pEntry->paDstRects = NULL;
+            pEntry->paDstUnstretchedRects = NULL;
+        }
+        crVrScrCompositorRectsInvalidate(pCompositor);
+    }
+
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+    return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, bool *pfChanged)
+{
+    if (pfChanged)
+        *pfChanged = false;
+    if (pEntry && (pEntry->Rect.xLeft != pPos->x || pEntry->Rect.yTop != pPos->y))
+    {
+        if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
+        {
+            int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Rect.xLeft, pPos->y - pEntry->Rect.yTop, pfChanged);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("VBoxVrCompositorEntryRegionsTranslate failed rc %d", rc));
+                return rc;
+            }
+
+            crVrScrCompositorRectsInvalidate(pCompositor);
+        }
+
+        VBoxRectMove(&pEntry->Rect, pPos->x, pPos->y);
+        CrVrScrCompositorEntrySetChanged(pEntry, true);
+
+        if (pfChanged)
+            *pfChanged = true;
+    }
+    return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryEnsureRegionsBounds(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool *pfChanged)
+{
+    RTRECT Rect;
+    Rect.xLeft = RT_MAX(pCompositor->Rect.xLeft, pEntry->Rect.xLeft);
+    Rect.yTop = RT_MAX(pCompositor->Rect.yTop, pEntry->Rect.yTop);
+    Rect.xRight = RT_MIN(pCompositor->Rect.xRight, pEntry->Rect.xRight);
+    Rect.yBottom = RT_MIN(pCompositor->Rect.yBottom, pEntry->Rect.yBottom);
+    bool fChanged = false;
+
+    if (pfChanged)
+        *pfChanged = false;
+
+    int rc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, 1, &Rect, &fChanged);
+    if (!RT_SUCCESS(rc))
+        WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", rc));
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+    return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags)
+{
+    int rc;
+    uint32_t fChangeFlags = 0;
+    bool fPosChanged = false;
+    RTRECT *paTranslatedRects = NULL;
+    if (pPos)
+    {
+        rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("RegionsAdd: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+            return rc;
+        }
+    }
+
+    if (fPosRelated)
+    {
+        if (!pEntry)
+        {
+            WARN(("Entry is expected to be specified for pos-related regions"));
+            return VERR_INVALID_PARAMETER;
+        }
+
+        if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
+        {
+            paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
+            if (!paTranslatedRects)
+            {
+                WARN(("RTMemAlloc failed"));
+                return VERR_NO_MEMORY;
+            }
+            memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
+            for (uint32_t i = 0; i < cRegions; ++i)
+            {
+                VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
+                paRegions = paTranslatedRects;
+            }
+        }
+    }
+
+    rc = crVrScrCompositorEntryRegionsAdd(pCompositor, pEntry, cRegions, paRegions, ppReplacedScrEntry, &fChangeFlags);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
+        goto done;
+    }
+
+    if ((fPosChanged || (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)) && pEntry)
+    {
+        bool fAdjusted = false;
+        rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, &fAdjusted);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+            goto done;
+        }
+
+        if (fAdjusted)
+        {
+            if (CrVrScrCompositorEntryIsUsed(pEntry))
+            {
+                fChangeFlags &= ~VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
+                fChangeFlags |= VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED;
+            }
+            else
+            {
+                fChangeFlags = 0;
+            }
+        }
+    }
+
+    if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+        fPosChanged = false;
+    else if (ppReplacedScrEntry)
+        *ppReplacedScrEntry = NULL;
+
+    if (pfChangeFlags)
+    {
+        if (fPosChanged)
+        {
+            /* means entry was in list and was moved, so regions changed */
+            *pfChangeFlags = VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
+        }
+        else
+            *pfChangeFlags = fChangeFlags;
+    }
+
+done:
+
+    if (paTranslatedRects)
+        RTMemFree(paTranslatedRects);
+
+    return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect)
+{
+    if (!memcmp(&pEntry->Rect, pRect, sizeof (*pRect)))
+    {
+        return VINF_SUCCESS;
+    }
+    RTPOINT Point = {pRect->xLeft, pRect->yTop};
+    bool fChanged = false;
+    int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, &Point, &fChanged);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crVrScrCompositorEntryPositionSet failed %d", rc));
+        return rc;
+    }
+
+    pEntry->Rect = *pRect;
+
+    if (!CrVrScrCompositorEntryIsUsed(pEntry))
+        return VINF_SUCCESS;
+
+    rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex)
+{
+    if (pEntry->pTex == pTex)
+        return VINF_SUCCESS;
+
+    if (pEntry->pTex)
+        CrTdRelease(pEntry->pTex);
+    if (pTex)
+        CrTdAddRef(pTex);
+    pEntry->pTex = pTex;
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged)
+{
+    /* @todo: the fChanged sate calculation is really rough now, this is enough for now though */
+    bool fChanged = false, fPosChanged = false;
+    bool fWasInList = CrVrScrCompositorEntryIsInList(pEntry);
+    RTRECT *paTranslatedRects = NULL;
+    int rc = CrVrScrCompositorEntryRemove(pCompositor, pEntry);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("RegionsSet: CrVrScrCompositorEntryRemove failed rc %d", rc));
+        return rc;
+    }
+
+    if (pPos)
+    {
+        rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+            return rc;
+        }
+    }
+
+    if (fPosRelated)
+    {
+        if (!pEntry)
+        {
+            WARN(("Entry is expected to be specified for pos-related regions"));
+            return VERR_INVALID_PARAMETER;
+        }
+
+        if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
+        {
+            paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
+            if (!paTranslatedRects)
+            {
+                WARN(("RTMemAlloc failed"));
+                return VERR_NO_MEMORY;
+            }
+            memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
+            for (uint32_t i = 0; i < cRegions; ++i)
+            {
+                VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
+                paRegions = paTranslatedRects;
+            }
+        }
+    }
+
+    rc = crVrScrCompositorEntryRegionsSet(pCompositor, pEntry, cRegions, paRegions, &fChanged);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+        return rc;
+    }
+
+    if (fChanged && CrVrScrCompositorEntryIsUsed(pEntry))
+    {
+        rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+            return rc;
+        }
+    }
+
+    if (pfChanged)
+        *pfChanged = fPosChanged || fChanged || fWasInList;
+
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+    bool fChanged = false;
+    int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
+        return rc;
+    }
+
+    if (fChanged)
+    {
+        CrVrScrCompositorEntrySetChanged(pEntry, true);
+        crVrScrCompositorRectsInvalidate(pCompositor);
+    }
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+    bool fChanged = false;
+    int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
+        return rc;
+    }
+
+    if (fChanged)
+        crVrScrCompositorRectsInvalidate(pCompositor);
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+    CrVrScrCompositorIterInit(pCompositor, &Iter);
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+    int rc = VINF_SUCCESS;
+    bool fChanged = false;
+
+    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+    {
+        bool fTmpChanged = false;
+        int tmpRc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
+        if (RT_SUCCESS(tmpRc))
+        {
+            fChanged |= fTmpChanged;
+        }
+        else
+        {
+            WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+            rc = tmpRc;
+        }
+    }
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+
+    return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+    CrVrScrCompositorIterInit(pCompositor, &Iter);
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+    int rc = VINF_SUCCESS;
+    bool fChanged = false;
+
+    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+    {
+        bool fTmpChanged = false;
+        int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
+        if (RT_SUCCESS(tmpRc))
+        {
+            fChanged |= fTmpChanged;
+        }
+        else
+        {
+            WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+            rc = tmpRc;
+        }
+    }
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+
+    return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos)
+{
+    int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, NULL);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+        return rc;
+    }
+
+    rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("RegionsSet: crVrScrCompositorEntryEnsureRegionsBounds failed rc %d", rc));
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
+{
+	if (CrVrScrCompositorEntryIsUsed(pEntry))
+	{
+		int rc = crVrScrCompositorRectsCheckInit(pCompositor);
+		if (!RT_SUCCESS(rc))
+		{
+			WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
+			return rc;
+		}
+	}
+
+    Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
+
+    *pcRegions = pEntry->cRects;
+    if (ppaSrcRegions)
+        *ppaSrcRegions = pEntry->paSrcRects;
+    if (ppaDstRegions)
+        *ppaDstRegions = pEntry->paDstRects;
+    if (ppaDstUnstretchedRects)
+        *ppaDstUnstretchedRects = pEntry->paDstUnstretchedRects;
+
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+    return CRBLT_FOP_COMBINE(pCompositor->fFlags, pEntry->fFlags);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
+{
+    if (pEntry->fFlags == fFlags)
+        return;
+
+    pEntry->fFlags = fFlags;
+    CrVrScrCompositorEntrySetChanged(pEntry, true);
+}
+
+static void crVrScrCompositorEntryDataCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+    pEntry->cRects = 0;
+    pEntry->paSrcRects = NULL;
+    pEntry->paDstRects = NULL;
+    pEntry->paDstUnstretchedRects = NULL;
+}
+
+static void crVrScrCompositorEntryDataCopy(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pToEntry)
+{
+    pToEntry->cRects = pEntry->cRects;
+    pToEntry->paSrcRects = pEntry->paSrcRects;
+    pToEntry->paDstRects = pEntry->paDstRects;
+    pToEntry->paDstUnstretchedRects = pEntry->paDstUnstretchedRects;
+    crVrScrCompositorEntryDataCleanup(pEntry);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+    if (!VBoxVrCompositorEntryRemove(&pCompositor->Compositor, &pEntry->Ce))
+        return VINF_SUCCESS;
+
+    CrVrScrCompositorEntrySetChanged(pEntry, true);
+    crVrScrCompositorEntryDataCleanup(pEntry);
+
+    crVrScrCompositorRectsInvalidate(pCompositor);
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry)
+{
+    Assert(!CrVrScrCompositorEntryIsUsed(pNewEntry));
+
+    if (!VBoxVrCompositorEntryReplace(&pCompositor->Compositor, &pEntry->Ce, &pNewEntry->Ce))
+        return false;
+
+    CrVrScrCompositorEntrySetChanged(pEntry, true);
+    crVrScrCompositorEntryDataCopy(pEntry, pNewEntry);
+    CrVrScrCompositorEntrySetChanged(pNewEntry, true);
+
+    return true;
+}
+
+static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(const struct VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
+{
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pCEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pEntry);
+
+    CrVrScrCompositorEntrySetChanged(pCEntry, true);
+
+    Assert(!CrVrScrCompositorEntryIsInList(pCEntry));
+
+    if (pReplacingEntry)
+    {
+        PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry);
+        Assert(CrVrScrCompositorEntryIsInList(pCReplacingEntry));
+        pCReplacingEntry->cRects = pCEntry->cRects;
+        pCReplacingEntry->paSrcRects = pCEntry->paSrcRects;
+        pCReplacingEntry->paDstRects = pCEntry->paDstRects;
+        pCReplacingEntry->paDstUnstretchedRects = pCEntry->paDstUnstretchedRects;
+    }
+
+    if (pCEntry->pfnEntryReleased)
+    {
+        PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
+        PVBOXVR_SCR_COMPOSITOR pCConpositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCompositor);
+        pCEntry->pfnEntryReleased(pCConpositor, pCEntry, pCReplacingEntry);
+    }
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect, bool *pfChanged)
+{
+    if (!memcmp(&pCompositor->Rect, pRect, sizeof (pCompositor->Rect)))
+    {
+        if (pfChanged)
+            *pfChanged = false;
+        return VINF_SUCCESS;
+    }
+
+    pCompositor->Rect = *pRect;
+
+    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+    CrVrScrCompositorIterInit(pCompositor, &Iter);
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+    {
+        int rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+            return rc;
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect)
+{
+    memset(pCompositor, 0, sizeof (*pCompositor));
+    VBoxVrCompositorInit(&pCompositor->Compositor, crVrScrCompositorEntryReleasedCB);
+    pCompositor->fFlags = CRBLT_F_LINEAR | CRBLT_F_INVERT_YCOORDS;
+    if (pRect)
+        pCompositor->Rect = *pRect;
+#ifndef IN_RING0
+    pCompositor->StretchX = 1.0;
+    pCompositor->StretchY = 1.0;
+#endif
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
+{
+    /* set changed flag first, while entries are in the list and we have them */
+    CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+    VBoxVrCompositorRegionsClear(&pCompositor->Compositor, pfChanged);
+    crVrScrCompositorRectsInvalidate(pCompositor);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor)
+{
+    CrVrScrCompositorRegionsClear(pCompositor, NULL);
+    if (pCompositor->paDstRects)
+    {
+        RTMemFree(pCompositor->paDstRects);
+        pCompositor->paDstRects = NULL;
+    }
+    if (pCompositor->paSrcRects)
+    {
+        RTMemFree(pCompositor->paSrcRects);
+        pCompositor->paSrcRects = NULL;
+    }
+    if (pCompositor->paDstUnstretchedRects)
+    {
+        RTMemFree(pCompositor->paDstUnstretchedRects);
+        pCompositor->paDstUnstretchedRects = NULL;
+    }
+
+    pCompositor->cRects = 0;
+    pCompositor->cRectsBuffer = 0;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
+{
+    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pCurEntry;
+    CrVrScrCompositorIterInit(pCompositor, &CIter);
+
+    while ((pCurEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+    {
+        CrVrScrCompositorEntrySetChanged(pCurEntry, fChanged);
+    }
+}
+
+#ifndef IN_RING0
+VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
+{
+    if (pCompositor->StretchX == StretchX && pCompositor->StretchY == StretchY)
+        return;
+
+    pCompositor->StretchX = StretchX;
+    pCompositor->StretchY = StretchY;
+    crVrScrCompositorRectsInvalidate(pCompositor);
+    CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+}
+#endif
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
+{
+    int rc = crVrScrCompositorRectsCheckInit(pCompositor);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
+        return rc;
+    }
+
+    Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
+
+    *pcRegions = pCompositor->cRects;
+    if (ppaSrcRegions)
+        *ppaSrcRegions = pCompositor->paSrcRects;
+    if (ppaDstRegions)
+        *ppaDstRegions = pCompositor->paDstRects;
+    if (ppaDstUnstretchedRects)
+        *ppaDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
+
+    return VINF_SUCCESS;
+}
+
+typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
+{
+    PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor;
+    void *pvVisitor;
+} VBOXVR_SCR_COMPOSITOR_VISITOR_CB, *PVBOXVR_SCR_COMPOSITOR_VISITOR_CB;
+
+static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
+{
+    PVBOXVR_SCR_COMPOSITOR_VISITOR_CB pData = (PVBOXVR_SCR_COMPOSITOR_VISITOR_CB)pvVisitor;
+    PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
+    return pData->pfnVisitor(pCompositor, pEntry, pData->pvVisitor);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
+{
+    VBOXVR_SCR_COMPOSITOR_VISITOR_CB Data;
+    Data.pfnVisitor = pfnVisitor;
+    Data.pvVisitor = pvVisitor;
+    VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorVisitCb, &Data);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorClone(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor)
+{
+    /* for simplicity just copy from one to another */
+    CrVrScrCompositorInit(pDstCompositor, CrVrScrCompositorRectGet(pCompositor));
+    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+    CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+    int rc = VINF_SUCCESS;
+    uint32_t cRects;
+    const RTRECT *pRects;
+
+    while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
+    {
+        /* get source rects, that will be non-stretched and entry pos - pased */
+        rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, NULL, &pRects);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
+            return rc;
+        }
+
+        PVBOXVR_SCR_COMPOSITOR_ENTRY pDstEntry = pfnEntryFor(pEntry, pvEntryFor);
+        if (!pDstEntry)
+        {
+            WARN(("pfnEntryFor failed"));
+            return VERR_INVALID_STATE;
+        }
+
+        rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, NULL, cRects, pRects, false, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+            return rc;
+        }
+    }
+
+    return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged)
+{
+    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
+    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+    CrVrScrCompositorIterInit(pCompositor, &CIter);
+    int rc = VINF_SUCCESS;
+    bool fChanged = false;
+
+    while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+    {
+        bool fCurChanged = false;
+
+        rc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pVr, &fCurChanged);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+            break;
+        }
+
+        fChanged |= fCurChanged;
+    }
+
+    if (pfChanged)
+        *pfChanged = fChanged;
+
+    return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged)
+{
+    int rc  = CrVrScrCompositorClone(pCompositor, pDstCompositor, pfnEntryFor, pvEntryFor);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrVrScrCompositorClone failed, rc %d", rc));
+        return rc;
+    }
+
+    rc = CrVrScrCompositorIntersectList(pDstCompositor, pVr, pfChanged);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrVrScrCompositorIntersectList failed, rc %d", rc));
+        CrVrScrCompositorClear(pDstCompositor);
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/util/error.c b/src/VBox/GuestHost/OpenGL/util/error.c
index f95fae1..48fbc57 100644
--- a/src/VBox/GuestHost/OpenGL/util/error.c
+++ b/src/VBox/GuestHost/OpenGL/util/error.c
@@ -498,7 +498,9 @@ DECLEXPORT(void) crDebug(const char *format, ... )
     outputChromiumMessage( output, txt );
 #else
     if (!output
+#ifndef DEBUG_misha
             || output==stderr
+#endif
             )
     {
         LogRel(("%s\n", txt));
diff --git a/src/VBox/GuestHost/OpenGL/util/hash.c b/src/VBox/GuestHost/OpenGL/util/hash.c
index db6c9e3..95f3ab6 100644
--- a/src/VBox/GuestHost/OpenGL/util/hash.c
+++ b/src/VBox/GuestHost/OpenGL/util/hash.c
@@ -217,7 +217,7 @@ void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
          * so we have either intersection */
 
         if (f->min > first)
-            f->min = first; /* first is guarantied not to touch any prev regions */
+            f->min = first; /* first is guaranteed not to touch any prev regions */
 
         newMax = last;
 
@@ -352,8 +352,12 @@ void crHashIdWalkKeys( CRHashIdPool *pool, CRHashIdWalkKeys walkFunc , void *dat
     {
         if (prev)
         {
-            Assert(prev->max < (f->min - 1));
-            walkFunc(prev->max+1, f->min - 1, data);
+            Assert(prev->max < f->min);
+            walkFunc(prev->max+1, f->min - prev->max, data);
+        }
+        else if (f->min > pool->min)
+        {
+            walkFunc(pool->min, f->min - pool->min, data);
         }
 
         prev = f;
@@ -363,7 +367,7 @@ void crHashIdWalkKeys( CRHashIdPool *pool, CRHashIdWalkKeys walkFunc , void *dat
 
     if (prev->max < pool->max)
     {
-        walkFunc(prev->max+1, pool->max, data);
+        walkFunc(prev->max+1, pool->max - prev->max, data);
     }
 }
 
diff --git a/src/VBox/GuestHost/OpenGL/util/htable.cpp b/src/VBox/GuestHost/OpenGL/util/htable.cpp
new file mode 100644
index 0000000..f84804f
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/htable.cpp
@@ -0,0 +1,195 @@
+/* $Id: htable.cpp $ */
+
+/** @file
+ * uint32_t handle to void simple table impl
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include <iprt/cdefs.h>
+#include <iprt/asm.h>
+#include "cr_spu.h"
+#include "cr_vreg.h"
+
+#include "cr_htable.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+#include <iprt/err.h>
+
+VBOXHTABLEDECL(int) CrHTableCreate(PCRHTABLE pTbl, uint32_t cSize)
+{
+    memset(pTbl, 0, sizeof (*pTbl));
+    if (!cSize)
+        return VINF_SUCCESS;
+    pTbl->paData = (void**)RTMemAllocZ(sizeof (pTbl->paData[0]) * cSize);
+    if (pTbl->paData)
+    {
+        pTbl->cSize = cSize;
+        return VINF_SUCCESS;
+    }
+    WARN(("RTMemAllocZ failed!"));
+    return VERR_NO_MEMORY;
+}
+
+VBOXHTABLEDECL(void) CrHTableDestroy(PCRHTABLE pTbl)
+{
+    if (!pTbl->paData)
+        return;
+
+    RTMemFree(pTbl->paData);
+}
+
+int crHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize)
+{
+    Assert(cNewSize > pTbl->cSize);
+    if (cNewSize > pTbl->cSize)
+    {
+        void **pvNewData = (void**)RTMemAllocZ(sizeof (pTbl->paData[0]) * cNewSize);
+        if (!pvNewData)
+        {
+            WARN(("RTMemAllocZ failed for size (%d)", sizeof (pTbl->paData[0]) * cNewSize));
+            return VERR_NO_MEMORY;
+        }
+        memcpy(pvNewData, pTbl->paData, sizeof (pTbl->paData[0]) * pTbl->cSize);
+        RTMemFree(pTbl->paData);
+        pTbl->iNext2Search = pTbl->cSize;
+        pTbl->cSize = cNewSize;
+        pTbl->paData = pvNewData;
+        return VINF_SUCCESS;
+    }
+    else if (cNewSize >= pTbl->cData)
+    {
+        WARN(("not implemented"));
+        return VERR_NOT_IMPLEMENTED;
+    }
+    WARN(("invalid parameter"));
+    return VERR_INVALID_PARAMETER;
+
+}
+
+VBOXHTABLEDECL(int) CrHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize)
+{
+    return crHTableRealloc(pTbl, cNewSize);
+}
+
+VBOXHTABLEDECL(void) CrHTableEmpty(PCRHTABLE pTbl)
+{
+    pTbl->cData = 0;
+    pTbl->iNext2Search = 0;
+    if (pTbl->cSize)
+        memset(pTbl->paData, 0, sizeof (pTbl->paData[0]) * pTbl->cSize);
+}
+
+static void* crHTablePutToSlot(PCRHTABLE pTbl, uint32_t iSlot, void* pvData)
+{
+    Assert(pvData);
+    void* pvOld = pTbl->paData[iSlot];
+    pTbl->paData[iSlot] = pvData;
+    if (!pvOld)
+        ++pTbl->cData;
+    Assert(pTbl->cData <= pTbl->cSize);
+    return pvOld;
+}
+
+VBOXHTABLEDECL(int) CrHTablePutToSlot(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle, void* pvData)
+{
+    if (!pvData)
+    {
+        AssertMsgFailed(("pvData is NULL\n"));
+        return VERR_INVALID_PARAMETER;
+    }
+    uint32_t iIndex = crHTableHandle2Index(hHandle);
+    if (iIndex >= pTbl->cSize)
+    {
+        int rc = crHTableRealloc(pTbl, iIndex + RT_MAX(10, pTbl->cSize/4));
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crHTableRealloc failed rc %d", rc));
+            return CRHTABLE_HANDLE_INVALID;
+        }
+    }
+
+    crHTablePutToSlot(pTbl, iIndex, pvData);
+
+    return VINF_SUCCESS;
+}
+
+VBOXHTABLEDECL(CRHTABLE_HANDLE) CrHTablePut(PCRHTABLE pTbl, void* pvData)
+{
+    if (!pvData)
+    {
+        AssertMsgFailed(("pvData is NULL\n"));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (pTbl->cSize == pTbl->cData)
+    {
+        int rc = crHTableRealloc(pTbl, pTbl->cSize + RT_MAX(10, pTbl->cSize/4));
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crHTableRealloc failed rc %d", rc));
+            return CRHTABLE_HANDLE_INVALID;
+        }
+    }
+    for (uint32_t i = pTbl->iNext2Search; ; ++i, i %= pTbl->cSize)
+    {
+        Assert(i < pTbl->cSize);
+        if (!pTbl->paData[i])
+        {
+            void *pvOld = crHTablePutToSlot(pTbl, i, pvData);
+            Assert(!pvOld);
+            pTbl->iNext2Search = i+1;
+            pTbl->iNext2Search %= pTbl->cSize;
+            return crHTableIndex2Handle(i);
+        }
+    }
+    WARN(("should not be here"));
+    return CRHTABLE_HANDLE_INVALID;
+}
+
+VBOXHTABLEDECL(void*) CrHTableRemove(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle)
+{
+    uint32_t iIndex = crHTableHandle2Index(hHandle);
+    Assert(iIndex < pTbl->cSize);
+    if (iIndex < pTbl->cSize)
+    {
+        void* pvData = pTbl->paData[iIndex];
+        if (pvData)
+        {
+            pTbl->paData[iIndex] = NULL;
+            --pTbl->cData;
+            Assert(pTbl->cData <= pTbl->cSize);
+            pTbl->iNext2Search = iIndex;
+        }
+        return pvData;
+    }
+    WARN(("invalid handle supplied %d", hHandle));
+    return NULL;
+}
+
+VBOXHTABLEDECL(void*) CrHTableGet(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle)
+{
+    uint32_t iIndex = crHTableHandle2Index(hHandle);
+    if (iIndex < pTbl->cSize)
+        return pTbl->paData[iIndex];
+    LOG(("invalid handle supplied %d", hHandle));
+    return NULL;
+}
diff --git a/src/VBox/GuestHost/OpenGL/util/net.c b/src/VBox/GuestHost/OpenGL/util/net.c
index cc2966f..72d9f7a 100644
--- a/src/VBox/GuestHost/OpenGL/util/net.c
+++ b/src/VBox/GuestHost/OpenGL/util/net.c
@@ -993,7 +993,7 @@ crNetRecvFlowControl( CRConnection *conn,   CRMessageFlowControl *msg,
     conn->InstantReclaim( conn, (CRMessage *) msg );
 }
 
-
+#ifdef IN_GUEST
 /**
  * Called by the main receive function when we get a CR_MESSAGE_WRITEBACK
  * message.  Writeback is used to implement glGet*() functions.
@@ -1026,7 +1026,7 @@ crNetRecvReadback( CRMessageReadback *rb, unsigned int len )
     (*writeback)--;
     crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb), payload_len );
 }
-
+#endif
 
 /**
  * This is used by the SPUs that do packing (such as Pack, Tilesort and
@@ -1104,13 +1104,21 @@ crNetDefaultRecv( CRConnection *conn, CRMessage *msg, unsigned int len )
             }
             break;
         case CR_MESSAGE_READ_PIXELS:
-            crError( "Can't handle read pixels" );
+            WARN(( "Can't handle read pixels" ));
             return;
         case CR_MESSAGE_WRITEBACK:
+#ifdef IN_GUEST
             crNetRecvWriteback( &(pRealMsg->writeback) );
+#else
+            WARN(("CR_MESSAGE_WRITEBACK not expected\n"));
+#endif
             return;
         case CR_MESSAGE_READBACK:
+#ifdef IN_GUEST
             crNetRecvReadback( &(pRealMsg->readback), len );
+#else
+            WARN(("CR_MESSAGE_READBACK not expected\n"));
+#endif
             return;
         case CR_MESSAGE_CRUT:
             /* nothing */
@@ -1128,10 +1136,10 @@ crNetDefaultRecv( CRConnection *conn, CRMessage *msg, unsigned int len )
             {
                 char string[128];
                 crBytesToString( string, sizeof(string), msg, len );
-                crError("crNetDefaultRecv: received a bad message: type=%d buf=[%s]\n"
+                WARN(("crNetDefaultRecv: received a bad message: type=%d buf=[%s]\n"
                                 "Did you add a new message type and forget to tell "
                                 "crNetDefaultRecv() about it?\n",
-                                msg->header.type, string );
+                                msg->header.type, string ));
             }
     }
 
diff --git a/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c b/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
index 4afd747..d5d057d 100644
--- a/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
+++ b/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
@@ -195,9 +195,6 @@ typedef enum {
     CR_VBOXHGCM_USERALLOCATED,
     CR_VBOXHGCM_MEMORY,
     CR_VBOXHGCM_MEMORY_BIG
-#ifdef RT_OS_WINDOWS
-    ,CR_VBOXHGCM_DDRAW_SURFACE
-#endif
 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
     ,CR_VBOXHGCM_UHGSMI_BUFFER
 #endif
@@ -220,9 +217,6 @@ typedef struct CRVBOXHGCMBUFFER {
         PVBOXUHGSMI_BUFFER pBuffer;
 #endif
     };
-#ifdef RT_OS_WINDOWS
-    LPDIRECTDRAWSURFACE  pDDS;
-#endif
 } CRVBOXHGCMBUFFER;
 
 #ifndef RT_OS_WINDOWS
@@ -705,92 +699,6 @@ static void *_crVBoxHGCMAlloc(CRConnection *conn)
                         (void *) g_crvboxhgcm.bufpool,
                         (unsigned int)sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size);
 
-#if defined(IN_GUEST) && defined(RT_OS_WINDOWS)
-        /* Try to start DDRAW on guest side */
-        if (!g_crvboxhgcm.pDirectDraw && 0)
-        {
-            HRESULT hr;
-
-            hr = DirectDrawCreate(NULL, &g_crvboxhgcm.pDirectDraw, NULL);
-            if (hr != DD_OK)
-            {
-                crWarning("Failed to create DirectDraw interface (%x)\n", hr);
-                g_crvboxhgcm.pDirectDraw = NULL;
-            }
-            else
-            {
-                hr = IDirectDraw_SetCooperativeLevel(g_crvboxhgcm.pDirectDraw, NULL, DDSCL_NORMAL);
-                if (hr != DD_OK)
-                {
-                    crWarning("Failed to SetCooperativeLevel (%x)\n", hr);
-                    IDirectDraw_Release(g_crvboxhgcm.pDirectDraw);
-                    g_crvboxhgcm.pDirectDraw = NULL;
-                }
-                crDebug("Created DirectDraw and set CooperativeLevel successfully\n");
-            }
-        }
-
-        /* Try to allocate buffer via DDRAW */
-        if (g_crvboxhgcm.pDirectDraw)
-        {
-            DDSURFACEDESC       ddsd;
-            HRESULT             hr;
-            LPDIRECTDRAWSURFACE lpDDS;
-
-            memset(&ddsd, 0, sizeof(ddsd));
-            ddsd.dwSize  = sizeof(ddsd);
-
-            /* @todo DDSCAPS_VIDEOMEMORY ain't working for some reason
-             * also, it would be better to request dwLinearSize but it fails too
-             * ddsd.dwLinearSize = sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size;
-             */
-
-            ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
-            ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
-            /* use 1 byte per pixel format */
-            ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
-            ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-            ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
-            ddsd.ddpfPixelFormat.dwRBitMask = 0xFF;
-            ddsd.ddpfPixelFormat.dwGBitMask = 0;
-            ddsd.ddpfPixelFormat.dwBBitMask = 0;
-            /* request given buffer size, rounded to 1k */
-            ddsd.dwWidth = 1024;
-            ddsd.dwHeight = (sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size + ddsd.dwWidth-1)/ddsd.dwWidth;
-
-            hr = IDirectDraw_CreateSurface(g_crvboxhgcm.pDirectDraw, &ddsd, &lpDDS, NULL);
-            if (hr != DD_OK)
-            {
-                crWarning("Failed to create DirectDraw surface (%x)\n", hr);
-            }
-            else
-            {
-                crDebug("Created DirectDraw surface (%x)\n", lpDDS);
-
-                hr = IDirectDrawSurface_Lock(lpDDS, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
-                if (hr != DD_OK)
-                {
-                    crWarning("Failed to lock DirectDraw surface (%x)\n", hr);
-                    IDirectDrawSurface_Release(lpDDS);
-                }
-                else
-                {
-                    uint32_t cbLocked;
-                    cbLocked = (ddsd.dwFlags & DDSD_LINEARSIZE) ? ddsd.dwLinearSize : ddsd.lPitch*ddsd.dwHeight;
-
-                    crDebug("Locked %d bytes DirectDraw surface\n", cbLocked);
-
-                    buf = (CRVBOXHGCMBUFFER *) ddsd.lpSurface;
-                    CRASSERT(buf);
-                    buf->magic = CR_VBOXHGCM_BUFFER_MAGIC;
-                    buf->kind  = CR_VBOXHGCM_DDRAW_SURFACE;
-                    buf->allocated = cbLocked;
-                    buf->pDDS = lpDDS;
-                }
-            }
-        }
-#endif
-
         /* We're either on host side, or we failed to allocate DDRAW buffer */
         if (!buf)
         {
@@ -800,9 +708,6 @@ static void *_crVBoxHGCMAlloc(CRConnection *conn)
             buf->magic = CR_VBOXHGCM_BUFFER_MAGIC;
             buf->kind  = CR_VBOXHGCM_MEMORY;
             buf->allocated = conn->buffer_size;
-#ifdef RT_OS_WINDOWS
-            buf->pDDS = NULL;
-#endif
         }
     }
 
@@ -944,18 +849,9 @@ crVBoxHGCMWriteReadExact(CRConnection *conn, const void *buf, unsigned int len,
     parms.hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
     parms.hdr.cParms      = SHCRGL_CPARMS_WRITE_READ;
 
-    //if (bufferKind != CR_VBOXHGCM_DDRAW_SURFACE)
-    {
-        parms.pBuffer.type                   = VMMDevHGCMParmType_LinAddr_In;
-        parms.pBuffer.u.Pointer.size         = len;
-        parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
-    }
-    /*else ///@todo it fails badly, have to check why. bird: This fails because buf isn't a physical address?
-    {
-        parms.pBuffer.type                 = VMMDevHGCMParmType_PhysAddr;
-        parms.pBuffer.u.Pointer.size       = len;
-        parms.pBuffer.u.Pointer.u.physAddr = (uintptr_t) buf;
-    }*/
+    parms.pBuffer.type                   = VMMDevHGCMParmType_LinAddr_In;
+    parms.pBuffer.u.Pointer.size         = len;
+    parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
 
     CRASSERT(!conn->pBuffer); //make sure there's no data to process
     parms.pWriteback.type                   = VMMDevHGCMParmType_LinAddr_Out;
@@ -1202,9 +1098,6 @@ static void _crVBoxHGCMFree(CRConnection *conn, void *buf)
     switch (hgcm_buffer->kind)
     {
         case CR_VBOXHGCM_MEMORY:
-#ifdef RT_OS_WINDOWS
-        case CR_VBOXHGCM_DDRAW_SURFACE:
-#endif
 #ifdef CHROMIUM_THREADSAFE
             crLockMutex(&g_crvboxhgcm.mutex);
 #endif
@@ -1283,7 +1176,7 @@ static void _crVBoxHGCMReceiveMessage(CRConnection *conn)
     else
     {
         /* we should NEVER have redir_ptr disabled with HGSMI command now */
-        CRASSERT(!conn->CmdData.pCmd);
+        CRASSERT(!conn->CmdData.pvCmd);
         if ( len <= conn->buffer_size )
         {
             /* put in pre-allocated buffer */
@@ -1298,9 +1191,6 @@ static void _crVBoxHGCMReceiveMessage(CRConnection *conn)
             hgcm_buffer->magic     = CR_VBOXHGCM_BUFFER_MAGIC;
             hgcm_buffer->kind      = CR_VBOXHGCM_MEMORY_BIG;
             hgcm_buffer->allocated = sizeof(CRVBOXHGCMBUFFER) + len;
-# ifdef RT_OS_WINDOWS
-            hgcm_buffer->pDDS      = NULL;
-# endif
         }
 
         hgcm_buffer->len = len;
@@ -2420,9 +2310,6 @@ void crVBoxHGCMInit(CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl, unsigned
 /* Callback function used to free buffer pool entries */
 void crVBoxHGCMBufferFree(void *data)
 {
-#ifdef RT_OS_WINDOWS
-    LPDIRECTDRAWSURFACE lpDDS;
-#endif
     CRVBOXHGCMBUFFER *hgcm_buffer = (CRVBOXHGCMBUFFER *) data;
 
     CRASSERT(hgcm_buffer->magic == CR_VBOXHGCM_BUFFER_MAGIC);
@@ -2432,15 +2319,6 @@ void crVBoxHGCMBufferFree(void *data)
         case CR_VBOXHGCM_MEMORY:
             crFree( hgcm_buffer );
             break;
-#ifdef RT_OS_WINDOWS
-        case CR_VBOXHGCM_DDRAW_SURFACE:
-            lpDDS = hgcm_buffer->pDDS;
-            CRASSERT(lpDDS);
-            IDirectDrawSurface_Unlock(lpDDS, NULL);
-            IDirectDrawSurface_Release(lpDDS);
-            crDebug("DDraw surface freed (%x)\n", lpDDS);
-            break;
-#endif
         case CR_VBOXHGCM_MEMORY_BIG:
             crFree( hgcm_buffer );
             break;
diff --git a/src/VBox/GuestHost/OpenGL/util/vreg.cpp b/src/VBox/GuestHost/OpenGL/util/vreg.cpp
index 74d8068..e2cea3b 100644
--- a/src/VBox/GuestHost/OpenGL/util/vreg.cpp
+++ b/src/VBox/GuestHost/OpenGL/util/vreg.cpp
@@ -21,7 +21,10 @@
 #include <iprt/asm.h>
 
 #include <cr_error.h>
-#define WARN(_m) do { crWarning _m ; } while (0)
+
+#ifdef DEBUG_misha
+# define VBOXVDBG_VR_LAL_DISABLE
+#endif
 
 #ifndef IN_RING0
 #include <iprt/memcache.h>
@@ -118,13 +121,7 @@ DECLINLINE(int) vboxVrLaCreate(LOOKASIDE_LIST_EX *pCache, size_t cbElement)
 # endif
 #endif
 
-#ifdef DEBUG_misha
-//# define VBOXVDBG_VR_LAL_DISABLE
-#endif
-
-#ifndef VBOXVDBG_VR_LAL_DISABLE
 static volatile int32_t g_cVBoxVrInits = 0;
-#endif
 
 static PVBOXVR_REG vboxVrRegCreate()
 {
@@ -801,25 +798,33 @@ static int vboxVrListIntersectNoJoin(PVBOXVR_LIST pList, const VBOXVR_LIST *pLis
 
             if (pReg1)
             {
-                if (!VBoxRectCmp(&pReg1->Rect, pRect2))
+                if (VBoxRectCovers(pRect2, &RegRect1))
                 {
-                    /* no change, and we can break the iteration here */
+                    /* no change */
 
                     /* zero up the pReg1 to mark it as intersected (see the code after this inner loop) */
                     pReg1 = NULL;
-                    break;
+
+                    if (!VBoxRectCmp(pRect2, &RegRect1))
+                        break; /* and we can break the iteration here */
                 }
-                /* @todo: this can have false-alarming sometimes if the separated rects will then be joind into the original rect,
-                 * so far this should not be a problem for VReg clients, so keep it this way for now  */
-                fChanged = true;
+                else
+                {
+                    /*just to ensure the VBoxRectCovers is true for equal rects */
+                    Assert(VBoxRectCmp(pRect2, &RegRect1));
 
-                /* re-use the reg entry */
-                vboxVrListRegRemove(pList, pReg1);
-                VBoxRectIntersect(&pReg1->Rect, pRect2);
-                Assert(!VBoxRectIsZero(&pReg1->Rect));
+                    /* @todo: this can have false-alarming sometimes if the separated rects will then be joind into the original rect,
+                     * so far this should not be a problem for VReg clients, so keep it this way for now  */
+                    fChanged = true;
 
-                vboxVrListRegAddOrder(pList, pMemberEntry, pReg1);
-                pReg1 = NULL;
+                    /* re-use the reg entry */
+                    vboxVrListRegRemove(pList, pReg1);
+                    VBoxRectIntersect(&pReg1->Rect, pRect2);
+                    Assert(!VBoxRectIsZero(&pReg1->Rect));
+
+                    vboxVrListRegAddOrder(pList, pMemberEntry, pReg1);
+                    pReg1 = NULL;
+                }
             }
             else
             {
@@ -1009,7 +1014,7 @@ VBOXVREGDECL(int) VBoxVrListRectsAdd(PVBOXVR_LIST pList, uint32_t cRects, const
         {
             PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
 
-            if (VBoxRectIsCoveres(&pReg1->Rect, &aRects[i]))
+            if (VBoxRectCovers(&pReg1->Rect, &aRects[i]))
             {
                 cCovered++;
                 break;
@@ -1157,7 +1162,7 @@ VBOXVREGDECL(int) VBoxVrListClone(const VBOXVR_LIST *pList, VBOXVR_LIST *pDstLis
     const VBOXVR_REG *pReg;
     RTListForEach(&pList->ListHead, pReg, const VBOXVR_REG, ListEntry)
     {
-        PVBOXVR_REG pDstReg = (PVBOXVR_REG)vboxVrRegLaAlloc(g_VBoxVrLookasideList);
+        PVBOXVR_REG pDstReg = vboxVrRegCreate();
         if (!pDstReg)
         {
             WARN(("vboxVrRegLaAlloc failed"));
@@ -1212,7 +1217,7 @@ DECLINLINE(void) vboxVrCompositorEntryRelease(PVBOXVR_COMPOSITOR pCompositor, PV
         pCompositor->pfnEntryReleased(pCompositor, pEntry, pReplacingEntry);
 }
 
-DECLINLINE(void) vboxVrCompositorEntryAcquire(PVBOXVR_COMPOSITOR_ENTRY pEntry)
+DECLINLINE(void) vboxVrCompositorEntryAddRef(PVBOXVR_COMPOSITOR_ENTRY pEntry)
 {
     ++pEntry->cRefs;
 }
@@ -1220,7 +1225,7 @@ DECLINLINE(void) vboxVrCompositorEntryAcquire(PVBOXVR_COMPOSITOR_ENTRY pEntry)
 DECLINLINE(void) vboxVrCompositorEntryAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry)
 {
     RTListPrepend(&pCompositor->List, &pEntry->Node);
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 }
 
 DECLINLINE(void) vboxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
@@ -1239,7 +1244,7 @@ static void vboxVrCompositorEntryReplace(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR
     pEntry->Node.pNext = NULL;
     pEntry->Node.pPrev = NULL;
 
-    vboxVrCompositorEntryAcquire(pReplacingEntry);
+    vboxVrCompositorEntryAddRef(pReplacingEntry);
     vboxVrCompositorEntryRelease(pCompositor, pEntry, pReplacingEntry);
 }
 
@@ -1256,7 +1261,7 @@ VBOXVREGDECL(bool) VBoxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, P
     if (!VBoxVrCompositorEntryIsInList(pEntry))
         return false;
 
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     VBoxVrListClear(&pEntry->Vr);
     vboxVrCompositorEntryRemove(pCompositor, pEntry, NULL);
@@ -1277,7 +1282,7 @@ VBOXVREGDECL(bool) VBoxVrCompositorEntryReplace(PVBOXVR_COMPOSITOR pCompositor,
 static int vboxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT * paRects, bool *pfChanged)
 {
     bool fChanged;
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     int rc = VBoxVrListRectsSubst(&pEntry->Vr, cRects, paRects, &fChanged);
     if (RT_SUCCESS(rc))
@@ -1299,12 +1304,12 @@ static int vboxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVB
 
 VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, PVBOXVR_COMPOSITOR_ENTRY *ppReplacedEntry, uint32_t *pfChangeFlags)
 {
-    bool fOthersChanged = false, fCurChanged = false, fEntryChanged = false, fEntryWasInList = false, fEntryReplaced = false;
-    PVBOXVR_COMPOSITOR_ENTRY pCur, pNext;
+    bool fOthersChanged = false, fCurChanged = false, fEntryChanged = false, fEntryWasInList = false;
+    PVBOXVR_COMPOSITOR_ENTRY pCur, pNext, pReplacedEntry = NULL;
     int rc = VINF_SUCCESS;
 
     if (pEntry)
-        vboxVrCompositorEntryAcquire(pEntry);
+        vboxVrCompositorEntryAddRef(pEntry);
 
     if (!cRects)
     {
@@ -1347,19 +1352,16 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsAdd(PVBOXVR_COMPOSITOR pCompositor
     RTListForEachSafe(&pCompositor->List, pCur, pNext, VBOXVR_COMPOSITOR_ENTRY, Node)
     {
         Assert(!VBoxVrListIsEmpty(&pCur->Vr));
-        if (pCur == pEntry)
-        {
-            Assert(fEntryWasInList);
-        }
-        else
+        if (pCur != pEntry)
         {
             if (pEntry && !VBoxVrListCmp(&pCur->Vr, &pEntry->Vr))
             {
                 VBoxVrListClear(&pCur->Vr);
+                pReplacedEntry = pCur;
+                vboxVrCompositorEntryAddRef(pReplacedEntry);
                 vboxVrCompositorEntryRemove(pCompositor, pCur, pEntry);
                 if (ppReplacedEntry)
-                    *ppReplacedEntry = pCur;
-                fEntryReplaced = true;
+                    *ppReplacedEntry = pReplacedEntry;
                 break;
             }
             else
@@ -1388,24 +1390,33 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsAdd(PVBOXVR_COMPOSITOR pCompositor
         vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
     }
 
-    if (pfChangeFlags)
+    uint32_t fFlags = 0;
+    if (fOthersChanged)
     {
-        uint32_t fFlags = 0;
-        if (fOthersChanged)
-            fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
-        else if (fEntryReplaced)
-        {
-            Assert(fEntryChanged);
-            fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
-        }
-        else if (fEntryChanged)
-            fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED;
+        Assert(!pReplacedEntry);
+        fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
+    }
+    else if (pReplacedEntry)
+    {
+        vboxVrCompositorEntryRelease(pCompositor, pReplacedEntry, pEntry);
+        Assert(fEntryChanged);
+        fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
+    }
+    else if (fEntryChanged)
+    {
+        Assert(!pReplacedEntry);
+        fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED;
+    }
+    else
+    {
+        Assert(!pReplacedEntry);
+    }
 
-        if (!fEntryWasInList)
-            Assert(fEntryChanged);
+    if (!fEntryWasInList)
+        Assert(fEntryChanged);
 
+    if (pfChangeFlags)
         *pfChangeFlags = fFlags;
-    }
 
     return VINF_SUCCESS;
 }
@@ -1420,7 +1431,7 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pComposit
         return VERR_INVALID_PARAMETER;
     }
 
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     if (VBoxVrListIsEmpty(&pEntry->Vr))
     {
@@ -1428,7 +1439,6 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pComposit
             *pfChanged = false;
         vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
         return VINF_SUCCESS;
-
     }
 
     int rc = vboxVrCompositorEntryRegionsSubst(pCompositor, pEntry, cRects, paRects, pfChanged);
@@ -1450,7 +1460,7 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSet(PVBOXVR_COMPOSITOR pCompositor
         return VERR_INVALID_PARAMETER;
     }
 
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     bool fChanged = false, fCurChanged = false;
     uint32_t fChangeFlags = 0;
@@ -1478,7 +1488,7 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersect(PVBOXVR_COMPOSITOR pComposi
     int rc = VINF_SUCCESS;
     bool fChanged = false;
 
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     if (VBoxVrCompositorEntryIsInList(pEntry))
     {
@@ -1510,7 +1520,7 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersect(PVBOXVR_COMPOSITOR pComp
     int rc = VINF_SUCCESS;
     bool fChanged = false;
 
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     if (VBoxVrCompositorEntryIsInList(pEntry))
     {
@@ -1605,7 +1615,7 @@ VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsTranslate(PVBOXVR_COMPOSITOR pComp
         return VERR_INVALID_PARAMETER;
     }
 
-    vboxVrCompositorEntryAcquire(pEntry);
+    vboxVrCompositorEntryAddRef(pEntry);
 
     if ((!x && !y)
             || !VBoxVrCompositorEntryIsInList(pEntry))
@@ -1680,927 +1690,3 @@ VBOXVREGDECL(void) VBoxVrCompositorVisit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOX
             return;
     }
 }
-
-
-
-#define VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED UINT32_MAX
-
-static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects)
-{
-    Assert(cRects);
-
-    if (pCompositor->cRectsBuffer >= cRects)
-    {
-        pCompositor->cRects = cRects;
-        return VINF_SUCCESS;
-    }
-
-    if (pCompositor->cRectsBuffer)
-    {
-        Assert(pCompositor->paSrcRects);
-        RTMemFree(pCompositor->paSrcRects);
-        pCompositor->paSrcRects = NULL;
-        Assert(pCompositor->paDstRects);
-        RTMemFree(pCompositor->paDstRects);
-        pCompositor->paDstRects = NULL;
-        Assert(pCompositor->paDstUnstretchedRects);
-        RTMemFree(pCompositor->paDstUnstretchedRects);
-        pCompositor->paDstUnstretchedRects = NULL;
-    }
-    else
-    {
-        Assert(!pCompositor->paSrcRects);
-        Assert(!pCompositor->paDstRects);
-        Assert(!pCompositor->paDstUnstretchedRects);
-    }
-
-    pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paSrcRects) * cRects);
-    if (pCompositor->paSrcRects)
-    {
-        pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstRects) * cRects);
-        if (pCompositor->paDstRects)
-        {
-            pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstUnstretchedRects) * cRects);
-            if (pCompositor->paDstUnstretchedRects)
-            {
-                pCompositor->cRects = cRects;
-                pCompositor->cRectsBuffer = cRects;
-                return VINF_SUCCESS;
-            }
-
-            RTMemFree(pCompositor->paDstRects);
-            pCompositor->paDstRects = NULL;
-        }
-        else
-        {
-            WARN(("RTMemAlloc failed!"));
-        }
-        RTMemFree(pCompositor->paSrcRects);
-        pCompositor->paSrcRects = NULL;
-    }
-    else
-    {
-        WARN(("RTMemAlloc failed!"));
-    }
-
-    pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
-    pCompositor->cRectsBuffer = 0;
-
-    return VERR_NO_MEMORY;
-}
-
-static void crVrScrCompositorRectsInvalidate(PVBOXVR_SCR_COMPOSITOR pCompositor)
-{
-    pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
-}
-
-static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor)
-{
-    uint32_t* pCounter = (uint32_t*)pvVisitor;
-    Assert(VBoxVrListRectsCount(&pEntry->Vr));
-    *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
-    return true;
-}
-
-typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
-{
-    PRTRECT paSrcRects;
-    PRTRECT paDstRects;
-    PRTRECT paDstUnstretchedRects;
-    uint32_t cRects;
-} VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER, *PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER;
-
-static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
-{
-    PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER pData = (PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER)pvVisitor;
-    PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
-    pEntry->paSrcRects = pData->paSrcRects;
-    pEntry->paDstRects = pData->paDstRects;
-    pEntry->paDstUnstretchedRects = pData->paDstUnstretchedRects;
-    uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
-    Assert(cRects);
-    Assert(cRects <= pData->cRects);
-    int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstUnstretchedRects);
-    AssertRC(rc);
-
-    if (!pEntry->Pos.x && !pEntry->Pos.y)
-    {
-        memcpy(pEntry->paSrcRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paSrcRects));
-    }
-    else
-    {
-        for (uint32_t i = 0; i < cRects; ++i)
-        {
-            pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstUnstretchedRects[i].xLeft - pEntry->Pos.x));
-            pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstUnstretchedRects[i].yTop - pEntry->Pos.y));
-            pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Pos.x));
-            pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Pos.y));
-        }
-    }
-
-#ifndef IN_RING0
-    if (pCompositor->StretchX != 1. || pCompositor->StretchY != 1.)
-    {
-        for (uint32_t i = 0; i < cRects; ++i)
-        {
-            if (pCompositor->StretchX != 1.)
-            {
-                pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
-                pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
-            }
-            if (pCompositor->StretchY != 1.)
-            {
-                pEntry->paDstRects[i].yTop = (int32_t)(pEntry->paDstUnstretchedRects[i].yTop * pCompositor->StretchY);
-                pEntry->paDstRects[i].yBottom = (int32_t)(pEntry->paDstUnstretchedRects[i].yBottom * pCompositor->StretchY);
-            }
-        }
-    }
-    else
-#endif
-    {
-        memcpy(pEntry->paDstRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paDstUnstretchedRects));
-    }
-
-#if 0//ndef IN_RING0
-    bool canZeroX = (pCompositor->StretchX < 1.);
-    bool canZeroY = (pCompositor->StretchY < 1.);
-    if (canZeroX && canZeroY)
-    {
-        /* filter out zero rectangles*/
-        uint32_t iOrig, iNew;
-        for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
-        {
-            PRTRECT pOrigRect = &pEntry->paDstRects[iOrig];
-            if (pOrigRect->xLeft != pOrigRect->xRight
-                    && pOrigRect->yTop != pOrigRect->yBottom)
-                continue;
-
-            if (iNew != iOrig)
-            {
-                PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
-                *pNewRect = *pOrigRect;
-            }
-
-            ++iNew;
-        }
-
-        Assert(iNew <= iOrig);
-
-        uint32_t cDiff = iOrig - iNew;
-
-        if (cDiff)
-        {
-            pCompositor->cRects -= cDiff;
-            cRects -= cDiff;
-        }
-    }
-#endif
-
-    pEntry->cRects = cRects;
-    pData->paDstRects += cRects;
-    pData->paSrcRects += cRects;
-    pData->paDstUnstretchedRects += cRects;
-    pData->cRects -= cRects;
-    return true;
-}
-
-static int crVrScrCompositorRectsCheckInit(PVBOXVR_SCR_COMPOSITOR pCompositor)
-{
-    if (pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED)
-        return VINF_SUCCESS;
-
-    uint32_t cRects = 0;
-    VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsCounterCb, &cRects);
-
-    if (!cRects)
-    {
-        pCompositor->cRects = 0;
-        return VINF_SUCCESS;
-    }
-
-    int rc = crVrScrCompositorRectsAssignBuffer(pCompositor, cRects);
-    if (!RT_SUCCESS(rc))
-        return rc;
-
-    VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER AssignerData;
-    AssignerData.paSrcRects = pCompositor->paSrcRects;
-    AssignerData.paDstRects = pCompositor->paDstRects;
-    AssignerData.paDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
-    AssignerData.cRects = pCompositor->cRects;
-    VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsAssignerCb, &AssignerData);
-    Assert(!AssignerData.cRects);
-    return VINF_SUCCESS;
-}
-
-
-static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangedFlags)
-{
-    uint32_t fChangedFlags = 0;
-    PVBOXVR_COMPOSITOR_ENTRY pReplacedEntry;
-    int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions, paRegions, &pReplacedEntry, &fChangedFlags);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
-        return rc;
-    }
-
-    VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
-
-    if (fChangedFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
-    {
-        crVrScrCompositorRectsInvalidate(pCompositor);
-    }
-    else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
-    {
-        Assert(!CrVrScrCompositorEntryIsInList(pReplacedScrEntry));
-        Assert(CrVrScrCompositorEntryIsInList(pEntry));
-        pEntry->cRects = pReplacedScrEntry->cRects;
-        pEntry->paSrcRects = pReplacedScrEntry->paSrcRects;
-        pEntry->paDstRects = pReplacedScrEntry->paDstRects;
-        pEntry->paDstUnstretchedRects = pReplacedScrEntry->paDstUnstretchedRects;
-    }
-
-    if (fChangedFlags & VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED)
-    {
-        CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
-    }
-    else if ((fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED) && pEntry)
-    {
-        CrVrScrCompositorEntrySetChanged(pEntry, true);
-    }
-
-    if (pfChangedFlags)
-        *pfChangedFlags = fChangedFlags;
-
-    if (ppReplacedScrEntry)
-        *ppReplacedScrEntry = pReplacedScrEntry;
-
-    return VINF_SUCCESS;
-}
-
-static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
-{
-    bool fChanged;
-    CrVrScrCompositorEntryIsInList(pEntry);
-    int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc));
-        return rc;
-    }
-
-    if (fChanged)
-    {
-        CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
-        if (!CrVrScrCompositorEntryIsInList(pEntry))
-        {
-            pEntry->cRects = 0;
-            pEntry->paSrcRects = NULL;
-            pEntry->paDstRects = NULL;
-            pEntry->paDstUnstretchedRects = NULL;
-        }
-        crVrScrCompositorRectsInvalidate(pCompositor);
-    }
-
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-    return VINF_SUCCESS;
-}
-
-static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, bool *pfChanged)
-{
-    if (pfChanged)
-        *pfChanged = false;
-    if (pEntry && (pEntry->Pos.x != pPos->x || pEntry->Pos.y != pPos->y))
-    {
-        if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
-        {
-            int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Pos.x, pPos->y - pEntry->Pos.y, pfChanged);
-            if (!RT_SUCCESS(rc))
-            {
-                WARN(("VBoxVrCompositorEntryRegionsTranslate failed rc %d", rc));
-                return rc;
-            }
-
-            crVrScrCompositorRectsInvalidate(pCompositor);
-        }
-
-        pEntry->Pos = *pPos;
-        CrVrScrCompositorEntrySetChanged(pEntry, true);
-
-        if (pfChanged)
-            *pfChanged = true;
-    }
-    return VINF_SUCCESS;
-}
-
-static int crVrScrCompositorEntryEnsureRegionsInTex(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool *pfChanged)
-{
-    RTRECT Rect;
-    Rect.xLeft = pEntry->Pos.x;
-    Rect.yTop = pEntry->Pos.y;
-    Rect.xRight = pEntry->Pos.x + pEntry->Tex.width;
-    Rect.yBottom = pEntry->Pos.y + pEntry->Tex.height;
-    bool fChanged = false;
-
-    if (pfChanged)
-        *pfChanged = false;
-
-    int rc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, 1, &Rect, &fChanged);
-    if (!RT_SUCCESS(rc))
-        WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", rc));
-
-    if (fChanged)
-    {
-        CrVrScrCompositorEntrySetChanged(pEntry, true);
-        crVrScrCompositorRectsInvalidate(pCompositor);
-    }
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-    return rc;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags)
-{
-    int rc;
-    uint32_t fChangeFlags = 0;
-    bool fPosChanged = false;
-    RTRECT *paTranslatedRects = NULL;
-    if (pPos)
-    {
-        rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
-        if (!RT_SUCCESS(rc))
-        {
-            WARN(("RegionsAdd: crVrScrCompositorEntryPositionSet failed rc %d", rc));
-            return rc;
-        }
-    }
-
-    if (fPosRelated)
-    {
-        if (!pEntry)
-        {
-            WARN(("Entry is expected to be specified for pos-related regions"));
-            return VERR_INVALID_PARAMETER;
-        }
-
-        if (cRegions && (pEntry->Pos.x || pEntry->Pos.y))
-        {
-            paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
-            if (!paTranslatedRects)
-            {
-                WARN(("RTMemAlloc failed"));
-                return VERR_NO_MEMORY;
-            }
-            memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
-            for (uint32_t i = 0; i < cRegions; ++i)
-            {
-                VBoxRectTranslate(&paTranslatedRects[i], pEntry->Pos.x, pEntry->Pos.y);
-                paRegions = paTranslatedRects;
-            }
-        }
-    }
-
-    rc = crVrScrCompositorEntryRegionsAdd(pCompositor, pEntry, cRegions, paRegions, ppReplacedScrEntry, &fChangeFlags);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("crVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
-        goto done;
-    }
-
-    if ((fPosChanged || (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)) && pEntry)
-    {
-        bool fAdjusted = false;
-        rc = crVrScrCompositorEntryEnsureRegionsInTex(pCompositor, pEntry, &fAdjusted);
-        if (!RT_SUCCESS(rc))
-        {
-            WARN(("crVrScrCompositorEntryEnsureRegionsInTex failed, rc %d", rc));
-            goto done;
-        }
-
-        if (fAdjusted)
-        {
-            fChangeFlags &= ~VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
-            fChangeFlags |= VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED;
-        }
-    }
-
-    if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
-        fPosChanged = false;
-    else if (ppReplacedScrEntry)
-        *ppReplacedScrEntry = NULL;
-
-    if (pfChangeFlags)
-    {
-        if (fPosChanged)
-        {
-            /* means entry was in list and was moved, so regions changed */
-            *pfChangeFlags = VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
-        }
-        else
-            *pfChangeFlags = fChangeFlags;
-    }
-
-done:
-
-    if (paTranslatedRects)
-        RTMemFree(paTranslatedRects);
-
-    return rc;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryTexUpdate(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_TEXTURE *pTex)
-{
-    bool fCompositorChanged = CrVrScrCompositorEntryIsUsed(pEntry) && (pEntry->Tex.width != pTex->width || pEntry->Tex.height != pTex->height);
-    pEntry->Tex = *pTex;
-    CrVrScrCompositorEntrySetChanged(pEntry, true);
-    if (fCompositorChanged)
-    {
-        int rc = crVrScrCompositorEntryEnsureRegionsInTex(pCompositor, pEntry, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            WARN(("crVrScrCompositorEntryEnsureRegionsInTex failed rc %d", rc));
-            return rc;
-        }
-    }
-    return VINF_SUCCESS;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged)
-{
-    /* @todo: the fChanged sate calculation is really rough now, this is enough for now though */
-    bool fChanged = false, fPosChanged = false;
-    bool fWasInList = CrVrScrCompositorEntryIsInList(pEntry);
-    RTRECT *paTranslatedRects = NULL;
-    int rc = CrVrScrCompositorEntryRemove(pCompositor, pEntry);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("RegionsSet: CrVrScrCompositorEntryRemove failed rc %d", rc));
-        return rc;
-    }
-
-    if (pPos)
-    {
-        rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
-        if (!RT_SUCCESS(rc))
-        {
-            WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
-            return rc;
-        }
-    }
-
-    if (fPosRelated)
-    {
-        if (!pEntry)
-        {
-            WARN(("Entry is expected to be specified for pos-related regions"));
-            return VERR_INVALID_PARAMETER;
-        }
-
-        if (cRegions && (pEntry->Pos.x || pEntry->Pos.y))
-        {
-            paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
-            if (!paTranslatedRects)
-            {
-                WARN(("RTMemAlloc failed"));
-                return VERR_NO_MEMORY;
-            }
-            memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
-            for (uint32_t i = 0; i < cRegions; ++i)
-            {
-                VBoxRectTranslate(&paTranslatedRects[i], pEntry->Pos.x, pEntry->Pos.y);
-                paRegions = paTranslatedRects;
-            }
-        }
-    }
-
-    rc = crVrScrCompositorEntryRegionsSet(pCompositor, pEntry, cRegions, paRegions, &fChanged);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("crVrScrCompositorEntryRegionsSet failed, rc %d", rc));
-        return rc;
-    }
-
-    if (fChanged && CrVrScrCompositorEntryIsUsed(pEntry))
-    {
-        rc = crVrScrCompositorEntryEnsureRegionsInTex(pCompositor, pEntry, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            WARN(("crVrScrCompositorEntryEnsureRegionsInTex failed, rc %d", rc));
-            return rc;
-        }
-    }
-
-    if (pfChanged)
-        *pfChanged = fPosChanged || fChanged || fWasInList;
-
-    return VINF_SUCCESS;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
-{
-    bool fChanged = false;
-    int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
-        return rc;
-    }
-
-    if (fChanged)
-    {
-        CrVrScrCompositorEntrySetChanged(pEntry, true);
-        crVrScrCompositorRectsInvalidate(pCompositor);
-    }
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-
-    return VINF_SUCCESS;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
-{
-    bool fChanged = false;
-    int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
-        return rc;
-    }
-
-    if (fChanged)
-    {
-        CrVrScrCompositorEntrySetChanged(pEntry, true);
-        crVrScrCompositorRectsInvalidate(pCompositor);
-    }
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-
-    return VINF_SUCCESS;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    CrVrScrCompositorIterInit(pCompositor, &Iter);
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    int rc = VINF_SUCCESS;
-    bool fChanged = false;
-
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        bool fTmpChanged = false;
-        int tmpRc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
-        if (RT_SUCCESS(tmpRc))
-        {
-            fChanged |= fTmpChanged;
-        }
-        else
-        {
-            WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
-            rc = tmpRc;
-        }
-    }
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-
-    return rc;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    CrVrScrCompositorIterInit(pCompositor, &Iter);
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    int rc = VINF_SUCCESS;
-    bool fChanged = false;
-
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        bool fTmpChanged = false;
-        int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
-        if (RT_SUCCESS(tmpRc))
-        {
-            fChanged |= fTmpChanged;
-        }
-        else
-        {
-            WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
-            rc = tmpRc;
-        }
-    }
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-
-    return rc;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos)
-{
-    int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, NULL);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
-        return rc;
-    }
-    return VINF_SUCCESS;
-}
-
-/* regions are valid until the next CrVrScrCompositor call */
-VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
-{
-    int rc = crVrScrCompositorRectsCheckInit(pCompositor);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
-        return rc;
-    }
-
-    Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
-
-    *pcRegions = pEntry->cRects;
-    if (ppaSrcRegions)
-        *ppaSrcRegions = pEntry->paSrcRects;
-    if (ppaDstRegions)
-        *ppaDstRegions = pEntry->paDstRects;
-    if (ppaDstUnstretchedRects)
-        *ppaDstUnstretchedRects = pEntry->paDstUnstretchedRects;
-
-    return VINF_SUCCESS;
-}
-
-VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
-{
-    return CRBLT_FOP_COMBINE(pCompositor->fFlags, pEntry->fFlags);
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
-{
-    if (pEntry->fFlags == fFlags)
-        return;
-
-    pEntry->fFlags = fFlags;
-    CrVrScrCompositorEntrySetChanged(pEntry, true);
-}
-
-static void crVrScrCompositorEntryDataCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
-{
-    pEntry->cRects = 0;
-    pEntry->paSrcRects = NULL;
-    pEntry->paDstRects = NULL;
-    pEntry->paDstUnstretchedRects = NULL;
-}
-
-static void crVrScrCompositorEntryDataCopy(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pToEntry)
-{
-    pToEntry->cRects = pEntry->cRects;
-    pToEntry->paSrcRects = pEntry->paSrcRects;
-    pToEntry->paDstRects = pEntry->paDstRects;
-    pToEntry->paDstUnstretchedRects = pEntry->paDstUnstretchedRects;
-    crVrScrCompositorEntryDataCleanup(pEntry);
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
-{
-    if (!VBoxVrCompositorEntryRemove(&pCompositor->Compositor, &pEntry->Ce))
-        return VINF_SUCCESS;
-
-    CrVrScrCompositorEntrySetChanged(pEntry, true);
-    crVrScrCompositorEntryDataCleanup(pEntry);
-
-    crVrScrCompositorRectsInvalidate(pCompositor);
-    return VINF_SUCCESS;
-}
-
-VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry)
-{
-    Assert(!CrVrScrCompositorEntryIsUsed(pNewEntry));
-
-    if (!VBoxVrCompositorEntryReplace(&pCompositor->Compositor, &pEntry->Ce, &pNewEntry->Ce))
-        return false;
-
-    CrVrScrCompositorEntrySetChanged(pEntry, true);
-    crVrScrCompositorEntryDataCopy(pEntry, pNewEntry);
-    CrVrScrCompositorEntrySetChanged(pNewEntry, true);
-
-    return true;
-}
-
-static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(const struct VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
-{
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pCEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pEntry);
-    CrVrScrCompositorEntrySetChanged(pCEntry, true);
-
-    if (pCEntry->pfnEntryReleased)
-    {
-        PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
-        PVBOXVR_SCR_COMPOSITOR pCConpositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCompositor);
-        pCEntry->pfnEntryReleased(pCConpositor, pCEntry, pCReplacingEntry);
-    }
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor)
-{
-    memset(pCompositor, 0, sizeof (*pCompositor));
-    VBoxVrCompositorInit(&pCompositor->Compositor, crVrScrCompositorEntryReleasedCB);
-    pCompositor->fFlags = CRBLT_F_LINEAR | CRBLT_F_INVERT_YCOORDS;
-#ifndef IN_RING0
-    pCompositor->StretchX = 1.0;
-    pCompositor->StretchY = 1.0;
-#endif
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
-{
-    /* set changed flag first, while entries are in the list and we have them */
-    CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
-    VBoxVrCompositorRegionsClear(&pCompositor->Compositor, pfChanged);
-    crVrScrCompositorRectsInvalidate(pCompositor);
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor)
-{
-    CrVrScrCompositorRegionsClear(pCompositor, NULL);
-    if (pCompositor->paDstRects)
-    {
-        RTMemFree(pCompositor->paDstRects);
-        pCompositor->paDstRects = NULL;
-    }
-    if (pCompositor->paSrcRects)
-    {
-        RTMemFree(pCompositor->paSrcRects);
-        pCompositor->paSrcRects = NULL;
-    }
-    if (pCompositor->paDstUnstretchedRects)
-    {
-        RTMemFree(pCompositor->paDstUnstretchedRects);
-        pCompositor->paDstUnstretchedRects = NULL;
-    }
-
-    pCompositor->cRects = 0;
-    pCompositor->cRectsBuffer = 0;
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pCurEntry;
-    CrVrScrCompositorIterInit(pCompositor, &CIter);
-
-    while ((pCurEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
-    {
-        CrVrScrCompositorEntrySetChanged(pCurEntry, fChanged);
-    }
-}
-
-#ifndef IN_RING0
-VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
-{
-    if (pCompositor->StretchX == StretchX && pCompositor->StretchY == StretchY)
-        return;
-
-    pCompositor->StretchX = StretchX;
-    pCompositor->StretchY = StretchY;
-    crVrScrCompositorRectsInvalidate(pCompositor);
-    CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
-}
-#endif
-
-/* regions are valid until the next CrVrScrCompositor call */
-VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
-{
-    int rc = crVrScrCompositorRectsCheckInit(pCompositor);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
-        return rc;
-    }
-
-    Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
-
-    *pcRegions = pCompositor->cRects;
-    if (ppaSrcRegions)
-        *ppaSrcRegions = pCompositor->paSrcRects;
-    if (ppaDstRegions)
-        *ppaDstRegions = pCompositor->paDstRects;
-    if (ppaDstUnstretchedRects)
-        *ppaDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
-
-    return VINF_SUCCESS;
-}
-
-typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
-{
-    PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor;
-    void *pvVisitor;
-} VBOXVR_SCR_COMPOSITOR_VISITOR_CB, *PVBOXVR_SCR_COMPOSITOR_VISITOR_CB;
-
-static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
-{
-    PVBOXVR_SCR_COMPOSITOR_VISITOR_CB pData = (PVBOXVR_SCR_COMPOSITOR_VISITOR_CB)pvVisitor;
-    PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
-    return pData->pfnVisitor(pCompositor, pEntry, pData->pvVisitor);
-}
-
-VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
-{
-    VBOXVR_SCR_COMPOSITOR_VISITOR_CB Data;
-    Data.pfnVisitor = pfnVisitor;
-    Data.pvVisitor = pvVisitor;
-    VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorVisitCb, &Data);
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorClone(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor)
-{
-    /* for simplicity just copy from one to another */
-    CrVrScrCompositorInit(pDstCompositor);
-    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    CrVrScrCompositorIterInit(pCompositor, &CIter);
-    int rc = VINF_SUCCESS;
-    uint32_t cRects;
-    const RTRECT *pRects;
-
-    while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
-    {
-        /* get source rects, that will be non-stretched and entry pos - pased */
-        rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, NULL, &pRects);
-        if (!RT_SUCCESS(rc))
-        {
-            WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
-            return rc;
-        }
-
-        PVBOXVR_SCR_COMPOSITOR_ENTRY pDstEntry = pfnEntryFor(pEntry, pvEntryFor);
-        if (!pDstEntry)
-        {
-            WARN(("pfnEntryFor failed"));
-            return VERR_INVALID_STATE;
-        }
-
-        rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, CrVrScrCompositorEntryPosGet(pEntry), cRects, pRects, false, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
-            return rc;
-        }
-    }
-
-    return rc;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    CrVrScrCompositorIterInit(pCompositor, &CIter);
-    int rc = VINF_SUCCESS;
-    bool fChanged = false;
-
-    while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
-    {
-        bool fCurChanged = false;
-
-        rc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pVr, &fCurChanged);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
-            break;
-        }
-
-        fChanged |= fCurChanged;
-    }
-
-    if (pfChanged)
-        *pfChanged = fChanged;
-
-    return rc;
-}
-
-VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged)
-{
-    int rc  = CrVrScrCompositorClone(pCompositor, pDstCompositor, pfnEntryFor, pvEntryFor);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("CrVrScrCompositorClone failed, rc %d", rc));
-        return rc;
-    }
-
-    rc = CrVrScrCompositorIntersectList(pDstCompositor, pVr, pfChanged);
-    if (!RT_SUCCESS(rc))
-    {
-        WARN(("CrVrScrCompositorIntersectList failed, rc %d", rc));
-        CrVrScrCompositorClear(pDstCompositor);
-        return rc;
-    }
-
-    return VINF_SUCCESS;
-}
diff --git a/src/VBox/HostDrivers/Support/SUPDrv.c b/src/VBox/HostDrivers/Support/SUPDrv.c
index b9e7ceb..580e318 100644
--- a/src/VBox/HostDrivers/Support/SUPDrv.c
+++ b/src/VBox/HostDrivers/Support/SUPDrv.c
@@ -3436,7 +3436,7 @@ SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps)
                 {
                     if (fInSmxMode && !fSmxVmxAllowed)
                         rc = VERR_VMX_MSR_SMX_VMXON_DISABLED;
-                    else if (!fVmxAllowed)
+                    else if (!fInSmxMode && !fVmxAllowed)
                         rc = VERR_VMX_MSR_VMXON_DISABLED;
                     else
                         rc = VINF_SUCCESS;
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/darwin/VBoxNetAdp-darwin.cpp b/src/VBox/HostDrivers/VBoxNetAdp/darwin/VBoxNetAdp-darwin.cpp
index 5bebdbe..e1a903b 100644
--- a/src/VBox/HostDrivers/VBoxNetAdp/darwin/VBoxNetAdp-darwin.cpp
+++ b/src/VBox/HostDrivers/VBoxNetAdp/darwin/VBoxNetAdp-darwin.cpp
@@ -39,6 +39,8 @@
 #include <iprt/uuid.h>
 #include <iprt/alloca.h>
 
+#include "../../darwin/VBoxNetSend.h"
+
 #include <sys/systm.h>
 RT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
 #include <sys/kpi_mbuf.h>
@@ -233,57 +235,6 @@ static errno_t vboxNetAdpDarwinBpfSend(ifnet_t pIface, u_int32_t uLinkType, mbuf
 }
 
 
-/**
- * Constructs and submits a dummy packet to ifnet_input(). This is a workaround
- * for "stuck dock icon" issue. When the first packet goes through the interface
- * DLIL grabs a reference to the thread that submits the packet and holds it
- * until the interface is destroyed. By submitting this dummy we make DLIL grab
- * the thread of a non-GUI process.
- *
- * Most of this function was copied from vboxNetFltDarwinMBufFromSG().
- *
- * @returns VBox status code.
- * @param   pIfNet      The interface that will hold the reference to the calling
- *                      thread. We submit dummy as if it was coming from this interface.
- */
-static int vboxNetSendDummy(ifnet_t pIfNet)
-{
-    int rc = 0;
-    size_t cbTotal = 50; /* No Ethernet header */
-    mbuf_how_t How = MBUF_WAITOK;
-
-    mbuf_t pPkt = NULL;
-    errno_t err = mbuf_allocpacket(How, cbTotal, NULL, &pPkt);
-    if (!err)
-    {
-        /* Skip zero sized memory buffers (paranoia). */
-        mbuf_t pCur = pPkt;
-        while (pCur && !mbuf_maxlen(pCur))
-            pCur = mbuf_next(pCur);
-        Assert(pCur);
-
-        /* Set the required packet header attributes. */
-        mbuf_pkthdr_setlen(pPkt, cbTotal);
-        mbuf_pkthdr_setheader(pPkt, mbuf_data(pCur));
-
-        mbuf_setlen(pCur, cbTotal);
-        memset(mbuf_data(pCur), 0, cbTotal);
-
-        mbuf_pkthdr_setrcvif(pPkt, pIfNet); /* will crash without this. */
-
-        errno_t err = ifnet_input(pIfNet, pPkt, NULL);
-        if (err)
-        {
-            rc = RTErrConvertFromErrno(err);
-            mbuf_freem(pPkt);
-        }
-    }
-    else
-        rc = RTErrConvertFromErrno(err);
-
-    return rc;
-}
-
 int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
 {
     int rc;
@@ -346,7 +297,7 @@ int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
             if (!err)
             {
                 ifnet_set_mtu(pThis->u.s.pIface, VBOXNETADP_MTU);
-                vboxNetSendDummy(pThis->u.s.pIface);
+                VBoxNetSendDummy(pThis->u.s.pIface);
                 return VINF_SUCCESS;
             }
             else
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp b/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp
index 2618097..673699b 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp
+++ b/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp
@@ -43,6 +43,9 @@
 #include <iprt/alloca.h>
 #include <iprt/time.h>
 #include <iprt/net.h>
+#include <iprt/thread.h>
+
+#include "../../darwin/VBoxNetSend.h"
 
 #include <mach/kmod.h>
 #include <sys/conf.h>
@@ -882,6 +885,41 @@ static errno_t vboxNetFltDarwinIffInput(void *pvThis, ifnet_t pIfNet, protocol_f
 }
 
 
+/** A worker thread for vboxNetFltSendDummy(). */
+static DECLCALLBACK(int) vboxNetFltSendDummyWorker(RTTHREAD hThreadSelf, void *pvUser)
+{
+    Assert(pvUser);
+    ifnet_t pIfNet = (ifnet_t)pvUser;
+    return VBoxNetSendDummy(pIfNet);
+}
+
+
+/**
+ * Prevent GUI icon freeze issue when VirtualBoxVM process terminates.
+ *
+ * This function is a workaround for stuck-in-dock issue.  The idea here is to
+ * send a dummy packet to an interface from the context of a kernel thread.
+ * Therefore, an XNU's receive thread (which is created as a result if we are
+ * the first who is communicating with the interface) will be associated with
+ * the kernel thread instead of VirtualBoxVM process.
+ *
+ * @param pIfNet    Interface to be used to send data.
+ */
+static void vboxNetFltSendDummy(ifnet_t pIfNet)
+{
+    RTTHREAD hThread;
+    int rc = RTThreadCreate(&hThread, vboxNetFltSendDummyWorker, (void *)pIfNet, 0,
+                            RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "DummyThread");
+    if (RT_SUCCESS(rc))
+    {
+        RTThreadWait(hThread, RT_INDEFINITE_WAIT, NULL);
+        LogFlow(("vboxNetFltSendDummy: a dummy packet has been successfully sent in order to prevent stuck-in-dock issue\n"));
+    }
+    else
+        LogFlow(("vboxNetFltSendDummy: unable to send dummy packet in order to prevent stuck-in-dock issue\n"));
+}
+
+
 /**
  * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered.
  *
@@ -917,6 +955,9 @@ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRedisco
     ASMAtomicUoWritePtr(&pThis->u.s.pIfNet, pIfNet);
     RTSpinlockReleaseNoInts(pThis->hSpinlock);
 
+    /* Prevent stuck-in-dock issue by associating interface receive thread with kernel thread. */
+    vboxNetFltSendDummy(pIfNet);
+
     /*
      * Get the mac address while we still have a valid ifnet reference.
      */
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h
index 41f8523..cf8087b 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h
@@ -14,8 +14,8 @@
  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
-#ifndef ___VboxNetFltNobj_h___
-#define ___VboxNetFltNobj_h___
+#ifndef ___VBoxNetFltNobj_h___
+#define ___VBoxNetFltNobj_h___
 
 #include <windows.h>
 /* atl stuff */
@@ -70,4 +70,4 @@ private:
     BOOL mbInstalling;
 };
 
-#endif /* #ifndef ___VboxNetFltNobj_h___ */
+#endif /* #ifndef ___VBoxNetFltNobj_h___ */
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h
index ba168a3..5cbf184 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h
@@ -14,10 +14,10 @@
  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
-#ifndef ___VboxNetFltNobjRc_h___
-#define ___VboxNetFltNobjRc_h___
+#ifndef ___VBoxNetFltNobjRc_h___
+#define ___VBoxNetFltNobjRc_h___
 
 /* registry script rc ID */
 #define IDR_VBOXNETFLT_NOBJ 101
 
-#endif /* #ifndef ___VboxNetFltNobjRc_h___ */
+#endif /* #ifndef ___VBoxNetFltNobjRc_h___ */
diff --git a/src/VBox/HostDrivers/darwin/VBoxNetSend.h b/src/VBox/HostDrivers/darwin/VBoxNetSend.h
new file mode 100644
index 0000000..42f7163
--- /dev/null
+++ b/src/VBox/HostDrivers/darwin/VBoxNetSend.h
@@ -0,0 +1,107 @@
+/* $Id: VBoxNetSend.h $ */
+/** @file
+ * A place to share code and definitions between VBoxNetAdp and VBoxNetFlt host drivers.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/** @todo move this to src/VBox/HostDrivers/darwin as a .cpp file. */
+#ifndef ___VBox_VBoxNetSend_h
+#define ___VBox_VBoxNetSend_h
+
+#if defined(RT_OS_DARWIN)
+
+# include <iprt/err.h>
+# include <iprt/assert.h>
+# include <iprt/string.h>
+
+# include <sys/socket.h>
+# include <net/kpi_interface.h>
+RT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
+# include <sys/kpi_mbuf.h>
+RT_C_DECLS_END
+# include <net/if.h>
+
+RT_C_DECLS_BEGIN
+
+# if defined(IN_RING0)
+
+/**
+ * Constructs and submits a dummy packet to ifnet_input().
+ *
+ * This is a workaround for "stuck dock icon" issue. When the first packet goes
+ * through the interface DLIL grabs a reference to the thread that submits the
+ * packet and holds it until the interface is destroyed. By submitting this
+ * dummy we make DLIL grab the thread of a non-GUI process.
+ *
+ * Most of this function was copied from vboxNetFltDarwinMBufFromSG().
+ *
+ * @returns VBox status code.
+ * @param   pIfNet      The interface that will hold the reference to the calling
+ *                      thread. We submit dummy as if it was coming from this interface.
+ */
+DECLINLINE(int) VBoxNetSendDummy(ifnet_t pIfNet)
+{
+    int rc = VINF_SUCCESS;
+
+    size_t      cbTotal = 50; /* No Ethernet header */
+    mbuf_how_t  How     = MBUF_WAITOK;
+    mbuf_t      pPkt    = NULL;
+    errno_t err = mbuf_allocpacket(How, cbTotal, NULL, &pPkt);
+    if (!err)
+    {
+        /* Skip zero sized memory buffers (paranoia). */
+        mbuf_t pCur = pPkt;
+        while (pCur && !mbuf_maxlen(pCur))
+            pCur = mbuf_next(pCur);
+        Assert(pCur);
+
+        /* Set the required packet header attributes. */
+        mbuf_pkthdr_setlen(pPkt, cbTotal);
+        mbuf_pkthdr_setheader(pPkt, mbuf_data(pCur));
+
+        mbuf_setlen(pCur, cbTotal);
+        memset(mbuf_data(pCur), 0, cbTotal);
+
+        mbuf_pkthdr_setrcvif(pPkt, pIfNet); /* will crash without this. */
+
+        errno_t err = ifnet_input(pIfNet, pPkt, NULL);
+        if (err)
+        {
+            rc = RTErrConvertFromErrno(err);
+            mbuf_freem(pPkt);
+        }
+    }
+    else
+        rc = RTErrConvertFromErrno(err);
+
+    return rc;
+}
+
+# endif /* IN_RING0 */
+
+RT_C_DECLS_END
+
+#endif /* RT_OS_DARWIN */
+
+#endif /* !___VBox_VBoxNetSend_h */
+
diff --git a/src/VBox/HostServices/SharedOpenGL/Makefile.kmk b/src/VBox/HostServices/SharedOpenGL/Makefile.kmk
index 1fa7b6e..baf6c70 100644
--- a/src/VBox/HostServices/SharedOpenGL/Makefile.kmk
+++ b/src/VBox/HostServices/SharedOpenGL/Makefile.kmk
@@ -131,7 +131,7 @@ VBoxOGLcrserverlib_SOURCES := \
 	crserverlib/server_getshaders.c \
 	crserverlib/server_framebuffer.c \
 	crserverlib/server_glsl.c \
-	crserverlib/server_muralfbo.c \
+	crserverlib/server_muralfbo.cpp \
 	crserverlib/server_texture.c \
 	crserverlib/server_presenter.cpp \
 	crserverlib/server_rpw.cpp \
@@ -174,7 +174,7 @@ $(VBOX_PATH_CROGL_GENFILES)/server_retval.c: $(addprefix $(PATH_SUB_CURRENT)/crs
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D)
 
-$(VBOX_PATH_CROGL_GENFILES)/server_get.c: $(addprefix $(PATH_SUB_CURRENT)/crserverlib/, server_get.py server_special get_components.py) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+$(VBOX_PATH_CROGL_GENFILES)/server_get.c: $(addprefix $(PATH_SUB_CURRENT)/crserverlib/, server_get.py server_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
 	$(call MSG_GENERATE,python,$@,$<)
 	$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D)
 
diff --git a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp
index fb83b05..228ccae 100644
--- a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp
@@ -31,7 +31,7 @@
 
 bool RTCALL VBoxOglIs3DAccelerationSupported()
 {
-    if (RTEnvGet("VBOX_CROGL_FORCE_SUPPORTED"))
+    if (RTEnvExist("VBOX_CROGL_FORCE_SUPPORTED"))
     {
         LogRel(("VBOX_CROGL_FORCE_SUPPORTED is specified, skipping 3D test, and treating as supported\n"));
         return true;
diff --git a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp
index a2cdd51..0693ed8 100644
--- a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp
@@ -31,7 +31,7 @@
 
 bool RTCALL VBoxOglIs3DAccelerationSupported()
 {
-    if (RTEnvGet("VBOX_CROGL_FORCE_SUPPORTED"))
+    if (RTEnvExist("VBOX_CROGL_FORCE_SUPPORTED"))
     {
         LogRel(("VBOX_CROGL_FORCE_SUPPORTED is specified, skipping 3D test, and treating as supported\n"));
         return true;
diff --git a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
index a7b0647..4388fde 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
@@ -42,6 +42,7 @@
 
 PVBOXHGCMSVCHELPERS g_pHelpers;
 static IConsole* g_pConsole = NULL;
+static uint32_t g_u32ScreenCount = 0;
 static PVM g_pVM = NULL;
 
 #ifndef RT_OS_WINDOWS
@@ -243,7 +244,7 @@ static DECLCALLBACK(void) svcNotifyEventCB(int32_t screenId, uint32_t uEvent, vo
     if (!pFramebuffer)
         return;
 
-    CHECK_ERROR2_STMT(pFramebuffer, Notify3DEvent(uEvent, (BYTE*)pvData), return);
+    pFramebuffer->Notify3DEvent(uEvent, (BYTE*)pvData);
 }
 
 
@@ -367,7 +368,7 @@ static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClie
         LogRel(("SHARED_CROPENGL svcLoadState: unsupported save state version %d\n", ui32));
 
         /*@todo ugly hack, as we don't know size of stored opengl data try to read untill end of opengl data marker*/
-        /*VboxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
+        /*VBoxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
         {
             const char *pMatch = &gszVBoxOGLSSMMagic[0];
             char current;
@@ -931,6 +932,32 @@ static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32
     g_pHelpers->pfnCallComplete (callHandle, rc);
 }
 
+static void crScreenshotHandle(CRVBOXHGCMTAKESCREENSHOT *pScreenshot, uint32_t idScreen, uint64_t u64Now)
+{
+    if (!pScreenshot->pfnScreenshotBegin || pScreenshot->pfnScreenshotBegin(pScreenshot->pvContext, idScreen, u64Now))
+    {
+        CR_SCREENSHOT Screenshot;
+
+        int rc = crServerVBoxScreenshotGet(idScreen, pScreenshot->u32Width, pScreenshot->u32Height, pScreenshot->u32Pitch, pScreenshot->pvBuffer, &Screenshot);
+        if (RT_SUCCESS(rc))
+        {
+            if (pScreenshot->pfnScreenshotPerform)
+                pScreenshot->pfnScreenshotPerform(pScreenshot->pvContext, idScreen,
+                        0, 0, 32,
+                        Screenshot.Img.pitch, Screenshot.Img.width, Screenshot.Img.height,
+                        (uint8_t*)Screenshot.Img.pvData, u64Now);
+            crServerVBoxScreenshotRelease(&Screenshot);
+        }
+        else
+        {
+            Assert(rc == VERR_INVALID_STATE);
+        }
+
+        if (pScreenshot->pfnScreenshotEnd)
+            pScreenshot->pfnScreenshotEnd(pScreenshot->pvContext, idScreen, u64Now);
+    }
+}
+
 /*
  * We differentiate between a function handler for the guest and one for the host.
  */
@@ -952,6 +979,10 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
 
     switch (u32Function)
     {
+        case SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS:
+        {
+            rc = crVBoxServerCrCmdNotifyCmds();
+        } break;
 #ifdef VBOX_WITH_CRHGSMI
         case SHCRGL_HOST_FN_CRHGSMI_CMD:
         {
@@ -1020,6 +1051,7 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
                     crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
 
                     g_pConsole = pConsole;
+                    g_u32ScreenCount = monitorCount;
 
                     rc = crVBoxServerSetScreenCount(monitorCount);
                     AssertRCReturn(rc, rc);
@@ -1095,16 +1127,15 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
             }
 
             if (    paParms[0].type != VBOX_HGCM_SVC_PARM_PTR     /* pRects */
-                 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT   /* cRects */
                )
             {
                 rc = VERR_INVALID_PARAMETER;
                 break;
             }
 
-            Assert(sizeof(RTRECT)==4*sizeof(GLint));
+            Assert(sizeof (RTRECT) == 4 * sizeof (GLint));
 
-            rc = crVBoxServerSetRootVisibleRegion(paParms[1].u.uint32, (const RTRECT*)paParms[0].u.pointer.addr);
+            rc = crVBoxServerSetRootVisibleRegion(paParms[0].u.pointer.size / sizeof (RTRECT), (const RTRECT*)paParms[0].u.pointer.addr);
             break;
         }
         case SHCRGL_HOST_FN_SCREEN_CHANGED:
@@ -1145,22 +1176,35 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
                 }
                 else
                 {
-                    CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
+#if 0
+                    CHECK_ERROR_RET(pFramebuffer, Lock(), rc);
+#endif
 
-                    if (!winId)
-                    {
-                        /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
-                        rc = crVBoxServerUnmapScreen(screenId);
-                        AssertRCReturn(rc, rc);
-                    }
-                    else
-                    {
-                        CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
-                        CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
+                    do {
+                        /* determine if the framebuffer is functional */
+                        rc = pFramebuffer->Notify3DEvent(VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL, NULL);
 
-                        rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
-                        AssertRCReturn(rc, rc);
-                    }
+                        if (rc == S_OK)
+                            CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(WinId)(&winId));
+
+                        if (!winId)
+                        {
+                            /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
+                            rc = crVBoxServerUnmapScreen(screenId);
+                            AssertRCReturn(rc, rc);
+                        }
+                        else
+                        {
+                            CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Width)(&w));
+                            CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Height)(&h));
+
+                            rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
+                            AssertRCReturn(rc, rc);
+                        }
+                    } while (0);
+#if 0
+                    CHECK_ERROR_RET(pFramebuffer, Unlock(), rc);
+#endif
                 }
 
                 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
@@ -1169,6 +1213,93 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
             }
             break;
         }
+        case SHCRGL_HOST_FN_TAKE_SCREENSHOT:
+        {
+            if (cParms != 1)
+            {
+                LogRel(("SHCRGL_HOST_FN_TAKE_SCREENSHOT: cParms invalid - %d", cParms));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
+            {
+                AssertMsgFailed(("invalid param\n"));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            if (!paParms->u.pointer.addr)
+            {
+                AssertMsgFailed(("invalid param\n"));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            if (paParms->u.pointer.size != sizeof (CRVBOXHGCMTAKESCREENSHOT))
+            {
+                AssertMsgFailed(("invalid param\n"));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)paParms->u.pointer.addr;
+            uint64_t u64Now = RTTimeProgramMilliTS();
+
+            if (pScreenshot->u32Screen == CRSCREEN_ALL)
+            {
+                for (uint32_t i = 0; i < g_u32ScreenCount; ++i)
+                {
+                    crScreenshotHandle(pScreenshot, i, u64Now);
+                }
+            }
+            else if (pScreenshot->u32Screen < g_u32ScreenCount)
+            {
+                crScreenshotHandle(pScreenshot, pScreenshot->u32Screen, u64Now);
+            }
+            else
+            {
+                AssertMsgFailed(("invalid screen id\n"));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+            break;
+        }
+        case SHCRGL_HOST_FN_DEV_RESIZE:
+        {
+            Log(("svcCall: SHCRGL_HOST_FN_DEV_RESIZE\n"));
+
+            /* Verify parameter count and types. */
+            if (cParms != SHCRGL_CPARMS_DEV_RESIZE)
+            {
+                LogRel(("SHCRGL_HOST_FN_DEV_RESIZE: cParms invalid - %d", cParms));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
+            {
+                AssertMsgFailed(("invalid param\n"));
+                return VERR_INVALID_PARAMETER;
+            }
+
+            if (!paParms->u.pointer.addr)
+            {
+                AssertMsgFailed(("invalid param\n"));
+                return VERR_INVALID_PARAMETER;
+            }
+
+            if (paParms->u.pointer.size != sizeof (CRVBOXHGCMDEVRESIZE))
+            {
+                AssertMsgFailed(("invalid param\n"));
+                return VERR_INVALID_PARAMETER;
+            }
+
+            CRVBOXHGCMDEVRESIZE *pResize = (CRVBOXHGCMDEVRESIZE*)paParms->u.pointer.addr;
+
+            rc = crVBoxServerNotifyResize(&pResize->Screen, pResize->pvVRAM);
+            break;
+        }
         case SHCRGL_HOST_FN_VIEWPORT_CHANGED:
         {
             Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
@@ -1213,6 +1344,48 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
 
             break;
         }
+        case SHCRGL_HOST_FN_VIEWPORT_CHANGED2:
+        {
+            Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
+
+            /* Verify parameter count and types. */
+            if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
+            {
+                LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR
+                    || !paParms[0].u.pointer.addr
+                    || paParms[0].u.pointer.size != sizeof (CRVBOXHGCMVIEWPORT))
+            {
+                LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param invalid - %d, %#x, %d",
+                        paParms[0].type,
+                        paParms[0].u.pointer.addr,
+                        paParms[0].u.pointer.size));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
+
+            CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)paParms[0].u.pointer.addr;
+
+            rc = crVBoxServerSetScreenViewport(pViewportInfo->u32Screen,
+                    pViewportInfo->x, /* x */
+                    pViewportInfo->y, /* y */
+                    pViewportInfo->width, /* w */
+                    pViewportInfo->height  /* h */);
+            if (!RT_SUCCESS(rc))
+            {
+                LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
+            }
+
+            crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
+
+            break;
+        }
         case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
         {
             /*
@@ -1247,19 +1420,18 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
                 {
                     if (pOutputRedirect->H3DORBegin != NULL)
                     {
-                        rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
-
+                        CROutputRedirect outputRedirect;
+                        outputRedirect.pvContext = pOutputRedirect->pvContext;
+                        outputRedirect.CRORBegin = pOutputRedirect->H3DORBegin;
+                        outputRedirect.CRORGeometry = pOutputRedirect->H3DORGeometry;
+                        outputRedirect.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
+                        outputRedirect.CRORFrame = pOutputRedirect->H3DORFrame;
+                        outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
+                        outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
+                        rc = crVBoxServerOutputRedirectSet(&outputRedirect);
                         if (RT_SUCCESS(rc))
                         {
-                            CROutputRedirect outputRedirect;
-                            outputRedirect.pvContext = pOutputRedirect->pvContext;
-                            outputRedirect.CRORBegin = pOutputRedirect->H3DORBegin;
-                            outputRedirect.CRORGeometry = pOutputRedirect->H3DORGeometry;
-                            outputRedirect.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
-                            outputRedirect.CRORFrame = pOutputRedirect->H3DORFrame;
-                            outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
-                            outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
-                            rc = crVBoxServerOutputRedirectSet(&outputRedirect);
+                            rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
                         }
                     }
                     else
@@ -1272,6 +1444,29 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
             }
             break;
         }
+        case SHCRGL_HOST_FN_WINDOWS_SHOW:
+        {
+            /* Verify parameter count and types. */
+            if (cParms != 1)
+            {
+                WARN(("invalid parameter"));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
+            {
+                WARN(("invalid parameter"));
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            rc = crServerVBoxWindowsShow(paParms[0].u.uint32);
+            if (!RT_SUCCESS(rc))
+                WARN(("crServerVBoxWindowsShow failed rc %d", rc));
+
+            break;
+        }
         default:
             rc = VERR_NOT_IMPLEMENTED;
             break;
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h b/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
index 417b9d2..0b8b464 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
@@ -14,6 +14,8 @@
 #include "state/cr_currentpointers.h"
 
 #include "cr_server.h"
+#include <cr_htable.h>
+#include <cr_compositor.h>
 
 #ifdef VBOX_WITH_CRHGSMI
 # include <VBox/VBoxVideo.h>
@@ -41,9 +43,10 @@ DECLINLINE(void) crServerCrHgsmiCmdComplete(struct VBOXVDMACMD_CHROMIUM_CMD *pCm
 }
 
 #define VBOXCRHGSMI_CMD_COMPLETE(_pData, _rc) do { \
+        Assert(CRVBOXHGSMI_CMDDATA_IS_HGSMICMD(_pData)); \
         CRVBOXHGSMI_CMDDATA_ASSERT_ISSET(_pData); \
         CRVBOXHGSMI_CMDDATA_RC(_pData, _rc); \
-        crServerCrHgsmiCmdComplete((_pData)->pCmd, VINF_SUCCESS); \
+        crServerCrHgsmiCmdComplete((_pData)->pHgsmiCmd, VINF_SUCCESS); \
     } while (0)
 
 #define VBOXCRHGSMI_CMD_CHECK_COMPLETE(_pData, _rc) do { \
@@ -112,13 +115,12 @@ GLboolean crServerClientInBeginEnd(const CRClient *client);
 
 GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID);
 GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID);
-GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID, GLboolean fUseDefaultDEntry);
+GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID);
 void crServerMuralTerm(CRMuralInfo *mural);
 GLboolean crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height);
-void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y, GLboolean fSkipCheckGeometry);
+void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y);
 void crServerMuralVisibleRegion( CRMuralInfo *mural, GLint cRects, const GLint *pRects );
 void crServerMuralShow( CRMuralInfo *mural, GLint state );
-int crServerMuralSynchRootVr(CRMuralInfo *mural, bool *pfChanged);
 
 GLint crServerGenerateID(GLint *pCounter);
 
@@ -128,82 +130,31 @@ GLuint crServerTranslateProgramID(GLuint id);
 
 CRMuralInfo * crServerGetDummyMural(GLint visualBits);
 
-void crServerPresentOutputRedirect(CRMuralInfo *pMural);
-void crServerOutputRedirectCheckEnableDisable(CRMuralInfo *pMural);
-
 void crServerCheckMuralGeometry(CRMuralInfo *mural);
+void crServerCheckAllMuralGeometry(CRMuralInfo *pMI);
 GLboolean crServerSupportRedirMuralFBO(void);
 
+void crVBoxServerMuralFbResizeBegin(HCR_FRAMEBUFFER hFb);
+void crVBoxServerMuralFbResizeEnd(HCR_FRAMEBUFFER hFb);
+
 void crVBoxServerNotifyEvent(int32_t idScreen, uint32_t uEvent, void*pvData);
-void crVBoxServerCheckVisibilityEvent(int32_t idScreen);
 
-void crServerDisplayTermAll();
+void crServerRedirMuralFbClear(CRMuralInfo *mural);
 
-void crServerWindowSize(CRMuralInfo *pMural);
-void crServerWindowShow(CRMuralInfo *pMural);
-void crServerWindowVisibleRegion(CRMuralInfo *pMural);
 void crServerWindowReparent(CRMuralInfo *pMural);
 
-void crServerWindowSetIsVisible(CRMuralInfo *pMural, GLboolean fIsVisible);
-void crServerWindowCheckIsVisible(CRMuralInfo *pMural);
-
-int crVBoxServerUpdateMuralRootVisibleRegion(CRMuralInfo *pMI);
-
-#define CR_SERVER_REDIR_F_NONE     0x00
-/* the data should be displayed on host (unset when is on or when CR_SERVER_REDIR_F_FBO_RAM_VMFB is set) */
-#define CR_SERVER_REDIR_F_DISPLAY       0x01
-/* guest window data get redirected to FBO on host */
-#define CR_SERVER_REDIR_F_FBO           0x02
-/* used with CR_SERVER_REDIR_F_FBO only
- * indicates that FBO data should be copied to RAM for further processing */
-#define CR_SERVER_REDIR_F_FBO_RAM       0x04
-/* used with CR_SERVER_REDIR_F_FBO_RAM only
- * indicates that FBO data should be passed to VRDP backend */
-#define CR_SERVER_REDIR_F_FBO_RAM_VRDP  0x08
-/* used with CR_SERVER_REDIR_F_FBO_RAM only
- * indicates that FBO data should be passed to VM Framebuffer */
-#define CR_SERVER_REDIR_F_FBO_RAM_VMFB  0x10
-/* used with CR_SERVER_REDIR_F_FBO_RAM only
- * makes the RPW (Read Pixels Worker) mechanism to be used for GPU memory aquisition */
-#define CR_SERVER_REDIR_F_FBO_RPW       0x20
-
-
-#define CR_SERVER_REDIR_F_ALL           0x3f
-
-#define CR_SERVER_REDIR_FGROUP_REQUIRE_FBO     (CR_SERVER_REDIR_F_ALL & ~CR_SERVER_REDIR_F_DISPLAY)
-#define CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM (CR_SERVER_REDIR_F_FBO_RAM_VRDP | CR_SERVER_REDIR_F_FBO_RAM_VMFB | CR_SERVER_REDIR_F_FBO_RPW)
-
-DECLINLINE(GLuint) crServerRedirModeAdjust(GLuint value)
-{
-    /* sanitize values */
-    value &= CR_SERVER_REDIR_F_ALL;
-
-    if (value & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO)
-        value |=  CR_SERVER_REDIR_F_FBO;
-    if (value & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM)
-        value |=  CR_SERVER_REDIR_F_FBO_RAM;
-
-    return value;
-}
-
-int32_t crServerSetOffscreenRenderingMode(GLuint value);
-void crServerRedirMuralFBO(CRMuralInfo *mural, GLuint redir);
+void crServerRedirMuralFBO(CRMuralInfo *mural, bool fEnabled);
 void crServerDeleteMuralFBO(CRMuralInfo *mural);
 void crServerPresentFBO(CRMuralInfo *mural);
 GLboolean crServerIsRedirectedToFBO();
 GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer);
 void crServerMuralFBOSwapBuffers(CRMuralInfo *mural);
 
-void crServerVBoxCompositionDisableEnter(CRMuralInfo *mural);
-void crServerVBoxCompositionDisableLeave(CRMuralInfo *mural, GLboolean fForcePresentOnEnabled);
-void crServerVBoxCompositionPresent(CRMuralInfo *mural);
-DECLINLINE(GLboolean) crServerVBoxCompositionPresentNeeded(CRMuralInfo *mural)
-{
-    return mural->bVisible
-                && mural->width
-                && mural->height
-                && !mural->fRootVrOn ? !CrVrScrCompositorIsEmpty(&mural->Compositor) : !CrVrScrCompositorIsEmpty(&mural->RootVrCompositor);
-}
+HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled();
+HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb);
+HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized();
+HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb);
+
 
 #define CR_SERVER_FBO_BB_IDX(_mural) ((_mural)->iBbBuffer)
 #define CR_SERVER_FBO_FB_IDX(_mural) (((_mural)->iBbBuffer + 1) % ((_mural)->cBuffers))
@@ -217,16 +168,15 @@ DECLINLINE(GLboolean) crServerVBoxCompositionPresentNeeded(CRMuralInfo *mural)
 
 int32_t crVBoxServerInternalClientRead(CRClient *pClient, uint8_t *pBuffer, uint32_t *pcbBuffer);
 
-PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen);
-
 void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo );
 
 PCR_BLITTER crServerVBoxBlitterGet();
+PCR_BLITTER crServerVBoxBlitterGetInitialized();
 
 DECLINLINE(void) crServerVBoxBlitterWinInit(CR_BLITTER_WINDOW *win, CRMuralInfo *mural)
 {
     win->Base.id = mural->spuWindow;
-    win->Base.visualBits = mural->CreateInfo.visualBits;
+    win->Base.visualBits = mural->CreateInfo.realVisualBits;
     win->width = mural->width;
     win->height = mural->height;
 }
@@ -236,7 +186,7 @@ DECLINLINE(void) crServerVBoxBlitterCtxInit(CR_BLITTER_CONTEXT *ctx, CRContextIn
     ctx->Base.id = ctxInfo->SpuContext;
     if (ctx->Base.id < 0)
         ctx->Base.id = cr_server.MainContextInfo.SpuContext;
-    ctx->Base.visualBits = cr_server.curClient->currentCtxInfo->CreateInfo.visualBits;
+    ctx->Base.visualBits = cr_server.curClient->currentCtxInfo->CreateInfo.realVisualBits;
 }
 
 /* display worker thread.
@@ -249,6 +199,19 @@ DECLINLINE(void) crServerXchgI8(int8_t *pu8Val1, int8_t *pu8Val2)
     *pu8Val2 = tmp;
 }
 
+#ifdef DEBUG
+# define CR_GLERR_CHECK(_op) do { \
+        GLenum status; \
+        while ((status = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR) {/*Assert(0);*/} \
+        _op \
+        while ((status = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR) {Assert(0);} \
+    } while (0)
+#else
+# define CR_GLERR_CHECK(_op) do { \
+        _op \
+    } while (0)
+#endif
+
 #ifdef DEBUG_misha
 # define CR_SERVER_RPW_DEBUG
 #endif
@@ -405,61 +368,100 @@ void crServerInitTmpCtxDispatch();
 
 int crServerVBoxParseNumerics(const char *pszStr, const int defaultVal);
 
-void CrDpRootUpdate(PCR_DISPLAY pDisplay);
-void CrDpEnter(PCR_DISPLAY pDisplay);
-void CrDpLeave(PCR_DISPLAY pDisplay);
-int CrDpInit(PCR_DISPLAY pDisplay);
-void CrDpTerm(PCR_DISPLAY pDisplay);
+typedef struct CR_FBMAP
+{
+    uint8_t Map[(CR_MAX_GUEST_MONITORS+7)/8];
+} CR_FBMAP;
 
-DECLINLINE(bool) CrDpIsEmpty(PCR_DISPLAY pDisplay)
+DECLINLINE(void) CrFBmInit(CR_FBMAP *pMap)
 {
-    return CrVrScrCompositorIsEmpty(&pDisplay->Mural.Compositor);
+    memset(pMap, 0, sizeof (*pMap));
 }
 
-int CrDpSaveState(PCR_DISPLAY pDisplay, PSSMHANDLE pSSM);
-int CrDpLoadState(PCR_DISPLAY pDisplay, PSSMHANDLE pSSM, uint32_t version);
+DECLINLINE(bool) CrFBmIsSet(CR_FBMAP *pMap, uint32_t i)
+{
+    return ASMBitTest(&pMap->Map, i);
+}
 
-void CrDpReparent(PCR_DISPLAY pDisplay, CRScreenInfo *pScreen);
+DECLINLINE(void) CrFBmSet(CR_FBMAP *pMap, uint32_t i)
+{
+    ASMBitSet(&pMap->Map, i);
+}
 
-void CrDpResize(PCR_DISPLAY pDisplay, int32_t xPos, int32_t yPos, uint32_t width, uint32_t height);
-void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased);
-void CrDpEntryCleanup(PCR_DISPLAY_ENTRY pEntry);
-int CrDpEntryRegionsSet(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions);
-int CrDpEntryRegionsAdd(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, CR_DISPLAY_ENTRY_MAP *pMap);
-void CrDpRegionsClear(PCR_DISPLAY pDisplay);
-DECLINLINE(bool) CrDpEntryIsUsed(PCR_DISPLAY_ENTRY pEntry)
+DECLINLINE(void) CrFBmSetAtomic(CR_FBMAP *pMap, uint32_t i)
 {
-    return CrVrScrCompositorEntryIsInList(&pEntry->CEntry);
+    ASMAtomicBitSet(&pMap->Map, i);
 }
 
-DECLINLINE(CRMuralInfo*) CrDpGetMural(PCR_DISPLAY pDisplay)
+DECLINLINE(void) CrFBmClear(CR_FBMAP *pMap, uint32_t i)
 {
-    return &pDisplay->Mural;
+    ASMBitClear(&pMap->Map, i);
 }
 
-int CrDemGlobalInit();
-void CrDemTeGlobalTerm();
-void CrDemEnter(PCR_DISPLAY_ENTRY_MAP pMap);
-void CrDemLeave(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY pNewEntry, PCR_DISPLAY_ENTRY pReplacedEntry);
-int CrDemInit(PCR_DISPLAY_ENTRY_MAP pMap);
-void CrDemTerm(PCR_DISPLAY_ENTRY_MAP pMap);
-PCR_DISPLAY_ENTRY CrDemEntryAcquire(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture, uint32_t fFlags);
-void CrDemEntryRelease(PCR_DISPLAY_ENTRY pEntry);
-int CrDemEntrySaveState(PCR_DISPLAY_ENTRY pEntry, PSSMHANDLE pSSM);
-int CrDemEntryLoadState(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY *ppEntry, PSSMHANDLE pSSM);
-
-int crServerDisplaySaveState(PSSMHANDLE pSSM);
-int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version);
-
-
-void crServerDEntryResized(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry);
-void crServerDEntryMoved(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry);
-void crServerDEntryVibleRegions(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry);
-void crServerDEntryCheckFBO(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx);
-
-void crServerDEntryAllResized(CRMuralInfo *pMural);
-void crServerDEntryAllMoved(CRMuralInfo *pMural);
-void crServerDEntryAllVibleRegions(CRMuralInfo *pMural);
+/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
+int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap);
+/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
+void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap);
+HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled();
+HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb);
+HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen);
+int CrPMgrModeVrdp(bool fEnable);
+int CrPMgrModeRootVr(bool fEnable);
+int CrPMgrModeWinVisible(bool fEnable);
+int CrPMgrRootVrUpdate();
+int CrPMgrViewportUpdate(uint32_t idScreen);
+int CrPMgrScreenChanged(uint32_t idScreen);
+int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb);
+int CrPMgrSaveState(PSSMHANDLE pSSM);
+int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version);
+HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen);
+/*cleanup stuff*/
+
+int CrPMgrInit();
+void CrPMgrTerm();
+
+typedef DECLCALLBACKPTR(bool, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB)(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
+
+bool CrFbHas3DData(HCR_FRAMEBUFFER hFb);
+void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext);
+int CrFbResize(HCR_FRAMEBUFFER hFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM);
+int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg);
+bool CrFbIsEnabled(HCR_FRAMEBUFFER hFb);
+int CrFbEntryCreateForTexId(HCR_FRAMEBUFFER hFb, GLuint idTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry);
+int CrFbEntryCreateForTexData(HCR_FRAMEBUFFER hFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry);
+void CrFbEntryAddRef(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
+void CrFbEntryRelease(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
+const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb);
+void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb);
+const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(HCR_FRAMEBUFFER hFb);
+const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry);
+
+/* start doing modifications to the framebuffer */
+int CrFbUpdateBegin(HCR_FRAMEBUFFER hFb);
+/*below commands can only be used in Framebuffer update mode, i.e. after the CrFbUpdateBegin succeeded */
+int CrFbEntryRegions(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
+
+/* complete doing modifications to the framebuffer */
+void CrFbUpdateEnd(HCR_FRAMEBUFFER hFb);
+
+int CrFbEntryRegionsAdd(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated);
+int CrFbEntryRegionsSet(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated);
+
+int CrFbEntryTexDataUpdate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex);
+
+CRHTABLE_HANDLE CrFbDDataAllocSlot(HCR_FRAMEBUFFER hFb);
+
+typedef DECLCALLBACKPTR(void, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB)(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
+
+void CrFbDDataReleaseSlot(HCR_FRAMEBUFFER hFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext);
+int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData);
+void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot);
+void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot);
+
+CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex);
+void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased);
+
+int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd);
 
 //#define VBOX_WITH_CRSERVER_DUMPER
 #ifdef VBOX_WITH_CRSERVER_DUMPER
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c
index 46d380a..64ef946 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c
@@ -443,8 +443,6 @@ crServerDispatchSwapBuffers( GLint window, GLint flags )
     else
     {
         cr_server.head_spu->dispatch_table.SwapBuffers( mural->spuWindow, flags );
-        if (crServerVBoxCompositionPresentNeeded(mural))
-            mural->fDataPresented = GL_TRUE;
     }
 
     CR_SERVER_DUMP_SWAPBUFFERS_LEAVE();
@@ -463,8 +461,6 @@ crServerDispatchFlush(void)
         {
             if (crServerIsRedirectedToFBO())
                 crServerPresentFBO(mural);
-            else if (crServerVBoxCompositionPresentNeeded(mural))
-                mural->fDataPresented = GL_TRUE;
         }
 
         if (ctx->framebufferobject.drawFB
@@ -487,8 +483,6 @@ crServerDispatchFinish(void)
         {
             if (crServerIsRedirectedToFBO())
                 crServerPresentFBO(mural);
-            else if (crServerVBoxCompositionPresentNeeded(mural))
-                mural->fDataPresented = GL_TRUE;
         }
 
         if (ctx->framebufferobject.drawFB
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
index 94ab6d9..c4b0ab9 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
@@ -51,16 +51,9 @@ setDefaults(void)
     cr_server.uniqueWindows = 0;
 
     cr_server.screenCount = 0;
-    cr_server.fPresentMode = CR_SERVER_REDIR_F_NONE;
-    cr_server.fPresentModeDefault = cr_server.fPresentMode;
-    cr_server.fVramPresentModeDefault = CR_SERVER_REDIR_F_FBO_RAM;
     cr_server.bUsePBOForReadback = GL_FALSE;
-    cr_server.bUseOutputRedirect = GL_FALSE;
     cr_server.bWindowsInitiallyHidden = GL_FALSE;
 
-    cr_server.cDisableEvents = 0;
-    memset(cr_server.aWinVisibilityInfos, 0, sizeof (cr_server.aWinVisibilityInfos));
-
     cr_server.pfnNotifyEventCB = NULL;
 }
 
@@ -216,51 +209,36 @@ void crServerSetVBoxConfiguration()
     cr_server.head_spu =
         crSPULoadChain(num_spus, spu_ids, spu_names, spu_dir, &cr_server);
 
-    env = crGetenv( "CR_SERVER_DEFAULT_RENDER_TYPE" );
+    env = crGetenv( "CR_SERVER_DEFAULT_VISUAL_BITS" );
     if (env != NULL && env[0] != '\0')
     {
-        unsigned int redir = (unsigned int)crServerVBoxParseNumerics(env, CR_SERVER_REDIR_F_NONE);
-        if (redir <= CR_SERVER_REDIR_F_ALL)
-        {
-            int rc = crServerSetOffscreenRenderingMode(redir);
-            if (!RT_SUCCESS(rc))
-                crWarning("offscreen rendering unsupported, no offscreen rendering will be used..");
-        }
+        unsigned int bits = (unsigned int)crServerVBoxParseNumerics(env, 0);
+        if (bits <= CR_ALL_BITS)
+            cr_server.fVisualBitsDefault = bits;
         else
-            crWarning("invalid redir option %c", redir);
-    }
-#if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(GLX)
-    if (cr_server.fPresentMode == CR_SERVER_REDIR_F_NONE)
-    {
-        /* the CR_SERVER_REDIR_F_FBO_BLT is set only if parent window is received, which means we are not in headles */
-        int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY);
-        if (!RT_SUCCESS(rc))
-            crWarning("offscreen rendering unsupported, no offscreen rendering will be used..");
-
+            crWarning("invalid bits option %c", bits);
     }
-#endif
-    cr_server.fPresentModeDefault = cr_server.fPresentMode;
-    cr_server.fVramPresentModeDefault = CR_SERVER_REDIR_F_FBO_RAM/* | CR_SERVER_REDIR_F_FBO_RPW*/;
+    else
+        cr_server.fVisualBitsDefault = CR_RGB_BIT | CR_ALPHA_BIT | CR_DOUBLE_BIT;
 
     env = crGetenv("CR_SERVER_CAPS");
     if (env && env[0] != '\0')
     {
         cr_server.u32Caps = crServerVBoxParseNumerics(env, 0);
-        cr_server.u32Caps &= ~(CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_NO_DWM_SUPPORT*/);
+        cr_server.u32Caps &= ~(CR_VBOX_CAP_TEX_PRESENT | CR_VBOX_CAP_CMDVBVA);
     }
     else
     {
-        cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_NO_DWM_SUPPORT*/;
-    }
+        cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_CMDVBVA*/;
+#ifdef DEBUG_misha
+        cr_server.u32Caps |= CR_VBOX_CAP_CMDVBVA;
+#endif
 
-    if (!(cr_server.fPresentModeDefault & CR_SERVER_REDIR_F_FBO))
-    {
-        /* can not do tex present in case CR_SERVER_REDIR_F_FBO is disabled */
-        cr_server.u32Caps &= ~CR_VBOX_CAP_TEX_PRESENT;
     }
 
-    crInfo("Cfg: fPresentModeDefault(%#x), fVramPresentModeDefault(%#x), u32Caps(%#x)",
-            cr_server.fPresentModeDefault, cr_server.fVramPresentModeDefault, cr_server.u32Caps);
+    crInfo("Cfg: u32Caps(%#x), fVisualBitsDefault(%#x)",
+            cr_server.u32Caps,
+            cr_server.fVisualBitsDefault);
 
     /* Need to do this as early as possible */
 
@@ -380,51 +358,36 @@ void crServerSetVBoxConfigurationHGCM()
     if (!cr_server.head_spu)
         return;
 
-    env = crGetenv( "CR_SERVER_DEFAULT_RENDER_TYPE" );
+
+    env = crGetenv( "CR_SERVER_DEFAULT_VISUAL_BITS" );
     if (env != NULL && env[0] != '\0')
     {
-        unsigned int redir = (unsigned int)crServerVBoxParseNumerics(env, CR_SERVER_REDIR_F_NONE);
-        if (redir <= CR_SERVER_REDIR_F_ALL)
-        {
-            int rc = crServerSetOffscreenRenderingMode(redir);
-            if (!RT_SUCCESS(rc))
-                crWarning("offscreen rendering unsupported, no offscreen rendering will be used..");
-        }
+        unsigned int bits = (unsigned int)crServerVBoxParseNumerics(env, 0);
+        if (bits <= CR_ALL_BITS)
+            cr_server.fVisualBitsDefault = bits;
         else
-            crWarning("invalid redir option %c", redir);
-    }
-#if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(GLX)
-    if (cr_server.fPresentMode == CR_SERVER_REDIR_F_NONE)
-    {
-        /* the CR_SERVER_REDIR_F_FBO_BLT is set only if parent window is received, which means we are not in headles */
-        int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY);
-        if (!RT_SUCCESS(rc))
-            crWarning("offscreen rendering unsupported, no offscreen rendering will be used..");
-
+            crWarning("invalid bits option %c", bits);
     }
-#endif
-    cr_server.fPresentModeDefault = cr_server.fPresentMode;
-    cr_server.fVramPresentModeDefault = CR_SERVER_REDIR_F_FBO_RAM/* | CR_SERVER_REDIR_F_FBO_RPW*/;
+    else
+        cr_server.fVisualBitsDefault = CR_RGB_BIT | CR_ALPHA_BIT | CR_DOUBLE_BIT;
 
     env = crGetenv("CR_SERVER_CAPS");
     if (env && env[0] != '\0')
     {
         cr_server.u32Caps = crServerVBoxParseNumerics(env, 0);
-        cr_server.u32Caps &= ~(CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_NO_DWM_SUPPORT*/);
+        cr_server.u32Caps &= ~(CR_VBOX_CAP_TEX_PRESENT | CR_VBOX_CAP_CMDVBVA);
     }
     else
     {
-        cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_NO_DWM_SUPPORT*/;
-    }
-
-    if (!(cr_server.fPresentModeDefault & CR_SERVER_REDIR_F_FBO))
-    {
-        /* can not do tex present in case CR_SERVER_REDIR_F_FBO is disabled */
-        cr_server.u32Caps &= ~CR_VBOX_CAP_TEX_PRESENT;
+        cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_CMDVBVA*/;
+#ifdef DEBUG_misha
+        cr_server.u32Caps |= CR_VBOX_CAP_CMDVBVA;
+#endif
     }
 
-    crInfo("Cfg: fPresentModeDefault(%#x), fVramPresentModeDefault(%#x), u32Caps(%#x)",
-            cr_server.fPresentModeDefault, cr_server.fVramPresentModeDefault, cr_server.u32Caps);
+    crInfo("Cfg: u32Caps(%#x), fVisualBitsDefault(%#x)",
+            cr_server.u32Caps,
+            cr_server.fVisualBitsDefault);
 
     cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]);
     cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]);
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
index 656ced5..afa2a20 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
@@ -43,16 +43,21 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
 
     pContextInfo->currentMural = NULL;
 
-    pContextInfo->CreateInfo.visualBits = visualBits;
+    pContextInfo->CreateInfo.requestedVisualBits = visualBits;
+
+    if (cr_server.fVisualBitsDefault)
+        visualBits = cr_server.fVisualBitsDefault;
+
+    pContextInfo->CreateInfo.realVisualBits = visualBits;
 
     /* Since the Cr server serialized all incoming clients/contexts into
      * one outgoing GL stream, we only need to create one context for the
      * head SPU.  We'll only have to make it current once too, below.
      */
     if (cr_server.firstCallCreateContext) {
-        cr_server.MainContextInfo.CreateInfo.visualBits = visualBits;
+        cr_server.MainContextInfo.CreateInfo.realVisualBits = visualBits;
         cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
-            CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, shareCtx);
+            CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, shareCtx);
         if (cr_server.MainContextInfo.SpuContext < 0) {
             crWarning("crServerDispatchCreateContext() failed.");
             crFree(pContextInfo);
@@ -67,13 +72,14 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
     }
     else {
         /* second or third or ... context */
-        if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.visualBits) != visualBits)) {
+        if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.realVisualBits) != visualBits)) {
             int oldSpuContext;
-
+            /* should never be here */
+            CRASSERT(0);
             /* the new context needs new visual attributes */
-            cr_server.MainContextInfo.CreateInfo.visualBits |= visualBits;
+            cr_server.MainContextInfo.CreateInfo.realVisualBits |= visualBits;
             crWarning("crServerDispatchCreateContext requires new visual (0x%x).",
-                    cr_server.MainContextInfo.CreateInfo.visualBits);
+                    cr_server.MainContextInfo.CreateInfo.realVisualBits);
 
             /* Here, we used to just destroy the old rendering context.
              * Unfortunately, this had the side effect of destroying
@@ -88,7 +94,7 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
             /* create new rendering context with suitable visual */
             oldSpuContext = cr_server.MainContextInfo.SpuContext;
             cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
-                CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
+                CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
             /* destroy old rendering context */
             cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext);
             if (cr_server.MainContextInfo.SpuContext < 0) {
@@ -105,7 +111,7 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
 
     if (cr_server.bUseMultipleContexts) {
         pContextInfo->SpuContext = cr_server.head_spu->dispatch_table.
-                CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
+                CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
         if (pContextInfo->SpuContext < 0) {
             crWarning("crServerDispatchCreateContext() failed.");
             crStateEnableDiffOnMakeCurrent(GL_TRUE);
@@ -133,7 +139,7 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
         retVal = preloadCtxID<0 ? (GLint)crHashtableAllocKeys( cr_server.contextTable, 1 ) : preloadCtxID;
 
         pContextInfo->pContext = newCtx;
-        pContextInfo->CreateInfo.visualBits = visualBits;
+        Assert(pContextInfo->CreateInfo.realVisualBits == visualBits);
         pContextInfo->CreateInfo.externalID = retVal;
         pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
         crHashtableAdd(cr_server.contextTable, retVal, pContextInfo);
@@ -199,7 +205,7 @@ crServerDispatchDestroyContext( GLint ctx )
 
     if (cr_server.currentCtxInfo == crCtxInfo)
     {
-        CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
+        CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
         crServerPerformMakeCurrent(dummyMural, &cr_server.MainContextInfo);
         CRASSERT(cr_server.currentCtxInfo == &cr_server.MainContextInfo);
     }
@@ -300,7 +306,7 @@ void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo )
      * crStateSwitchPrepare restores the FBO state to its default values before the context window switch,
      * while crStateSwitchPostprocess restores it back to the original values */
     oldCtx = crStateGetCurrent();
-    if (oldMural && (oldMural->fPresentMode & CR_SERVER_REDIR_F_FBO) && crServerSupportRedirMuralFBO())
+    if (oldMural && oldMural->fRedirected && crServerSupportRedirMuralFBO())
     {
         idDrawFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurDrawBuffer);
         idReadFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurReadBuffer);
@@ -382,7 +388,7 @@ void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo )
     /* This used to be earlier, after crStateUpdateColorBits() call */
     crStateMakeCurrent( ctx );
 
-    if (mural && (mural->fPresentMode & CR_SERVER_REDIR_F_FBO) && crServerSupportRedirMuralFBO())
+    if (mural && mural->fRedirected  && crServerSupportRedirMuralFBO())
     {
         GLuint id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
         if (id != mural->iCurDrawBuffer)
@@ -413,7 +419,7 @@ void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo )
             && cr_server.curClient)
         cr_server.curClient->currentMural->bFbDraw = GL_TRUE;
 
-    if (!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
+    if (!mural->fRedirected)
     {
         ctx->buffer.width = mural->width;
         ctx->buffer.height = mural->height;
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
index cacc353..9e5b539 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
@@ -46,6 +46,7 @@ keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
 for func_name in keys:
     current = 0
     array = ""
+    condition = ""
     m = re.search( r"^(Color|Normal)([1234])(ub|b|us|s|ui|i|f|d)$", func_name )
     if m :
         current = 1
@@ -68,6 +69,7 @@ for func_name in keys:
         name = "texCoord"
         type = m.group(3) + m.group(2)
         array = "[texture-GL_TEXTURE0_ARB]"
+        condition = "if (texture >= GL_TEXTURE0_ARB && texture < GL_TEXTURE0_ARB + CR_MAX_TEXTURE_UNITS)"
     m = re.match( r"^(Index)(ub|b|us|s|ui|i|f|d)$", func_name )
     if m :
         current = 1
@@ -91,18 +93,23 @@ for func_name in keys:
         name = string.lower( m.group(1)[:1] ) + m.group(1)[1:]
         type = m.group(3) + m.group(2)
         array = "[index]"
+        condition = "if (index < CR_MAX_VERTEX_ATTRIBS)"
     if func_name == "VertexAttrib4NubARB":
         current = 1
         name = "vertexAttrib"
         type = "ub4"
         array = "[index]"
+        condition = "if (index < CR_MAX_VERTEX_ATTRIBS)"
 
     if current:
         params = apiutil.Parameters(func_name)
         print 'void SERVER_DISPATCH_APIENTRY crServerDispatch%s( %s )' % ( func_name, apiutil.MakeDeclarationString(params) )
         print '{'
-        print '\tcr_server.head_spu->dispatch_table.%s( %s );' % (func_name, apiutil.MakeCallString(params) )
-        print "\tcr_server.current.c.%s.%s%s = cr_unpackData;" % (name,type,array)
+        print '\t%s' % (condition)
+        print '\t{'
+        print '\t\tcr_server.head_spu->dispatch_table.%s( %s );' % (func_name, apiutil.MakeCallString(params) )
+        print "\t\tcr_server.current.c.%s.%s%s = cr_unpackData;" % (name,type,array)
+        print '\t}'
         print '}\n' 
 
 print """
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
index 89391d6..58d4953 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
@@ -108,8 +108,6 @@ convert_bufferid = [
     'GetVertexAttribivNV'
 ];
 
-from get_components import *;
-
 keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
 for func_name in keys:
     #(return_type, arg_names, arg_types) = gl_mapping[func_name]
@@ -142,5 +140,5 @@ for func_name in keys:
         if func_name in no_pnames:
             print '\tcrServerReturnValue( &(%s[0]), %d*sizeof(%s) );' % (local_argname, max_components[func_name], local_argtype );
         else:
-            print '\tcrServerReturnValue( &(%s[0]), lookupComponents(pname)*sizeof(%s) );' % (local_argname, local_argtype );
+            print '\tcrServerReturnValue( &(%s[0]), crStateHlpComponentsCount(pname)*sizeof(%s) );' % (local_argname, local_argtype );
         print '}\n'
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c
index ec968f1..20acbc0 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c
@@ -97,11 +97,11 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedShaders(GLuint program,
     crFree(pLocal);
 }
 
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj)
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * count, VBoxGLhandleARB * obj)
 {
     GLsizei *pLocal;
 
-    pLocal = (GLsizei*) crAlloc(maxCount*sizeof(GLhandleARB)+sizeof(GLsizei));
+    pLocal = (GLsizei*) crAlloc(maxCount*sizeof(VBoxGLhandleARB)+sizeof(GLsizei));
     if (!pLocal)
     {
         GLsizei zero=0;
@@ -109,7 +109,7 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(GLhandleARB
     }
     /* initial (fallback )value */
     *pLocal = 0;
-    cr_server.head_spu->dispatch_table.GetAttachedObjectsARB(crStateGetProgramHWID(containerObj), maxCount, pLocal, (GLhandleARB*)&pLocal[1]);
+    cr_server.head_spu->dispatch_table.GetAttachedObjectsARB(crStateGetProgramHWID(containerObj), maxCount, pLocal, (VBoxGLhandleARB*)&pLocal[1]);
 
     {
         GLsizei i;
@@ -119,13 +119,13 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(GLhandleARB
           ids[i] = crStateGLSLShaderHWIDtoID(ids[i]);
     }
 
-    crServerReturnValue(pLocal, (*pLocal)*sizeof(GLhandleARB)+sizeof(GLsizei));
+    crServerReturnValue(pLocal, (*pLocal)*sizeof(VBoxGLhandleARB)+sizeof(GLsizei));
     crFree(pLocal);
 }
 
 AssertCompile(sizeof(GLsizei) == 4);
 
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetInfoLogARB(VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
 {
     GLsizei *pLocal;
     GLuint hwid;
@@ -304,7 +304,7 @@ GLboolean SERVER_DISPATCH_APIENTRY crServerDispatchIsProgram(GLuint program)
     return retval; /* ignored */
 }
 
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterfvARB( GLhandleARB obj, GLenum pname, GLfloat * params )
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterfvARB( VBoxGLhandleARB obj, GLenum pname, GLfloat * params )
 {
     GLfloat local_params[1];
     GLuint hwid = crStateGetProgramHWID(obj);
@@ -323,7 +323,7 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterfvARB( GLhandleA
     crServerReturnValue( &(local_params[0]), 1*sizeof(GLfloat) );
 }
 
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterivARB( GLhandleARB obj, GLenum pname, GLint * params )
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterivARB( VBoxGLhandleARB obj, GLenum pname, GLint * params )
 {
     GLint local_params[1];
     GLuint hwid = crStateGetProgramHWID(obj);
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c
index 0c6d613..25d4b91 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c
@@ -111,7 +111,7 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchBindAttribLocation(GLuint program,
     cr_server.head_spu->dispatch_table.BindAttribLocation(crStateGetProgramHWID(program), index, name);
 }
 
-void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteObjectARB(GLhandleARB obj)
+void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteObjectARB(VBoxGLhandleARB obj)
 {
     GLuint hwid =  crStateDeleteObjectARB(obj);
 
@@ -129,9 +129,9 @@ GLint SERVER_DISPATCH_APIENTRY crServerDispatchGetAttribLocation( GLuint program
     return retval; /* WILL PROBABLY BE IGNORED */
 }
 
-GLhandleARB SERVER_DISPATCH_APIENTRY crServerDispatchGetHandleARB( GLenum pname )
+VBoxGLhandleARB SERVER_DISPATCH_APIENTRY crServerDispatchGetHandleARB( GLenum pname )
 {
-    GLhandleARB retval;
+    VBoxGLhandleARB retval;
     retval = cr_server.head_spu->dispatch_table.GetHandleARB(pname);
     if (pname==GL_PROGRAM_OBJECT_ARB)
     {
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c
index 220ee28..6c3d9bd 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c
@@ -60,6 +60,7 @@ GLuint crServerTranslateProgramID( GLuint id )
 void SERVER_DISPATCH_APIENTRY
 crServerDispatchNewList( GLuint list, GLenum mode )
 {
+    Assert(0);
     if (mode == GL_COMPILE_AND_EXECUTE)
         crWarning("using glNewList(GL_COMPILE_AND_EXECUTE) can confuse the crserver");
 
@@ -73,7 +74,7 @@ static void crServerQueryHWState()
     GLuint fbFbo, bbFbo;
     CRClient *client = cr_server.curClient;
     CRMuralInfo *mural = client ? client->currentMural : NULL;
-    if (mural && mural->fPresentMode & CR_SERVER_REDIR_F_FBO)
+    if (mural && mural->fRedirected)
     {
         fbFbo = mural->aidFBOs[CR_SERVER_FBO_FB_IDX(mural)];
         bbFbo = mural->aidFBOs[CR_SERVER_FBO_BB_IDX(mural)];
@@ -291,6 +292,12 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteTextures( GLsizei n, const G
         newTextures[i] = crStateGetTextureHWID(textures[i]);
     }
 
+    for (i = 0; i < n; ++i)
+    {
+        crDebug("DeleteTexture: %d, pid %d, ctx %d", textures[i], (uint32_t)cr_server.curClient->pid, cr_server.currentCtxInfo->pContext->id);
+    }
+
+
     crStateDeleteTextures(n, textures);
     cr_server.head_spu->dispatch_table.DeleteTextures(n, newTextures);
     crFree(newTextures);
@@ -307,12 +314,13 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchPrioritizeTextures( GLsizei n, con
         return;
     }
 
+    crStatePrioritizeTextures(n, textures, priorities);
+
     for (i = 0; i < n; i++)
     {
         newTextures[i] = crStateGetTextureHWID(textures[i]);
     }
 
-    crStatePrioritizeTextures(n, textures, priorities);
     cr_server.head_spu->dispatch_table.PrioritizeTextures(n, newTextures, priorities);
     crFree(newTextures);
 }
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
index 9a6275f..89b9c61 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
@@ -136,6 +136,7 @@ static void crServerTearDown( void )
 {
     GLint i;
     CRClientNode *pNode, *pNext;
+    GLboolean fOldEnableDiff;
 
     /* avoid a race condition */
     if (tearingdown)
@@ -158,11 +159,6 @@ static void crServerTearDown( void )
     cr_server.currentNativeWindow = 0;
     cr_server.currentMural = NULL;
 
-    if (CrBltIsInitialized(&cr_server.Blitter))
-    {
-        CrBltTerm(&cr_server.Blitter);
-    }
-
     /* sync our state with renderspu,
      * do it before mural & context deletion to avoid deleting currently set murals/contexts*/
     cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0);
@@ -178,20 +174,27 @@ static void crServerTearDown( void )
     /* Free all context info */
     crFreeHashtable(cr_server.contextTable, deleteContextInfoCallback);
 
+    /* synchronize with reality */
+    fOldEnableDiff = crStateEnableDiffOnMakeCurrent(GL_FALSE);
+    if(cr_server.MainContextInfo.pContext)
+        crStateMakeCurrent(cr_server.MainContextInfo.pContext);
+    crStateEnableDiffOnMakeCurrent(fOldEnableDiff);
+
     /* Free vertex programs */
     crFreeHashtable(cr_server.programTable, crFree);
 
-    /* Free dummy murals */
-    crFreeHashtable(cr_server.dummyMuralTable, deleteMuralInfoCallback);
-
     /* Free murals */
     crFreeHashtable(cr_server.muralTable, deleteMuralInfoCallback);
 
-    crServerDisplayTermAll();
-    CrDemTerm(&cr_server.PresentTexturepMap);
-    CrDemTeGlobalTerm();
-    memset(cr_server.DisplaysInitMap, 0, sizeof (cr_server.DisplaysInitMap));
-    memset(cr_server.aDispplays, 0, sizeof (cr_server.aDispplays));
+    CrPMgrTerm();
+
+    if (CrBltIsInitialized(&cr_server.Blitter))
+    {
+        CrBltTerm(&cr_server.Blitter);
+    }
+
+    /* Free dummy murals */
+    crFreeHashtable(cr_server.dummyMuralTable, deleteMuralInfoCallback);
 
     for (i = 0; i < cr_server.numClients; i++) {
         if (cr_server.clients[i]) {
@@ -331,7 +334,7 @@ crServerInit(int argc, char *argv[])
     }
 #endif
 
-//    cr_server.bUseMultipleContexts = (crGetenv( "CR_SERVER_ENABLE_MULTIPLE_CONTEXTS" ) != NULL);
+    cr_server.bUseMultipleContexts = (crGetenv( "CR_SERVER_ENABLE_MULTIPLE_CONTEXTS" ) != NULL);
 
     if (cr_server.bUseMultipleContexts)
     {
@@ -368,11 +371,7 @@ crServerInit(int argc, char *argv[])
 
     cr_server.dummyMuralTable = crAllocHashtable();
 
-    CrDemGlobalInit();
-
-    CrDemInit(&cr_server.PresentTexturepMap);
-    memset(cr_server.DisplaysInitMap, 0, sizeof (cr_server.DisplaysInitMap));
-    memset(cr_server.aDispplays, 0, sizeof (cr_server.aDispplays));
+    CrPMgrInit();
 
     cr_server.fRootVrOn = GL_FALSE;
     VBoxVrListInit(&cr_server.RootVr);
@@ -395,6 +394,14 @@ crServerInit(int argc, char *argv[])
     crServerInitTmpCtxDispatch();
     crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
 
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+    crMemset(&cr_server.Recorder, 0, sizeof (cr_server.Recorder));
+    crMemset(&cr_server.RecorderBlitter, 0, sizeof (cr_server.RecorderBlitter));
+    crMemset(&cr_server.DbgPrintDumper, 0, sizeof (cr_server.DbgPrintDumper));
+    crMemset(&cr_server.HtmlDumper, 0, sizeof (cr_server.HtmlDumper));
+    cr_server.pDumper = NULL;
+#endif
+
     crUnpackSetReturnPointer( &(cr_server.return_ptr) );
     crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
 
@@ -431,7 +438,7 @@ GLboolean crVBoxServerInit(void)
     }
 #endif
 
-//    cr_server.bUseMultipleContexts = (crGetenv( "CR_SERVER_ENABLE_MULTIPLE_CONTEXTS" ) != NULL);
+    cr_server.bUseMultipleContexts = (crGetenv( "CR_SERVER_ENABLE_MULTIPLE_CONTEXTS" ) != NULL);
 
     if (cr_server.bUseMultipleContexts)
     {
@@ -477,11 +484,7 @@ GLboolean crVBoxServerInit(void)
 
     cr_server.dummyMuralTable = crAllocHashtable();
 
-    CrDemGlobalInit();
-
-    CrDemInit(&cr_server.PresentTexturepMap);
-    memset(cr_server.DisplaysInitMap, 0, sizeof (cr_server.DisplaysInitMap));
-    memset(cr_server.aDispplays, 0, sizeof (cr_server.aDispplays));
+    CrPMgrInit();
 
     cr_server.fRootVrOn = GL_FALSE;
     VBoxVrListInit(&cr_server.RootVr);
@@ -509,6 +512,14 @@ GLboolean crVBoxServerInit(void)
     crServerInitTmpCtxDispatch();
     crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
 
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+    crMemset(&cr_server.Recorder, 0, sizeof (cr_server.Recorder));
+    crMemset(&cr_server.RecorderBlitter, 0, sizeof (cr_server.RecorderBlitter));
+    crMemset(&cr_server.DbgPrintDumper, 0, sizeof (cr_server.DbgPrintDumper));
+    crMemset(&cr_server.HtmlDumper, 0, sizeof (cr_server.HtmlDumper));
+    cr_server.pDumper = NULL;
+#endif
+
     /*Check for PBO support*/
     if (crStateGetCurrent()->extensions.ARB_pixel_buffer_object)
     {
@@ -849,14 +860,19 @@ static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *d
 static void crVBoxServerSaveCreateInfoFromMuralInfoCB(unsigned long key, void *data1, void *data2)
 {
     CRMuralInfo *pMural = (CRMuralInfo *)data1;
-    CRCreateInfo_t *pCreateInfo = &pMural->CreateInfo;
-    crVBoxServerSaveCreateInfoCB(key, pCreateInfo, data2);
+    CRCreateInfo_t CreateInfo;
+    CreateInfo.pszDpyName = pMural->CreateInfo.pszDpyName;
+    CreateInfo.visualBits = pMural->CreateInfo.requestedVisualBits;
+    CreateInfo.externalID = pMural->CreateInfo.externalID;
+    crVBoxServerSaveCreateInfoCB(key, &CreateInfo, data2);
 }
 
 static void crVBoxServerSaveCreateInfoFromCtxInfoCB(unsigned long key, void *data1, void *data2)
 {
     CRContextInfo *pContextInfo = (CRContextInfo *)data1;
-    CRCreateInfo_t CreateInfo = pContextInfo->CreateInfo;
+    CRCreateInfo_t CreateInfo;
+    CreateInfo.pszDpyName = pContextInfo->CreateInfo.pszDpyName;
+    CreateInfo.visualBits = pContextInfo->CreateInfo.requestedVisualBits;
     /* saved state contains internal id */
     CreateInfo.externalID = pContextInfo->pContext->id;
     crVBoxServerSaveCreateInfoCB(key, &CreateInfo, data2);
@@ -915,7 +931,7 @@ static void crVBoxServerBuildAdditionalWindowContextMapCB(unsigned long key, voi
 
     Assert(!crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
 
-    if (cr_server.MainContextInfo.CreateInfo.visualBits == pMural->CreateInfo.visualBits)
+    if (cr_server.MainContextInfo.CreateInfo.realVisualBits == pMural->CreateInfo.realVisualBits)
     {
         pContextInfo = &cr_server.MainContextInfo;
     }
@@ -960,7 +976,7 @@ static void crVBoxServerBuildContextWindowMapWindowWalkerCB(unsigned long key, v
     if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
         return;
 
-    CRASSERT(pMural->CreateInfo.visualBits == pData->pContextInfo->CreateInfo.visualBits);
+    CRASSERT(pMural->CreateInfo.realVisualBits == pData->pContextInfo->CreateInfo.realVisualBits);
     pData->pMural = pMural;
 }
 
@@ -988,7 +1004,7 @@ CRMuralInfo * crServerGetDummyMural(GLint visualBits)
             crWarning("crCalloc failed!");
             return NULL;
         }
-        id = crServerMuralInit(pMural, "", visualBits, 0, GL_TRUE);
+        id = crServerMuralInit(pMural, "", visualBits, 0);
         if (id < 0)
         {
             crWarning("crServerMuralInit failed!");
@@ -1028,7 +1044,7 @@ static void crVBoxServerBuildContextUnusedWindowMapCB(unsigned long key, void *d
 
     if (!pMural)
     {
-        pMural = crServerGetDummyMural(pContextInfo->CreateInfo.visualBits);
+        pMural = crServerGetDummyMural(pContextInfo->CreateInfo.realVisualBits);
         if (!pMural)
         {
             crWarning("crServerGetDummyMural failed");
@@ -1132,7 +1148,7 @@ static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInf
     pData->cElements = 0;
 
     pEl = &pData->aElements[pData->cElements];
-    pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+    pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
     pEl->enmBuffer = pData->aElements[1].idFBO ? GL_COLOR_ATTACHMENT0 : GL_FRONT;
     pEl->posX = 0;
     pEl->posY = 0;
@@ -1152,14 +1168,14 @@ static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInf
 
     /* there is a lot of code that assumes we have double buffering, just assert here to print a warning in the log
      * so that we know that something irregular is going on */
-    CRASSERT(pCtxInfo->CreateInfo.visualBits & CR_DOUBLE_BIT);
-    if ((pCtxInfo->CreateInfo.visualBits & CR_DOUBLE_BIT)
+    CRASSERT(pCtxInfo->CreateInfo.requestedVisualBits & CR_DOUBLE_BIT);
+    if ((pCtxInfo->CreateInfo.requestedVisualBits & CR_DOUBLE_BIT)
     		|| version < SHCROGL_SSM_VERSION_WITH_SINGLE_DEPTH_STENCIL /* <- older version had a typo which lead to back always being used,
     																	* no matter what the visual bits are */
     		)
     {
         pEl = &pData->aElements[pData->cElements];
-        pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_BB_IDX(pMural)] : 0;
+        pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_BB_IDX(pMural)] : 0;
         pEl->enmBuffer = pData->aElements[1].idFBO ? GL_COLOR_ATTACHMENT0 : GL_BACK;
         pEl->posX = 0;
         pEl->posY = 0;
@@ -1184,12 +1200,12 @@ static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInf
 
     if (version < SHCROGL_SSM_VERSION_WITH_SINGLE_DEPTH_STENCIL)
     {
-/*        if (pCtxInfo->CreateInfo.visualBits & CR_DEPTH_BIT) */ /* <- older version had a typo which lead to back always being used,
+/*        if (pCtxInfo->CreateInfo.requestedVisualBits & CR_DEPTH_BIT) */ /* <- older version had a typo which lead to back always being used,
 																  * no matter what the visual bits are */
         {
             AssertCompile(sizeof (GLfloat) == 4);
             pEl = &pData->aElements[pData->cElements];
-            pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+            pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
             pEl->enmBuffer = 0; /* we do not care */
             pEl->posX = 0;
             pEl->posY = 0;
@@ -1215,12 +1231,12 @@ static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInf
             ++pData->cElements;
         }
 
- /*       if (pCtxInfo->CreateInfo.visualBits & CR_STENCIL_BIT) */ /* <- older version had a typo which lead to back always being used,
+ /*       if (pCtxInfo->CreateInfo.requestedVisualBits & CR_STENCIL_BIT) */ /* <- older version had a typo which lead to back always being used,
 																	* no matter what the visual bits are */
         {
             AssertCompile(sizeof (GLuint) == 4);
             pEl = &pData->aElements[pData->cElements];
-            pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+            pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
             pEl->enmBuffer = 0; /* we do not care */
             pEl->posX = 0;
             pEl->posY = 0;
@@ -1241,11 +1257,11 @@ static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInf
         return VINF_SUCCESS;
     }
 
-    if ((pCtxInfo->CreateInfo.visualBits & CR_STENCIL_BIT)
-    		|| (pCtxInfo->CreateInfo.visualBits & CR_DEPTH_BIT))
+    if ((pCtxInfo->CreateInfo.requestedVisualBits & CR_STENCIL_BIT)
+    		|| (pCtxInfo->CreateInfo.requestedVisualBits & CR_DEPTH_BIT))
     {
         pEl = &pData->aElements[pData->cElements];
-        pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+        pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
         pEl->enmBuffer = 0; /* we do not care */
         pEl->posX = 0;
         pEl->posY = 0;
@@ -1702,7 +1718,7 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
         }
     }
 
-    rc = crServerDisplaySaveState(pSSM);
+    rc = CrPMgrSaveState(pSSM);
     AssertRCReturn(rc, rc);
 
     /* all context gl error states should have now be synced with chromium erro states,
@@ -2120,13 +2136,6 @@ static int32_t crVBoxServerLoadMurals(CR_SERVER_LOADSTATE_READER *pReader, uint3
         {
             crFree(muralInfo.pVisibleRects);
         }
-
-        Assert(!pActualMural->fDataPresented);
-
-        if (version >= SHCROGL_SSM_VERSION_WITH_PRESENT_STATE)
-            pActualMural->fDataPresented = muralInfo.fDataPresented;
-        else
-            pActualMural->fDataPresented = crServerVBoxCompositionPresentNeeded(pActualMural);
     }
 
     CRASSERT(RT_SUCCESS(rc));
@@ -2214,10 +2223,7 @@ static int crVBoxServerLoadFBImage(PSSMHANDLE pSSM, uint32_t version,
         CRASSERT(!pBuf->pBackImg);
         crVBoxServerFBImageDataTerm(&Data.data);
 
-        if ((pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) && pMural->fDataPresented && crServerVBoxCompositionPresentNeeded(pMural))
-        {
-            crServerPresentFBO(pMural);
-        }
+        crServerPresentFBO(pMural);
 
         CRASSERT(cr_server.currentMural);
         cr_server.head_spu->dispatch_table.MakeCurrent( cr_server.currentMural->spuWindow,
@@ -2352,7 +2358,7 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
         CRASSERT(cr_server.MainContextInfo.SpuContext > 0);
         CRASSERT(!cr_server.currentCtxInfo);
         CRASSERT(!cr_server.currentMural);
-        pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
+        pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
         CRASSERT(pMural);
         crServerPerformMakeCurrent(pMural, &cr_server.MainContextInfo);
     }
@@ -2386,7 +2392,7 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
             else
             {
                 /* null winId means a dummy mural, get it */
-                pMural = crServerGetDummyMural(pContextInfo->CreateInfo.visualBits);
+                pMural = crServerGetDummyMural(pContextInfo->CreateInfo.realVisualBits);
                 CRASSERT(pMural);
             }
         }
@@ -2593,7 +2599,9 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
 
     if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_INFO)
     {
-        rc = crServerDisplayLoadState(pSSM, version);
+        HCR_FRAMEBUFFER hFb;
+
+        rc = CrPMgrLoadState(pSSM, version);
         AssertRCReturn(rc, rc);
     }
 
@@ -2637,32 +2645,11 @@ void crVBoxServerNotifyEvent(int32_t idScreen, uint32_t uEvent, void*pvData)
     cr_server.pfnNotifyEventCB(idScreen, uEvent, pvData);
 }
 
-void crVBoxServerCheckVisibilityEvent(int32_t idScreen)
+void crServerWindowReparent(CRMuralInfo *pMural)
 {
-    if (cr_server.cDisableEvents)
-        return;
-
-    if (idScreen < 0)
-    {
-        int32_t i = 0;
-        for (; i < cr_server.screenCount; ++i)
-        {
-            crVBoxServerCheckVisibilityEvent(i);
-        }
-        return;
-    }
-
-    CRASSERT(idScreen < cr_server.screenCount);
+    pMural->fHasParentWindow = !!cr_server.screen[pMural->screenId].winID;
 
-    if (!cr_server.aWinVisibilityInfos[idScreen].fVisibleChanged
-            && !cr_server.aWinVisibilityInfos[idScreen].cVisibleWindows == !cr_server.aWinVisibilityInfos[idScreen].fLastReportedVisible)
-        return;
-
-    crVBoxServerNotifyEvent(idScreen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA,
-            cr_server.aWinVisibilityInfos[idScreen].cVisibleWindows ? (void*)1 : NULL);
-
-    cr_server.aWinVisibilityInfos[idScreen].fLastReportedVisible = cr_server.aWinVisibilityInfos[idScreen].cVisibleWindows ? 1 : 0;
-    cr_server.aWinVisibilityInfos[idScreen].fVisibleChanged = 0;
+    renderspuReparentWindow(pMural->spuWindow);
 }
 
 static void crVBoxServerReparentMuralCB(unsigned long key, void *data1, void *data2)
@@ -2670,22 +2657,12 @@ static void crVBoxServerReparentMuralCB(unsigned long key, void *data1, void *da
     CRMuralInfo *pMI = (CRMuralInfo*) data1;
     int *sIndex = (int*) data2;
 
-    Assert(pMI->cDisabled);
-
     if (pMI->screenId == *sIndex)
     {
         crServerWindowReparent(pMI);
     }
 }
 
-static void crVBoxServerCheckMuralCB(unsigned long key, void *data1, void *data2)
-{
-    CRMuralInfo *pMI = (CRMuralInfo*) data1;
-    (void) data2;
-
-    crServerCheckMuralGeometry(pMI);
-}
-
 DECLEXPORT(int32_t) crVBoxServerSetScreenCount(int sCount)
 {
     int i;
@@ -2720,8 +2697,6 @@ DECLEXPORT(int32_t) crVBoxServerUnmapScreen(int sIndex)
 
     if (MAPPED(SCREEN(sIndex)))
     {
-        PCR_DISPLAY pDisplay = crServerDisplayGetInitialized(sIndex);
-
         SCREEN(sIndex).winID = 0;
         renderspuSetWindowId(0);
 
@@ -2729,16 +2704,11 @@ DECLEXPORT(int32_t) crVBoxServerUnmapScreen(int sIndex)
 
         crHashtableWalk(cr_server.dummyMuralTable, crVBoxServerReparentMuralCB, &sIndex);
 
-        if (pDisplay)
-            CrDpReparent(pDisplay, &SCREEN(sIndex));
+        CrPMgrScreenChanged((uint32_t)sIndex);
     }
 
     renderspuSetWindowId(SCREEN(0).winID);
 
-    crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
-
-/*    crVBoxServerNotifyEvent(sIndex, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, NULL); */
-
     return VINF_SUCCESS;
 }
 
@@ -2767,8 +2737,6 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
     crHashtableWalk(cr_server.dummyMuralTable, crVBoxServerReparentMuralCB, &sIndex);
     renderspuSetWindowId(SCREEN(0).winID);
 
-    crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
-
 #ifndef WINDOWS
     /*Restore FB content for clients, which have current window on a screen being remapped*/
     {
@@ -2802,72 +2770,15 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
     }
 #endif
 
-    {
-        PCR_DISPLAY pDisplay = crServerDisplayGetInitialized(sIndex);
-        if (pDisplay)
-            CrDpReparent(pDisplay, &SCREEN(sIndex));
-    }
-
-    crVBoxServerNotifyEvent(sIndex, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA,
-            cr_server.aWinVisibilityInfos[sIndex].cVisibleWindows ? (void*)1 : NULL);
+    CrPMgrScreenChanged((uint32_t)sIndex);
 
     return VINF_SUCCESS;
 }
 
-int crVBoxServerUpdateMuralRootVisibleRegion(CRMuralInfo *pMI)
-{
-    GLboolean fForcePresent;
-
-    int rc = VINF_SUCCESS;
-
-    fForcePresent = crServerVBoxCompositionPresentNeeded(pMI);
-
-    crServerVBoxCompositionDisableEnter(pMI);
-
-    if (cr_server.fRootVrOn)
-    {
-        if (!pMI->fRootVrOn)
-        {
-            CrVrScrCompositorInit(&pMI->RootVrCompositor);
-        }
-
-        rc = crServerMuralSynchRootVr(pMI, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
-            goto end;
-        }
-    }
-    else
-    {
-        CrVrScrCompositorClear(&pMI->RootVrCompositor);
-    }
-
-    pMI->fRootVrOn = cr_server.fRootVrOn;
-
-    crServerWindowVisibleRegion(pMI);
-
-end:
-    crServerVBoxCompositionDisableLeave(pMI, fForcePresent);
-
-    return rc;
-}
-
-static void crVBoxServerSetRootVisibleRegionCB(unsigned long key, void *data1, void *data2)
-{
-    CRMuralInfo *pMI = (CRMuralInfo*) data1;
-
-    if (!pMI->CreateInfo.externalID)
-        return;
-    (void) data2;
-
-    crVBoxServerUpdateMuralRootVisibleRegion(pMI);
-}
-
 DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, const RTRECT *pRects)
 {
     int32_t rc = VINF_SUCCESS;
-    int i;
+    GLboolean fOldRootVrOn = cr_server.fRootVrOn;
 
     /* non-zero rects pointer indicate rects are present and switched on
      * i.e. cRects==0 and pRects!=NULL means root visible regioning is ON and there are no visible regions,
@@ -2894,15 +2805,23 @@ DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, const RTRECT
         cr_server.fRootVrOn = GL_FALSE;
     }
 
-    crHashtableWalk(cr_server.muralTable, crVBoxServerSetRootVisibleRegionCB, NULL);
-
-    for (i = 0; i < cr_server.screenCount; ++i)
+    if (!fOldRootVrOn != !cr_server.fRootVrOn)
     {
-        PCR_DISPLAY pDisplay = crServerDisplayGetInitialized((uint32_t)i);
-        if (!pDisplay)
-            continue;
-
-        CrDpRootUpdate(pDisplay);
+        rc = CrPMgrModeRootVr(cr_server.fRootVrOn);
+        if (!RT_SUCCESS(rc))
+        {
+            crWarning("CrPMgrModeRootVr failed rc %d", rc);
+            return rc;
+        }
+    }
+    else if (cr_server.fRootVrOn)
+    {
+        rc = CrPMgrRootVrUpdate();
+        if (!RT_SUCCESS(rc))
+        {
+            crWarning("CrPMgrRootVrUpdate failed rc %d", rc);
+            return rc;
+        }
     }
 
     return VINF_SUCCESS;
@@ -2913,52 +2832,9 @@ DECLEXPORT(void) crVBoxServerSetPresentFBOCB(PFNCRSERVERPRESENTFBO pfnPresentFBO
     cr_server.pfnPresentFBO = pfnPresentFBO;
 }
 
-int32_t crServerSetOffscreenRenderingMode(GLuint value)
-{
-    /* sanitize values */
-    value = crServerRedirModeAdjust(value);
-
-    if (value == CR_SERVER_REDIR_F_NONE)
-    {
-        crWarning("crServerSetOffscreenRenderingMode: value undefined");
-    }
-
-    if (cr_server.fPresentMode==value)
-    {
-        return VINF_SUCCESS;
-    }
-
-    if ((value & CR_SERVER_REDIR_F_FBO) && !crServerSupportRedirMuralFBO())
-    {
-        crWarning("crServerSetOffscreenRenderingMode: FBO not supported");
-        return VERR_NOT_SUPPORTED;
-    }
-
-    cr_server.fPresentMode=value;
-
-    crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
-
-    return VINF_SUCCESS;
-}
-
 DECLEXPORT(int32_t) crVBoxServerSetOffscreenRendering(GLboolean value)
 {
-    return crServerSetOffscreenRenderingMode(value ?
-            cr_server.fPresentModeDefault | CR_SERVER_REDIR_F_FBO_RAM_VRDP | cr_server.fVramPresentModeDefault
-            : cr_server.fPresentModeDefault);
-}
-
-static void crVBoxServerOutputRedirectCB(unsigned long key, void *data1, void *data2)
-{
-    CRMuralInfo *mural = (CRMuralInfo*) data1;
-
-    if (!mural->CreateInfo.externalID)
-        return;
-
-    if (cr_server.bUseOutputRedirect)
-        crServerPresentOutputRedirect(mural);
-    else
-        crServerOutputRedirectCheckEnableDisable(mural);
+    return CrPMgrModeVrdp(value);
 }
 
 DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallbacks)
@@ -2967,81 +2843,406 @@ DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallb
     if (pCallbacks)
     {
         cr_server.outputRedirect = *pCallbacks;
-        cr_server.bUseOutputRedirect = true;
     }
     else
     {
-        cr_server.bUseOutputRedirect = false;
+        memset (&cr_server.outputRedirect, 0, sizeof (cr_server.outputRedirect));
     }
 
-    /* dynamically intercept already existing output */
-    crHashtableWalk(cr_server.muralTable, crVBoxServerOutputRedirectCB, NULL);
-
     return VINF_SUCCESS;
 }
 
-static void crVBoxServerUpdateScreenViewportCB(unsigned long key, void *data1, void *data2)
+DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h)
 {
-    CRMuralInfo *mural = (CRMuralInfo*) data1;
-    int *sIndex = (int*) data2;
+    CRScreenViewportInfo *pViewport;
+    RTRECT NewRect;
+    int rc;
 
-    if (mural->screenId != *sIndex)
-        return;
+    crDebug("crVBoxServerSetScreenViewport(%i)", sIndex);
 
-    crServerCheckMuralGeometry(mural);
+    if (sIndex<0 || sIndex>=cr_server.screenCount)
+    {
+        crWarning("crVBoxServerSetScreenViewport: invalid screen id %d", sIndex);
+        return VERR_INVALID_PARAMETER;
+    }
+
+    NewRect.xLeft = x;
+    NewRect.yTop = y;
+    NewRect.xRight = x + w;
+    NewRect.yBottom = y + h;
+
+    pViewport = &cr_server.screenVieport[sIndex];
+    /*always do viewport updates no matter whether the rectangle actually changes,
+     * this is needed to ensure window is adjusted properly on OSX */
+    pViewport->Rect = NewRect;
+    rc = CrPMgrViewportUpdate((uint32_t)sIndex);
+    if (!RT_SUCCESS(rc))
+    {
+        crWarning("CrPMgrViewportUpdate failed %d", rc);
+        return rc;
+    }
+
+    return VINF_SUCCESS;
 }
 
 
-DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h)
+#ifdef VBOX_WITH_CRHGSMI
+
+static int32_t crVBoxServerCmdVbvaCrCmdProcess(struct VBOXCMDVBVA_CRCMD_CMD *pCmd)
 {
-    CRScreenViewportInfo *pVieport;
-    GLboolean fPosChanged, fSizeChanged;
+    int32_t rc;
+    uint32_t cBuffers = pCmd->cBuffers;
+    uint32_t cParams;
+    uint32_t cbHdr;
+    CRVBOXHGSMIHDR *pHdr;
+    uint32_t u32Function;
+    uint32_t u32ClientID;
+    CRClient *pClient;
 
-    crDebug("crVBoxServerSetScreenViewport(%i)", sIndex);
+    if (!g_pvVRamBase)
+    {
+        crWarning("g_pvVRamBase is not initialized");
+        return VERR_INVALID_STATE;
+    }
 
-    if (sIndex<0 || sIndex>=cr_server.screenCount)
+    if (!cBuffers)
     {
-        crWarning("crVBoxServerSetScreenViewport: invalid screen id %d", sIndex);
+        crWarning("zero buffers passed in!");
         return VERR_INVALID_PARAMETER;
     }
 
-    pVieport = &cr_server.screenVieport[sIndex];
-    fPosChanged = (pVieport->x != x || pVieport->y != y);
-    fSizeChanged = (pVieport->w != w || pVieport->h != h);
+    cParams = cBuffers-1;
 
-    if (!fPosChanged && !fSizeChanged)
+    cbHdr = pCmd->aBuffers[0].cbBuffer;
+    pHdr = VBOXCRHGSMI_PTR_SAFE(pCmd->aBuffers[0].offBuffer, cbHdr, CRVBOXHGSMIHDR);
+    if (!pHdr)
     {
-        crDebug("crVBoxServerSetScreenViewport: no changes");
-        return VINF_SUCCESS;
+        crWarning("invalid header buffer!");
+        return VERR_INVALID_PARAMETER;
     }
 
-    if (fPosChanged)
+    if (cbHdr < sizeof (*pHdr))
     {
-        pVieport->x = x;
-        pVieport->y = y;
-
-        crHashtableWalk(cr_server.muralTable, crVBoxServerUpdateScreenViewportCB, &sIndex);
+        crWarning("invalid header buffer size!");
+        return VERR_INVALID_PARAMETER;
     }
 
-    if (fSizeChanged)
+    u32Function = pHdr->u32Function;
+    u32ClientID = pHdr->u32ClientID;
+
+    switch (u32Function)
     {
-        pVieport->w = w;
-        pVieport->h = h;
+        case SHCRGL_GUEST_FN_WRITE:
+        {
+            Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
+
+            /* @todo: Verify  */
+            if (cParams == 1)
+            {
+                CRVBOXHGSMIWRITE* pFnCmd = (CRVBOXHGSMIWRITE*)pHdr;
+                VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+                /* Fetch parameters. */
+                uint32_t cbBuffer = pBuf->cbBuffer;
+                uint8_t *pBuffer  = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+                if (cbHdr < sizeof (*pFnCmd))
+                {
+                    crWarning("invalid write cmd buffer size!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                CRASSERT(cbBuffer);
+                if (!pBuffer)
+                {
+                    crWarning("invalid buffer data received from guest!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                rc = crVBoxServerClientGet(u32ClientID, &pClient);
+                if (RT_FAILURE(rc))
+                {
+                    break;
+                }
+
+                /* This should never fire unless we start to multithread */
+                CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+                pClient->conn->pBuffer = pBuffer;
+                pClient->conn->cbBuffer = cbBuffer;
+                CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, false);
+                rc = crVBoxServerInternalClientWriteRead(pClient);
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+                return rc;
+            }
+            else
+            {
+                crWarning("invalid number of args");
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+            break;
+        }
+
+        case SHCRGL_GUEST_FN_INJECT:
+        {
+            Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
+
+            /* @todo: Verify  */
+            if (cParams == 1)
+            {
+                CRVBOXHGSMIINJECT *pFnCmd = (CRVBOXHGSMIINJECT*)pHdr;
+                /* Fetch parameters. */
+                uint32_t u32InjectClientID = pFnCmd->u32ClientID;
+                VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+                uint32_t cbBuffer = pBuf->cbBuffer;
+                uint8_t *pBuffer  = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+                if (cbHdr < sizeof (*pFnCmd))
+                {
+                    crWarning("invalid inject cmd buffer size!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                CRASSERT(cbBuffer);
+                if (!pBuffer)
+                {
+                    crWarning("invalid buffer data received from guest!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                rc = crVBoxServerClientGet(u32InjectClientID, &pClient);
+                if (RT_FAILURE(rc))
+                {
+                    break;
+                }
+
+                /* This should never fire unless we start to multithread */
+                CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+                pClient->conn->pBuffer = pBuffer;
+                pClient->conn->cbBuffer = cbBuffer;
+                CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, false);
+                rc = crVBoxServerInternalClientWriteRead(pClient);
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+                return rc;
+            }
+
+            crWarning("invalid number of args");
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        case SHCRGL_GUEST_FN_READ:
+        {
+            Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
+
+            /* @todo: Verify  */
+            if (cParams == 1)
+            {
+                CRVBOXHGSMIREAD *pFnCmd = (CRVBOXHGSMIREAD*)pHdr;
+                VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+                /* Fetch parameters. */
+                uint32_t cbBuffer = pBuf->cbBuffer;
+                uint8_t *pBuffer  = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+                if (cbHdr < sizeof (*pFnCmd))
+                {
+                    crWarning("invalid read cmd buffer size!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+
+                if (!pBuffer)
+                {
+                    crWarning("invalid buffer data received from guest!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                rc = crVBoxServerClientGet(u32ClientID, &pClient);
+                if (RT_FAILURE(rc))
+                {
+                    break;
+                }
+
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+                rc = crVBoxServerInternalClientRead(pClient, pBuffer, &cbBuffer);
+
+                /* Return the required buffer size always */
+                pFnCmd->cbBuffer = cbBuffer;
+
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+                /* the read command is never pended, complete it right away */
+                pHdr->result = rc;
+
+                return VINF_SUCCESS;
+            }
+
+            crWarning("invalid number of args");
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        case SHCRGL_GUEST_FN_WRITE_READ:
+        {
+            Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
+
+            /* @todo: Verify  */
+            if (cParams == 2)
+            {
+                CRVBOXHGSMIWRITEREAD *pFnCmd = (CRVBOXHGSMIWRITEREAD*)pHdr;
+                VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+                VBOXCMDVBVA_CRCMD_BUFFER *pWbBuf = &pCmd->aBuffers[2];
+
+                /* Fetch parameters. */
+                uint32_t cbBuffer = pBuf->cbBuffer;
+                uint8_t *pBuffer  = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+                uint32_t cbWriteback = pWbBuf->cbBuffer;
+                char *pWriteback  = VBOXCRHGSMI_PTR_SAFE(pWbBuf->offBuffer, cbWriteback, char);
+
+                if (cbHdr < sizeof (*pFnCmd))
+                {
+                    crWarning("invalid write_read cmd buffer size!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+
+                CRASSERT(cbBuffer);
+                if (!pBuffer)
+                {
+                    crWarning("invalid write buffer data received from guest!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                CRASSERT(cbWriteback);
+                if (!pWriteback)
+                {
+                    crWarning("invalid writeback buffer data received from guest!");
+                    rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+                rc = crVBoxServerClientGet(u32ClientID, &pClient);
+                if (RT_FAILURE(rc))
+                {
+                    pHdr->result = rc;
+                    return VINF_SUCCESS;
+                }
+
+                /* This should never fire unless we start to multithread */
+                CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+                pClient->conn->pBuffer = pBuffer;
+                pClient->conn->cbBuffer = cbBuffer;
+                CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback, false);
+                rc = crVBoxServerInternalClientWriteRead(pClient);
+                CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+                return rc;
+            }
+
+            crWarning("invalid number of args");
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        case SHCRGL_GUEST_FN_SET_VERSION:
+        {
+            crWarning("invalid function");
+            rc = VERR_NOT_IMPLEMENTED;
+            break;
+        }
+
+        case SHCRGL_GUEST_FN_SET_PID:
+        {
+            crWarning("invalid function");
+            rc = VERR_NOT_IMPLEMENTED;
+            break;
+        }
+
+        default:
+        {
+            crWarning("invalid function");
+            rc = VERR_NOT_IMPLEMENTED;
+            break;
+        }
 
-        /* no need to do anything here actually */
     }
 
-    if (fPosChanged || fSizeChanged)
+    /* we can be on fail only here */
+    CRASSERT(RT_FAILURE(rc));
+    pHdr->result = rc;
+
+    return rc;
+}
+
+static int32_t crVBoxServerCrCmdProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
+{
+    switch (pCmd->u8OpCode)
     {
-        PCR_DISPLAY pDisplay = crServerDisplayGetInitialized(sIndex);
-        if (pDisplay)
-            CrDpResize(pDisplay, SCREEN(sIndex).x, SCREEN(sIndex).y, SCREEN(sIndex).w, SCREEN(sIndex).h);
+        case VBOXCMDVBVA_OPTYPE_CRCMD:
+        {
+            VBOXCMDVBVA_CRCMD *pCrCmdDr = (VBOXCMDVBVA_CRCMD*)pCmd;
+            VBOXCMDVBVA_CRCMD_CMD *pCrCmd = &pCrCmdDr->Cmd;
+            int rc = crVBoxServerCmdVbvaCrCmdProcess(pCrCmd);
+            if (RT_SUCCESS(rc))
+            {
+            /* success */
+                pCmd->i8Result = 0;
+            }
+            else
+            {
+                crWarning("crVBoxServerCmdVbvaCrCmdProcess failed, rc %d", rc);
+                pCmd->i8Result = -1;
+            }
+            break;
+        }
+        case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID:
+        {
+            crVBoxServerCrCmdBltProcess(pCmd, cbCmd);
+            break;
+        }
+        default:
+            WARN(("unsupported command"));
+            pCmd->i8Result = -1;
     }
     return VINF_SUCCESS;
 }
 
+int32_t crVBoxServerCrCmdNotifyCmds()
+{
+    PVBOXCMDVBVA_HDR pCmd = NULL;
+    uint32_t cbCmd;
+
+    for (;;)
+    {
+        int rc = cr_server.CltInfo.pfnCmdGet(cr_server.CltInfo.hClient, &pCmd, &cbCmd);
+        if (rc == VINF_EOF)
+            return VINF_SUCCESS;
+        if (!RT_SUCCESS(rc))
+            return rc;
+
+        rc = crVBoxServerCrCmdProcess(pCmd, cbCmd);
+        if (!RT_SUCCESS(rc))
+            return rc;
+    }
+
+    /* should not be here! */
+    AssertFailed();
+    return VERR_INTERNAL_ERROR;
+}
 
-#ifdef VBOX_WITH_CRHGSMI
 /* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place.
  *
  * For now we need the notion of CrHgdmi commands in the crserver_lib to be able to complete it asynchronously once it is really processed.
@@ -3055,8 +3256,11 @@ DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t
  *
  * NOTE: it is ALWAYS responsibility of the crVBoxServerCrHgsmiCmd to complete the command!
  * */
+
+
 int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t cbCmd)
 {
+
     int32_t rc;
     uint32_t cBuffers = pCmd->cBuffers;
     uint32_t cParams;
@@ -3069,6 +3273,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
     if (!g_pvVRamBase)
     {
         crWarning("g_pvVRamBase is not initialized");
+
         crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_STATE);
         return VINF_SUCCESS;
     }
@@ -3076,6 +3281,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
     if (!cBuffers)
     {
         crWarning("zero buffers passed in!");
+
         crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
         return VINF_SUCCESS;
     }
@@ -3087,6 +3293,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
     if (!pHdr)
     {
         crWarning("invalid header buffer!");
+
         crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
         return VINF_SUCCESS;
     }
@@ -3094,6 +3301,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
     if (cbHdr < sizeof (*pHdr))
     {
         crWarning("invalid header buffer size!");
+
         crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
         return VINF_SUCCESS;
     }
@@ -3143,7 +3351,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
 
                 pClient->conn->pBuffer = pBuffer;
                 pClient->conn->cbBuffer = cbBuffer;
-                CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr);
+                CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, true);
                 rc = crVBoxServerInternalClientWriteRead(pClient);
                 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
                 return rc;
@@ -3198,7 +3406,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
 
                 pClient->conn->pBuffer = pBuffer;
                 pClient->conn->cbBuffer = cbBuffer;
-                CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr);
+                CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, true);
                 rc = crVBoxServerInternalClientWriteRead(pClient);
                 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
                 return rc;
@@ -3254,6 +3462,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
 
                 /* the read command is never pended, complete it right away */
                 pHdr->result = rc;
+
                 crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
                 return VINF_SUCCESS;
             }
@@ -3318,7 +3527,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
 
                 pClient->conn->pBuffer = pBuffer;
                 pClient->conn->cbBuffer = cbBuffer;
-                CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback);
+                CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback, true);
                 rc = crVBoxServerInternalClientWriteRead(pClient);
                 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
                 return rc;
@@ -3355,8 +3564,24 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
     /* we can be on fail only here */
     CRASSERT(RT_FAILURE(rc));
     pHdr->result = rc;
+
     crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
     return rc;
+
+}
+
+static DECLCALLBACK(bool) crVBoxServerHasData()
+{
+    HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+    for (;
+            hFb;
+            hFb = CrPMgrFbGetNextEnabled(hFb))
+    {
+        if (CrFbHas3DData(hFb))
+            return true;
+    }
+
+    return false;
 }
 
 int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl)
@@ -3370,6 +3595,7 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c
             PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)pCtl;
             g_pvVRamBase = (uint8_t*)pSetup->pvVRamBase;
             g_cbVRam = pSetup->cbVRam;
+            cr_server.CltInfo = *pSetup->pCrCmdClientInfo;
             rc = VINF_SUCCESS;
             break;
         }
@@ -3377,11 +3603,14 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c
         case VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END:
             rc = VINF_SUCCESS;
             break;
-        case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION:
+        case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB:
         {
-            PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION)pCtl;
+            PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB)pCtl;
             g_hCrHgsmiCompletion = pSetup->hCompletion;
             g_pfnCrHgsmiCompletion = pSetup->pfnCompletion;
+
+            pSetup->MainInterface.pfnHasData = crVBoxServerHasData;
+
             rc = VINF_SUCCESS;
             break;
         }
@@ -3398,4 +3627,5 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c
      * or Hgcm Host Fast Call commands that do require completion. All this details are hidden here */
     return rc;
 }
+
 #endif
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c
index 527b00f..e938599 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c
@@ -239,6 +239,10 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target
         cr_server.projectionOverride = GL_TRUE;
         break;
 
+    case GL_HH_SET_TMPCTX_MAKE_CURRENT:
+        /*we should not receive it from the guest! */
+        break;
+
     default:
         /* Pass the parameter info to the head SPU */
         cr_server.head_spu->dispatch_table.ChromiumParametervCR( target, type, count, values );
@@ -671,8 +675,8 @@ PCR_BLITTER crServerVBoxBlitterGet()
         int rc;
         CRASSERT(cr_server.MainContextInfo.SpuContext);
         Ctx.Base.id = cr_server.MainContextInfo.SpuContext;
-        Ctx.Base.visualBits = cr_server.MainContextInfo.CreateInfo.visualBits;
-        rc = CrBltInit(&cr_server.Blitter, &Ctx, true, true, NULL, &cr_server.head_spu->dispatch_table);
+        Ctx.Base.visualBits = cr_server.MainContextInfo.CreateInfo.realVisualBits;
+        rc = CrBltInit(&cr_server.Blitter, &Ctx, true, true, NULL, &cr_server.TmpCtxDispatch);
         if (RT_SUCCESS(rc))
         {
             CRASSERT(CrBltIsInitialized(&cr_server.Blitter));
@@ -684,9 +688,27 @@ PCR_BLITTER crServerVBoxBlitterGet()
             return NULL;
         }
     }
+
+    if (!CrBltMuralGetCurrentInfo(&cr_server.Blitter)->Base.id)
+    {
+        CRMuralInfo *dummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+        CR_BLITTER_WINDOW DummyInfo;
+        CRASSERT(dummy);
+        crServerVBoxBlitterWinInit(&DummyInfo, dummy);
+        CrBltMuralSetCurrentInfo(&cr_server.Blitter, &DummyInfo);
+    }
+
     return &cr_server.Blitter;
 }
 
+PCR_BLITTER crServerVBoxBlitterGetInitialized()
+{
+    if (CrBltIsInitialized(&cr_server.Blitter))
+        return &cr_server.Blitter;
+    return NULL;
+}
+
+
 int crServerVBoxBlitterTexInit(CRContext *ctx, CRMuralInfo *mural, PVBOXVR_TEXTURE pTex, GLboolean fDraw)
 {
     CRTextureObj *tobj;
@@ -701,7 +723,7 @@ int crServerVBoxBlitterTexInit(CRContext *ctx, CRMuralInfo *mural, PVBOXVR_TEXTU
     {
         GLuint hwid;
 
-        if (!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
+        if (!mural->fRedirected)
             return VERR_NOT_IMPLEMENTED;
 
         enmBuf = fDraw ? ctx->buffer.drawBuffer : ctx->buffer.readBuffer;
@@ -846,14 +868,14 @@ int crServerVBoxBlitterBlitCurrentCtx(GLint srcX0, GLint srcY0, GLint srcX1, GLi
 
     crServerVBoxBlitterCtxInit(&Ctx, cr_server.curClient->currentCtxInfo);
 
-    CrBltMuralSetCurrent(pBlitter, &BltInfo);
+    CrBltMuralSetCurrentInfo(pBlitter, &BltInfo);
 
     idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
     idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
 
     crStateSwitchPrepare(NULL, ctx, idDrawFBO, idReadFBO);
 
-    rc = CrBltEnter(pBlitter, &Ctx, &BltInfo);
+    rc = CrBltEnter(pBlitter);
     if (RT_SUCCESS(rc))
     {
         RTRECT ReadRect, DrawRect;
@@ -1338,13 +1360,35 @@ crServerMakeTmpCtxCurrent( GLint window, GLint nativeWindow, GLint context )
 
     if (pCtx)
     {
-        GLint curSrvSpuCtx = cr_server.currentCtxInfo && cr_server.currentCtxInfo->SpuContext > 0 ? cr_server.currentCtxInfo->SpuContext : cr_server.MainContextInfo.SpuContext;
-        bool fSwitchToTmpCtx = (curSrvSpuCtx != context);
         CRMuralInfo *pCurrentMural = cr_server.currentMural;
-        CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
-        pCurCtx = pCurCtxInfo ? pCurCtxInfo->pContext : NULL;
 
-        CRASSERT(pCurCtx == pCtx);
+        pCurCtx = cr_server.currentCtxInfo ? cr_server.currentCtxInfo->pContext : cr_server.MainContextInfo.pContext;
+        Assert(pCurCtx == pCtx);
+
+        if (!context)
+        {
+            if (pCurrentMural)
+            {
+                Assert(cr_server.currentCtxInfo);
+                context = cr_server.currentCtxInfo->SpuContext > 0 ? cr_server.currentCtxInfo->SpuContext : cr_server.MainContextInfo.SpuContext;
+                window = pCurrentMural->spuWindow;
+            }
+            else
+            {
+                CRMuralInfo * pDummy;
+                Assert(!cr_server.currentCtxInfo);
+                pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+                context = cr_server.MainContextInfo.SpuContext;
+                window = pDummy->spuWindow;
+            }
+
+
+            fDoPrePostProcess = -1;
+        }
+        else
+        {
+            fDoPrePostProcess = 1;
+        }
 
         if (pCurrentMural)
         {
@@ -1356,8 +1400,6 @@ crServerMakeTmpCtxCurrent( GLint window, GLint nativeWindow, GLint context )
             idDrawFBO = 0;
             idReadFBO = 0;
         }
-
-        fDoPrePostProcess = fSwitchToTmpCtx ? 1 : -1;
     }
     else
     {
@@ -1375,9 +1417,15 @@ crServerMakeTmpCtxCurrent( GLint window, GLint nativeWindow, GLint context )
 
 void crServerInitTmpCtxDispatch()
 {
+    MakeCurrentFunc_t pfnMakeCurrent;
+
     crSPUInitDispatchTable(&cr_server.TmpCtxDispatch);
     crSPUCopyDispatchTable(&cr_server.TmpCtxDispatch, &cr_server.head_spu->dispatch_table);
     cr_server.TmpCtxDispatch.MakeCurrent = crServerMakeTmpCtxCurrent;
+
+    pfnMakeCurrent = crServerMakeTmpCtxCurrent;
+    cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_TMPCTX_MAKE_CURRENT, GL_BYTE, sizeof (void*), &pfnMakeCurrent);
+
 }
 
 /* dump stuff */
@@ -1397,8 +1445,13 @@ void crServerInitTmpCtxDispatch()
 
 int64_t g_CrDbgDumpPid = 0;
 unsigned long g_CrDbgDumpEnabled = 0;
-unsigned long g_CrDbgDumpDraw = CR_SERVER_DUMP_F_COMPILE_SHADER
+unsigned long g_CrDbgDumpDraw = 0
+#if 0
+        | CR_SERVER_DUMP_F_COMPILE_SHADER
         | CR_SERVER_DUMP_F_LINK_PROGRAM
+#endif
+        ;
+#if 0
         | CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
         | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
         | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER
@@ -1409,7 +1462,8 @@ unsigned long g_CrDbgDumpDraw = CR_SERVER_DUMP_F_COMPILE_SHADER
         | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER
         | CR_SERVER_DUMP_F_DRAWEL
         | CR_SERVER_DUMP_F_SHADER_SOURCE
-        ; //CR_SERVER_DUMP_F_DRAW_BUFF_ENTER | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE;
+        ;
+#endif
 unsigned long g_CrDbgDumpDrawFramesSettings = CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
         | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
         | CR_SERVER_DUMP_F_DRAW_TEX_ENTER
@@ -1421,6 +1475,25 @@ unsigned long g_CrDbgDumpDrawFramesAppliedSettings = 0;
 unsigned long g_CrDbgDumpDrawFramesSavedInitSettings = 0;
 unsigned long g_CrDbgDumpDrawFramesCount = 0;
 
+uint32_t g_CrDbgDumpDrawCount = 0;
+uint32_t g_CrDbgDumpDumpOnCount = 10;
+uint32_t g_CrDbgDumpDumpOnCountEnabled = 0;
+uint32_t g_CrDbgDumpDumpOnCountPerform = 0;
+uint32_t g_CrDbgDumpDrawFlags = CR_SERVER_DUMP_F_COMPILE_SHADER
+        | CR_SERVER_DUMP_F_SHADER_SOURCE
+        | CR_SERVER_DUMP_F_COMPILE_SHADER
+        | CR_SERVER_DUMP_F_LINK_PROGRAM
+        | CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
+        | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
+        | CR_SERVER_DUMP_F_DRAW_TEX_ENTER
+        | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER
+        | CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_ENTER
+        | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER
+        | CR_SERVER_DUMP_F_DRAW_STATE_ENTER
+        | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER
+        | CR_SERVER_DUMP_F_DRAWEL
+        | CR_SERVER_DUMP_F_TEXPRESENT;
+
 void crServerDumpCheckTerm()
 {
     if (!CrBltIsInitialized(&cr_server.RecorderBlitter))
@@ -1436,39 +1509,45 @@ int crServerDumpCheckInit()
     CR_BLITTER_CONTEXT BltCtx;
     CRMuralInfo *pBlitterMural;
 
-    if (CrBltIsInitialized(&cr_server.RecorderBlitter))
-        return VINF_SUCCESS;
-
-    pBlitterMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
-    if (!pBlitterMural)
+    if (!CrBltIsInitialized(&cr_server.RecorderBlitter))
     {
-        crWarning("crServerGetDummyMural failed");
-        return VERR_GENERAL_FAILURE;
-    }
+        pBlitterMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+        if (!pBlitterMural)
+        {
+            crWarning("crServerGetDummyMural failed");
+            return VERR_GENERAL_FAILURE;
+        }
 
-    crServerVBoxBlitterWinInit(&BltWin, pBlitterMural);
-    crServerVBoxBlitterCtxInit(&BltCtx, &cr_server.MainContextInfo);
+        crServerVBoxBlitterWinInit(&BltWin, pBlitterMural);
+        crServerVBoxBlitterCtxInit(&BltCtx, &cr_server.MainContextInfo);
 
-    rc = CrBltInit(&cr_server.RecorderBlitter, &BltCtx, true, true, NULL, &cr_server.TmpCtxDispatch);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrBltInit failed rc %d", rc);
-        return rc;
-    }
+        rc = CrBltInit(&cr_server.RecorderBlitter, &BltCtx, true, true, NULL, &cr_server.TmpCtxDispatch);
+        if (!RT_SUCCESS(rc))
+        {
+            crWarning("CrBltInit failed rc %d", rc);
+            return rc;
+        }
 
-    rc = CrBltMuralSetCurrent(&cr_server.RecorderBlitter, &BltWin);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrBltMuralSetCurrent failed rc %d", rc);
-        return rc;
+        rc = CrBltMuralSetCurrentInfo(&cr_server.RecorderBlitter, &BltWin);
+        if (!RT_SUCCESS(rc))
+        {
+            crWarning("CrBltMuralSetCurrentInfo failed rc %d", rc);
+            return rc;
+        }
     }
 
 #if 0
     crDmpDbgPrintInit(&cr_server.DbgPrintDumper);
     cr_server.pDumper = &cr_server.DbgPrintDumper.Base;
 #else
-    crDmpHtmlInit(&cr_server.HtmlDumper, "S:\\projects\\virtualbox\\3d\\dumps\\1", "index.html");
-    cr_server.pDumper = &cr_server.HtmlDumper.Base;
+    if (!crDmpHtmlIsInited(&cr_server.HtmlDumper))
+    {
+        static int cCounter = 0;
+//    crDmpHtmlInit(&cr_server.HtmlDumper, "S:\\projects\\virtualbox\\3d\\dumps\\1", "index.html");
+        crDmpHtmlInitF(&cr_server.HtmlDumper, "/Users/oracle-mac/vbox/dump/1", "index%d.html", cCounter);
+        cr_server.pDumper = &cr_server.HtmlDumper.Base;
+        ++cCounter;
+    }
 #endif
 
     crRecInit(&cr_server.Recorder, &cr_server.RecorderBlitter, &cr_server.TmpCtxDispatch, cr_server.pDumper);
@@ -1629,15 +1708,57 @@ void crServerDumpTextures()
 
 void crServerDumpFilterOpLeave(unsigned long event, CR_DUMPER *pDumper)
 {
+    if (CR_SERVER_DUMP_F_DRAW_LEAVE_ALL & event)
+    {
+        g_CrDbgDumpDumpOnCountPerform = 0;
+    }
 }
 
 bool crServerDumpFilterOpEnter(unsigned long event, CR_DUMPER *pDumper)
 {
+    if ((CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER & event)
+            || (CR_SERVER_DUMP_F_TEXPRESENT & event))
+    {
+        if (g_CrDbgDumpDumpOnCountEnabled == 1)
+            g_CrDbgDumpDumpOnCountEnabled = 2;
+        else if (g_CrDbgDumpDumpOnCountEnabled)
+        {
+            g_CrDbgDumpDumpOnCountEnabled = 0;
+            if (cr_server.pDumper == &cr_server.HtmlDumper.Base)
+            {
+                crDmpHtmlTerm(&cr_server.HtmlDumper);
+                cr_server.pDumper = NULL;
+            }
+        }
+
+        g_CrDbgDumpDrawCount = 0;
+    }
+    else if (CR_SERVER_DUMP_F_DRAW_ENTER_ALL & event)
+    {
+        if (g_CrDbgDumpDumpOnCountEnabled == 2)
+        {
+            if (g_CrDbgDumpDumpOnCount == g_CrDbgDumpDrawCount)
+            {
+                g_CrDbgDumpDumpOnCountPerform = 1;
+            }
+            ++g_CrDbgDumpDrawCount;
+        }
+    }
+    if (g_CrDbgDumpDumpOnCountPerform)
+    {
+        if (g_CrDbgDumpDrawFlags & event)
+            return true;
+    }
     return CR_SERVER_DUMP_DEFAULT_FILTER_OP(event);
 }
 
 bool crServerDumpFilterDmp(unsigned long event, CR_DUMPER *pDumper)
 {
+    if (g_CrDbgDumpDumpOnCountPerform)
+    {
+        if (g_CrDbgDumpDrawFlags & event)
+            return true;
+    }
     return CR_SERVER_DUMP_DEFAULT_FILTER_DMP(event);
 }
 
@@ -1672,4 +1793,132 @@ void crServerDumpFramesCheck()
     }
 }
 #endif
-/* */
+
+GLvoid crServerSpriteCoordReplEnable(GLboolean fEnable)
+{
+    CRContext *g = crStateGetCurrent();
+    CRTextureState *t = &(g->texture);
+    GLuint curTextureUnit = t->curTextureUnit;
+    GLuint curTextureUnitRestore = curTextureUnit;
+    GLuint i;
+
+    for (i = 0; i < g->limits.maxTextureUnits; ++i)
+    {
+        if (g->point.coordReplacement[i])
+        {
+            if (i != curTextureUnit)
+            {
+                curTextureUnit = i;
+                cr_server.head_spu->dispatch_table.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+            }
+
+            cr_server.head_spu->dispatch_table.TexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, (GLint)fEnable);
+        }
+    }
+
+    if (curTextureUnit != curTextureUnitRestore)
+    {
+        cr_server.head_spu->dispatch_table.ActiveTextureARB( curTextureUnitRestore + GL_TEXTURE0_ARB );
+    }
+}
+
+GLvoid SERVER_DISPATCH_APIENTRY crServerDispatchDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+#ifdef DEBUG
+    GLenum status = cr_server.head_spu->dispatch_table.CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
+    Assert(GL_FRAMEBUFFER_COMPLETE == status);
+#endif
+    if (mode == GL_POINTS)
+        crServerSpriteCoordReplEnable(GL_TRUE);
+    CR_SERVER_DUMP_DRAW_ENTER();
+    CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.DrawArrays(mode, first, count););
+    CR_SERVER_DUMP_DRAW_LEAVE();
+    if (mode == GL_POINTS)
+        crServerSpriteCoordReplEnable(GL_FALSE);
+}
+
+GLvoid SERVER_DISPATCH_APIENTRY crServerDispatchDrawElements(GLenum mode,  GLsizei count,  GLenum type,  const GLvoid * indices)
+{
+#ifdef DEBUG
+    GLenum status = cr_server.head_spu->dispatch_table.CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
+    Assert(GL_FRAMEBUFFER_COMPLETE == status);
+#endif
+    if (mode == GL_POINTS)
+        crServerSpriteCoordReplEnable(GL_TRUE);
+    CR_SERVER_DUMP_DRAW_ENTER();
+    CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.DrawElements(mode, count, type, indices););
+    CR_SERVER_DUMP_DRAW_LEAVE();
+    if (mode == GL_POINTS)
+        crServerSpriteCoordReplEnable(GL_FALSE);
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchEnd( void )
+{
+    CRContext *g = crStateGetCurrent();
+    GLenum mode = g->current.mode;
+
+    crStateEnd();
+    cr_server.head_spu->dispatch_table.End();
+
+    CR_SERVER_DUMP_DRAW_LEAVE();
+
+    if (mode == GL_POINTS)
+        crServerSpriteCoordReplEnable(GL_FALSE);
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchBegin(GLenum mode)
+{
+#ifdef DEBUG
+    CRContext *ctx = crStateGetCurrent();
+    SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
+
+    if (ctx->program.vpProgramBinding)
+    {
+        AssertRelease(ctx->program.currentVertexProgram);
+
+        if (ctx->program.currentVertexProgram->isARBprogram)
+        {
+            GLint pid=-1;
+            gl->GetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &pid);
+
+            if (pid != ctx->program.currentVertexProgram->id)
+            {
+                crWarning("pid(%d) != ctx->program.currentVertexProgram->id(%d)", pid, ctx->program.currentVertexProgram->id);
+            }
+            AssertRelease(pid == ctx->program.currentVertexProgram->id);
+        }
+        else
+        {
+            GLint pid=-1;
+
+            gl->GetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &pid);
+            if (pid != ctx->program.currentVertexProgram->id)
+            {
+                crWarning("pid(%d) != ctx->program.currentVertexProgram->id(%d)", pid, ctx->program.currentVertexProgram->id);
+            }
+            AssertRelease(pid == ctx->program.currentVertexProgram->id);
+        }
+    }
+    else if (ctx->glsl.activeProgram)
+    {
+        GLint pid=-1;
+
+        gl->GetIntegerv(GL_CURRENT_PROGRAM, &pid);
+        crDebug("pid %i, state: id %i, hwid %i", pid, ctx->glsl.activeProgram->id, ctx->glsl.activeProgram->hwid);
+        if (pid != ctx->glsl.activeProgram->hwid)
+        {
+            crWarning("pid(%d) != ctx->glsl.activeProgram->hwid(%d)", pid, ctx->glsl.activeProgram->hwid);
+        }
+        AssertRelease(pid == ctx->glsl.activeProgram->hwid);
+    }
+#endif
+
+    if (mode == GL_POINTS)
+        crServerSpriteCoordReplEnable(GL_TRUE);
+
+    CR_SERVER_DUMP_DRAW_ENTER();
+
+    crStateBegin(mode);
+    cr_server.head_spu->dispatch_table.Begin(mode);
+}
+
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c
deleted file mode 100644
index dd4b4de..0000000
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/* $Id: server_muralfbo.c $ */
-
-/** @file
- * VBox crOpenGL: Window to FBO redirect support.
- */
-
-/*
- * Copyright (C) 2010-2013 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "server.h"
-#include "cr_string.h"
-#include "cr_mem.h"
-#include "cr_vreg.h"
-#include "render/renderspu.h"
-
-static int crServerGetPointScreen(GLint x, GLint y)
-{
-    int i;
-
-    for (i=0; i<cr_server.screenCount; ++i)
-    {
-        if ((x>=cr_server.screen[i].x && x<cr_server.screen[i].x+(int)cr_server.screen[i].w)
-           && (y>=cr_server.screen[i].y && y<cr_server.screen[i].y+(int)cr_server.screen[i].h))
-        {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-static GLboolean crServerMuralCoverScreen(CRMuralInfo *mural, int sId)
-{
-    return mural->gX < cr_server.screen[sId].x
-           && mural->gX+(int)mural->width > cr_server.screen[sId].x+(int)cr_server.screen[sId].w
-           && mural->gY < cr_server.screen[sId].y
-           && mural->gY+(int)mural->height > cr_server.screen[sId].y+(int)cr_server.screen[sId].h;
-}
-
-void crServerDEntryResized(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
-{
-    /*PBO*/
-    if (pDEntry->idPBO)
-    {
-        CRASSERT(cr_server.bUsePBOForReadback);
-        cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
-        pDEntry->idPBO = 0;
-    }
-
-    if (pDEntry->idInvertTex)
-    {
-        cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
-        pDEntry->idInvertTex = 0;
-    }
-
-    if (pDEntry->pvORInstance)
-    {
-        cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
-                                                pMural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
-                                                pMural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
-                                                CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
-                                                CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
-
-        crServerDEntryVibleRegions(pMural, pDEntry);
-    }
-}
-
-void crServerDEntryMoved(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
-{
-    if (pDEntry->pvORInstance)
-    {
-        cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
-                                                pMural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
-                                                pMural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
-                                                CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
-                                                CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
-
-        crServerDEntryVibleRegions(pMural, pDEntry);
-    }
-
-}
-
-void crServerDEntryVibleRegions(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
-{
-    if (pDEntry->pvORInstance)
-    {
-        uint32_t cRects;
-        const RTRECT *pRects;
-
-        int rc = CrVrScrCompositorEntryRegionsGet(&pMural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
-            return;
-        }
-
-        cr_server.outputRedirect.CRORVisibleRegion(pDEntry->pvORInstance, cRects, pRects);
-    }
-}
-
-/***/
-void crServerDEntryAllResized(CRMuralInfo *pMural)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-
-    CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-        crServerDEntryResized(pMural, pDEntry);
-    }
-}
-
-void crServerDEntryAllMoved(CRMuralInfo *pMural)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-
-    CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
-
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-        crServerDEntryMoved(pMural, pDEntry);
-    }
-}
-
-void crServerDEntryAllVibleRegions(CRMuralInfo *pMural)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-
-    CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
-
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-        crServerDEntryVibleRegions(pMural, pDEntry);
-    }
-}
-/**/
-
-void crServerDEntryCheckFBO(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx)
-{
-    if (!cr_server.bUsePBOForReadback == !pDEntry->idPBO)
-        return;
-
-    if (cr_server.bUsePBOForReadback)
-    {
-        Assert(!pDEntry->idPBO);
-        cr_server.head_spu->dispatch_table.GenBuffersARB(1, &pDEntry->idPBO);
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pDEntry->idPBO);
-        cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
-                CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width*CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height*4,
-                0, GL_STREAM_READ_ARB);
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
-
-        if (!pDEntry->idPBO)
-        {
-            crWarning("PBO create failed");
-        }
-    }
-}
-
-void crServerDEntryCheckInvertTex(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx)
-{
-    CRContextInfo *pMuralContextInfo;
-
-    if (pDEntry->idInvertTex)
-        return;
-
-    pMuralContextInfo = cr_server.currentCtxInfo;
-    if (!pMuralContextInfo)
-    {
-        /* happens on saved state load */
-        CRASSERT(cr_server.MainContextInfo.SpuContext);
-        pMuralContextInfo = &cr_server.MainContextInfo;
-        cr_server.head_spu->dispatch_table.MakeCurrent(pMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
-    }
-
-    if (pMuralContextInfo->CreateInfo.visualBits != pMural->CreateInfo.visualBits)
-    {
-        crWarning("mural visual bits do not match with current context visual bits!");
-    }
-
-    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
-    {
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
-    }
-
-    cr_server.head_spu->dispatch_table.GenTextures(1, &pDEntry->idInvertTex);
-    CRASSERT(pDEntry->idInvertTex);
-    cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, pDEntry->idInvertTex);
-    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-    cr_server.head_spu->dispatch_table.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
-            CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
-            CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height,
-            0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-
-
-    /*Restore gl state*/
-    cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D,
-            ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid);
-
-    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
-    {
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
-    }
-
-    if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
-    {
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
-    }
-    else
-    {
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
-    }
-}
-
-void crServerDEntryImgRelease(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, void*pvImg)
-{
-    GLuint idPBO;
-    CRContext *ctx = crStateGetCurrent();
-
-    idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
-
-    CrHlpFreeTexImage(ctx, idPBO, pvImg);
-}
-
-
-void* crServerDEntryImgAcquire(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, GLenum enmFormat)
-{
-    void* pvData;
-    GLuint idPBO;
-    VBOXVR_TEXTURE Tex;
-    const VBOXVR_TEXTURE * pTex;
-    CRContext *ctx = crStateGetCurrent();
-
-    crServerDEntryCheckFBO(pMural, pDEntry, ctx);
-
-    if (cr_server.bUsePBOForReadback && !pDEntry->idPBO)
-    {
-        crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
-    }
-
-    idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
-
-    if (!(CrVrScrCompositorEntryFlagsGet(&pDEntry->CEntry) & CRBLT_F_INVERT_SRC_YCOORDS))
-        pTex = CrVrScrCompositorEntryTexGet(&pDEntry->CEntry);
-    else
-    {
-        CRMuralInfo *pCurrentMural = cr_server.currentMural;
-        CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
-        PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
-        CRMuralInfo *pBlitterMural;
-        CR_SERVER_CTX_SWITCH CtxSwitch;
-        RTRECT SrcRect, DstRect;
-        CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
-        CR_BLITTER_CONTEXT CtxBltInfo;
-        int rc;
-
-        crServerDEntryCheckInvertTex(pMural, pDEntry, ctx);
-        if (!pDEntry->idInvertTex)
-        {
-            crWarning("crServerDEntryCheckInvertTex failed");
-            return NULL;
-        }
-
-        Tex = *CrVrScrCompositorEntryTexGet(&pDEntry->CEntry);
-        Tex.hwid = pDEntry->idInvertTex;
-
-        SrcRect.xLeft = 0;
-        SrcRect.yTop = Tex.height;
-        SrcRect.xRight = Tex.width;
-        SrcRect.yBottom = 0;
-
-        DstRect.xLeft = 0;
-        DstRect.yTop = 0;
-        DstRect.xRight = Tex.width;
-        DstRect.yBottom = Tex.height;
-
-        if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
-        {
-            pBlitterMural = pCurrentMural;
-        }
-        else
-        {
-            pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
-            if (!pBlitterMural)
-            {
-                crWarning("crServerGetDummyMural failed for blitter mural");
-                return NULL;
-            }
-        }
-
-        crServerCtxSwitchPrepare(&CtxSwitch, NULL);
-
-        crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
-        crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
-        crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
-
-        CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
-
-        rc =  CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
-        if (RT_SUCCESS(rc))
-        {
-            CrBltBlitTexTex(pBlitter, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry), &SrcRect, &Tex, &DstRect, 1, 0);
-            CrBltLeave(pBlitter);
-        }
-        else
-        {
-            crWarning("CrBltEnter failed rc %d", rc);
-        }
-
-        crServerCtxSwitchPostprocess(&CtxSwitch);
-
-        pTex = &Tex;
-    }
-
-    pvData = CrHlpGetTexImage(ctx, pTex, idPBO, enmFormat);
-    if (!pvData)
-        crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
-
-    return pvData;
-}
-
-
-/* Called when a new CRMuralInfo is created
- * or when OutputRedirect status is changed.
- */
-void crServerSetupOutputRedirectEntry(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry)
-{
-    /* Unset the previous redirect. */
-    if (pDEntry->pvORInstance)
-    {
-        cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
-        pDEntry->pvORInstance = NULL;
-    }
-
-    /* Setup a new redirect. */
-    if (cr_server.bUseOutputRedirect)
-    {
-        /* Query supported formats. */
-        uint32_t cbFormats = 4096;
-        char *pachFormats = (char *)crAlloc(cbFormats);
-
-        if (pachFormats)
-        {
-            int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
-                                                                  0 /* H3DOR_PROP_FORMATS */, // @todo from a header
-                                                                  pachFormats, cbFormats, &cbFormats);
-            if (RT_SUCCESS(rc))
-            {
-                if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
-                {
-                    cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
-                                                       &pDEntry->pvORInstance,
-                                                       "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
-                }
-            }
-
-            crFree(pachFormats);
-        }
-
-        /* If this is not NULL then there was a supported format. */
-        if (pDEntry->pvORInstance)
-        {
-            uint32_t cRects;
-            const RTRECT *pRects;
-
-            int rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
-            if (!RT_SUCCESS(rc))
-            {
-                crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
-                return;
-            }
-
-            cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
-                                                  mural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
-                                                  mural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
-                                                  CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
-                                                  CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
-
-            cr_server.outputRedirect.CRORVisibleRegion(pDEntry->pvORInstance, cRects, pRects);
-//!!
-//            crServerPresentFBO(mural);
-        }
-    }
-}
-
-void crServerCheckMuralGeometry(CRMuralInfo *mural)
-{
-    int tlS, brS, trS, blS;
-    int overlappingScreenCount = 0, primaryS = -1 , i;
-    uint64_t winID = 0;
-    GLuint fPresentMode;
-
-    if (!mural->CreateInfo.externalID)
-        return;
-
-    CRASSERT(mural->spuWindow);
-    CRASSERT(mural->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID);
-
-    crServerVBoxCompositionDisableEnter(mural);
-
-    if (!mural->width || !mural->height)
-    {
-        crServerRedirMuralFBO(mural, CR_SERVER_REDIR_F_NONE);
-        crServerDeleteMuralFBO(mural);
-        crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
-        return;
-    }
-
-    tlS = crServerGetPointScreen(mural->gX, mural->gY);
-    brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
-
-    if ((tlS==brS && tlS>=0) || cr_server.screenCount <= 1)
-    {
-        if (cr_server.screenCount <= 1)
-        {
-            if (tlS != brS)
-            {
-                if (tlS >= 0)
-                    brS = tlS;
-                else
-                    tlS = brS;
-            }
-
-            primaryS = 0;
-        }
-        else
-        {
-            Assert(brS == tlS);
-
-            primaryS = brS;
-        }
-
-
-        Assert(brS == tlS);
-
-        if (tlS>=0 && cr_server.screen[tlS].winID)
-        {
-            overlappingScreenCount = 1;
-        }
-    }
-    else
-    {
-        bool fFoundWindIdScreen = false;
-        trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
-        blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
-
-        primaryS = -1; overlappingScreenCount = 0;
-        for (i=0; i<cr_server.screenCount; ++i)
-        {
-            if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
-                || crServerMuralCoverScreen(mural, i))
-            {
-                if ((!fFoundWindIdScreen && cr_server.screen[i].winID) || primaryS<0)
-                    primaryS = i;
-
-                if (cr_server.screen[i].winID)
-                {
-                    overlappingScreenCount++;
-                    fFoundWindIdScreen = true;
-                }
-            }
-        }
-
-        if (primaryS<0)
-        {
-            primaryS = 0;
-        }
-    }
-
-    CRASSERT(primaryS >= 0);
-
-    winID = overlappingScreenCount ? cr_server.screen[primaryS].winID : 0;
-
-    if (!winID != !mural->fHasParentWindow
-            || (winID && primaryS!=mural->screenId))
-    {
-        mural->fHasParentWindow = !!winID;
-
-        renderspuSetWindowId(winID);
-        renderspuReparentWindow(mural->spuWindow);
-        renderspuSetWindowId(cr_server.screen[0].winID);
-    }
-
-    if (primaryS != mural->screenId)
-    {
-        /* mark it invisible on the old screen */
-        crServerWindowSetIsVisible(mural, GL_FALSE);
-        mural->screenId = primaryS;
-        /* check if mural is visivle on the new screen, and mark it as such */
-        crServerWindowCheckIsVisible(mural);
-    }
-
-    mural->hX = mural->gX-cr_server.screen[primaryS].x;
-    mural->hY = mural->gY-cr_server.screen[primaryS].y;
-
-    fPresentMode = cr_server.fPresentMode;
-
-    if (!mural->fHasParentWindow)
-        fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
-
-    if (!overlappingScreenCount)
-        fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
-    else if (overlappingScreenCount > 1)
-        fPresentMode = (fPresentMode | CR_SERVER_REDIR_F_FBO_RAM_VMFB | cr_server.fVramPresentModeDefault) & ~CR_SERVER_REDIR_F_DISPLAY;
-
-    if (!mural->fUseDefaultDEntry)
-    {
-        /* only display matters */
-        fPresentMode &= CR_SERVER_REDIR_F_DISPLAY;
-    }
-
-    fPresentMode = crServerRedirModeAdjust(fPresentMode);
-
-    if (!(fPresentMode & CR_SERVER_REDIR_F_FBO))
-    {
-        crServerRedirMuralFBO(mural, fPresentMode);
-        crServerDeleteMuralFBO(mural);
-    }
-    else
-    {
-        if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO)
-        {
-            if (mural->width!=mural->fboWidth
-                || mural->height!=mural->fboHeight)
-            {
-                crServerRedirMuralFBO(mural, fPresentMode & CR_SERVER_REDIR_F_DISPLAY);
-                crServerDeleteMuralFBO(mural);
-            }
-        }
-
-        crServerRedirMuralFBO(mural, fPresentMode);
-    }
-
-    if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
-    {
-        CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
-
-        cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
-    }
-
-    crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
-}
-
-GLboolean crServerSupportRedirMuralFBO(void)
-{
-    static GLboolean fInited = GL_FALSE;
-    static GLboolean fSupported = GL_FALSE;
-    if (!fInited)
-    {
-        const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
-
-        fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
-                 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
-               && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
-        fInited = GL_TRUE;
-    }
-    return fSupported;
-}
-
-static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels);
-
-#define CR_SERVER_MURAL_FROM_RPW_ENTRY(_pEntry) ((CRMuralInfo*)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(CRMuralInfo, RpwEntry)))
-
-static DECLCALLBACK(void) crServerMuralRpwDataCB(const struct CR_SERVER_RPW_ENTRY* pEntry, void *pvEntryTexData)
-{
-    CRMuralInfo *pMural = CR_SERVER_MURAL_FROM_RPW_ENTRY(pEntry);
-
-    Assert(&pMural->RpwEntry == pEntry);
-    crError("port me!");
-    //    crServerPresentMuralVRAM(pMural, pvEntryTexData);
-}
-
-static void crServerCreateMuralFBO(CRMuralInfo *mural);
-
-static bool crServerEnableMuralRpw(CRMuralInfo *mural, GLboolean fEnable)
-{
-    if (!mural->CreateInfo.externalID)
-    {
-        crWarning("trying to change Rpw setting for internal mural %d", mural->spuWindow);
-        return !fEnable;
-    }
-
-    if (fEnable)
-    {
-        if (!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW))
-        {
-            int rc;
-            if (!crServerRpwIsInitialized(&cr_server.RpwWorker))
-            {
-                rc = crServerRpwInit(&cr_server.RpwWorker);
-                if (!RT_SUCCESS(rc))
-                {
-                    crWarning("crServerRpwInit failed rc %d", rc);
-                    return false;
-                }
-            }
-
-            CRASSERT(!mural->RpwEntry.Size.cx);
-            CRASSERT(!mural->RpwEntry.Size.cy);
-
-            if (!crServerRpwEntryIsInitialized(&mural->RpwEntry))
-            {
-                rc = crServerRpwEntryInit(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height, crServerMuralRpwDataCB);
-                if (!RT_SUCCESS(rc))
-                {
-                    crWarning("crServerRpwEntryInit failed rc %d", rc);
-                    return false;
-                }
-            }
-            else
-            {
-                rc = crServerRpwEntryResize(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height);
-                if (!RT_SUCCESS(rc))
-                {
-                    crWarning("crServerRpwEntryResize failed rc %d", rc);
-                    return false;
-                }
-            }
-
-            mural->fPresentMode |= CR_SERVER_REDIR_F_FBO_RPW;
-        }
-    }
-    else
-    {
-        if ((mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW))
-        {
-//            crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
-            mural->fPresentMode &= ~CR_SERVER_REDIR_F_FBO_RPW;
-        }
-    }
-
-    return true;
-}
-
-static void crServerEnableDisplayMuralFBO(CRMuralInfo *mural, GLboolean fEnable)
-{
-    if (!mural->CreateInfo.externalID)
-    {
-        crWarning("trying to change display setting for internal mural %d", mural->spuWindow);
-        return;
-    }
-
-    if (fEnable)
-    {
-        if (!(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
-        {
-            mural->fPresentMode |= CR_SERVER_REDIR_F_DISPLAY;
-
-            if  (mural->bVisible)
-                crServerWindowShow(mural);
-        }
-    }
-    else
-    {
-        if ((mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
-        {
-            mural->fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
-
-            if (mural->bVisible)
-                crServerWindowShow(mural);
-        }
-    }
-}
-
-void crServerRedirMuralFBO(CRMuralInfo *mural, GLuint redir)
-{
-    if (mural->fPresentMode == redir)
-    {
-//        if (redir)
-//            crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
-        return;
-    }
-
-    if (!mural->CreateInfo.externalID)
-    {
-        crWarning("trying to change redir setting for internal mural %d", mural->spuWindow);
-        return;
-    }
-
-    crServerVBoxCompositionDisableEnter(mural);
-
-    if (redir & CR_SERVER_REDIR_F_FBO)
-    {
-        if (!crServerSupportRedirMuralFBO())
-        {
-            crWarning("FBO not supported, can't redirect window output");
-            goto end;
-        }
-
-        if (mural->fUseDefaultDEntry && mural->aidFBOs[0]==0)
-        {
-            crServerCreateMuralFBO(mural);
-        }
-
-        if (cr_server.curClient && cr_server.curClient->currentMural == mural)
-        {
-            if (!crStateGetCurrent()->framebufferobject.drawFB)
-            {
-                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
-            }
-            if (!crStateGetCurrent()->framebufferobject.readFB)
-            {
-                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
-            }
-
-            crStateGetCurrent()->buffer.width = 0;
-            crStateGetCurrent()->buffer.height = 0;
-        }
-    }
-    else
-    {
-        if (cr_server.curClient && cr_server.curClient->currentMural == mural)
-        {
-            if (!crStateGetCurrent()->framebufferobject.drawFB)
-            {
-                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
-            }
-            if (!crStateGetCurrent()->framebufferobject.readFB)
-            {
-                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
-            }
-
-            crStateGetCurrent()->buffer.width = mural->width;
-            crStateGetCurrent()->buffer.height = mural->height;
-        }
-    }
-
-    crServerEnableMuralRpw(mural, !!(redir & CR_SERVER_REDIR_F_FBO_RPW));
-
-    crServerEnableDisplayMuralFBO(mural, !!(redir & CR_SERVER_REDIR_F_DISPLAY));
-
-    mural->fPresentMode = redir;
-
-end:
-    crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
-}
-
-static void crServerCreateMuralFBO(CRMuralInfo *mural)
-{
-    CRContext *ctx = crStateGetCurrent();
-    GLuint uid, i;
-    GLenum status;
-    SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
-    CRContextInfo *pMuralContextInfo;
-
-    CRASSERT(mural->aidFBOs[0]==0);
-    CRASSERT(mural->aidFBOs[1]==0);
-    CRASSERT(mural->fUseDefaultDEntry);
-    CRASSERT(mural->width == mural->DefaultDEntry.CEntry.Tex.width);
-    CRASSERT(mural->height == mural->DefaultDEntry.CEntry.Tex.height);
-
-    pMuralContextInfo = cr_server.currentCtxInfo;
-    if (!pMuralContextInfo)
-    {
-        /* happens on saved state load */
-        CRASSERT(cr_server.MainContextInfo.SpuContext);
-        pMuralContextInfo = &cr_server.MainContextInfo;
-        cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
-    }
-
-    if (pMuralContextInfo->CreateInfo.visualBits != mural->CreateInfo.visualBits)
-    {
-        crWarning("mural visual bits do not match with current context visual bits!");
-    }
-
-    mural->cBuffers = 2;
-    mural->iBbBuffer = 0;
-    /*Color texture*/
-
-    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
-    {
-        gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
-    }
-
-    for (i = 0; i < mural->cBuffers; ++i)
-    {
-        gl->GenTextures(1, &mural->aidColorTexs[i]);
-        gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-        gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
-                       0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-    }
-
-    /*Depth&Stencil*/
-    gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
-    gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
-    gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
-                           mural->width, mural->height);
-
-    /*FBO*/
-    for (i = 0; i < mural->cBuffers; ++i)
-    {
-        gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
-        gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
-
-        gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                                    GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
-        gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
-                                       GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
-        gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
-                                       GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
-
-        status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-        if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
-        {
-            crWarning("FBO status(0x%x) isn't complete", status);
-        }
-    }
-
-    mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
-    mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
-
-    mural->fboWidth = mural->width;
-    mural->fboHeight = mural->height;
-
-    mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
-    mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
-
-    /*Restore gl state*/
-    uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
-    gl->BindTexture(GL_TEXTURE_2D, uid);
-
-    uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
-    gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
-
-    uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
-    gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
-
-    uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
-    gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
-
-    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
-    {
-        gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
-    }
-
-    if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
-    {
-        gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
-    }
-    else
-    {
-        gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
-    }
-
-    CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-
-    CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-
-//    if (mural->fRootVrOn)
-//        CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-}
-
-void crServerDeleteMuralFBO(CRMuralInfo *mural)
-{
-    CRASSERT(!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO));
-
-    if (mural->aidFBOs[0]!=0)
-    {
-        GLuint i;
-        for (i = 0; i < mural->cBuffers; ++i)
-        {
-            cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
-            mural->aidColorTexs[i] = 0;
-        }
-
-        cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
-        mural->idDepthStencilRB = 0;
-
-        for (i = 0; i < mural->cBuffers; ++i)
-        {
-            cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
-            mural->aidFBOs[i] = 0;
-        }
-    }
-
-    mural->cBuffers = 0;
-
-    if (crServerRpwEntryIsInitialized(&mural->RpwEntry))
-        crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
-}
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
-static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
-{
-    CRASSERT(a && b && rect);
-
-    rect->x1 = MAX(a->x1, b->x1);
-    rect->x2 = MIN(a->x2, b->x2);
-    rect->y1 = MAX(a->y1, b->y1);
-    rect->y2 = MIN(a->y2, b->y2);
-
-    return (rect->x2>rect->x1) && (rect->y2>rect->y1);
-}
-
-static GLboolean crServerIntersectScreen(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, int sId, CRrecti *rect)
-{
-    rect->x1 = MAX(mural->gX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x, cr_server.screen[sId].x);
-    rect->x2 = MIN(mural->gX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x
-            + (int)CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
-            cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
-    rect->y1 = MAX(mural->gY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y, cr_server.screen[sId].y);
-    rect->y2 = MIN(mural->gY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y
-            + (int)CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height,
-            cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
-
-    return (rect->x2>rect->x1) && (rect->y2>rect->y1);
-}
-
-static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
-{
-    int i;
-    int dstrowsize = 4*(pRect->x2-pRect->x1);
-    int srcrowsize = 4*srcWidth;
-    int height = pRect->y2-pRect->y1;
-
-    pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
-
-    for (i=0; i<height; ++i)
-    {
-        crMemcpy(pDst, pSrc, dstrowsize);
-
-        pSrc -= srcrowsize;
-        pDst += dstrowsize;
-    }
-}
-
-static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
-{
-    pDst->x1 = pSrc->x1+dx;
-    pDst->x2 = pSrc->x2+dx;
-    pDst->y1 = pSrc->y1+dy;
-    pDst->y2 = pSrc->y2+dy;
-}
-
-static void crServerVBoxCompositionPresentPerform(CRMuralInfo *mural)
-{
-    CRMuralInfo *currentMural = cr_server.currentMural;
-    CRContextInfo *curCtxInfo = cr_server.currentCtxInfo;
-    GLuint idDrawFBO, idReadFBO;
-    CRContext *curCtx = curCtxInfo ? curCtxInfo->pContext : NULL;
-
-    CRASSERT(curCtx == crStateGetCurrent());
-
-    Assert((mural->fPresentMode & CR_SERVER_REDIR_F_FBO) || !mural->fUseDefaultDEntry);
-    Assert(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY);
-
-    mural->fDataPresented = GL_TRUE;
-
-    if (currentMural)
-    {
-        idDrawFBO = CR_SERVER_FBO_FOR_IDX(currentMural, currentMural->iCurDrawBuffer);
-        idReadFBO = CR_SERVER_FBO_FOR_IDX(currentMural, currentMural->iCurReadBuffer);
-    }
-    else
-    {
-        idDrawFBO = 0;
-        idReadFBO = 0;
-    }
-
-    crStateSwitchPrepare(NULL, curCtx, idDrawFBO, idReadFBO);
-
-    if (!mural->fRootVrOn)
-        cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->Compositor, NULL);
-    else
-        cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->RootVrCompositor, NULL);
-
-    crStateSwitchPostprocess(curCtx, NULL, idDrawFBO, idReadFBO);
-}
-
-void crServerVBoxCompositionPresent(CRMuralInfo *mural)
-{
-    if (!crServerVBoxCompositionPresentNeeded(mural))
-        return;
-    crServerVBoxCompositionPresentPerform(mural);
-}
-
-static void crServerVBoxCompositionReenable(CRMuralInfo *mural)
-{
-    GLboolean fForcePresent = mural->fForcePresentState;
-    GLboolean fOrPresentOnReenable = mural->fOrPresentOnReenable;
-
-    mural->fForcePresentState = GL_FALSE;
-    mural->fOrPresentOnReenable = GL_FALSE;
-
-    if ((mural->fUseDefaultDEntry && !(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
-            || !mural->fDataPresented
-            || (!fForcePresent
-                    && !crServerVBoxCompositionPresentNeeded(mural)))
-        return;
-
-    if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
-        crServerVBoxCompositionPresentPerform(mural);
-
-    if (fOrPresentOnReenable
-            && cr_server.bUseOutputRedirect
-            && crServerVBoxCompositionPresentNeeded(mural))
-        crServerPresentOutputRedirect(mural);
-}
-
-static void crServerVBoxCompositionDisable(CRMuralInfo *mural)
-{
-    if (!(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
-            || (mural->fUseDefaultDEntry && !(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
-            || !mural->fDataPresented)
-        return;
-    cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, NULL, NULL);
-}
-
-void crServerVBoxCompositionDisableEnter(CRMuralInfo *mural)
-{
-    ++cr_server.cDisableEvents;
-    Assert(cr_server.cDisableEvents);
-
-    ++mural->cDisabled;
-    Assert(mural->cDisabled);
-    if (mural->cDisabled == 1)
-    {
-        crServerVBoxCompositionDisable(mural);
-    }
-}
-
-void crServerVBoxCompositionDisableLeave(CRMuralInfo *mural, GLboolean fForcePresentOnEnabled)
-{
-    mural->fForcePresentState |= fForcePresentOnEnabled;
-    --mural->cDisabled;
-    Assert(mural->cDisabled < UINT32_MAX/2);
-    if (!mural->cDisabled)
-    {
-        crServerVBoxCompositionReenable(mural);
-    }
-
-    --cr_server.cDisableEvents;
-    Assert(cr_server.cDisableEvents < UINT32_MAX/2);
-    crVBoxServerCheckVisibilityEvent(-1);
-}
-
-static void crServerVBoxCompositionSetEnableStateGlobalCB(unsigned long key, void *data1, void *data2)
-{
-    CRMuralInfo *mural = (CRMuralInfo *)data1;
-
-    if (data2)
-        crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
-    else
-        crServerVBoxCompositionDisableEnter(mural);
-}
-
-DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
-{
-    int i;
-
-    crHashtableWalk(cr_server.muralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
-
-    crHashtableWalk(cr_server.dummyMuralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
-
-    for (i = 0; i < cr_server.screenCount; ++i)
-    {
-        PCR_DISPLAY pDisplay = crServerDisplayGetInitialized((uint32_t)i);
-        if (!pDisplay)
-            continue;
-
-        if (!fEnable)
-            CrDpEnter(pDisplay);
-        else
-            CrDpLeave(pDisplay);
-    }
-}
-
-static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels)
-{
-    char *tmppixels;
-    CRrecti rect, rectwr, sectr;
-    int i, rc;
-    uint32_t j;
-
-    if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RAM_VMFB)
-    {
-        for (i=0; i<cr_server.screenCount; ++i)
-        {
-            if (crServerIntersectScreen(mural, pDEntry, i, &rect))
-            {
-                uint32_t cRects;
-                const RTRECT *pRects;
-
-                /* rect in window relative coords */
-                crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
-
-                rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
-                if (RT_SUCCESS(rc))
-                {
-                    /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
-                    for (j=0; j<cRects; ++j)
-                    {
-                        if (crServerIntersectRect(&rectwr, (CRrecti*)&pRects[j], &sectr))
-                        {
-                            tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
-                            if (!tmppixels)
-                            {
-                                crWarning("Out of memory in crServerPresentFBO");
-                                crFree(pixels);
-                                return;
-                            }
-
-                            crServerCopySubImage(tmppixels, pixels, &sectr, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
-                            /*Note: pfnPresentFBO would free tmppixels*/
-                            cr_server.pfnPresentFBO(tmppixels, i,
-                                                    sectr.x1+mural->gX+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x-cr_server.screen[i].x,
-                                                    sectr.y1+mural->gY+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y-cr_server.screen[i].y,
-                                                    sectr.x2-sectr.x1, sectr.y2-sectr.y1);
-                        }
-                    }
-                }
-                else
-                {
-                    crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
-                }
-            }
-        }
-    }
-
-    if (pDEntry->pvORInstance)
-    {
-        /* @todo find out why presentfbo is not called but crorframe is called. */
-        cr_server.outputRedirect.CRORFrame(pDEntry->pvORInstance,
-                                           pixels,
-                                           4 * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
-    }
-}
-
-void crServerPresentOutputRedirectEntry(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
-{
-    char *pixels=NULL;
-
-    if (!pDEntry->pvORInstance)
-    {
-        crServerSetupOutputRedirectEntry(pMural, pDEntry);
-        if (!pDEntry->pvORInstance)
-        {
-            crWarning("crServerSetupOutputRedirectEntry failed!");
-            return;
-        }
-    }
-
-    if (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW)
-    {
-        crError("port me!");
-#if 0
-        /* 1. blit to RPW entry draw texture */
-        CRMuralInfo *pCurrentMural = cr_server.currentMural;
-        CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
-        PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
-        CRMuralInfo *pBlitterMural;
-        CR_SERVER_CTX_SWITCH CtxSwitch;
-        RTRECT Rect;
-        VBOXVR_TEXTURE DstTex;
-        CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
-        CR_BLITTER_CONTEXT CtxBltInfo;
-        int rc;
-
-        Rect.xLeft = 0;
-        Rect.yTop = 0;
-        Rect.xRight = Tex.width;
-        Rect.yBottom = Tex.height;
-
-        if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
-        {
-            pBlitterMural = pCurrentMural;
-        }
-        else
-        {
-            pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
-            if (!pBlitterMural)
-            {
-                crWarning("crServerGetDummyMural failed for blitter mural");
-                return;
-            }
-        }
-
-        crServerRpwEntryDrawSettingsToTex(&mural->RpwEntry, &DstTex);
-
-        crServerCtxSwitchPrepare(&CtxSwitch, NULL);
-
-        crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
-        crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
-        crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
-
-        CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
-
-        rc =  CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
-        if (RT_SUCCESS(rc))
-        {
-            CrBltBlitTexTex(pBlitter, &Tex, &Rect, &DstTex, &Rect, 1, 0);
-            CrBltLeave(pBlitter);
-        }
-        else
-        {
-            crWarning("CrBltEnter failed rc %d", rc);
-        }
-
-        crServerCtxSwitchPostprocess(&CtxSwitch);
-
-#if 1
-        if (RT_SUCCESS(rc))
-        {
-            /* 2. submit RPW entry */
-            rc =  crServerRpwEntrySubmit(&cr_server.RpwWorker, &mural->RpwEntry);
-            if (!RT_SUCCESS(rc))
-            {
-                crWarning("crServerRpwEntrySubmit failed rc %d", rc);
-            }
-        }
-#endif
-#endif
-        return;
-    }
-
-    pixels = crServerDEntryImgAcquire(pMural, pDEntry, GL_BGRA);
-    if (!pixels)
-    {
-        crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
-        return;
-    }
-
-    crServerDentryPresentVRAM(pMural, pDEntry, pixels);
-
-    crServerDEntryImgRelease(pMural, pDEntry, pixels);
-}
-
-void crServerPresentOutputRedirect(CRMuralInfo *pMural)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-
-    CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
-
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-        crServerPresentOutputRedirectEntry(pMural, pDEntry);
-    }
-}
-
-void crServerOutputRedirectCheckEnableDisable(CRMuralInfo *pMural)
-{
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-
-    CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
-
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-        crServerSetupOutputRedirectEntry(pMural, pDEntry);
-    }
-}
-
-void crServerPresentFBO(CRMuralInfo *mural)
-{
-    CRASSERT(mural->fPresentMode & CR_SERVER_REDIR_F_FBO);
-    CRASSERT(cr_server.pfnPresentFBO || (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY));
-
-    if (!crServerVBoxCompositionPresentNeeded(mural))
-        return;
-
-    mural->fDataPresented = GL_TRUE;
-
-    if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
-        crServerVBoxCompositionPresentPerform(mural);
-
-    if (mural->fPresentMode & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM)
-        crServerPresentOutputRedirect(mural);
-}
-
-GLboolean crServerIsRedirectedToFBO()
-{
-#ifdef DEBUG_misha
-    Assert(cr_server.curClient);
-    if (cr_server.curClient)
-    {
-        Assert(cr_server.curClient->currentMural == cr_server.currentMural);
-        Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
-    }
-#endif
-    return cr_server.curClient
-           && cr_server.curClient->currentMural
-           && (cr_server.curClient->currentMural->fPresentMode & CR_SERVER_REDIR_F_FBO);
-}
-
-GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
-{
-    switch (buffer)
-    {
-        case GL_FRONT:
-        case GL_FRONT_LEFT:
-        case GL_FRONT_RIGHT:
-            return CR_SERVER_FBO_FB_IDX(mural);
-        case GL_BACK:
-        case GL_BACK_LEFT:
-        case GL_BACK_RIGHT:
-            return CR_SERVER_FBO_BB_IDX(mural);
-        case GL_NONE:
-        case GL_AUX0:
-        case GL_AUX1:
-        case GL_AUX2:
-        case GL_AUX3:
-        case GL_LEFT:
-        case GL_RIGHT:
-        case GL_FRONT_AND_BACK:
-            return -1;
-        default:
-            crWarning("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer);
-            return -2;
-    }
-}
-
-void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
-{
-    CRContext *ctx = crStateGetCurrent();
-    GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
-    GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
-    mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
-    if (mural->iCurDrawBuffer >= 0)
-        mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
-    if (mural->iCurReadBuffer >= 0)
-        mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
-    Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
-    Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
-    if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
-    {
-        cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
-    }
-    if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
-    {
-        cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
-    }
-    Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-    Assert(mural->fUseDefaultDEntry);
-    CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-    if (mural->fRootVrOn)
-        CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp
new file mode 100644
index 0000000..e9ae9e7
--- /dev/null
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp
@@ -0,0 +1,836 @@
+/* $Id: server_muralfbo.cpp $ */
+
+/** @file
+ * VBox crOpenGL: Window to FBO redirect support.
+ */
+
+/*
+ * Copyright (C) 2010-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "server.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_vreg.h"
+#include "render/renderspu.h"
+
+static void crServerRedirMuralFbSync(CRMuralInfo *mural);
+
+void crServerCheckMuralGeometry(CRMuralInfo *mural)
+{
+    if (!mural->CreateInfo.externalID)
+        return;
+
+    CRASSERT(mural->spuWindow);
+    CRASSERT(mural->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID);
+
+    if (!mural->width || !mural->height
+            || mural->fboWidth != mural->width
+            || mural->fboHeight != mural->height)
+    {
+        crServerRedirMuralFbClear(mural);
+        crServerRedirMuralFBO(mural, false);
+        crServerDeleteMuralFBO(mural);
+    }
+
+    if (!mural->width || !mural->height)
+        return;
+
+    crServerRedirMuralFBO(mural, true);
+    crServerRedirMuralFbSync(mural);
+}
+
+static void crServerCheckMuralGeometryCB(unsigned long key, void *data1, void *data2)
+{
+    CRMuralInfo *pMI = (CRMuralInfo*) data1;
+
+    if (!pMI->fRedirected || pMI == data2)
+        return;
+
+    crServerCheckMuralGeometry(pMI);
+}
+
+
+void crServerCheckAllMuralGeometry(CRMuralInfo *pMI)
+{
+    CR_FBMAP Map;
+    int rc = CrPMgrHlpGlblUpdateBegin(&Map);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrPMgrHlpGlblUpdateBegin failed %d", rc));
+        return;
+    }
+
+    crHashtableWalk(cr_server.muralTable, crServerCheckMuralGeometryCB, pMI);
+
+    if (pMI)
+        crServerCheckMuralGeometry(pMI);
+
+    CrPMgrHlpGlblUpdateEnd(&Map);
+}
+
+GLboolean crServerSupportRedirMuralFBO(void)
+{
+    static GLboolean fInited = GL_FALSE;
+    static GLboolean fSupported = GL_FALSE;
+    if (!fInited)
+    {
+        const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
+
+        fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
+                 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
+               && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
+        fInited = GL_TRUE;
+    }
+    return fSupported;
+}
+
+static void crServerCreateMuralFBO(CRMuralInfo *mural);
+
+void crServerRedirMuralFbClear(CRMuralInfo *mural)
+{
+    uint32_t i;
+    for (i = 0; i < mural->cUsedFBDatas; ++i)
+    {
+        CR_FBDATA *pData = mural->apUsedFBDatas[i];
+        int rc = CrFbUpdateBegin(pData->hFb);
+        if (RT_SUCCESS(rc))
+        {
+            CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
+            CrFbUpdateEnd(pData->hFb);
+        }
+        else
+            WARN(("CrFbUpdateBegin failed rc %d", rc));
+    }
+    mural->cUsedFBDatas = 0;
+
+    for (i = 0; i < cr_server.screenCount; ++i)
+    {
+        GLuint j;
+        CR_FBDATA *pData = &mural->aFBDatas[i];
+        if (!pData->hFb)
+            continue;
+
+        CrFbEntryRelease(pData->hFb, pData->hFbEntry);
+        pData->hFbEntry = NULL;
+
+        for (j = 0; j < mural->cBuffers; ++j)
+        {
+            CrTdRelease(pData->apTexDatas[j]);
+            pData->apTexDatas[j] = NULL;
+        }
+
+        pData->hFb = NULL;
+    }
+}
+
+static int crServerRedirMuralDbSyncFb(CRMuralInfo *mural, HCR_FRAMEBUFFER hFb, CR_FBDATA **ppData)
+{
+    CR_FBDATA *pData;
+    const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(hFb);
+    const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
+    RTRECT FbRect = *CrVrScrCompositorRectGet(pCompositor);
+    RTRECT DefaultRegionsRect;
+    const RTRECT * pRegions;
+    uint32_t cRegions;
+    RTPOINT Pos;
+    RTRECT MuralRect;
+    int rc;
+
+    CRASSERT(mural->fRedirected);
+
+    *ppData = NULL;
+
+    if (!mural->bVisible)
+        return VINF_SUCCESS;
+
+    MuralRect.xLeft = mural->gX;
+    MuralRect.yTop = mural->gY;
+    MuralRect.xRight = MuralRect.xLeft + mural->width;
+    MuralRect.yBottom = MuralRect.yTop + mural->height;
+
+    Pos.x = mural->gX - pScreenInfo->i32OriginX;
+    Pos.y = mural->gY - pScreenInfo->i32OriginY;
+
+    VBoxRectTranslate(&FbRect, pScreenInfo->i32OriginX, pScreenInfo->i32OriginY);
+
+    VBoxRectIntersect(&FbRect, &MuralRect);
+
+    if (VBoxRectIsZero(&FbRect))
+        return VINF_SUCCESS;
+
+    if (mural->bReceivedRects)
+    {
+        pRegions = (const RTRECT*)mural->pVisibleRects;
+        cRegions = mural->cVisibleRects;
+    }
+    else
+    {
+        DefaultRegionsRect.xLeft = 0;
+        DefaultRegionsRect.yTop = 0;
+        DefaultRegionsRect.xRight = mural->width;
+        DefaultRegionsRect.yBottom = mural->height;
+        pRegions = &DefaultRegionsRect;
+        cRegions = 1;
+    }
+
+    if (!cRegions)
+        return VINF_SUCCESS;
+
+    pData = &mural->aFBDatas[pScreenInfo->u32ViewIndex];
+
+    if (!pData->hFb)
+    {
+        pData->hFb = hFb;
+
+        for (uint32_t i = 0; i < mural->cBuffers; ++i)
+        {
+            VBOXVR_TEXTURE Tex;
+            int rc;
+            Tex.width = mural->width;
+            Tex.height = mural->height;
+            Tex.hwid = mural->aidColorTexs[i];
+            Tex.target = GL_TEXTURE_2D;
+
+            pData->apTexDatas[i] = CrFbTexDataCreate(&Tex);
+        }
+
+        rc = CrFbEntryCreateForTexData(hFb, pData->apTexDatas[CR_SERVER_FBO_FB_IDX(mural)], 0, &pData->hFbEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
+        }
+    }
+    else
+    {
+        CRASSERT(pData->hFb == hFb);
+    }
+
+    rc = CrFbUpdateBegin(hFb);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrFbUpdateBegin failed rc %d", rc));
+        return rc;
+    }
+
+    rc = CrFbEntryRegionsSet(hFb, pData->hFbEntry, &Pos, cRegions, pRegions, true);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrFbEntryRegionsSet failed rc %d", rc));
+    }
+
+    CrFbUpdateEnd(hFb);
+
+    const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry = CrFbEntryGetCompositorEntry(pData->hFbEntry);
+    if (CrVrScrCompositorEntryIsUsed(pCEntry))
+        *ppData = pData;
+
+    return rc;
+}
+
+static void crServerRedirMuralFbSync(CRMuralInfo *mural)
+{
+    uint32_t i;
+    uint32_t cUsedFBs = 0;
+    HCR_FRAMEBUFFER ahUsedFbs[CR_MAX_GUEST_MONITORS];
+    HCR_FRAMEBUFFER hFb;
+
+    for (i = 0; i < mural->cUsedFBDatas; ++i)
+    {
+        CR_FBDATA *pData = mural->apUsedFBDatas[i];
+        int rc = CrFbUpdateBegin(pData->hFb);
+        if (RT_SUCCESS(rc))
+        {
+            ahUsedFbs[cUsedFBs] = pData->hFb;
+            CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
+            ++cUsedFBs;
+        }
+        else
+            WARN(("CrFbUpdateBegin failed rc %d", rc));
+    }
+    mural->cUsedFBDatas = 0;
+
+    if (!mural->width
+            || !mural->height
+            || !mural->bVisible
+            )
+        goto end;
+
+    CRASSERT(mural->fRedirected);
+
+    for (hFb = CrPMgrFbGetFirstEnabled();
+            hFb;
+            hFb = CrPMgrFbGetNextEnabled(hFb))
+    {
+        CR_FBDATA *pData = NULL;
+        int rc = crServerRedirMuralDbSyncFb(mural, hFb, &pData);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crServerRedirMuralDbSyncFb failed %d", rc));
+            continue;
+        }
+
+        if (!pData)
+            continue;
+
+        mural->apUsedFBDatas[mural->cUsedFBDatas] = pData;
+        ++mural->cUsedFBDatas;
+    }
+
+end:
+
+    for (i = 0; i < cUsedFBs; ++i)
+    {
+        CrFbUpdateEnd(ahUsedFbs[i]);
+    }
+}
+
+static void crVBoxServerMuralFbCleanCB(unsigned long key, void *data1, void *data2)
+{
+    CRMuralInfo *pMI = (CRMuralInfo*) data1;
+    HCR_FRAMEBUFFER hFb = (HCR_FRAMEBUFFER)data2;
+    uint32_t i;
+    for (i = 0; i < pMI->cUsedFBDatas; ++i)
+    {
+        CR_FBDATA *pData = pMI->apUsedFBDatas[i];
+        if (hFb != pData->hFb)
+            continue;
+
+        CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
+        break;
+    }
+}
+
+static void crVBoxServerMuralFbSetCB(unsigned long key, void *data1, void *data2)
+{
+    CRMuralInfo *pMI = (CRMuralInfo*) data1;
+    HCR_FRAMEBUFFER hFb = (HCR_FRAMEBUFFER)data2;
+    uint32_t i;
+    CR_FBDATA *pData = NULL;
+    bool fFbWasUsed = false;
+
+    Assert(hFb);
+
+    if (!pMI->fRedirected)
+    {
+        Assert(!pMI->cUsedFBDatas);
+        return;
+    }
+
+    for (i = 0; i < pMI->cUsedFBDatas; ++i)
+    {
+        CR_FBDATA *pData = pMI->apUsedFBDatas[i];
+        if (hFb != pData->hFb)
+            continue;
+
+        fFbWasUsed = true;
+        break;
+    }
+
+    if (CrFbIsEnabled(hFb))
+    {
+        int rc = crServerRedirMuralDbSyncFb(pMI, hFb, &pData);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("crServerRedirMuralDbSyncFb failed %d", rc));
+            pData = NULL;
+        }
+    }
+
+    if (pData)
+    {
+        if (!fFbWasUsed)
+        {
+            uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+            for (i = 0; i < pMI->cUsedFBDatas; ++i)
+            {
+                CR_FBDATA *pData = pMI->apUsedFBDatas[i];
+                uint32_t idCurScreen = CrFbGetScreenInfo(pData->hFb)->u32ViewIndex;
+                if (idCurScreen > idScreen)
+                    break;
+
+                Assert(idCurScreen != idScreen);
+            }
+
+            for (int j = pMI->cUsedFBDatas; j > i; --j)
+            {
+                pMI->apUsedFBDatas[j] = pMI->apUsedFBDatas[j-1];
+            }
+
+            pMI->apUsedFBDatas[i] = pData;
+            ++pMI->cUsedFBDatas;
+        }
+        /* else - nothing to do */
+    }
+    else
+    {
+        if (fFbWasUsed)
+        {
+            for (int j = i; j < pMI->cUsedFBDatas - 1; ++j)
+            {
+                pMI->apUsedFBDatas[j] = pMI->apUsedFBDatas[j+1];
+            }
+            --pMI->cUsedFBDatas;
+        }
+        /* else - nothing to do */
+    }
+}
+
+void crVBoxServerMuralFbResizeEnd(HCR_FRAMEBUFFER hFb)
+{
+    crHashtableWalk(cr_server.muralTable, crVBoxServerMuralFbSetCB, hFb);
+}
+
+void crVBoxServerMuralFbResizeBegin(HCR_FRAMEBUFFER hFb)
+{
+    crHashtableWalk(cr_server.muralTable, crVBoxServerMuralFbCleanCB, hFb);
+}
+
+
+static int crVBoxServerResizeScreen(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM)
+{
+    int rc;
+    HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
+    if (!hFb)
+    {
+        WARN(("CrPMgrFbGet failed"));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    rc = CrFbUpdateBegin(hFb);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrFbUpdateBegin failed %d", rc));
+        return rc;
+    }
+
+    crVBoxServerMuralFbResizeBegin(hFb);
+
+    rc = CrFbResize(hFb, pScreen, pvVRAM);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrFbResize failed %d", rc));
+    }
+
+    crVBoxServerMuralFbResizeEnd(hFb);
+
+    CrFbUpdateEnd(hFb);
+
+    CrPMgrNotifyResize(hFb);
+
+    return rc;
+}
+
+DECLEXPORT(int) crVBoxServerNotifyResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM)
+{
+    int rc = crVBoxServerResizeScreen(pScreen, pvVRAM);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("err"));
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+void crServerRedirMuralFBO(CRMuralInfo *mural, bool fEnabled)
+{
+    if (!mural->fRedirected == !fEnabled)
+    {
+        return;
+    }
+
+    if (!mural->CreateInfo.externalID)
+    {
+        WARN(("trying to change redir setting for internal mural %d", mural->spuWindow));
+        return;
+    }
+
+    if (fEnabled)
+    {
+        if (!crServerSupportRedirMuralFBO())
+        {
+            WARN(("FBO not supported, can't redirect window output"));
+            return;
+        }
+
+        if (mural->aidFBOs[0]==0)
+        {
+            crServerCreateMuralFBO(mural);
+        }
+
+        if (cr_server.curClient && cr_server.curClient->currentMural == mural)
+        {
+            if (!crStateGetCurrent()->framebufferobject.drawFB)
+            {
+                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
+            }
+            if (!crStateGetCurrent()->framebufferobject.readFB)
+            {
+                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
+            }
+
+            crStateGetCurrent()->buffer.width = 0;
+            crStateGetCurrent()->buffer.height = 0;
+        }
+    }
+    else
+    {
+        if (cr_server.curClient && cr_server.curClient->currentMural == mural)
+        {
+            if (!crStateGetCurrent()->framebufferobject.drawFB)
+            {
+                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+            }
+            if (!crStateGetCurrent()->framebufferobject.readFB)
+            {
+                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+            }
+
+            crStateGetCurrent()->buffer.width = mural->width;
+            crStateGetCurrent()->buffer.height = mural->height;
+        }
+    }
+
+    mural->fRedirected = !!fEnabled;
+}
+
+static void crServerCreateMuralFBO(CRMuralInfo *mural)
+{
+    CRContext *ctx = crStateGetCurrent();
+    GLuint uid, i;
+    GLenum status;
+    SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
+    CRContextInfo *pMuralContextInfo;
+
+    CRASSERT(mural->aidFBOs[0]==0);
+    CRASSERT(mural->aidFBOs[1]==0);
+
+    pMuralContextInfo = cr_server.currentCtxInfo;
+    if (!pMuralContextInfo)
+    {
+        /* happens on saved state load */
+        CRASSERT(cr_server.MainContextInfo.SpuContext);
+        pMuralContextInfo = &cr_server.MainContextInfo;
+        cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
+    }
+
+    if (pMuralContextInfo->CreateInfo.realVisualBits != mural->CreateInfo.realVisualBits)
+    {
+        WARN(("mural visual bits do not match with current context visual bits!"));
+    }
+
+    mural->cBuffers = 2;
+    mural->iBbBuffer = 0;
+    /*Color texture*/
+
+    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+    {
+        gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+    }
+
+    for (i = 0; i < mural->cBuffers; ++i)
+    {
+        gl->GenTextures(1, &mural->aidColorTexs[i]);
+        gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+        gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
+                       0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+    }
+
+    /*Depth&Stencil*/
+    gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
+    gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
+    gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+                           mural->width, mural->height);
+
+    /*FBO*/
+    for (i = 0; i < mural->cBuffers; ++i)
+    {
+        gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
+        gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
+
+        gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+                                    GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
+        gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+                                       GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
+        gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
+                                       GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
+
+        status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+        if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
+        {
+            WARN(("FBO status(0x%x) isn't complete", status));
+        }
+    }
+
+    mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
+    mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
+
+    mural->fboWidth = mural->width;
+    mural->fboHeight = mural->height;
+
+    mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
+    mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
+
+    /*Restore gl state*/
+    uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
+    gl->BindTexture(GL_TEXTURE_2D, uid);
+
+    uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
+    gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
+
+    uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
+    gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
+
+    uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
+    gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
+
+    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+    {
+        gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
+    }
+
+    if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
+    {
+        gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
+    }
+    else
+    {
+        gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+    }
+
+    CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
+}
+
+void crServerDeleteMuralFBO(CRMuralInfo *mural)
+{
+    if (mural->aidFBOs[0]!=0)
+    {
+        GLuint i;
+        for (i = 0; i < mural->cBuffers; ++i)
+        {
+            cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
+            mural->aidColorTexs[i] = 0;
+        }
+
+        cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
+        mural->idDepthStencilRB = 0;
+
+        for (i = 0; i < mural->cBuffers; ++i)
+        {
+            cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
+            mural->aidFBOs[i] = 0;
+        }
+    }
+
+    mural->cBuffers = 0;
+}
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
+{
+    CRASSERT(a && b && rect);
+
+    rect->x1 = MAX(a->x1, b->x1);
+    rect->x2 = MIN(a->x2, b->x2);
+    rect->y1 = MAX(a->y1, b->y1);
+    rect->y2 = MIN(a->y2, b->y2);
+
+    return (rect->x2>rect->x1) && (rect->y2>rect->y1);
+}
+
+DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
+{
+}
+
+DECLEXPORT(void) crServerVBoxScreenshotRelease(CR_SCREENSHOT *pScreenshot)
+{
+    if (pScreenshot->fDataAllocated)
+    {
+        RTMemFree(pScreenshot->Img.pvData);
+        pScreenshot->fDataAllocated = 0;
+    }
+}
+
+DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, uint32_t height, uint32_t pitch, void *pvBuffer, CR_SCREENSHOT *pScreenshot)
+{
+    HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32Screen);
+    if (!hFb)
+        return VERR_INVALID_STATE;
+
+    const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+
+    if (!width)
+        width = pScreen->u32Width;
+    if (!height)
+        height = pScreen->u32Height;
+    if (!pitch)
+        pitch = pScreen->u32LineSize;
+
+    if (CrFbHas3DData(hFb)
+            || pScreen->u32Width != width
+            || pScreen->u32Height != height
+            || pScreen->u32LineSize != pitch
+            || pScreen->u16BitsPerPixel != 32)
+    {
+        RTRECT Rect;
+
+        pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
+        if (!pvBuffer)
+        {
+            pScreenshot->Img.pvData = RTMemAlloc(pScreenshot->Img.cbData);
+            if (!pScreenshot->Img.pvData)
+            {
+                WARN(("RTMemAlloc failed"));
+                return VERR_NO_MEMORY;
+            }
+            pScreenshot->fDataAllocated = 1;
+        }
+        else
+        {
+            pScreenshot->Img.pvData = pvBuffer;
+            pScreenshot->fDataAllocated = 0;
+        }
+
+        pScreenshot->Img.enmFormat = GL_BGRA;
+        pScreenshot->Img.width = width;
+        pScreenshot->Img.height = height;
+        pScreenshot->Img.bpp = 32;
+        pScreenshot->Img.pitch = pitch;
+        Rect.xLeft = 0;
+        Rect.yTop = 0;
+        Rect.xRight = pScreen->u32Width;
+        Rect.yBottom = pScreen->u32Height;
+        int rc = CrFbBltGetContents(hFb, &Rect, 1, &Rect, &pScreenshot->Img);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrFbBltGetContents failed %d", rc));
+            crServerVBoxScreenshotRelease(pScreenshot);
+            return rc;
+        }
+    }
+    else
+    {
+        pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
+        if (!pvBuffer)
+            pScreenshot->Img.pvData = CrFbGetVRAM(hFb);
+        else
+        {
+            pScreenshot->Img.pvData = pvBuffer;
+            memcpy(pvBuffer, CrFbGetVRAM(hFb), pScreenshot->Img.cbData);
+        }
+        pScreenshot->Img.enmFormat = GL_BGRA;
+        pScreenshot->Img.width = pScreen->u32Width;
+        pScreenshot->Img.height = pScreen->u32Height;
+        pScreenshot->Img.bpp = pScreen->u16BitsPerPixel;
+        pScreenshot->Img.pitch = pScreen->u32LineSize;
+
+        pScreenshot->fDataAllocated = 0;
+    }
+
+    pScreenshot->u32Screen = u32Screen;
+
+    return VINF_SUCCESS;
+}
+
+extern DECLEXPORT(int) crServerVBoxWindowsShow(bool fShow)
+{
+    return CrPMgrModeWinVisible(fShow);
+}
+
+void crServerPresentFBO(CRMuralInfo *mural)
+{
+    uint32_t i;
+    for (i = 0; i < mural->cUsedFBDatas; ++i)
+    {
+        CR_FBDATA *pData = mural->apUsedFBDatas[i];
+        int rc = CrFbUpdateBegin(pData->hFb);
+        if (RT_SUCCESS(rc))
+        {
+            CrFbEntryTexDataUpdate(pData->hFb, pData->hFbEntry, pData->apTexDatas[CR_SERVER_FBO_FB_IDX(mural)]);
+            CrFbUpdateEnd(pData->hFb);
+        }
+        else
+            WARN(("CrFbUpdateBegin failed rc %d", rc));
+    }
+}
+
+GLboolean crServerIsRedirectedToFBO()
+{
+#ifdef DEBUG_misha
+    Assert(cr_server.curClient);
+    if (cr_server.curClient)
+    {
+        Assert(cr_server.curClient->currentMural == cr_server.currentMural);
+        Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
+    }
+#endif
+    return cr_server.curClient
+           && cr_server.curClient->currentMural
+           && cr_server.curClient->currentMural->fRedirected;
+}
+
+GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
+{
+    switch (buffer)
+    {
+        case GL_FRONT:
+        case GL_FRONT_LEFT:
+        case GL_FRONT_RIGHT:
+            return CR_SERVER_FBO_FB_IDX(mural);
+        case GL_BACK:
+        case GL_BACK_LEFT:
+        case GL_BACK_RIGHT:
+            return CR_SERVER_FBO_BB_IDX(mural);
+        case GL_NONE:
+        case GL_AUX0:
+        case GL_AUX1:
+        case GL_AUX2:
+        case GL_AUX3:
+        case GL_LEFT:
+        case GL_RIGHT:
+        case GL_FRONT_AND_BACK:
+            return -1;
+        default:
+            WARN(("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer));
+            return -2;
+    }
+}
+
+void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
+{
+    CRContext *ctx = crStateGetCurrent();
+    GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
+    GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
+    mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
+    if (mural->iCurDrawBuffer >= 0)
+        mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
+    if (mural->iCurReadBuffer >= 0)
+        mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
+    Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
+    Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
+    if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
+    {
+        cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
+    }
+    if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
+    {
+        cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
+    }
+    Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
+}
+
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
index 0c9354c..49fa537 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
@@ -25,673 +25,4043 @@
 #include "cr_mem.h"
 #include "cr_string.h"
 #include <cr_vreg.h>
+#include <cr_htable.h>
+#include <cr_bmpscale.h>
 
 #include <iprt/cdefs.h>
 #include <iprt/types.h>
 #include <iprt/asm.h>
 #include <iprt/mem.h>
 #include <iprt/list.h>
-#include <iprt/memcache.h>
 
-#include "render/renderspu.h"
 
-/* DISPLAY */
+#ifdef DEBUG_misha
+# define VBOXVDBG_MEMCACHE_DISABLE
+#endif
+
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+# include <iprt/memcache.h>
+#endif
+
+#include "render/renderspu.h"
 
-int CrDpInit(PCR_DISPLAY pDisplay)
+class ICrFbDisplay
 {
-    const GLint visBits = cr_server.MainContextInfo.CreateInfo.visualBits;
-    if (crServerMuralInit(&pDisplay->Mural, "", visBits, -1, GL_FALSE) < 0)
-    {
-        crWarning("crServerMuralInit failed!");
-        return VERR_GENERAL_FAILURE;
-    }
+public:
+    virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
+    virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
 
-    crServerWindowVisibleRegion(&pDisplay->Mural);
-    crServerDEntryAllVibleRegions(&pDisplay->Mural);
+    virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+    virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+    virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+    virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+    virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
 
-    crServerMuralShow(&pDisplay->Mural, GL_TRUE);
+    virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
 
-    pDisplay->fForcePresent = GL_FALSE;
-    return VINF_SUCCESS;
-}
+    virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
 
-void CrDpTerm(PCR_DISPLAY pDisplay)
-{
-    crServerMuralTerm(&pDisplay->Mural);
-}
+    virtual ~ICrFbDisplay() {}
+};
 
-void CrDpResize(PCR_DISPLAY pDisplay, int32_t xPos, int32_t yPos, uint32_t width, uint32_t height)
-{
-    if (xPos != pDisplay->Mural.gX
-            || yPos != pDisplay->Mural.gY
-            || width != pDisplay->Mural.width
-            || height != pDisplay->Mural.height)
-    {
-        crServerMuralPosition(&pDisplay->Mural, xPos, yPos, GL_TRUE);
-        if (!crServerMuralSize(&pDisplay->Mural, width, height))
-            crServerCheckMuralGeometry(&pDisplay->Mural);
-    }
-    else
-        crServerCheckMuralGeometry(&pDisplay->Mural);
-}
+class CrFbDisplayComposite;
+class CrFbDisplayBase;
+class CrFbDisplayWindow;
+class CrFbDisplayWindowRootVr;
+class CrFbDisplayVrdp;
 
-void CrDpReparent(PCR_DISPLAY pDisplay, CRScreenInfo *pScreen)
+typedef struct CR_FRAMEBUFFER
+{
+    VBOXVR_SCR_COMPOSITOR Compositor;
+    struct VBVAINFOSCREEN ScreenInfo;
+    void *pvVram;
+    ICrFbDisplay *pDisplay;
+    RTLISTNODE EntriesList;
+    uint32_t cEntries; /* <- just for debugging */
+    uint32_t cUpdating;
+    CRHTABLE SlotTable;
+} CR_FRAMEBUFFER;
+
+typedef union CR_FBENTRY_FLAGS
 {
-    renderspuSetWindowId(pScreen->winID);
-    crServerWindowReparent(&pDisplay->Mural);
-    renderspuSetWindowId(cr_server.screen[0].winID);
+    struct {
+        uint32_t fCreateNotified : 1;
+        uint32_t fInList         : 1;
+        uint32_t Reserved        : 30;
+    };
+    uint32_t Value;
+} CR_FBENTRY_FLAGS;
+
+typedef struct CR_FRAMEBUFFER_ENTRY
+{
+    VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
+    RTLISTNODE Node;
+    uint32_t cRefs;
+    CR_FBENTRY_FLAGS Flags;
+    CRHTABLE HTable;
+} CR_FRAMEBUFFER_ENTRY;
 
-    CrDpResize(pDisplay, pScreen->x, pScreen->y, pScreen->w, pScreen->h);
+typedef struct CR_FBTEX
+{
+    CR_TEXDATA Tex;
+    CRTextureObj *pTobj;
+} CR_FBTEX;
 
-    if (pScreen->winID)
-    {
-        /* need to do this on win, since otherwise the window ends up being with empty visible regions for some reason */
-        crServerWindowVisibleRegion(&pDisplay->Mural);
-    }
-}
+#define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
+#define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
+#define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
 
 
-int CrDpSaveState(PCR_DISPLAY pDisplay, PSSMHANDLE pSSM)
+typedef struct CR_FBDISPLAY_INFO
 {
-    VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
-    CrVrScrCompositorIterInit(&pDisplay->Mural.Compositor, &Iter);
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    uint32_t u32 = 0;
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        ++u32;
-    }
-
-    int rc = SSMR3PutU32(pSSM, u32);
-    AssertRCReturn(rc, rc);
+    uint32_t u32Mode;
+    CrFbDisplayWindow *pDpWin;
+    CrFbDisplayWindowRootVr *pDpWinRootVr;
+    CrFbDisplayVrdp *pDpVrdp;
+    CrFbDisplayComposite *pDpComposite;
+} CR_FBDISPLAY_INFO;
+
+typedef struct CR_PRESENTER_GLOBALS
+{
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+    RTMEMCACHE FbEntryLookasideList;
+    RTMEMCACHE FbTexLookasideList;
+    RTMEMCACHE CEntryLookasideList;
+#endif
+    uint32_t u32DisplayMode;
+    CRHashTable *pFbTexMap;
+    CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
+    CR_FBMAP FramebufferInitMap;
+    CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
+    bool fWindowsForceHidden;
+    uint32_t cbTmpBuf;
+    void *pvTmpBuf;
+    uint32_t cbTmpBuf2;
+    void *pvTmpBuf2;
+} CR_PRESENTER_GLOBALS;
+
+static CR_PRESENTER_GLOBALS g_CrPresenter;
+
+/* FRAMEBUFFER */
+
+void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idScreen)
+{
+    RTRECT Rect;
+    Rect.xLeft = 0;
+    Rect.yTop = 0;
+    Rect.xRight = 1;
+    Rect.yBottom = 1;
+    memset(pFb, 0, sizeof (*pFb));
+    pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
+    pFb->ScreenInfo.u32ViewIndex = idScreen;
+    CrVrScrCompositorInit(&pFb->Compositor, &Rect);
+    RTListInit(&pFb->EntriesList);
+    CrHTableCreate(&pFb->SlotTable, 0);
+}
 
-    CrVrScrCompositorIterInit(&pDisplay->Mural.Compositor, &Iter);
+bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
+{
+    return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
+}
 
-    while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
-    {
-        CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-        rc = CrDemEntrySaveState(pDEntry, pSSM);
-        AssertRCReturn(rc, rc);
+HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
 
-        u32 = CrVrScrCompositorEntryFlagsGet(&pDEntry->CEntry);
-        rc = SSMR3PutU32(pSSM, u32);
-        AssertRCReturn(rc, rc);
+const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
+{
+    return &pFb->Compositor;
+}
 
-        rc = SSMR3PutS32(pSSM, CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x);
-        AssertRCReturn(rc, rc);
+DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
+{
+    return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
+}
 
-        rc = SSMR3PutS32(pSSM, CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y);
-        AssertRCReturn(rc, rc);
+const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
+{
+    return &hFb->ScreenInfo;
+}
 
-        const RTRECT * pRects;
-        rc = CrVrScrCompositorEntryRegionsGet(&pDisplay->Mural.Compositor, &pDEntry->CEntry, &u32, NULL, NULL, &pRects);
-        AssertRCReturn(rc, rc);
+void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
+{
+    return hFb->pvVram;
+}
 
-        rc = SSMR3PutU32(pSSM, u32);
-        AssertRCReturn(rc, rc);
+int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
+{
+    ++pFb->cUpdating;
 
-        if (u32)
-        {
-            rc = SSMR3PutMem(pSSM, pRects, u32 * sizeof (*pRects));
-            AssertRCReturn(rc, rc);
-        }
+    if (pFb->cUpdating == 1)
+    {
+        if (pFb->pDisplay)
+            pFb->pDisplay->UpdateBegin(pFb);
     }
 
     return VINF_SUCCESS;
 }
 
-int CrDpLoadState(PCR_DISPLAY pDisplay, PSSMHANDLE pSSM, uint32_t version)
+void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
 {
-    uint32_t u32 = 0;
-    int rc = SSMR3GetU32(pSSM, &u32);
-    AssertRCReturn(rc, rc);
-
-    if (!u32)
-        return VINF_SUCCESS;
+    if (!pFb->cUpdating)
+    {
+        WARN(("invalid UpdateEnd call!"));
+        return;
+    }
 
-    CrDpEnter(pDisplay);
+    --pFb->cUpdating;
 
-    for (uint32_t i = 0; i < u32; ++i)
+    if (!pFb->cUpdating)
     {
-        CR_DISPLAY_ENTRY *pDEntry;
-        rc = CrDemEntryLoadState(&cr_server.PresentTexturepMap, &pDEntry, pSSM);
-        AssertRCReturn(rc, rc);
+        if (pFb->pDisplay)
+            pFb->pDisplay->UpdateEnd(pFb);
+    }
+}
 
-        uint32_t fFlags;
-        rc = SSMR3GetU32(pSSM, &fFlags);
-        AssertRCReturn(rc, rc);
+bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
+{
+    return !!pFb->cUpdating;
+}
 
-        CrVrScrCompositorEntryFlagsSet(&pDEntry->CEntry, fFlags);
+bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
+{
+    return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
+}
 
-        RTPOINT Pos;
-        rc = SSMR3GetS32(pSSM, &Pos.x);
-        AssertRCReturn(rc, rc);
+static void crFbBltMem(uint8_t *pu8Src, int32_t cbSrcPitch, uint8_t *pu8Dst, int32_t cbDstPitch, uint32_t width, uint32_t height)
+{
+    uint32_t cbCopyRow = width * 4;
 
-        rc = SSMR3GetS32(pSSM, &Pos.y);
-        AssertRCReturn(rc, rc);
+    for (uint32_t i = 0; i < height; ++i)
+    {
+        memcpy(pu8Dst, pu8Src, cbCopyRow);
 
-        uint32_t cRects;
-        rc = SSMR3GetU32(pSSM, &cRects);
-        AssertRCReturn(rc, rc);
+        pu8Src += cbSrcPitch;
+        pu8Dst += cbDstPitch;
+    }
+}
 
-        RTRECT * pRects = NULL;
-        if (cRects)
-        {
-            pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
-            AssertReturn(pRects, VERR_NO_MEMORY);
+static void crFbBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, CR_BLITTER_IMG *pDst)
+{
+    int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
+    int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
+    Assert(srcX >= 0);
+    Assert(srcY >= 0);
+    Assert(srcX < pSrc->width);
+    Assert(srcY < pSrc->height);
+
+    int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
+    int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
+    Assert(dstX >= 0);
+    Assert(dstY >= 0);
+
+    uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
+    uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
+
+    crFbBltMem(pu8Src, fSrcInvert ? -pSrc->pitch : pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
+}
 
-            rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
-            AssertRCReturn(rc, rc);
-        }
+static void crFbBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst)
+{
+    int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
+    int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
+    Assert(srcX >= 0);
+    Assert(srcY >= 0);
+    Assert(srcX < pSrc->width);
+    Assert(srcY < pSrc->height);
+
+    RTPOINT ScaledDtsDataPoint;
+    RTRECT ScaledCopyRect;
+
+    VBoxRectScaled(pCopyRect, strX, strY, &ScaledCopyRect);
+    ScaledDtsDataPoint.x = CR_FLOAT_RCAST(int32_t, strX * pDstDataPoint->x);
+    ScaledDtsDataPoint.y = CR_FLOAT_RCAST(int32_t, strY * pDstDataPoint->y);
+
+    int32_t dstX = ScaledCopyRect.xLeft - ScaledDtsDataPoint.x;
+    int32_t dstY = ScaledCopyRect.yTop - ScaledDtsDataPoint.y;
+    Assert(dstX >= 0);
+    Assert(dstY >= 0);
+
+    int32_t ScaledDstWidth = ScaledCopyRect.xRight - ScaledCopyRect.xLeft;
+    int32_t delta = (int32_t)pDst->width - dstX - ScaledDstWidth;
+    if (delta < 0)
+        ScaledDstWidth += delta;
+
+    if (ScaledDstWidth <= 0)
+    {
+        LOG(("ScaledDstWidth <= 0"));
+        if (ScaledDstWidth < 0)
+            WARN(("dst width (%d) < 0", ScaledDstWidth));
+        return;
+    }
 
-        rc = CrDpEntryRegionsAdd(pDisplay, pDEntry, &Pos, (uint32_t)cRects, (const RTRECT*)pRects, NULL);
-        AssertRCReturn(rc, rc);
+    int32_t ScaledDstHeight = ScaledCopyRect.yBottom - ScaledCopyRect.yTop;
+    delta = (int32_t)pDst->height - dstY - ScaledDstHeight;
+    if (delta < 0)
+        ScaledDstHeight += delta;
 
-        if (pRects)
-            crFree(pRects);
+    if (ScaledDstHeight <= 0)
+    {
+        LOG(("ScaledDstHeight <= 0"));
+        if (ScaledDstHeight < 0)
+            WARN(("dst height (%d) < 0", ScaledDstHeight));
+        return;
     }
 
-    CrDpLeave(pDisplay);
+    uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
+    uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
 
-    return VINF_SUCCESS;
+    CrBmpScale32(pu8Dst, pDst->pitch,
+                        ScaledDstWidth,
+                        ScaledDstHeight,
+                        pu8Src,
+                        fSrcInvert ? -pSrc->pitch : pSrc->pitch,
+                        pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
 }
 
-
-int CrDpEntryRegionsSet(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
+static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
 {
-    int rc = CrVrScrCompositorEntryRegionsSet(&pDisplay->Mural.Compositor, pEntry ? &pEntry->CEntry : NULL, pPos, cRegions, paRegions, false, NULL);
-    return rc;
+    pImg->pvData = pvVram;
+    pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
+    pImg->enmFormat = GL_BGRA;
+    pImg->width = pScreen->u32Width;
+    pImg->height = pScreen->u32Height;
+    pImg->bpp = pScreen->u16BitsPerPixel;
+    pImg->pitch = pScreen->u32LineSize;
 }
 
-void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
+static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
 {
-    crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
+    const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+    void *pvVram = CrFbGetVRAM(hFb);
+    crFbImgFromScreenVram(pScreen, pvVram, pImg);
 }
 
-void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
+static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
 {
-    crDebug("Dumping rects (%d)", cRects);
-    for (uint32_t i = 0; i < cRects; ++i)
+    VBOXVR_LIST List;
+    uint32_t c2DRects = 0;
+    CR_TEXDATA *pEnteredTex = NULL;
+    PCR_BLITTER pEnteredBlitter = NULL;
+    uint32_t width = 0, height = 0;
+    RTPOINT ScaledEntryPoint = {0};
+
+    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+    RTPOINT SrcPoint = {pSrcRect->xLeft, pSrcRect->yTop};
+    float strX = ((float)pImg->width) / (pSrcRect->xRight - pSrcRect->xLeft);
+    float strY = ((float)pImg->height) / (pSrcRect->yBottom - pSrcRect->yTop);
+
+    RTPOINT ScaledSrcPoint;
+    ScaledSrcPoint.x = CR_FLOAT_RCAST(int32_t, strX * SrcPoint.x);
+    ScaledSrcPoint.y = CR_FLOAT_RCAST(int32_t, strY * SrcPoint.y);
+
+    RTPOINT ZeroPoint = {0, 0};
+
+    VBoxVrListInit(&List);
+    int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
+    if (!RT_SUCCESS(rc))
     {
-        crDbgDumpRect(i, &paRects[i]);
+        WARN(("VBoxVrListRectsAdd failed rc %d", rc));
+        goto end;
     }
-    crDebug("End Dumping rects (%d)", cRects);
-}
-
-int CrDpEntryRegionsAdd(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, CR_DISPLAY_ENTRY_MAP *pMap)
-{
-    uint32_t fChangeFlags = 0;
-    VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
 
-    if (pMap)
-        CrDemEnter(pMap);
+    CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
 
-    int rc = CrVrScrCompositorEntryRegionsAdd(&pDisplay->Mural.Compositor, pEntry ? &pEntry->CEntry : NULL, pPos, cRegions, paRegions, false, &pReplacedScrEntry, &fChangeFlags);
-    if (RT_SUCCESS(rc))
+    for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
+            pEntry;
+            pEntry = CrVrScrCompositorConstIterNext(&Iter))
     {
-        if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
+        uint32_t cRegions;
+        const RTRECT *pRegions;
+        rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
+            goto end;
+        }
+
+        rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("VBoxVrListRectsSubst failed rc %d", rc));
+            goto end;
+        }
+
+        for (uint32_t i = 0; i < cRects; ++i)
         {
-            bool fChanged = true;
-            if (pDisplay->Mural.fRootVrOn)
+            const RTRECT * pRect = &pRects[i];
+            for (uint32_t j = 0; j < cRegions; ++j)
             {
-                int rc = crServerMuralSynchRootVr(&pDisplay->Mural, &fChanged);
+                const RTRECT * pReg = &pRegions[j];
+                RTRECT Intersection;
+                VBoxRectIntersected(pRect, pReg, &Intersection);
+                if (VBoxRectIsZero(&Intersection))
+                    continue;
+
+                VBoxRectScale(&Intersection, strX, strY);
+                if (VBoxRectIsZero(&Intersection))
+                    continue;
+
+                CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+                const CR_BLITTER_IMG *pSrcImg;
+
+                if (pEnteredTex != pTex)
+                {
+                    if (!pEnteredBlitter)
+                    {
+                        pEnteredBlitter = CrTdBlitterGet(pTex);
+                        rc = CrBltEnter(pEnteredBlitter);
+                        if (!RT_SUCCESS(rc))
+                        {
+                            WARN(("CrBltEnter failed %d", rc));
+                            pEnteredBlitter = NULL;
+                            goto end;
+                        }
+                    }
+
+                    if (pEnteredTex)
+                    {
+                        CrTdBltLeave(pEnteredTex);
+
+                        pEnteredTex = NULL;
+
+                        if (pEnteredBlitter != CrTdBlitterGet(pTex))
+                        {
+                            WARN(("blitters not equal!"));
+                            CrBltLeave(pEnteredBlitter);
+
+                            pEnteredBlitter = CrTdBlitterGet(pTex);
+                            rc = CrBltEnter(pEnteredBlitter);
+                             if (!RT_SUCCESS(rc))
+                             {
+                                 WARN(("CrBltEnter failed %d", rc));
+                                 pEnteredBlitter = NULL;
+                                 goto end;
+                             }
+                        }
+                    }
+
+                    rc = CrTdBltEnter(pTex);
+                    if (!RT_SUCCESS(rc))
+                    {
+                        WARN(("CrTdBltEnter failed %d", rc));
+                        goto end;
+                    }
+
+                    pEnteredTex = pTex;
+
+                    const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
+
+                    width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
+                    height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
+                    ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft);
+                    ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop);
+                }
+
+                rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
                 if (!RT_SUCCESS(rc))
                 {
-                    crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
-                    fChanged = false;
+                    WARN(("CrTdBltDataAcquire failed rc %d", rc));
+                    goto end;
                 }
-            }
 
-            if (fChanged)
-                crServerWindowVisibleRegion(&pDisplay->Mural);
+                bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
 
-            crServerDEntryAllVibleRegions(&pDisplay->Mural);
+                crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ScaledSrcPoint, pImg);
 
-            Assert(!pReplacedScrEntry);
+                CrTdBltDataReleaseScaled(pTex, pSrcImg);
+            }
         }
-        else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)
+    }
+
+    c2DRects = VBoxVrListRectsCount(&List);
+    if (c2DRects)
+    {
+        if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
         {
-            if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
-            {
-                Assert(pReplacedScrEntry);
-                Assert(pEntry);
-                if (pDisplay->Mural.fRootVrOn)
-                {
-                    CR_DISPLAY_ENTRY *pReplacedDEntry = CR_DENTRY_FROM_CENTRY(pReplacedScrEntry);
-                    Assert(CrVrScrCompositorEntryIsUsed(&pReplacedDEntry->RootVrCEntry));
-                    Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->RootVrCEntry));
-                    CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, CrVrScrCompositorEntryTexGet(&pEntry->CEntry), NULL);
-                    CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, CrVrScrCompositorEntryFlagsGet(&pEntry->CEntry));
-                    CrVrScrCompositorEntryReplace(&pDisplay->Mural.RootVrCompositor, &pReplacedDEntry->RootVrCEntry, &pEntry->RootVrCEntry);
-                }
-            }
-            else
+            if (g_CrPresenter.pvTmpBuf2)
+                RTMemFree(g_CrPresenter.pvTmpBuf2);
+
+            g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
+            g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
+            if (!g_CrPresenter.pvTmpBuf2)
             {
-                Assert(!pReplacedScrEntry);
-                if (pDisplay->Mural.fRootVrOn)
-                {
-                    bool fChanged = false;
-                    int rc = crServerMuralSynchRootVr(&pDisplay->Mural, &fChanged);
-                    if (RT_SUCCESS(rc))
-                    {
-                        if (fChanged)
-                            crServerWindowVisibleRegion(&pDisplay->Mural);
-                    }
-                    else
-                        crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
-                }
+                WARN(("RTMemAlloc failed!"));
+                g_CrPresenter.cbTmpBuf2 = 0;
+                rc = VERR_NO_MEMORY;
+                goto end;
             }
         }
-        else
+
+        RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
+
+        rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
+        if (!RT_SUCCESS(rc))
         {
-            Assert(!(fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED));
-            Assert(!pReplacedScrEntry);
+            WARN(("VBoxVrListRectsGet failed, rc %d", rc));
+            goto end;
+        }
+
+        RTPOINT Pos = {0};
+        const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
+
+        uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft);
+        uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop;
+
+        uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth);
+        uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight);
+
+        CR_BLITTER_IMG FbImg;
+
+        bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight;
+
+        crFbImgFromFb(hFb, &FbImg);
+
+        for (uint32_t i = 0; i < cRects; ++i)
+        {
+            const RTRECT * pRect = &pRects[i];
+            for (uint32_t j = 0; j < c2DRects; ++j)
+            {
+                const RTRECT * p2DRect = &p2DRects[j];
+                RTRECT Intersection;
+                VBoxRectIntersected(pRect, p2DRect, &Intersection);
+                if (VBoxRectIsZero(&Intersection))
+                    continue;
+
+                if (!fScale)
+                    crFbBltImg(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, pImg);
+                else
+                    crFbBltImgScaled(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, strX, strY, pImg);
+            }
         }
     }
-    else
-        crWarning("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc);
 
-    if (pMap)
-        CrDemLeave(pMap, CR_DENTRY_FROM_CENTRY(pEntry), CR_DENTRY_FROM_CENTRY(pReplacedScrEntry));
+end:
+
+    if (pEnteredTex)
+        CrTdBltLeave(pEnteredTex);
+
+    if (pEnteredBlitter)
+        CrBltLeave(pEnteredBlitter);
+
+    VBoxVrListClear(&List);
 
     return rc;
 }
 
-void CrDpRegionsClear(PCR_DISPLAY pDisplay)
+static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
 {
-    bool fChanged = false;
-    CrVrScrCompositorRegionsClear(&pDisplay->Mural.Compositor, &fChanged);
-    if (fChanged)
+    uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
+    uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
+
+    /* destination is bigger than the source, do 3D data stretching with CPU */
+    CR_BLITTER_IMG Img;
+    Img.cbData = srcWidth * srcHeight * 4;
+    Img.pvData = RTMemAlloc(Img.cbData);
+    if (!Img.pvData)
     {
-        crServerMuralVisibleRegion(&pDisplay->Mural, 0, NULL);
+        WARN(("RTMemAlloc Failed"));
+        return VERR_NO_MEMORY;
     }
-}
+    Img.enmFormat = pImg->enmFormat;
+    Img.width = srcWidth;
+    Img.height = srcHeight;
+    Img.bpp = pImg->bpp;
+    Img.pitch = Img.width * 4;
+
+    int rc = CrFbBltGetContents(hFb, pSrcRect, cRects, pRects, &Img);
+    if (RT_SUCCESS(rc))
+    {
+        CrBmpScale32((uint8_t *)pImg->pvData,
+                            pImg->pitch,
+                            pImg->width, pImg->height,
+                            (const uint8_t *)Img.pvData,
+                            Img.pitch,
+                            Img.width, Img.height);
+    }
+    else
+        WARN(("CrFbBltGetContents failed %d", rc));
+
+    RTMemFree(Img.pvData);
+
+    return rc;
 
-#define PCR_DISPLAY_ENTRY_FROM_CENTRY(_pe) ((PCR_DISPLAY_ENTRY)((uint8_t*)(_pe) - RT_OFFSETOF(CR_DISPLAY_ENTRY, CEntry)))
-static DECLCALLBACK(void) crDpEntryCEntryReleaseCB(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
-{
-    PCR_DISPLAY_ENTRY pCEntry = PCR_DISPLAY_ENTRY_FROM_CENTRY(pEntry);
-    CrDemEntryRelease(pCEntry);
 }
 
-void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
+int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
 {
-    CrVrScrCompositorEntryInit(&pEntry->CEntry, pTextureData, pfnEntryReleased);
-    CrVrScrCompositorEntryFlagsSet(&pEntry->CEntry, fFlags);
-    CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, pTextureData, NULL);
-    CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, fFlags);
-    pEntry->pvORInstance = NULL;
-    pEntry->idPBO = 0;
-    pEntry->idInvertTex = 0;
+    uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
+    uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
+    if ((srcWidth == pImg->width
+            && srcHeight == pImg->height)
+            || !CrFbHas3DData(hFb)
+            || (srcWidth * srcHeight > pImg->width * pImg->height))
+    {
+        return crFbBltGetContentsDirect(hFb, pSrcRect, cRects, pRects, pImg);
+    }
+
+    return crFbBltGetContentsScaleCPU(hFb, pSrcRect, cRects, pRects, pImg);
 }
 
-void CrDpEntryCleanup(PCR_DISPLAY_ENTRY pDEntry)
+
+int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
 {
-    if (pDEntry->idPBO)
+    if (!pFb->cUpdating)
     {
-        CRASSERT(cr_server.bUsePBOForReadback);
-        cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
-        pDEntry->idPBO = 0;
+        WARN(("no update in progress"));
+        return VERR_INVALID_STATE;
     }
 
-    if (pDEntry->idInvertTex)
+    if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
     {
-        cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
-        pDEntry->idInvertTex = 0;
+        CrVrScrCompositorClear(&pFb->Compositor);
     }
 
-    if (pDEntry->pvORInstance)
+    RTRECT Rect;
+    Rect.xLeft = 0;
+    Rect.yTop = 0;
+    Rect.xRight = pScreen->u32Width;
+    Rect.yBottom = pScreen->u32Height;
+    int rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
+    if (!RT_SUCCESS(rc))
     {
-        cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
-        pDEntry->pvORInstance = NULL;
+        WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
+        return rc;
     }
-}
 
-void CrDpEnter(PCR_DISPLAY pDisplay)
-{
-    pDisplay->fForcePresent |= crServerVBoxCompositionPresentNeeded(&pDisplay->Mural);
-    crServerVBoxCompositionDisableEnter(&pDisplay->Mural);
-}
+    pFb->ScreenInfo = *pScreen;
+    pFb->pvVram = pvVRAM;
 
-void CrDpLeave(PCR_DISPLAY pDisplay)
-{
-    pDisplay->Mural.fDataPresented = GL_TRUE;
-    pDisplay->Mural.fOrPresentOnReenable = GL_TRUE;
-    crServerVBoxCompositionDisableLeave(&pDisplay->Mural, pDisplay->fForcePresent);
-    pDisplay->fForcePresent = GL_FALSE;
+    if (pFb->pDisplay)
+        pFb->pDisplay->FramebufferChanged(pFb);
+
+    return VINF_SUCCESS;
 }
 
-void CrDpRootUpdate(PCR_DISPLAY pDisplay)
+void CrFbTerm(CR_FRAMEBUFFER *pFb)
 {
-    crVBoxServerUpdateMuralRootVisibleRegion(&pDisplay->Mural);
-}
+    if (pFb->cUpdating)
+    {
+        WARN(("update in progress"));
+        return;
+    }
+    uint32_t idScreen = pFb->ScreenInfo.u32ViewIndex;
 
+    CrVrScrCompositorClear(&pFb->Compositor);
+    CrHTableDestroy(&pFb->SlotTable);
 
-typedef struct CR_DEM_ENTRY_INFO
-{
-    CRTextureObj *pTobj;
-    uint32_t cEntries;
-} CR_DEM_ENTRY_INFO;
+    Assert(RTListIsEmpty(&pFb->EntriesList));
+    Assert(!pFb->cEntries);
 
-typedef struct CR_DEM_ENTRY
-{
-    CR_DISPLAY_ENTRY Entry;
-    CR_DEM_ENTRY_INFO *pInfo;
-    CR_DISPLAY_ENTRY_MAP *pMap;
-    RTLISTNODE Node;
-} CR_DEM_ENTRY;
+    memset(pFb, 0, sizeof (*pFb));
 
-#define PCR_DEM_ENTRY_FROM_ENTRY(_pEntry) ((CR_DEM_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_DEM_ENTRY, Entry)))
+    pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
+    pFb->ScreenInfo.u32ViewIndex = idScreen;
+}
 
-static RTMEMCACHE g_VBoxCrDemLookasideList;
-static RTMEMCACHE g_VBoxCrDemInfoLookasideList;
+ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
+{
+    return pFb->pDisplay;
+}
 
-int CrDemGlobalInit()
+int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
 {
-    int rc = RTMemCacheCreate(&g_VBoxCrDemLookasideList, sizeof (CR_DEM_ENTRY),
-                            0, /* size_t cbAlignment */
-                            UINT32_MAX, /* uint32_t cMaxObjects */
-                            NULL, /* PFNMEMCACHECTOR pfnCtor*/
-                            NULL, /* PFNMEMCACHEDTOR pfnDtor*/
-                            NULL, /* void *pvUser*/
-                            0 /* uint32_t fFlags*/
-                            );
-    if (RT_SUCCESS(rc))
+    if (pFb->cUpdating)
     {
-        rc = RTMemCacheCreate(&g_VBoxCrDemInfoLookasideList, sizeof (CR_DEM_ENTRY_INFO),
-                                    0, /* size_t cbAlignment */
-                                    UINT32_MAX, /* uint32_t cMaxObjects */
-                                    NULL, /* PFNMEMCACHECTOR pfnCtor*/
-                                    NULL, /* PFNMEMCACHEDTOR pfnDtor*/
-                                    NULL, /* void *pvUser*/
-                                    0 /* uint32_t fFlags*/
-                                    );
-        if (RT_SUCCESS(rc))
-            return VINF_SUCCESS;
-        else
-            crWarning("RTMemCacheCreate failed rc %d", rc);
-
-        RTMemCacheDestroy(g_VBoxCrDemLookasideList);
+        WARN(("update in progress"));
+        return VERR_INVALID_STATE;
     }
-    else
-        crWarning("RTMemCacheCreate failed rc %d", rc);
+
+    if (pFb->pDisplay == pDisplay)
+        return VINF_SUCCESS;
+
+    pFb->pDisplay = pDisplay;
+
     return VINF_SUCCESS;
 }
 
-void CrDemTeGlobalTerm()
-{
-    RTMemCacheDestroy(g_VBoxCrDemLookasideList);
-    RTMemCacheDestroy(g_VBoxCrDemInfoLookasideList);
-}
+#define CR_PMGR_MODE_WINDOW 0x1
+/* mutually exclusive with CR_PMGR_MODE_WINDOW */
+#define CR_PMGR_MODE_ROOTVR 0x2
+#define CR_PMGR_MODE_VRDP   0x4
+#define CR_PMGR_MODE_ALL    0x7
 
-static CR_DEM_ENTRY* crDemEntryAlloc()
+static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
+
+static CR_FBTEX* crFbTexAlloc()
 {
-    return (CR_DEM_ENTRY*)RTMemCacheAlloc(g_VBoxCrDemLookasideList);
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+    return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
+#else
+    return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
+#endif
 }
 
-static CR_DEM_ENTRY_INFO* crDemEntryInfoAlloc()
+static void crFbTexFree(CR_FBTEX *pTex)
 {
-    return (CR_DEM_ENTRY_INFO*)RTMemCacheAlloc(g_VBoxCrDemInfoLookasideList);
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+    RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
+#else
+    RTMemFree(pTex);
+#endif
 }
 
-static void crDemEntryFree(CR_DEM_ENTRY* pDemEntry)
+static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
 {
-    CrDpEntryCleanup(&pDemEntry->Entry);
-    RTMemCacheFree(g_VBoxCrDemLookasideList, pDemEntry);
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+    return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
+#else
+    return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
+#endif
 }
 
-static void crDemEntryInfoFree(CR_DEM_ENTRY_INFO* pDemEntryInfo)
+static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
 {
-    RTMemCacheFree(g_VBoxCrDemInfoLookasideList, pDemEntryInfo);
+    Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+    RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
+#else
+    RTMemFree(pEntry);
+#endif
 }
 
-void crDemEntryRelease(PCR_DISPLAY_ENTRY_MAP pMap, CR_DEM_ENTRY *pDemEntry)
+DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
 {
-    CR_DEM_ENTRY_INFO *pInfo = pDemEntry->pInfo;
-    CRTextureObj *pTobj = pInfo->pTobj;
+    CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
+    CRTextureObj *pTobj = pFbTex->pTobj;
 
-    --pInfo->cEntries;
+    CrTdBltDataCleanupNe(pTex);
 
-    if (!pInfo->cEntries)
+    if (pTobj)
     {
-        CR_STATE_SHAREDOBJ_USAGE_CLEAR(pInfo->pTobj, cr_server.MainContextInfo.pContext);
+        CR_STATE_SHAREDOBJ_USAGE_CLEAR(pTobj, cr_server.MainContextInfo.pContext);
 
-        crHashtableDelete(pMap->pTexIdToDemInfoMap, pTobj->id, NULL);
+        crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
 
-        crDemEntryInfoFree(pInfo);
-    }
+        if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
+        {
+            CRSharedState *pShared = crStateGlobalSharedAcquire();
 
-    if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
-    {
-        CRSharedState *pShared = crStateGlobalSharedAcquire();
+            CRASSERT(pShared);
+            /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
+             * in addition to calling crStateDeleteTextureObject to delete a state object */
+            crHashtableDelete(pShared->textureTable, pTobj->id, crStateDeleteTextureCallback);
 
-        CRASSERT(pShared);
-        /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
-         * in addition to calling crStateDeleteTextureObject to delete a state object */
-        crHashtableDelete(pShared->textureTable, pTobj->id, crStateDeleteTextureCallback);
+            crStateGlobalSharedRelease();
+        }
 
         crStateGlobalSharedRelease();
     }
 
-    crStateGlobalSharedRelease();
-
-    if (!pMap->cEntered)
-        crDemEntryFree(pDemEntry);
-    else
-        RTListNodeInsertAfter(&pMap->ReleasedList, &pDemEntry->Node);
-}
-
-int CrDemInit(PCR_DISPLAY_ENTRY_MAP pMap)
-{
-    pMap->pTexIdToDemInfoMap = crAllocHashtable();
-    if (pMap->pTexIdToDemInfoMap)
-    {
-        RTListInit(&pMap->ReleasedList);
-        return VINF_SUCCESS;
-    }
-
-    crWarning("crAllocHashtable failed");
-    return VERR_NO_MEMORY;
+    crFbTexFree(pFbTex);
 }
 
-void CrDemTerm(PCR_DISPLAY_ENTRY_MAP pMap)
+void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
 {
-    CRASSERT(RTListIsEmpty(&pMap->ReleasedList));
-    CRASSERT(!pMap->cEntered);
-    crFreeHashtable(pMap->pTexIdToDemInfoMap, NULL);
-    pMap->pTexIdToDemInfoMap = NULL;
-}
+    PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
 
-void CrDemEnter(PCR_DISPLAY_ENTRY_MAP pMap)
-{
-    ++pMap->cEntered;
-    Assert(pMap->cEntered);
+    CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
 }
 
-void CrDemLeave(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY pNewEntry, PCR_DISPLAY_ENTRY pReplacedEntry)
+static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
 {
-    Assert(pMap->cEntered);
-    --pMap->cEntered;
-    Assert(!pReplacedEntry || pNewEntry);
-    if (pNewEntry && pReplacedEntry)
+    CR_FBTEX *pFbTex = crFbTexAlloc();
+    if (!pFbTex)
     {
-        CR_DEM_ENTRY *pNewDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pNewEntry);
-        CR_DEM_ENTRY *pReplacedDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pReplacedEntry);
-        Assert(!RTListIsEmpty(&pMap->ReleasedList));
-        Assert(!RTListIsEmpty(&pReplacedDemEntry->Node));
-        Assert(RTListIsEmpty(&pNewDemEntry->Node));
-        Assert(!pNewDemEntry->Entry.pvORInstance);
-        if (!pNewDemEntry->Entry.pvORInstance)
-        {
-            pNewDemEntry->Entry.pvORInstance = pReplacedDemEntry->Entry.pvORInstance;
-            pReplacedDemEntry->Entry.pvORInstance = NULL;
-        }
-        RTListNodeRemove(&pReplacedDemEntry->Node);
-        crDemEntryFree(pReplacedDemEntry);
+        WARN(("crFbTexAlloc failed!"));
+        return NULL;
     }
 
-    if (!pMap->cEntered)
-    {
-        CR_DEM_ENTRY *pCurEntry, *pNextEntry;
-        RTListForEachSafe(&pMap->ReleasedList, pCurEntry, pNextEntry, CR_DEM_ENTRY, Node)
-        {
-            RTListNodeRemove(&pCurEntry->Node);
-            crDemEntryFree(pCurEntry);
-        }
-    }
-}
+    CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
+    pFbTex->pTobj = NULL;
 
-void CrDemEntryRelease(PCR_DISPLAY_ENTRY pEntry)
-{
-    CR_DEM_ENTRY *pDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pEntry);
-    crDemEntryRelease(pDemEntry->pMap, pDemEntry);
+    return pFbTex;
 }
 
-int CrDemEntrySaveState(PCR_DISPLAY_ENTRY pEntry, PSSMHANDLE pSSM)
-{
-    CR_DEM_ENTRY *pDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pEntry);
-    int  rc = SSMR3PutU32(pSSM, pDemEntry->pInfo->pTobj->id);
-    AssertRCReturn(rc, rc);
-    return rc;
-}
 
-int CrDemEntryLoadState(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY *ppEntry, PSSMHANDLE pSSM)
+CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
 {
-    uint32_t u32;
-    int  rc = SSMR3GetU32(pSSM, &u32);
-    AssertRCReturn(rc, rc);
-
-    PCR_DISPLAY_ENTRY pEntry = CrDemEntryAcquire(pMap, u32, CRBLT_F_INVERT_SRC_YCOORDS);
-    if (!pEntry)
+    CR_FBTEX *pFbTex = crFbTexCreate(pTex);
+    if (!pFbTex)
     {
-        crWarning("CrDemEntryAcquire failed");
-        return VERR_NO_MEMORY;
+        WARN(("crFbTexCreate failed!"));
+        return NULL;
     }
 
-    *ppEntry = pEntry;
-    return VINF_SUCCESS;
+    return &pFbTex->Tex;
 }
 
-PCR_DISPLAY_ENTRY CrDemEntryAcquire(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture, uint32_t fFlags)
+static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
 {
-    CR_DEM_ENTRY *pDemEntry = NULL;
+    CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
+    if (pFbTex)
+    {
+        CrTdAddRef(&pFbTex->Tex);
+        return pFbTex;
+    }
 
     CRSharedState *pShared = crStateGlobalSharedAcquire();
     if (!pShared)
     {
-        crWarning("pShared is null!");
+        WARN(("pShared is null!"));
         return NULL;
     }
 
     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
     if (!pTobj)
     {
-        crWarning("pTobj is null!");
+        LOG(("pTobj is null!"));
         crStateGlobalSharedRelease();
         return NULL;
     }
 
     Assert(pTobj->id == idTexture);
 
-    GLuint hwId = crStateGetTextureObjHWID(pTobj);
-    if (!hwId)
+    GLuint hwid = crStateGetTextureObjHWID(pTobj);
+    if (!hwid)
     {
-        crWarning("hwId is null!");
+        WARN(("hwId is null!"));
         crStateGlobalSharedRelease();
         return NULL;
     }
 
-    VBOXVR_TEXTURE TextureData;
-    TextureData.width = pTobj->level[0]->width;
-    TextureData.height = pTobj->level[0]->height;
-    TextureData.target = pTobj->target;
-    TextureData.hwid = hwId;
+    VBOXVR_TEXTURE Tex;
+    Tex.width = pTobj->level[0]->width;
+    Tex.height = pTobj->level[0]->height;
+    Tex.hwid = hwid;
+    Tex.target = pTobj->target;
 
-    pDemEntry = crDemEntryAlloc();
-    if (!pDemEntry)
+    pFbTex = crFbTexCreate(&Tex);
+    if (!pFbTex)
     {
-        crWarning("crDemEntryAlloc failed allocating CR_DEM_ENTRY");
+        WARN(("crFbTexCreate failed!"));
         crStateGlobalSharedRelease();
         return NULL;
     }
 
-    CrDpEntryInit(&pDemEntry->Entry, &TextureData, fFlags, crDpEntryCEntryReleaseCB);
+    CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
 
-    CR_DEM_ENTRY_INFO *pInfo = (CR_DEM_ENTRY_INFO*)crHashtableSearch(pMap->pTexIdToDemInfoMap, pTobj->id);
-    if (!pInfo)
+    pFbTex->pTobj = pTobj;
+
+    crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
+
+    return pFbTex;
+}
+
+static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+    if (pEntry->Flags.fCreateNotified)
+    {
+        pEntry->Flags.fCreateNotified = 0;
+        if (pFb->pDisplay)
+            pFb->pDisplay->EntryDestroyed(pFb, pEntry);
+
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
+        if (pTex)
+            CrTdBltDataInvalidateNe(pTex);
+    }
+}
+
+static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+    crFbEntryMarkDestroyed(pFb, pEntry);
+    CrVrScrCompositorEntryCleanup(&pEntry->Entry);
+    CrHTableDestroy(&pEntry->HTable);
+    Assert(pFb->cEntries);
+    RTListNodeRemove(&pEntry->Node);
+    --pFb->cEntries;
+    crFbEntryFree(pEntry);
+}
+
+DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+    return ++pEntry->cRefs;
+}
+
+DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+    uint32_t cRefs = --pEntry->cRefs;
+    if (!cRefs)
+        crFbEntryDestroy(pFb, pEntry);
+    return cRefs;
+}
+
+static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
+{
+    CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
+    CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
+    CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
+    if (pFbReplacingEntry)
+    {
+        /*replace operation implies the replaced entry gets auto-destroyed,
+         * while all its data gets moved to the *clean* replacing entry
+         * 1. ensure the replacing entry is cleaned up */
+        crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
+
+        CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
+
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
+        CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
+
+        CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
+
+        if (pFb->pDisplay)
+            pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
+
+        CrTdBltDataInvalidateNe(pTex);
+
+        /* 2. mark the replaced entry is destroyed */
+        Assert(pFbEntry->Flags.fCreateNotified);
+        Assert(pFbEntry->Flags.fInList);
+        pFbEntry->Flags.fCreateNotified = 0;
+        pFbEntry->Flags.fInList = 0;
+        pFbReplacingEntry->Flags.fCreateNotified = 1;
+        pFbReplacingEntry->Flags.fInList = 1;
+    }
+    else
+    {
+        if (pFbEntry->Flags.fInList)
+        {
+            pFbEntry->Flags.fInList = 0;
+            if (pFb->pDisplay)
+                pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
+
+            CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
+            if (pTex)
+                CrTdBltDataInvalidateNe(pTex);
+        }
+    }
+
+    crFbEntryRelease(pFb, pFbEntry);
+}
+
+static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
+{
+    CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
+    if (!pEntry)
+    {
+        WARN(("crFbEntryAlloc failed!"));
+        return NULL;
+    }
+
+    CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
+    CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
+    pEntry->cRefs = 1;
+    pEntry->Flags.Value = 0;
+    CrHTableCreate(&pEntry->HTable, 0);
+
+    RTListAppend(&pFb->EntriesList, &pEntry->Node);
+    ++pFb->cEntries;
+
+    return pEntry;
+}
+
+int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
+{
+    RTRECT Rect;
+    Rect.xLeft = 0;
+    Rect.yTop = 0;
+    Rect.xRight = pTex->Tex.width;
+    Rect.yBottom = pTex->Tex.height;
+    CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
+    if (!pEntry)
+    {
+        WARN(("crFbEntryCreate failed"));
+        return VERR_NO_MEMORY;
+    }
+
+    *phEntry = pEntry;
+    return VINF_SUCCESS;
+}
+
+int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
+{
+    if (!pFb->cUpdating)
+    {
+        WARN(("framebuffer not updating"));
+        return VERR_INVALID_STATE;
+    }
+
+    if (pTex)
+        CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
+
+    if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
+    {
+        if (pFb->pDisplay)
+            pFb->pDisplay->EntryTexChanged(pFb, pEntry);
+
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
+        if (pTex)
+            CrTdBltDataInvalidateNe(pTex);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
+{
+    CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
+    if (!pFbTex)
+    {
+        LOG(("crFbTexAcquire failed"));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    CR_TEXDATA* pTex = &pFbTex->Tex;
+    int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
+    if (!RT_SUCCESS(rc))
+    {
+    	WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
+    }
+
+    /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
+    CrTdRelease(pTex);
+    return rc;
+}
+
+void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+    ++hEntry->cRefs;
+}
+
+void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+    crFbEntryRelease(pFb, hEntry);
+}
+
+int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
+{
+    if (!hFb->cUpdating)
+    {
+        WARN(("framebuffer not updating"));
+        return VERR_INVALID_STATE;
+    }
+
+    bool fChanged = false;
+    CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
+    if (fChanged)
+    {
+        if (hFb->pDisplay)
+            hFb->pDisplay->RegionsChanged(hFb);
+    }
+
+    return VINF_SUCCESS;
+}
+
+int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
+{
+    if (!pFb->cUpdating)
+    {
+        WARN(("framebuffer not updating"));
+        return VERR_INVALID_STATE;
+    }
+
+    uint32_t fChangeFlags = 0;
+    VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
+    VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
+    bool fEntryWasInList;
+
+    if (hEntry)
+    {
+        crFbEntryAddRef(hEntry);
+        pNewEntry = &hEntry->Entry;
+        fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
+
+        Assert(!hEntry->Flags.fInList == !fEntryWasInList);
+    }
+    else
+    {
+        pNewEntry = NULL;
+        fEntryWasInList = false;
+    }
+
+    int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
+    if (RT_SUCCESS(rc))
+    {
+        if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
+        {
+            if (!fEntryWasInList && pNewEntry)
+            {
+                Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
+                if (!hEntry->Flags.fCreateNotified)
+                {
+                    hEntry->Flags.fCreateNotified = 1;
+                    if (pFb->pDisplay)
+                        pFb->pDisplay->EntryCreated(pFb, hEntry);
+                }
+
+#ifdef DEBUG_misha
+                /* in theory hEntry->Flags.fInList can be set if entry is replaced,
+                 * but then modified to fit the compositor rects,
+                 * and so we get the regions changed notification as a result
+                 * this should not generally happen though, so put an assertion to debug that situation */
+                Assert(!hEntry->Flags.fInList);
+#endif
+                if (!hEntry->Flags.fInList)
+                {
+                    hEntry->Flags.fInList = 1;
+
+                    if (pFb->pDisplay)
+                        pFb->pDisplay->EntryAdded(pFb, hEntry);
+                }
+            }
+            if (pFb->pDisplay)
+                pFb->pDisplay->RegionsChanged(pFb);
+
+            Assert(!pReplacedScrEntry);
+        }
+        else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+        {
+            Assert(pReplacedScrEntry);
+            /* we have already processed that in a "release" callback */
+            Assert(hEntry);
+        }
+        else
+        {
+            Assert(!fChangeFlags);
+            Assert(!pReplacedScrEntry);
+        }
+
+        if (hEntry)
+        {
+            if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
+            {
+                if (pFb->pDisplay)
+                    pFb->pDisplay->EntryTexChanged(pFb, hEntry);
+
+                CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
+                if (pTex)
+                    CrTdBltDataInvalidateNe(pTex);
+            }
+        }
+    }
+    else
+        WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
+
+    return rc;
+}
+
+int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
+{
+    if (!pFb->cUpdating)
+    {
+        WARN(("framebuffer not updating"));
+        return VERR_INVALID_STATE;
+    }
+
+    bool fChanged = 0;
+    VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
+    VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
+    bool fEntryWasInList;
+
+    if (hEntry)
+    {
+        crFbEntryAddRef(hEntry);
+        pNewEntry = &hEntry->Entry;
+        fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
+        Assert(!hEntry->Flags.fInList == !fEntryWasInList);
+    }
+    else
+    {
+        pNewEntry = NULL;
+        fEntryWasInList = false;
+    }
+
+    int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
+    if (RT_SUCCESS(rc))
+    {
+        if (fChanged)
+        {
+            if (!fEntryWasInList && pNewEntry)
+            {
+                if (CrVrScrCompositorEntryIsUsed(pNewEntry))
+                {
+                    if (!hEntry->Flags.fCreateNotified)
+                    {
+                        hEntry->Flags.fCreateNotified = 1;
+
+                        if (pFb->pDisplay)
+                            pFb->pDisplay->EntryCreated(pFb, hEntry);
+                    }
+
+                    Assert(!hEntry->Flags.fInList);
+                    hEntry->Flags.fInList = 1;
+
+                    if (pFb->pDisplay)
+                        pFb->pDisplay->EntryAdded(pFb, hEntry);
+                }
+            }
+
+            if (pFb->pDisplay)
+                pFb->pDisplay->RegionsChanged(pFb);
+        }
+
+        if (hEntry)
+        {
+            if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
+            {
+                if (pFb->pDisplay)
+                    pFb->pDisplay->EntryTexChanged(pFb, hEntry);
+
+                CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
+                if (pTex)
+                    CrTdBltDataInvalidateNe(pTex);
+            }
+        }
+    }
+    else
+        WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+
+    return rc;
+}
+
+const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+    return &hEntry->Entry;
+}
+
+HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
+{
+    return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
+}
+
+void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
+{
+    HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
+    RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
+    {
+        if (hEntry->Flags.fCreateNotified)
+        {
+            if (!pfnVisitorCb(hFb, hEntry, pvContext))
+                return;
+        }
+    }
+}
+
+
+CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
+{
+    return CrHTablePut(&pFb->SlotTable, (void*)1);
+}
+
+void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
+{
+    HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
+    RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
+    {
+        if (CrFbDDataEntryGet(hEntry, hSlot))
+        {
+            if (pfnReleaseCb)
+                pfnReleaseCb(pFb, hEntry, pvContext);
+
+            CrFbDDataEntryClear(hEntry, hSlot);
+        }
+    }
+
+    CrHTableRemove(&pFb->SlotTable, hSlot);
+}
+
+int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
+{
+    return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
+}
+
+void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
+{
+    return CrHTableRemove(&hEntry->HTable, hSlot);
+}
+
+void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
+{
+    return CrHTableGet(&hEntry->HTable, hSlot);
+}
+
+typedef union CR_FBDISPBASE_FLAGS
+{
+    struct {
+        uint32_t fRegionsShanged : 1;
+        uint32_t Reserved        : 31;
+    };
+    uint32_t u32Value;
+} CR_FBDISPBASE_FLAGS;
+
+class CrFbDisplayBase : public ICrFbDisplay
+{
+public:
+    CrFbDisplayBase() :
+        mpContainer(NULL),
+        mpFb(NULL),
+        mcUpdates(0),
+        mhSlot(CRHTABLE_HANDLE_INVALID)
+    {
+        mFlags.u32Value = 0;
+    }
+
+    virtual bool isComposite()
+    {
+        return false;
+    }
+
+    class CrFbDisplayComposite* getContainer()
+    {
+        return mpContainer;
+    }
+
+    bool isInList()
+    {
+        return !!mpContainer;
+    }
+
+    bool isUpdating()
+    {
+        return !!mcUpdates;
+    }
+
+    int setRegionsChanged()
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        mFlags.fRegionsShanged = 1;
+        return VINF_SUCCESS;
+    }
+
+    int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
+    {
+        if (mcUpdates)
+        {
+            WARN(("trying to set framebuffer while update is in progress"));
+            return VERR_INVALID_STATE;
+        }
+
+        if (mpFb == pFb)
+            return VINF_SUCCESS;
+
+        int rc = setFramebufferBegin(pFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        if (mpFb)
+        {
+            rc = fbCleanup();
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                setFramebufferEnd(pFb);
+                return rc;
+            }
+        }
+
+        mpFb = pFb;
+
+        if (mpFb)
+        {
+            rc = fbSync();
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                setFramebufferEnd(pFb);
+                return rc;
+            }
+        }
+
+        setFramebufferEnd(pFb);
+        return VINF_SUCCESS;
+    }
+
+    struct CR_FRAMEBUFFER* getFramebuffer()
+    {
+        return mpFb;
+    }
+
+    virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+    {
+        ++mcUpdates;
+        Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
+        return VINF_SUCCESS;
+    }
+
+    virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+    {
+        --mcUpdates;
+        Assert(mcUpdates < UINT32_MAX/2);
+        if (!mcUpdates)
+            onUpdateEnd();
+    }
+
+    virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        mFlags.fRegionsShanged = 1;
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        mFlags.fRegionsShanged = 1;
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        mFlags.fRegionsShanged = 1;
+        return VINF_SUCCESS;
+    }
+
+    virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        mFlags.fRegionsShanged = 1;
+        return VINF_SUCCESS;
+    }
+
+    virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        if (!mcUpdates)
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual ~CrFbDisplayBase();
+
+    /*@todo: move to protected and switch from RTLISTNODE*/
+    RTLISTNODE mNode;
+    class CrFbDisplayComposite* mpContainer;
+protected:
+    virtual void onUpdateEnd()
+    {
+        if (mFlags.fRegionsShanged)
+        {
+            mFlags.fRegionsShanged = 0;
+            if (getFramebuffer()) /*<-dont't do anything on cleanup*/
+                ueRegions();
+        }
+    }
+
+    virtual void ueRegions()
+    {
+    }
+
+    static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
+    {
+        int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+        }
+        return true;
+    }
+
+    static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
+    {
+        int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+        }
+        return true;
+    }
+
+    int fbSynchAddAllEntries()
+    {
+        VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+        const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+
+        CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
+
+        int rc = VINF_SUCCESS;
+
+        CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
+
+        while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+        {
+            HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+
+            rc = EntryAdded(mpFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                EntryDestroyed(mpFb, hEntry);
+                break;
+            }
+        }
+
+        return rc;
+    }
+
+    int fbCleanupRemoveAllEntries()
+    {
+        VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+        const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+
+        CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
+
+        int rc = VINF_SUCCESS;
+
+        while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+        {
+            HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+            rc = EntryRemoved(mpFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                break;
+            }
+
+            CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
+        }
+
+        return rc;
+    }
+
+    virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
+    {
+        return UpdateBegin(pFb);
+    }
+    virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
+    {
+        UpdateEnd(pFb);
+    }
+
+    static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
+    {
+    }
+
+    virtual void slotRelease()
+    {
+        Assert(mhSlot);
+        CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
+    }
+
+    virtual int fbCleanup()
+    {
+        if (mhSlot)
+        {
+            slotRelease();
+            mhSlot = 0;
+        }
+        mpFb = NULL;
+        return VINF_SUCCESS;
+    }
+
+    virtual int fbSync()
+    {
+        return VINF_SUCCESS;
+    }
+
+    CRHTABLE_HANDLE slotGet()
+    {
+        if (!mhSlot)
+        {
+            if (mpFb)
+                mhSlot = CrFbDDataAllocSlot(mpFb);
+        }
+
+        return mhSlot;
+    }
+
+private:
+    struct CR_FRAMEBUFFER *mpFb;
+    uint32_t mcUpdates;
+    CRHTABLE_HANDLE mhSlot;
+    CR_FBDISPBASE_FLAGS mFlags;
+};
+
+class CrFbDisplayComposite : public CrFbDisplayBase
+{
+public:
+    CrFbDisplayComposite() :
+        mcDisplays(0)
+    {
+        RTListInit(&mDisplays);
+    }
+
+    virtual bool isComposite()
+    {
+        return true;
+    }
+
+    uint32_t getDisplayCount()
+    {
+        return mcDisplays;
+    }
+
+    bool add(CrFbDisplayBase *pDisplay)
+    {
+        if (pDisplay->isInList())
+        {
+            WARN(("entry in list already"));
+            return false;
+        }
+
+        RTListAppend(&mDisplays, &pDisplay->mNode);
+        pDisplay->mpContainer = this;
+        pDisplay->setFramebuffer(getFramebuffer());
+        ++mcDisplays;
+        return true;
+    }
+
+    bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
+    {
+        if (pDisplay->getContainer() != this)
+        {
+            WARN(("invalid entry container"));
+            return false;
+        }
+
+        RTListNodeRemove(&pDisplay->mNode);
+        pDisplay->mpContainer = NULL;
+        if (fCleanupDisplay)
+            pDisplay->setFramebuffer(NULL);
+        --mcDisplays;
+        return true;
+    }
+
+    CrFbDisplayBase* first()
+    {
+        return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
+    }
+
+    CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
+    {
+        if (pDisplay->getContainer() != this)
+        {
+            WARN(("invalid entry container"));
+            return NULL;
+        }
+
+        return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
+    }
+
+    virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
+    {
+        CrFbDisplayBase::setFramebuffer(pFb);
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            pIter->setFramebuffer(pFb);
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = CrFbDisplayBase::UpdateBegin(pFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            rc = pIter->UpdateBegin(pFb);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+    {
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            pIter->UpdateEnd(pFb);
+        }
+
+        CrFbDisplayBase::UpdateEnd(pFb);
+    }
+
+    virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->EntryAdded(pFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->EntryCreated(pFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+    {
+        int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->EntryTexChanged(pFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->EntryRemoved(pFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->EntryDestroyed(pFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = CrFbDisplayBase::RegionsChanged(pFb);
+          if (!RT_SUCCESS(rc))
+          {
+              WARN(("err"));
+              return rc;
+          }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->RegionsChanged(pFb);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+          if (!RT_SUCCESS(rc))
+          {
+              WARN(("err"));
+              return rc;
+          }
+
+        CrFbDisplayBase *pIter;
+        RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+        {
+            int rc = pIter->FramebufferChanged(pFb);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+        return VINF_SUCCESS;
+    }
+
+    virtual ~CrFbDisplayComposite()
+    {
+        cleanup();
+    }
+
+    void cleanup(bool fCleanupDisplays = true)
+    {
+        CrFbDisplayBase *pIter, *pIterNext;
+        RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
+        {
+            remove(pIter, fCleanupDisplays);
+        }
+    }
+private:
+    RTLISTNODE mDisplays;
+    uint32_t mcDisplays;
+};
+
+typedef union CR_FBWIN_FLAGS
+{
+    struct {
+        uint32_t fVisible : 1;
+        uint32_t fDataPresented : 1;
+        uint32_t fForcePresentOnReenable : 1;
+        uint32_t fCompositoEntriesModified : 1;
+        uint32_t Reserved : 28;
+    };
+    uint32_t Value;
+} CR_FBWIN_FLAGS;
+
+class CrFbWindow
+{
+public:
+    CrFbWindow(uint64_t parentId) :
+        mSpuWindow(0),
+        mpCompositor(NULL),
+        mcUpdates(0),
+        mxPos(0),
+        myPos(0),
+        mWidth(0),
+        mHeight(0),
+        mParentId(parentId)
+    {
+        mFlags.Value = 0;
+    }
+
+    bool IsCreated()
+    {
+        return !!mSpuWindow;
+    }
+
+    void Destroy()
+    {
+        CRASSERT(!mcUpdates);
+
+        if (!mSpuWindow)
+            return;
+
+        cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
+
+        mSpuWindow = 0;
+        mFlags.fDataPresented = 0;
+    }
+
+    int Reparent(uint64_t parentId)
+    {
+        if (!checkInitedUpdating())
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        uint64_t oldParentId = mParentId;
+
+        mParentId = parentId;
+
+        if (mSpuWindow)
+        {
+            if (oldParentId && !parentId && mFlags.fVisible)
+                cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
+
+            renderspuSetWindowId(mParentId);
+            renderspuReparentWindow(mSpuWindow);
+            renderspuSetWindowId(cr_server.screen[0].winID);
+
+            if (parentId)
+                cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
+
+            if (!oldParentId && parentId && mFlags.fVisible)
+                cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    int SetVisible(bool fVisible)
+    {
+        if (!checkInitedUpdating())
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        LOG(("CrWIN: Vidible [%d]", fVisible));
+
+        if (!fVisible != !mFlags.fVisible)
+        {
+            mFlags.fVisible = fVisible;
+            if (mSpuWindow && mParentId)
+                cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    int SetSize(uint32_t width, uint32_t height)
+    {
+        if (!checkInitedUpdating())
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        LOG(("CrWIN: Size [%d ; %d]", width, height));
+
+        if (mWidth != width || mHeight != height)
+        {
+            mFlags.fCompositoEntriesModified = 1;
+            mWidth = width;
+            mHeight = height;
+            if (mSpuWindow)
+                cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    int SetPosition(int32_t x, int32_t y)
+    {
+        if (!checkInitedUpdating())
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        LOG(("CrWIN: Pos [%d ; %d]", x, y));
+//      always do WindowPosition to ensure window is adjusted properly
+//        if (x != mxPos || y != myPos)
+        {
+            mxPos = x;
+            myPos = y;
+            if (mSpuWindow)
+                cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    int SetVisibleRegionsChanged()
+    {
+        if (!checkInitedUpdating())
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        mFlags.fCompositoEntriesModified = 1;
+        return VINF_SUCCESS;
+    }
+
+    int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
+    {
+        if (!checkInitedUpdating())
+        {
+            WARN(("err"));
+            return VERR_INVALID_STATE;
+        }
+
+        mpCompositor = pCompositor;
+        mFlags.fCompositoEntriesModified = 1;
+        return VINF_SUCCESS;
+    }
+
+    int UpdateBegin()
+    {
+        ++mcUpdates;
+        if (mcUpdates > 1)
+            return VINF_SUCCESS;
+
+        Assert(!mFlags.fForcePresentOnReenable);
+//        Assert(!mFlags.fCompositoEntriesModified);
+
+        if (mFlags.fDataPresented)
+        {
+            Assert(mSpuWindow);
+            cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
+            mFlags.fForcePresentOnReenable = isPresentNeeded();
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    void UpdateEnd()
+    {
+        --mcUpdates;
+        Assert(mcUpdates < UINT32_MAX/2);
+        if (mcUpdates)
+            return;
+
+        checkRegions();
+
+        if (mSpuWindow)
+        {
+            bool fPresentNeeded = isPresentNeeded();
+            if (fPresentNeeded || mFlags.fForcePresentOnReenable)
+            {
+                mFlags.fForcePresentOnReenable = false;
+                cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
+            }
+
+            /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
+             * the backend should clean up the compositor as soon as presentation is performed */
+            mFlags.fDataPresented = fPresentNeeded;
+        }
+        else
+        {
+            Assert(!mFlags.fDataPresented);
+            Assert(!mFlags.fForcePresentOnReenable);
+        }
+    }
+
+    uint64_t GetParentId()
+    {
+        return mParentId;
+    }
+
+    int Create()
+    {
+        if (mSpuWindow)
+        {
+            //WARN(("window already created"));
+            return VINF_ALREADY_INITIALIZED;
+        }
+
+        CRASSERT(cr_server.fVisualBitsDefault);
+        renderspuSetWindowId(mParentId);
+        mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
+        renderspuSetWindowId(cr_server.screen[0].winID);
+        if (mSpuWindow < 0) {
+            WARN(("WindowCreate failed"));
+            return VERR_GENERAL_FAILURE;
+        }
+
+        cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
+        cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
+
+        checkRegions();
+
+        if (mParentId && mFlags.fVisible)
+            cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
+
+        return VINF_SUCCESS;
+    }
+
+    ~CrFbWindow()
+    {
+        Destroy();
+    }
+protected:
+    void checkRegions()
+    {
+        if (!mSpuWindow)
+            return;
+
+        if (!mFlags.fCompositoEntriesModified)
+            return;
+
+        uint32_t cRects;
+        const RTRECT *pRects;
+        if (mpCompositor)
+        {
+            int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
+                cRects = 0;
+                pRects = NULL;
+            }
+        }
+        else
+        {
+            cRects = 0;
+            pRects = NULL;
+        }
+
+        cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
+
+        mFlags.fCompositoEntriesModified = 0;
+    }
+
+    bool isPresentNeeded()
+    {
+        return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
+    }
+
+    bool checkInitedUpdating()
+    {
+        if (!mcUpdates)
+        {
+            WARN(("not updating"));
+            return false;
+        }
+
+        return true;
+    }
+private:
+    GLint mSpuWindow;
+    const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
+    uint32_t mcUpdates;
+    int32_t mxPos;
+    int32_t myPos;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    CR_FBWIN_FLAGS mFlags;
+    uint64_t mParentId;
+};
+
+typedef union CR_FBDISPWINDOW_FLAGS
+{
+    struct {
+        uint32_t fNeVisible : 1;
+        uint32_t fNeForce   : 1;
+        uint32_t Reserved   : 30;
+    };
+    uint32_t u32Value;
+} CR_FBDISPWINDOW_FLAGS;
+class CrFbDisplayWindow : public CrFbDisplayBase
+{
+public:
+    CrFbDisplayWindow(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
+        mpWindow(pWindow),
+        mViewportRect(*pViewportRect),
+        mu32Screen(~0)
+    {
+        mFlags.u32Value = 0;
+        CRASSERT(pWindow);
+    }
+
+    virtual ~CrFbDisplayWindow()
+    {
+        if (mpWindow)
+            delete mpWindow;
+    }
+
+    virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = mpWindow->UpdateBegin();
+        if (RT_SUCCESS(rc))
+        {
+            rc = CrFbDisplayBase::UpdateBegin(pFb);
+            if (RT_SUCCESS(rc))
+                return VINF_SUCCESS;
+            else
+                WARN(("err"));
+        }
+        else
+            WARN(("err"));
+
+        return rc;
+    }
+
+    virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+    {
+        CrFbDisplayBase::UpdateEnd(pFb);
+
+        mpWindow->UpdateEnd();
+    }
+
+    virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        if (mpWindow->GetParentId())
+        {
+            rc = mpWindow->Create();
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+    {
+        int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        if (mpWindow->GetParentId())
+        {
+            rc = mpWindow->Create();
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        if (mpWindow->GetParentId())
+        {
+            rc = mpWindow->Create();
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("err"));
+                return rc;
+            }
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return screenChanged();
+    }
+
+    const RTRECT* getViewportRect()
+    {
+        return &mViewportRect;
+    }
+
+    virtual int setViewportRect(const RTRECT *pViewportRect)
+    {
+        if (!isUpdating())
+        {
+            WARN(("not updating!"));
+            return VERR_INVALID_STATE;
+        }
+
+// always call SetPosition to ensure window is adjustep properly
+//        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
+        {
+            const RTRECT* pRect = getRect();
+            int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("SetPosition failed"));
+                return rc;
+            }
+        }
+
+        mViewportRect = *pViewportRect;
+
+        return VINF_SUCCESS;
+    }
+
+    virtual CrFbWindow * windowDetach()
+    {
+        if (isUpdating())
+        {
+            WARN(("updating!"));
+            return NULL;
+        }
+
+        CrFbWindow * pWindow = mpWindow;
+        if (mpWindow)
+        {
+            windowCleanup();
+            mpWindow = NULL;
+        }
+        return pWindow;
+    }
+
+    virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
+    {
+        if (isUpdating())
+        {
+            WARN(("updating!"));
+            return NULL;
+        }
+
+        CrFbWindow * pOld = mpWindow;
+        if (mpWindow)
+            windowDetach();
+
+        mpWindow = pNewWindow;
+        if (pNewWindow)
+            windowSync();
+
+        return mpWindow;
+    }
+
+    virtual int reparent(uint64_t parentId)
+    {
+        if (!isUpdating())
+        {
+            WARN(("not updating!"));
+            return VERR_INVALID_STATE;
+        }
+
+        int rc = mpWindow->Reparent(parentId);
+        if (!RT_SUCCESS(rc))
+            WARN(("window reparent failed"));
+
+        mFlags.fNeForce = 1;
+
+        return rc;
+    }
+
+    virtual bool isVisible()
+    {
+        HCR_FRAMEBUFFER hFb = getFramebuffer();
+        if (!hFb)
+            return false;
+        const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
+        return !CrVrScrCompositorIsEmpty(pCompositor);
+    }
+
+    int winVisibilityChanged()
+    {
+        int rc = mpWindow->UpdateBegin();
+        if (RT_SUCCESS(rc))
+        {
+            rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
+            if (!RT_SUCCESS(rc))
+                WARN(("SetVisible failed, rc %d", rc));
+
+            mpWindow->UpdateEnd();
+        }
+        else
+            WARN(("UpdateBegin failed, rc %d", rc));
+
+        return rc;
+    }
+
+protected:
+    virtual void onUpdateEnd()
+    {
+        CrFbDisplayBase::onUpdateEnd();
+        bool fVisible = isVisible();
+        if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
+        {
+            crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
+            mFlags.fNeVisible = fVisible;
+            mFlags.fNeForce = 0;
+        }
+    }
+
+    virtual void ueRegions()
+    {
+        mpWindow->SetVisibleRegionsChanged();
+    }
+
+    virtual int screenChanged()
+    {
+        if (!isUpdating())
+        {
+            WARN(("not updating!"));
+            return VERR_INVALID_STATE;
+        }
+
+        if (CrFbIsEnabled(getFramebuffer()))
+        {
+            const RTRECT* pRect = getRect();
+            int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("SetComposition failed rc %d", rc));
+                return rc;
+            }
+
+            setRegionsChanged();
+
+            return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
+        }
+
+        return mpWindow->SetVisible(false);
+    }
+
+    virtual int windowSetCompositor(bool fSet)
+    {
+        if (fSet)
+        {
+            const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
+            return mpWindow->SetCompositor(pCompositor);
+        }
+        return mpWindow->SetCompositor(NULL);
+    }
+
+    virtual int windowCleanup()
+    {
+        int rc = mpWindow->UpdateBegin();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        rc = mpWindow->SetVisible(false);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            mpWindow->UpdateEnd();
+            return rc;
+        }
+
+        rc = windowSetCompositor(false);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            mpWindow->UpdateEnd();
+            return rc;
+        }
+
+        mpWindow->UpdateEnd();
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int fbCleanup()
+    {
+        int rc = windowCleanup();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("windowCleanup failed"));
+            return rc;
+        }
+        return CrFbDisplayBase::fbCleanup();
+    }
+
+    virtual int windowSync()
+    {
+        const RTRECT* pRect = getRect();
+
+        int rc = mpWindow->UpdateBegin();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        rc = windowSetCompositor(true);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            mpWindow->UpdateEnd();
+            return rc;
+        }
+
+        rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            mpWindow->UpdateEnd();
+            return rc;
+        }
+
+        rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            mpWindow->UpdateEnd();
+            return rc;
+        }
+
+        rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            mpWindow->UpdateEnd();
+            return rc;
+        }
+
+        mpWindow->UpdateEnd();
+
+        return rc;
+    }
+
+    virtual int fbSync()
+    {
+        int rc = CrFbDisplayBase::fbSync();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        mu32Screen = CrFbGetScreenInfo(getFramebuffer())->u32ViewIndex;
+
+        return windowSync();
+    }
+
+    virtual const struct RTRECT* getRect()
+    {
+        const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
+        return CrVrScrCompositorRectGet(pCompositor);
+    }
+
+    CrFbWindow* getWindow() {return mpWindow;}
+private:
+    CrFbWindow *mpWindow;
+    RTRECT mViewportRect;
+    CR_FBDISPWINDOW_FLAGS mFlags;
+    uint32_t mu32Screen;
+};
+
+class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
+{
+public:
+    CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
+        CrFbDisplayWindow(pWindow, pViewportRect)
+    {
+        CrVrScrCompositorInit(&mCompositor, NULL);
+    }
+
+    virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
+        CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
+        CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
+        rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrFbDDataEntryPut failed rc %d", rc));
+            entryFree(pMyEntry);
+            return rc;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+        Assert(pMyEntry);
+        CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+    {
+        int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
+        CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+        CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+        rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+        CrVrScrCompositorEntryCleanup(pMyEntry);
+        entryFree(pMyEntry);
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int setViewportRect(const RTRECT *pViewportRect)
+    {
+        int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        rc = setRegionsChanged();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+protected:
+    virtual int windowSetCompositor(bool fSet)
+    {
+        if (fSet)
+            return getWindow()->SetCompositor(&mCompositor);
+        return getWindow()->SetCompositor(NULL);
+    }
+
+    virtual void ueRegions()
+    {
+        synchCompositorRegions();
+    }
+
+    int compositorMarkUpdated()
+    {
+        CrVrScrCompositorClear(&mCompositor);
+
+        int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        rc = setRegionsChanged();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("screenChanged failed %d", rc));
+            return rc;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int screenChanged()
+    {
+        int rc = compositorMarkUpdated();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        rc = CrFbDisplayWindow::screenChanged();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("screenChanged failed %d", rc));
+            return rc;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual const struct RTRECT* getRect()
+    {
+        return CrVrScrCompositorRectGet(&mCompositor);
+    }
+
+    virtual int fbCleanup()
+    {
+        int rc = clearCompositor();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return CrFbDisplayWindow::fbCleanup();
+    }
+
+    virtual int fbSync()
+    {
+        int rc = synchCompositor();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return CrFbDisplayWindow::fbSync();
+    }
+
+    VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
+    {
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+        return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
+#else
+        return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
+#endif
+    }
+
+    void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
+    {
+        Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+        RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
+#else
+        RTMemFree(pEntry);
+#endif
+    }
+
+    int synchCompositorRegions()
+    {
+        int rc;
+
+        rootVrTranslateForPos();
+
+        /* ensure the rootvr compositor does not hold any data,
+         * i.e. cleanup all rootvr entries data */
+        CrVrScrCompositorClear(&mCompositor);
+
+        rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
+            return rc;
+        }
+
+        return getWindow()->SetVisibleRegionsChanged();
+    }
+
+    virtual int synchCompositor()
+    {
+        int rc = compositorMarkUpdated();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("compositorMarkUpdated failed, rc %d", rc));
+            return rc;
+        }
+
+        rc = fbSynchAddAllEntries();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("fbSynchAddAllEntries failed, rc %d", rc));
+            return rc;
+        }
+
+        return rc;
+    }
+
+    virtual int clearCompositor()
+    {
+        return fbCleanupRemoveAllEntries();
+    }
+
+    void rootVrTranslateForPos()
+    {
+        const RTRECT *pRect = getViewportRect();
+        const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
+        int32_t x = pScreen->i32OriginX;
+        int32_t y = pScreen->i32OriginY;
+        int32_t dx = cr_server.RootVrCurPoint.x - x;
+        int32_t dy = cr_server.RootVrCurPoint.y - y;
+
+        cr_server.RootVrCurPoint.x = x;
+        cr_server.RootVrCurPoint.y = y;
+
+        VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
+    }
+
+    static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
+    {
+        CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
+        HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+        VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
+        Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
+        CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
+        return pMyEntry;
+    }
+private:
+    VBOXVR_SCR_COMPOSITOR mCompositor;
+};
+
+class CrFbDisplayVrdp : public CrFbDisplayBase
+{
+public:
+    CrFbDisplayVrdp()
+    {
+        memset(&mPos, 0, sizeof (mPos));
+    }
+
+    virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("EntryAdded failed rc %d", rc));
+            return rc;
+        }
+
+        Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
+        rc = vrdpCreate(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("vrdpCreate failed rc %d", rc));
+            return rc;
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+    {
+        int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
+        CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
+        CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
+
+        CrTdBltDataInvalidateNe(pReplacedTex);
+
+        rc = CrTdBltEnter(pNewTex);
+        if (RT_SUCCESS(rc))
+        {
+            rc = vrdpFrame(hNewEntry);
+            CrTdBltLeave(pNewTex);
+        }
+        else
+            WARN(("CrTdBltEnter failed %d", rc));
+
+        return rc;
+    }
+
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+
+        rc = CrTdBltEnter(pTex);
+        if (RT_SUCCESS(rc))
+        {
+            rc = vrdpFrame(hEntry);
+            CrTdBltLeave(pTex);
+        }
+        else
+            WARN(("CrTdBltEnter failed %d", rc));
+
+    	return rc;
+    }
+
+    virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+        CrTdBltDataInvalidateNe(pTex);
+
+        return vrdpRegions(pFb, hEntry);
+    }
+
+    virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        vrdpDestroy(hEntry);
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        vrdpGeometry(hEntry);
+
+        return VINF_SUCCESS;
+    }
+
+    virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = CrFbDisplayBase::RegionsChanged(pFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return vrdpRegionsAll(pFb);
+    }
+
+    virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+    {
+        int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        syncPos();
+
+        rc = vrdpSyncEntryAll(pFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return vrdpRegionsAll(pFb);
+    }
+
+protected:
+    void syncPos()
+    {
+        const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
+        mPos.x = pScreenInfo->i32OriginX;
+        mPos.y = pScreenInfo->i32OriginY;
+    }
+
+    virtual int fbCleanup()
+    {
+        int rc = fbCleanupRemoveAllEntries();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return CrFbDisplayBase::fbCleanup();
+    }
+
+    virtual int fbSync()
+    {
+        syncPos();
+
+        int rc = fbSynchAddAllEntries();
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("err"));
+            return rc;
+        }
+
+        return CrFbDisplayBase::fbSync();
+    }
+protected:
+    void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+        cr_server.outputRedirect.CROREnd(pVrdp);
+    }
+
+    void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+    	void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+
+        cr_server.outputRedirect.CRORGeometry(pVrdp,
+        										mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
+        										mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
+        									   CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
+                                               CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
+    }
+
+    int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+    	const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+        uint32_t cRects;
+        const RTRECT *pRects;
+
+        int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
+            return rc;
+        }
+
+        cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
+        return VINF_SUCCESS;
+    }
+
+    int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+        const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+    	CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+    	const CR_BLITTER_IMG *pImg;
+    	CrTdBltDataInvalidateNe(pTex);
+    	int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
+    	if (!RT_SUCCESS(rc))
+    	{
+    		WARN(("CrTdBltDataAcquire failed rc %d", rc));
+    		return rc;
+    	}
+
+        cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
+        CrTdBltDataRelease(pTex);
+        return VINF_SUCCESS;
+    }
+
+    int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
+    {
+    	const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
+        VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+        CrVrScrCompositorConstIterInit(pCompositor, &Iter);
+        const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+        while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+        {
+        	HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+        	vrdpRegions(pFb, hEntry);
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        vrdpGeometry(hEntry);
+
+        return vrdpRegions(pFb, hEntry);;
+    }
+
+    int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
+    {
+        const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
+        VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+        CrVrScrCompositorConstIterInit(pCompositor, &Iter);
+        const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+        while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+        {
+            HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+            int rc = vrdpSynchEntry(pFb, hEntry);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("vrdpSynchEntry failed rc %d", rc));
+                return rc;
+            }
+        }
+
+        return VINF_SUCCESS;
+    }
+
+    int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+    	void *pVrdp;
+
+        /* Query supported formats. */
+        uint32_t cbFormats = 4096;
+        char *pachFormats = (char *)crAlloc(cbFormats);
+
+        if (!pachFormats)
+        {
+            WARN(("crAlloc failed"));
+            return VERR_NO_MEMORY;
+        }
+
+        int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
+                                                                  0 /* H3DOR_PROP_FORMATS */, // @todo from a header
+                                                                  pachFormats, cbFormats, &cbFormats);
+        if (RT_SUCCESS(rc))
+        {
+            if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
+            {
+                cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
+                		        &pVrdp,
+                                "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
+
+                if (pVrdp)
+                {
+                    rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
+                    if (RT_SUCCESS(rc))
+                    {
+                    	vrdpGeometry(hEntry);
+                    	vrdpRegions(hFb, hEntry);
+                    	//vrdpFrame(hEntry);
+                        return VINF_SUCCESS;
+                    }
+                    else
+                    	WARN(("CrFbDDataEntryPut failed rc %d", rc));
+
+                    cr_server.outputRedirect.CROREnd(pVrdp);
+                }
+                else
+                {
+                    WARN(("CRORBegin failed"));
+                    rc = VERR_GENERAL_FAILURE;
+                }
+            }
+        }
+        else
+            WARN(("CRORContextProperty failed rc %d", rc));
+
+        crFree(pachFormats);
+
+        return rc;
+    }
+private:
+    RTPOINT mPos;
+};
+
+CrFbDisplayBase::~CrFbDisplayBase()
+{
+    Assert(!mcUpdates);
+
+    if (mpContainer)
+        mpContainer->remove(this);
+}
+
+
+#if 0
+
+
+
+
+
+void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
+{
+    crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
+}
+
+void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
+{
+    crDebug("Dumping rects (%d)", cRects);
+    for (uint32_t i = 0; i < cRects; ++i)
+    {
+        crDbgDumpRect(i, &paRects[i]);
+    }
+    crDebug("End Dumping rects (%d)", cRects);
+}
+
+int crServerDisplaySaveState(PSSMHANDLE pSSM)
+{
+    int rc;
+    int cDisplays = 0, i;
+    for (i = 0; i < cr_server.screenCount; ++i)
+    {
+        if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
+            ++cDisplays;
+    }
+
+    rc = SSMR3PutS32(pSSM, cDisplays);
+    AssertRCReturn(rc, rc);
+
+    if (!cDisplays)
+        return VINF_SUCCESS;
+
+    rc = SSMR3PutS32(pSSM, cr_server.screenCount);
+    AssertRCReturn(rc, rc);
+
+    for (i = 0; i < cr_server.screenCount; ++i)
+    {
+        rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
+        AssertRCReturn(rc, rc);
+
+        rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
+        AssertRCReturn(rc, rc);
+
+        rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
+        AssertRCReturn(rc, rc);
+
+        rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
+        AssertRCReturn(rc, rc);
+    }
+
+    for (i = 0; i < cr_server.screenCount; ++i)
+    {
+        if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
+        {
+            rc = SSMR3PutS32(pSSM, i);
+            AssertRCReturn(rc, rc);
+
+            rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
+            AssertRCReturn(rc, rc);
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
+{
+
+}
+#endif
+
+class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
+{
+public:
+    virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+    {
+        entryDataChanged(pFb, hReplacedEntry);
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        entryDataChanged(pFb, hEntry);
+        return VINF_SUCCESS;
+    }
+
+    virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+        entryDataChanged(pFb, hEntry);
+        return VINF_SUCCESS;
+    }
+protected:
+    virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+    {
+
+    }
+};
+
+int CrPMgrInit()
+{
+    int rc = VINF_SUCCESS;
+    memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
+    g_CrPresenter.pFbTexMap = crAllocHashtable();
+    if (g_CrPresenter.pFbTexMap)
+    {
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+        rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
+                                0, /* size_t cbAlignment */
+                                UINT32_MAX, /* uint32_t cMaxObjects */
+                                NULL, /* PFNMEMCACHECTOR pfnCtor*/
+                                NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+                                NULL, /* void *pvUser*/
+                                0 /* uint32_t fFlags*/
+                                );
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
+                                        0, /* size_t cbAlignment */
+                                        UINT32_MAX, /* uint32_t cMaxObjects */
+                                        NULL, /* PFNMEMCACHECTOR pfnCtor*/
+                                        NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+                                        NULL, /* void *pvUser*/
+                                        0 /* uint32_t fFlags*/
+                                        );
+            if (RT_SUCCESS(rc))
+            {
+                rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
+                                            0, /* size_t cbAlignment */
+                                            UINT32_MAX, /* uint32_t cMaxObjects */
+                                            NULL, /* PFNMEMCACHECTOR pfnCtor*/
+                                            NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+                                            NULL, /* void *pvUser*/
+                                            0 /* uint32_t fFlags*/
+                                            );
+                if (RT_SUCCESS(rc))
+                {
+#endif
+                    rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
+                    if (RT_SUCCESS(rc))
+                        return VINF_SUCCESS;
+                    else
+                        WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+                    RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
+                }
+                else
+                    WARN(("RTMemCacheCreate failed rc %d", rc));
+
+                RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
+            }
+            else
+                WARN(("RTMemCacheCreate failed rc %d", rc));
+
+            RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
+        }
+        else
+            WARN(("RTMemCacheCreate failed rc %d", rc));
+#endif
+    }
+    else
     {
-        pInfo = crDemEntryInfoAlloc();
-        CRASSERT(pInfo);
-        crHashtableAdd(pMap->pTexIdToDemInfoMap, pTobj->id, pInfo);
-        pInfo->cEntries = 0;
-        pInfo->pTobj = pTobj;
+        WARN(("crAllocHashtable failed"));
+        rc = VERR_NO_MEMORY;
     }
+    return rc;
+}
+
+void CrPMgrTerm()
+{
+    crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
 
-    ++pInfo->cEntries;
-    pDemEntry->pInfo = pInfo;
-    pDemEntry->pMap = pMap;
-    RTListInit(&pDemEntry->Node);
+    HCR_FRAMEBUFFER hFb;
 
-    /* just use main context info's context to hold the texture reference */
-    CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
+    for (hFb = CrPMgrFbGetFirstInitialized();
+            hFb;
+            hFb = CrPMgrFbGetNextInitialized(hFb))
+    {
+        uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+        CrFbDisplaySet(hFb, NULL);
+        CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+
+        if (pInfo->pDpComposite)
+            delete pInfo->pDpComposite;
+
+        Assert(!pInfo->pDpWin);
+        Assert(!pInfo->pDpWinRootVr);
+        Assert(!pInfo->pDpVrdp);
+
+        CrFbTerm(hFb);
+    }
+
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+    RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
+    RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
+    RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
+#endif
+    crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
+
+    if (g_CrPresenter.pvTmpBuf)
+        RTMemFree(g_CrPresenter.pvTmpBuf);
+
+    if (g_CrPresenter.pvTmpBuf2)
+        RTMemFree(g_CrPresenter.pvTmpBuf2);
+
+    memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
+{
+    if (idScreen >= CR_MAX_GUEST_MONITORS)
+    {
+        WARN(("invalid idScreen %d", idScreen));
+        return NULL;
+    }
+
+    if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
+    {
+        CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
+        CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
+    }
+    else
+        Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
+
+    return &g_CrPresenter.aFramebuffers[idScreen];
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
+{
+    if (idScreen >= CR_MAX_GUEST_MONITORS)
+    {
+        WARN(("invalid idScreen %d", idScreen));
+        return NULL;
+    }
+
+    if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
+    {
+        return NULL;
+    }
+    else
+        Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
+
+    return &g_CrPresenter.aFramebuffers[idScreen];
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
+{
+    HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
+
+    if(hFb && CrFbIsEnabled(hFb))
+        return hFb;
+
+    return NULL;
+}
+
+static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
+{
+    for (;i < cr_server.screenCount; ++i)
+    {
+        HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
+        if (hFb)
+            return hFb;
+    }
+
+    return NULL;
+}
+
+static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
+{
+    for (;i < cr_server.screenCount; ++i)
+    {
+        HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
+        if (hFb)
+            return hFb;
+    }
+
+    return NULL;
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
+{
+    HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
+//    if (!hFb)
+//        WARN(("no enabled framebuffer found"));
+    return hFb;
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
+{
+    return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
+{
+    HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
+//    if (!hFb)
+//        WARN(("no initialized framebuffer found"));
+    return hFb;
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
+{
+    return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
+}
+
+static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
+{
+    u32Mode = CR_PMGR_MODE_ALL & u32Mode;
+    if (CR_PMGR_MODE_ROOTVR & u32Mode)
+        u32Mode &= ~CR_PMGR_MODE_WINDOW;
+    return u32Mode;
+}
+
+int CrPMgrScreenChanged(uint32_t idScreen)
+{
+    if (idScreen >= CR_MAX_GUEST_MONITORS)
+    {
+        WARN(("invalid idScreen %d", idScreen));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+    if (pInfo->pDpWin)
+    {
+        HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
+        if (CrFbIsUpdating(hFb))
+        {
+            WARN(("trying to update viewport while framebuffer is being updated"));
+            return VERR_INVALID_STATE;
+        }
+
+        int rc = pInfo->pDpWin->UpdateBegin(hFb);
+        if (RT_SUCCESS(rc))
+        {
+            pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
+
+            pInfo->pDpWin->UpdateEnd(hFb);
+        }
+        else
+            WARN(("UpdateBegin failed %d", rc));
+    }
+
+    return VINF_SUCCESS;
+}
+
+int CrPMgrViewportUpdate(uint32_t idScreen)
+{
+    if (idScreen >= CR_MAX_GUEST_MONITORS)
+    {
+        WARN(("invalid idScreen %d", idScreen));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+    if (pInfo->pDpWin)
+    {
+        HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
+        if (CrFbIsUpdating(hFb))
+        {
+            WARN(("trying to update viewport while framebuffer is being updated"));
+            return VERR_INVALID_STATE;
+        }
+
+        int rc = pInfo->pDpWin->UpdateBegin(hFb);
+        if (RT_SUCCESS(rc))
+        {
+            pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
+            pInfo->pDpWin->UpdateEnd(hFb);
+        }
+        else
+            WARN(("UpdateBegin failed %d", rc));
+    }
+
+    return VINF_SUCCESS;
+}
+
+int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
+{
+    uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+
+    CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+    u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
+    u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
+    u32ModeRemove &= pInfo->u32Mode;
+    u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
+    uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
+    uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
+    if (u32Tmp != u32ModeResulting)
+    {
+        u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
+        u32ModeRemove |= (~u32Tmp & u32ModeResulting);
+        u32ModeResulting = u32Tmp;
+        Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
+    }
+    if (!u32ModeRemove && !u32ModeAdd)
+        return VINF_SUCCESS;
+
+    if (!pInfo->pDpComposite)
+    {
+        pInfo->pDpComposite = new CrFbDisplayComposite();
+        pInfo->pDpComposite->setFramebuffer(hFb);
+    }
+
+    CrFbWindow * pOldWin = NULL;
+
+    if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
+    {
+        CRASSERT(pInfo->pDpWinRootVr);
+        CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
+        pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
+        pOldWin = pInfo->pDpWinRootVr->windowDetach();
+        CRASSERT(pOldWin);
+        delete pInfo->pDpWinRootVr;
+        pInfo->pDpWinRootVr = NULL;
+        pInfo->pDpWin = NULL;
+    }
+    else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
+    {
+        CRASSERT(!pInfo->pDpWinRootVr);
+        CRASSERT(pInfo->pDpWin);
+        pInfo->pDpComposite->remove(pInfo->pDpWin);
+        pOldWin = pInfo->pDpWin->windowDetach();
+        CRASSERT(pOldWin);
+        delete pInfo->pDpWin;
+        pInfo->pDpWin = NULL;
+    }
+
+    if (u32ModeRemove & CR_PMGR_MODE_VRDP)
+    {
+        CRASSERT(pInfo->pDpVrdp);
+        if (pInfo->pDpComposite)
+            pInfo->pDpComposite->remove(pInfo->pDpVrdp);
+        else
+            CrFbDisplaySet(hFb, NULL);
+
+        delete pInfo->pDpVrdp;
+        pInfo->pDpVrdp = NULL;
+    }
+
+    CrFbDisplayBase *pDpToSet = NULL;
+
+    if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
+    {
+        CRASSERT(!pInfo->pDpWin);
+        CRASSERT(!pInfo->pDpWinRootVr);
+
+        if (!pOldWin)
+            pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
+
+        pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
+        pOldWin = NULL;
+        pInfo->pDpWin = pInfo->pDpWinRootVr;
+        pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
+    }
+    else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
+    {
+        CRASSERT(!pInfo->pDpWin);
+        CRASSERT(!pInfo->pDpWinRootVr);
+
+        if (!pOldWin)
+            pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
+
+        pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
+        pOldWin = NULL;
+        pInfo->pDpComposite->add(pInfo->pDpWin);
+    }
+
+    if (u32ModeAdd & CR_PMGR_MODE_VRDP)
+    {
+        CRASSERT(!pInfo->pDpVrdp);
+        pInfo->pDpVrdp = new CrFbDisplayVrdp();
+        pInfo->pDpComposite->add(pInfo->pDpVrdp);
+    }
+
+    if (pInfo->pDpComposite->getDisplayCount() > 1)
+    {
+        ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
+        if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
+            CrFbDisplaySet(hFb, pInfo->pDpComposite);
+    }
+    else
+    {
+        ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
+        ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
+        if (pCur != pFirst)
+            CrFbDisplaySet(hFb, pFirst);
+    }
+
+    if (pOldWin)
+        delete pOldWin;
+
+    pInfo->u32Mode = u32ModeResulting;
+
+    return VINF_SUCCESS;
+}
+
+static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
+{
+    g_CrPresenter.u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
+
+    for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+            hFb;
+            hFb = CrPMgrFbGetNextEnabled(hFb))
+    {
+        CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
+    }
+
+    return VINF_SUCCESS;
+}
+
+int CrPMgrModeVrdp(bool fEnable)
+{
+    uint32_t u32ModeAdd, u32ModeRemove;
+    if (fEnable)
+    {
+        u32ModeAdd = CR_PMGR_MODE_VRDP;
+        u32ModeRemove = 0;
+    }
+    else
+    {
+        u32ModeAdd = 0;
+        u32ModeRemove = CR_PMGR_MODE_VRDP;
+    }
+    return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
+}
+
+int CrPMgrModeRootVr(bool fEnable)
+{
+    uint32_t u32ModeAdd, u32ModeRemove;
+    if (fEnable)
+    {
+        u32ModeAdd = CR_PMGR_MODE_ROOTVR;
+        u32ModeRemove = CR_PMGR_MODE_WINDOW;
+    }
+    else
+    {
+        u32ModeAdd = CR_PMGR_MODE_WINDOW;
+        u32ModeRemove = CR_PMGR_MODE_ROOTVR;
+    }
+
+    return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
+}
+
+int CrPMgrModeWinVisible(bool fEnable)
+{
+    if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
+        return VINF_SUCCESS;
+
+    g_CrPresenter.fWindowsForceHidden = !fEnable;
+
+    for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+            hFb;
+            hFb = CrPMgrFbGetNextEnabled(hFb))
+    {
+        uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+
+        CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+
+        if (pInfo->pDpWin)
+            pInfo->pDpWin->winVisibilityChanged();
+    }
+
+    return VINF_SUCCESS;
+}
+
+int CrPMgrRootVrUpdate()
+{
+    for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+            hFb;
+            hFb = CrPMgrFbGetNextEnabled(hFb))
+    {
+        uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+        CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+        int rc = CrFbUpdateBegin(hFb);
+        if (RT_SUCCESS(rc))
+        {
+            pInfo->pDpWinRootVr->RegionsChanged(hFb);
+            CrFbUpdateEnd(hFb);
+        }
+        else
+            WARN(("CrFbUpdateBegin failed %d", rc));
+    }
+
+    return VINF_SUCCESS;
+}
+
+/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
+int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
+{
+    CrFBmInit(pMap);
+    for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+            hFb;
+            hFb = CrPMgrFbGetNextEnabled(hFb))
+    {
+        int rc = CrFbUpdateBegin(hFb);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("UpdateBegin failed, rc %d", rc));
+            for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
+                        hFb != hTmpFb;
+                        hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
+            {
+                CrFbUpdateEnd(hTmpFb);
+                CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
+            }
+            return rc;
+        }
+
+        CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
+    }
+
+    return VINF_SUCCESS;
+}
+
+/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
+void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
+{
+    for (uint32_t i = 0; i < cr_server.screenCount; ++i)
+    {
+        if (!CrFBmIsSet(pMap, i))
+            continue;
+
+        HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
+        CRASSERT(hFb);
+        CrFbUpdateEnd(hFb);
+    }
+}
+
+/*client should notify the manager about the framebuffer resize via this function */
+int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
+{
+    int rc = VINF_SUCCESS;
+    if (CrFbIsEnabled(hFb))
+    {
+        rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrPMgrModeModify failed rc %d", rc));
+            return rc;
+        }
+    }
+    else
+    {
+        rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
+        if (!RT_SUCCESS(rc))
+        {
+            WARN(("CrPMgrModeModify failed rc %d", rc));
+            return rc;
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
+{
+    const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
+    CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+    CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+    int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
+    AssertRCReturn(rc, rc);
+    uint32_t u32 = 0;
+
+    u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
+    rc = SSMR3PutU32(pSSM, u32);
+    AssertRCReturn(rc, rc);
+
+    const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
+
+    rc = SSMR3PutS32(pSSM, pRect->xLeft);
+    AssertRCReturn(rc, rc);
+    rc = SSMR3PutS32(pSSM, pRect->yTop);
+    AssertRCReturn(rc, rc);
+#if 0
+    rc = SSMR3PutS32(pSSM, pRect->xRight);
+    AssertRCReturn(rc, rc);
+    rc = SSMR3PutS32(pSSM, pRect->yBottom);
+    AssertRCReturn(rc, rc);
+#endif
 
-    return &pDemEntry->Entry;
-}
+    rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
+    AssertRCReturn(rc, rc);
 
-PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen)
-{
-    if (idScreen >= CR_MAX_GUEST_MONITORS)
-    {
-        crWarning("invalid idScreen %d", idScreen);
-        return NULL;
-    }
+    rc = SSMR3PutU32(pSSM, u32);
+    AssertRCReturn(rc, rc);
 
-    if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
+    if (u32)
     {
-        Assert(cr_server.aDispplays[idScreen].Mural.screenId == idScreen);
-        return &cr_server.aDispplays[idScreen];
+        rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
+        AssertRCReturn(rc, rc);
     }
-    return NULL;
+    return rc;
 }
 
-static PCR_DISPLAY crServerDisplayGet(uint32_t idScreen)
+int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
 {
-    if (idScreen >= CR_MAX_GUEST_MONITORS)
+    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+    CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
+    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+    uint32_t u32 = 0;
+    while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
     {
-        crWarning("invalid idScreen %d", idScreen);
-        return NULL;
+        CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+        CRASSERT(pTexData);
+        CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+        if (pFbTex->pTobj)
+            ++u32;
     }
 
-    if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
+    int rc = SSMR3PutU32(pSSM, u32);
+    AssertRCReturn(rc, rc);
+
+    CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
+
+    while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
     {
-        Assert(cr_server.aDispplays[idScreen].Mural.screenId == idScreen);
-        return &cr_server.aDispplays[idScreen];
+        CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+        CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+        if (pFbTex->pTobj)
+        {
+            HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+            rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
+            AssertRCReturn(rc, rc);
+        }
     }
 
-     int rc = CrDpInit(&cr_server.aDispplays[idScreen]);
-     if (RT_SUCCESS(rc))
-     {
-         CrDpResize(&cr_server.aDispplays[idScreen],
-                 cr_server.screen[idScreen].x, cr_server.screen[idScreen].y,
-                 cr_server.screen[idScreen].w, cr_server.screen[idScreen].h);
-         ASMBitSet(cr_server.DisplaysInitMap, idScreen);
-         return &cr_server.aDispplays[idScreen];
-     }
-     else
-     {
-         crWarning("CrDpInit failed for screen %d", idScreen);
-     }
-
-    return NULL;
+    return VINF_SUCCESS;
 }
 
-int crServerDisplaySaveState(PSSMHANDLE pSSM)
+int CrPMgrSaveState(PSSMHANDLE pSSM)
 {
     int rc;
     int cDisplays = 0, i;
     for (i = 0; i < cr_server.screenCount; ++i)
     {
-        if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
+        if (CrPMgrFbGetEnabled(i))
             ++cDisplays;
     }
 
@@ -706,27 +4076,41 @@ int crServerDisplaySaveState(PSSMHANDLE pSSM)
 
     for (i = 0; i < cr_server.screenCount; ++i)
     {
-        rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
-        AssertRCReturn(rc, rc);
+        CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
+        if (hFb)
+        {
+            Assert(hFb->ScreenInfo.u32ViewIndex == i);
+            rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
+            AssertRCReturn(rc, rc);
 
-        rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
-        AssertRCReturn(rc, rc);
+            rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
+            AssertRCReturn(rc, rc);
 
-        rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
-        AssertRCReturn(rc, rc);
+            rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
+            AssertRCReturn(rc, rc);
 
-        rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
-        AssertRCReturn(rc, rc);
-    }
+            rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
+            AssertRCReturn(rc, rc);
 
-    for (i = 0; i < cr_server.screenCount; ++i)
-    {
-        if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
-        {
-            rc = SSMR3PutS32(pSSM, i);
+            rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
             AssertRCReturn(rc, rc);
 
-            rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
+            rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
+            AssertRCReturn(rc, rc);
+
+            rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
+            AssertRCReturn(rc, rc);
+
+            rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
+            AssertRCReturn(rc, rc);
+
+            rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
+            AssertRCReturn(rc, rc);
+
+            rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
+            AssertRCReturn(rc, rc);
+
+            rc = CrFbSaveState(hFb, pSSM);
             AssertRCReturn(rc, rc);
         }
     }
@@ -734,7 +4118,89 @@ int crServerDisplaySaveState(PSSMHANDLE pSSM)
     return VINF_SUCCESS;
 }
 
-int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
+int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
+{
+    uint32_t texture;
+    int  rc = SSMR3GetU32(pSSM, &texture);
+    AssertRCReturn(rc, rc);
+
+    uint32_t fFlags;
+    rc = SSMR3GetU32(pSSM, &fFlags);
+    AssertRCReturn(rc, rc);
+
+
+    HCR_FRAMEBUFFER_ENTRY hEntry;
+
+    rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("CrFbEntryCreateForTexId Failed"));
+        return rc;
+    }
+
+    Assert(hEntry);
+
+    const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
+    CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+    CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+
+    RTPOINT Point;
+    rc = SSMR3GetS32(pSSM, &Point.x);
+    AssertRCReturn(rc, rc);
+
+    rc = SSMR3GetS32(pSSM, &Point.y);
+    AssertRCReturn(rc, rc);
+
+    uint32_t cRects;
+    rc = SSMR3GetU32(pSSM, &cRects);
+    AssertRCReturn(rc, rc);
+
+    RTRECT * pRects = NULL;
+    if (cRects)
+    {
+        pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
+        AssertReturn(pRects, VERR_NO_MEMORY);
+
+        rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
+        AssertRCReturn(rc, rc);
+    }
+
+    rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
+    AssertRCReturn(rc, rc);
+
+    if (pRects)
+        crFree(pRects);
+
+    CrFbEntryRelease(pFb, hEntry);
+
+    return VINF_SUCCESS;
+}
+
+int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
+{
+    uint32_t u32 = 0;
+    int rc = SSMR3GetU32(pSSM, &u32);
+    AssertRCReturn(rc, rc);
+
+    if (!u32)
+        return VINF_SUCCESS;
+
+    rc = CrFbUpdateBegin(pFb);
+    AssertRCReturn(rc, rc);
+
+    for (uint32_t i = 0; i < u32; ++i)
+    {
+        rc = CrFbEntryLoadState(pFb, pSSM, version);
+        AssertRCReturn(rc, rc);
+
+    }
+
+    CrFbUpdateEnd(pFb);
+
+    return VINF_SUCCESS;
+}
+
+int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
 {
     int rc;
     int cDisplays, screenCount, i;
@@ -750,30 +4216,26 @@ int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
 
     CRASSERT(screenCount == cr_server.screenCount);
 
-    crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
+    CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
 
-    for (i = 0; i < cr_server.screenCount; ++i)
+    if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
     {
-        int32_t    x, y;
-        uint32_t   w, h;
-        rc = SSMR3GetS32(pSSM, &x);
-        AssertRCReturn(rc, rc);
-
-        rc = SSMR3GetS32(pSSM, &y);
-        AssertRCReturn(rc, rc);
+        for (i = 0; i < cr_server.screenCount; ++i)
+        {
+            rc = SSMR3GetS32(pSSM, &screen[i].x);
+            AssertRCReturn(rc, rc);
 
-        rc = SSMR3GetU32(pSSM, &w);
-        AssertRCReturn(rc, rc);
+            rc = SSMR3GetS32(pSSM, &screen[i].y);
+            AssertRCReturn(rc, rc);
 
-        rc = SSMR3GetU32(pSSM, &h);
-        AssertRCReturn(rc, rc);
+            rc = SSMR3GetU32(pSSM, &screen[i].w);
+            AssertRCReturn(rc, rc);
 
-        rc = crVBoxServerMapScreen(i, x, y, w, h, cr_server.screen[i].winID);
-        AssertRCReturn(rc, rc);
+            rc = SSMR3GetU32(pSSM, &screen[i].h);
+            AssertRCReturn(rc, rc);
+        }
     }
 
-    crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
-
     for (i = 0; i < cDisplays; ++i)
     {
         int iScreen;
@@ -781,204 +4243,298 @@ int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
         rc = SSMR3GetS32(pSSM, &iScreen);
         AssertRCReturn(rc, rc);
 
-        PCR_DISPLAY pDisplay = crServerDisplayGet((uint32_t)iScreen);
-        if (!pDisplay)
+        CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
+        Assert(pFb);
+
+        rc = CrFbUpdateBegin(pFb);
+        if (!RT_SUCCESS(rc))
         {
-            crWarning("crServerDisplayGet failed");
-            return VERR_GENERAL_FAILURE;
+            WARN(("CrFbUpdateBegin failed %d", rc));
+            return rc;
         }
 
-        rc = CrDpLoadState(pDisplay, pSSM, u32Version);
-        AssertRCReturn(rc, rc);
-    }
+        VBVAINFOSCREEN Screen;
+        void *pvVRAM;
 
-    return VINF_SUCCESS;
-}
+        Screen.u32ViewIndex = iScreen;
 
-void crServerDisplayTermAll()
-{
-    int i;
-    for (i = 0; i < cr_server.screenCount; ++i)
-    {
-        if (ASMBitTest(cr_server.DisplaysInitMap, i))
+        if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
         {
-            CrDpTerm(&cr_server.aDispplays[i]);
-            ASMBitClear(cr_server.DisplaysInitMap, i);
+            memset(&Screen, 0, sizeof (Screen));
+            Screen.u32LineSize = 4 * screen[iScreen].w;
+            Screen.u32Width = screen[iScreen].w;
+            Screen.u32Height = screen[iScreen].h;
+            Screen.u16BitsPerPixel = 4;
+            Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
+
+            pvVRAM = g_pvVRamBase;
         }
-    }
-}
-
-void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData)
-{
-    if (idPBO)
-    {
-        cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
-        if (pCurCtx)
-            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
         else
-            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
-    }
-    else
-    {
-        crFree(pvData);
-        if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
-            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
-    }
-}
+        {
+            rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
+            AssertRCReturn(rc, rc);
 
-void CrHlpPutTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLenum enmFormat, void *pvData)
-{
-    CRASSERT(pTexture->hwid);
-    cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
+            rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
+            AssertRCReturn(rc, rc);
 
-    if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
-    {
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
-    }
+            rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
+            AssertRCReturn(rc, rc);
 
-    /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
-    cr_server.head_spu->dispatch_table.TexSubImage2D(GL_TEXTURE_2D,  0 /* level*/,  0 /*xoffset*/,  0 /*yoffset*/,  pTexture->width, pTexture->height, enmFormat, GL_UNSIGNED_BYTE, pvData);
+            rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
+            AssertRCReturn(rc, rc);
 
-    /*restore gl state*/
-    if (pCurCtx)
-    {
-        CRTextureObj *pTObj;
-        CRTextureLevel *pTImg;
-        crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
+            rc = SSMR3GetU32(pSSM, &Screen.u32Width);
+            AssertRCReturn(rc, rc);
 
-        GLuint uid = pTObj->hwid;
-        cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
-    }
-    else
-    {
-        cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
-    }
+            rc = SSMR3GetU32(pSSM, &Screen.u32Height);
+            AssertRCReturn(rc, rc);
 
-    if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pCurCtx->bufferobject.unpackBuffer->hwid);
-}
+            rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
+            AssertRCReturn(rc, rc);
 
-void* CrHlpGetTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLuint idPBO, GLenum enmFormat)
-{
-    void *pvData = NULL;
-    cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
+            rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
+            AssertRCReturn(rc, rc);
 
-    if (idPBO)
-    {
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, idPBO);
-    }
-    else
-    {
-        if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
-        {
-            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+            uint32_t offVram = 0;
+            rc = SSMR3GetU32(pSSM, &offVram);
+            AssertRCReturn(rc, rc);
+
+            pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
         }
 
-        pvData = crAlloc(4*pTexture->width*pTexture->height);
-        if (!pvData)
+        crVBoxServerMuralFbResizeBegin(pFb);
+
+        rc = CrFbResize(pFb, &Screen, pvVRAM);
+        if (!RT_SUCCESS(rc))
         {
-            crWarning("Out of memory in CrHlpGetTexImage");
-            return NULL;
+            WARN(("CrFbResize failed %d", rc));
+            return rc;
         }
-    }
 
-    /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
-    cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
+        rc = CrFbLoadState(pFb, pSSM, version);
+        AssertRCReturn(rc, rc);
 
-    /*restore gl state*/
-    if (pCurCtx)
-    {
-        CRTextureObj *pTObj;
-        CRTextureLevel *pTImg;
-        crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
+        crVBoxServerMuralFbResizeEnd(pFb);
 
-        GLuint uid = pTObj->hwid;
-        cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
-    }
-    else
-    {
-        cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
-    }
+        CrFbUpdateEnd(pFb);
 
-    if (idPBO)
-    {
-        pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
-        if (!pvData)
-        {
-            crWarning("Failed to MapBuffer in CrHlpGetTexImage");
-            return NULL;
-        }
+        CrPMgrNotifyResize(pFb);
     }
 
-    CRASSERT(pvData);
-    return pvData;
+    return VINF_SUCCESS;
 }
 
+
 void SERVER_DISPATCH_APIENTRY
 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
 {
     uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
     if (idScreen >= CR_MAX_GUEST_MONITORS)
     {
-        crWarning("Invalid guest screen");
+        WARN(("Invalid guest screen"));
         return;
     }
 
-    PCR_DISPLAY pDisplay;
-    PCR_DISPLAY_ENTRY pEntry = NULL;
+    HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
+    if (!hFb)
+    {
+        WARN(("request to present on disabled framebuffer, ignore"));
+        return;
+    }
 
+    HCR_FRAMEBUFFER_ENTRY hEntry;
+    int rc;
     if (texture)
     {
-        pEntry = CrDemEntryAcquire(&cr_server.PresentTexturepMap, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS);
-        if (!pEntry)
+        rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
+        if (!RT_SUCCESS(rc))
         {
-            crWarning("CrDemEntryAcquire Failed");
+            LOG(("CrFbEntryCreateForTexId Failed"));
             return;
         }
 
-        pDisplay = crServerDisplayGet(idScreen);
-        if (!pDisplay)
+        Assert(hEntry);
+
+#if 0
+        if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
         {
-            crWarning("crServerDisplayGet Failed");
-            CrDemEntryRelease(pEntry);
-            return;
+            CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
         }
+#endif
     }
     else
+        hEntry = NULL;
+
+    rc = CrFbUpdateBegin(hFb);
+    if (RT_SUCCESS(rc))
     {
-        pDisplay = crServerDisplayGetInitialized(idScreen);
-        if (!pDisplay)
+        if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
         {
-            /* no display initialized, and nothing to present */
-            return;
+            RTPOINT Point = {xPos, yPos};
+            rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
+        }
+        else
+        {
+            CrFbRegionsClear(hFb);
         }
-    }
 
-    if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
+        CrFbUpdateEnd(hFb);
+    }
+    else
     {
-        CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
+        WARN(("CrFbUpdateBegin Failed"));
     }
 
-    CrDpEnter(pDisplay);
+    if (hEntry)
+        CrFbEntryRelease(hFb, hEntry);
+}
+
+DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
+{
+    pRect->xLeft = pVbvaRect->xLeft;
+    pRect->yTop = pVbvaRect->yTop;
+    pRect->xRight = pVbvaRect->xRight;
+    pRect->yBottom = pVbvaRect->yBottom;
+}
 
-    if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
+DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
+{
+    uint32_t i = 0;
+    for (; i < cRects; ++i)
     {
-        RTPOINT Point = {xPos, yPos};
-        int rc = CrDpEntryRegionsAdd(pDisplay, pEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, &cr_server.PresentTexturepMap);
-        if (!RT_SUCCESS(rc))
+        crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
+    }
+}
+
+int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
+{
+    uint8_t u8Flags = pCmd->u8Flags;
+    if (u8Flags & (VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY | VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY))
+    {
+        VBOXCMDVBVA_BLT_PRIMARY *pBlt = (VBOXCMDVBVA_BLT_PRIMARY*)pCmd;
+        uint8_t u8PrimaryID = pBlt->Hdr.u8PrimaryID;
+        HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
+        if (!hFb)
+        {
+            WARN(("request to present on disabled framebuffer, ignore"));
+            pCmd->i8Result = -1;
+            return VINF_SUCCESS;
+        }
+
+        const VBOXCMDVBVA_RECT *pPRects = pBlt->aRects;
+        uint32_t cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
+        RTRECT *pRects;
+        if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
+        {
+            if (g_CrPresenter.pvTmpBuf)
+                RTMemFree(g_CrPresenter.pvTmpBuf);
+
+            g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
+            g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
+            if (!g_CrPresenter.pvTmpBuf)
+            {
+                WARN(("RTMemAlloc failed!"));
+                g_CrPresenter.cbTmpBuf = 0;
+                pCmd->i8Result = -1;
+                return VINF_SUCCESS;
+            }
+        }
+
+        pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
+
+        crVBoxPRectUnpacks(pPRects, pRects, cRects);
+
+        Assert(!((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT)));
+
+        if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY)
+        {
+            if (!(u8Flags & VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY))
+            {
+                /* blit to primary from non-primary */
+                uint32_t texId;
+                if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID)
+                {
+                    /* TexPresent */
+                    texId = pBlt->alloc.id;
+                }
+                else
+                {
+                    VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.offVRAM;
+                    const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+                    uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height;
+                    if (offVRAM >= g_cbVRam
+                            || offVRAM + cbScreen >= g_cbVRam)
+                    {
+                        WARN(("invalid param"));
+                        pCmd->i8Result = -1;
+                        return VINF_SUCCESS;
+                    }
+
+                    uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
+                    texId = 0;
+                    /*todo: notify VGA device to perform updates */
+                }
+
+                crServerDispatchVBoxTexPresent(texId, u8PrimaryID, pBlt->Pos.x, pBlt->Pos.y, cRects, (const GLint*)pRects);
+            }
+            else
+            {
+                /* blit from one primary to another primary, wow */
+                WARN(("not implemented"));
+                pCmd->i8Result = -1;
+                return VINF_SUCCESS;
+            }
+        }
+        else
         {
-            crWarning("CrDpEntryRegionsAdd Failed rc %d", rc);
-            /* no need to release anything, as CrDpEntryRegionsAdd would do everything for us as needed */
-//            if (pEntry)
-//                CrDemEntryRelease(pEntry);
+            Assert(u8Flags & VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY);
+            /* blit from primary to non-primary */
+            if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID)
+            {
+                uint32_t texId = pBlt->alloc.id;
+                WARN(("not implemented"));
+                pCmd->i8Result = -1;
+                return VINF_SUCCESS;
+            }
+            else
+            {
+                VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.offVRAM;
+                const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+                uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height;
+                if (offVRAM >= g_cbVRam
+                        || offVRAM + cbScreen >= g_cbVRam)
+                {
+                    WARN(("invalid param"));
+                    pCmd->i8Result = -1;
+                    return VINF_SUCCESS;
+                }
+
+                uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
+
+                RTRECT Rect;
+                Rect.xLeft = pBlt->Pos.x;
+                Rect.yTop = pBlt->Pos.y;
+                Rect.xRight = Rect.xLeft + pScreen->u32Width;
+                Rect.yBottom = Rect.yTop + pScreen->u32Height;
+                CR_BLITTER_IMG Img;
+                crFbImgFromScreenVram(pScreen, pu8Buf, &Img);
+                int rc = CrFbBltGetContents(hFb, &Rect, cRects, pRects, &Img);
+                if (!RT_SUCCESS(rc))
+                {
+                    WARN(("CrFbBltGetContents failed %d", rc));
+                    pCmd->i8Result = -1;
+                    return VINF_SUCCESS;
+                }
+            }
         }
     }
     else
     {
-        if (pEntry)
-            CrDemEntryRelease(pEntry);
-        CrDpRegionsClear(pDisplay);
+        WARN(("not implemented"));
+        pCmd->i8Result = -1;
+        return VINF_SUCCESS;
     }
 
-    CrDpLeave(pDisplay);
+    pCmd->i8Result = 0;
+    return VINF_SUCCESS;
 }
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp
index a784407..51c5d46 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp
@@ -350,14 +350,14 @@ int crServerRpwInit(CR_SERVER_RPW *pWorker)
             rc =  RTSemEventCreate(&pWorker->Ctl.hCompleteEvent);
             if (RT_SUCCESS(rc))
             {
-                CRASSERT(cr_server.MainContextInfo.CreateInfo.visualBits);
+                CRASSERT(cr_server.MainContextInfo.CreateInfo.realVisualBits);
                 CRASSERT(cr_server.MainContextInfo.SpuContext);
 
-                pWorker->ctxId = cr_server.head_spu->dispatch_table.CreateContext("", cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
+                pWorker->ctxId = cr_server.head_spu->dispatch_table.CreateContext("", cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
                 if (pWorker->ctxId)
                 {
                     CRMuralInfo *pDummyMural;
-                    pWorker->ctxVisBits = cr_server.MainContextInfo.CreateInfo.visualBits;
+                    pWorker->ctxVisBits = cr_server.MainContextInfo.CreateInfo.realVisualBits;
                     pDummyMural = crServerGetDummyMural(pWorker->ctxVisBits);
                     if (pDummyMural)
                     {
@@ -447,7 +447,7 @@ int crServerRpwEntryResizeCleaned(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *p
 
     if (!cr_server.currentCtxInfo)
     {
-        CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
+        CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
         if (!pDummy)
         {
             crWarning("crServerGetDummyMural failed");
@@ -535,7 +535,7 @@ int crServerRpwEntryCleanup(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
 
     if (!cr_server.currentCtxInfo)
     {
-        CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
+        CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
         if (!pDummy)
         {
             crWarning("crServerGetDummyMural failed");
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
index 38d301d..1698841 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
@@ -138,7 +138,14 @@ for index in range(len(funcs)):
     		*get_values = (%s)CR_MAX_TEXTURE_UNITS;
     	} 
     }
-    """ % (types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index])
+    else if (GL_MAX_VERTEX_ATTRIBS_ARB==pname)
+    {
+        if (CR_MAX_VERTEX_ATTRIBS < (GLuint)*get_values)
+        {
+            *get_values = (%s)CR_MAX_VERTEX_ATTRIBS;
+        } 
+    }
+    """ % (types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index])
     print '\tcrServerReturnValue( get_values, tablesize );'
     print '\tcrFree(get_values);'
     print '}\n'
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
index d7475e1..e2df4e9 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
@@ -253,3 +253,13 @@ VBoxTexPresent
 GetError
 GetProgramiv
 GetShaderiv
+Begin
+DrawArrays
+DrawElements
+End
+TexEnvf
+TexEnvfv
+TexEnvi
+TexEnviv
+GetTexEnvfv
+GetTexEnviv
\ No newline at end of file
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
index d67c433..bfadeda 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
@@ -441,7 +441,7 @@ crServerDispatchMessage(CRConnection *conn, CRMessage *msg)
         {
             uint32_t cbWriteback = pCmdData->cbWriteback;
             rc = crVBoxServerInternalClientRead(conn->pClient, (uint8_t*)pCmdData->pWriteback, &cbWriteback);
-            CRASSERT(rc == VINF_SUCCESS || rc == VERR_BUFFER_OVERFLOW);
+            Assert(rc == VINF_SUCCESS || rc == VERR_BUFFER_OVERFLOW);
             *pCmdData->pcbWriteback = cbWriteback;
         }
         VBOXCRHGSMI_CMD_CHECK_COMPLETE(pCmdData, rc);
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c
index 392bcd2..8037ac6 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c
@@ -136,3 +136,56 @@ CR_FUNC_IMAGE(TexImage2D,
 CR_FUNC_IMAGE(TexImage3D,
     (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels),
     (target, level, internalFormat, width, height, depth, border, format, type, realptr), pixels)
+
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnvf( GLenum target, GLenum pname, GLfloat param )
+{
+    crStateTexEnvf( target, pname, param );
+    if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+        CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnvf( target, pname, param ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnvfv( GLenum target, GLenum pname, const GLfloat * params )
+{
+    crStateTexEnvfv( target, pname, params );
+    if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+        CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnvfv( target, pname, params ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnvi( GLenum target, GLenum pname, GLint param )
+{
+    crStateTexEnvi( target, pname, param );
+    if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+        CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnvi( target, pname, param ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnviv( GLenum target, GLenum pname, const GLint * params )
+{
+    crStateTexEnviv( target, pname, params );
+    if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+        CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnviv( target, pname, params ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetTexEnvfv( GLenum target, GLenum pname, GLfloat * params )
+{
+    GLfloat local_params[4];
+    (void) params;
+    if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+        cr_server.head_spu->dispatch_table.GetTexEnvfv( target, pname, local_params );
+    else
+        crStateGetTexEnvfv( target, pname, local_params );
+
+    crServerReturnValue( &(local_params[0]), crStateHlpComponentsCount(pname)*sizeof (GLfloat) );
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetTexEnviv( GLenum target, GLenum pname, GLint * params )
+{
+    GLint local_params[4];
+    (void) params;
+    if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+        cr_server.head_spu->dispatch_table.GetTexEnviv( target, pname, local_params );
+    else
+        crStateGetTexEnviv( target, pname, local_params );
+
+    crServerReturnValue( &(local_params[0]), crStateHlpComponentsCount(pname)*sizeof (GLint) );
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
index c286331..b74c622 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
@@ -12,173 +12,48 @@
 
 #include "render/renderspu.h"
 
-static GLboolean crServerWindowCalcIsVisible(CRMuralInfo *pMural)
-{
-    uint32_t cRegions;
-    int rc;
-    if (!pMural->width || !pMural->height)
-        return GL_FALSE;
-
-    if (!pMural->bVisible || !(pMural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
-        return GL_FALSE;
-
-    rc = CrVrScrCompositorRegionsGet(pMural->fRootVrOn ? &pMural->RootVrCompositor : &pMural->Compositor, &cRegions, NULL, NULL, NULL);
-    if (RT_FAILURE(rc))
-    {
-        crWarning("CrVrScrCompositorRegionsGet failed, rc %d", rc);
-        return GL_FALSE;
-    }
-
-    if (!cRegions)
-        return GL_FALSE;
-
-    return GL_TRUE;
-}
-
-void crServerWindowSetIsVisible(CRMuralInfo *pMural, GLboolean fIsVisible)
-{
-    if (!fIsVisible == !pMural->fIsVisible)
-        return;
-
-    pMural->fIsVisible = fIsVisible;
-
-    CRASSERT(pMural->screenId < cr_server.screenCount);
-
-    if (fIsVisible)
-    {
-        ++cr_server.aWinVisibilityInfos[pMural->screenId].cVisibleWindows;
-        cr_server.aWinVisibilityInfos[pMural->screenId].fVisibleChanged = 1;
-    }
-    else
-    {
-        --cr_server.aWinVisibilityInfos[pMural->screenId].cVisibleWindows;
-        CRASSERT(cr_server.aWinVisibilityInfos[pMural->screenId].cVisibleWindows < UINT32_MAX/2);
-        if (!cr_server.aWinVisibilityInfos[pMural->screenId].cVisibleWindows)
-            cr_server.aWinVisibilityInfos[pMural->screenId].fVisibleChanged = 0;
-    }
-
-    crVBoxServerCheckVisibilityEvent(pMural->screenId);
-}
-
-void crServerWindowCheckIsVisible(CRMuralInfo *pMural)
-{
-    GLboolean fIsVisible = crServerWindowCalcIsVisible(pMural);
-
-    crServerWindowSetIsVisible(pMural, fIsVisible);
-}
-
-void crServerWindowSize(CRMuralInfo *pMural)
-{
-    cr_server.head_spu->dispatch_table.WindowSize(pMural->spuWindow, pMural->width, pMural->height);
-
-    crServerWindowCheckIsVisible(pMural);
-}
-
-void crServerWindowShow(CRMuralInfo *pMural)
-{
-    cr_server.head_spu->dispatch_table.WindowShow(pMural->spuWindow,
-            !!(pMural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY) && pMural->bVisible);
-
-    crServerWindowCheckIsVisible(pMural);
-}
-
-void crServerWindowVisibleRegion(CRMuralInfo *pMural)
-{
-    uint32_t cRects;
-    const RTRECT *pRects;
-    int rc = CrVrScrCompositorRegionsGet(pMural->fRootVrOn ? &pMural->RootVrCompositor : &pMural->Compositor, &cRects, NULL, &pRects, NULL);
-    if (RT_SUCCESS(rc))
-    {
-        cr_server.head_spu->dispatch_table.WindowVisibleRegion(pMural->spuWindow, cRects, (const GLint*)pRects);
-
-        crServerWindowCheckIsVisible(pMural);
-    }
-    else
-        crWarning("CrVrScrCompositorRegionsGet failed rc %d", rc);
-
-}
-
-void crServerWindowReparent(CRMuralInfo *pMural)
-{
-    crServerVBoxCompositionDisableEnter(pMural);
-
-    pMural->fHasParentWindow = !!cr_server.screen[pMural->screenId].winID;
-
-    renderspuReparentWindow(pMural->spuWindow);
-
-    crServerVBoxCompositionDisableLeave(pMural, GL_FALSE);
-}
-
 GLint SERVER_DISPATCH_APIENTRY
 crServerDispatchWindowCreate(const char *dpyName, GLint visBits)
 {
     return crServerDispatchWindowCreateEx(dpyName, visBits, -1);
 }
 
-static DECLCALLBACK(void) crServerMuralDefaultEntryReleasedCB(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
-{
-    CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-    CrDpEntryCleanup(pDEntry);
-}
-
-GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID, GLboolean fUseDefaultDEntry)
+GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID)
 {
     CRMuralInfo *defaultMural;
     GLint dims[2];
     GLint windowID = -1;
     GLint spuWindow;
     int rc;
+    GLint realVisBits = visBits;
 
     crMemset(mural, 0, sizeof (*mural));
 
-    CrVrScrCompositorInit(&mural->Compositor);
-
-    if (cr_server.fRootVrOn)
-    {
-        CrVrScrCompositorInit(&mural->RootVrCompositor);
-    }
+    if (cr_server.fVisualBitsDefault)
+        realVisBits = cr_server.fVisualBitsDefault;
 
     /*
      * Have first SPU make a new window.
      */
-    spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, visBits );
+    spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, realVisBits );
     if (spuWindow < 0) {
-        CrVrScrCompositorClear(&mural->Compositor);
-        if (cr_server.fRootVrOn)
-            CrVrScrCompositorClear(&mural->RootVrCompositor);
         return spuWindow;
     }
 
     /* get initial window size */
     cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, spuWindow, GL_INT, 2, dims);
 
-    mural->fUseDefaultDEntry = fUseDefaultDEntry;
-
-    if (fUseDefaultDEntry)
-    {
-        VBOXVR_TEXTURE Tex = {0};
-        Tex.width = dims[0];
-        Tex.height = dims[1];
-        Tex.target = GL_TEXTURE_2D;
-        Tex.hwid = 0;
-
-        CrDpEntryInit(&mural->DefaultDEntry, &Tex, 0, crServerMuralDefaultEntryReleasedCB);
-
-        mural->fRootVrOn = cr_server.fRootVrOn;
-    }
-
     defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
     CRASSERT(defaultMural);
     mural->gX = 0;
     mural->gY = 0;
     mural->width = dims[0];
     mural->height = dims[1];
-    
+
     mural->spuWindow = spuWindow;
     mural->screenId = 0;
     mural->fHasParentWindow = !!cr_server.screen[0].winID;
     mural->bVisible = !cr_server.bWindowsInitiallyHidden;
-    mural->fPresentMode = CR_SERVER_REDIR_F_NONE;
 
     mural->cVisibleRects = 0;
     mural->pVisibleRects = NULL;
@@ -190,57 +65,17 @@ GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits,
     else
         windowID = preloadWinID<0 ? (GLint)crHashtableAllocKeys( cr_server.muralTable, 1 ) : preloadWinID;
 
-    mural->CreateInfo.visualBits = visBits;
+    mural->CreateInfo.realVisualBits = realVisBits;
+    mural->CreateInfo.requestedVisualBits = visBits;
     mural->CreateInfo.externalID = windowID;
     mural->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
 
     CR_STATE_SHAREDOBJ_USAGE_INIT(mural);
 
-    if (fUseDefaultDEntry)
-    {
-        RTRECT Rect;
-        Rect.xLeft = 0;
-        Rect.xRight = mural->width;
-        Rect.yTop = 0;
-        Rect.yBottom = mural->height;
-        rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->DefaultDEntry.CEntry, NULL, 1, &Rect, false, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
-            return -1;
-        }
-    }
-
-    if (mural->fRootVrOn)
-    {
-        uint32_t cRects;
-        const RTRECT *pRects;
-        int rc = crServerMuralSynchRootVr(mural, NULL);
-        if (RT_SUCCESS(rc))
-        {
-            rc = CrVrScrCompositorRegionsGet(&mural->RootVrCompositor, &cRects, NULL, &pRects, NULL);
-            if (RT_SUCCESS(rc))
-            {
-                if (cRects != 1
-                        || pRects[0].xLeft != 0 || pRects[0].yTop != 0
-                        || pRects[0].xRight != mural->width || pRects[0].yBottom != mural->height)
-                {
-                    /* do visible rects only if they differ from the default */
-                    crServerWindowVisibleRegion(mural);
-                }
-            }
-            else
-            {
-                crWarning("CrVrScrCompositorRegionsGet failed, rc %d", rc);
-            }
-        }
-    }
-
     return windowID;
 }
 
-GLint
-crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
+GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
 {
     CRMuralInfo *mural;
     GLint windowID = -1;
@@ -286,7 +121,7 @@ crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preload
         return -1;
     }
 
-    windowID = crServerMuralInit(mural, dpyName, visBits, preloadWinID, GL_TRUE);
+    windowID = crServerMuralInit(mural, dpyName, visBits, preloadWinID);
     if (windowID < 0)
     {
         crWarning("crServerMuralInit failed!");
@@ -311,42 +146,12 @@ crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preload
     }
 
     /* ensure we have a dummy mural created right away to avoid potential deadlocks on VM shutdown */
-    crServerGetDummyMural(mural->CreateInfo.visualBits);
+    crServerGetDummyMural(mural->CreateInfo.realVisualBits);
 
     crServerReturnValue( &windowID, sizeof(windowID) );
     return windowID;
 }
 
-static bool crServerVBoxTranslateIntersectRect(CRMuralInfo *mural, const RTRECT *pSrcRect, PRTRECT pDstRect)
-{
-    int32_t xLeft = RT_MAX(mural->gX, pSrcRect->xRight);
-    int32_t yTop = RT_MAX(mural->gY, pSrcRect->yBottom);
-    int32_t xRight = RT_MIN(mural->gX + mural->width, pSrcRect->xLeft);
-    int32_t yBottom = RT_MIN(mural->gY + mural->height, pSrcRect->yTop);
-
-    if (xLeft < xRight && yTop < yBottom)
-    {
-        pDstRect->xLeft = xLeft;
-        pDstRect->yTop = yTop;
-        pDstRect->xRight = xRight;
-        pDstRect->yBottom = yBottom;
-        return true;
-    }
-
-    return false;
-}
-
-static void crServerVBoxRootVrTranslateForMural(CRMuralInfo *mural)
-{
-    int32_t dx = cr_server.RootVrCurPoint.x - mural->gX;
-    int32_t dy = cr_server.RootVrCurPoint.y - mural->gY;
-
-    cr_server.RootVrCurPoint.x = mural->gX;
-    cr_server.RootVrCurPoint.y = mural->gY;
-
-    VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
-}
-
 static int crServerRemoveClientWindow(CRClient *pClient, GLint window)
 {
     int pos;
@@ -365,12 +170,13 @@ static int crServerRemoveClientWindow(CRClient *pClient, GLint window)
 
 void crServerMuralTerm(CRMuralInfo *mural)
 {
-    crServerRedirMuralFBO(mural, CR_SERVER_REDIR_F_NONE);
+	PCR_BLITTER pBlitter;
+    crServerRedirMuralFBO(mural, false);
     crServerDeleteMuralFBO(mural);
 
     if (cr_server.currentMural == mural)
     {
-        CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
+        CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
         /* reset the current context to some dummy values to ensure render spu does not switch to a default "0" context,
          * which might lead to muralFBO (offscreen rendering) gl entities being created in a scope of that context */
         cr_server.head_spu->dispatch_table.MakeCurrent(dummyMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
@@ -382,6 +188,19 @@ void crServerMuralTerm(CRMuralInfo *mural)
         CRASSERT(cr_server.currentWindow != mural->CreateInfo.externalID);
     }
 
+    pBlitter = crServerVBoxBlitterGetInitialized();
+    if (pBlitter)
+    {
+    	const CR_BLITTER_WINDOW * pWindow = CrBltMuralGetCurrentInfo(pBlitter);
+    	if (pWindow && pWindow->Base.id == mural->spuWindow)
+    	{
+    		CRMuralInfo *dummy = crServerGetDummyMural(mural->CreateInfo.realVisualBits);
+    		CR_BLITTER_WINDOW DummyInfo;
+    		CRASSERT(dummy);
+    		crServerVBoxBlitterWinInit(&DummyInfo, dummy);
+    		CrBltMuralSetCurrentInfo(pBlitter, &DummyInfo);
+    	}
+    }
 
     cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow );
 
@@ -393,10 +212,7 @@ void crServerMuralTerm(CRMuralInfo *mural)
     if (mural->CreateInfo.pszDpyName)
         crFree(mural->CreateInfo.pszDpyName);
 
-    CrVrScrCompositorClear(&mural->Compositor);
-
-    if (mural->fRootVrOn)
-        CrVrScrCompositorClear(&mural->RootVrCompositor);
+    crServerRedirMuralFbClear(mural);
 }
 
 static void crServerCleanupCtxMuralRefsCB(unsigned long key, void *data1, void *data2)
@@ -496,141 +312,26 @@ crServerDispatchWindowDestroy( GLint window )
     }
 
     crHashtableDelete(cr_server.muralTable, window, crFree);
-}
 
-static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) crServerMuralGetRootVrCEntry(VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
-{
-    CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-    Assert(!CrVrScrCompositorEntryIsUsed(&pDEntry->RootVrCEntry));
-    CrVrScrCompositorEntryInit(&pDEntry->RootVrCEntry, CrVrScrCompositorEntryTexGet(pEntry), NULL);
-    CrVrScrCompositorEntryFlagsSet(&pDEntry->RootVrCEntry, CrVrScrCompositorEntryFlagsGet(pEntry));
-    return &pDEntry->RootVrCEntry;
-}
-
-int crServerMuralSynchRootVr(CRMuralInfo *mural, bool *pfChanged)
-{
-    int rc;
-
-    crServerVBoxRootVrTranslateForMural(mural);
-
-    /* ensure the rootvr compositor does not hold any data,
-     * i.e. cleanup all rootvr entries data */
-    CrVrScrCompositorClear(&mural->RootVrCompositor);
-
-    rc = CrVrScrCompositorIntersectedList(&mural->Compositor, &cr_server.RootVr, &mural->RootVrCompositor, crServerMuralGetRootVrCEntry, NULL, pfChanged);
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrVrScrCompositorIntersectedList failed, rc %d", rc);
-        return rc;
-    }
-
-    return VINF_SUCCESS;
+    crServerCheckAllMuralGeometry(NULL);
 }
 
 GLboolean crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height)
 {
-    RTRECT Rect;
-    VBOXVR_TEXTURE Tex;
-    int rc = VINF_SUCCESS;
-    Tex.width = width;
-    Tex.height = height;
-    Tex.target = GL_TEXTURE_2D;
-    Tex.hwid = 0;
-
     if (mural->width == width && mural->height == height)
         return GL_FALSE;
 
-
-    /* since we're going to change the current compositor & the window we need to avoid
-     * renderspu fron dealing with inconsistent data, i.e. modified compositor and
-     * still unmodified window.
-     * So what we do is:
-     * 1. tell renderspu to stop using the current compositor -> renderspu would do necessary synchronization with its redraw thread to ensure compositor is no longer used
-     * 2. do necessary modifications
-     * 3. (so far not needed for resize, but in case it is in the future) re-set the compositor */
-
-    /* 1. tell renderspu to stop using the current compositor (see above comment) */
-    crServerVBoxCompositionDisableEnter(mural);
-
-    /* 2. do necessary modifications (see above comment) */
-    /* NOTE: we can do it even if mural->fPresentMode == CR_SERVER_REDIR_F_NONE to make sure the compositor data is always up to date */
-    /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
-    /* CrVrScrCompositorLock(&mural->Compositor); */
-    if (mural->fUseDefaultDEntry)
-    {
-        if (!mural->bReceivedRects)
-        {
-            rc = CrVrScrCompositorEntryRemove(&mural->Compositor, &mural->DefaultDEntry.CEntry);
-            if (!RT_SUCCESS(rc))
-            {
-                crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
-                goto end;
-            }
-            CrVrScrCompositorEntryInit(&mural->DefaultDEntry.CEntry, &Tex, NULL);
-            /* initially set regions to all visible since this is what some guest assume
-             * and will not post any more visible regions command */
-            Rect.xLeft = 0;
-            Rect.xRight = width;
-            Rect.yTop = 0;
-            Rect.yBottom = height;
-            rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->DefaultDEntry.CEntry, NULL, 1, &Rect, false, NULL);
-            if (!RT_SUCCESS(rc))
-            {
-                crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
-                goto end;
-            }
-        }
-        else
-        {
-            rc = CrVrScrCompositorEntryTexUpdate(&mural->Compositor, &mural->DefaultDEntry.CEntry, &Tex);
-            if (!RT_SUCCESS(rc))
-            {
-                crWarning("CrVrScrCompositorEntryTexUpdate failed, rc %d", rc);
-                goto end;
-            }
-        }
-    }
-    else
-    {
-        CrVrScrCompositorClear(&mural->Compositor);
-    }
-
-    /* CrVrScrCompositorUnlock(&mural->Compositor); */
     mural->width = width;
     mural->height = height;
 
-    mural->fDataPresented = GL_FALSE;
-
-    if (cr_server.curClient && cr_server.curClient->currentMural == mural)
+    if (cr_server.curClient && cr_server.curClient->currentMural == mural
+            && !mural->fRedirected)
     {
         crStateGetCurrent()->buffer.width = mural->width;
         crStateGetCurrent()->buffer.height = mural->height;
     }
 
-    if (mural->fRootVrOn)
-    {
-        rc = crServerMuralSynchRootVr(mural, NULL);
-        if (!RT_SUCCESS(rc))
-        {
-            crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
-            goto end;
-        }
-    }
-
-    crServerCheckMuralGeometry(mural);
-
-    crServerWindowSize(mural);
-
-    crServerWindowVisibleRegion(mural);
-
-    crServerDEntryAllResized(mural);
-end:
-    /* 3. (so far not needed for resize, but in case it is in the future) re-set the compositor (see above comment) */
-    /* uncomment when needed */
-    /* NOTE: !!! we have mural->fHasPresentationData set to GL_FALSE above, so crServerVBoxCompositionReenable will have no effect in any way
-
-    */
-    crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
+    crServerCheckAllMuralGeometry(mural);
 
     return GL_TRUE;
 }
@@ -657,62 +358,15 @@ crServerDispatchWindowSize( GLint window, GLint width, GLint height )
     }
 }
 
-void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y, GLboolean fSkipCheckGeometry)
+void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y)
 {
-    GLboolean fForcePresent = GL_FALSE;
-    /*  crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
-
-//    if (mural->gX != x || mural->gY != y)
-    {
-        /* since we're going to change the current compositor & the window we need to avoid
-         * renderspu fron dealing with inconsistent data, i.e. modified compositor and
-         * still unmodified window.
-         * So what we do is:
-         * 1. tell renderspu to stop using the current compositor -> renderspu would do necessary synchronization with its redraw thread to ensure compositor is no longer used
-         * 2. do necessary modifications
-         * 3. re-set the compositor */
-
-        /* 1. tell renderspu to stop using the current compositor (see above comment) */
-        crServerVBoxCompositionDisableEnter(mural);
-
-        /* 2. do necessary modifications (see above comment) */
-        /* NOTE: we can do it even if !(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY) to make sure the compositor data is always up to date */
-
-        if (mural->gX != x || mural->gY != y)
-        {
-            if (mural->fRootVrOn)
-            {
-                fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
-            }
-
-            mural->gX = x;
-            mural->gY = y;
-
-            /* no need to set position because the position is relative to window */
-            /*CrVrScrCompositorEntryPosSet(&mural->Compositor, &mural->CEntry, &Pos);*/
-
-            if (mural->fRootVrOn)
-            {
-                int rc = crServerMuralSynchRootVr(mural, NULL);
-                if (RT_SUCCESS(rc))
-                {
-                    crServerWindowVisibleRegion(mural);
-                }
-                else
-                {
-                    crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
-                }
-            }
-        }
-
-        if (!fSkipCheckGeometry)
-            crServerCheckMuralGeometry(mural);
+    if (mural->gX == x && mural->gY == y)
+        return;
 
-        crServerDEntryAllMoved(mural);
+    mural->gX = x;
+    mural->gY = y;
 
-        /* 3. re-set the compositor (see above comment) */
-        crServerVBoxCompositionDisableLeave(mural, fForcePresent);
-    }
+    crServerCheckAllMuralGeometry(mural);
 }
 
 void SERVER_DISPATCH_APIENTRY
@@ -725,27 +379,11 @@ crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
 #endif
          return;
     }
-    crServerMuralPosition(mural, x, y, GL_FALSE);
+    crServerMuralPosition(mural, x, y);
 }
 
 void crServerMuralVisibleRegion( CRMuralInfo *mural, GLint cRects, const GLint *pRects )
 {
-    GLboolean fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
-    bool fRegionsChanged = false;
-    int rc = VINF_SUCCESS;
-
-    /* since we're going to change the current compositor & the window we need to avoid
-     * renderspu fron dealing with inconsistent data, i.e. modified compositor and
-     * still unmodified window.
-     * So what we do is:
-     * 1. tell renderspu to stop using the current compositor -> renderspu would do necessary synchronization with its redraw thread to ensure compositor is no longer used
-     * 2. do necessary modifications
-     * 3. re-set the compositor */
-
-    /* 1. tell renderspu to stop using the current compositor (see above comment) */
-    crServerVBoxCompositionDisableEnter(mural);
-
-    /* 2. do necessary modifications (see above comment) */
     if (mural->pVisibleRects)
     {
         crFree(mural->pVisibleRects);
@@ -764,37 +402,7 @@ void crServerMuralVisibleRegion( CRMuralInfo *mural, GLint cRects, const GLint *
         crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
     }
 
-    Assert(mural->fUseDefaultDEntry);
-    /* NOTE: we can do it even if !(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY) to make sure the compositor data is always up to date */
-    /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
-    /* CrVrScrCompositorLock(&mural->Compositor); */
-    rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->DefaultDEntry.CEntry, NULL, cRects, (const RTRECT *)pRects, false, &fRegionsChanged);
-    /*CrVrScrCompositorUnlock(&mural->Compositor);*/
-    if (!RT_SUCCESS(rc))
-    {
-        crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
-        goto end;
-    }
-
-    if (fRegionsChanged)
-    {
-        if (mural->fRootVrOn)
-        {
-            rc = crServerMuralSynchRootVr(mural, NULL);
-            if (!RT_SUCCESS(rc))
-            {
-                crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
-                goto end;
-            }
-        }
-
-        crServerWindowVisibleRegion(mural);
-
-        crServerDEntryAllVibleRegions(mural);
-    }
-end:
-    /* 3. re-set the compositor (see above comment) */
-    crServerVBoxCompositionDisableLeave(mural, fForcePresent);
+    crServerCheckAllMuralGeometry(mural);
 }
 
 void SERVER_DISPATCH_APIENTRY
@@ -813,10 +421,15 @@ crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, const GLint *pR
 
 void crServerMuralShow( CRMuralInfo *mural, GLint state )
 {
+    if (!mural->bVisible == !state)
+        return;
+
     mural->bVisible = !!state;
 
-    if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
-        crServerWindowShow(mural);
+    if (mural->bVisible)
+        crServerCheckMuralGeometry(mural);
+    else
+        crServerCheckAllMuralGeometry(mural);
 }
 
 void SERVER_DISPATCH_APIENTRY
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
index 5a69306..b907c6a 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
@@ -301,7 +301,7 @@ renderspuDestroyContext( GLint ctx )
     }
 
     curCtx = GET_CONTEXT_VAL();
-    CRASSERT(curCtx);
+//    CRASSERT(curCtx);
     if (curCtx == context)
     {
         renderspuMakeCurrent( CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID );
@@ -765,7 +765,7 @@ renderspuWindowShow( GLint win, GLint flag )
 }
 
 static void RENDER_APIENTRY
-renderspuVBoxPresentComposition( GLint win, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+renderspuVBoxPresentComposition( GLint win, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
 {
     WindowInfo *window;
     CRASSERT(win >= 0);
@@ -788,12 +788,12 @@ renderspuVBoxPresentComposition( GLint win, struct VBOXVR_SCR_COMPOSITOR * pComp
     }
 }
 
-void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
+void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
 {
-    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    CrVrScrCompositorIterInit(pCompositor, &CIter);
-    while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+    CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+    while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
     {
         uint32_t cRegions;
         const RTRECT *paSrcRegions, *paDstRegions;
@@ -805,11 +805,12 @@ void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pComp
             for (i = 0; i < cRegions; ++i)
             {
                 RTRECT DstRect;
+                const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
                 DstRect.xLeft = paDstRegions[i].xLeft * scaleX;
                 DstRect.yTop = paDstRegions[i].yTop * scaleY;
                 DstRect.xRight = paDstRegions[i].xRight * scaleX;
                 DstRect.yBottom = paDstRegions[i].yBottom * scaleY;
-                CrBltBlitTexMural(pBlitter, true, &pEntry->Tex, &paSrcRegions[i], &DstRect, 1, fFlags);
+                CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), &paSrcRegions[i], &DstRect, 1, fFlags);
             }
         }
         else
@@ -819,12 +820,12 @@ void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pComp
     }
 }
 
-void renderspuVBoxCompositorBlit ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
+void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
 {
-    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
-    CrVrScrCompositorIterInit(pCompositor, &CIter);
-    while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+    CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+    while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
     {
         uint32_t cRegions;
         const RTRECT *paSrcRegions, *paDstRegions;
@@ -832,7 +833,8 @@ void renderspuVBoxCompositorBlit ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, P
         uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
         if (RT_SUCCESS(rc))
         {
-            CrBltBlitTexMural(pBlitter, true, &pEntry->Tex, paSrcRegions, paDstRegions, cRegions, fFlags);
+            const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+            CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), paSrcRegions, paDstRegions, cRegions, fFlags);
         }
         else
         {
@@ -849,15 +851,15 @@ void renderspuVBoxPresentBlitterCleanup( WindowInfo *window )
     if (render_spu.blitterTable)
     {
         const CR_BLITTER_WINDOW * pBltInfo = CrBltMuralGetCurrentInfo(window->pBlitter);
-        if (pBltInfo->Base.id == window->BltInfo.Base.id)
+        if (pBltInfo && pBltInfo->Base.id == window->BltInfo.Base.id)
         {
-            CrBltMuralSetCurrent(window->pBlitter, NULL);
+            CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
         }
     }
     else
     {
         CRASSERT(CrBltMuralGetCurrentInfo(window->pBlitter)->Base.id == window->BltInfo.Base.id);
-        CrBltMuralSetCurrent(window->pBlitter, NULL);
+        CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
         CrBltTerm(window->pBlitter);
     }
     window->pBlitter = NULL;
@@ -894,7 +896,7 @@ PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
                 return NULL;
             }
 
-            rc = CrBltInit(pBlitter, &pDefaultCtxInfo->BltInfo, true, true, NULL, render_spu.blitterDispatch);
+            rc = CrBltInit(pBlitter, &pDefaultCtxInfo->BltInfo, true, true, NULL, &render_spu.blitterDispatch);
 
             /* we can release it either way, since it will be retained when used as a shared context */
             renderspuDefaultSharedContextRelease(pDefaultCtxInfo);
@@ -919,29 +921,17 @@ PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
         window->pBlitter = pBlitter;
     }
 
-    CrBltMuralSetCurrent(pBlitter, &window->BltInfo);
+    CrBltMuralSetCurrentInfo(pBlitter, &window->BltInfo);
     return pBlitter;
 }
 
 int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
 {
     int rc;
-    PCR_BLITTER_CONTEXT pCtxInfo = NULL;
-    PCR_BLITTER_WINDOW pWindowInfo = NULL;
-    GET_CONTEXT(pCtx);
-
-    if (pCtx)
-    {
-        if (pCtx->currentWindow)
-        {
-            pCtxInfo = &pCtx->BltInfo;
-            pWindowInfo =  &pCtx->currentWindow->BltInfo;
-        }
-    }
 
     CrBltSetMakeCurrentUserData(pBlitter, i32MakeCurrentUserData);
 
-    rc = CrBltEnter(pBlitter, pCtxInfo, pWindowInfo);
+    rc = CrBltEnter(pBlitter);
     if (!RT_SUCCESS(rc))
     {
         crWarning("CrBltEnter failed, rc %d", rc);
@@ -968,7 +958,7 @@ PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_
 {
     if (!window->pBlitter)
     {
-        struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
+        const struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
         /* just use compositor lock to synchronize */
         pTmpCompositor = renderspuVBoxCompositorAcquire(window);
         CRASSERT(pTmpCompositor);
@@ -1005,7 +995,7 @@ PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_
     return window->pBlitter;
 }
 
-void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
+void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
 {
     PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData);
     if (!pBlitter)
@@ -1018,7 +1008,7 @@ void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, struct VBOXVR_S
     CrBltLeave(pBlitter);
 }
 
-void renderspuVBoxCompositorSet( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor)
+void renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
 {
     int rc;
     /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
@@ -1055,12 +1045,12 @@ void renderspuVBoxCompositorClearAll()
     crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
 }
 
-struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
+const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
 {
     int rc = RTCritSectEnter(&window->CompositorLock);
     if (RT_SUCCESS(rc))
     {
-        VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
+        const VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
         if (pCompositor)
             return pCompositor;
 
@@ -1088,7 +1078,7 @@ int renderspuVBoxCompositorUnlock(WindowInfo *window)
     return rc;
 }
 
-int renderspuVBoxCompositorTryAcquire(WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
+int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
 {
     int rc = RTCritSectTryEnter(&window->CompositorLock);
     if (RT_SUCCESS(rc))
@@ -1550,9 +1540,16 @@ renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
         }
         break;
 
+    case GL_HH_SET_TMPCTX_MAKE_CURRENT:
+    	if (type == GL_BYTE && count == sizeof (void*))
+    		memcpy(&render_spu.blitterDispatch.MakeCurrent, values, count);
+    	else
+    		WARN(("unexpected type(%#x) - count(%d) pair", type, count));
+    	break;
+
     default:
 #if 0
-        crWarning("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target);
+        WARN(("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target));
 #endif
         break;
     }
@@ -1707,6 +1704,9 @@ renderspuGetString(GLenum pname)
             return NULL;
         }
 
+        if (!context)
+            return (const GLubyte *)nativeExt;
+
         crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
         s1 = crStrIntersect(nativeExt, crExt);
         remove_trailing_space(s1);
@@ -1815,6 +1815,5 @@ renderspuCreateFunctions(SPUNamedFunctionTable table[])
     FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
     FILLIN( "GetString", renderspuGetString );
     FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
-
     return i;
 }
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu.h b/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
index 2793f97..1d7704c 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
@@ -28,6 +28,7 @@
 #include "cr_hash.h"
 #include "cr_server.h"
 #include "cr_blitter.h"
+#include "cr_compositor.h"
 
 #include <iprt/cdefs.h>
 #include <iprt/critsect.h>
@@ -102,7 +103,7 @@ typedef struct WindowInfo {
     GLboolean fCompositorPresentEmpty;
     char *title;
 
-    PVBOXVR_SCR_COMPOSITOR pCompositor;
+    const VBOXVR_SCR_COMPOSITOR *pCompositor;
     /* the composotor lock is used to synchronize the current compositor access,
      * i.e. the compositor can be accessed by a gui refraw thread,
      * while chromium thread might try to set a new compositor
@@ -209,6 +210,15 @@ typedef struct CR_RENDER_WINCMD
 } CR_RENDER_WINCMD, *PCR_RENDER_WINCMD;
 #endif
 
+#ifdef RT_OS_DARWIN
+typedef void (*PFNDELETE_OBJECT)(GLhandleARB obj);
+typedef void (*PFNGET_ATTACHED_OBJECTS)( GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj );
+typedef GLhandleARB (*PFNGET_HANDLE)(GLenum pname);
+typedef void (*PFNGET_INFO_LOG)( GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog );
+typedef void (*PFNGET_OBJECT_PARAMETERFV)( GLhandleARB obj, GLenum pname, GLfloat * params );
+typedef void (*PFNGET_OBJECT_PARAMETERIV)( GLhandleARB obj, GLenum pname, GLint * params );
+#endif
+
 /**
  * Renderspu state info
  */
@@ -275,7 +285,7 @@ typedef struct {
     char *swap_master_url;
     CRConnection **swap_conns;
 
-    SPUDispatchTable *blitterDispatch;
+    SPUDispatchTable blitterDispatch;
     CRHashTable *blitterTable;
 
 #ifdef USE_OSMESA
@@ -310,6 +320,13 @@ typedef struct {
 
 #ifdef RT_OS_DARWIN
 # ifdef VBOX_WITH_COCOA_QT
+    PFNDELETE_OBJECT pfnDeleteObject;
+    PFNGET_ATTACHED_OBJECTS pfnGetAttachedObjects;
+    PFNGET_HANDLE pfnGetHandle;
+    PFNGET_INFO_LOG pfnGetInfoLog;
+    PFNGET_OBJECT_PARAMETERFV pfnGetObjectParameterfv;
+    PFNGET_OBJECT_PARAMETERIV pfnGetObjectParameteriv;
+
     CR_GLSL_CACHE GlobalShaders;
 # else
     RgnHandle hRootVisibleRegion;
@@ -389,17 +406,18 @@ extern void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt );
 extern void renderspu_SystemMakeCurrent( WindowInfo *window, GLint windowInfor, ContextInfo *context );
 extern void renderspu_SystemSwapBuffers( WindowInfo *window, GLint flags );
 extern void renderspu_SystemReparentWindow(WindowInfo *window);
-extern void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry );
+extern void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry );
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable);
 extern void renderspu_GCWindow(void);
 extern int renderspuCreateFunctions( SPUNamedFunctionTable table[] );
-extern void renderspuVBoxCompositorSet( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor);
+extern void renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor);
 extern void renderspuVBoxCompositorClearAll();
 extern int renderspuVBoxCompositorLock(WindowInfo *window);
 extern int renderspuVBoxCompositorUnlock(WindowInfo *window);
-extern struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window);
-extern int renderspuVBoxCompositorTryAcquire(WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR **ppCompositor);
+extern const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window);
+extern int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor);
 extern void renderspuVBoxCompositorRelease( WindowInfo *window);
-extern void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData );
+extern void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData );
 extern PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window );
 void renderspuVBoxPresentBlitterCleanup( WindowInfo *window );
 extern int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData );
@@ -411,8 +429,8 @@ extern void renderspuPerformMakeCurrent(WindowInfo *window, GLint nativeWindow,
 extern GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id);
 extern GLboolean renderspuWindowInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id );
 extern GLboolean renderspuInitVisual(VisualInfo *pVisInfo, const char *displayName, GLbitfield visAttribs);
-extern void renderspuVBoxCompositorBlit ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter);
-extern void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY);
+extern void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter);
+extern void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY);
 extern GLint renderspuCreateContextEx(const char *dpyName, GLint visBits, GLint id, GLint shareCtx);
 extern GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id );
 
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c
index d1bcd37..3d14fa3 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c
@@ -607,7 +607,7 @@ renderspu_SystemShowWindow(WindowInfo *window, GLboolean showIt)
     }
 }
 
-void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
 {
     renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
 }
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c
index 41f5c5b..f9492a2 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c
@@ -21,6 +21,9 @@
 #include <iprt/string.h>
 #include <iprt/path.h>
 
+#include <cr_string.h>
+#include <cr_mem.h>
+
 GLboolean renderspu_SystemInitVisual(VisualInfo *pVisInfo)
 {
     CRASSERT(pVisInfo);
@@ -151,7 +154,7 @@ void renderspu_SystemShowWindow(WindowInfo *pWinInfo, GLboolean fShowIt)
     cocoaViewShow(pWinInfo->window, fShowIt);
 }
 
-void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
 {
     cocoaViewPresentComposition(window->window, pChangedEntry);
 }
@@ -198,6 +201,23 @@ int renderspu_SystemTerm()
     return VINF_SUCCESS;
 }
 
+static SPUNamedFunctionTable * renderspuFindEntry(SPUNamedFunctionTable *aFunctions, const char *pcszName)
+{
+    SPUNamedFunctionTable *pCur;
+
+    for (pCur = aFunctions ; pCur->name != NULL ; pCur++)
+    {
+        if (!crStrcmp( pcszName, pCur->name ) )
+        {
+            return pCur;
+        }
+    }
+
+    AssertFailed();
+
+    return NULL;
+}
+
 typedef struct CR_RENDER_CTX_INFO
 {
     ContextInfo * pContext;
@@ -250,7 +270,7 @@ void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, Conte
 
     if (!CrGlslIsInited(&render_spu.GlobalShaders))
     {
-        CrGlslInit(&render_spu.GlobalShaders, render_spu.blitterDispatch);
+        CrGlslInit(&render_spu.GlobalShaders, &render_spu.blitterDispatch);
     }
 
     if (fromContext)
@@ -289,3 +309,178 @@ void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, Conte
             crWarning("renderspuCtxSetCurrentWithAnyWindow failed!");
     }
 }
+
+AssertCompile(sizeof (GLhandleARB) == sizeof (void*));
+
+static VBoxGLhandleARB crHndlSearchVBox(GLhandleARB hNative)
+{
+    CRASSERT(!(((uintptr_t)hNative) >> 32));
+    return (VBoxGLhandleARB)((uintptr_t)hNative);
+}
+
+static GLhandleARB crHndlSearchNative(VBoxGLhandleARB hVBox)
+{
+    return (GLhandleARB)((uintptr_t)hVBox);
+}
+
+static VBoxGLhandleARB crHndlAcquireVBox(GLhandleARB hNative)
+{
+    CRASSERT(!(((uintptr_t)hNative) >> 32));
+    return (VBoxGLhandleARB)((uintptr_t)hNative);
+}
+
+static GLhandleARB crHndlReleaseVBox(VBoxGLhandleARB hVBox)
+{
+    return (GLhandleARB)((uintptr_t)hVBox);
+}
+
+static void SPU_APIENTRY renderspu_SystemDeleteObjectARB(VBoxGLhandleARB obj)
+{
+    GLhandleARB hNative = crHndlReleaseVBox(obj);
+    if (!hNative)
+    {
+        crWarning("no native for %d", obj);
+        return;
+    }
+
+    render_spu.pfnDeleteObject(hNative);
+}
+
+static void SPU_APIENTRY renderspu_SystemGetAttachedObjectsARB( VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * pCount, VBoxGLhandleARB * obj )
+{
+    GLhandleARB *paAttachments;
+    GLhandleARB hNative = crHndlSearchNative(containerObj);
+    GLsizei count, i;
+
+    if (pCount)
+        *pCount = 0;
+
+    if (!hNative)
+    {
+        crWarning("no native for %d", obj);
+        return;
+    }
+
+    paAttachments = crCalloc(maxCount * sizeof (*paAttachments));
+    if (!paAttachments)
+    {
+        crWarning("crCalloc failed");
+        return;
+    }
+
+    render_spu.pfnGetAttachedObjects(hNative, maxCount, &count, paAttachments);
+    if (pCount)
+        *pCount = count;
+    if (count > maxCount)
+    {
+        crWarning("count too big");
+        count = maxCount;
+    }
+
+    for (i = 0; i < count; ++i)
+    {
+        obj[i] = crHndlSearchVBox(paAttachments[i]);
+        CRASSERT(obj[i]);
+    }
+
+    crFree(paAttachments);
+}
+
+static VBoxGLhandleARB SPU_APIENTRY renderspu_SystemGetHandleARB(GLenum pname)
+{
+    GLhandleARB hNative = render_spu.pfnGetHandle(pname);
+    VBoxGLhandleARB hVBox;
+    if (!hNative)
+    {
+        crWarning("pfnGetHandle failed");
+        return 0;
+    }
+    hVBox = crHndlAcquireVBox(hNative);
+    CRASSERT(hVBox);
+    return hVBox;
+}
+
+static void SPU_APIENTRY renderspu_SystemGetInfoLogARB( VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog )
+{
+    GLhandleARB hNative = crHndlSearchNative(obj);
+    if (!hNative)
+    {
+        crWarning("invalid handle!");
+        return;
+    }
+
+    render_spu.pfnGetInfoLog(hNative, maxLength, length, infoLog);
+}
+
+static void SPU_APIENTRY renderspu_SystemGetObjectParameterfvARB( VBoxGLhandleARB obj, GLenum pname, GLfloat * params )
+{
+    GLhandleARB hNative = crHndlSearchNative(obj);
+    if (!hNative)
+    {
+        crWarning("invalid handle!");
+        return;
+    }
+
+    render_spu.pfnGetObjectParameterfv(hNative, pname, params);
+}
+
+static void SPU_APIENTRY renderspu_SystemGetObjectParameterivARB( VBoxGLhandleARB obj, GLenum pname, GLint * params )
+{
+    GLhandleARB hNative = crHndlSearchNative(obj);
+    if (!hNative)
+    {
+        crWarning("invalid handle!");
+        return;
+    }
+
+    render_spu.pfnGetObjectParameteriv(hNative, pname, params);
+}
+
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
+{
+    SPUNamedFunctionTable * pEntry;
+
+    pEntry = renderspuFindEntry(aFunctions, "DeleteObjectARB");
+    if (pEntry)
+    {
+        render_spu.pfnDeleteObject = (PFNDELETE_OBJECT)pEntry->fn;
+        pEntry->fn = (SPUGenericFunction)renderspu_SystemDeleteObjectARB;
+    }
+
+    pEntry = renderspuFindEntry(aFunctions, "GetAttachedObjectsARB");
+    if (pEntry)
+    {
+        render_spu.pfnGetAttachedObjects = (PFNGET_ATTACHED_OBJECTS)pEntry->fn;
+        pEntry->fn = (SPUGenericFunction)renderspu_SystemGetAttachedObjectsARB;
+    }
+
+    pEntry = renderspuFindEntry(aFunctions, "GetHandleARB");
+    if (pEntry)
+    {
+        render_spu.pfnGetHandle = (PFNGET_HANDLE)pEntry->fn;
+        pEntry->fn = (SPUGenericFunction)renderspu_SystemGetHandleARB;
+    }
+
+    pEntry = renderspuFindEntry(aFunctions, "GetInfoLogARB");
+    if (pEntry)
+    {
+        render_spu.pfnGetInfoLog = (PFNGET_INFO_LOG)pEntry->fn;
+        pEntry->fn = (SPUGenericFunction)renderspu_SystemGetInfoLogARB;
+    }
+
+    pEntry = renderspuFindEntry(aFunctions, "GetObjectParameterfvARB");
+    if (pEntry)
+    {
+        render_spu.pfnGetObjectParameterfv = (PFNGET_OBJECT_PARAMETERFV)pEntry->fn;
+        pEntry->fn = (SPUGenericFunction)renderspu_SystemGetObjectParameterfvARB;
+    }
+
+    pEntry = renderspuFindEntry(aFunctions, "GetObjectParameterivARB");
+    if (pEntry)
+    {
+        render_spu.pfnGetObjectParameteriv = (PFNGET_OBJECT_PARAMETERIV)pEntry->fn;
+        pEntry->fn = (SPUGenericFunction)renderspu_SystemGetObjectParameterivARB;
+    }
+
+    return cFunctions;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h
index 79d61e2..546f98b 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h
@@ -22,6 +22,8 @@
 #include <VBox/VBoxCocoa.h>
 #include <OpenGL/OpenGL.h>
 #include <cr_vreg.h>
+#include <cr_compositor.h>
+
 
 RT_C_DECLS_BEGIN
 
@@ -46,7 +48,7 @@ void cocoaViewGetGeometry(NativeNSViewRef pView, int *pX, int *pY, int *pW, int
 
 void cocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx);
 void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, const GLint* paRects);
-void cocoaViewPresentComposition(NativeNSViewRef pView, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry);
+void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry);
 
 RT_C_DECLS_END
 
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
index d28962b..db2c00c 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
@@ -347,6 +347,8 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     WindowInfo *m_pWinInfo;
     bool m_fNeedViewportUpdate;
     bool m_fNeedCtxUpdate;
+    bool m_fDataVisible;
+    bool m_fEverSized;
 }
 - (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo;
 - (void)setGLCtx:(NSOpenGLContext*)pCtx;
@@ -359,11 +361,13 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
 
 - (void)setPos:(NSPoint)pos;
 - (NSPoint)pos;
+- (bool)isEverSized;
 - (void)setSize:(NSSize)size;
 - (NSSize)size;
 - (void)updateViewportCS;
-- (void)reshape;
-- (void)reshapeLocked;
+- (void)vboxReshapePerform;
+- (void)vboxReshapeOnResizePerform;
+- (void)vboxReshapeOnReparentPerform;
 
 - (void)createDockTile;
 - (void)deleteDockTile;
@@ -372,11 +376,11 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
 - (void)swapFBO;
 - (void)vboxTryDraw;
 - (void)vboxTryDrawUI;
-- (void)vboxPresent:(PVBOXVR_SCR_COMPOSITOR)pCompositor;
-- (void)vboxPresentCS:(PVBOXVR_SCR_COMPOSITOR)pCompositor;
-- (void)vboxPresentToDockTileCS:(PVBOXVR_SCR_COMPOSITOR)pCompositor;
-- (void)vboxPresentToViewCS:(PVBOXVR_SCR_COMPOSITOR)pCompositor;
-- (void)presentComposition:(PVBOXVR_SCR_COMPOSITOR_ENTRY)pChangedEntry;
+- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry;
 - (void)vboxBlitterSyncWindow;
 
 - (void)clearVisibleRegions;
@@ -718,10 +722,16 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     /* Reposition this window with the help of the OverlayView. Perform the
      * call in the OpenGL thread. */
     /*
-    [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
+    [m_pOverlayView performSelector:@selector(vboxReshapePerform) onThread:m_Thread withObject:nil waitUntilDone:YES];
     */
 
-    [m_pOverlayView reshape];
+    if ([m_pOverlayView isEverSized])
+    {    
+        if([NSThread isMainThread])
+            [m_pOverlayView vboxReshapePerform];
+        else
+            [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
+    }
 }
 
 - (void)parentWindowChanged:(NSWindow*)pWindow
@@ -743,10 +753,17 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
         /* Reshape the overlay view after a short waiting time to let the main
          * window resize itself properly. */
         /*
-        [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
-        [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
+        [m_pOverlayView performSelector:@selector(vboxReshapePerform) withObject:nil afterDelay:0.2];
+        [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(vboxReshapePerform) userInfo:nil repeats:NO];
         */
-        [m_pOverlayView reshape];
+
+        if ([m_pOverlayView isEverSized])
+        {    
+            if([NSThread isMainThread])
+                [m_pOverlayView vboxReshapePerform];
+            else
+                [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
+        }        
     }
 }
 
@@ -777,6 +794,8 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     m_pWinInfo             	  = pWinInfo;
     m_fNeedViewportUpdate     = true;        
     m_fNeedCtxUpdate          = true;
+    m_fDataVisible            = false;
+    m_fEverSized              = false;
     
     self = [super initWithFrame:frame];
 
@@ -789,13 +808,8 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
 {
     [self deleteDockTile];
     
-    if (m_pGLCtx)
-    {
-        if ([m_pGLCtx view] == self)
-            [m_pGLCtx clearDrawable];
-
-        m_pGLCtx = nil;
-    }
+    [self setGLCtx:nil];
+    
     if (m_pSharedGLCtx)
     {
         if ([m_pSharedGLCtx view] == self)
@@ -807,6 +821,8 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
         
         CrBltTerm(m_pBlitter);
         
+        RTMemFree(m_pBlitter);
+        
         m_pBlitter = nil;
     }
 
@@ -835,9 +851,15 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
 
     /* ensure the context drawable is cleared to avoid holding a reference to inexistent view */
     if (m_pGLCtx)
+    {
         [m_pGLCtx clearDrawable];
+        [m_pGLCtx release];
+        /*[m_pGLCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
+    }
 
     m_pGLCtx = pCtx;
+    if (pCtx)
+        [pCtx retain];
 }
 
 - (NSOpenGLContext*)glCtx
@@ -875,7 +897,8 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
 
     m_Pos = pos;
 
-    [self reshape];
+    if (m_fEverSized)
+        [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
     
     /* we need to redwar on regions change, however the compositor now is cleared 
      * because all compositor&window data-related modifications are performed with compositor cleared
@@ -891,29 +914,22 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     return m_Pos;
 }
 
+- (bool)isEverSized
+{
+    return m_fEverSized;
+}
+
 - (void)setSize:(NSSize)size
 {
     NSOpenGLContext *pCurCtx;
     NSView *pCurView;
     m_Size = size;
+    
+    m_fEverSized = true;
 
     DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
-    [self reshape];
-    [self createDockTile];
-    /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
-    m_fNeedViewportUpdate = true;
-    pCurCtx = [NSOpenGLContext currentContext];
-    if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
-    {
-        [m_pGLCtx update];
-        m_fNeedCtxUpdate = false;
-    }
-    else
-    {
-        /* do it in a lazy way */
-        m_fNeedCtxUpdate = true;
-    }
-    
+    [self performSelectorOnMainThread:@selector(vboxReshapeOnResizePerform) withObject:nil waitUntilDone:NO];
+
     /* we need to redwar on regions change, however the compositor now is cleared 
      * because all compositor&window data-related modifications are performed with compositor cleared
      * the renderspu client will re-set the compositor after modifications are complete
@@ -938,9 +954,37 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     [self vboxBlitterSyncWindow];
         
     /* Clear background to transparent */
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);}
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+}
 
-- (void)reshapeLocked
+- (void)vboxReshapeOnResizePerform
+{
+    [self vboxReshapePerform];
+    
+    [self createDockTile];
+    /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
+    m_fNeedViewportUpdate = true;
+#if 0
+    pCurCtx = [NSOpenGLContext currentContext];
+    if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
+    {
+        [m_pGLCtx update];
+        m_fNeedCtxUpdate = false;
+    }
+    else
+    {
+        /* do it in a lazy way */
+        m_fNeedCtxUpdate = true;
+    }
+#endif
+}
+
+- (void)vboxReshapeOnReparentPerform
+{
+    [self createDockTile];
+}
+
+- (void)vboxReshapePerform
 {
     NSRect parentFrame = NSZeroRect;
     NSPoint parentPos  = NSZeroPoint;
@@ -948,7 +992,7 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     NSRect childFrame  = NSZeroRect;
     NSRect newFrame    = NSZeroRect;
 
-    DEBUG_MSG(("OVIW(%p): reshape\n", (void*)self));
+    DEBUG_MSG(("OVIW(%p): vboxReshapePerform\n", (void*)self));
     
     parentFrame = [m_pParentView frame];
     DEBUG_MSG(("FIXED parentFrame [%f:%f], [%f:%f]\n", parentFrame.origin.x, parentFrame.origin.y, parentFrame.size.width, parentFrame.size.height));    
@@ -1035,16 +1079,6 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     }
 }
 
-- (void)reshape
-{
-    int rc = renderspuVBoxCompositorLock(m_pWinInfo);
-    if (RT_SUCCESS(rc))
-    {
-        [self reshapeLocked];
-        renderspuVBoxCompositorUnlock(m_pWinInfo);
-    }
-}
-
 - (void)createDockTile
 {
 	NSView *pDockScreen      = nil;
@@ -1107,151 +1141,100 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     }
 }
 
-- (void)vboxTryDraw
+- (bool)vboxSharedCtxCreate
 {
-    GLint opaque       = 0;
-    if ([self lockFocusIfCanDraw])
+    if (m_pSharedGLCtx)
+        return true;
+        
+    Assert(!m_pBlitter);
+    m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
+    if (!m_pBlitter)
     {
-        VBOXVR_SCR_COMPOSITOR *pCompositor = NULL;
-        if (!m_pSharedGLCtx)
-	    {
-	    	pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
-	    	if (pCompositor)
-	    	{
-	    	    Assert(!m_pBlitter);
-                m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
-                if (m_pBlitter)
-                {
-                    int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, render_spu.blitterDispatch);
-                    if (RT_SUCCESS(rc))
-                    {
-                        DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
-                    }
-                    else
-                    {
-                        DEBUG_WARN(("CrBltInit failed, rc %d", rc));
-                        RTMemFree(m_pBlitter);
-                        m_pBlitter = NULL;
-                    }        
-                }
-                else
-                {
-                    DEBUG_WARN(("m_pBlitter allocation failed"));
-                }
-                    
-	    	    if (m_pBlitter)
-	    	    {
-    		        /* Create a shared context out of the main context. Use the same pixel format. */
-    		        m_pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
-    		
-    		        /* Set the new context as non opaque */
-    		        [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
-    		        /* Set this view as the drawable for the new context */
-    		        [m_pSharedGLCtx setView: self];
-    		        m_fNeedViewportUpdate = true;
-    		    }
-#ifdef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
-				renderspuVBoxCompositorRelease(m_pWinInfo);
-				pCompositor = NULL;
-#endif
-		    }
-		}
-		
-		if (m_pSharedGLCtx)
-		{
-			if (!pCompositor)
-			{
-#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
-				/* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
-				int rc = renderspuVBoxCompositorTryAcquire(m_pWinInfo, &pCompositor);
-				if (RT_SUCCESS(rc))
-				{
-					Assert(pCompositor);
-				}
-			    else if (rc == VERR_SEM_BUSY)
-#endif
-			    {
-			        glFlush();
-			            
-			        /* issue to the gui thread */
-			        [self setNeedsDisplay:YES];
-			    }
-#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
-			    else
-			    {
-			        /* this is somewhat we do not expect */
-			        DEBUG_MSG(("renderspuVBoxCompositorTryAcquire failed rc %d", rc));
-			    }
-#endif
-			}
-		
-#ifdef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
-			Assert(!pCompositor);
-#endif	
-			if (pCompositor)
-			{
-				[self vboxPresent:pCompositor];
-				renderspuVBoxCompositorRelease(m_pWinInfo);
-			}
-		}
-		else
-		{
-			AssertRelease(!pCompositor);
-		}
-        [self unlockFocus];
+        DEBUG_WARN(("m_pBlitter allocation failed"));
+        return false;
     }
-    else
+        
+    int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
+    if (RT_SUCCESS(rc))
     {
-        [self setNeedsDisplay:YES];
+        DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
     }
+    else
+    {
+        DEBUG_WARN(("CrBltInit failed, rc %d", rc));
+        RTMemFree(m_pBlitter);
+        m_pBlitter = NULL;
+        return false;
+    }        
+    
+    GLint opaque       = 0;
+    /* Create a shared context out of the main context. Use the same pixel format. */
+    NSOpenGLContext *pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
+        
+    /* Set the new context as non opaque */
+    [pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
+    /* Set this view as the drawable for the new context */
+    [pSharedGLCtx setView: self];
+    m_fNeedViewportUpdate = true;
+    
+    m_pSharedGLCtx = pSharedGLCtx;
+    
+    return true;
+}
+
+- (void)vboxTryDraw
+{
+    glFlush();
+                        
+    /* issue to the gui thread */
+    [self setNeedsDisplay:YES];
 }
 
 - (void)vboxTryDrawUI
 {
-    if ([self lockFocusIfCanDraw])
+    const VBOXVR_SCR_COMPOSITOR *pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
+    if (!m_fDataVisible && !pCompositor)
+        return;
+
+    VBOXVR_SCR_COMPOSITOR TmpCompositor;
+    
+    if (pCompositor)
     {
-        if (m_pSharedGLCtx)
-	    {
-#if 1
-            /* tmp workaround to prevent potential deadlock:
-             * crOpenGL service thread does compositor lock acquire and calls cocoa NS methods that could synchronize on the GUI thread
-             * while here we do a reverse order: acquire compositor lock being in gui thread.
-             * this is why we do only try acquire and re-submit repaint event if compositor lock is busy */
-             VBOXVR_SCR_COMPOSITOR *pCompositor = NULL;
-            int rc = renderspuVBoxCompositorTryAcquire(m_pWinInfo, &pCompositor);
-            if (RT_SUCCESS(rc))
-            {
-                Assert(pCompositor);
-                [self vboxPresent:pCompositor];
-                renderspuVBoxCompositorRelease(m_pWinInfo);
-            }
-            else if (rc == VERR_SEM_BUSY)
-            {
-                /* re-issue to the gui thread */
-# ifdef DEBUG_misha
-                DEBUG_WARN(("renderspuVBoxCompositorTryAcquire busy\n"));
-# endif 
-                [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
-            }
-            else
+        if (!m_pSharedGLCtx)
+        {
+            Assert(!m_fDataVisible);
+            renderspuVBoxCompositorRelease(m_pWinInfo);
+            if (![self vboxSharedCtxCreate])
             {
-                /* this is somewhat we do not expect */
-                DEBUG_WARN(("renderspuVBoxCompositorTryAcquire failed rc %d", rc));
+                DEBUG_WARN(("vboxSharedCtxCreate failed\n"));
+                return;
             }
-#else
-	    	VBOXVR_SCR_COMPOSITOR *pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
-	    	if (pCompositor)
-	    	{
-	    		[self vboxPresent:pCompositor];
-				renderspuVBoxCompositorRelease(m_pWinInfo);
-			}
-#endif
-		}
+            
+            Assert(m_pSharedGLCtx);
+            
+            pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
+            Assert(!m_fDataVisible);
+            if (!pCompositor)
+                return;
+        }
+    }
+    else
+    {
+        CrVrScrCompositorInit(&TmpCompositor, NULL);
+        pCompositor = &TmpCompositor;
+    }
+    
+    if ([self lockFocusIfCanDraw])
+    {
+        [self vboxPresent:pCompositor];
+        if (pCompositor != &TmpCompositor)
+            renderspuVBoxCompositorRelease(m_pWinInfo);
+            
         [self unlockFocus];
     }
     else
     {
-        [self setNeedsDisplay:YES];
+        [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
     }
 }
 
@@ -1260,22 +1243,13 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     [m_pGLCtx flushBuffer];
 }
 
-- (void)vboxPresent:(PVBOXVR_SCR_COMPOSITOR)pCompositor
+- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
 {
     VBOX_CR_RENDER_CTX_INFO CtxInfo;    
     
     DEBUG_MSG(("OVIW(%p): renderFBOToView\n", (void*)self));    
     
     Assert(pCompositor);
-    
-#if 0 //def DEBUG
-            {
-            	NSOpenGLContext *pTstOldCtx = [NSOpenGLContext currentContext];
-            	NSView *pTstOldView = (pTstOldCtx ? [pTstOldCtx view] : nil);
-            	Assert(pTstOldCtx == m_pGLCtx);
-            	Assert(pTstOldView == self);
-            }
-#endif
 
     vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
     
@@ -1284,7 +1258,7 @@ static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
     vboxCtxLeave(&CtxInfo);
 }
 
-- (void)vboxPresentCS:(PVBOXVR_SCR_COMPOSITOR)pCompositor
+- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
 {
         {
             if ([m_pSharedGLCtx view] != self)
@@ -1337,17 +1311,17 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
     pRect->yBottom = (int)((pR->origin.y + pR->size.height) * yStretch);
 }
 
-- (void)vboxPresentToViewCS:(PVBOXVR_SCR_COMPOSITOR)pCompositor
+- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
 {
     NSRect r = [self frame];
     float xStretch, yStretch;
     DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
 
 #if 1 /* Set to 0 to see the docktile instead of the real output */
-    VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-    PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
         
-    CrVrScrCompositorIterInit(pCompositor, &CIter);
+    CrVrScrCompositorConstIterInit(pCompositor, &CIter);
         
     glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
     glDrawBuffer(GL_BACK);
@@ -1355,9 +1329,11 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
     /* Clear background to transparent */
     glClear(GL_COLOR_BUFFER_BIT);
     
+    m_fDataVisible = false;
+    
     CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
         
-    while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+    while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
     {
         uint32_t cRegions;
         const RTRECT *paSrcRegions, *paDstRegions;
@@ -1366,15 +1342,16 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
         if (RT_SUCCESS(rc))
         {
             uint32_t i;
-            int rc = CrBltEnter(m_pBlitter, NULL, NULL);
+            int rc = CrBltEnter(m_pBlitter);
             if (RT_SUCCESS(rc))
             {                   
                 for (i = 0; i < cRegions; ++i)
                 {
                     const RTRECT * pSrcRect = &paSrcRegions[i];
                     const RTRECT * pDstRect = &paDstRegions[i];
-                    RTRECT SrcRect, DstRect, RestrictSrcRect, RestrictDstRect;
-                    
+                    RTRECT DstRect, RestrictDstRect;
+                    RTRECT SrcRect, RestrictSrcRect;
+
                     vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
                     VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
                     
@@ -1382,8 +1359,9 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
                         continue;
 
                     VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
-                        
+
                     vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
+                    VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
                     VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
                     
                     if (VBoxRectIsZero(&SrcRect))
@@ -1392,7 +1370,11 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
                     pSrcRect = &SrcRect;
                     pDstRect = &DstRect;
                     
-                    CrBltBlitTexMural(m_pBlitter, true, &pEntry->Tex, pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
+                    const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+                    
+                    CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
+                    
+                    m_fDataVisible = true;
                 }
                 CrBltLeave(m_pBlitter);
             }
@@ -1415,7 +1397,7 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
             [m_pSharedGLCtx flushBuffer];
 }
 
-- (void)presentComposition:(PVBOXVR_SCR_COMPOSITOR_ENTRY)pChangedEntry
+- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry
 {
     [self vboxTryDraw];
 }
@@ -1434,19 +1416,19 @@ DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, floa
     WinInfo.width = r.size.width;
     WinInfo.height = r.size.height;
     
-    Assert(WinInfo.width = m_RootRect.size.width);
-    Assert(WinInfo.height = m_RootRect.size.height);
+    Assert(WinInfo.width == m_RootRect.size.width);
+    Assert(WinInfo.height == m_RootRect.size.height);
 
-    /*CrBltMuralSetCurrent(m_pBlitter, NULL);*/
+    /*CrBltMuralSetCurrentInfo(m_pBlitter, NULL);*/
     
-    CrBltMuralSetCurrent(m_pBlitter, &WinInfo);
+    CrBltMuralSetCurrentInfo(m_pBlitter, &WinInfo);
     CrBltCheckUpdateViewport(m_pBlitter);
 }
 
 #ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
 static int g_cVBoxTgaCtr = 0;
 #endif
-- (void)vboxPresentToDockTileCS:(PVBOXVR_SCR_COMPOSITOR)pCompositor
+- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
 {
     NSRect r        = [self frame];
     NSRect rr       = NSZeroRect;
@@ -1459,8 +1441,8 @@ static int g_cVBoxTgaCtr = 0;
         /* Only update after at least 200 ms, cause glReadPixels is
          * heavy performance wise. */
         uint64_t uiNewTime = RTTimeMilliTS();
-        VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
-        PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+        VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+        const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
         
         if (uiNewTime - m_uiDockUpdateTime > 200)
         {
@@ -1491,8 +1473,8 @@ static int g_cVBoxTgaCtr = 0;
             
             CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
             
-            CrVrScrCompositorIterInit(pCompositor, &CIter);
-            while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+            CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+            while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
             {
                 uint32_t cRegions;
                 const RTRECT *paSrcRegions, *paDstRegions;
@@ -1501,7 +1483,7 @@ static int g_cVBoxTgaCtr = 0;
                 if (RT_SUCCESS(rc))
                 {
                     uint32_t i;
-                    int rc = CrBltEnter(m_pBlitter, NULL, NULL);
+                    int rc = CrBltEnter(m_pBlitter);
                     if (RT_SUCCESS(rc))
                     {                   
                         for (i = 0; i < cRegions; ++i)
@@ -1515,12 +1497,13 @@ static int g_cVBoxTgaCtr = 0;
                             
                             VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
                             
-                            VBoxRectStretch(&DstRect, m_FBOThumbScaleX, m_FBOThumbScaleY);
+                            VBoxRectScale(&DstRect, m_FBOThumbScaleX, m_FBOThumbScaleY);
                     
                             if (VBoxRectIsZero(&DstRect))
                                 continue;
                         
                             vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
+                            VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
                             VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
                     
                             if (VBoxRectIsZero(&SrcRect))
@@ -1529,7 +1512,9 @@ static int g_cVBoxTgaCtr = 0;
                             pSrcRect = &SrcRect;
                             pDstRect = &DstRect;
                             
-                            CrBltBlitTexMural(m_pBlitter, true, &pEntry->Tex, pSrcRect, pDstRect, 1, fFlags);
+                            const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+                            
+                            CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags);
                         }
                         CrBltLeave(m_pBlitter);
                     }
@@ -1746,9 +1731,8 @@ void cocoaGLCtxDestroy(NativeNSOpenGLContextRef pCtx)
 {
     NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
 
-    /*
     [pCtx release];
-    */
+    /*[pCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
 
     [pPool release];
 }
@@ -1797,7 +1781,8 @@ void cocoaViewReparent(NativeNSViewRef pView, NativeNSViewRef pParentView)
         if (pParentView != nil)
         {
             [[pParentView window] addChildWindow:[pOView overlayWin] ordered:NSWindowAbove];
-            [pOView createDockTile];
+            if ([pOView isEverSized])
+                [pOView performSelectorOnMainThread:@selector(vboxReshapeOnReparentPerform) withObject:nil waitUntilDone:NO];
         }
     }
 
@@ -1905,7 +1890,7 @@ void cocoaViewGetGeometry(NativeNSViewRef pView, int *pX, int *pY, int *pW, int
     [pPool release];
 }
 
-void cocoaViewPresentComposition(NativeNSViewRef pView, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
+void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
 {
     NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
     NSOpenGLContext *pCtx;
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
index b09017c..9bdcf29 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
@@ -578,7 +578,7 @@ static DECLCALLBACK(int) renderspuWinCmdThreadProc(RTTHREAD ThreadSelf, void *pv
                     WindowInfo *pWindow = (WindowInfo*)crHashtableSearch(render_spu.pWinToInfoTable, event.xexpose.window);
                     if (pWindow)
                     {
-                        struct VBOXVR_SCR_COMPOSITOR * pCompositor;
+                        const struct VBOXVR_SCR_COMPOSITOR * pCompositor;
 
                         pCompositor = renderspuVBoxCompositorAcquire(pWindow);
                         if (pCompositor)
@@ -1968,14 +1968,14 @@ renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
     }
 }
 
-void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
 {
     /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
      * here it forces rendering in WinCmd thread rather than a Main thread.
      * it is used for debugging only in any way actually.
      * @todo: change to some more generic macro name */
 #ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
-    struct VBOXVR_SCR_COMPOSITOR *pCompositor;
+    const struct VBOXVR_SCR_COMPOSITOR *pCompositor;
     /* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
     int rc = renderspuVBoxCompositorTryAcquire(window, &pCompositor);
     if (RT_SUCCESS(rc))
@@ -2079,3 +2079,8 @@ void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, Conte
 {
 
 }
+
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
+{
+    return cFunctions;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
index d75d2b1..6d46faf 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
@@ -373,6 +373,8 @@ renderSPUInit( int id, SPU *child, SPU *self,
 
     render_spu.gather_conns = NULL;
 
+    numFuncs = renderspu_SystemPostprocessFunctions(_cr_render_table, numFuncs, RT_ELEMENTS(_cr_render_table));
+
     crDebug("Render SPU: ---------- End of Init -------------");
 
     return &render_functions;
@@ -383,7 +385,8 @@ static void renderSPUSelfDispatch(SPUDispatchTable *self)
     crSPUInitDispatchTable( &(render_spu.self) );
     crSPUCopyDispatchTable( &(render_spu.self), self );
 
-    render_spu.blitterDispatch = &(render_spu.self);
+    crSPUInitDispatchTable( &(render_spu.blitterDispatch) );
+    crSPUCopyDispatchTable( &(render_spu.blitterDispatch), self );
 
     render_spu.server = (CRServer *)(self->server);
 
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
index d20493a..1175b29 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
@@ -430,7 +430,7 @@ MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
             WindowInfo *pWindow = (WindowInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
             if (pWindow)
             {
-                struct VBOXVR_SCR_COMPOSITOR * pCompositor;
+                const struct VBOXVR_SCR_COMPOSITOR * pCompositor;
 
                 pCompositor = renderspuVBoxCompositorAcquire(pWindow);
                 if (pCompositor)
@@ -1251,14 +1251,14 @@ void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
     window->visible = showIt;
 }
 
-void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
 {
     /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
      * here it forces rendering in WinCmd thread rather than a Main thread.
      * it is used for debugging only in any way actually.
      * @todo: change to some more generic macro name */
 #ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
-    struct VBOXVR_SCR_COMPOSITOR *pCompositor;
+    const struct VBOXVR_SCR_COMPOSITOR *pCompositor;
     /* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
     int rc = renderspuVBoxCompositorTryAcquire(window, &pCompositor);
     if (RT_SUCCESS(rc))
@@ -1687,3 +1687,8 @@ void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, Conte
 {
 
 }
+
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
+{
+    return cFunctions;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c
index 26ae126..2e90b3d 100644
--- a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c
+++ b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c
@@ -39,8 +39,8 @@ void crUnpackExtendShaderSource(void)
     GLsizei count = READ_DATA(12, GLsizei);
     GLint hasNonLocalLen = READ_DATA(16, GLsizei);
     GLint *pLocalLength = DATA_POINTER(20, GLint);
-    const char **ppStrings = NULL;
-    GLsizei i;
+    char **ppStrings = NULL;
+    GLsizei i, j, jUpTo;
     int pos=20+count*sizeof(*pLocalLength);
 
     if (hasNonLocalLen>0)
@@ -60,9 +60,24 @@ void crUnpackExtendShaderSource(void)
         {
             pLocalLength[i] -= 1;
         }
+
+        Assert(pLocalLength[i] > 0);
+        jUpTo = i == count -1 ? pLocalLength[i] - 1 : pLocalLength[i];
+        for (j = 0; j < jUpTo; ++j)
+        {
+            char *pString = ppStrings[i];
+
+            if (pString[j] == '\0')
+            {
+                Assert(j == jUpTo - 1);
+                pString[j] = '\n';
+            }
+        }
     }
 
-    cr_unpackDispatch.ShaderSource(shader, count, ppStrings, length ? length : pLocalLength);
+//    cr_unpackDispatch.ShaderSource(shader, count, ppStrings, length ? length : pLocalLength);
+    cr_unpackDispatch.ShaderSource(shader, 1, ppStrings, 0);
+
     crFree(ppStrings);
 }
 
@@ -249,7 +264,7 @@ void crUnpackExtendGetAttachedShaders(void)
 
 void crUnpackExtendGetAttachedObjectsARB(void)
 {
-	GLhandleARB containerObj = READ_DATA(8, GLhandleARB);
+	VBoxGLhandleARB containerObj = READ_DATA(8, VBoxGLhandleARB);
 	GLsizei maxCount = READ_DATA(12, GLsizei);
 	SET_RETURN_PTR(16);
 	SET_WRITEBACK_PTR(24);
@@ -258,7 +273,7 @@ void crUnpackExtendGetAttachedObjectsARB(void)
 
 void crUnpackExtendGetInfoLogARB(void)
 {
-	GLhandleARB obj = READ_DATA(8, GLhandleARB);
+	VBoxGLhandleARB obj = READ_DATA(8, VBoxGLhandleARB);
 	GLsizei maxLength = READ_DATA(12, GLsizei);
 	SET_RETURN_PTR(16);
 	SET_WRITEBACK_PTR(24);
diff --git a/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings b/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings
index b4dca11..6831370 100644
--- a/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings
+++ b/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings
@@ -9,7 +9,7 @@
 'choiceVBoxCLI_title' = '@VBOX_PRODUCT@ Command Line Utilities';
 'choiceVBoxCLI_msg' = 'Installs the @VBOX_PRODUCT@ command line utilities into /usr/bin.';
 
-'RUNNING_VMS_TLE' = "Running VirtualBox VM's detected!";
+'RUNNING_VMS_TLE' = "Running VirtualBox VMs detected!";
 'RUNNING_VMS_MSG' = "The installer has detected running Virtual Machines. Please shutdown all running VirtualBox machines and then restart the installation.";
 
 'UNSUPPORTED_HW_MACHINE_TLE' = "Unsupported hardware architecture detected!";
diff --git a/src/VBox/Installer/linux/Makefile.kmk b/src/VBox/Installer/linux/Makefile.kmk
index 97dc6e6..7811273 100644
--- a/src/VBox/Installer/linux/Makefile.kmk
+++ b/src/VBox/Installer/linux/Makefile.kmk
@@ -321,7 +321,8 @@ VBOX_MIME_ICONS = \
 VBOX_DESKTOP_ICONS = \
 	$(addprefix $(PATH_ROOT)/src/VBox/Resources/$(if $(VBOX_OSE),OSE,NonOSE)/,\
 	    $(foreach s,16 20 32 40 48 64 128,\
-		virtualbox-$(s)px.png=>$(s)x$(s)/virtualbox.png))
+		virtualbox-$(s)px.png=>$(s)x$(s)/virtualbox.png) \
+		virtualbox.svg=>scalable/virtualbox.svg)
 
 #
 # All the bin files that goes into the archives.
diff --git a/src/VBox/Installer/linux/install.sh b/src/VBox/Installer/linux/install.sh
index c76ab08..a590e8a 100755
--- a/src/VBox/Installer/linux/install.sh
+++ b/src/VBox/Installer/linux/install.sh
@@ -423,7 +423,7 @@ if [ "$ACTION" = "install" ]; then
         cd $i
         if [ -d /usr/share/icons/hicolor/$i ]; then
             for j in *; do
-                if [ "$j" = "virtualbox.png" ]; then
+                if expr "$j" : "virtualbox\..*" > /dev/null; then
                     dst=apps
                 else
                     dst=mimetypes
diff --git a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec
index 19c9334..07bc38c 100644
--- a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec
+++ b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec
@@ -104,9 +104,9 @@ mv VBoxCreateUSBNode.sh $RPM_BUILD_ROOT/usr/share/virtualbox
 cp icons/128x128/virtualbox.png $RPM_BUILD_ROOT/usr/share/pixmaps/virtualbox.png
 cd icons
   for i in *; do
-    if [ -f $i/virtualbox.png ]; then
+    if [ -f $i/virtualbox.* ]; then
       install -d $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/apps
-      mv $i/virtualbox.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/apps
+      mv $i/virtualbox.* $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/apps
     fi
     install -d $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/mimetypes
     mv $i/* $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/mimetypes || true
diff --git a/src/VBox/Installer/linux/scripts/install.sh b/src/VBox/Installer/linux/scripts/install.sh
index 2b4f089..576eb4e 100755
--- a/src/VBox/Installer/linux/scripts/install.sh
+++ b/src/VBox/Installer/linux/scripts/install.sh
@@ -186,9 +186,9 @@ test -z "${NO_QT}" &&
 test -z "${NO_QT}" &&
     for i in "${INSTALL_SOURCE}/icons/"*; do
         folder=`expr "${i}/" : '.*/\([^/][^/]*/\)/*'`
-        if test -f "${i}/virtualbox.png"; then
+        if test -f "${i}/virtualbox."*; then
             install -d -g 0 -o 0 "${PREFIX}/share/icons/hicolor/${folder}/apps"
-            mv "${i}/virtualbox.png" "${PREFIX}/share/icons/hicolor/${folder}/apps"
+            mv "${i}/virtualbox."* "${PREFIX}/share/icons/hicolor/${folder}/apps"
         fi
         install -d -g 0 -o 0 "${PREFIX}/share/icons/hicolor/${folder}/mimetypes"
         mv "${i}/"* "${PREFIX}/share/icons/hicolor/${folder}/mimetypes" 2>/dev/null || true
diff --git a/src/VBox/Installer/solaris/smf-vboxautostart.sh b/src/VBox/Installer/solaris/smf-vboxautostart.sh
index 8eb3a84..6e0332b 100755
--- a/src/VBox/Installer/solaris/smf-vboxautostart.sh
+++ b/src/VBox/Installer/solaris/smf-vboxautostart.sh
@@ -1,7 +1,7 @@
 #!/sbin/sh
 # $Id: smf-vboxautostart.sh $
 
-# Copyright (C) 2012 Oracle Corporation
+# Copyright (C) 2012-2014 Oracle Corporation
 #
 # This file is part of VirtualBox Open Source Edition (OSE), as
 # available from http://www.virtualbox.org. This file is free software;
@@ -24,13 +24,13 @@ VW_EXIT=0
 
 case $VW_OPT in
     start)
-        if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then
+        if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then
             echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist."
             return $SMF_EXIT_ERR_CONFIG
         fi
 
-        if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then
-            echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist."
+        if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then
+            echo "ERROR: /opt/VirtualBox/VBoxAutostart is not exectuable."
             return $SMF_EXIT_ERR_CONFIG
         fi
 
@@ -43,17 +43,20 @@ case $VW_OPT in
         [ $? != 0 ] && VW_LOGSIZE=
         VW_LOGINTERVAL=`/usr/bin/svcprop -p config/loginterval $SMF_FMRI 2>/dev/null`
         [ $? != 0 ] && VW_LOGINTERVAL=
+        VW_VBOXGROUP=`/usr/bin/svcprop -p config/vboxgroup $SMF_FMRI 2>/dev/null`
+        [ $? != 0 ] && VW_VBOXGROUP=
 
         # Provide sensible defaults
         [ -z "$VW_CONFIG" ] && VW_CONFIG=/etc/vbox/autostart.cfg
         [ -z "$VW_ROTATE" ] && VW_ROTATE=10
         [ -z "$VW_LOGSIZE" ] && VW_LOGSIZE=104857600
         [ -z "$VW_LOGINTERVAL" ] && VW_LOGINTERVAL=86400
+        [ -z "$VW_VBOXGROUP" ] && VW_VBOXGROUP=staff
 
         # Get all users
-        for VW_USER in `logins -g staff`
+        for VW_USER in `logins -g $VW_VBOXGROUP | cut -d' ' -f1`
         do
-            exec su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --background --start --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\""
+            su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --background --start --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\""
 
             VW_EXIT=$?
             if [ $VW_EXIT != 0 ]; then
@@ -64,13 +67,13 @@ case $VW_OPT in
         done
     ;;
     stop)
-        if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then
+        if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then
             echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist."
             return $SMF_EXIT_ERR_CONFIG
         fi
 
-        if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then
-            echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist."
+        if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then
+            echo "ERROR: /opt/VirtualBox/VBoxAutostart is not executable."
             return $SMF_EXIT_ERR_CONFIG
         fi
 
@@ -83,17 +86,20 @@ case $VW_OPT in
         [ $? != 0 ] && VW_LOGSIZE=
         VW_LOGINTERVAL=`/usr/bin/svcprop -p config/loginterval $SMF_FMRI 2>/dev/null`
         [ $? != 0 ] && VW_LOGINTERVAL=
+        VW_VBOXGROUP=`/usr/bin/svcprop -p config/vboxgroup $SMF_FMRI 2>/dev/null`
+        [ $? != 0 ] && VW_VBOXGROUP=
 
         # Provide sensible defaults
         [ -z "$VW_CONFIG" ] && VW_CONFIG=/etc/vbox/autostart.cfg
         [ -z "$VW_ROTATE" ] && VW_ROTATE=10
         [ -z "$VW_LOGSIZE" ] && VW_LOGSIZE=104857600
         [ -z "$VW_LOGINTERVAL" ] && VW_LOGINTERVAL=86400
+        [ -z "$VW_VBOXGROUP" ] && VW_VBOXGROUP=staff
 
         # Get all users
-        for VW_USER in `logins -g staff`
+        for VW_USER in `logins -g $VW_VBOXGROUP | cut -d' ' -f1`
         do
-            exec su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --stop --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\""
+            su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --stop --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\""
 
             VW_EXIT=$?
             if [ $VW_EXIT != 0 ]; then
diff --git a/src/VBox/Installer/solaris/vboxconfig.sh b/src/VBox/Installer/solaris/vboxconfig.sh
index 80e7ea6..85448d8 100755
--- a/src/VBox/Installer/solaris/vboxconfig.sh
+++ b/src/VBox/Installer/solaris/vboxconfig.sh
@@ -257,9 +257,10 @@ get_sysinfo()
                     # not set by most pkg(5) tools...
                     # STR_KERN_MAJOR is now of the format "5.12-5.12.0.0.0.9.1.3.0:20121012T032837Z" with '9' representing
                     # the build number.
-                    BRANCH_VERSION=STR_KERN_MAJOR
+                    BRANCH_VERSION=$STR_KERN_MAJOR
                     HOST_OS_MAJORVERSION=`echo "$BRANCH_VERSION" | cut -f2 -d'-' | cut -f1,2 -d'.'`
-                    if test "HOST_OS_MAJORVERSION" = "5.12"; then
+                    if test "$HOST_OS_MAJORVERSION" = "5.12"; then
+                        HOST_OS_MAJORVERSION="12"
                         HOST_OS_MINORVERSION=`echo "$BRANCH_VERSION" | cut -f2 -d'-' | cut -f6 -d'.'`
                         return 0
                     else
diff --git a/src/VBox/Installer/solaris/virtualbox-autostart.xml b/src/VBox/Installer/solaris/virtualbox-autostart.xml
index bee110b..e523b9f 100644
--- a/src/VBox/Installer/solaris/virtualbox-autostart.xml
+++ b/src/VBox/Installer/solaris/virtualbox-autostart.xml
@@ -93,6 +93,7 @@
 
         <property_group name='config' type='application'>
             <propval name='config' type='astring' value='/etc/vbox/autostart.cfg' />
+            <propval name='vboxgroup' type='astring' value='staff' />
         </property_group>
 
         <template>
diff --git a/src/VBox/Installer/win/VirtualBox.wxs b/src/VBox/Installer/win/VirtualBox.wxs
index ea14897..176c1e1 100644
--- a/src/VBox/Installer/win/VirtualBox.wxs
+++ b/src/VBox/Installer/win/VirtualBox.wxs
@@ -640,6 +640,12 @@
                     </Component>
 <?endif?>
 
+                    <!-- C API (glue) binding -->
+                    <Component Id="cp_VBoxCAPI" Guid="097F7F53-7111-467F-8E0C-257D9926FDA0">
+                        <File Id="file_VBoxCAPI.dll" Name="VBoxCAPI.dll"
+                              Source="$(env.PATH_OUT)\bin\VBoxCAPI.dll" />
+                    </Component>
+
 <?if $(env.VBOX_WITH_PYTHON) = "yes" ?>
                     <Component Id="cp_VBoxPythonBinding" Guid="293D7E11-78DA-4C31-AEED-AE2FE42F6881">
                         <Condition>PYTHON_INSTALLED</Condition>
@@ -730,6 +736,7 @@
 <?if $(env.VBOX_WITH_WEBSERVICES) = "yes" ?>
             <ComponentRef Id="cp_VBoxWebService" />
 <?endif?>
+            <ComponentRef Id="cp_VBoxCAPI" />
             <ComponentRef Id="cp_VBoxDrv" />
 
             <Feature Id="VBoxUSB" Title="VirtualBox USB Support" Level="1"
diff --git a/src/VBox/Main/Makefile.kmk b/src/VBox/Main/Makefile.kmk
index cda8c29..302f681 100644
--- a/src/VBox/Main/Makefile.kmk
+++ b/src/VBox/Main/Makefile.kmk
@@ -4,7 +4,7 @@
 #
 
 #
-# Copyright (C) 2004-2013 Oracle Corporation
+# Copyright (C) 2004-2014 Oracle Corporation
 #
 # This file is part of VirtualBox Open Source Edition (OSE), as
 # available from http://www.virtualbox.org. This file is free software;
@@ -54,11 +54,14 @@ endif
 VBOX_MAIN_DEFS += \
 	$(if $(VBOX_WITH_RAW_MODE),VBOX_WITH_RAW_MODE,) \
 	$(if $(VBOX_WITH_RAW_RING1),VBOX_WITH_RAW_RING1,) \
+	$(if $(VBOX_WITH_VMSVGA),VBOX_WITH_VMSVGA,) \
+	$(if $(VBOX_WITH_VMSVGA3D),VBOX_WITH_VMSVGA3D,) \
 	$(if $(VBOX_WITH_NETFLT),VBOX_WITH_NETFLT,) \
 	$(if $(VBOX_WITH_COPYTOGUEST),VBOX_WITH_COPYTOGUEST,) \
 	$(if $(VBOX_WITH_DRAG_AND_DROP),VBOX_WITH_DRAG_AND_DROP,) \
 	$(if $(VBOX_WITH_DRAG_AND_DROP_GH),VBOX_WITH_DRAG_AND_DROP_GH,) \
 	$(if $(VBOX_WITH_CROGL),VBOX_WITH_CROGL,) \
+	$(if $(VBOX_WITH_CRHGSMI),VBOX_WITH_CRHGSMI,) \
 	$(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,) \
 	$(if $(VBOX_WITH_GUEST_PROPS_RDONLY_GUEST),VBOX_WITH_GUEST_PROPS_RDONLY_GUEST,) \
 	$(if $(VBOX_WITH_GUEST_CONTROL),VBOX_WITH_GUEST_CONTROL,) \
@@ -106,6 +109,12 @@ if "$(KBUILD_TARGET)" != "win"
 	$(VBOX_IDL_HEADER.XPCOM) \
 	$(VBOX_IDL_TYPELIB.XPCOM)
 
+ INSTALLS += VBox-xpcom-bindings-lib
+ VBox-xpcom-bindings-lib_INST = $(INST_SDK)bindings/xpcom/lib/
+ VBox-xpcom-bindings-lib_MODE = a+r,u+w
+ VBox-xpcom-bindings-lib_SOURCES = $(VBoxCOM_0_OUTDIR)/VirtualBox_XPCOM_i.c=>VirtualBox_i.c
+ VBox-xpcom-bindings-lib_CLEAN = $(VBoxCOM_0_OUTDIR)/VirtualBox_XPCOM_i.c
+
  VBOX_MAIN_PREREQS += $(VBOX_IDL_TYPELIB.XPCOM) $(VBOX_IDL_HEADER.XPCOM)
  BLDDIRS += \
 	$(VBOX_PATH_SDK)/bindings/xpcom/idl \
@@ -268,7 +277,9 @@ VBoxSVC_DEFS = \
 	$(if $(VBOX_WITH_VUSB),VBOX_WITH_VUSB,) \
 	$(if $(VBOX_WITH_S3),VBOX_WITH_S3,) \
 	$(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH,) \
-	$(if $(VBOX_WITH_NAT_SERVICE),VBOX_WITH_NAT_SERVICE,)
+	$(if $(VBOX_WITH_NAT_SERVICE),VBOX_WITH_NAT_SERVICE,) \
+	$(if $(VBOX_WITH_CROGL),VBOX_WITH_CROGL,) \
+	$(if $(VBOX_WITH_CRHGSMI),VBOX_WITH_CRHGSMI,)
 ifdef VBOX_WITH_USB
  VBoxSVC_DEFS += \
 	VBOX_WITH_USB \
@@ -377,6 +388,10 @@ VBoxSVC_SOURCES = \
 	$(VBOX_AUTOGEN_EVENT_CPP) \
 	$(if $(VBOX_WITH_XPCOM),src-server/xpcom/server.cpp,)
 
+ifn1of ($(KBUILD_TARGET), win darwin) 
+	VBoxSVC_SOURCES += $(PATH_ROOT)/src/VBox/Devices/Network/slirp/resolv_conf_parser.c
+endif
+
 VBoxSVC_SOURCES.darwin = \
 	src-server/darwin/iokit.cpp \
 	src-server/darwin/HostPowerDarwin.cpp \
@@ -824,10 +839,11 @@ VBoxCOM_INCS          += \
 ifeq ($(KBUILD_TARGET),win)
  VBoxCOM_DEFS.x86       = _WIN32_WINNT=0x0500
  VBoxCOM_DEFS.amd64     = _WIN32_WINNT=0x0510
- VBoxCOM_SOURCES.win    = \
+ VBoxCOM_SOURCES       += \
 	$(VBoxCOM_0_OUTDIR)/VirtualBox_i.c
 else # !win
  VBoxCOM_SOURCES       += \
+	$(VBoxCOM_0_OUTDIR)/VirtualBox_XPCOM_i.c \
 	glue/xpcom/helpers.cpp
 endif # !win
 
@@ -840,8 +856,6 @@ ifdef VBOX_WITH_32_ON_64_MAIN_API
  LIBRARIES += VBoxCOM-x86
  VBoxCOM-x86_TEMPLATE = VBoxMainLib-x86
  VBoxCOM-x86_EXTENDS  = VBoxCOM
- VBoxCOM-x86_SOURCES.win    = \
-	$(VBoxCOM-x86_0_OUTDIR)/VirtualBox_i.c
 endif
 
 
@@ -930,7 +944,7 @@ $(VBOX_IDL_FILE.MSCOM): $(VBOX_PATH_MAIN_SRC)/idl/midl.xsl $(VBOX_XIDL_FILE) | $
 
 # Aliases for testing purposes.
 ifdef VBOX_WITH_XPCOM
-testidl:    $(VBOX_IDL_FILE.XPCOM) $(VBOX_IDL_TYPELIB.XPCOM)
+testidl:    $(VBOX_IDL_FILE.XPCOM) $(VBOX_IDL_TYPELIB.XPCOM) $(VBoxCOM_0_OUTDIR)/VirtualBox_XPCOM_i.c
 testidlhdr: $(VBOX_IDL_HEADER.XPCOM)
 else
 testidl:    $(VBOX_IDL_FILE.MSCOM) $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
@@ -938,6 +952,10 @@ testidl:    $(VBOX_IDL_FILE.MSCOM) $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
 endif
 
 
+$(VBoxCOM_0_OUTDIR)/VirtualBox_XPCOM_i.c: $(VBOX_PATH_MAIN_SRC)/idl/xpidl_iid.xsl $(VBOX_XIDL_FILE) | $$(dir $$@)
+	$(call MSG_TOOL,xsltproc,VBoxSVC,$<,$@)
+	$(QUIET)$(VBOX_XSLTPROC) -o $@ $< $(VBOX_XIDL_FILE)
+
 $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
 + $(VBoxCOM_0_OUTDIR)/VirtualBox.h \
 + $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb: $(VBOX_IDL_FILE.MSCOM) | $$(dir $$@)
diff --git a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.c b/src/VBox/Main/cbinding/LegacyVBoxXPCOMCGlue.c
similarity index 53%
copy from src/VBox/Main/cbinding/VBoxXPCOMCGlue.c
copy to src/VBox/Main/cbinding/LegacyVBoxXPCOMCGlue.c
index 0513480..3a5e698 100644
--- a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.c
+++ b/src/VBox/Main/cbinding/LegacyVBoxXPCOMCGlue.c
@@ -1,10 +1,10 @@
-/* $Revision: 90721 $ */
-/** @file
- * Glue code for dynamically linking to VBoxXPCOMC.
+/* $Revision: 91907 $ */
+/** @file VBoxXPCOMCGlue.c
+ * Glue code for dynamically linking to VBoxCAPI, LEGACY VARIANT.
  */
 
 /*
- * Copyright (C) 2008-2013 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -31,26 +31,32 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
+#include "VBoxXPCOMCGlue.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdint.h>
-#include <dlfcn.h>
-#include <pthread.h>
-
-#include "VBoxXPCOMCGlue.h"
+#ifndef WIN32
+# include <dlfcn.h>
+# include <pthread.h>
+#else /* WIN32 */
+# include <Windows.h>
+#endif /* WIN32 */
 
 
 /*******************************************************************************
 *   Defined Constants And Macros                                               *
 *******************************************************************************/
 #if defined(__linux__) || defined(__linux_gnu__) || defined(__sun__) || defined(__FreeBSD__)
-# define DYNLIB_NAME    "VBoxXPCOMC.so"
+# define DYNLIB_NAME        "VBoxXPCOMC.so"
 #elif defined(__APPLE__)
-# define DYNLIB_NAME    "VBoxXPCOMC.dylib"
-#elif defined(_MSC_VER) || defined(__OS2__)
-# define DYNLIB_NAME    "VBoxXPCOMC.dll"
+# define DYNLIB_NAME        "VBoxXPCOMC.dylib"
+#elif defined(__OS2__)
+# define DYNLIB_NAME        "VBoxXPCOMC.dll"
+#elif defined(WIN32)
+# define DYNLIB_NAME        "VBoxCAPI.dll"
 #else
 # error "Port me"
 #endif
@@ -59,25 +65,31 @@
 /*******************************************************************************
 *   Global Variables                                                           *
 *******************************************************************************/
-/** The dlopen handle for VBoxXPCOMC. */
-void *g_hVBoxXPCOMC = NULL;
+/** The so/dynsym/dll handle for VBoxCAPI. */
+#ifndef WIN32
+void *g_hVBoxCAPI = NULL;
+#else /* WIN32 */
+HMODULE g_hVBoxCAPI = NULL;
+#endif /* WIN32 */
 /** The last load error. */
-char g_szVBoxErrMsg[256];
-/** Pointer to the VBoxXPCOMC function table. */
-PCVBOXXPCOM g_pVBoxFuncs = NULL;
-/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
-PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL;
+char g_szVBoxErrMsg[256] = "";
+/** Pointer to the VBOXCAPI function table. */
+PCVBOXCAPI g_pVBoxFuncs = NULL;
+/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
+PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions = NULL;
 
 typedef void FNDUMMY(void);
 typedef FNDUMMY *PFNDUMMY;
 /** Just a dummy global structure containing a bunch of
- * function pointers to code which is wanted in the link.
- * In this case this is for helping gdb as it gets hideously
- * confused if the application doesn't drag in pthreads.
- */
-PFNDUMMY g_apfnVBoxXPCOMCGlue[] =
+ * function pointers to code which is wanted in the link. */
+PFNDUMMY g_apfnVBoxCAPIGlue[] =
 {
-    (PFNDUMMY)pthread_create
+#ifndef WIN32
+    /* The following link dependency is for helping gdb as it gets hideously
+     * confused if the application doesn't drag in pthreads, but uses it. */
+    (PFNDUMMY)pthread_create,
+#endif /* !WIN32 */
+    NULL
 };
 
 
@@ -102,21 +114,20 @@ static void setErrMsg(int fAlways, const char *pszFormat, ...)
 
 
 /**
- * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all
- * the symbols we need.
+ * Try load C API .so/dylib/dll from the specified location and resolve all
+ * the symbols we need. Tries both the new style and legacy name.
  *
  * @returns 0 on success, -1 on failure.
- * @param   pszHome         The director where to try load VBoxXPCOMC from. Can
- *                          be NULL.
+ * @param   pszHome         The directory where to try load VBoxCAPI/VBoxXPCOMC
+ *                          from. Can be NULL.
  * @param   fSetAppHome     Whether to set the VBOX_APP_HOME env.var. or not
  *                          (boolean).
  */
-static int tryLoadOne(const char *pszHome, int fSetAppHome)
+static int tryLoadLibrary(const char *pszHome, int fSetAppHome)
 {
     size_t      cchHome = pszHome ? strlen(pszHome) : 0;
     size_t      cbBufNeeded;
     char        szName[4096];
-    int         rc = -1;
 
     /*
      * Construct the full name.
@@ -142,20 +153,29 @@ static int tryLoadOne(const char *pszHome, int fSetAppHome)
      */
     if (fSetAppHome)
     {
+#ifndef WIN32
         if (pszHome)
             setenv("VBOX_APP_HOME", pszHome, 1 /* always override */);
         else
             unsetenv("VBOX_APP_HOME");
+#endif /* !WIN32 */
     }
-    g_hVBoxXPCOMC = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
-    if (g_hVBoxXPCOMC)
+
+#ifndef WIN32
+    g_hVBoxCAPI = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
+    if (g_hVBoxCAPI)
     {
-        PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions;
-        pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS)(uintptr_t)
-            dlsym(g_hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME);
+        PFNVBOXGETCAPIFUNCTIONS pfnGetFunctions;
+        pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
+            dlsym(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
+#ifdef VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME
+        if (!pfnGetFunctions)
+            pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
+                dlsym(g_hVBoxCAPI, VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME);
+#endif /* VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME */
         if (pfnGetFunctions)
         {
-            g_pVBoxFuncs = pfnGetFunctions(VBOX_XPCOMC_VERSION);
+            g_pVBoxFuncs = pfnGetFunctions(VBOX_CAPI_VERSION);
             if (g_pVBoxFuncs)
             {
                 g_pfnGetFunctions = pfnGetFunctions;
@@ -164,62 +184,113 @@ static int tryLoadOne(const char *pszHome, int fSetAppHome)
 
             /* bail out */
             setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
-                      szName, VBOX_XPCOMC_VERSION);
+                      szName, VBOX_CAPI_VERSION);
         }
         else
             setErrMsg(1, "dlsym(%.80s/%.32s): %.128s",
-                      szName, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, dlerror());
-        dlclose(g_hVBoxXPCOMC);
-        g_hVBoxXPCOMC = NULL;
+                      szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, dlerror());
+        dlclose(g_hVBoxCAPI);
+        g_hVBoxCAPI = NULL;
     }
     else
         setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror());
-    return rc;
+#else /* !WIN32 */
+    g_hVBoxCAPI = LoadLibraryExA(szName, NULL /* hFile */, 0 /* dwFlags */);
+    if (g_hVBoxCAPI)
+    {
+        PFNVBOXGETCAPIFUNCTIONS pfnGetFunctions;
+        pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)
+            GetProcAddress(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
+        if (pfnGetFunctions)
+        {
+            g_pVBoxFuncs = pfnGetFunctions(VBOX_CAPI_VERSION);
+            if (g_pVBoxFuncs)
+            {
+                g_pfnGetFunctions = pfnGetFunctions;
+                return 0;
+            }
+
+            /* bail out */
+            setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
+                      szName, VBOX_CAPI_VERSION);
+        }
+        else
+            setErrMsg(1, "GetProcAddress(%.80s/%.32s): %d",
+                      szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, GetLastError());
+        FreeLibrary(g_hVBoxCAPI);
+        g_hVBoxCAPI = NULL;
+    }
+    else
+        setErrMsg(0, "LoadLibraryEx(%.80s): %d", szName, GetLastError());
+#endif /* !WIN32 */
+
+    return -1;
 }
 
 
 /**
- * Tries to locate and load VBoxXPCOMC.so/dylib/dll, resolving all the related
+ * Tries to locate and load VBoxCAPI.so/dylib/dll, resolving all the related
  * function pointers.
  *
  * @returns 0 on success, -1 on failure.
  *
  * @remark  This should be considered moved into a separate glue library since
- *          its its going to be pretty much the same for any user of VBoxXPCOMC
+ *          its its going to be pretty much the same for any user of VBoxCAPI
  *          and it will just cause trouble to have duplicate versions of this
  *          source code all around the place.
  */
 int VBoxCGlueInit(void)
 {
+    const char *pszHome;
+
+    memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
+
     /*
      * If the user specifies the location, try only that.
      */
-    const char *pszHome = getenv("VBOX_APP_HOME");
+    pszHome = getenv("VBOX_APP_HOME");
     if (pszHome)
-        return tryLoadOne(pszHome, 0);
+        return tryLoadLibrary(pszHome, 0);
 
     /*
      * Try the known standard locations.
      */
-    g_szVBoxErrMsg[0] = '\0';
 #if defined(__gnu__linux__) || defined(__linux__)
-    if (tryLoadOne("/opt/VirtualBox", 1) == 0)
+    if (tryLoadLibrary("/opt/VirtualBox", 1) == 0)
         return 0;
-    if (tryLoadOne("/usr/lib/virtualbox", 1) == 0)
+    if (tryLoadLibrary("/usr/lib/virtualbox", 1) == 0)
         return 0;
 #elif defined(__sun__)
-    if (tryLoadOne("/opt/VirtualBox/amd64", 1) == 0)
+    if (tryLoadLibrary("/opt/VirtualBox/amd64", 1) == 0)
         return 0;
-    if (tryLoadOne("/opt/VirtualBox/i386", 1) == 0)
+    if (tryLoadLibrary("/opt/VirtualBox/i386", 1) == 0)
         return 0;
 #elif defined(__APPLE__)
-    if (tryLoadOne("/Application/VirtualBox.app/Contents/MacOS", 1) == 0)
+    if (tryLoadLibrary("/Application/VirtualBox.app/Contents/MacOS", 1) == 0)
         return 0;
 #elif defined(__FreeBSD__)
-    if (tryLoadOne("/usr/local/lib/virtualbox", 1) == 0)
+    if (tryLoadLibrary("/usr/local/lib/virtualbox", 1) == 0)
         return 0;
 #elif defined(__OS2__)
-    if (tryLoadOne("C:/Apps/VirtualBox", 1) == 0)
+    if (tryLoadLibrary("C:/Apps/VirtualBox", 1) == 0)
+        return 0;
+#elif defined(WIN32)
+    pszHome = getenv("ProgramFiles");
+    if (pszHome)
+    {
+        char szPath[4096];
+        size_t cb = sizeof(szPath);
+        char *tmp = szPath;
+        strncpy(tmp, pszHome, cb);
+        tmp[cb - 1] = '\0';
+        cb -= strlen(tmp);
+        tmp += strlen(tmp);
+        strncpy(tmp, "/Oracle/VirtualBox", cb);
+        tmp[cb - 1] = '\0';
+        if (tryLoadLibrary(szPath, 1) == 0)
+            return 0;
+    }
+    if (tryLoadLibrary("C:/Program Files/Oracle/VirtualBox", 1) == 0)
         return 0;
 #else
 # error "port me"
@@ -228,7 +299,7 @@ int VBoxCGlueInit(void)
     /*
      * Finally try the dynamic linker search path.
      */
-    if (tryLoadOne(NULL, 1) == 0)
+    if (tryLoadLibrary(NULL, 1) == 0)
         return 0;
 
     /* No luck, return failure. */
@@ -241,12 +312,16 @@ int VBoxCGlueInit(void)
  */
 void VBoxCGlueTerm(void)
 {
-    if (g_hVBoxXPCOMC)
+    if (g_hVBoxCAPI)
     {
 #if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
-        dlclose(g_hVBoxXPCOMC);
+#ifndef WIN32
+        dlclose(g_hVBoxCAPI);
+#else
+        FreeLibrary(g_hVBoxCAPI);
+#endif
 #endif
-        g_hVBoxXPCOMC = NULL;
+        g_hVBoxCAPI = NULL;
     }
     g_pVBoxFuncs = NULL;
     g_pfnGetFunctions = NULL;
diff --git a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in b/src/VBox/Main/cbinding/LegacyVBoxXPCOMCGlue.h
similarity index 69%
copy from src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in
copy to src/VBox/Main/cbinding/LegacyVBoxXPCOMCGlue.h
index 7a1e9cc..a6670fa 100644
--- a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in
+++ b/src/VBox/Main/cbinding/LegacyVBoxXPCOMCGlue.h
@@ -1,10 +1,10 @@
-/* $Revision: 75934 $ */
+/* $Revision: 91907 $ */
 /** @file VBoxXPCOMCGlue.h
- * Glue for dynamically linking with VBoxXPCOMC.
+ * Glue for dynamically linking with VBoxCAPI, LEGACY VARIANT.
  */
 
 /*
- * Copyright (C) 2008-2012 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -28,23 +28,28 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef ___VBoxXPCOMC_cglue_h
-#define ___VBoxXPCOMC_cglue_h
+#ifndef ___VBoxXPCOMCGlue_h
+#define ___VBoxXPCOMCGlue_h
 
-#include "VBoxCAPI_v at VBOX_API_VERSION@.h"
+#undef VBOX_WITH_GLUE
+#include "VBoxCAPI_v4_3.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/** The dlopen handle for VBoxXPCOMC. */
-extern void *g_hVBoxXPCOMC;
+/** The so/dynsym/dll handle for VBoxCAPI. */
+#ifndef WIN32
+extern void *g_hVBoxCAPI;
+#else
+extern HMODULE g_hVBoxCAPI;
+#endif
 /** The last load error. */
 extern char g_szVBoxErrMsg[256];
-/** Pointer to the VBoxXPCOMC function table. */
-extern PCVBOXXPCOM g_pVBoxFuncs;
-/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
-extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
+/** Pointer to the VBOXCAPI function table. */
+extern PCVBOXCAPI g_pVBoxFuncs;
+/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
+extern PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions;
 
 
 int VBoxCGlueInit(void);
diff --git a/src/VBox/Main/cbinding/Makefile.kmk b/src/VBox/Main/cbinding/Makefile.kmk
index fb80762..e84dfcb 100644
--- a/src/VBox/Main/cbinding/Makefile.kmk
+++ b/src/VBox/Main/cbinding/Makefile.kmk
@@ -4,7 +4,7 @@
 #
 
 #
-# Copyright (C) 2009-2013 Oracle Corporation
+# Copyright (C) 2009-2014 Oracle Corporation
 #
 # This file is part of VirtualBox Open Source Edition (OSE), as
 # available from http://www.virtualbox.org. This file is free software;
@@ -19,30 +19,29 @@ SUB_DEPTH = ../../../..
 include $(KBUILD_PATH)/subheader.kmk
 
 
-if defined(VBOX_WITH_XPCOM) || defined(VBOX_ONLY_SDK)
 #
 # The samples
 #
-INSTALLS += XpComCSamples
-XpComCSamples_MODE = a+r,u+rw
-XpComCSamples_INST = \
-	$(INST_SDK)bindings/xpcom/cbinding/samples/
-XpComCSamples_SOURCES = \
-	tstXPCOMCGlue.c \
-	makefile.tstXPCOMCGlue=>Makefile
-
-INSTALLS += XpComCGlue
-XpComCGlue_MODE = a+r,u+rw
-XpComCGlue_INST = \
-	$(INST_SDK)bindings/xpcom/cbinding/
-XpComCGlue_SOURCES = \
-	VBoxXPCOMCGlue.c \
-	$(XpComCHeaders_0_OUTDIR)/VBoxXPCOMCGlue.h
-
-INSTALLS += XpComCHeaders
-XpComCHeaders_MODE = a+r,u+rw
-XpComCHeaders_INST = $(INST_SDK)bindings/xpcom/include/
-XpComCHeaders_SOURCES = \
+INSTALLS += CAPISamples
+CAPISamples_MODE = a+r,u+rw
+CAPISamples_INST = \
+	$(INST_SDK)bindings/c/samples/
+CAPISamples_SOURCES = \
+	tstCAPIGlue.c \
+	makefile.tstCAPIGlue=>Makefile
+
+INSTALLS += CAPIGlue
+CAPIGlue_MODE = a+r,u+rw
+CAPIGlue_INST = \
+	$(INST_SDK)bindings/c/glue/
+CAPIGlue_SOURCES = \
+	VBoxCAPIGlue.c \
+	$(CAPIHeaders_0_OUTDIR)/VBoxCAPIGlue.h
+
+INSTALLS += CAPIHeaders
+CAPIHeaders_MODE = a+r,u+rw
+CAPIHeaders_INST = $(INST_SDK)bindings/c/include/
+CAPIHeaders_SOURCES = \
 	VBoxCAPI_v2_2.h \
 	VBoxCAPI_v3_0.h \
 	VBoxCAPI_v3_1.h \
@@ -50,10 +49,10 @@ XpComCHeaders_SOURCES = \
 	VBoxCAPI_v4_0.h \
 	VBoxCAPI_v4_1.h \
 	VBoxCAPI_v4_2.h \
-	$(XpComCHeaders_0_OUTDIR)/VBoxCAPI.h=>VBoxCAPI_v$(VBOX_API_VERSION).h
+	$(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h=>VBoxCAPI_v$(VBOX_API_VERSION).h
 
-$$(XpComCHeaders_0_OUTDIR)/VBoxXPCOMCGlue.h: \
-		$(PATH_SUB_CURRENT)/VBoxXPCOMCGlue.h.in \
+$$(CAPIHeaders_0_OUTDIR)/VBoxCAPIGlue.h: \
+		$(PATH_SUB_CURRENT)/VBoxCAPIGlue.h.in \
 		$(MAKEFILE_CURRENT) \
 		| $$(dir $$@)
 	$(call MSG_GENERATE,,$@)
@@ -61,62 +60,103 @@ $$(XpComCHeaders_0_OUTDIR)/VBoxXPCOMCGlue.h: \
 		-e 's/@VBOX_API_VERSION@/$(VBOX_API_VERSION)/' \
 		<  $< >  $@
 
-$$(XpComCHeaders_0_OUTDIR)/VBoxCAPI.h: \
-		$(PATH_SUB_CURRENT)/xpcidl.xsl \
+$$(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h: \
+		$(PATH_SUB_CURRENT)/capiidl.xsl \
 		$(VBOX_XIDL_FILE) \
 		| $$(dir $$@)
-	$(call MSG_TOOL,xsltproc,XpComCHeaders,$<,$@)
+	$(call MSG_TOOL,xsltproc,CAPIHeaders,$<,$@)
 	$(QUIET)$(VBOX_XSLTPROC) -o $@ $^
 
-endif # VBOX_WITH_XPCOM || SDK
-if !defined(VBOX_ONLY_SDK) && defined(VBOX_WITH_XPCOM)
+# Additional legacy install, to keep compatibility with older 4.3 SDK packages,
+# to avoid breaking 3rd party code in the middle of the 4.3 release.
+INSTALLS += LegacyXPCOMCGlue
+LegacyXPCOMCGlue_MODE = a+r,u+rw
+LegacyXPCOMCGlue_INST = \
+	$(INST_SDK)bindings/xpcom/cbinding/
+LegacyXPCOMCGlue_SOURCES = \
+	LegacyVBoxXPCOMCGlue.c=>VBoxXPCOMCGlue.c \
+	LegacyVBoxXPCOMCGlue.h=>VBoxXPCOMCGlue.h
+
+# Additional legacy install, to keep compatibility with older 4.3 SDK packages,
+# to avoid breaking 3rd party code in the middle of the 4.3 release.
+INSTALLS += LegacyXPCOMCHeaders
+LegacyXPCOMCHeaders_MODE = a+r,u+rw
+LegacyXPCOMCHeaders_INST = $(INST_SDK)bindings/xpcom/include/
+LegacyXPCOMCHeaders_SOURCES = \
+	VBoxCAPI_v2_2.h \
+	VBoxCAPI_v3_0.h \
+	VBoxCAPI_v3_1.h \
+	VBoxCAPI_v3_2.h \
+	VBoxCAPI_v4_0.h \
+	VBoxCAPI_v4_1.h \
+	VBoxCAPI_v4_2.h \
+	$(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h=>VBoxCAPI_v$(VBOX_API_VERSION).h
+
+if !defined(VBOX_ONLY_SDK)
 
  #
- # The C utility DLL
+ # The C API binding utility DLL
  #
+ DLLS += VBoxCAPI
+ VBoxCAPI_TEMPLATE = VBOXMAINCLIENTDLL
  ifdef VBOX_WITH_XPCOM
- DLLS += VBoxXPCOMC
- VBoxXPCOMC_TEMPLATE = VBOXMAINDLL
- VBoxXPCOMC_DEFS = IN_VBOXXPCOMC
- VBoxXPCOMC_SOURCES = \
- 	VBoxXPCOMC.cpp
- VBoxXPCOMC_INCS = \
-  	$(XpComCHeaders_0_OUTDIR)
- VBoxXPCOMC_INTERMEDIATES = \
- 	$(XpComCHeaders_0_OUTDIR)/VBoxCAPI.h
+  # Keep old name on XPCOM so that legacy code is happy.
+  VBoxCAPI_INST = $(INST_BIN)VBoxXPCOMC$(VBOX_SUFF_DLL)
  endif
+ VBoxCAPI_DEFS = IN_VBOXCAPI
+ VBoxCAPI_SOURCES = \
+ 	VBoxCAPI.cpp
+ VBoxCAPI_INCS = \
+ 	$(CAPIHeaders_0_OUTDIR)
+ VBoxCAPI_INTERMEDIATES = \
+ 	$(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h
 
  #
  # The C glue library.
  #
- LIBRARIES += VBoxXPCOMCGlue
- VBoxXPCOMCGlue_TEMPLATE = VBOXMAINEXE
- VBoxXPCOMCGlue_DEFS = IN_VBOXXPCOMC
- VBoxXPCOMCGlue_SOURCES = \
- 	VBoxXPCOMCGlue.c
- VBoxXPCOMCGlue_INCS = \
-  	$(VBOX_PATH_SDK)/bindings/xpcom/cbinding
- VBoxXPCOMCGlue_INTERMEDIATES = \
- 	$(VBOX_PATH_SDK)/bindings/xpcom/cbinding/VBoxXPCOMCGlue.h \
- 	$(VBOX_PATH_SDK)/bindings/xpcom/include/VBoxCAPI_v$(VBOX_API_VERSION).h
+ LIBRARIES += VBoxCAPIGlue
+ VBoxCAPIGlue_TEMPLATE = VBOXMAINEXE
+ VBoxCAPIGlue_DEFS = IN_VBOXCAPI
+ VBoxCAPIGlue_SOURCES = \
+ 	VBoxCAPIGlue.c
+ ifdef VBOX_WITH_XPCOM
+  VBoxCAPIGlue_SOURCES += \
+ 	$(VBOX_PATH_SDK)/bindings/xpcom/lib/VirtualBox_i.c
+ else
+  VBoxCAPIGlue_SOURCES += \
+ 	$(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c
+ endif
+ VBoxCAPIGlue_INCS = \
+ 	$(VBOX_PATH_SDK)/bindings/c/include \
+ 	$(VBOX_PATH_SDK)/bindings/c/glue
+ VBoxCAPIGlue_INTERMEDIATES = \
+ 	$(VBOX_PATH_SDK)/bindings/c/glue/VBoxCAPIGlue.h \
+ 	$(VBOX_PATH_SDK)/bindings/c/include/VBoxCAPI_v$(VBOX_API_VERSION).h
 
  if defined(VBOX_WITH_TESTCASES) && "$(KBUILD_TARGET)" != "darwin"
   #
   # The testcase (also in samples).
   # C testcase using the dynamic glue.
   #
-  PROGRAMS += tstXPCOMCGlue
-  tstXPCOMCGlue_TEMPLATE = VBOXR3TSTEXE
-  tstXPCOMCGlue_INCS = \
-  	$(VBOX_PATH_SDK)/bindings/xpcom/include \
-  	$(VBOX_PATH_SDK)/bindings/xpcom/cbinding
-  tstXPCOMCGlue_INTERMEDIATES = \
-  	$(VBOX_PATH_SDK)/bindings/xpcom/cbinding/VBoxXPCOMCGlue.h \
-  	$(VBOX_PATH_SDK)/bindings/xpcom/include/VBoxCAPI_v$(VBOX_API_VERSION).h
-  tstXPCOMCGlue_SOURCES = \
-  	tstXPCOMCGlue.c
-  tstXPCOMCGlue_LIBS = \
-  	$(VBoxXPCOMCGlue_1_TARGET)
+  PROGRAMS += tstCAPIGlue
+  tstCAPIGlue_TEMPLATE = VBOXR3TSTEXE
+  tstCAPIGlue_INCS = \
+  	$(VBOX_PATH_SDK)/bindings/c/include \
+  	$(VBOX_PATH_SDK)/bindings/c/glue
+  ifdef VBOX_WITH_XPCOM
+   tstCAPIGlue_INCS += \
+   	$(VBOX_PATH_SDK)/bindings/xpcom/include
+  else
+   tstCAPIGlue_INCS += \
+   	$(VBOX_PATH_SDK)/bindings/mscom/include
+  endif
+  tstCAPIGlue_INTERMEDIATES = \
+  	$(VBOX_PATH_SDK)/bindings/c/glue/VBoxCAPIGlue.h \
+  	$(VBOX_PATH_SDK)/bindings/c/include/VBoxCAPI_v$(VBOX_API_VERSION).h
+  tstCAPIGlue_SOURCES = \
+  	tstCAPIGlue.c
+  tstCAPIGlue_LIBS = \
+  	$(VBoxCAPIGlue_1_TARGET)
  endif
 
 endif # ! VBOX_ONLY_SDK
diff --git a/src/VBox/Main/cbinding/VBoxCAPI.cpp b/src/VBox/Main/cbinding/VBoxCAPI.cpp
new file mode 100644
index 0000000..094d4e4
--- /dev/null
+++ b/src/VBox/Main/cbinding/VBoxCAPI.cpp
@@ -0,0 +1,924 @@
+/* $Id: VBoxCAPI.cpp $ */
+/** @file VBoxCAPI.cpp
+ * Utility functions to use with the C API binding.
+ */
+
+/*
+ * Copyright (C) 2009-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#define LOG_GROUP LOG_GROUP_MAIN
+
+#include "VBoxCAPI.h"
+
+#ifdef VBOX_WITH_XPCOM
+# include <nsMemory.h>
+# include <nsIServiceManager.h>
+# include <nsEventQueueUtils.h>
+# include <nsIExceptionService.h>
+# include <stdlib.h>
+#endif /* VBOX_WITH_XPCOM */
+
+#include <iprt/initterm.h>
+#include <iprt/string.h>
+#include <iprt/uuid.h>
+#include <iprt/env.h>
+#include <iprt/mem.h>
+#include <VBox/log.h>
+#include <VBox/version.h>
+
+#include "VBox/com/com.h"
+#include "VBox/com/NativeEventQueue.h"
+
+using namespace std;
+
+/* The following 2 object references should be eliminated once the legacy
+ * way to initialize the COM/XPCOM C bindings is removed. */
+static ISession            *g_Session           = NULL;
+static IVirtualBox         *g_VirtualBox        = NULL;
+
+#ifdef VBOX_WITH_XPCOM
+/* This object reference should be eliminated once the legacy way of handling
+ * the event queue (XPCOM specific) is removed. */
+static nsIEventQueue       *g_EventQueue        = NULL;
+#endif /* VBOX_WITH_XPCOM */
+
+static void VBoxComUninitialize(void);
+static void VBoxClientUninitialize(void);
+
+static int
+VBoxUtf16ToUtf8(CBSTR pwszString, char **ppszString)
+{
+    if (!pwszString)
+    {
+        *ppszString = NULL;
+        return VINF_SUCCESS;
+    }
+    return RTUtf16ToUtf8(pwszString, ppszString);
+}
+
+static int
+VBoxUtf8ToUtf16(const char *pszString, BSTR *ppwszString)
+{
+    if (!pszString)
+    {
+        *ppwszString = NULL;
+        return VINF_SUCCESS;
+    }
+#ifdef VBOX_WITH_XPCOM
+    return RTStrToUtf16(pszString, ppwszString);
+#else /* !VBOX_WITH_XPCOM */
+    PRTUTF16 pwsz;
+    int vrc = RTStrToUtf16(pszString, &pwsz);
+    *ppwszString = ::SysAllocString(pwsz);
+    RTUtf16Free(pwsz);
+    return vrc;
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static void
+VBoxUtf16Free(BSTR pwszString)
+{
+#ifdef VBOX_WITH_XPCOM
+    RTUtf16Free(pwszString);
+#else /* !VBOX_WITH_XPCOM */
+    ::SysFreeString(pwszString);
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static void
+VBoxUtf8Free(char *pszString)
+{
+    RTStrFree(pszString);
+}
+
+static void
+VBoxComUnallocString(BSTR pwsz)
+{
+    if (pwsz)
+    {
+#ifdef VBOX_WITH_XPCOM
+        nsMemory::Free(pwsz);
+#else /* !VBOX_WITH_XPCOM */
+        ::SysFreeString(pwsz);
+#endif /* !VBOX_WITH_XPCOM */
+    }
+}
+
+static void
+VBoxComUnallocMem(void *pv)
+{
+    VBoxComUnallocString((BSTR)pv);
+}
+
+static ULONG
+VBoxVTElemSize(VARTYPE vt)
+{
+    switch (vt)
+    {
+        case VT_BOOL:
+        case VT_I1:
+        case VT_UI1:
+            return 1;
+        case VT_I2:
+        case VT_UI2:
+            return 2;
+        case VT_I4:
+        case VT_UI4:
+        case VT_HRESULT:
+            return 4;
+        case VT_I8:
+        case VT_UI8:
+            return 8;
+        case VT_BSTR:
+        case VT_DISPATCH:
+        case VT_UNKNOWN:
+            return sizeof(void *);
+        default:
+            return 0;
+    }
+}
+
+static SAFEARRAY *
+VBoxSafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
+{
+#ifdef VBOX_WITH_XPCOM
+    NOREF(lLbound);
+    ULONG cbElement = VBoxVTElemSize(vt);
+    if (!cbElement)
+        return NULL;
+    SAFEARRAY *psa = (SAFEARRAY *)RTMemAllocZ(sizeof(SAFEARRAY));
+    if (!psa)
+        return psa;
+    if (cElements)
+    {
+        void *pv = nsMemory::Alloc(cElements * cbElement);
+        if (!pv)
+        {
+            RTMemFree(psa);
+            return NULL;
+        }
+        psa->pv = pv;
+        psa->c = cElements;
+    }
+    return psa;
+#else /* !VBOX_WITH_XPCOM */
+    return SafeArrayCreateVector(vt, lLbound, cElements);
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static SAFEARRAY *
+VBoxSafeArrayOutParamAlloc(void)
+{
+#ifdef VBOX_WITH_XPCOM
+    return (SAFEARRAY *)RTMemAllocZ(sizeof(SAFEARRAY));
+#else /* !VBOX_WITH_XPCOM */
+    return NULL;
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static HRESULT
+VBoxSafeArrayDestroy(SAFEARRAY *psa)
+{
+#ifdef VBOX_WITH_XPCOM
+    if (psa)
+    {
+        if (psa->pv)
+            nsMemory::Free(psa->pv);
+        RTMemFree(psa);
+    }
+    return S_OK;
+#else /* !VBOX_WITH_XPCOM */
+    return SafeArrayDestroy(psa);
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static HRESULT
+VBoxSafeArrayCopyInParamHelper(SAFEARRAY *psa, const void *pv, ULONG cb)
+{
+    if (!pv || !psa)
+        return E_POINTER;
+    if (!cb)
+        return S_OK;
+
+    void *pData;
+#ifdef VBOX_WITH_XPCOM
+    pData = psa->pv;
+#else /* !VBOX_WITH_XPCOM */
+    HRESULT rc = SafeArrayAccessData(psa, &pData);
+    if (FAILED(rc))
+        return rc;
+#endif /* !VBOX_WITH_XPCOM */
+    memcpy(pData, pv, cb);
+#ifndef VBOX_WITH_XPCOM
+    SafeArrayUnaccessData(psa);
+#endif /* !VBOX_WITH_XPCOM */
+    return S_OK;
+}
+
+static HRESULT
+VBoxSafeArrayCopyOutParamHelper(void **ppv, ULONG *pcb, VARTYPE vt, SAFEARRAY *psa)
+{
+    if (!ppv)
+        return E_POINTER;
+    ULONG cbElement = VBoxVTElemSize(vt);
+    if (!cbElement)
+        return E_INVALIDARG;
+#ifndef VBOX_WITH_XPCOM
+    if (psa->cDims != 1)
+        return E_INVALIDARG;
+    Assert(cbElement = psa->cbElements);
+#endif /* !VBOX_WITH_XPCOM */
+    void *pData;
+    ULONG cElements;
+#ifdef VBOX_WITH_XPCOM
+    pData = psa->pv;
+    cElements = psa->c;
+#else /* !VBOX_WITH_XPCOM */
+    HRESULT rc = SafeArrayAccessData(psa, &pData);
+    if (FAILED(rc))
+        return rc;
+    cElements = psa->rgsabound[0].cElements;
+#endif /* !VBOX_WITH_XPCOM */
+    size_t cbTotal = cbElement * cElements;
+    void *pv = malloc(cbTotal);
+    if (pv)
+    {
+        memcpy(pv, pData, cbTotal);
+        *ppv = pv;
+        if (pcb)
+            *pcb = (ULONG)cbTotal;
+    }
+#ifndef VBOX_WITH_XPCOM
+    SafeArrayUnaccessData(psa);
+#endif /* !VBOX_WITH_XPCOM */
+    return S_OK;
+}
+
+static HRESULT
+VBoxSafeArrayCopyOutIfaceParamHelper(IUnknown ***ppaObj, ULONG *pcObj, SAFEARRAY *psa)
+{
+    ULONG mypcb;
+    HRESULT rc = VBoxSafeArrayCopyOutParamHelper((void **)ppaObj, &mypcb, VT_UNKNOWN, psa);
+    if (FAILED(rc))
+        return rc;
+    ULONG cElements = mypcb / sizeof(void *);
+    if (pcObj)
+        *pcObj = cElements;
+#ifndef VBOX_WITH_XPCOM
+    /* Do this only for COM, as there the SAFEARRAY destruction will release
+     * the contained references automatically. XPCOM doesn't do that, which
+     * means that copying implicitly transfers ownership. */
+    IUnknown **paObj = *ppaObj;
+    for (ULONG i = 0; i < cElements; i++)
+    {
+        IUnknown *pObj = paObj[i];
+        if (pObj)
+            pObj->AddRef();
+    }
+#endif /* VBOX_WITH_XPCOM */
+    return S_OK;
+}
+
+static void
+VBoxComInitialize(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
+                  const char *pszSessionIID, ISession **ppSession)
+{
+    int vrc;
+    IID virtualBoxIID;
+    IID sessionIID;
+
+    *ppSession    = NULL;
+    *ppVirtualBox = NULL;
+
+    /* convert the string representation of the UUIDs (if provided) to IID */
+    if (pszVirtualBoxIID && *pszVirtualBoxIID)
+    {
+        vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxIID, pszVirtualBoxIID);
+        if (RT_FAILURE(vrc))
+            return;
+    }
+    else
+        virtualBoxIID = IID_IVirtualBox;
+    if (pszSessionIID && *pszSessionIID)
+    {
+        vrc = ::RTUuidFromStr((RTUUID *)&sessionIID, pszSessionIID);
+        if (RT_FAILURE(vrc))
+            return;
+    }
+    else
+        sessionIID = IID_ISession;
+
+    HRESULT rc = com::Initialize();
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: COM/XPCOM could not be initialized! rc=%Rhrc\n", rc));
+        VBoxComUninitialize();
+        return;
+    }
+
+#ifdef VBOX_WITH_XPCOM
+    rc = NS_GetMainEventQ(&g_EventQueue);
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: Could not get XPCOM event queue! rc=%Rhrc\n", rc));
+        VBoxComUninitialize();
+        return;
+    }
+#endif /* VBOX_WITH_XPCOM */
+
+#ifdef VBOX_WITH_XPCOM
+    nsIComponentManager *pManager;
+    rc = NS_GetComponentManager(&pManager);
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
+        VBoxComUninitialize();
+        return;
+    }
+
+    rc = pManager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
+                                              nsnull,
+                                              virtualBoxIID,
+                                              (void **)&g_VirtualBox);
+#else /* !VBOX_WITH_XPCOM */
+    rc = CoCreateInstance(CLSID_VirtualBox, NULL, CLSCTX_LOCAL_SERVER, virtualBoxIID, (void **)&g_VirtualBox);
+#endif /* !VBOX_WITH_XPCOM */
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: Could not instantiate VirtualBox object! rc=%Rhrc\n",rc));
+#ifdef VBOX_WITH_XPCOM
+        pManager->Release();
+        pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+        VBoxComUninitialize();
+        return;
+    }
+
+    Log(("Cbinding: IVirtualBox object created.\n"));
+
+#ifdef VBOX_WITH_XPCOM
+    rc = pManager->CreateInstanceByContractID(NS_SESSION_CONTRACTID,
+                                              nsnull,
+                                              sessionIID,
+                                              (void **)&g_Session);
+#else /* !VBOX_WITH_XPCOM */
+    rc = CoCreateInstance(CLSID_Session, NULL, CLSCTX_INPROC_SERVER, sessionIID, (void **)&g_Session);
+#endif /* !VBOX_WITH_XPCOM */
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: Could not instantiate Session object! rc=%Rhrc\n",rc));
+#ifdef VBOX_WITH_XPCOM
+        pManager->Release();
+        pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+        VBoxComUninitialize();
+        return;
+    }
+
+    Log(("Cbinding: ISession object created.\n"));
+
+#ifdef VBOX_WITH_XPCOM
+    pManager->Release();
+    pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+
+    *ppSession = g_Session;
+    *ppVirtualBox = g_VirtualBox;
+}
+
+static void
+VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
+{
+    VBoxComInitialize(NULL, ppVirtualBox, NULL, ppSession);
+}
+
+static void
+VBoxComUninitialize(void)
+{
+    if (g_Session)
+    {
+        g_Session->Release();
+        g_Session = NULL;
+    }
+    if (g_VirtualBox)
+    {
+        g_VirtualBox->Release();
+        g_VirtualBox = NULL;
+    }
+#ifdef VBOX_WITH_XPCOM
+    if (g_EventQueue)
+    {
+        g_EventQueue->Release();
+        g_EventQueue = NULL;
+    }
+#endif /* VBOX_WITH_XPCOM */
+    com::Shutdown();
+    Log(("Cbinding: Cleaned up the created objects.\n"));
+}
+
+#ifdef VBOX_WITH_XPCOM
+static void
+VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
+{
+    *ppEventQueue = g_EventQueue;
+}
+#endif /* VBOX_WITH_XPCOM */
+
+static int
+VBoxProcessEventQueue(LONG64 iTimeoutMS)
+{
+    RTMSINTERVAL iTimeout;
+    if (iTimeoutMS < 0 || iTimeoutMS > UINT32_MAX)
+        iTimeout = RT_INDEFINITE_WAIT;
+    else
+        iTimeout = (RTMSINTERVAL)iTimeoutMS;
+    int vrc = com::NativeEventQueue::getMainEventQueue()->processEventQueue(iTimeout);
+    switch (vrc)
+    {
+        case VINF_SUCCESS:
+            return 0;
+        case VINF_INTERRUPTED:
+            return 1;
+        case VERR_INTERRUPTED:
+            return 2;
+        case VERR_TIMEOUT:
+            return 3;
+        case VERR_INVALID_CONTEXT:
+            return 4;
+        default:
+            return 5;
+    }
+}
+
+static int
+VBoxInterruptEventQueueProcessing(void)
+{
+    com::NativeEventQueue::getMainEventQueue()->interruptEventQueueProcessing();
+    return 0;
+}
+
+static HRESULT
+VBoxGetException(IErrorInfo **ppException)
+{
+    HRESULT rc;
+
+    *ppException = NULL;
+
+#ifdef VBOX_WITH_XPCOM
+    nsIServiceManager *mgr = NULL;
+    rc = NS_GetServiceManager(&mgr);
+    if (FAILED(rc) || !mgr)
+        return rc;
+
+    IID esid = NS_IEXCEPTIONSERVICE_IID;
+    nsIExceptionService *es = NULL;
+    rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
+    if (FAILED(rc) || !es)
+    {
+        mgr->Release();
+        return rc;
+    }
+
+    nsIExceptionManager *em;
+    rc = es->GetCurrentExceptionManager(&em);
+    if (FAILED(rc) || !em)
+    {
+        es->Release();
+        mgr->Release();
+        return rc;
+    }
+
+    nsIException *ex;
+    rc = em->GetCurrentException(&ex);
+    if (FAILED(rc))
+    {
+        em->Release();
+        es->Release();
+        mgr->Release();
+        return rc;
+    }
+
+    *ppException = ex;
+    em->Release();
+    es->Release();
+    mgr->Release();
+#else /* !VBOX_WITH_XPCOM */
+    IErrorInfo *ex;
+    rc = ::GetErrorInfo(0, &ex);
+    if (FAILED(rc))
+        return rc;
+
+    *ppException = ex;
+#endif /* !VBOX_WITH_XPCOM */
+
+    return rc;
+}
+
+static HRESULT
+VBoxClearException(void)
+{
+    HRESULT rc;
+
+#ifdef VBOX_WITH_XPCOM
+    nsIServiceManager *mgr = NULL;
+    rc = NS_GetServiceManager(&mgr);
+    if (FAILED(rc) || !mgr)
+        return rc;
+
+    IID esid = NS_IEXCEPTIONSERVICE_IID;
+    nsIExceptionService *es = NULL;
+    rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
+    if (FAILED(rc) || !es)
+    {
+        mgr->Release();
+        return rc;
+    }
+
+    nsIExceptionManager *em;
+    rc = es->GetCurrentExceptionManager(&em);
+    if (FAILED(rc) || !em)
+    {
+        es->Release();
+        mgr->Release();
+        return rc;
+    }
+
+    rc = em->SetCurrentException(NULL);
+    em->Release();
+    es->Release();
+    mgr->Release();
+#else /* !VBOX_WITH_XPCOM */
+    rc = ::SetErrorInfo(0, NULL);
+#endif /* !VBOX_WITH_XPCOM */
+
+    return rc;
+}
+
+static HRESULT
+VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
+{
+    IID virtualBoxClientIID;
+
+    *ppVirtualBoxClient = NULL;
+
+    /* convert the string representation of UUID to IID type */
+    if (pszVirtualBoxClientIID && *pszVirtualBoxClientIID)
+    {
+        int vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxClientIID, pszVirtualBoxClientIID);
+        if (RT_FAILURE(vrc))
+            return E_INVALIDARG;
+    }
+    else
+        virtualBoxClientIID = IID_IVirtualBoxClient;
+
+    HRESULT rc = com::Initialize();
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: COM/XPCOM could not be initialized! rc=%Rhrc\n", rc));
+        VBoxClientUninitialize();
+        return rc;
+    }
+
+#ifdef VBOX_WITH_XPCOM
+    rc = NS_GetMainEventQ(&g_EventQueue);
+    if (NS_FAILED(rc))
+    {
+        Log(("Cbinding: Could not get XPCOM event queue! rc=%Rhrc\n", rc));
+        VBoxClientUninitialize();
+        return rc;
+    }
+#endif /* VBOX_WITH_XPCOM */
+
+#ifdef VBOX_WITH_XPCOM
+    nsIComponentManager *pManager;
+    rc = NS_GetComponentManager(&pManager);
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
+        VBoxClientUninitialize();
+        return rc;
+    }
+
+    rc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
+                                              nsnull,
+                                              virtualBoxClientIID,
+                                              (void **)ppVirtualBoxClient);
+#else /* !VBOX_WITH_XPCOM */
+    rc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, virtualBoxClientIID, (void **)ppVirtualBoxClient);
+#endif /* !VBOX_WITH_XPCOM */
+    if (FAILED(rc))
+    {
+        Log(("Cbinding: Could not instantiate VirtualBoxClient object! rc=%Rhrc\n",rc));
+#ifdef VBOX_WITH_XPCOM
+        pManager->Release();
+        pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+        VBoxClientUninitialize();
+        return rc;
+    }
+
+#ifdef VBOX_WITH_XPCOM
+    pManager->Release();
+    pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+
+    Log(("Cbinding: IVirtualBoxClient object created.\n"));
+
+    return S_OK;
+}
+
+static HRESULT
+VBoxClientThreadInitialize(void)
+{
+    return com::Initialize();
+}
+
+static HRESULT
+VBoxClientThreadUninitialize(void)
+{
+    return com::Shutdown();
+}
+
+static void
+VBoxClientUninitialize(void)
+{
+#ifdef VBOX_WITH_XPCOM
+    if (g_EventQueue)
+    {
+        NS_RELEASE(g_EventQueue);
+        g_EventQueue = NULL;
+    }
+#endif /* VBOX_WITH_XPCOM */
+    com::Shutdown();
+    Log(("Cbinding: Cleaned up the created objects.\n"));
+}
+
+static unsigned int
+VBoxVersion(void)
+{
+    return VBOX_VERSION_MAJOR * 1000 * 1000 + VBOX_VERSION_MINOR * 1000 + VBOX_VERSION_BUILD;
+}
+
+static unsigned int
+VBoxAPIVersion(void)
+{
+    return VBOX_VERSION_MAJOR * 1000 + VBOX_VERSION_MINOR + (VBOX_VERSION_BUILD > 50 ? 1 : 0);
+}
+
+VBOXCAPI_DECL(PCVBOXCAPI)
+VBoxGetCAPIFunctions(unsigned uVersion)
+{
+    /* This is the first piece of code which knows that IPRT exists, so
+     * initialize it properly. The limited initialization in VBoxC is not
+     * sufficient, and causes trouble with com::Initialize() misbehaving. */
+    RTR3InitDll(0);
+
+    /*
+     * The current interface version.
+     */
+    static const VBOXCAPI s_Functions =
+    {
+        sizeof(VBOXCAPI),
+        VBOX_CAPI_VERSION,
+
+        VBoxVersion,
+        VBoxAPIVersion,
+
+        VBoxClientInitialize,
+        VBoxClientThreadInitialize,
+        VBoxClientThreadUninitialize,
+        VBoxClientUninitialize,
+
+        VBoxComInitialize,
+        VBoxComUninitialize,
+
+        VBoxComUnallocString,
+
+        VBoxUtf16ToUtf8,
+        VBoxUtf8ToUtf16,
+        VBoxUtf8Free,
+        VBoxUtf16Free,
+
+        VBoxSafeArrayCreateVector,
+        VBoxSafeArrayOutParamAlloc,
+        VBoxSafeArrayCopyInParamHelper,
+        VBoxSafeArrayCopyOutParamHelper,
+        VBoxSafeArrayCopyOutIfaceParamHelper,
+        VBoxSafeArrayDestroy,
+
+#ifdef VBOX_WITH_XPCOM
+        VBoxGetEventQueue,
+#endif /* VBOX_WITH_XPCOM */
+        VBoxGetException,
+        VBoxClearException,
+        VBoxProcessEventQueue,
+        VBoxInterruptEventQueueProcessing,
+
+        VBOX_CAPI_VERSION
+    };
+
+    if ((uVersion & 0xffff0000U) == (VBOX_CAPI_VERSION & 0xffff0000U))
+        return &s_Functions;
+
+    /*
+     * Legacy interface version 3.0.
+     */
+    static const struct VBOXCAPIV3
+    {
+        /** The size of the structure. */
+        unsigned cb;
+        /** The structure version. */
+        unsigned uVersion;
+
+        unsigned int (*pfnGetVersion)(void);
+
+        unsigned int (*pfnGetAPIVersion)(void);
+
+        HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
+                                       IVirtualBoxClient **ppVirtualBoxClient);
+        void (*pfnClientUninitialize)(void);
+
+        void  (*pfnComInitialize)(const char *pszVirtualBoxIID,
+                                  IVirtualBox **ppVirtualBox,
+                                  const char *pszSessionIID,
+                                  ISession **ppSession);
+
+        void  (*pfnComUninitialize)(void);
+
+        void  (*pfnComUnallocMem)(void *pv);
+
+        int   (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+        int   (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+        void  (*pfnUtf8Free)(char *pszString);
+        void  (*pfnUtf16Free)(BSTR pwszString);
+
+#ifdef VBOX_WITH_XPCOM
+        void  (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
+#endif /* VBOX_WITH_XPCOM */
+        HRESULT (*pfnGetException)(IErrorInfo **ppException);
+        HRESULT (*pfnClearException)(void);
+
+        /** Tail version, same as uVersion. */
+        unsigned uEndVersion;
+    } s_Functions_v3_0 =
+    {
+        sizeof(s_Functions_v3_0),
+        0x00030000U,
+
+        VBoxVersion,
+        VBoxAPIVersion,
+
+        VBoxClientInitialize,
+        VBoxClientUninitialize,
+
+        VBoxComInitialize,
+        VBoxComUninitialize,
+
+        VBoxComUnallocMem,
+
+        VBoxUtf16ToUtf8,
+        VBoxUtf8ToUtf16,
+        VBoxUtf8Free,
+        VBoxUtf16Free,
+
+#ifdef VBOX_WITH_XPCOM
+        VBoxGetEventQueue,
+#endif /* VBOX_WITH_XPCOM */
+        VBoxGetException,
+        VBoxClearException,
+
+        0x00030000U
+    };
+
+    if ((uVersion & 0xffff0000U) == 0x00030000U)
+        return (PCVBOXCAPI)&s_Functions_v3_0;
+
+    /*
+     * Legacy interface version 2.0.
+     */
+    static const struct VBOXCAPIV2
+    {
+        /** The size of the structure. */
+        unsigned cb;
+        /** The structure version. */
+        unsigned uVersion;
+
+        unsigned int (*pfnGetVersion)(void);
+
+        void  (*pfnComInitialize)(const char *pszVirtualBoxIID,
+                                  IVirtualBox **ppVirtualBox,
+                                  const char *pszSessionIID,
+                                  ISession **ppSession);
+
+        void  (*pfnComUninitialize)(void);
+
+        void  (*pfnComUnallocMem)(void *pv);
+        void  (*pfnUtf16Free)(BSTR pwszString);
+        void  (*pfnUtf8Free)(char *pszString);
+
+        int   (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+        int   (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+
+#ifdef VBOX_WITH_XPCOM
+        void  (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
+#endif /* VBOX_WITH_XPCOM */
+
+        /** Tail version, same as uVersion. */
+        unsigned uEndVersion;
+    } s_Functions_v2_0 =
+    {
+        sizeof(s_Functions_v2_0),
+        0x00020000U,
+
+        VBoxVersion,
+
+        VBoxComInitialize,
+        VBoxComUninitialize,
+
+        VBoxComUnallocMem,
+        VBoxUtf16Free,
+        VBoxUtf8Free,
+
+        VBoxUtf16ToUtf8,
+        VBoxUtf8ToUtf16,
+
+#ifdef VBOX_WITH_XPCOM
+        VBoxGetEventQueue,
+#endif /* VBOX_WITH_XPCOM */
+
+        0x00020000U
+    };
+
+    if ((uVersion & 0xffff0000U) == 0x00020000U)
+        return (PCVBOXCAPI)&s_Functions_v2_0;
+
+    /*
+     * Legacy interface version 1.0.
+     */
+    static const struct VBOXCAPIV1
+    {
+        /** The size of the structure. */
+        unsigned cb;
+        /** The structure version. */
+        unsigned uVersion;
+
+        unsigned int (*pfnGetVersion)(void);
+
+        void  (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
+        void  (*pfnComUninitialize)(void);
+
+        void  (*pfnComUnallocMem)(void *pv);
+        void  (*pfnUtf16Free)(BSTR pwszString);
+        void  (*pfnUtf8Free)(char *pszString);
+
+        int   (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+        int   (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+
+        /** Tail version, same as uVersion. */
+        unsigned uEndVersion;
+    } s_Functions_v1_0 =
+    {
+        sizeof(s_Functions_v1_0),
+        0x00010000U,
+
+        VBoxVersion,
+
+        VBoxComInitializeV1,
+        VBoxComUninitialize,
+
+        VBoxComUnallocMem,
+        VBoxUtf16Free,
+        VBoxUtf8Free,
+
+        VBoxUtf16ToUtf8,
+        VBoxUtf8ToUtf16,
+
+        0x00010000U
+    };
+
+    if ((uVersion & 0xffff0000U) == 0x00010000U)
+        return (PCVBOXCAPI)&s_Functions_v1_0;
+
+    /*
+     * Unsupported interface version.
+     */
+    return NULL;
+}
+
+#ifdef VBOX_WITH_XPCOM
+VBOXCAPI_DECL(PCVBOXCAPI)
+VBoxGetXPCOMCFunctions(unsigned uVersion)
+{
+    return VBoxGetCAPIFunctions(uVersion);
+}
+#endif /* VBOX_WITH_XPCOM */
+/* vim: set ts=4 sw=4 et: */
diff --git a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.c b/src/VBox/Main/cbinding/VBoxCAPIGlue.c
similarity index 53%
rename from src/VBox/Main/cbinding/VBoxXPCOMCGlue.c
rename to src/VBox/Main/cbinding/VBoxCAPIGlue.c
index 0513480..d229a6b 100644
--- a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.c
+++ b/src/VBox/Main/cbinding/VBoxCAPIGlue.c
@@ -1,10 +1,10 @@
-/* $Revision: 90721 $ */
+/* $Revision: 91907 $ */
 /** @file
- * Glue code for dynamically linking to VBoxXPCOMC.
+ * Glue code for dynamically linking to VBoxCAPI.
  */
 
 /*
- * Copyright (C) 2008-2013 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -31,26 +31,32 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
+#include "VBoxCAPIGlue.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdint.h>
-#include <dlfcn.h>
-#include <pthread.h>
-
-#include "VBoxXPCOMCGlue.h"
+#ifndef WIN32
+# include <dlfcn.h>
+# include <pthread.h>
+#else /* WIN32 */
+# include <Windows.h>
+#endif /* WIN32 */
 
 
 /*******************************************************************************
 *   Defined Constants And Macros                                               *
 *******************************************************************************/
 #if defined(__linux__) || defined(__linux_gnu__) || defined(__sun__) || defined(__FreeBSD__)
-# define DYNLIB_NAME    "VBoxXPCOMC.so"
+# define DYNLIB_NAME        "VBoxXPCOMC.so"
 #elif defined(__APPLE__)
-# define DYNLIB_NAME    "VBoxXPCOMC.dylib"
-#elif defined(_MSC_VER) || defined(__OS2__)
-# define DYNLIB_NAME    "VBoxXPCOMC.dll"
+# define DYNLIB_NAME        "VBoxXPCOMC.dylib"
+#elif defined(__OS2__)
+# define DYNLIB_NAME        "VBoxXPCOMC.dll"
+#elif defined(WIN32)
+# define DYNLIB_NAME        "VBoxCAPI.dll"
 #else
 # error "Port me"
 #endif
@@ -59,25 +65,31 @@
 /*******************************************************************************
 *   Global Variables                                                           *
 *******************************************************************************/
-/** The dlopen handle for VBoxXPCOMC. */
-void *g_hVBoxXPCOMC = NULL;
+/** The so/dynsym/dll handle for VBoxCAPI. */
+#ifndef WIN32
+void *g_hVBoxCAPI = NULL;
+#else /* WIN32 */
+HMODULE g_hVBoxCAPI = NULL;
+#endif /* WIN32 */
 /** The last load error. */
-char g_szVBoxErrMsg[256];
-/** Pointer to the VBoxXPCOMC function table. */
-PCVBOXXPCOM g_pVBoxFuncs = NULL;
-/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
-PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL;
+char g_szVBoxErrMsg[256] = "";
+/** Pointer to the VBOXCAPI function table. */
+PCVBOXCAPI g_pVBoxFuncs = NULL;
+/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
+PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions = NULL;
 
 typedef void FNDUMMY(void);
 typedef FNDUMMY *PFNDUMMY;
 /** Just a dummy global structure containing a bunch of
- * function pointers to code which is wanted in the link.
- * In this case this is for helping gdb as it gets hideously
- * confused if the application doesn't drag in pthreads.
- */
-PFNDUMMY g_apfnVBoxXPCOMCGlue[] =
+ * function pointers to code which is wanted in the link. */
+PFNDUMMY g_apfnVBoxCAPIGlue[] =
 {
-    (PFNDUMMY)pthread_create
+#ifndef WIN32
+    /* The following link dependency is for helping gdb as it gets hideously
+     * confused if the application doesn't drag in pthreads, but uses it. */
+    (PFNDUMMY)pthread_create,
+#endif /* !WIN32 */
+    NULL
 };
 
 
@@ -102,21 +114,20 @@ static void setErrMsg(int fAlways, const char *pszFormat, ...)
 
 
 /**
- * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all
- * the symbols we need.
+ * Try load C API .so/dylib/dll from the specified location and resolve all
+ * the symbols we need. Tries both the new style and legacy name.
  *
  * @returns 0 on success, -1 on failure.
- * @param   pszHome         The director where to try load VBoxXPCOMC from. Can
- *                          be NULL.
+ * @param   pszHome         The directory where to try load VBoxCAPI/VBoxXPCOMC
+ *                          from. Can be NULL.
  * @param   fSetAppHome     Whether to set the VBOX_APP_HOME env.var. or not
  *                          (boolean).
  */
-static int tryLoadOne(const char *pszHome, int fSetAppHome)
+static int tryLoadLibrary(const char *pszHome, int fSetAppHome)
 {
     size_t      cchHome = pszHome ? strlen(pszHome) : 0;
     size_t      cbBufNeeded;
     char        szName[4096];
-    int         rc = -1;
 
     /*
      * Construct the full name.
@@ -142,20 +153,29 @@ static int tryLoadOne(const char *pszHome, int fSetAppHome)
      */
     if (fSetAppHome)
     {
+#ifndef WIN32
         if (pszHome)
             setenv("VBOX_APP_HOME", pszHome, 1 /* always override */);
         else
             unsetenv("VBOX_APP_HOME");
+#endif /* !WIN32 */
     }
-    g_hVBoxXPCOMC = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
-    if (g_hVBoxXPCOMC)
+
+#ifndef WIN32
+    g_hVBoxCAPI = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
+    if (g_hVBoxCAPI)
     {
-        PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions;
-        pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS)(uintptr_t)
-            dlsym(g_hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME);
+        PFNVBOXGETCAPIFUNCTIONS pfnGetFunctions;
+        pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
+            dlsym(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
+#ifdef VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME
+        if (!pfnGetFunctions)
+            pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
+                dlsym(g_hVBoxCAPI, VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME);
+#endif /* VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME */
         if (pfnGetFunctions)
         {
-            g_pVBoxFuncs = pfnGetFunctions(VBOX_XPCOMC_VERSION);
+            g_pVBoxFuncs = pfnGetFunctions(VBOX_CAPI_VERSION);
             if (g_pVBoxFuncs)
             {
                 g_pfnGetFunctions = pfnGetFunctions;
@@ -164,62 +184,113 @@ static int tryLoadOne(const char *pszHome, int fSetAppHome)
 
             /* bail out */
             setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
-                      szName, VBOX_XPCOMC_VERSION);
+                      szName, VBOX_CAPI_VERSION);
         }
         else
             setErrMsg(1, "dlsym(%.80s/%.32s): %.128s",
-                      szName, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, dlerror());
-        dlclose(g_hVBoxXPCOMC);
-        g_hVBoxXPCOMC = NULL;
+                      szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, dlerror());
+        dlclose(g_hVBoxCAPI);
+        g_hVBoxCAPI = NULL;
     }
     else
         setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror());
-    return rc;
+#else /* !WIN32 */
+    g_hVBoxCAPI = LoadLibraryExA(szName, NULL /* hFile */, 0 /* dwFlags */);
+    if (g_hVBoxCAPI)
+    {
+        PFNVBOXGETCAPIFUNCTIONS pfnGetFunctions;
+        pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)
+            GetProcAddress(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
+        if (pfnGetFunctions)
+        {
+            g_pVBoxFuncs = pfnGetFunctions(VBOX_CAPI_VERSION);
+            if (g_pVBoxFuncs)
+            {
+                g_pfnGetFunctions = pfnGetFunctions;
+                return 0;
+            }
+
+            /* bail out */
+            setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
+                      szName, VBOX_CAPI_VERSION);
+        }
+        else
+            setErrMsg(1, "GetProcAddress(%.80s/%.32s): %d",
+                      szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, GetLastError());
+        FreeLibrary(g_hVBoxCAPI);
+        g_hVBoxCAPI = NULL;
+    }
+    else
+        setErrMsg(0, "LoadLibraryEx(%.80s): %d", szName, GetLastError());
+#endif /* !WIN32 */
+
+    return -1;
 }
 
 
 /**
- * Tries to locate and load VBoxXPCOMC.so/dylib/dll, resolving all the related
+ * Tries to locate and load VBoxCAPI.so/dylib/dll, resolving all the related
  * function pointers.
  *
  * @returns 0 on success, -1 on failure.
  *
  * @remark  This should be considered moved into a separate glue library since
- *          its its going to be pretty much the same for any user of VBoxXPCOMC
+ *          its its going to be pretty much the same for any user of VBoxCAPI
  *          and it will just cause trouble to have duplicate versions of this
  *          source code all around the place.
  */
 int VBoxCGlueInit(void)
 {
+    const char *pszHome;
+
+    memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
+
     /*
      * If the user specifies the location, try only that.
      */
-    const char *pszHome = getenv("VBOX_APP_HOME");
+    pszHome = getenv("VBOX_APP_HOME");
     if (pszHome)
-        return tryLoadOne(pszHome, 0);
+        return tryLoadLibrary(pszHome, 0);
 
     /*
      * Try the known standard locations.
      */
-    g_szVBoxErrMsg[0] = '\0';
 #if defined(__gnu__linux__) || defined(__linux__)
-    if (tryLoadOne("/opt/VirtualBox", 1) == 0)
+    if (tryLoadLibrary("/opt/VirtualBox", 1) == 0)
         return 0;
-    if (tryLoadOne("/usr/lib/virtualbox", 1) == 0)
+    if (tryLoadLibrary("/usr/lib/virtualbox", 1) == 0)
         return 0;
 #elif defined(__sun__)
-    if (tryLoadOne("/opt/VirtualBox/amd64", 1) == 0)
+    if (tryLoadLibrary("/opt/VirtualBox/amd64", 1) == 0)
         return 0;
-    if (tryLoadOne("/opt/VirtualBox/i386", 1) == 0)
+    if (tryLoadLibrary("/opt/VirtualBox/i386", 1) == 0)
         return 0;
 #elif defined(__APPLE__)
-    if (tryLoadOne("/Application/VirtualBox.app/Contents/MacOS", 1) == 0)
+    if (tryLoadLibrary("/Application/VirtualBox.app/Contents/MacOS", 1) == 0)
         return 0;
 #elif defined(__FreeBSD__)
-    if (tryLoadOne("/usr/local/lib/virtualbox", 1) == 0)
+    if (tryLoadLibrary("/usr/local/lib/virtualbox", 1) == 0)
         return 0;
 #elif defined(__OS2__)
-    if (tryLoadOne("C:/Apps/VirtualBox", 1) == 0)
+    if (tryLoadLibrary("C:/Apps/VirtualBox", 1) == 0)
+        return 0;
+#elif defined(WIN32)
+    pszHome = getenv("ProgramFiles");
+    if (pszHome)
+    {
+        char szPath[4096];
+        size_t cb = sizeof(szPath);
+        char *tmp = szPath;
+        strncpy(tmp, pszHome, cb);
+        tmp[cb - 1] = '\0';
+        cb -= strlen(tmp);
+        tmp += strlen(tmp);
+        strncpy(tmp, "/Oracle/VirtualBox", cb);
+        tmp[cb - 1] = '\0';
+        if (tryLoadLibrary(szPath, 1) == 0)
+            return 0;
+    }
+    if (tryLoadLibrary("C:/Program Files/Oracle/VirtualBox", 1) == 0)
         return 0;
 #else
 # error "port me"
@@ -228,7 +299,7 @@ int VBoxCGlueInit(void)
     /*
      * Finally try the dynamic linker search path.
      */
-    if (tryLoadOne(NULL, 1) == 0)
+    if (tryLoadLibrary(NULL, 1) == 0)
         return 0;
 
     /* No luck, return failure. */
@@ -241,12 +312,16 @@ int VBoxCGlueInit(void)
  */
 void VBoxCGlueTerm(void)
 {
-    if (g_hVBoxXPCOMC)
+    if (g_hVBoxCAPI)
     {
 #if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
-        dlclose(g_hVBoxXPCOMC);
+#ifndef WIN32
+        dlclose(g_hVBoxCAPI);
+#else
+        FreeLibrary(g_hVBoxCAPI);
+#endif
 #endif
-        g_hVBoxXPCOMC = NULL;
+        g_hVBoxCAPI = NULL;
     }
     g_pVBoxFuncs = NULL;
     g_pfnGetFunctions = NULL;
diff --git a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in b/src/VBox/Main/cbinding/VBoxCAPIGlue.h.in
similarity index 69%
rename from src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in
rename to src/VBox/Main/cbinding/VBoxCAPIGlue.h.in
index 7a1e9cc..603b136 100644
--- a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in
+++ b/src/VBox/Main/cbinding/VBoxCAPIGlue.h.in
@@ -1,10 +1,10 @@
-/* $Revision: 75934 $ */
-/** @file VBoxXPCOMCGlue.h
- * Glue for dynamically linking with VBoxXPCOMC.
+/* $Revision: 91907 $ */
+/** @file VBoxCAPIGlue.h
+ * Glue for dynamically linking with VBoxCAPI.
  */
 
 /*
- * Copyright (C) 2008-2012 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -28,23 +28,29 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef ___VBoxXPCOMC_cglue_h
-#define ___VBoxXPCOMC_cglue_h
+#ifndef ___VBoxCAPIGlue_h
+#define ___VBoxCAPIGlue_h
 
+#undef VBOX_WITH_GLUE
+#define VBOX_WITH_GLUE
 #include "VBoxCAPI_v at VBOX_API_VERSION@.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/** The dlopen handle for VBoxXPCOMC. */
-extern void *g_hVBoxXPCOMC;
+/** The so/dynsym/dll handle for VBoxCAPI. */
+#ifndef WIN32
+extern void *g_hVBoxCAPI;
+#else
+extern HMODULE g_hVBoxCAPI;
+#endif
 /** The last load error. */
 extern char g_szVBoxErrMsg[256];
-/** Pointer to the VBoxXPCOMC function table. */
-extern PCVBOXXPCOM g_pVBoxFuncs;
-/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
-extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
+/** Pointer to the VBOXCAPI function table. */
+extern PCVBOXCAPI g_pVBoxFuncs;
+/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
+extern PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions;
 
 
 int VBoxCGlueInit(void);
diff --git a/src/VBox/Main/cbinding/VBoxXPCOMC.cpp b/src/VBox/Main/cbinding/VBoxXPCOMC.cpp
deleted file mode 100644
index ceed755..0000000
--- a/src/VBox/Main/cbinding/VBoxXPCOMC.cpp
+++ /dev/null
@@ -1,492 +0,0 @@
-/* $Id: VBoxXPCOMC.cpp $ */
-/** @file VBoxXPCOMC.cpp
- * Utility functions to use with the C binding for XPCOM.
- */
-
-/*
- * Copyright (C) 2009-2013 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#define LOG_GROUP LOG_GROUP_MAIN
-#include <nsMemory.h>
-#include <nsIServiceManager.h>
-#include <nsEventQueueUtils.h>
-#include <nsIExceptionService.h>
-
-#include <iprt/string.h>
-#include <iprt/env.h>
-#include <VBox/log.h>
-
-#include "VBoxCAPI.h"
-#include "VBox/com/com.h"
-#include "VBox/version.h"
-
-using namespace std;
-
-/* The following 3 object references should be eliminated once the legacy
- * way to initialize the XPCOM C bindings is removed. */
-static ISession            *g_Session           = NULL;
-static IVirtualBox         *g_VirtualBox        = NULL;
-static nsIComponentManager *g_Manager           = NULL;
-
-static nsIEventQueue       *g_EventQueue        = NULL;
-
-static void VBoxComUninitialize(void);
-static void VBoxClientUninitialize(void);
-
-static int
-VBoxUtf16ToUtf8(const PRUnichar *pwszString, char **ppszString)
-{
-    return RTUtf16ToUtf8(pwszString, ppszString);
-}
-
-static int
-VBoxUtf8ToUtf16(const char *pszString, PRUnichar **ppwszString)
-{
-    return RTStrToUtf16(pszString, ppwszString);
-}
-
-static void
-VBoxUtf16Free(PRUnichar *pwszString)
-{
-    RTUtf16Free(pwszString);
-}
-
-static void
-VBoxUtf8Free(char *pszString)
-{
-    RTStrFree(pszString);
-}
-
-static void
-VBoxComUnallocMem(void *ptr)
-{
-    if (ptr)
-        nsMemory::Free(ptr);
-}
-
-static void
-VBoxComInitialize(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
-                  const char *pszSessionIID, ISession **ppSession)
-{
-    nsresult rc;
-    nsID virtualBoxIID;
-    nsID sessionIID;
-
-    *ppSession    = NULL;
-    *ppVirtualBox = NULL;
-
-    /* convert the string representation of UUID to nsIID type */
-    if (!(virtualBoxIID.Parse(pszVirtualBoxIID) && sessionIID.Parse(pszSessionIID)))
-        return;
-
-    rc = com::Initialize();
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: XPCOM could not be initialized! rc=%Rhrc\n", rc));
-        VBoxComUninitialize();
-        return;
-    }
-
-    rc = NS_GetComponentManager(&g_Manager);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
-        VBoxComUninitialize();
-        return;
-    }
-
-    rc = NS_GetMainEventQ(&g_EventQueue);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not get xpcom event queue! rc=%Rhrc\n", rc));
-        VBoxComUninitialize();
-        return;
-    }
-
-    rc = g_Manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
-                                               nsnull,
-                                               virtualBoxIID,
-                                               (void **)&g_VirtualBox);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not instantiate VirtualBox object! rc=%Rhrc\n",rc));
-        VBoxComUninitialize();
-        return;
-    }
-
-    Log(("Cbinding: IVirtualBox object created.\n"));
-
-    rc = g_Manager->CreateInstanceByContractID(NS_SESSION_CONTRACTID,
-                                               nsnull,
-                                               sessionIID,
-                                               (void **)&g_Session);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not instantiate Session object! rc=%Rhrc\n",rc));
-        VBoxComUninitialize();
-        return;
-    }
-
-    Log(("Cbinding: ISession object created.\n"));
-
-    *ppSession = g_Session;
-    *ppVirtualBox = g_VirtualBox;
-}
-
-static void
-VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
-{
-    VBoxComInitialize(IVIRTUALBOX_IID_STR, ppVirtualBox,
-                      ISESSION_IID_STR, ppSession);
-}
-
-static void
-VBoxComUninitialize(void)
-{
-    if (g_Session)
-    {
-        NS_RELEASE(g_Session);
-        g_Session = NULL;
-    }
-    if (g_VirtualBox)
-    {
-        NS_RELEASE(g_VirtualBox);
-        g_VirtualBox = NULL;
-    }
-    if (g_EventQueue)
-    {
-        NS_RELEASE(g_EventQueue);
-        g_EventQueue = NULL;
-    }
-    if (g_Manager)
-    {
-        NS_RELEASE(g_Manager);
-        g_Manager = NULL;
-    }
-    com::Shutdown();
-    Log(("Cbinding: Cleaned up the created objects.\n"));
-}
-
-static void
-VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
-{
-    *ppEventQueue = g_EventQueue;
-}
-
-static nsresult
-VBoxGetException(nsIException **ppException)
-{
-    nsresult rc;
-
-    *ppException = NULL;
-    nsIServiceManager *mgr = NULL;
-    rc = NS_GetServiceManager(&mgr);
-    if (NS_FAILED(rc) || !mgr)
-        return rc;
-
-    nsIID esid = NS_IEXCEPTIONSERVICE_IID;
-    nsIExceptionService *es = NULL;
-    rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
-    if (NS_FAILED(rc) || !es)
-    {
-        NS_RELEASE(mgr);
-        return rc;
-    }
-
-    nsIExceptionManager *em;
-    rc = es->GetCurrentExceptionManager(&em);
-    if (NS_FAILED(rc) || !em)
-    {
-        NS_RELEASE(es);
-        NS_RELEASE(mgr);
-        return rc;
-    }
-
-    nsIException *ex;
-    rc = em->GetCurrentException(&ex);
-    if (NS_FAILED(rc))
-    {
-        NS_RELEASE(em);
-        NS_RELEASE(es);
-        NS_RELEASE(mgr);
-        return rc;
-    }
-
-    *ppException = ex;
-    NS_RELEASE(em);
-    NS_RELEASE(es);
-    NS_RELEASE(mgr);
-    return rc;
-}
-
-static nsresult
-VBoxClearException(void)
-{
-    nsresult rc;
-
-    nsIServiceManager *mgr = NULL;
-    rc = NS_GetServiceManager(&mgr);
-    if (NS_FAILED(rc) || !mgr)
-        return rc;
-
-    nsIID esid = NS_IEXCEPTIONSERVICE_IID;
-    nsIExceptionService *es = NULL;
-    rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
-    if (NS_FAILED(rc) || !es)
-    {
-        NS_RELEASE(mgr);
-        return rc;
-    }
-
-    nsIExceptionManager *em;
-    rc = es->GetCurrentExceptionManager(&em);
-    if (NS_FAILED(rc) || !em)
-    {
-        NS_RELEASE(es);
-        NS_RELEASE(mgr);
-        return rc;
-    }
-
-    rc = em->SetCurrentException(NULL);
-    NS_RELEASE(em);
-    NS_RELEASE(es);
-    NS_RELEASE(mgr);
-    return rc;
-}
-
-static nsresult
-VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
-{
-    nsresult rc;
-    nsID virtualBoxClientIID;
-    nsID sessionIID;
-
-    *ppVirtualBoxClient = NULL;
-
-    /* convert the string representation of UUID to nsIID type */
-    if (!virtualBoxClientIID.Parse(pszVirtualBoxClientIID))
-        return NS_ERROR_INVALID_ARG;
-
-    rc = com::Initialize();
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: XPCOM could not be initialized! rc=%Rhrc\n", rc));
-        VBoxClientUninitialize();
-        return rc;
-    }
-
-    nsIComponentManager *pManager;
-    rc = NS_GetComponentManager(&pManager);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
-        VBoxClientUninitialize();
-        return rc;
-    }
-
-    rc = NS_GetMainEventQ(&g_EventQueue);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not get xpcom event queue! rc=%Rhrc\n", rc));
-        VBoxClientUninitialize();
-        return rc;
-    }
-
-    rc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
-                                              nsnull,
-                                              virtualBoxClientIID,
-                                              (void **)ppVirtualBoxClient);
-    if (NS_FAILED(rc))
-    {
-        Log(("Cbinding: Could not instantiate VirtualBoxClient object! rc=%Rhrc\n",rc));
-        VBoxClientUninitialize();
-        return rc;
-    }
-
-    NS_RELEASE(pManager);
-    pManager = NULL;
-
-    Log(("Cbinding: IVirtualBoxClient object created.\n"));
-
-    return NS_OK;
-}
-
-static void
-VBoxClientUninitialize(void)
-{
-    if (g_EventQueue)
-    {
-        NS_RELEASE(g_EventQueue);
-        g_EventQueue = NULL;
-    }
-    com::Shutdown();
-    Log(("Cbinding: Cleaned up the created objects.\n"));
-}
-
-static unsigned int
-VBoxVersion(void)
-{
-    return VBOX_VERSION_MAJOR * 1000 * 1000 + VBOX_VERSION_MINOR * 1000 + VBOX_VERSION_BUILD;
-}
-
-static unsigned int
-VBoxAPIVersion(void)
-{
-    return VBOX_VERSION_MAJOR * 1000 + VBOX_VERSION_MINOR + (VBOX_VERSION_BUILD > 50 ? 1 : 0);
-}
-
-VBOXXPCOMC_DECL(PCVBOXXPCOM)
-VBoxGetXPCOMCFunctions(unsigned uVersion)
-{
-    /*
-     * The current interface version.
-     */
-    static const VBOXXPCOMC s_Functions =
-    {
-        sizeof(VBOXXPCOMC),
-        VBOX_XPCOMC_VERSION,
-
-        VBoxVersion,
-        VBoxAPIVersion,
-
-        VBoxClientInitialize,
-        VBoxClientUninitialize,
-
-        VBoxComInitialize,
-        VBoxComUninitialize,
-
-        VBoxComUnallocMem,
-
-        VBoxUtf16ToUtf8,
-        VBoxUtf8ToUtf16,
-        VBoxUtf8Free,
-        VBoxUtf16Free,
-
-        VBoxGetEventQueue,
-        VBoxGetException,
-        VBoxClearException,
-
-        VBOX_XPCOMC_VERSION
-    };
-
-    if ((uVersion & 0xffff0000U) == (VBOX_XPCOMC_VERSION & 0xffff0000U))
-        return &s_Functions;
-
-    /*
-     * Legacy interface version 2.0.
-     */
-    static const struct VBOXXPCOMCV2
-    {
-        /** The size of the structure. */
-        unsigned cb;
-        /** The structure version. */
-        unsigned uVersion;
-
-        unsigned int (*pfnGetVersion)(void);
-
-        void  (*pfnComInitialize)(const char *pszVirtualBoxIID,
-                                  IVirtualBox **ppVirtualBox,
-                                  const char *pszSessionIID,
-                                  ISession **ppSession);
-
-        void  (*pfnComUninitialize)(void);
-
-        void  (*pfnComUnallocMem)(void *pv);
-        void  (*pfnUtf16Free)(PRUnichar *pwszString);
-        void  (*pfnUtf8Free)(char *pszString);
-
-        int   (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
-        int   (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
-
-        void  (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
-
-        /** Tail version, same as uVersion. */
-        unsigned uEndVersion;
-    } s_Functions_v2_0 =
-    {
-        sizeof(s_Functions_v2_0),
-        0x00020000U,
-
-        VBoxVersion,
-
-        VBoxComInitialize,
-        VBoxComUninitialize,
-
-        VBoxComUnallocMem,
-        VBoxUtf16Free,
-        VBoxUtf8Free,
-
-        VBoxUtf16ToUtf8,
-        VBoxUtf8ToUtf16,
-
-        VBoxGetEventQueue,
-
-        0x00020000U
-    };
-
-    if ((uVersion & 0xffff0000U) == 0x00020000U)
-        return (PCVBOXXPCOM)&s_Functions_v2_0;
-
-    /*
-     * Legacy interface version 1.0.
-     */
-    static const struct VBOXXPCOMCV1
-    {
-        /** The size of the structure. */
-        unsigned cb;
-        /** The structure version. */
-        unsigned uVersion;
-
-        unsigned int (*pfnGetVersion)(void);
-
-        void  (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
-        void  (*pfnComUninitialize)(void);
-
-        void  (*pfnComUnallocMem)(void *pv);
-        void  (*pfnUtf16Free)(PRUnichar *pwszString);
-        void  (*pfnUtf8Free)(char *pszString);
-
-        int   (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
-        int   (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
-
-        /** Tail version, same as uVersion. */
-        unsigned uEndVersion;
-    } s_Functions_v1_0 =
-    {
-        sizeof(s_Functions_v1_0),
-        0x00010000U,
-
-        VBoxVersion,
-
-        VBoxComInitializeV1,
-        VBoxComUninitialize,
-
-        VBoxComUnallocMem,
-        VBoxUtf16Free,
-        VBoxUtf8Free,
-
-        VBoxUtf16ToUtf8,
-        VBoxUtf8ToUtf16,
-
-        0x00010000U
-    };
-
-    if ((uVersion & 0xffff0000U) == 0x00010000U)
-        return (PCVBOXXPCOM)&s_Functions_v1_0;
-
-    /*
-     * Unsupported interface version.
-     */
-    return NULL;
-}
-
-/* vim: set ts=4 sw=4 et: */
diff --git a/src/VBox/Main/cbinding/xpcidl.xsl b/src/VBox/Main/cbinding/capiidl.xsl
similarity index 57%
rename from src/VBox/Main/cbinding/xpcidl.xsl
rename to src/VBox/Main/cbinding/capiidl.xsl
index 71deff3..7c23637 100644
--- a/src/VBox/Main/cbinding/xpcidl.xsl
+++ b/src/VBox/Main/cbinding/capiidl.xsl
@@ -1,11 +1,13 @@
 <?xml version="1.0"?>
-<!-- $Id: xpcidl.xsl $ -->
+<!-- $Id: capiidl.xsl $ -->
 
 <!--
- *  A template to generate a XPCOM IDL compatible interface definition file
- *  from the generic interface definition expressed in XML.
+ *  A template to generate a C header file for all relevant XPCOM interfaces
+ *  provided or needed for calling the VirtualBox API. The header file also
+ *  works on Windows, by using the C bindings header created by the MS COM IDL
+ *  compiler (which simultaneously supports C and C++, unlike XPCOM).
 
-    Copyright (C) 2008-2013 Oracle Corporation
+    Copyright (C) 2008-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -99,15 +101,16 @@
  *  header
 -->
 <xsl:template match="/idl">
-  <xsl:text>
-/*
+  <xsl:text>/*
  *  DO NOT EDIT! This is a generated file.
  *
- *  XPCOM IDL (XPIDL) definition for VirtualBox Main API (COM interfaces)
- *  generated from XIDL (XML interface definition).
+ *  Header file which provides C declarations for VirtualBox Main API
+ *  (COM interfaces), generated from XIDL (XML interface definition).
+ *  On Windows (which uses COM instead of XPCOM) the native C support
+ *  is used, and most of this file is not used.
  *
  *  Source    : src/VBox/Main/idl/VirtualBox.xidl
- *  Generator : src/VBox/Main/idl/xpcidl.xsl
+ *  Generator : src/VBox/Main/cbinding/capiidl.xsl
  *
  *  This file contains portions from the following Mozilla XPCOM files:
  *      xpcom/include/xpcom/nsID.h
@@ -120,7 +123,7 @@
  */
 
 /*
- * Copyright (C) 2008-2012 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * This file is part of a free software library; you can redistribute
  * it and/or modify it under the terms of the GNU Lesser General
@@ -139,16 +142,76 @@
  * otherwise unspecified.
  */
 
-#ifndef ___VirtualBox_CXPCOM_h
-#define ___VirtualBox_CXPCOM_h
+#ifndef ___VirtualBox_CAPI_h
+#define ___VirtualBox_CAPI_h
+
+#ifdef _WIN32
+# undef COBJMACROS
+# define COBJMACROS
+# include "Windows.h"
+#endif /* _WIN32 */
+
+#ifdef WIN32
+# ifdef IN_VBOXCAPI
+#  define VBOXCAPI_DECL(type) extern __declspec(dllexport) type
+# else /* !IN_VBOXCAPI */
+#  define VBOXCAPI_DECL(type) __declspec(dllimport) type
+# endif /* !IN_VBOXCAPI */
+#endif /* WIN32 */
 
 #ifdef __cplusplus
-# include "VirtualBox_XPCOM.h"
-#else /* !__cplusplus */
+/* The C++ treatment in this file is not meant for SDK users, it only exists
+ * so that this file can be used to produce the VBoxCAPI shared library which
+ * has to use C++ as it does all the conversion magic. */
+# ifdef IN_VBOXCAPI
+#  include "VBox/com/VirtualBox.h"
+#  ifndef WIN32
+#   include "nsIEventQueue.h"
+#  endif /* !WIN32 */
+# else /* !IN_VBOXCAPI */
+#  error Do not include this header file from C++ code
+# endif /* !IN_VBOXCAPI */
+#endif /* __cplusplus */
+
+#ifdef __GNUC__
+# define VBOX_EXTERN_CONST(type, name) extern const type name __attribute__((nocommon))
+#else /* !__GNUC__ */
+# define VBOX_EXTERN_CONST(type, name) extern const type name
+#endif /* !__GNUC__ */
+
+/* Treat WIN32 completely separately, as on Windows VirtualBox uses COM, not
+ * XPCOM like on all other platforms. While the code below would also compile
+ * on Windows, we need to switch to the native C support provided by the header
+ * files produced by the COM IDL compiler. */
+#ifdef WIN32
+# include "ObjBase.h"
+# include "oaidl.h"
+# include "VirtualBox.h"
+
+#ifndef __cplusplus
+/* Skip this in the C++ case as there's already a definition for CBSTR. */
+typedef const BSTR CBSTR;
+#endif /* !__cplusplus */
+
+#define VBOX_WINAPI WINAPI
+
+#define ComSafeArrayAsInParam(f) (f)
+#define ComSafeArrayAsOutParam(f) (&(f))
+#define ComSafeArrayAsOutIfaceParam(f,t) (&(f))
+
+#else /* !WIN32 */
 
 #include <stddef.h>
 #include "wchar.h"
 
+#ifdef IN_VBOXCAPI
+# define VBOXCAPI_DECL(type) PR_EXPORT(type)
+#else /* !IN_VBOXCAPI */
+# define VBOXCAPI_DECL(type) PR_IMPORT(type)
+#endif /* !IN_VBOXCAPI */
+
+#ifndef __cplusplus
+
 #if defined(WIN32)
 
 #define PR_EXPORT(__type) extern __declspec(dllexport) __type
@@ -360,6 +423,8 @@ typedef wchar_t PRUnichar;
 #else
 typedef PRUint16 PRUnichar;
 #endif
+typedef PRUnichar *BSTR;
+typedef const PRUnichar *CBSTR;
 #endif
 
 typedef long PRWord;
@@ -720,7 +785,6 @@ PR_EXTERN(void) PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
 /* Returned when a factory already is registered */
 #define NS_ERROR_FACTORY_EXISTS            (NS_ERROR_BASE + 0x100)
 
-
 /**
  * An "interface id" which can be used to uniquely identify a given
  * interface.
@@ -728,32 +792,118 @@ PR_EXTERN(void) PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
  */
 
 struct nsID {
-  PRUint32 m0;
-  PRUint16 m1;
-  PRUint16 m2;
-  PRUint8 m3[8];
+    PRUint32 m0;
+    PRUint16 m1;
+    PRUint16 m2;
+    PRUint8 m3[8];
 };
 
 typedef struct nsID nsID;
 typedef nsID nsIID;
+typedef nsID nsCID;
 
-struct nsISupports;   /* forward declaration */
-struct nsIStackFrame; /* forward declaration */
-struct nsIException;  /* forward declaration */
-typedef struct nsISupports nsISupports;     /* forward declaration */
-typedef struct nsIStackFrame nsIStackFrame; /* forward declaration */
-typedef struct nsIException nsIException;   /* forward declaration */
+#endif /* __cplusplus */
 
-/**
- * IID for the nsISupports interface
- * {00000000-0000-0000-c000-000000000046}
- *
- * To maintain binary compatibility with COM's IUnknown, we define the IID
- * of nsISupports to be the same as that of COM's IUnknown.
- */
-#define NS_ISUPPORTS_IID                                                      \
-  { 0x00000000, 0x0000, 0x0000,                                               \
-    {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
+#define VBOX_WINAPI
+
+/* Various COM types defined by their XPCOM equivalent */
+typedef PRInt64 LONG64;
+typedef PRInt32 LONG;
+typedef PRInt32 DWORD;
+typedef PRInt16 SHORT;
+typedef PRUint64 ULONG64;
+typedef PRUint32 ULONG;
+typedef PRUint16 USHORT;
+
+typedef PRBool BOOL;
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#define HRESULT nsresult
+#define SUCCEEDED NS_SUCCEEDED
+#define FAILED NS_FAILED
+
+/* OLE error codes */
+#define S_OK                ((nsresult)NS_OK)
+#define E_UNEXPECTED        NS_ERROR_UNEXPECTED
+#define E_NOTIMPL           NS_ERROR_NOT_IMPLEMENTED
+#define E_OUTOFMEMORY       NS_ERROR_OUT_OF_MEMORY
+#define E_INVALIDARG        NS_ERROR_INVALID_ARG
+#define E_NOINTERFACE       NS_ERROR_NO_INTERFACE
+#define E_POINTER           NS_ERROR_NULL_POINTER
+#define E_ABORT             NS_ERROR_ABORT
+#define E_FAIL              NS_ERROR_FAILURE
+/* Note: a better analog for E_ACCESSDENIED would probably be
+ * NS_ERROR_NOT_AVAILABLE, but we want binary compatibility for now. */
+#define E_ACCESSDENIED      ((nsresult)0x80070005L)
+
+/* Basic vartype for COM compatibility. */
+typedef enum VARTYPE
+{
+    VT_I2 = 2,
+    VT_I4 = 3,
+    VT_BSTR = 8,
+    VT_DISPATCH = 9,
+    VT_BOOL = 11,
+    VT_UNKNOWN = 13,
+    VT_I1 = 16,
+    VT_UI1 = 17,
+    VT_UI2 = 18,
+    VT_UI4 = 19,
+    VT_I8 = 20,
+    VT_UI8 = 21,
+    VT_HRESULT = 25
+} VARTYPE;
+
+/* Basic safearray type for COM compatibility. */
+typedef struct SAFEARRAY
+{
+    void *pv;
+    ULONG c;
+} SAFEARRAY;
+
+#define ComSafeArrayAsInParam(f) ((f)->c), ((f)->pv)
+#define ComSafeArrayAsOutParam(f) (&((f)->c)), (&((f)->pv))
+#define ComSafeArrayAsOutIfaceParam(f,t) (&((f)->c)), (t**)(&((f)->pv))
+
+/* Glossing over differences between COM and XPCOM */
+#define IErrorInfo nsIException
+#define IUnknown nsISupports
+#define IDispatch nsISupports
+
+/* Make things as COM compatible as possible */
+#define interface struct
+#ifdef CONST_VTABLE
+# define CONST_VTBL const
+#else /* !CONST_VTABLE */
+# define CONST_VTBL
+#endif /* !CONST_VTABLE */
+
+#ifndef __cplusplus
+
+/** @todo this first batch of forward declarations (and the corresponding ones
+ * generated for each interface) are 100% redundant, remove eventually. */
+interface nsISupports;   /* forward declaration */
+interface nsIException;  /* forward declaration */
+interface nsIStackFrame; /* forward declaration */
+interface nsIEventTarget;/* forward declaration */
+interface nsIEventQueue; /* forward declaration */
+
+typedef interface nsISupports nsISupports;     /* forward declaration */
+typedef interface nsIException nsIException;   /* forward declaration */
+typedef interface nsIStackFrame nsIStackFrame; /* forward declaration */
+typedef interface nsIEventTarget nsIEventTarget;/* forward declaration */
+typedef interface nsIEventQueue nsIEventQueue; /* forward declaration */
+
+/* starting interface:    nsISupports */
+#define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046"
+
+#define NS_ISUPPORTS_IID \
+    { 0x00000000, 0x0000, 0x0000, \
+      {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
 
 /**
  * Reference count values
@@ -763,6 +913,11 @@ typedef struct nsIException nsIException;   /* forward declaration */
  * The following ifdef exists to maintain binary compatibility with
  * IUnknown.
  */
+#if defined(XP_WIN) && PR_BYTES_PER_LONG == 4
+typedef unsigned long nsrefcnt;
+#else
+typedef PRUint32 nsrefcnt;
+#endif
 
 /**
  * Basic component object model interface. Objects which implement
@@ -770,156 +925,239 @@ typedef struct nsIException nsIException;   /* forward declaration */
  * and a reference counted memory model (AddRef/Release). This is
  * modelled after the win32 IUnknown API.
  */
-struct nsISupports_vtbl {
-
-  /**
-   * @name Methods
-   */
-
-  /**
-   * A run time mechanism for interface discovery.
-   * @param aIID         [in]  A requested interface IID
-   * @param aInstancePtr [out] A pointer to an interface pointer to
-   *                           receive the result.
-   * @return            NS_OK if the interface is supported by the associated
-   *                          instance, NS_NOINTERFACE if it is not.
-   * NS_ERROR_INVALID_POINTER if aInstancePtr is NULL.
-   */
-  nsresult (*QueryInterface)(nsISupports *pThis, const nsID *iid, void **resultp);
-  /**
-   * Increases the reference count for this interface.
-   * The associated instance will not be deleted unless
-   * the reference count is returned to zero.
-   *
-   * @return The resulting reference count.
-   */
-  nsresult (*AddRef)(nsISupports *pThis);
-
-  /**
-   * Decreases the reference count for this interface.
-   * Generally, if the reference count returns to zero,
-   * the associated instance is deleted.
-   *
-   * @return The resulting reference count.
-   */
-  nsresult (*Release)(nsISupports *pThis);
-
+#ifndef VBOX_WITH_GLUE
+struct nsISupports_vtbl
+{
+    nsresult (*QueryInterface)(nsISupports *pThis, const nsID *iid, void **resultp);
+    nsrefcnt (*AddRef)(nsISupports *pThis);
+    nsrefcnt (*Release)(nsISupports *pThis);
 };
-
-struct nsISupports {
+#else /* !VBOX_WITH_GLUE */
+struct nsISupportsVtbl
+{
+    nsresult (*QueryInterface)(nsISupports *pThis, const nsID *iid, void **resultp);
+    nsrefcnt (*AddRef)(nsISupports *pThis);
+    nsrefcnt (*Release)(nsISupports *pThis);
+};
+#define nsISupports_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsISupports_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsISupports_Release(p) ((p)->lpVtbl->Release(p))
+#define IUnknown_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define IUnknown_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define IUnknown_Release(p) ((p)->lpVtbl->Release(p))
+#define IDispatch_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define IDispatch_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define IDispatch_Release(p) ((p)->lpVtbl->Release(p))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsISupports
+{
+#ifndef VBOX_WITH_GLUE
     struct nsISupports_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+    CONST_VTBL struct nsISupportsVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
 };
 
 /* starting interface:    nsIException */
 #define NS_IEXCEPTION_IID_STR "f3a8d3b4-c424-4edc-8bf6-8974c983ba78"
 
 #define NS_IEXCEPTION_IID \
-  {0xf3a8d3b4, 0xc424, 0x4edc, \
-    { 0x8b, 0xf6, 0x89, 0x74, 0xc9, 0x83, 0xba, 0x78 }}
-
-struct nsIException_vtbl {
-
-  /* Methods from the Class nsISupports */
-  struct nsISupports_vtbl nsisupports;
-
-  /* readonly attribute string message; */
-  nsresult (*GetMessage)(nsIException *pThis, PRUnichar * *aMessage);
-
-  /* readonly attribute nsresult (*result; */
-  nsresult (*GetResult)(nsIException *pThis, nsresult *aResult);
-
-  /* readonly attribute string name; */
-  nsresult (*GetName)(nsIException *pThis, PRUnichar * *aName);
+    {0xf3a8d3b4, 0xc424, 0x4edc, \
+      { 0x8b, 0xf6, 0x89, 0x74, 0xc9, 0x83, 0xba, 0x78 }}
 
-  /* readonly attribute string filename; */
-  nsresult (*GetFilename)(nsIException *pThis, PRUnichar * *aFilename);
-
-  /* readonly attribute PRUint32 lineNumber; */
-  nsresult (*GetLineNumber)(nsIException *pThis, PRUint32 *aLineNumber);
-
-  /* readonly attribute PRUint32 columnNumber; */
-  nsresult (*GetColumnNumber)(nsIException *pThis, PRUint32 *aColumnNumber);
-
-  /* readonly attribute nsIStackFrame location; */
-  nsresult (*GetLocation)(nsIException *pThis, nsIStackFrame * *aLocation);
-
-  /* readonly attribute nsIException inner; */
-  nsresult (*GetInner)(nsIException *pThis, nsIException * *aInner);
-
-  /* readonly attribute nsISupports data; */
-  nsresult (*GetData)(nsIException *pThis, nsISupports * *aData);
+#ifndef VBOX_WITH_GLUE
+struct nsIException_vtbl
+{
+    /* Methods from the interface nsISupports */
+    struct nsISupports_vtbl nsisupports;
 
-  /* string toString (); */
-  nsresult (*ToString)(nsIException *pThis, PRUnichar **_retval);
+    nsresult (*GetMessage)(nsIException *pThis, PRUnichar * *aMessage);
+    nsresult (*GetResult)(nsIException *pThis, nsresult *aResult);
+    nsresult (*GetName)(nsIException *pThis, PRUnichar * *aName);
+    nsresult (*GetFilename)(nsIException *pThis, PRUnichar * *aFilename);
+    nsresult (*GetLineNumber)(nsIException *pThis, PRUint32 *aLineNumber);
+    nsresult (*GetColumnNumber)(nsIException *pThis, PRUint32 *aColumnNumber);
+    nsresult (*GetLocation)(nsIException *pThis, nsIStackFrame * *aLocation);
+    nsresult (*GetInner)(nsIException *pThis, nsIException * *aInner);
+    nsresult (*GetData)(nsIException *pThis, nsISupports * *aData);
+    nsresult (*ToString)(nsIException *pThis, PRUnichar **_retval);
 };
-
-struct nsIException {
+#else /* !VBOX_WITH_GLUE */
+struct nsIExceptionVtbl
+{
+    nsresult (*QueryInterface)(nsIException *pThis, const nsID *iid, void **resultp);
+    nsrefcnt (*AddRef)(nsIException *pThis);
+    nsrefcnt (*Release)(nsIException *pThis);
+
+    nsresult (*GetMessage)(nsIException *pThis, PRUnichar * *aMessage);
+    nsresult (*GetResult)(nsIException *pThis, nsresult *aResult);
+    nsresult (*GetName)(nsIException *pThis, PRUnichar * *aName);
+    nsresult (*GetFilename)(nsIException *pThis, PRUnichar * *aFilename);
+    nsresult (*GetLineNumber)(nsIException *pThis, PRUint32 *aLineNumber);
+    nsresult (*GetColumnNumber)(nsIException *pThis, PRUint32 *aColumnNumber);
+    nsresult (*GetLocation)(nsIException *pThis, nsIStackFrame * *aLocation);
+    nsresult (*GetInner)(nsIException *pThis, nsIException * *aInner);
+    nsresult (*GetData)(nsIException *pThis, nsISupports * *aData);
+    nsresult (*ToString)(nsIException *pThis, PRUnichar **_retval);
+};
+#define nsIException_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIException_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIException_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIException_get_Message(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define nsIException_GetMessage(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define nsIException_get_Result(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define nsIException_GetResult(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define nsIException_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIException_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIException_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIException_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIException_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIException_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIException_get_ColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define nsIException_GetColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define nsIException_get_Inner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define nsIException_GetInner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define nsIException_get_Data(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define nsIException_GetData(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define nsIException_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))
+#define IErrorInfo_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define IErrorInfo_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define IErrorInfo_Release(p) ((p)->lpVtbl->Release(p))
+#define IErrorInfo_get_Message(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define IErrorInfo_GetMessage(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define IErrorInfo_get_Result(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define IErrorInfo_GetResult(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define IErrorInfo_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define IErrorInfo_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define IErrorInfo_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define IErrorInfo_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define IErrorInfo_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define IErrorInfo_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define IErrorInfo_get_ColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define IErrorInfo_GetColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define IErrorInfo_get_Inner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define IErrorInfo_GetInner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define IErrorInfo_get_Data(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define IErrorInfo_GetData(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define IErrorInfo_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIException
+{
+#ifndef VBOX_WITH_GLUE
     struct nsIException_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+    CONST_VTBL struct nsIExceptionVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
 };
 
 /* starting interface:    nsIStackFrame */
 #define NS_ISTACKFRAME_IID_STR "91d82105-7c62-4f8b-9779-154277c0ee90"
 
 #define NS_ISTACKFRAME_IID \
-  {0x91d82105, 0x7c62, 0x4f8b, \
-    { 0x97, 0x79, 0x15, 0x42, 0x77, 0xc0, 0xee, 0x90 }}
+    {0x91d82105, 0x7c62, 0x4f8b, \
+      { 0x97, 0x79, 0x15, 0x42, 0x77, 0xc0, 0xee, 0x90 }}
 
-struct nsIStackFrame_vtbl {
-
-  /* Methods from the Class nsISupports */
-  struct nsISupports_vtbl nsisupports;
-
-  /* readonly attribute PRUint32 language; */
-  nsresult (*GetLanguage)(nsIStackFrame *pThis, PRUint32 *aLanguage);
-
-  /* readonly attribute string languageName; */
-  nsresult (*GetLanguageName)(nsIStackFrame *pThis, PRUnichar * *aLanguageName);
-
-  /* readonly attribute string filename; */
-  nsresult (*GetFilename)(nsIStackFrame *pThis, PRUnichar * *aFilename);
-
-  /* readonly attribute string name; */
-  nsresult (*GetName)(nsIStackFrame *pThis, PRUnichar * *aName);
-
-  /* readonly attribute PRInt32 lineNumber; */
-  nsresult (*GetLineNumber)(nsIStackFrame *pThis, PRInt32 *aLineNumber);
-
-  /* readonly attribute string sourceLine; */
-  nsresult (*GetSourceLine)(nsIStackFrame *pThis, PRUnichar * *aSourceLine);
-
-  /* readonly attribute nsIStackFrame caller; */
-  nsresult (*GetCaller)(nsIStackFrame *pThis, nsIStackFrame * *aCaller);
+#ifndef VBOX_WITH_GLUE
+struct nsIStackFrame_vtbl
+{
+    /* Methods from the interface nsISupports */
+    struct nsISupports_vtbl nsisupports;
 
-  /* string toString (); */
-  nsresult (*ToString)(nsIStackFrame *pThis, PRUnichar **_retval);
+    nsresult (*GetLanguage)(nsIStackFrame *pThis, PRUint32 *aLanguage);
+    nsresult (*GetLanguageName)(nsIStackFrame *pThis, PRUnichar * *aLanguageName);
+    nsresult (*GetFilename)(nsIStackFrame *pThis, PRUnichar * *aFilename);
+    nsresult (*GetName)(nsIStackFrame *pThis, PRUnichar * *aName);
+    nsresult (*GetLineNumber)(nsIStackFrame *pThis, PRInt32 *aLineNumber);
+    nsresult (*GetSourceLine)(nsIStackFrame *pThis, PRUnichar * *aSourceLine);
+    nsresult (*GetCaller)(nsIStackFrame *pThis, nsIStackFrame * *aCaller);
+    nsresult (*ToString)(nsIStackFrame *pThis, PRUnichar **_retval);
 };
-
-struct nsIStackFrame {
+#else /* !VBOX_WITH_GLUE */
+struct nsIStackFrameVtbl
+{
+    nsresult (*QueryInterface)(nsIStackFrame *pThis, const nsID *iid, void **resultp);
+    nsrefcnt (*AddRef)(nsIStackFrame *pThis);
+    nsrefcnt (*Release)(nsIStackFrame *pThis);
+
+    nsresult (*GetLanguage)(nsIStackFrame *pThis, PRUint32 *aLanguage);
+    nsresult (*GetLanguageName)(nsIStackFrame *pThis, PRUnichar * *aLanguageName);
+    nsresult (*GetFilename)(nsIStackFrame *pThis, PRUnichar * *aFilename);
+    nsresult (*GetName)(nsIStackFrame *pThis, PRUnichar * *aName);
+    nsresult (*GetLineNumber)(nsIStackFrame *pThis, PRInt32 *aLineNumber);
+    nsresult (*GetSourceLine)(nsIStackFrame *pThis, PRUnichar * *aSourceLine);
+    nsresult (*GetCaller)(nsIStackFrame *pThis, nsIStackFrame * *aCaller);
+    nsresult (*ToString)(nsIStackFrame *pThis, PRUnichar **_retval);
+};
+#define nsIStackFrame_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIStackFrame_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIStackFrame_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIStackFrame_get_Language(p, aLanguage) ((p)->lpVtbl->GetLanguge(p, aLanguage))
+#define nsIStackFrame_GetLanguage(p, aLanguage) ((p)->lpVtbl->GetLanguge(p, aLanguage))
+#define nsIStackFrame_get_LanguageName(p, aLanguageName) ((p)->lpVtbl->GetLanguageName(p, aLanguageName))
+#define nsIStackFrame_GetLanguageName(p, aLanguageName) ((p)->lpVtbl->GetLanguageName(p, aLanguageName))
+#define nsIStackFrame_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIStackFrame_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIStackFrame_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIStackFrame_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIStackFrame_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIStackFrame_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIStackFrame_get_SourceLine(p, aSourceLine) ((p)->lpVtbl->GetSourceLine(p, aSourceLine))
+#define nsIStackFrame_GetSourceLine(p, aSourceLine) ((p)->lpVtbl->GetSourceLine(p, aSourceLine))
+#define nsIStackFrame_get_Caller(p, aCaller) ((p)->lpVtbl->GetCaller(p, aCaller))
+#define nsIStackFrame_GetCaller(p, aCaller) ((p)->lpVtbl->GetCaller(p, aCaller))
+#define nsIStackFrame_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIStackFrame
+{
+#ifndef VBOX_WITH_GLUE
     struct nsIStackFrame_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+    CONST_VTBL struct nsIStackFrameVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
 };
 
 /* starting interface:    nsIEventTarget */
 #define NS_IEVENTTARGET_IID_STR "ea99ad5b-cc67-4efb-97c9-2ef620a59f2a"
 
 #define NS_IEVENTTARGET_IID \
-  {0xea99ad5b, 0xcc67, 0x4efb, \
-    { 0x97, 0xc9, 0x2e, 0xf6, 0x20, 0xa5, 0x9f, 0x2a }}
-
-struct nsIEventTarget;
-typedef struct nsIEventTarget nsIEventTarget;
-
-struct nsIEventTarget_vtbl {
+    {0xea99ad5b, 0xcc67, 0x4efb, \
+      { 0x97, 0xc9, 0x2e, 0xf6, 0x20, 0xa5, 0x9f, 0x2a }}
 
+#ifndef VBOX_WITH_GLUE
+struct nsIEventTarget_vtbl
+{
     struct nsISupports_vtbl nsisupports;
 
     nsresult (*PostEvent)(nsIEventTarget *pThis, PLEvent * aEvent);
-
     nsresult (*IsOnCurrentThread)(nsIEventTarget *pThis, PRBool *_retval);
-
 };
+#else /* !VBOX_WITH_GLUE */
+struct nsIEventTargetVtbl
+{
+    nsresult (*QueryInterface)(nsIEventTarget *pThis, const nsID *iid, void **resultp);
+    nsrefcnt (*AddRef)(nsIEventTarget *pThis);
+    nsrefcnt (*Release)(nsIEventTarget *pThis);
 
-struct nsIEventTarget {
+    nsresult (*PostEvent)(nsIEventTarget *pThis, PLEvent * aEvent);
+    nsresult (*IsOnCurrentThread)(nsIEventTarget *pThis, PRBool *_retval);
+};
+#define nsIEventTarget_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIEventTarget_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIEventTarget_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIEventTarget_PostEvent(p, aEvent) ((p)->lpVtbl->PostEvent(p, aEvent))
+#define nsIEventTarget_IsOnCurrentThread(p, retval) ((p)->lpVtbl->IsOnCurrentThread(p, retval))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIEventTarget
+{
+#ifndef VBOX_WITH_GLUE
     struct nsIEventTarget_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+    CONST_VTBL struct nsIEventTargetVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
 };
 
 /* starting interface:    nsIEventQueue */
@@ -929,78 +1167,114 @@ struct nsIEventTarget {
   {0x176afb41, 0x00a4, 0x11d3, \
     { 0x9f, 0x2a, 0x00, 0x40, 0x05, 0x53, 0xee, 0xf0 }}
 
-struct nsIEventQueue;
-typedef struct nsIEventQueue nsIEventQueue;
-
-struct nsIEventQueue_vtbl {
-
+#ifndef VBOX_WITH_GLUE
+struct nsIEventQueue_vtbl
+{
     struct nsIEventTarget_vtbl nsieventtarget;
 
     nsresult (*InitEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * owner, PLHandleEventProc handler, PLDestroyEventProc destructor);
-
     nsresult (*PostSynchronousEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * *aResult);
-
     nsresult (*PendingEvents)(nsIEventQueue *pThis, PRBool *_retval);
-
     nsresult (*ProcessPendingEvents)(nsIEventQueue *pThis);
-
     nsresult (*EventLoop)(nsIEventQueue *pThis);
-
     nsresult (*EventAvailable)(nsIEventQueue *pThis, PRBool *aResult);
-
     nsresult (*GetEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
-
     nsresult (*HandleEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
-
     nsresult (*WaitForEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
-
     PRInt32 (*GetEventQueueSelectFD)(nsIEventQueue *pThis);
-
     nsresult (*Init)(nsIEventQueue *pThis, PRBool aNative);
-
     nsresult (*InitFromPRThread)(nsIEventQueue *pThis, PRThread * thread, PRBool aNative);
-
     nsresult (*InitFromPLQueue)(nsIEventQueue *pThis, PLEventQueue * aQueue);
-
     nsresult (*EnterMonitor)(nsIEventQueue *pThis);
-
     nsresult (*ExitMonitor)(nsIEventQueue *pThis);
-
     nsresult (*RevokeEvents)(nsIEventQueue *pThis, void * owner);
-
     nsresult (*GetPLEventQueue)(nsIEventQueue *pThis, PLEventQueue * *_retval);
-
     nsresult (*IsQueueNative)(nsIEventQueue *pThis, PRBool *_retval);
-
     nsresult (*StopAcceptingEvents)(nsIEventQueue *pThis);
-
 };
+#else /* !VBOX_WITH_GLUE */
+struct nsIEventQueueVtbl
+{
+    nsresult (*QueryInterface)(nsIEventQueue *pThis, const nsID *iid, void **resultp);
+    nsrefcnt (*AddRef)(nsIEventQueue *pThis);
+    nsrefcnt (*Release)(nsIEventQueue *pThis);
+
+    nsresult (*PostEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
+    nsresult (*IsOnCurrentThread)(nsIEventQueue *pThis, PRBool *_retval);
 
-struct nsIEventQueue {
+    nsresult (*InitEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * owner, PLHandleEventProc handler, PLDestroyEventProc destructor);
+    nsresult (*PostSynchronousEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * *aResult);
+    nsresult (*PendingEvents)(nsIEventQueue *pThis, PRBool *_retval);
+    nsresult (*ProcessPendingEvents)(nsIEventQueue *pThis);
+    nsresult (*EventLoop)(nsIEventQueue *pThis);
+    nsresult (*EventAvailable)(nsIEventQueue *pThis, PRBool *aResult);
+    nsresult (*GetEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+    nsresult (*HandleEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
+    nsresult (*WaitForEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+    PRInt32 (*GetEventQueueSelectFD)(nsIEventQueue *pThis);
+    nsresult (*Init)(nsIEventQueue *pThis, PRBool aNative);
+    nsresult (*InitFromPRThread)(nsIEventQueue *pThis, PRThread * thread, PRBool aNative);
+    nsresult (*InitFromPLQueue)(nsIEventQueue *pThis, PLEventQueue * aQueue);
+    nsresult (*EnterMonitor)(nsIEventQueue *pThis);
+    nsresult (*ExitMonitor)(nsIEventQueue *pThis);
+    nsresult (*RevokeEvents)(nsIEventQueue *pThis, void * owner);
+    nsresult (*GetPLEventQueue)(nsIEventQueue *pThis, PLEventQueue * *_retval);
+    nsresult (*IsQueueNative)(nsIEventQueue *pThis, PRBool *_retval);
+    nsresult (*StopAcceptingEvents)(nsIEventQueue *pThis);
+};
+#define nsIEventQueue_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIEventQueue_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIEventQueue_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIEventQueue_PostEvent(p, aEvent) ((p)->lpVtbl->PostEvent(p, aEvent))
+#define nsIEventQueue_IsOnCurrentThread(p, retval) ((p)->lpVtbl->IsOnCurrentThread(p, retval))
+#define nsIEventQueue_InitEvent(p, aEvent, owner, handler, destructor) ((p)->lpVtbl->InitEvent(p, aEvent, owner, handler, destructor))
+#define nsIEventQueue_PostSynchronousEvent(p, aEvent, aResult) ((p)->lpVtbl->PostSynchronousEvent(p, aEvent, aResult))
+#define nsIEventQueue_ProcessPendingEvents(p) ((p)->lpVtbl->ProcessPendingEvents(p))
+#define nsIEventQueue_EventLoop(p) ((p)->lpVtbl->EventLoop(p))
+#define nsIEventQueue_EventAvailable(p, aResult) ((p)->lpVtbl->EventAvailable(p, aResult))
+#define nsIEventQueue_get_Event(p, aEvent) ((p)->lpVtbl->GetEvent(p, aEvent))
+#define nsIEventQueue_GetEvent(p, aEvent) ((p)->lpVtbl->GetEvent(p, aEvent))
+#define nsIEventQueue_HandleEvent(p, aEvent) ((p)->lpVtbl->HandleEvent(p, aEvent))
+#define nsIEventQueue_WaitForEvent(p, aEvent) ((p)->lpVtbl->WaitForEvent(p, aEvent))
+#define nsIEventQueue_GetEventQueueSelectFD(p) ((p)->lpVtbl->GetEventQueueSelectFD(p))
+#define nsIEventQueue_Init(p, aNative) ((p)->lpVtbl->Init(p, aNative))
+#define nsIEventQueue_InitFromPLQueue(p, aQueue) ((p)->lpVtbl->InitFromPLQueue(p, aQueue))
+#define nsIEventQueue_EnterMonitor(p) ((p)->lpVtbl->EnterMonitor(p))
+#define nsIEventQueue_ExitMonitor(p) ((p)->lpVtbl->ExitMonitor(p))
+#define nsIEventQueue_RevokeEvents(p, owner) ((p)->lpVtbl->RevokeEvents(p, owner))
+#define nsIEventQueue_GetPLEventQueue(p, retval) ((p)->lpVtbl->GetPLEventQueue(p, retval))
+#define nsIEventQueue_IsQueueNative(p, retval) ((p)->lpVtbl->IsQueueNative(p, retval))
+#define nsIEventQueue_StopAcceptingEvents(p) ((p)->lpVtbl->StopAcceptingEvents(p))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIEventQueue
+{
+#ifndef VBOX_WITH_GLUE
     struct nsIEventQueue_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+    CONST_VTBL struct nsIEventQueueVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
 };
 
 </xsl:text>
  <xsl:apply-templates/>
-<xsl:text>
-#endif /* !__cplusplus */
+ <xsl:text>
 
-#ifdef IN_VBOXXPCOMC
-# define VBOXXPCOMC_DECL(type)  PR_EXPORT(type)
-#else
-# define VBOXXPCOMC_DECL(type)  PR_IMPORT(type)
-#endif
+#endif /* __cplusplus */
+
+#endif /* !WIN32 */
 
 #ifdef __cplusplus
-extern "C" {
-#endif
+extern "C"
+{
+#endif /* __cplusplus */
 
 
 /**
  * Function table for dynamic linking.
- * Use VBoxGetFunctions() to obtain the pointer to it.
+ * Use VBoxGetCAPIFunctions() to obtain the pointer to it.
  */
-typedef struct VBOXXPCOMC
+typedef struct VBOXCAPI
 {
     /** The size of the structure. */
     unsigned cb;
@@ -1031,11 +1305,29 @@ typedef struct VBOXXPCOMC
      *
      * @param pszVirtualBoxClientIID    pass IVIRTUALBOXCLIENT_IID_STR
      * @param ppVirtualBoxClient        output parameter for VirtualBoxClient
-     *              reference, handled as usual with XPCOM.
-     * @returns XPCOM error code
+     *              reference, handled as usual with COM/XPCOM.
+     * @returns COM/XPCOM error code
+     */
+    HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
+                                   IVirtualBoxClient **ppVirtualBoxClient);
+    /**
+     * Initialize the use of the C bindings in a non-primary thread.
+     *
+     * Must be called on any newly created thread which wants to use the
+     * VirtualBox API.
+     *
+     * @returns COM/XPCOM error code
      */
-    nsresult (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
-                                    IVirtualBoxClient **ppVirtualBoxClient);
+    HRESULT (*pfnClientThreadInitialize)(void);
+    /**
+     * Uninitialize the use of the C bindings in a non-primary thread.
+     *
+     * Should be called before terminating the thread which initialized the
+     * C bindings using pfnClientThreadInitialize.
+     *
+     * @returns COM/XPCOM error code
+     */
+    HRESULT (*pfnClientThreadUninitialize)(void);
     /**
      * Uninitialize the C bindings for an API client.
      *
@@ -1076,11 +1368,15 @@ typedef struct VBOXXPCOMC
     void (*pfnComUninitialize)(void);
 
     /**
-     * Free memory managed by XPCOM.
+     * Free string managed by COM/XPCOM.
      *
-     * @param pv        pointer to memory block to be freed
+     * @param pwsz          pointer to string to be freed
      */
-    void  (*pfnComUnallocMem)(void *pv);
+    void  (*pfnComUnallocString)(BSTR pwsz);
+#ifndef WIN32
+    /** Legacy function, was always for freeing strings only. */
+#define pfnComUnallocMem(pv) pfnComUnallocString((BSTR)(pv))
+#endif /* !WIN32 */
 
     /**
      * Convert string from UTF-16 encoding to UTF-8 encoding.
@@ -1089,7 +1385,7 @@ typedef struct VBOXXPCOMC
      * @param ppszString    output string
      * @returns IPRT status code
      */
-    int   (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
+    int   (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
     /**
      * Convert string from UTF-8 encoding to UTF-16 encoding.
      *
@@ -1097,7 +1393,7 @@ typedef struct VBOXXPCOMC
      * @param ppwszString   output string
      * @returns IPRT status code
      */
-    int   (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
+    int   (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
     /**
      * Free memory returned by pfnUtf16ToUtf8. Do not use for anything else.
      *
@@ -1109,65 +1405,195 @@ typedef struct VBOXXPCOMC
      *
      * @param pwszString    string to be freed.
      */
-    void  (*pfnUtf16Free)(PRUnichar *pwszString);
+    void  (*pfnUtf16Free)(BSTR pwszString);
 
     /**
-     * Get main XPCOM event queue.
+     * Create a safearray (used for passing arrays to COM/XPCOM)
+     *
+     * Must be freed by pfnSafeArrayDestroy.
+     *
+     * @param vt            variant type, defines the size of the elements
+     * @param lLbound       lower bound of the index, should be 0
+     * @param cElements     number of elements
+     * @returns pointer to safearray
+     */
+    SAFEARRAY *(*pfnSafeArrayCreateVector)(VARTYPE vt, LONG lLbound, ULONG cElements);
+    /**
+     * Pre-allocate a safearray to be used by an out safearray parameter
+     *
+     * Must be freed by pfnSafeArrayDestroy.
+     *
+     * @returns pointer to safearray (system dependent, may be NULL if
+     *    there is no need to pre-allocate a safearray)
+     */
+    SAFEARRAY *(*pfnSafeArrayOutParamAlloc)(void);
+    /**
+     * Copy a C array into a safearray (for passing as an input parameter)
+     *
+     * @param psa           pointer to already created safearray.
+     * @param pv            pointer to memory block to copy into safearray.
+     * @param cb            number of bytes to copy.
+     * @returns COM/XPCOM error code
+     */
+    HRESULT (*pfnSafeArrayCopyInParamHelper)(SAFEARRAY *psa, const void *pv, ULONG cb);
+    /**
+     * Copy a safearray into a C array (for getting an output parameter)
+     *
+     * @param ppv           output pointer to newly created array, which has to
+     *          be freed with free().
+     * @param pcb           number of bytes in the output buffer.
+     * @param vt            variant type, defines the size of the elements
+     * @param psa           pointer to safearray for getting the data
+     * @returns COM/XPCOM error code
+     */
+    HRESULT (*pfnSafeArrayCopyOutParamHelper)(void **ppv, ULONG *pcb, VARTYPE vt, SAFEARRAY *psa);
+    /**
+     * Copy a safearray into a C array (special variant for interface pointers)
+     *
+     * @param ppaObj        output pointer to newly created array, which has
+     *          to be freed with free(). Note that it's the caller's
+     *          responsibility to call Release() on each non-NULL interface
+     *          pointer before freeing.
+     * @param pcObj         number of pointers in the output buffer.
+     * @param psa           pointer to safearray for getting the data
+     * @returns COM/XPCOM error code
+     */
+    HRESULT (*pfnSafeArrayCopyOutIfaceParamHelper)(IUnknown ***ppaObj, ULONG *pcObj, SAFEARRAY *psa);
+    /**
+     * Free a safearray
+     *
+     * @param psa           pointer to safearray for getting the data
+     * @returns COM/XPCOM error code
+     */
+    HRESULT (*pfnSafeArrayDestroy)(SAFEARRAY *psa);
+
+#ifndef WIN32
+    /**
+     * Get XPCOM event queue. Deprecated!
      *
      * @param ppEventQueue      output parameter for nsIEventQueue reference,
      *              owned by C bindings.
      */
     void  (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
+#endif /* !WIN32 */
 
     /**
-     * Get current XPCOM exception.
+     * Get current COM/XPCOM exception.
      *
-     * @param ppException       output parameter for nsIException reference,
+     * @param ppException       output parameter for exception info reference,
      *              may be @c NULL if no exception object has been created by
-     *              a previous XPCOM call.
-     * @returns XPCOM error code
+     *              a previous COM/XPCOM call.
+     * @returns COM/XPCOM error code
      */
-    nsresult (*pfnGetException)(nsIException **ppException);
+    HRESULT (*pfnGetException)(IErrorInfo **ppException);
     /**
-     * Clears current XPCOM exception.
+     * Clears current COM/XPCOM exception.
      *
-     * @returns XPCOM error code
+     * @returns COM/XPCOM error code
      */
-    nsresult (*pfnClearException)(void);
+    HRESULT (*pfnClearException)(void);
+
+    /**
+     * Process the event queue for a given amount of time.
+     *
+     * Must be called on the primary thread. Typical timeouts are from 200 to
+     * 5000 msecs, to allow for checking a volatile variable if the event queue
+     * processing should be terminated (,
+     * or 0 if only the pending events should be processed, without waiting.
+     *
+     * @param iTimeoutMS        how long to process the event queue, -1 means
+     *              infinitely long
+     * @returns status code
+     * @retval 0 if at least one event has been processed
+     * @retval 1 if any signal interrupted the native system call (or returned
+     *      otherwise)
+     * @retval 2 if the event queue was explicitly interrupted
+     * @retval 3 if the timeout expired
+     * @retval 4 if the function was called from the wrong thread
+     * @retval 5 for all other (unexpected) errors
+     */
+    int (*pfnProcessEventQueue)(LONG64 iTimeoutMS);
+    /**
+     * Interrupt event queue processing.
+     *
+     * Can be called on any thread. Note that this function is not async-signal
+     * safe, so never use it in such a context, instead use a volatile global
+     * variable and a sensible timeout.
+     * @returns 0 if successful, 1 otherwise.
+     */
+    int (*pfnInterruptEventQueueProcessing)(void);
 
     /** Tail version, same as uVersion. */
     unsigned uEndVersion;
-} VBOXXPCOMC;
-/** Pointer to a const VBoxXPCOMC function table. */
-typedef VBOXXPCOMC const *PCVBOXXPCOM;
+} VBOXCAPI;
+/** Pointer to a const VBOXCAPI function table. */
+typedef VBOXCAPI const *PCVBOXCAPI;
+#ifndef WIN32
+/** Backwards compatibility: Pointer to a const VBOXCAPI function table.
+ * Use PCVBOXCAPI instead. */
+typedef VBOXCAPI const *PCVBOXXPCOM;
+#endif /* !WIN32 */
+
+#ifndef WIN32
+/** Backwards compatibility: make sure old code using VBOXXPCOMC still compiles.
+ * Use VBOXCAPI instead. */
+#define VBOXXPCOMC VBOXCAPI
+#endif /* !WIN32 */
 
 /** The current interface version.
- * For use with VBoxGetXPCOMCFunctions and to be found in
- * VBOXXPCOMC::uVersion. */
-#define VBOX_XPCOMC_VERSION     0x00030000U
-
-VBOXXPCOMC_DECL(PCVBOXXPCOM) VBoxGetXPCOMCFunctions(unsigned uVersion);
-/** Typedef for VBoxGetXPCOMCFunctions. */
-typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
-
-/** The symbol name of VBoxGetXPCOMCFunctions. */
-#if defined(__OS2__)
-# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME   "_VBoxGetXPCOMCFunctions"
-#else
-# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME   "VBoxGetXPCOMCFunctions"
-#endif
+ * For use with VBoxGetCAPIFunctions and to be found in VBOXCAPI::uVersion. */
+#define VBOX_CAPI_VERSION 0x00040000U
+
+#ifndef WIN32
+/** Backwards compatibility: The current interface version.
+ * Use VBOX_CAPI_VERSION instead. */
+#define VBOX_XPCOMC_VERSION VBOX_CAPI_VERSION
+#endif /* !WIN32 */
+
+/** VBoxGetCAPIFunctions. */
+VBOXCAPI_DECL(PCVBOXCAPI) VBoxGetCAPIFunctions(unsigned uVersion);
+#ifndef WIN32
+/** Backwards compatibility: VBoxGetXPCOMCFunctions.
+ * Use VBoxGetCAPIFunctions instead. */
+VBOXCAPI_DECL(PCVBOXCAPI) VBoxGetXPCOMCFunctions(unsigned uVersion);
+#endif /* !WIN32 */
+
+/** Typedef for VBoxGetCAPIFunctions. */
+typedef PCVBOXCAPI (*PFNVBOXGETCAPIFUNCTIONS)(unsigned uVersion);
+#ifndef WIN32
+/** Backwards compatibility: Typedef for VBoxGetXPCOMCFunctions.
+ * Use PFNVBOXGETCAPIFUNCTIONS instead. */
+typedef PCVBOXCAPI (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
+#endif /* !WIN32 */
+
+/** The symbol name of VBoxGetCAPIFunctions. */
+#ifdef __OS2__
+# define VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME "_VBoxGetCAPIFunctions"
+#else /* !__OS2__ */
+# define VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME "VBoxGetCAPIFunctions"
+#endif /* !__OS2__ */
+#ifndef WIN32
+/** Backwards compatibility: The symbol name of VBoxGetXPCOMCFunctions.
+ * Use VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME instead. */
+# ifdef __OS2__
+#  define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "_VBoxGetXPCOMCFunctions"
+# else /* !__OS2__ */
+#  define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "VBoxGetXPCOMCFunctions"
+# endif /* !__OS2__ */
+#endif /* !WIN32 */
 
 
 #ifdef __cplusplus
 }
-#endif
+#endif /* __cplusplus */
 
-#endif /* !___VirtualBox_CXPCOM_h */
+#endif /* !___VirtualBox_CAPI_h */
 </xsl:text>
 </xsl:template>
 
 <!--
  *  ignore all |if|s except those for XPIDL target
+-->
 <xsl:template match="if">
   <xsl:if test="@target='xpidl'">
     <xsl:apply-templates/>
@@ -1184,45 +1610,6 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
   </xsl:if>
 </xsl:template>
 
--->
-
-<!--
- *  cpp_quote
-<xsl:template match="cpp">
-  <xsl:if test="text()">
-    <xsl:text>%{C++</xsl:text>
-    <xsl:value-of select="text()"/>
-    <xsl:text>&#x0A;%}&#x0A;&#x0A;</xsl:text>
-  </xsl:if>
-  <xsl:if test="not(text()) and @line">
-    <xsl:text>%{C++&#x0A;</xsl:text>
-    <xsl:value-of select="@line"/>
-    <xsl:text>&#x0A;%}&#x0A;&#x0A;</xsl:text>
-  </xsl:if>
-</xsl:template>
--->
-
-
-<!--
- *  #if statement (@if attribute)
- *  @note
- *      xpidl doesn't support any preprocessor defines other than #include
- *      (it just ignores them), so the generated IDL will most likely be
- *      invalid. So for now we forbid using @if attributes
--->
-<xsl:template match="@if" mode="begin">
-  <xsl:message terminate="yes">
-    @if attributes are not currently allowed because xpidl lacks
-    support for #ifdef and stuff.
-  </xsl:message>
-  <xsl:text>#if </xsl:text>
-  <xsl:value-of select="."/>
-  <xsl:text>&#x0A;</xsl:text>
-</xsl:template>
-<xsl:template match="@if" mode="end">
-  <xsl:text>#endif&#x0A;</xsl:text>
-</xsl:template>
-
 
 <!--
  *  libraries
@@ -1235,10 +1622,10 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
   </xsl:for-each>
   <xsl:text>&#x0A;&#x0A;</xsl:text>
   <!-- forward declarations -->
-  <xsl:apply-templates select="if | interface" mode="forward"/>
+  <xsl:apply-templates select="interface | if/interface" mode="forward"/>
   <xsl:text>&#x0A;</xsl:text>
   <!-- typedef'ing the struct declarations -->
-  <xsl:apply-templates select="if | interface" mode="typedef"/>
+  <xsl:apply-templates select="interface | if/interface" mode="typedef"/>
   <xsl:text>&#x0A;</xsl:text>
   <!-- all enums go first -->
   <xsl:apply-templates select="enum | if/enum"/>
@@ -1262,9 +1649,11 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
  *  forward declarations
 -->
 <xsl:template match="interface" mode="forward">
-  <xsl:text>struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>;&#x0A;</xsl:text>
+  <xsl:if test="not(@internal='yes')">
+    <xsl:text>interface </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>;&#x0A;</xsl:text>
+  </xsl:if>
 </xsl:template>
 
 
@@ -1272,93 +1661,298 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
  *  typedef'ing the struct declarations
 -->
 <xsl:template match="interface" mode="typedef">
-  <xsl:text>typedef struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text> </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>;&#x0A;</xsl:text>
+  <xsl:if test="not(@internal='yes')">
+    <xsl:text>typedef interface </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text> </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>;&#x0A;</xsl:text>
+  </xsl:if>
 </xsl:template>
 
 
 <!--
- *  interfaces
+ *  COBJMACRO style convenience macros for calling methods
 -->
-<xsl:template match="interface">
-  <xsl:text>/* Start of struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text> Declaration */&#x0A;</xsl:text>
-  <xsl:text>#define </xsl:text>
-  <xsl:call-template name="uppercase">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:value-of select="concat('_IID_STR "', at uuid,'"')"/>
-  <xsl:text>&#x0A;</xsl:text>
-  <xsl:text>#define </xsl:text>
-  <xsl:call-template name="uppercase">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_IID { \&#x0A;</xsl:text>
-  <xsl:text>    0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
-  <xsl:text>, \&#x0A;    </xsl:text>
-  <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
-  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
-  <xsl:text> } \&#x0A;}&#x0A;</xsl:text>
-  <xsl:text>struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>_vtbl&#x0A;{&#x0A;</xsl:text>
-  <xsl:text>    </xsl:text>
+<xsl:template match="interface" mode="cobjmacro">
+  <xsl:param name="iface"/>
+
+  <xsl:variable name="extends" select="@extends"/>
   <xsl:choose>
-    <xsl:when test="@extends='$unknown'">struct nsISupports_vtbl nsisupports;</xsl:when>
-    <xsl:when test="@extends='$dispatched'">struct nsISupports_vtbl nsisupports;</xsl:when>
-    <xsl:when test="@extends='$errorinfo'">struct nsIException_vtbl nsiexception;</xsl:when>
+    <xsl:when test="$extends='$unknown'">
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_AddRef(p) ((p)->lpVtbl->AddRef(p))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_Release(p) ((p)->lpVtbl->Release(p))&#x0A;</xsl:text>
+    </xsl:when>
+    <xsl:when test="$extends='$errorinfo'">
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_AddRef(p) ((p)->lpVtbl->AddRef(p))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_Release(p) ((p)->lpVtbl->Release(p))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Message(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetMessage(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Result(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetResult(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_ColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Location(p, aLocation) ((p)->lpVtbl->GetLocation(p, aLocation))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetLocation(p, aLocation) ((p)->lpVtbl->GetLocation(p, aLocation))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Inner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetInner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_get_Data(p, aData) ((p)->lpVtbl->GetData(p, aData))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_GetData(p, aData) ((p)->lpVtbl->GetData(p, aData))&#x0A;</xsl:text>
+      <xsl:text>#define </xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))&#x0A;</xsl:text>
+    </xsl:when>
     <xsl:otherwise>
-      <xsl:text>struct </xsl:text>
-      <xsl:value-of select="@extends"/>
-      <xsl:text>_vtbl </xsl:text>
-      <xsl:call-template name="lowercase">
-        <xsl:with-param name="str" select="@extends"/>
-      </xsl:call-template>
-      <xsl:text>;</xsl:text>
+      <xsl:apply-templates select="//interface[@name=$extends]" mode="cobjmacro">
+        <xsl:with-param name="iface" select="$iface"/>
+      </xsl:apply-templates>
     </xsl:otherwise>
   </xsl:choose>
-  <xsl:text>&#x0A;&#x0A;</xsl:text>
   <!-- attributes (properties) -->
-  <xsl:apply-templates select="attribute"/>
+  <xsl:apply-templates select="attribute | if/attribute" mode="cobjmacro">
+    <xsl:with-param name="iface" select="$iface"/>
+  </xsl:apply-templates>
   <!-- methods -->
-  <xsl:apply-templates select="method"/>
-  <!-- 'if' enclosed elements, unsorted -->
-  <xsl:apply-templates select="if"/>
-  <!-- -->
-  <xsl:text>};</xsl:text>
-  <xsl:text>&#x0A;&#x0A;</xsl:text>
-  <xsl:text>struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>&#x0A;{&#x0A;    struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>_vtbl *vtbl;&#x0A;};&#x0A;</xsl:text>
-  <xsl:text>/* End of struct </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text> Declaration */&#x0A;&#x0A;&#x0A;</xsl:text>
+  <xsl:apply-templates select="method | if/method" mode="cobjmacro">
+    <xsl:with-param name="iface" select="$iface"/>
+  </xsl:apply-templates>
 </xsl:template>
 
 
 <!--
- *  attributes
+ *  emit flat vtable, compatible with COM
 -->
-<xsl:template match="interface//attribute">
-  <xsl:apply-templates select="@if" mode="begin"/>
-  <xsl:if test="@mod='ptr'">
-    <!-- attributes using native types must be non-scriptable
-    <xsl:text>    [noscript]&#x0A;</xsl:text>-->
+<xsl:template match="interface" mode="vtab_flat">
+  <xsl:param name="iface"/>
+
+  <xsl:variable name="extends" select="@extends"/>
+  <xsl:choose>
+    <xsl:when test="$extends='$unknown'">
+      <xsl:text>    nsresult (*QueryInterface)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, const nsID *iid, void **resultp);&#x0A;</xsl:text>
+      <xsl:text>    nsrefcnt (*AddRef)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis);&#x0A;</xsl:text>
+      <xsl:text>    nsrefcnt (*Release)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis);&#x0A;</xsl:text>
+    </xsl:when>
+    <xsl:when test="$extends='$errorinfo'">
+      <xsl:text>    nsresult (*QueryInterface)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, const nsID *iid, void **resultp);&#x0A;</xsl:text>
+      <xsl:text>    nsrefcnt (*AddRef)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis);&#x0A;</xsl:text>
+      <xsl:text>    nsrefcnt (*Release)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetMessage)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, PRUnichar * *aMessage);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetResult)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, nsresult *aResult);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetName)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text>*pThis, PRUnichar * *aName);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetFilename)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, PRUnichar * *aFilename);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetLineNumber)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, PRUint32 *aLineNumber);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetColumnNumber)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, PRUint32 *aColumnNumber);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetLocation)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, nsIStackFrame * *aLocation);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetInner)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, nsIException * *aInner);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*GetData)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, nsISupports * *aData);&#x0A;</xsl:text>
+      <xsl:text>    nsresult (*ToString)(</xsl:text>
+      <xsl:value-of select="$iface"/>
+      <xsl:text> *pThis, PRUnichar **_retval);&#x0A;</xsl:text>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:apply-templates select="//interface[@name=$extends]" mode="vtab_flat">
+        <xsl:with-param name="iface" select="$iface"/>
+      </xsl:apply-templates>
+    </xsl:otherwise>
+  </xsl:choose>
+  <!-- attributes (properties) -->
+  <xsl:apply-templates select="attribute | if/attribute">
+    <xsl:with-param name="iface" select="$iface"/>
+  </xsl:apply-templates>
+  <!-- methods -->
+  <xsl:apply-templates select="method | if/method">
+    <xsl:with-param name="iface" select="$iface"/>
+  </xsl:apply-templates>
+</xsl:template>
+
+
+<!--
+ *  interfaces
+-->
+<xsl:template match="interface">
+  <xsl:if test="not(@internal='yes')">
+    <xsl:text>/* Start of struct </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text> declaration */&#x0A;</xsl:text>
+    <xsl:text>#define </xsl:text>
+    <xsl:call-template name="uppercase">
+      <xsl:with-param name="str" select="@name"/>
+    </xsl:call-template>
+    <xsl:value-of select="concat('_IID_STR "', at uuid,'"')"/>
+    <xsl:text>&#x0A;</xsl:text>
+    <xsl:text>#define </xsl:text>
+    <xsl:call-template name="uppercase">
+      <xsl:with-param name="str" select="@name"/>
+    </xsl:call-template>
+    <xsl:text>_IID { \&#x0A;</xsl:text>
+    <xsl:text>    0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
+    <xsl:text>, \&#x0A;    </xsl:text>
+    <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
+    <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
+    <xsl:text> } \&#x0A;}&#x0A;</xsl:text>
+    <xsl:text>/* COM compatibility */&#x0A;</xsl:text>
+    <xsl:text>VBOX_EXTERN_CONST(nsIID, IID_</xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>);&#x0A;</xsl:text>
+    <xsl:text>#ifndef VBOX_WITH_GLUE&#x0A;</xsl:text>
+    <xsl:text>struct </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>_vtbl&#x0A;{&#x0A;</xsl:text>
+    <xsl:text>    </xsl:text>
+    <xsl:choose>
+      <xsl:when test="@extends='$unknown'">struct nsISupports_vtbl nsisupports;</xsl:when>
+      <xsl:when test="@extends='$errorinfo'">struct nsIException_vtbl nsiexception;</xsl:when>
+      <xsl:otherwise>
+        <xsl:text>struct </xsl:text>
+        <xsl:value-of select="@extends"/>
+        <xsl:text>_vtbl </xsl:text>
+        <xsl:call-template name="lowercase">
+          <xsl:with-param name="str" select="@extends"/>
+        </xsl:call-template>
+        <xsl:text>;</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+    <xsl:text>&#x0A;&#x0A;</xsl:text>
+    <!-- attributes (properties) -->
+    <xsl:apply-templates select="attribute | if/attribute"/>
+    <!-- methods -->
+    <xsl:apply-templates select="method | if/method"/>
+    <!-- -->
+    <xsl:text>};&#x0A;</xsl:text>
+    <xsl:text>#else /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+    <xsl:text>struct </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>Vtbl&#x0A;{&#x0A;</xsl:text>
+    <xsl:apply-templates select="." mode="vtab_flat">
+      <xsl:with-param name="iface" select="@name"/>
+    </xsl:apply-templates>
+    <xsl:text>};&#x0A;</xsl:text>
+    <xsl:apply-templates select="." mode="cobjmacro">
+      <xsl:with-param name="iface" select="@name"/>
+    </xsl:apply-templates>
+    <!-- -->
+    <xsl:text>#endif /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+    <xsl:text>&#x0A;</xsl:text>
+    <xsl:text>interface </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>&#x0A;{&#x0A;</xsl:text>
+    <xsl:text>#ifndef VBOX_WITH_GLUE&#x0A;</xsl:text>
+    <xsl:text>    struct </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>_vtbl *vtbl;&#x0A;</xsl:text>
+    <xsl:text>#else /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+    <xsl:text>    CONST_VTBL struct </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>Vtbl *lpVtbl;&#x0A;</xsl:text>
+    <xsl:text>#endif /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+    <xsl:text>};&#x0A;</xsl:text>
+    <xsl:text>/* End of struct </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text> declaration */&#x0A;&#x0A;&#x0A;</xsl:text>
   </xsl:if>
+</xsl:template>
+
+
+<!--
+ *  attributes
+-->
+<xsl:template match="attribute">
+  <xsl:param name="iface" select="ancestor::interface/@name"/>
+
   <xsl:choose>
     <!-- safearray pseudo attribute -->
     <xsl:when test="@safearray='yes'">
@@ -1368,7 +1962,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
         <xsl:with-param name="str" select="@name"/>
       </xsl:call-template>
       <xsl:text>)(</xsl:text>
-      <xsl:value-of select="../@name" />
+      <xsl:value-of select="$iface" />
       <xsl:text> *pThis, </xsl:text>
       <!-- array size -->
       <xsl:text>PRUint32 *</xsl:text>
@@ -1386,7 +1980,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
           <xsl:with-param name="str" select="@name"/>
         </xsl:call-template>
         <xsl:text>)(</xsl:text>
-        <xsl:value-of select="../@name" />
+        <xsl:value-of select="$iface" />
         <xsl:text> *pThis, </xsl:text>
         <!-- array size -->
         <xsl:text>PRUint32 </xsl:text>
@@ -1408,7 +2002,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
           <xsl:with-param name="str" select="@name"/>
         </xsl:call-template>
         <xsl:text>)(</xsl:text>
-        <xsl:value-of select="../@name" />
+        <xsl:value-of select="$iface" />
         <xsl:text> *pThis, </xsl:text>
         <xsl:apply-templates select="@type" mode="forwarder"/>
         <xsl:text> *</xsl:text>
@@ -1424,7 +2018,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
             <xsl:with-param name="str" select="@name"/>
           </xsl:call-template>
           <xsl:text>)(</xsl:text>
-          <xsl:value-of select="../@name" />
+          <xsl:value-of select="$iface" />
           <xsl:text> *pThis, </xsl:text>
           <xsl:apply-templates select="@type" mode="forwarder"/>
           <xsl:text> *</xsl:text>
@@ -1435,7 +2029,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
             <xsl:with-param name="str" select="@name"/>
           </xsl:call-template>
           <xsl:text>)(</xsl:text>
-          <xsl:value-of select="../@name" />
+          <xsl:value-of select="$iface" />
           <xsl:text> *pThis, </xsl:text>
           <xsl:apply-templates select="@type" mode="forwarder"/>
           <xsl:text> </xsl:text>
@@ -1445,169 +2039,102 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
       </xsl:choose>
     </xsl:otherwise>
   </xsl:choose>
-  <xsl:apply-templates select="@if" mode="end"/>
   <xsl:text>&#x0A;</xsl:text>
 </xsl:template>
 
-<xsl:template match="interface//attribute" mode="forwarder">
-
-  <xsl:variable name="parent" select="ancestor::interface"/>
+<xsl:template match="attribute" mode="cobjmacro">
+  <xsl:param name="iface"/>
 
-  <xsl:apply-templates select="@if" mode="begin"/>
-
-  <!-- getter: COM_FORWARD_Interface_GETTER_Name_TO(smth) -->
-  <xsl:text>#define COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_GETTER_</xsl:text>
-  <xsl:call-template name="capitalize">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_TO(smth) NS_IMETHOD Get</xsl:text>
+  <!-- getter (COM compatible) -->
+  <xsl:text>#define </xsl:text>
+  <xsl:value-of select="concat($iface, '_get_')"/>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text> (</xsl:text>
-  <xsl:if test="@safearray='yes'">
-    <xsl:text>PRUint32 * a</xsl:text>
-    <xsl:call-template name="capitalize">
-      <xsl:with-param name="str" select="@name"/>
-    </xsl:call-template>
-    <xsl:text>Size, </xsl:text>
-  </xsl:if>
-  <xsl:apply-templates select="@type" mode="forwarder"/>
-  <xsl:if test="@safearray='yes'">
-    <xsl:text> *</xsl:text>
-  </xsl:if>
-  <xsl:text> * a</xsl:text>
+  <xsl:text>(p, a</xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>) { return smth Get</xsl:text>
+  <xsl:text>) ((p)->lpVtbl->Get</xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text> (</xsl:text>
-  <xsl:if test="@safearray='yes'">
-    <xsl:text>a</xsl:text>
-    <xsl:call-template name="capitalize">
-      <xsl:with-param name="str" select="@name"/>
-    </xsl:call-template>
-    <xsl:text>Size, </xsl:text>
-  </xsl:if>
-  <xsl:text>a</xsl:text>
+  <xsl:text>(p, a</xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>); }&#x0A;</xsl:text>
-  <!-- getter: COM_FORWARD_Interface_GETTER_Name_TO_OBJ(obj) -->
-  <xsl:text>#define COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_GETTER_</xsl:text>
+  <xsl:text>))&#x0A;</xsl:text>
+
+  <!-- getter (XPCOM compatible) -->
+  <xsl:text>#define </xsl:text>
+  <xsl:value-of select="concat($iface, '_Get')"/>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>_TO_OBJ(obj) COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_GETTER_</xsl:text>
+  <xsl:text>(p, a</xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>_TO ((obj)->)&#x0A;</xsl:text>
-  <!-- getter: COM_FORWARD_Interface_GETTER_Name_TO_BASE(base) -->
-  <xsl:text>#define COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_GETTER_</xsl:text>
+  <xsl:text>) ((p)->lpVtbl->Get</xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>_TO_BASE(base) COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_GETTER_</xsl:text>
+  <xsl:text>(p, a</xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>_TO (base::)&#x0A;</xsl:text>
-  <!-- -->
+  <xsl:text>))&#x0A;</xsl:text>
+
   <xsl:if test="not(@readonly='yes')">
-    <!-- setter: COM_FORWARD_Interface_SETTER_Name_TO(smth) -->
-    <xsl:text>#define COM_FORWARD_</xsl:text>
-    <xsl:value-of select="$parent/@name"/>
-    <xsl:text>_SETTER_</xsl:text>
+    <!-- setter (COM compatible) -->
+    <xsl:text>#define </xsl:text>
+    <xsl:value-of select="concat($iface, '_set_')"/>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>_TO(smth) NS_IMETHOD Set</xsl:text>
-    <xsl:call-template name="capitalize">
-      <xsl:with-param name="str" select="@name"/>
-    </xsl:call-template>
-    <xsl:text> (</xsl:text>
-    <xsl:if test="@safearray='yes'">
-      <xsl:text>PRUint32 a</xsl:text>
-      <xsl:call-template name="capitalize">
-        <xsl:with-param name="str" select="@name"/>
-      </xsl:call-template>
-      <xsl:text>Size, </xsl:text>
-    </xsl:if>
-    <xsl:if test="not(@safearray='yes') and (@type='string' or @type='wstring')">
-      <xsl:text>const </xsl:text>
-    </xsl:if>
-    <xsl:apply-templates select="@type" mode="forwarder"/>
-    <xsl:if test="@safearray='yes'">
-      <xsl:text> *</xsl:text>
-    </xsl:if>
-    <xsl:text> a</xsl:text>
+    <xsl:text>(p, a</xsl:text>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>) { return smth Set</xsl:text>
+    <xsl:text>) ((p)->lpVtbl->Set</xsl:text>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text> (a</xsl:text>
+    <xsl:text>(p, a</xsl:text>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>); }&#x0A;</xsl:text>
-    <!-- setter: COM_FORWARD_Interface_SETTER_Name_TO_OBJ(obj) -->
-    <xsl:text>#define COM_FORWARD_</xsl:text>
-    <xsl:value-of select="$parent/@name"/>
-    <xsl:text>_SETTER_</xsl:text>
+    <xsl:text>))&#x0A;</xsl:text>
+
+    <!-- setter (XPCOM compatible) -->
+    <xsl:text>#define </xsl:text>
+    <xsl:value-of select="concat($iface, '_Set')"/>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>_TO_OBJ(obj) COM_FORWARD_</xsl:text>
-    <xsl:value-of select="$parent/@name"/>
-    <xsl:text>_SETTER_</xsl:text>
+    <xsl:text>(p, a</xsl:text>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>_TO ((obj)->)&#x0A;</xsl:text>
-    <!-- setter: COM_FORWARD_Interface_SETTER_Name_TO_BASE(base) -->
-    <xsl:text>#define COM_FORWARD_</xsl:text>
-    <xsl:value-of select="$parent/@name"/>
-    <xsl:text>_SETTER_</xsl:text>
+    <xsl:text>) ((p)->lpVtbl->Set</xsl:text>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>_TO_BASE(base) COM_FORWARD_</xsl:text>
-    <xsl:value-of select="$parent/@name"/>
-    <xsl:text>_SETTER_</xsl:text>
+    <xsl:text>(p, a</xsl:text>
     <xsl:call-template name="capitalize">
       <xsl:with-param name="str" select="@name"/>
     </xsl:call-template>
-    <xsl:text>_TO (base::)&#x0A;</xsl:text>
-  </xsl:if>
-
-  <xsl:apply-templates select="@if" mode="end"/>
+    <xsl:text>))&#x0A;</xsl:text>
 
+  </xsl:if>
 </xsl:template>
 
-
 <!--
  *  methods
 -->
-<xsl:template match="interface//method">
-  <xsl:apply-templates select="@if" mode="begin"/>
+<xsl:template match="method">
+  <xsl:param name="iface" select="ancestor::interface/@name"/>
+
   <xsl:if test="param/@mod='ptr'">
     <!-- methods using native types must be non-scriptable
     <xsl:text>    [noscript]&#x0A;</xsl:text>-->
@@ -1619,7 +2146,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
   <xsl:if test="param">
     <xsl:text>)(&#x0A;</xsl:text>
     <xsl:text>        </xsl:text>
-    <xsl:value-of select="../@name" />
+    <xsl:value-of select="$iface" />
     <xsl:text> *pThis,&#x0A;</xsl:text>
     <xsl:for-each select="param [position() != last()]">
       <xsl:text>        </xsl:text>
@@ -1632,109 +2159,39 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
   </xsl:if>
   <xsl:if test="not(param)">
     <xsl:text>)(</xsl:text>
-    <xsl:value-of select="../@name" />
+    <xsl:value-of select="$iface" />
     <xsl:text> *pThis );&#x0A;</xsl:text>
   </xsl:if>
-  <xsl:apply-templates select="@if" mode="end"/>
   <xsl:text>&#x0A;</xsl:text>
 </xsl:template>
 
-<xsl:template match="interface//method" mode="forwarder">
+<xsl:template match="method" mode="cobjmacro">
+  <xsl:param name="iface"/>
 
-  <xsl:variable name="parent" select="ancestor::interface"/>
-
-  <xsl:apply-templates select="@if" mode="begin"/>
-
-  <xsl:text>#define COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_</xsl:text>
-  <xsl:call-template name="capitalize">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_TO(smth) NS_IMETHOD </xsl:text>
-  <xsl:call-template name="capitalize">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:choose>
-    <xsl:when test="param">
-      <xsl:text> (</xsl:text>
-      <xsl:for-each select="param [position() != last()]">
-        <xsl:apply-templates select="." mode="forwarder"/>
-        <xsl:text>, </xsl:text>
-      </xsl:for-each>
-      <xsl:apply-templates select="param [last()]" mode="forwarder"/>
-      <xsl:text>) { return smth </xsl:text>
-      <xsl:call-template name="capitalize">
-        <xsl:with-param name="str" select="@name"/>
-      </xsl:call-template>
-      <xsl:text> (</xsl:text>
-      <xsl:for-each select="param [position() != last()]">
-        <xsl:if test="@safearray='yes'">
-          <xsl:text>a</xsl:text>
-          <xsl:call-template name="capitalize">
-            <xsl:with-param name="str" select="@name"/>
-          </xsl:call-template>
-          <xsl:text>Size+++, </xsl:text>
-        </xsl:if>
-        <xsl:text>a</xsl:text>
-        <xsl:call-template name="capitalize">
-          <xsl:with-param name="str" select="@name"/>
-        </xsl:call-template>
-        <xsl:text>, </xsl:text>
-      </xsl:for-each>
-      <xsl:if test="param [last()]/@safearray='yes'">
-        <xsl:text>a</xsl:text>
-        <xsl:call-template name="capitalize">
-          <xsl:with-param name="str" select="param [last()]/@name"/>
-        </xsl:call-template>
-        <xsl:text>Size, </xsl:text>
-      </xsl:if>
-      <xsl:text>a</xsl:text>
-      <xsl:call-template name="capitalize">
-        <xsl:with-param name="str" select="param [last()]/@name"/>
-      </xsl:call-template>
-      <xsl:text>); }</xsl:text>
-    </xsl:when>
-    <xsl:otherwise test="not(param)">
-      <xsl:text>() { return smth </xsl:text>
-      <xsl:call-template name="capitalize">
-        <xsl:with-param name="str" select="@name"/>
-      </xsl:call-template>
-      <xsl:text>(); }</xsl:text>
-    </xsl:otherwise>
-  </xsl:choose>
-  <xsl:text>&#x0A;</xsl:text>
-  <!-- COM_FORWARD_Interface_Method_TO_OBJ(obj) -->
-  <xsl:text>#define COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_</xsl:text>
-  <xsl:call-template name="capitalize">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_TO_OBJ(obj) COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_</xsl:text>
-  <xsl:call-template name="capitalize">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_TO ((obj)->)&#x0A;</xsl:text>
-  <!-- COM_FORWARD_Interface_Method_TO_BASE(base) -->
-  <xsl:text>#define COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_</xsl:text>
+  <xsl:text>#define </xsl:text>
+  <xsl:value-of select="concat($iface, '_')"/>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>_TO_BASE(base) COM_FORWARD_</xsl:text>
-  <xsl:value-of select="$parent/@name"/>
-  <xsl:text>_</xsl:text>
+  <xsl:text>(p</xsl:text>
+  <xsl:for-each select="param">
+    <xsl:text>, a</xsl:text>
+    <xsl:call-template name="capitalize">
+      <xsl:with-param name="str" select="@name"/>
+    </xsl:call-template>
+  </xsl:for-each>
+  <xsl:text>) ((p)->lpVtbl-></xsl:text>
   <xsl:call-template name="capitalize">
     <xsl:with-param name="str" select="@name"/>
   </xsl:call-template>
-  <xsl:text>_TO (base::)&#x0A;</xsl:text>
-
-  <xsl:apply-templates select="@if" mode="end"/>
-
+  <xsl:text>(p</xsl:text>
+  <xsl:for-each select="param">
+    <xsl:text>, a</xsl:text>
+    <xsl:call-template name="capitalize">
+      <xsl:with-param name="str" select="@name"/>
+    </xsl:call-template>
+  </xsl:for-each>
+  <xsl:text>))&#x0A;</xsl:text>
 </xsl:template>
 
 
@@ -1781,14 +2238,10 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
   <xsl:value-of select="@name"/>
   <xsl:text>;1"&#x0A;</xsl:text>
   <!-- CLSID_xxx declarations for XPCOM, for compatibility with Win32 -->
-  <xsl:text>/* for compatibility with Win32 */&#x0A;</xsl:text>
-  <xsl:text>#define CLSID_</xsl:text>
+  <xsl:text>/* COM compatibility */&#x0A;</xsl:text>
+  <xsl:text>VBOX_EXTERN_CONST(nsCID, CLSID_</xsl:text>
   <xsl:value-of select="@name"/>
-  <xsl:text> (nsCID) NS_</xsl:text>
-  <xsl:call-template name="uppercase">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_CID&#x0A;</xsl:text>
+  <xsl:text>);&#x0A;</xsl:text>
   <xsl:text>&#x0A;&#x0A;</xsl:text>
 </xsl:template>
 
@@ -1799,7 +2252,7 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
 <xsl:template match="enum">
   <xsl:text>/* Start of enum </xsl:text>
   <xsl:value-of select="@name"/>
-  <xsl:text> Declaration */&#x0A;</xsl:text>
+  <xsl:text> declaration */&#x0A;</xsl:text>
   <xsl:text>#define </xsl:text>
   <xsl:call-template name="uppercase">
     <xsl:with-param name="str" select="@name"/>
@@ -1841,7 +2294,9 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
   <xsl:text>};&#x0A;</xsl:text>
   <xsl:text>/* End of enum </xsl:text>
   <xsl:value-of select="@name"/>
-  <xsl:text> Declaration */&#x0A;&#x0A;&#x0A;</xsl:text>
+  <xsl:text> declaration */
+#define </xsl:text>
+  <xsl:value-of select="concat(@name, '_T PRUint32&#x0A;&#x0A;&#x0A;')"/>
 </xsl:template>
 
 
diff --git a/src/VBox/Main/cbinding/makefile.tstCAPIGlue b/src/VBox/Main/cbinding/makefile.tstCAPIGlue
new file mode 100644
index 0000000..057395a
--- /dev/null
+++ b/src/VBox/Main/cbinding/makefile.tstCAPIGlue
@@ -0,0 +1,50 @@
+# $Revision: 91907 $
+## @file makefile.tstCAPIGlue
+# Makefile for sample program illustrating use of C binding for COM/XPCOM.
+#
+
+#
+# Copyright (C) 2009-2014 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+PATH_SDK      = ../../..
+CAPI_INC      = -I$(PATH_SDK)/bindings/c/include
+ifeq ($(BUILD_PLATFORM),win)
+PLATFORM_INC  = -I$(PATH_SDK)/bindings/mscom/include
+PLATFORM_LIB  = $(PATH_SDK)/bindings/mscom/lib
+else
+PLATFORM_INC  = -I$(PATH_SDK)/bindings/xpcom/include
+PLATFORM_LIB  = $(PATH_SDK)/bindings/xpcom/lib
+endif
+GLUE_DIR      = $(PATH_SDK)/bindings/c/glue
+GLUE_INC      = -I$(GLUE_DIR)
+
+CC            = gcc
+CFLAGS        = -g -Wall
+
+.PHONY: all
+all: tstCAPIGlue
+
+.PHONY: clean
+clean:
+	rm -f tstCAPIGlue.o VBoxCAPIGlue.o VirtualBox_i.o tstCAPIGlue
+
+tstCAPIGlue: tstCAPIGlue.o VBoxCAPIGlue.o VirtualBox_i.o
+	$(CC) -o $@ $^ -ldl -lpthread
+
+tstCAPIGlue.o: tstCAPIGlue.c
+	$(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+VBoxCAPIGlue.o: $(GLUE_DIR)/VBoxCAPIGlue.c
+	$(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+VirtualBox_i.o: $(PLATFORM_LIB)/VirtualBox_i.c
+	$(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
diff --git a/src/VBox/Main/cbinding/makefile.tstXPCOMCGlue b/src/VBox/Main/cbinding/makefile.tstXPCOMCGlue
deleted file mode 100644
index 2615a82..0000000
--- a/src/VBox/Main/cbinding/makefile.tstXPCOMCGlue
+++ /dev/null
@@ -1,39 +0,0 @@
-# $Revision: 90721 $
-## @file makefile.tstXPCOMCGlue
-# Makefile for sample program illustrating use of C binding for XPCOM.
-#
-
-#
-# Copyright (C) 2009-2013 Oracle Corporation
-#
-# This file is part of VirtualBox Open Source Edition (OSE), as
-# available from http://www.virtualbox.org. This file is free software;
-# you can redistribute it and/or modify it under the terms of the GNU
-# General Public License (GPL) as published by the Free Software
-# Foundation, in version 2 as it comes in the "COPYING" file of the
-# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-#
-
-INCS_XPCOM    = -I../../include
-GLUE_DIR      = ..
-GLUE_INC      = -I..
-
-CC            = gcc
-CFLAGS        = -g -Wall
-
-.PHONY: all
-all: tstXPCOMCGlue
-
-.PHONY: clean
-clean:
-	rm -f tstXPCOMCGlue.o tstXPCOMCGlue VBoxXPCOMCGlue.o
-
-tstXPCOMCGlue: tstXPCOMCGlue.o VBoxXPCOMCGlue.o
-	$(CC) -o $@ $^ -ldl -lpthread
-
-tstXPCOMCGlue.o: tstXPCOMCGlue.c
-	$(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $<
-
-VBoxXPCOMCGlue.o: $(GLUE_DIR)/VBoxXPCOMCGlue.c
-	$(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $<
diff --git a/src/VBox/Main/cbinding/tstCAPIGlue.c b/src/VBox/Main/cbinding/tstCAPIGlue.c
new file mode 100644
index 0000000..5715a6f
--- /dev/null
+++ b/src/VBox/Main/cbinding/tstCAPIGlue.c
@@ -0,0 +1,1112 @@
+/* $Revision: 91907 $ */
+/** @file tstCAPIGlue.c
+ * Demonstrator program to illustrate use of C bindings of Main API.
+ *
+ * It has sample code showing how to retrieve all available error information,
+ * and how to handle active (event delivery through callbacks) or passive
+ * (event delivery through a polling mechanism) event listeners.
+ */
+
+/*
+ * Copyright (C) 2009-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "VBoxCAPIGlue.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifndef WIN32
+# include <signal.h>
+# include <unistd.h>
+# include <sys/poll.h>
+#endif
+
+/**
+ * Select between active event listener (defined) and passive event listener
+ * (undefined). The active event listener case needs much more code, and
+ * additionally requires a lot more platform dependent code.
+ */
+#undef USE_ACTIVE_EVENT_LISTENER
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Set by Ctrl+C handler. */
+static volatile int g_fStop = 0;
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+# ifdef WIN32
+/** The COM type information for IEventListener, for implementing IDispatch. */
+static ITypeInfo *g_pTInfoIEventListener = NULL;
+# endif /* WIN32 */
+#endif /* USE_ACTIVE_EVENT_LISTENER */
+
+static const char *GetStateName(MachineState_T machineState)
+{
+    switch (machineState)
+    {
+        case MachineState_Null:                return "<null>";
+        case MachineState_PoweredOff:          return "PoweredOff";
+        case MachineState_Saved:               return "Saved";
+        case MachineState_Teleported:          return "Teleported";
+        case MachineState_Aborted:             return "Aborted";
+        case MachineState_Running:             return "Running";
+        case MachineState_Paused:              return "Paused";
+        case MachineState_Stuck:               return "Stuck";
+        case MachineState_Teleporting:         return "Teleporting";
+        case MachineState_LiveSnapshotting:    return "LiveSnapshotting";
+        case MachineState_Starting:            return "Starting";
+        case MachineState_Stopping:            return "Stopping";
+        case MachineState_Saving:              return "Saving";
+        case MachineState_Restoring:           return "Restoring";
+        case MachineState_TeleportingPausedVM: return "TeleportingPausedVM";
+        case MachineState_TeleportingIn:       return "TeleportingIn";
+        case MachineState_FaultTolerantSyncing: return "FaultTolerantSyncing";
+        case MachineState_DeletingSnapshotOnline: return "DeletingSnapshotOnline";
+        case MachineState_DeletingSnapshotPaused: return "DeletingSnapshotPaused";
+        case MachineState_RestoringSnapshot:   return "RestoringSnapshot";
+        case MachineState_DeletingSnapshot:    return "DeletingSnapshot";
+        case MachineState_SettingUp:           return "SettingUp";
+        default:                               return "no idea";
+    }
+}
+
+/**
+ * Ctrl+C handler, terminate event listener.
+ *
+ * Remember that most function calls are not allowed in this context (including
+ * printf!), so make sure that this does as little as possible.
+ *
+ * @param  iInfo    Platform dependent detail info (ignored).
+ */
+static BOOL VBOX_WINAPI ctrlCHandler(DWORD iInfo)
+{
+    (void)iInfo;
+    g_fStop = 1;
+    return TRUE;
+}
+
+/**
+ * Sample event processing function, dumping some event information.
+ * Shared between active and passive event demo, to highlight that this part
+ * is identical between the two.
+ */
+static HRESULT EventListenerDemoProcessEvent(IEvent *event)
+{
+    VBoxEventType_T evType;
+    HRESULT rc;
+
+    if (!event)
+    {
+        printf("event null\n");
+        return S_OK;
+    }
+
+    evType = VBoxEventType_Invalid;
+    rc = IEvent_get_Type(event, &evType);
+    if (FAILED(rc))
+    {
+        printf("cannot get event type, rc=%#x\n", rc);
+        return S_OK;
+    }
+
+    switch (evType)
+    {
+        case VBoxEventType_OnMousePointerShapeChanged:
+            printf("OnMousePointerShapeChanged\n");
+            break;
+
+        case VBoxEventType_OnMouseCapabilityChanged:
+            printf("OnMouseCapabilityChanged\n");
+            break;
+
+        case VBoxEventType_OnKeyboardLedsChanged:
+            printf("OnMouseCapabilityChanged\n");
+            break;
+
+        case VBoxEventType_OnStateChanged:
+        {
+            IStateChangedEvent *ev = NULL;
+            enum MachineState state;
+            rc = IEvent_QueryInterface(event, &IID_IStateChangedEvent, (void **)&ev);
+            if (FAILED(rc))
+            {
+                printf("cannot get StateChangedEvent interface, rc=%#x\n", rc);
+                return S_OK;
+            }
+            if (!ev)
+            {
+                printf("StateChangedEvent reference null\n");
+                return S_OK;
+            }
+            rc = IStateChangedEvent_get_State(ev, &state);
+            if (FAILED(rc))
+                printf("warning: cannot get state, rc=%#x\n", rc);
+            IStateChangedEvent_Release(ev);
+            printf("OnStateChanged: %s\n", GetStateName(state));
+
+            fflush(stdout);
+            if (   state == MachineState_PoweredOff
+                || state == MachineState_Saved
+                || state == MachineState_Teleported
+                || state == MachineState_Aborted
+               )
+                g_fStop = 1;
+            break;
+        }
+
+        case VBoxEventType_OnAdditionsStateChanged:
+            printf("OnAdditionsStateChanged\n");
+            break;
+
+        case VBoxEventType_OnNetworkAdapterChanged:
+            printf("OnNetworkAdapterChanged\n");
+            break;
+
+        case VBoxEventType_OnSerialPortChanged:
+            printf("OnSerialPortChanged\n");
+            break;
+
+        case VBoxEventType_OnParallelPortChanged:
+            printf("OnParallelPortChanged\n");
+            break;
+
+        case VBoxEventType_OnStorageControllerChanged:
+            printf("OnStorageControllerChanged\n");
+            break;
+
+        case VBoxEventType_OnMediumChanged:
+            printf("OnMediumChanged\n");
+            break;
+
+        case VBoxEventType_OnVRDEServerChanged:
+            printf("OnVRDEServerChanged\n");
+            break;
+
+        case VBoxEventType_OnUSBControllerChanged:
+            printf("OnUSBControllerChanged\n");
+            break;
+
+        case VBoxEventType_OnUSBDeviceStateChanged:
+            printf("OnUSBDeviceStateChanged\n");
+            break;
+
+        case VBoxEventType_OnSharedFolderChanged:
+            printf("OnSharedFolderChanged\n");
+            break;
+
+        case VBoxEventType_OnRuntimeError:
+            printf("OnRuntimeError\n");
+            break;
+
+        case VBoxEventType_OnCanShowWindow:
+            printf("OnCanShowWindow\n");
+            break;
+        case VBoxEventType_OnShowWindow:
+            printf("OnShowWindow\n");
+            break;
+
+        default:
+            printf("unknown event: %d\n", evType);
+    }
+
+    return S_OK;
+}
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+
+struct IEventListenerDemo;
+typedef struct IEventListenerDemo IEventListenerDemo;
+
+typedef struct IEventListenerDemoVtbl
+{
+    HRESULT (*QueryInterface)(IEventListenerDemo *pThis, REFIID riid, void **ppvObject);
+    ULONG (*AddRef)(IEventListenerDemo *pThis);
+    ULONG (*Release)(IEventListenerDemo *pThis);
+#ifdef WIN32
+    HRESULT (*GetTypeInfoCount)(IEventListenerDemo *pThis, UINT *pctinfo);
+    HRESULT (*GetTypeInfo)(IEventListenerDemo *pThis, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
+    HRESULT (*GetIDsOfNames)(IEventListenerDemo *pThis, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
+    HRESULT (*Invoke)(IEventListenerDemo *pThis, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
+#endif
+    HRESULT (*HandleEvent)(IEventListenerDemo *pThis, IEvent *aEvent);
+} IEventListenerDemoVtbl;
+
+typedef struct IEventListenerDemo
+{
+    struct IEventListenerDemoVtbl *lpVtbl;
+
+    int cRef;
+
+#ifdef WIN32
+    /* Active event delivery needs a free threaded marshaler, as the default
+     * proxy marshaling cannot deal correctly with this case. */
+    IUnknown *pUnkMarshaler;
+#endif
+} IEventListenerDemo;
+
+/* Defines for easily calling IEventListenerDemo functions. */
+
+/* IUnknown functions. */
+#define IEventListenerDemo_QueryInterface(This,riid,ppvObject) \
+    ( (This)->lpVtbl->QueryInterface(This,riid,ppvObject) )
+
+#define IEventListenerDemo_AddRef(This) \
+    ( (This)->lpVtbl->AddRef(This) )
+
+#define IEventListenerDemo_Release(This) \
+    ( (This)->lpVtbl->Release(This) )
+
+#ifdef WIN32
+/* IDispatch functions. */
+#define IEventListenerDemo_GetTypeInfoCount(This,pctinfo) \
+    ( (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) )
+
+#define IEventListenerDemo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+    ( (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) )
+
+#define IEventListenerDemo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+    ( (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )
+
+#define IEventListenerDemo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+    ( (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )
+#endif
+
+/* IEventListener functions. */
+#define IEventListenerDemo_HandleEvent(This,aEvent) \
+    ( (This)->lpVtbl->HandleEvent(This,aEvent) )
+
+
+/**
+ * Event handler function, for active event processing.
+ */
+static HRESULT IEventListenerDemoImpl_HandleEvent(IEventListenerDemo *pThis, IEvent *event)
+{
+    return EventListenerDemoProcessEvent(event);
+}
+
+static HRESULT IEventListenerDemoImpl_QueryInterface(IEventListenerDemo *pThis, const IID *iid, void **resultp)
+{
+    /* match iid */
+    if (    !memcmp(iid, &IID_IEventListener, sizeof(IID))
+        ||  !memcmp(iid, &IID_IDispatch, sizeof(IID))
+        ||  !memcmp(iid, &IID_IUnknown, sizeof(IID)))
+    {
+        IEventListenerDemo_AddRef(pThis);
+        *resultp = pThis;
+        return S_OK;
+    }
+#ifdef WIN32
+    if (!memcmp(iid, &IID_IMarshal, sizeof(IID)))
+        return IUnknown_QueryInterface(pThis->pUnkMarshaler, iid, resultp);
+#endif
+
+    return E_NOINTERFACE;
+}
+
+static HRESULT IEventListenerDemoImpl_AddRef(IEventListenerDemo *pThis)
+{
+    return ++(pThis->cRef);
+}
+
+static HRESULT IEventListenerDemoImpl_Release(IEventListenerDemo *pThis)
+{
+    HRESULT c;
+
+    c = --(pThis->cRef);
+    if (!c)
+        free(pThis);
+    return c;
+}
+
+#ifdef WIN32
+static HRESULT IEventListenerDemoImpl_GetTypeInfoCount(IEventListenerDemo *pThis, UINT *pctinfo)
+{
+    if (!pctinfo)
+        return E_POINTER;
+    *pctinfo = 1;
+    return S_OK;
+}
+
+static HRESULT IEventListenerDemoImpl_GetTypeInfo(IEventListenerDemo *pThis, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    if (!ppTInfo)
+        return E_POINTER;
+    ITypeInfo_AddRef(g_pTInfoIEventListener);
+    *ppTInfo = g_pTInfoIEventListener;
+    return S_OK;
+}
+
+static HRESULT IEventListenerDemoImpl_GetIDsOfNames(IEventListenerDemo *pThis, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    return ITypeInfo_GetIDsOfNames(g_pTInfoIEventListener, rgszNames, cNames, rgDispId);
+}
+
+static HRESULT IEventListenerDemoImpl_Invoke(IEventListenerDemo *pThis, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    return ITypeInfo_Invoke(g_pTInfoIEventListener, (IDispatch *)pThis, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT LoadTypeInfo(REFIID riid, ITypeInfo **pTInfo)
+{
+    HRESULT rc;
+    ITypeLib *pTypeLib;
+    rc = LoadRegTypeLib(&LIBID_VirtualBox, 1 /* major */, 0 /* minor */, 0 /* lcid */, &pTypeLib);
+    if (FAILED(rc))
+        return rc;
+    rc = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, pTInfo);
+
+    /* No longer need access to the type lib, release it. */
+    ITypeLib_Release(pTypeLib);
+
+    return rc;
+}
+#endif
+
+#ifdef __GNUC__
+typedef struct IEventListenerDemoVtblInt
+{
+    ptrdiff_t offset_to_top;
+    void *typeinfo;
+    IEventListenerDemoVtbl lpVtbl;
+} IEventListenerDemoVtblInt;
+
+static IEventListenerDemoVtblInt g_IEventListenerDemoVtblInt =
+{
+    0,      /* offset_to_top */
+    NULL,   /* typeinfo, not vital */
+    {
+        IEventListenerDemoImpl_QueryInterface,
+        IEventListenerDemoImpl_AddRef,
+        IEventListenerDemoImpl_Release,
+#ifdef WIN32
+        IEventListenerDemoImpl_GetTypeInfoCount,
+        IEventListenerDemoImpl_GetTypeInfo,
+        IEventListenerDemoImpl_GetIDsOfNames,
+        IEventListenerDemoImpl_Invoke,
+#endif
+        IEventListenerDemoImpl_HandleEvent
+    }
+};
+#elif defined(_MSC_VER)
+typedef struct IEventListenerDemoVtblInt
+{
+    IEventListenerDemoVtbl lpVtbl;
+} IEventListenerDemoVtblInt;
+
+static IEventListenerDemoVtblInt g_IEventListenerDemoVtblInt =
+{
+    {
+        IEventListenerDemoImpl_QueryInterface,
+        IEventListenerDemoImpl_AddRef,
+        IEventListenerDemoImpl_Release,
+#ifdef WIN32
+        IEventListenerDemoImpl_GetTypeInfoCount,
+        IEventListenerDemoImpl_GetTypeInfo,
+        IEventListenerDemoImpl_GetIDsOfNames,
+        IEventListenerDemoImpl_Invoke,
+#endif
+        IEventListenerDemoImpl_HandleEvent
+    }
+};
+#else
+# error Port me!
+#endif
+
+/**
+ * Register active event listener for the selected VM.
+ *
+ * @param   virtualBox ptr to IVirtualBox object
+ * @param   session    ptr to ISession object
+ * @param   id         identifies the machine to start
+ */
+static void registerActiveEventListener(IVirtualBox *virtualBox, ISession *session, BSTR machineId)
+{
+    IConsole *console = NULL;
+    HRESULT rc;
+
+    rc = ISession_get_Console(session, &console);
+    if ((SUCCEEDED(rc)) && console)
+    {
+        IEventSource *es = NULL;
+        rc = IConsole_get_EventSource(console, &es);
+        if (SUCCEEDED(rc) && es)
+        {
+            static const ULONG interestingEvents[] =
+                {
+                    VBoxEventType_OnMousePointerShapeChanged,
+                    VBoxEventType_OnMouseCapabilityChanged,
+                    VBoxEventType_OnKeyboardLedsChanged,
+                    VBoxEventType_OnStateChanged,
+                    VBoxEventType_OnAdditionsStateChanged,
+                    VBoxEventType_OnNetworkAdapterChanged,
+                    VBoxEventType_OnSerialPortChanged,
+                    VBoxEventType_OnParallelPortChanged,
+                    VBoxEventType_OnStorageControllerChanged,
+                    VBoxEventType_OnMediumChanged,
+                    VBoxEventType_OnVRDEServerChanged,
+                    VBoxEventType_OnUSBControllerChanged,
+                    VBoxEventType_OnUSBDeviceStateChanged,
+                    VBoxEventType_OnSharedFolderChanged,
+                    VBoxEventType_OnRuntimeError,
+                    VBoxEventType_OnCanShowWindow,
+                    VBoxEventType_OnShowWindow
+                };
+            SAFEARRAY *interestingEventsSA = NULL;
+            IEventListenerDemo *consoleListener = NULL;
+
+            /* The VirtualBox API expects enum values as VT_I4, which in the
+             * future can be hopefully relaxed. */
+            interestingEventsSA = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0, sizeof(interestingEvents) / sizeof(interestingEvents[0]));
+            g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(interestingEventsSA, &interestingEvents, sizeof(interestingEvents));
+
+            consoleListener = calloc(1, sizeof(IEventListenerDemo));
+            if (consoleListener)
+            {
+                consoleListener->lpVtbl = &(g_IEventListenerDemoVtblInt.lpVtbl);
+#ifdef WIN32
+                CoCreateFreeThreadedMarshaler((IUnknown *)consoleListener, &consoleListener->pUnkMarshaler);
+#endif
+                IEventListenerDemo_AddRef(consoleListener);
+
+                rc = IEventSource_RegisterListener(es, (IEventListener *)consoleListener,
+                                                   ComSafeArrayAsInParam(interestingEventsSA),
+                                                   1 /* active */);
+                if (SUCCEEDED(rc))
+                {
+                    /* Just wait here for events, no easy way to do this better
+                     * as there's not much to do after this completes. */
+                    printf("Entering event loop, PowerOff the machine to exit or press Ctrl-C to terminate\n");
+                    fflush(stdout);
+#ifdef WIN32
+                    SetConsoleCtrlHandler(ctrlCHandler, TRUE);
+#else
+                    signal(SIGINT, (void (*)(int))ctrlCHandler);
+#endif
+
+                    while (!g_fStop)
+                    {
+                        g_pVBoxFuncs->pfnProcessEventQueue(250);
+                    }
+
+#ifdef WIN32
+                    SetConsoleCtrlHandler(ctrlCHandler, FALSE);
+#else
+                    signal(SIGINT, SIG_DFL);
+#endif
+                }
+                else
+                {
+                    printf("Failed to register event listener.\n");
+                }
+                IEventSource_UnregisterListener(es, (IEventListener *)consoleListener);
+#ifdef WIN32
+                if (consoleListener->pUnkMarshaler)
+                    IUnknown_Release(consoleListener->pUnkMarshaler);
+#endif
+                IEventListenerDemo_Release(consoleListener);
+            }
+            else
+            {
+                printf("Failed while allocating memory for console event listener.\n");
+            }
+            g_pVBoxFuncs->pfnSafeArrayDestroy(interestingEventsSA);
+            IEventSource_Release(es);
+        }
+        else
+        {
+            printf("Failed to get the event source instance.\n");
+        }
+        IConsole_Release(console);
+    }
+}
+
+#else /* !USE_ACTIVE_EVENT_LISTENER */
+
+/**
+ * Register passive event listener for the selected VM.
+ *
+ * @param   virtualBox ptr to IVirtualBox object
+ * @param   session    ptr to ISession object
+ * @param   id         identifies the machine to start
+ */
+static void registerPassiveEventListener(IVirtualBox *virtualBox, ISession *session, BSTR machineId)
+{
+    IConsole *console = NULL;
+    HRESULT rc;
+
+    rc = ISession_get_Console(session, &console);
+    if ((SUCCEEDED(rc)) && console)
+    {
+        IEventSource *es = NULL;
+        rc = IConsole_get_EventSource(console, &es);
+        if (SUCCEEDED(rc) && es)
+        {
+            static const ULONG interestingEvents[] =
+                {
+                    VBoxEventType_OnMousePointerShapeChanged,
+                    VBoxEventType_OnMouseCapabilityChanged,
+                    VBoxEventType_OnKeyboardLedsChanged,
+                    VBoxEventType_OnStateChanged,
+                    VBoxEventType_OnAdditionsStateChanged,
+                    VBoxEventType_OnNetworkAdapterChanged,
+                    VBoxEventType_OnSerialPortChanged,
+                    VBoxEventType_OnParallelPortChanged,
+                    VBoxEventType_OnStorageControllerChanged,
+                    VBoxEventType_OnMediumChanged,
+                    VBoxEventType_OnVRDEServerChanged,
+                    VBoxEventType_OnUSBControllerChanged,
+                    VBoxEventType_OnUSBDeviceStateChanged,
+                    VBoxEventType_OnSharedFolderChanged,
+                    VBoxEventType_OnRuntimeError,
+                    VBoxEventType_OnCanShowWindow,
+                    VBoxEventType_OnShowWindow
+                };
+            SAFEARRAY *interestingEventsSA = NULL;
+            IEventListener *consoleListener = NULL;
+
+            /* The VirtualBox API expects enum values as VT_I4, which in the
+             * future can be hopefully relaxed. */
+            interestingEventsSA = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0, sizeof(interestingEvents) / sizeof(interestingEvents[0]));
+            g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(interestingEventsSA, &interestingEvents, sizeof(interestingEvents));
+
+            rc = IEventSource_CreateListener(es, &consoleListener);
+            if (SUCCEEDED(rc) && consoleListener)
+            {
+                rc = IEventSource_RegisterListener(es, consoleListener,
+                                                   ComSafeArrayAsInParam(interestingEventsSA),
+                                                   0 /* passive */);
+                if (SUCCEEDED(rc))
+                {
+                    /* Just wait here for events, no easy way to do this better
+                     * as there's not much to do after this completes. */
+                    printf("Entering event loop, PowerOff the machine to exit or press Ctrl-C to terminate\n");
+                    fflush(stdout);
+#ifdef WIN32
+                    SetConsoleCtrlHandler(ctrlCHandler, TRUE);
+#else
+                    signal(SIGINT, (void (*)(int))ctrlCHandler);
+#endif
+
+                    while (!g_fStop)
+                    {
+                        IEvent *ev = NULL;
+                        rc = IEventSource_GetEvent(es, consoleListener, 250, &ev);
+                        if (FAILED(rc))
+                        {
+                            printf("Failed getting event: %#x\n", rc);
+                            g_fStop = 1;
+                            continue;
+                        }
+                        /* handle timeouts, resulting in NULL events */
+                        if (!ev)
+                            continue;
+                        rc = EventListenerDemoProcessEvent(ev);
+                        if (FAILED(rc))
+                        {
+                            printf("Failed processing event: %#x\n", rc);
+                            g_fStop = 1;
+                            /* finish processing the event */
+                        }
+                        rc = IEventSource_EventProcessed(es, consoleListener, ev);
+                        if (FAILED(rc))
+                        {
+                            printf("Failed to mark event as processed: %#x\n", rc);
+                            g_fStop = 1;
+                            /* continue with event release */
+                        }
+                        if (ev)
+                        {
+                            IEvent_Release(ev);
+                            ev = NULL;
+                        }
+                    }
+
+#ifdef WIN32
+                    SetConsoleCtrlHandler(ctrlCHandler, FALSE);
+#else
+                    signal(SIGINT, SIG_DFL);
+#endif
+                }
+                else
+                {
+                    printf("Failed to register event listener.\n");
+                }
+                IEventSource_UnregisterListener(es, (IEventListener *)consoleListener);
+                IEventListener_Release(consoleListener);
+            }
+            else
+            {
+                printf("Failed to create an event listener instance.\n");
+            }
+            g_pVBoxFuncs->pfnSafeArrayDestroy(interestingEventsSA);
+            IEventSource_Release(es);
+        }
+        else
+        {
+            printf("Failed to get the event source instance.\n");
+        }
+        IConsole_Release(console);
+    }
+}
+
+#endif /* !USE_ACTIVE_EVENT_LISTENER */
+
+/**
+ * Print detailed error information if available.
+ * @param   pszExecutable   string with the executable name
+ * @param   pszErrorMsg     string containing the code location specific error message
+ * @param   rc              COM/XPCOM result code
+ */
+static void PrintErrorInfo(const char *pszExecutable, const char *pszErrorMsg, HRESULT rc)
+{
+    IErrorInfo *ex;
+    HRESULT rc2 = S_OK;
+    fprintf(stderr, "%s: %s (rc=%#010x)\n", pszExecutable, pszErrorMsg, (unsigned)rc);
+    rc2 = g_pVBoxFuncs->pfnGetException(&ex);
+    if (SUCCEEDED(rc2))
+    {
+        IVirtualBoxErrorInfo *ei;
+        rc2 = IErrorInfo_QueryInterface(ex, &IID_IVirtualBoxErrorInfo, (void **)&ei);
+        if (FAILED(rc2))
+            ei = NULL;
+        if (ei)
+        {
+            /* got extended error info, maybe multiple infos */
+            do
+            {
+                LONG resultCode = S_OK;
+                BSTR componentUtf16 = NULL;
+                char *component = NULL;
+                BSTR textUtf16 = NULL;
+                char *text = NULL;
+                IVirtualBoxErrorInfo *ei_next = NULL;
+                fprintf(stderr, "Extended error info (IVirtualBoxErrorInfo):\n");
+
+                IVirtualBoxErrorInfo_get_ResultCode(ei, &resultCode);
+                fprintf(stderr, "  resultCode=%#010x\n", (unsigned)resultCode);
+
+                IVirtualBoxErrorInfo_get_Component(ei, &componentUtf16);
+                g_pVBoxFuncs->pfnUtf16ToUtf8(componentUtf16, &component);
+                g_pVBoxFuncs->pfnComUnallocString(componentUtf16);
+                fprintf(stderr, "  component=%s\n", component);
+                g_pVBoxFuncs->pfnUtf8Free(component);
+
+                IVirtualBoxErrorInfo_get_Text(ei, &textUtf16);
+                g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
+                g_pVBoxFuncs->pfnComUnallocString(textUtf16);
+                fprintf(stderr, "  text=%s\n", text);
+                g_pVBoxFuncs->pfnUtf8Free(text);
+
+                rc2 = IVirtualBoxErrorInfo_get_Next(ei, &ei_next);
+                if (FAILED(rc2))
+                    ei_next = NULL;
+                IVirtualBoxErrorInfo_Release(ei);
+                ei = ei_next;
+            }
+            while (ei);
+        }
+
+        IErrorInfo_Release(ex);
+        g_pVBoxFuncs->pfnClearException();
+    }
+}
+
+/**
+ * Start a VM.
+ *
+ * @param   argv0       executable name
+ * @param   virtualBox  ptr to IVirtualBox object
+ * @param   session     ptr to ISession object
+ * @param   id          identifies the machine to start
+ */
+static void startVM(const char *argv0, IVirtualBox *virtualBox, ISession *session, BSTR id)
+{
+    HRESULT rc;
+    IMachine  *machine    = NULL;
+    IProgress *progress   = NULL;
+    BSTR env              = NULL;
+    BSTR sessionType;
+
+    rc = IVirtualBox_FindMachine(virtualBox, id, &machine);
+    if (FAILED(rc) || !machine)
+    {
+        PrintErrorInfo(argv0, "Error: Couldn't get the Machine reference", rc);
+        return;
+    }
+
+    g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType);
+    rc = IMachine_LaunchVMProcess(machine, session, sessionType, env, &progress);
+    g_pVBoxFuncs->pfnUtf16Free(sessionType);
+    if (SUCCEEDED(rc))
+    {
+        BOOL completed;
+        LONG resultCode;
+
+        printf("Waiting for the remote session to open...\n");
+        IProgress_WaitForCompletion(progress, -1);
+
+        rc = IProgress_get_Completed(progress, &completed);
+        if (FAILED(rc))
+            fprintf(stderr, "Error: GetCompleted status failed\n");
+
+        IProgress_get_ResultCode(progress, &resultCode);
+        if (FAILED(resultCode))
+        {
+            IVirtualBoxErrorInfo *errorInfo;
+            BSTR textUtf16;
+            char *text;
+
+            IProgress_get_ErrorInfo(progress, &errorInfo);
+            IVirtualBoxErrorInfo_get_Text(errorInfo, &textUtf16);
+            g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
+            printf("Error: %s\n", text);
+
+            g_pVBoxFuncs->pfnComUnallocString(textUtf16);
+            g_pVBoxFuncs->pfnUtf8Free(text);
+            IVirtualBoxErrorInfo_Release(errorInfo);
+        }
+        else
+        {
+            fprintf(stderr, "VM process has been successfully started\n");
+
+            /* Kick off the event listener demo part, which is quite separate.
+             * Ignore it if you need a more basic sample. */
+#ifdef USE_ACTIVE_EVENT_LISTENER
+            registerActiveEventListener(virtualBox, session, id);
+#else /* !USE_ACTIVE_EVENT_LISTENER */
+            registerPassiveEventListener(virtualBox, session, id);
+#endif /* !USE_ACTIVE_EVENT_LISTENER */
+        }
+        IProgress_Release(progress);
+    }
+    else
+        PrintErrorInfo(argv0, "Error: LaunchVMProcess failed", rc);
+
+    /* It's important to always release resources. */
+    IMachine_Release(machine);
+}
+
+/**
+ * List the registered VMs.
+ *
+ * @param   argv0       executable name
+ * @param   virtualBox  ptr to IVirtualBox object
+ * @param   session     ptr to ISession object
+ */
+static void listVMs(const char *argv0, IVirtualBox *virtualBox, ISession *session)
+{
+    HRESULT rc;
+    SAFEARRAY *machinesSA = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc();
+    IMachine **machines = NULL;
+    ULONG machineCnt = 0;
+    ULONG i;
+    unsigned start_id;
+
+    /*
+     * Get the list of all registered VMs.
+     */
+    rc = IVirtualBox_get_Machines(virtualBox, ComSafeArrayAsOutIfaceParam(machinesSA, IMachine *));
+    if (FAILED(rc))
+    {
+        PrintErrorInfo(argv0, "could not get list of machines", rc);
+        return;
+    }
+
+    /*
+     * Extract interface pointers from machinesSA, and update the reference
+     * counter of each object, as destroying machinesSA would call Release.
+     */
+    g_pVBoxFuncs->pfnSafeArrayCopyOutIfaceParamHelper((IUnknown ***)&machines, &machineCnt, machinesSA);
+    g_pVBoxFuncs->pfnSafeArrayDestroy(machinesSA);
+
+    if (!machineCnt)
+    {
+        printf("\tNo VMs\n");
+        return;
+    }
+
+    printf("VM List:\n\n");
+
+    /*
+     * Iterate through the collection.
+     */
+
+    for (i = 0; i < machineCnt; ++i)
+    {
+        IMachine *machine      = machines[i];
+        BOOL      isAccessible = FALSE;
+
+        printf("\tMachine #%u\n", (unsigned)i);
+
+        if (!machine)
+        {
+            printf("\t(skipped, NULL)\n");
+            continue;
+        }
+
+        IMachine_get_Accessible(machine, &isAccessible);
+
+        if (isAccessible)
+        {
+            BSTR machineNameUtf16;
+            char *machineName;
+
+            IMachine_get_Name(machine, &machineNameUtf16);
+            g_pVBoxFuncs->pfnUtf16ToUtf8(machineNameUtf16,&machineName);
+            g_pVBoxFuncs->pfnComUnallocString(machineNameUtf16);
+            printf("\tName:        %s\n", machineName);
+            g_pVBoxFuncs->pfnUtf8Free(machineName);
+        }
+        else
+        {
+            printf("\tName:        <inaccessible>\n");
+        }
+
+        {
+            BSTR uuidUtf16;
+            char      *uuidUtf8;
+
+            IMachine_get_Id(machine, &uuidUtf16);
+            g_pVBoxFuncs->pfnUtf16ToUtf8(uuidUtf16, &uuidUtf8);
+            g_pVBoxFuncs->pfnComUnallocString(uuidUtf16);
+            printf("\tUUID:        %s\n", uuidUtf8);
+            g_pVBoxFuncs->pfnUtf8Free(uuidUtf8);
+        }
+
+        if (isAccessible)
+        {
+            {
+                BSTR      configFileUtf16;
+                char      *configFileUtf8;
+
+                IMachine_get_SettingsFilePath(machine, &configFileUtf16);
+                g_pVBoxFuncs->pfnUtf16ToUtf8(configFileUtf16, &configFileUtf8);
+                g_pVBoxFuncs->pfnComUnallocString(configFileUtf16);
+                printf("\tConfig file: %s\n", configFileUtf8);
+                g_pVBoxFuncs->pfnUtf8Free(configFileUtf8);
+            }
+
+            {
+                ULONG memorySize;
+
+                IMachine_get_MemorySize(machine, &memorySize);
+                printf("\tMemory size: %uMB\n", memorySize);
+            }
+
+            {
+                BSTR typeId;
+                BSTR osNameUtf16;
+                char *osName;
+                IGuestOSType *osType = NULL;
+
+                IMachine_get_OSTypeId(machine, &typeId);
+                IVirtualBox_GetGuestOSType(virtualBox, typeId, &osType);
+                g_pVBoxFuncs->pfnComUnallocString(typeId);
+                IGuestOSType_get_Description(osType, &osNameUtf16);
+                g_pVBoxFuncs->pfnUtf16ToUtf8(osNameUtf16,&osName);
+                g_pVBoxFuncs->pfnComUnallocString(osNameUtf16);
+                printf("\tGuest OS:    %s\n\n", osName);
+                g_pVBoxFuncs->pfnUtf8Free(osName);
+
+                IGuestOSType_Release(osType);
+            }
+        }
+    }
+
+    /*
+     * Let the user chose a machine to start.
+     */
+
+    printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ",
+        (unsigned)(machineCnt - 1));
+    fflush(stdout);
+
+    if (scanf("%u", &start_id) == 1 && start_id < machineCnt)
+    {
+        IMachine *machine = machines[start_id];
+
+        if (machine)
+        {
+            BSTR uuidUtf16 = NULL;
+
+            IMachine_get_Id(machine, &uuidUtf16);
+            startVM(argv0, virtualBox, session, uuidUtf16);
+            g_pVBoxFuncs->pfnComUnallocString(uuidUtf16);
+        }
+    }
+
+    /*
+     * Don't forget to release the objects in the array.
+     */
+
+    for (i = 0; i < machineCnt; ++i)
+    {
+        IMachine *machine = machines[i];
+
+        if (machine)
+        {
+            IMachine_Release(machine);
+        }
+    }
+    if (machines)
+        free(machines);
+}
+
+/* Main - Start the ball rolling. */
+
+int main(int argc, char **argv)
+{
+    IVirtualBoxClient *vboxclient = NULL;
+    IVirtualBox *vbox            = NULL;
+    ISession   *session          = NULL;
+    ULONG       revision         = 0;
+    BSTR        versionUtf16     = NULL;
+    BSTR        homefolderUtf16  = NULL;
+    HRESULT    rc;     /* Result code of various function (method) calls. */
+
+    printf("Starting main()\n");
+
+    if (VBoxCGlueInit())
+    {
+        fprintf(stderr, "%s: FATAL: VBoxCGlueInit failed: %s\n",
+                argv[0], g_szVBoxErrMsg);
+        return EXIT_FAILURE;
+    }
+
+    {
+        unsigned ver = g_pVBoxFuncs->pfnGetVersion();
+        printf("VirtualBox version: %u.%u.%u\n", ver / 1000000, ver / 1000 % 1000, ver % 1000);
+        ver = g_pVBoxFuncs->pfnGetAPIVersion();
+        printf("VirtualBox API version: %u.%u\n", ver / 1000, ver % 1000);
+    }
+
+    g_pVBoxFuncs->pfnClientInitialize(NULL, &vboxclient);
+    if (!vboxclient)
+    {
+        fprintf(stderr, "%s: FATAL: could not get VirtualBoxClient reference\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    printf("----------------------------------------------------\n");
+
+    rc = IVirtualBoxClient_get_VirtualBox(vboxclient, &vbox);
+    if (FAILED(rc) || !vbox)
+    {
+        PrintErrorInfo(argv[0], "FATAL: could not get VirtualBox reference", rc);
+        return EXIT_FAILURE;
+    }
+    rc = IVirtualBoxClient_get_Session(vboxclient, &session);
+    if (FAILED(rc) || !session)
+    {
+        PrintErrorInfo(argv[0], "FATAL: could not get Session reference", rc);
+        return EXIT_FAILURE;
+    }
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+# ifdef WIN32
+    rc = LoadTypeInfo(&IID_IEventListener, &g_pTInfoIEventListener);
+    if (FAILED(rc) || !g_pTInfoIEventListener)
+    {
+        PrintErrorInfo(argv[0], "FATAL: could not get type information for IEventListener", rc);
+        return EXIT_FAILURE;
+    }
+# endif /* WIN32 */
+#endif /* USE_ACTIVE_EVENT_LISTENER */
+
+    /*
+     * Now ask for revision, version and home folder information of
+     * this vbox. Were not using fancy macros here so it
+     * remains easy to see how we access C++'s vtable.
+     */
+
+    /* 1. Revision */
+
+    rc = IVirtualBox_get_Revision(vbox, &revision);
+    if (SUCCEEDED(rc))
+        printf("\tRevision: %u\n", revision);
+    else
+        PrintErrorInfo(argv[0], "GetRevision() failed", rc);
+
+    /* 2. Version */
+
+    rc = IVirtualBox_get_Version(vbox, &versionUtf16);
+    if (SUCCEEDED(rc))
+    {
+        char *version = NULL;
+        g_pVBoxFuncs->pfnUtf16ToUtf8(versionUtf16, &version);
+        printf("\tVersion: %s\n", version);
+        g_pVBoxFuncs->pfnUtf8Free(version);
+        g_pVBoxFuncs->pfnComUnallocString(versionUtf16);
+    }
+    else
+        PrintErrorInfo(argv[0], "GetVersion() failed", rc);
+
+    /* 3. Home Folder */
+
+    rc = IVirtualBox_get_HomeFolder(vbox, &homefolderUtf16);
+    if (SUCCEEDED(rc))
+    {
+        char *homefolder = NULL;
+        g_pVBoxFuncs->pfnUtf16ToUtf8(homefolderUtf16, &homefolder);
+        printf("\tHomeFolder: %s\n", homefolder);
+        g_pVBoxFuncs->pfnUtf8Free(homefolder);
+        g_pVBoxFuncs->pfnComUnallocString(homefolderUtf16);
+    }
+    else
+        PrintErrorInfo(argv[0], "GetHomeFolder() failed", rc);
+
+    listVMs(argv[0], vbox, session);
+    ISession_UnlockMachine(session);
+
+    printf("----------------------------------------------------\n");
+
+    /*
+     * Do as mom told us: always clean up after yourself.
+     */
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+# ifdef WIN32
+    if (g_pTInfoIEventListener)
+    {
+        ITypeInfo_Release(g_pTInfoIEventListener);
+        g_pTInfoIEventListener = NULL;
+    }
+# endif /* WIN32 */
+#endif /* USE_ACTIVE_EVENT_LISTENER */
+
+    if (session)
+    {
+        ISession_Release(session);
+        session = NULL;
+    }
+    if (vbox)
+    {
+        IVirtualBox_Release(vbox);
+        vbox = NULL;
+    }
+    if (vboxclient)
+    {
+        IVirtualBoxClient_Release(vboxclient);
+        vboxclient = NULL;
+    }
+
+    g_pVBoxFuncs->pfnClientUninitialize();
+    VBoxCGlueTerm();
+    printf("Finished main()\n");
+
+    return 0;
+}
+/* vim: set ts=4 sw=4 et: */
diff --git a/src/VBox/Main/cbinding/tstXPCOMCGlue.c b/src/VBox/Main/cbinding/tstXPCOMCGlue.c
deleted file mode 100644
index cd67a4c..0000000
--- a/src/VBox/Main/cbinding/tstXPCOMCGlue.c
+++ /dev/null
@@ -1,822 +0,0 @@
-/* $Revision: 90721 $ */
-/** @file tstXPCOMCGlue.c
- * Demonstrator program to illustrate use of C bindings of Main API, including
- * how to retrieve all available error information.
- *
- * This includes code which shows how to handle active event listeners
- * (event delivery through callbacks), which is not so frequently seen in
- * other samples which mostly use passive event listeners.
- *
- * Linux only at the moment due to shared library magic in the Makefile.
- */
-
-/*
- * Copyright (C) 2009-2013 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "VBoxXPCOMCGlue.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/poll.h>
-
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
-/** Set by signal handler. */
-static volatile int g_fStop = 0;
-
-static const char *GetStateName(PRUint32 machineState)
-{
-    switch (machineState)
-    {
-        case MachineState_Null:                return "<null>";
-        case MachineState_PoweredOff:          return "PoweredOff";
-        case MachineState_Saved:               return "Saved";
-        case MachineState_Teleported:          return "Teleported";
-        case MachineState_Aborted:             return "Aborted";
-        case MachineState_Running:             return "Running";
-        case MachineState_Paused:              return "Paused";
-        case MachineState_Stuck:               return "Stuck";
-        case MachineState_Teleporting:         return "Teleporting";
-        case MachineState_LiveSnapshotting:    return "LiveSnapshotting";
-        case MachineState_Starting:            return "Starting";
-        case MachineState_Stopping:            return "Stopping";
-        case MachineState_Saving:              return "Saving";
-        case MachineState_Restoring:           return "Restoring";
-        case MachineState_TeleportingPausedVM: return "TeleportingPausedVM";
-        case MachineState_TeleportingIn:       return "TeleportingIn";
-        case MachineState_FaultTolerantSyncing: return "FaultTolerantSyncing";
-        case MachineState_DeletingSnapshotOnline: return "DeletingSnapshotOnline";
-        case MachineState_DeletingSnapshotPaused: return "DeletingSnapshotPaused";
-        case MachineState_RestoringSnapshot:   return "RestoringSnapshot";
-        case MachineState_DeletingSnapshot:    return "DeletingSnapshot";
-        case MachineState_SettingUp:           return "SettingUp";
-        default:                               return "no idea";
-    }
-}
-
-struct IEventListenerDemo_vtbl
-{
-    struct IEventListener_vtbl ieventlistener;
-};
-
-typedef struct IEventListenerDemo
-{
-    struct IEventListenerDemo_vtbl *vtbl;
-
-    int refcount;
-} IEventListenerDemo;
-
-/**
- * Event handler function
- */
-static nsresult IEventListenerDemo_HandleEvent(IEventListener *pThis, IEvent *event)
-{
-    enum VBoxEventType evType;
-    nsresult rc;
-
-    if (!event)
-    {
-        printf("event null\n");
-        return NS_OK;
-    }
-
-    evType = VBoxEventType_Invalid;
-    rc = event->vtbl->GetType(event, &evType);
-    if (NS_FAILED(rc))
-    {
-        printf("cannot get event type, rc=%#x\n", rc);
-        return NS_OK;
-    }
-
-    switch (evType)
-    {
-        case VBoxEventType_OnMousePointerShapeChanged:
-            printf("OnMousePointerShapeChanged\n");
-            break;
-
-        case VBoxEventType_OnMouseCapabilityChanged:
-            printf("OnMouseCapabilityChanged\n");
-            break;
-
-        case VBoxEventType_OnKeyboardLedsChanged:
-            printf("OnMouseCapabilityChanged\n");
-            break;
-
-        case VBoxEventType_OnStateChanged:
-        {
-            static const nsID istateChangedEventUUID = ISTATECHANGEDEVENT_IID;
-            IStateChangedEvent *ev = NULL;
-            enum MachineState state;
-            rc = event->vtbl->nsisupports.QueryInterface((nsISupports *)event, &istateChangedEventUUID, (void **)&ev);
-            if (NS_FAILED(rc))
-            {
-                printf("cannot get StateChangedEvent interface, rc=%#x\n", rc);
-                return NS_OK;
-            }
-            if (!ev)
-            {
-                printf("StateChangedEvent reference null\n");
-                return NS_OK;
-            }
-            rc = ev->vtbl->GetState(ev, &state);
-            if (NS_FAILED(rc))
-                printf("warning: cannot get state, rc=%#x\n", rc);
-            ev->vtbl->ievent.nsisupports.Release((nsISupports *)ev);
-            printf("OnStateChanged: %s\n", GetStateName(state));
-
-            fflush(stdout);
-            if (   state == MachineState_PoweredOff
-                || state == MachineState_Saved
-                || state == MachineState_Teleported
-                || state == MachineState_Aborted
-               )
-                g_fStop = 1;
-            break;
-        }
-
-        case VBoxEventType_OnAdditionsStateChanged:
-            printf("OnAdditionsStateChanged\n");
-            break;
-
-        case VBoxEventType_OnNetworkAdapterChanged:
-            printf("OnNetworkAdapterChanged\n");
-            break;
-
-        case VBoxEventType_OnSerialPortChanged:
-            printf("OnSerialPortChanged\n");
-            break;
-
-        case VBoxEventType_OnParallelPortChanged:
-            printf("OnParallelPortChanged\n");
-            break;
-
-        case VBoxEventType_OnStorageControllerChanged:
-            printf("OnStorageControllerChanged\n");
-            break;
-
-        case VBoxEventType_OnMediumChanged:
-            printf("OnMediumChanged\n");
-            break;
-
-        case VBoxEventType_OnVRDEServerChanged:
-            printf("OnVRDEServerChanged\n");
-            break;
-
-        case VBoxEventType_OnUSBControllerChanged:
-            printf("OnUSBControllerChanged\n");
-            break;
-
-        case VBoxEventType_OnUSBDeviceStateChanged:
-            printf("OnUSBDeviceStateChanged\n");
-            break;
-
-        case VBoxEventType_OnSharedFolderChanged:
-            printf("OnSharedFolderChanged\n");
-            break;
-
-        case VBoxEventType_OnRuntimeError:
-            printf("OnRuntimeError\n");
-            break;
-
-        case VBoxEventType_OnCanShowWindow:
-            printf("OnCanShowWindow\n");
-            break;
-        case VBoxEventType_OnShowWindow:
-            printf("OnShowWindow\n");
-            break;
-
-        default:
-            printf("unknown event: %d\n", evType);
-    }
-
-    return NS_OK;
-}
-
-static nsresult IEventListenerDemo_QueryInterface(nsISupports *pThis, const nsID *iid, void **resultp)
-{
-    static const nsID ieventListenerUUID = IEVENTLISTENER_IID;
-    static const nsID isupportIID = NS_ISUPPORTS_IID;
-
-    /* match iid */
-    if (    memcmp(iid, &ieventListenerUUID, sizeof(nsID)) == 0
-        ||  memcmp(iid, &isupportIID, sizeof(nsID)) == 0)
-    {
-        pThis->vtbl->AddRef(pThis);
-        *resultp = pThis;
-        return NS_OK;
-    }
-
-    return NS_NOINTERFACE;
-}
-
-static nsresult IEventListenerDemo_AddRef(nsISupports *pThis)
-{
-    return ++(((IEventListenerDemo *)pThis)->refcount);
-}
-
-static nsresult IEventListenerDemo_Release(nsISupports *pThis)
-{
-    nsresult c;
-
-    c = --(((IEventListenerDemo *)pThis)->refcount);
-    if (c == 0)
-        free(pThis);
-    return c;
-}
-
-struct IEventListenerDemo_vtbl_int_gcc
-{
-    ptrdiff_t offset_to_top;
-    void *typeinfo;
-    struct IEventListenerDemo_vtbl vtbl;
-};
-
-static struct IEventListenerDemo_vtbl_int_gcc g_IEventListenerDemo_vtbl_int_gcc =
-{
-    0,      /* offset_to_top */
-    NULL,   /* typeinfo, not vital */
-    {
-        {
-            {
-                IEventListenerDemo_QueryInterface,
-                IEventListenerDemo_AddRef,
-                IEventListenerDemo_Release
-            },
-            IEventListenerDemo_HandleEvent
-        }
-    }
-};
-
-/**
- * Signal handler, terminate event listener.
- *
- * @param  iSig     The signal number (ignored).
- */
-static void sigIntHandler(int iSig)
-{
-    (void)iSig;
-    g_fStop = 1;
-}
-
-/**
- * Register event listener for the selected VM.
- *
- * @param   virtualBox ptr to IVirtualBox object
- * @param   session    ptr to ISession object
- * @param   id         identifies the machine to start
- * @param   queue      handle to the event queue
- */
-static void registerEventListener(IVirtualBox *virtualBox, ISession *session, PRUnichar *machineId, nsIEventQueue *queue)
-{
-    IConsole *console = NULL;
-    nsresult rc;
-
-    rc = session->vtbl->GetConsole(session, &console);
-    if ((NS_SUCCEEDED(rc)) && console)
-    {
-        IEventSource *es = NULL;
-        rc = console->vtbl->GetEventSource(console, &es);
-        if (NS_SUCCEEDED(rc) && es)
-        {
-            PRUint32 interestingEvents[] =
-                {
-                    VBoxEventType_OnMousePointerShapeChanged,
-                    VBoxEventType_OnMouseCapabilityChanged,
-                    VBoxEventType_OnKeyboardLedsChanged,
-                    VBoxEventType_OnStateChanged,
-                    VBoxEventType_OnAdditionsStateChanged,
-                    VBoxEventType_OnNetworkAdapterChanged,
-                    VBoxEventType_OnSerialPortChanged,
-                    VBoxEventType_OnParallelPortChanged,
-                    VBoxEventType_OnStorageControllerChanged,
-                    VBoxEventType_OnMediumChanged,
-                    VBoxEventType_OnVRDEServerChanged,
-                    VBoxEventType_OnUSBControllerChanged,
-                    VBoxEventType_OnUSBDeviceStateChanged,
-                    VBoxEventType_OnSharedFolderChanged,
-                    VBoxEventType_OnRuntimeError,
-                    VBoxEventType_OnCanShowWindow,
-                    VBoxEventType_OnShowWindow
-                };
-            IEventListenerDemo *consoleListener = NULL;
-            consoleListener = calloc(1, sizeof(IEventListenerDemo));
-            if (consoleListener)
-            {
-                consoleListener->vtbl = &(g_IEventListenerDemo_vtbl_int_gcc.vtbl);
-                consoleListener->vtbl->ieventlistener.nsisupports.AddRef((nsISupports *)consoleListener);
-
-                rc = es->vtbl->RegisterListener(es, (IEventListener *)consoleListener,
-                                                sizeof(interestingEvents) / sizeof(interestingEvents[0]),
-                                                interestingEvents, 1 /* active */);
-                if (NS_SUCCEEDED(rc))
-                {
-                    /* Just wait here for events, no easy way to do this better
-                     * as there's not much to do after this completes. */
-                    PRInt32 fd;
-                    int ret;
-                    printf("Entering event loop, PowerOff the machine to exit or press Ctrl-C to terminate\n");
-                    fflush(stdout);
-                    signal(SIGINT, sigIntHandler);
-
-                    fd = queue->vtbl->GetEventQueueSelectFD(queue);
-                    if (fd >= 0)
-                    {
-                        while (!g_fStop)
-                        {
-                            struct pollfd pfd;
-
-                            pfd.fd = fd;
-                            pfd.events = POLLIN | POLLERR | POLLHUP;
-                            pfd.revents = 0;
-
-                            ret = poll(&pfd, 1, 250);
-
-                            if (ret <= 0)
-                                continue;
-
-                            if (pfd.revents & POLLHUP)
-                                g_fStop = 1;
-
-                            queue->vtbl->ProcessPendingEvents(queue);
-                        }
-                    }
-                    else
-                    {
-                        while (!g_fStop)
-                        {
-                            PLEvent *pEvent = NULL;
-                            rc = queue->vtbl->WaitForEvent(queue, &pEvent);
-                            if (NS_SUCCEEDED(rc))
-                                queue->vtbl->HandleEvent(queue, pEvent);
-                        }
-                    }
-                    signal(SIGINT, SIG_DFL);
-                }
-                es->vtbl->UnregisterListener(es, (IEventListener *)consoleListener);
-                consoleListener->vtbl->ieventlistener.nsisupports.Release((nsISupports *)consoleListener);
-            }
-            else
-            {
-                printf("Failed while allocating memory for console event listener.\n");
-            }
-            es->vtbl->nsisupports.Release((nsISupports *)es);
-        }
-        console->vtbl->nsisupports.Release((nsISupports *)console);
-    }
-}
-
-/**
- * Print detailed error information if available.
- * @param   pszExecutable   string with the executable name
- * @param   pszErrorMsg     string containing the code location specific error message
- * @param   rc              XPCOM result code
- */
-static void PrintErrorInfo(const char *pszExecutable, const char *pszErrorMsg, nsresult rc)
-{
-    nsIException *ex;
-    nsresult rc2 = NS_OK;
-    fprintf(stderr, "%s: %s (rc=%#010x)\n", pszExecutable, pszErrorMsg, (unsigned)rc);
-    rc2 = g_pVBoxFuncs->pfnGetException(&ex);
-    if (NS_SUCCEEDED(rc2))
-    {
-        static const nsID vbei = IVIRTUALBOXERRORINFO_IID;
-        IVirtualBoxErrorInfo *ei;
-        rc2 = ex->vtbl->nsisupports.QueryInterface((nsISupports *)ex, &vbei, (void **)&ei);
-        if (NS_FAILED(rc2))
-            ei = NULL;
-        if (ei)
-        {
-            /* got extended error info, maybe multiple infos */
-            do
-            {
-                PRInt32 resultCode = NS_OK;
-                PRUnichar *componentUtf16 = NULL;
-                char *component = NULL;
-                PRUnichar *textUtf16 = NULL;
-                char *text = NULL;
-                IVirtualBoxErrorInfo *ei_next = NULL;
-                fprintf(stderr, "Extended error info (IVirtualBoxErrorInfo):\n");
-
-                ei->vtbl->GetResultCode(ei, &resultCode);
-                fprintf(stderr, "  resultCode=%#010x\n", (unsigned)resultCode);
-
-                ei->vtbl->GetComponent(ei, &componentUtf16);
-                g_pVBoxFuncs->pfnUtf16ToUtf8(componentUtf16, &component);
-                g_pVBoxFuncs->pfnComUnallocMem(componentUtf16);
-                fprintf(stderr, "  component=%s\n", component);
-                g_pVBoxFuncs->pfnUtf8Free(component);
-
-                ei->vtbl->GetText(ei, &textUtf16);
-                g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
-                g_pVBoxFuncs->pfnComUnallocMem(textUtf16);
-                fprintf(stderr, "  text=%s\n", text);
-                g_pVBoxFuncs->pfnUtf8Free(text);
-
-                rc2 = ei->vtbl->GetNext(ei, &ei_next);
-                if (NS_FAILED(rc2))
-                    ei_next = NULL;
-                ei->vtbl->nsiexception.nsisupports.Release((nsISupports *)ei);
-                ei = ei_next;
-            }
-            while (ei);
-        }
-        else
-        {
-            /* got basic error info */
-            nsresult resultCode = NS_OK;
-            PRUnichar *messageUtf16 = NULL;
-            char *message = NULL;
-            fprintf(stderr, "Basic error info (nsIException):\n");
-
-            ex->vtbl->GetResult(ex, &resultCode);
-            fprintf(stderr, "  resultCode=%#010x\n", resultCode);
-
-            ex->vtbl->GetMessage(ex, &messageUtf16);
-            g_pVBoxFuncs->pfnUtf16ToUtf8(messageUtf16, &message);
-            g_pVBoxFuncs->pfnComUnallocMem(messageUtf16);
-            fprintf(stderr, "  message=%s\n", message);
-            g_pVBoxFuncs->pfnUtf8Free(message);
-        }
-
-        ex->vtbl->nsisupports.Release((nsISupports *)ex);
-        g_pVBoxFuncs->pfnClearException();
-    }
-}
-
-/**
- * Start a VM.
- *
- * @param   argv0       executable name
- * @param   virtualBox  ptr to IVirtualBox object
- * @param   session     ptr to ISession object
- * @param   id          identifies the machine to start
- * @param   queue       ptr to event queue
- */
-static void startVM(const char *argv0, IVirtualBox *virtualBox, ISession *session, PRUnichar *id, nsIEventQueue *queue)
-{
-    nsresult rc;
-    IMachine  *machine    = NULL;
-    IProgress *progress   = NULL;
-    PRUnichar *env        = NULL;
-    PRUnichar *sessionType;
-
-    rc = virtualBox->vtbl->FindMachine(virtualBox, id, &machine);
-    if (NS_FAILED(rc) || !machine)
-    {
-        PrintErrorInfo(argv0, "Error: Couldn't get the Machine reference", rc);
-        return;
-    }
-
-    g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType);
-    rc = machine->vtbl->LaunchVMProcess(machine,
-        session,
-        sessionType,
-        env,
-        &progress
-    );
-    g_pVBoxFuncs->pfnUtf16Free(sessionType);
-    if (NS_SUCCEEDED(rc))
-    {
-        PRBool completed;
-        PRInt32 resultCode;
-
-        printf("Waiting for the remote session to open...\n");
-        progress->vtbl->WaitForCompletion(progress, -1);
-
-        rc = progress->vtbl->GetCompleted(progress, &completed);
-        if (NS_FAILED(rc))
-            fprintf(stderr, "Error: GetCompleted status failed\n");
-
-        progress->vtbl->GetResultCode(progress, &resultCode);
-        if (NS_FAILED(resultCode))
-        {
-            IVirtualBoxErrorInfo *errorInfo;
-            PRUnichar *textUtf16;
-            char *text;
-
-            progress->vtbl->GetErrorInfo(progress, &errorInfo);
-            errorInfo->vtbl->GetText(errorInfo, &textUtf16);
-            g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
-            printf("Error: %s\n", text);
-
-            g_pVBoxFuncs->pfnComUnallocMem(textUtf16);
-            g_pVBoxFuncs->pfnUtf8Free(text);
-        }
-        else
-        {
-            fprintf(stderr, "VM process has been successfully started\n");
-
-            /* Kick off the event listener demo part, which is quite separate.
-             * Ignore it if you need a more basic sample. */
-            registerEventListener(virtualBox, session, id, queue);
-        }
-        progress->vtbl->nsisupports.Release((nsISupports *)progress);
-    }
-    else
-        PrintErrorInfo(argv0, "Error: LaunchVMProcess failed", rc);
-
-    /* It's important to always release resources. */
-    machine->vtbl->nsisupports.Release((nsISupports *)machine);
-}
-
-/**
- * List the registered VMs.
- *
- * @param   argv0       executable name
- * @param   virtualBox  ptr to IVirtualBox object
- * @param   session     ptr to ISession object
- * @param   queue       ptr to event queue
- */
-static void listVMs(const char *argv0, IVirtualBox *virtualBox, ISession *session, nsIEventQueue *queue)
-{
-    nsresult rc;
-    IMachine **machines = NULL;
-    PRUint32 machineCnt = 0;
-    PRUint32 i;
-    unsigned start_id;
-
-    /*
-     * Get the list of all registered VMs.
-     */
-
-    rc = virtualBox->vtbl->GetMachines(virtualBox, &machineCnt, &machines);
-    if (NS_FAILED(rc))
-    {
-        PrintErrorInfo(argv0, "could not get list of machines", rc);
-        return;
-    }
-
-    if (machineCnt == 0)
-    {
-        printf("\tNo VMs\n");
-        return;
-    }
-
-    printf("VM List:\n\n");
-
-    /*
-     * Iterate through the collection.
-     */
-
-    for (i = 0; i < machineCnt; ++i)
-    {
-        IMachine *machine      = machines[i];
-        PRBool    isAccessible = PR_FALSE;
-
-        printf("\tMachine #%u\n", (unsigned)i);
-
-        if (!machine)
-        {
-            printf("\t(skipped, NULL)\n");
-            continue;
-        }
-
-        machine->vtbl->GetAccessible(machine, &isAccessible);
-
-        if (isAccessible)
-        {
-            PRUnichar *machineNameUtf16;
-            char *machineName;
-
-            machine->vtbl->GetName(machine, &machineNameUtf16);
-            g_pVBoxFuncs->pfnUtf16ToUtf8(machineNameUtf16,&machineName);
-            g_pVBoxFuncs->pfnComUnallocMem(machineNameUtf16);
-            printf("\tName:        %s\n", machineName);
-            g_pVBoxFuncs->pfnUtf8Free(machineName);
-        }
-        else
-        {
-            printf("\tName:        <inaccessible>\n");
-        }
-
-        {
-            PRUnichar *uuidUtf16;
-            char      *uuidUtf8;
-
-            machine->vtbl->GetId(machine, &uuidUtf16);
-            g_pVBoxFuncs->pfnUtf16ToUtf8(uuidUtf16, &uuidUtf8);
-            g_pVBoxFuncs->pfnComUnallocMem(uuidUtf16);
-            printf("\tUUID:        %s\n", uuidUtf8);
-            g_pVBoxFuncs->pfnUtf8Free(uuidUtf8);
-        }
-
-        if (isAccessible)
-        {
-            {
-                PRUnichar *configFileUtf16;
-                char      *configFileUtf8;
-
-                machine->vtbl->GetSettingsFilePath(machine, &configFileUtf16);
-                g_pVBoxFuncs->pfnUtf16ToUtf8(configFileUtf16, &configFileUtf8);
-                g_pVBoxFuncs->pfnComUnallocMem(configFileUtf16);
-                printf("\tConfig file: %s\n", configFileUtf8);
-                g_pVBoxFuncs->pfnUtf8Free(configFileUtf8);
-            }
-
-            {
-                PRUint32 memorySize;
-
-                machine->vtbl->GetMemorySize(machine, &memorySize);
-                printf("\tMemory size: %uMB\n", memorySize);
-            }
-
-            {
-                PRUnichar *typeId;
-                PRUnichar *osNameUtf16;
-                char *osName;
-                IGuestOSType *osType = NULL;
-
-                machine->vtbl->GetOSTypeId(machine, &typeId);
-                virtualBox->vtbl->GetGuestOSType(virtualBox, typeId, &osType);
-                g_pVBoxFuncs->pfnComUnallocMem(typeId);
-                osType->vtbl->GetDescription(osType, &osNameUtf16);
-                g_pVBoxFuncs->pfnUtf16ToUtf8(osNameUtf16,&osName);
-                g_pVBoxFuncs->pfnComUnallocMem(osNameUtf16);
-                printf("\tGuest OS:    %s\n\n", osName);
-                g_pVBoxFuncs->pfnUtf8Free(osName);
-
-                osType->vtbl->nsisupports.Release((nsISupports *)osType);
-            }
-        }
-    }
-
-    /*
-     * Let the user chose a machine to start.
-     */
-
-    printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ",
-        (unsigned)(machineCnt - 1));
-    fflush(stdout);
-
-    if (scanf("%u", &start_id) == 1 && start_id < machineCnt)
-    {
-        IMachine *machine = machines[start_id];
-
-        if (machine)
-        {
-            PRUnichar *uuidUtf16 = NULL;
-
-            machine->vtbl->GetId(machine, &uuidUtf16);
-            startVM(argv0, virtualBox, session, uuidUtf16, queue);
-            g_pVBoxFuncs->pfnComUnallocMem(uuidUtf16);
-        }
-    }
-
-    /*
-     * Don't forget to release the objects in the array.
-     */
-
-    for (i = 0; i < machineCnt; ++i)
-    {
-        IMachine *machine = machines[i];
-
-        if (machine)
-        {
-            machine->vtbl->nsisupports.Release((nsISupports *)machine);
-        }
-    }
-    if (machines)
-        g_pVBoxFuncs->pfnComUnallocMem(machines);
-}
-
-/* Main - Start the ball rolling. */
-
-int main(int argc, char **argv)
-{
-    IVirtualBoxClient *vboxclient = NULL;
-    IVirtualBox *vbox            = NULL;
-    ISession   *session          = NULL;
-    nsIEventQueue *queue         = NULL;
-    PRUint32    revision         = 0;
-    PRUnichar  *versionUtf16     = NULL;
-    PRUnichar  *homefolderUtf16  = NULL;
-    nsresult    rc;     /* Result code of various function (method) calls. */
-
-    printf("Starting main()\n");
-
-    if (VBoxCGlueInit() != 0)
-    {
-        fprintf(stderr, "%s: FATAL: VBoxCGlueInit failed: %s\n",
-                argv[0], g_szVBoxErrMsg);
-        return EXIT_FAILURE;
-    }
-
-    {
-        unsigned ver = g_pVBoxFuncs->pfnGetVersion();
-        printf("VirtualBox version: %u.%u.%u\n", ver / 1000000, ver / 1000 % 1000, ver % 1000);
-        ver = g_pVBoxFuncs->pfnGetAPIVersion();
-        printf("VirtualBox API version: %u.%u\n", ver / 1000, ver % 1000);
-    }
-
-    g_pVBoxFuncs->pfnClientInitialize(IVIRTUALBOXCLIENT_IID_STR, &vboxclient);
-    if (vboxclient == NULL)
-    {
-        fprintf(stderr, "%s: FATAL: could not get VirtualBoxClient reference\n", argv[0]);
-        return EXIT_FAILURE;
-    }
-
-    printf("----------------------------------------------------\n");
-
-    rc = vboxclient->vtbl->GetVirtualBox(vboxclient, &vbox);
-    if (NS_FAILED(rc) || !vbox)
-    {
-        PrintErrorInfo(argv[0], "FATAL: could not get VirtualBox reference", rc);
-        return EXIT_FAILURE;
-    }
-    rc = vboxclient->vtbl->GetSession(vboxclient, &session);
-    if (NS_FAILED(rc) || !session)
-    {
-        PrintErrorInfo(argv[0], "FATAL: could not get Session reference", rc);
-        return EXIT_FAILURE;
-    }
-
-    g_pVBoxFuncs->pfnGetEventQueue(&queue);
-
-    /*
-     * Now ask for revision, version and home folder information of
-     * this vbox. Were not using fancy macros here so it
-     * remains easy to see how we access C++'s vtable.
-     */
-
-    /* 1. Revision */
-
-    rc = vbox->vtbl->GetRevision(vbox, &revision);
-    if (NS_SUCCEEDED(rc))
-        printf("\tRevision: %u\n", revision);
-    else
-        PrintErrorInfo(argv[0], "GetRevision() failed", rc);
-
-    /* 2. Version */
-
-    rc = vbox->vtbl->GetVersion(vbox, &versionUtf16);
-    if (NS_SUCCEEDED(rc))
-    {
-        char *version = NULL;
-        g_pVBoxFuncs->pfnUtf16ToUtf8(versionUtf16, &version);
-        printf("\tVersion: %s\n", version);
-        g_pVBoxFuncs->pfnUtf8Free(version);
-        g_pVBoxFuncs->pfnComUnallocMem(versionUtf16);
-    }
-    else
-        PrintErrorInfo(argv[0], "GetVersion() failed", rc);
-
-    /* 3. Home Folder */
-
-    rc = vbox->vtbl->GetHomeFolder(vbox, &homefolderUtf16);
-    if (NS_SUCCEEDED(rc))
-    {
-        char *homefolder = NULL;
-        g_pVBoxFuncs->pfnUtf16ToUtf8(homefolderUtf16, &homefolder);
-        printf("\tHomeFolder: %s\n", homefolder);
-        g_pVBoxFuncs->pfnUtf8Free(homefolder);
-        g_pVBoxFuncs->pfnComUnallocMem(homefolderUtf16);
-    }
-    else
-        PrintErrorInfo(argv[0], "GetHomeFolder() failed", rc);
-
-    listVMs(argv[0], vbox, session, queue);
-    session->vtbl->UnlockMachine(session);
-
-    printf("----------------------------------------------------\n");
-
-    /*
-     * Do as mom told us: always clean up after yourself.
-     */
-
-    if (session)
-    {
-        session->vtbl->nsisupports.Release((nsISupports *)session);
-        session = NULL;
-    }
-    if (vbox)
-    {
-        vbox->vtbl->nsisupports.Release((nsISupports *)vbox);
-        vbox = NULL;
-    }
-    if (vboxclient)
-    {
-        vboxclient->vtbl->nsisupports.Release((nsISupports *)vboxclient);
-        vboxclient = NULL;
-    }
-    g_pVBoxFuncs->pfnClientUninitialize();
-    VBoxCGlueTerm();
-    printf("Finished main()\n");
-
-    return 0;
-}
-/* vim: set ts=4 sw=4 et: */
diff --git a/src/VBox/Main/glue/glue-java.xsl b/src/VBox/Main/glue/glue-java.xsl
index 6b651e6..a1f47fc 100644
--- a/src/VBox/Main/glue/glue-java.xsl
+++ b/src/VBox/Main/glue/glue-java.xsl
@@ -10,7 +10,7 @@
         XSLT stylesheet that generates Java glue code for XPCOM, MSCOM and JAX-WS from
         VirtualBox.xidl.
 
-    Copyright (C) 2010-2013 Oracle Corporation
+    Copyright (C) 2010-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -46,7 +46,7 @@
 <xsl:template name="fileheader">
   <xsl:param name="name" />
   <xsl:text>/*
- * Copyright (C) 2010-2013 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of the VirtualBox SDK, as available from
  * http://www.virtualbox.org.  This library is free software; you can
@@ -1599,7 +1599,7 @@
           </xsl:when>
           <xsl:when test="@dir='in'">
             <xsl:if test="(@safearray='yes') and not(@type = 'octet')">
-              <xsl:value-of select="concat(@name, '.size(), ')" />
+              <xsl:value-of select="concat(@name, ' != null ? ', @name, '.size() : 0, ')" />
             </xsl:if>
             <xsl:variable name="unwrapped">
               <xsl:call-template name="cookInParam">
@@ -2486,7 +2486,7 @@
       <xsl:otherwise>
         <xsl:variable name="extends" select="//interface[@name=$ifname]/@extends" />
         <xsl:choose>
-          <xsl:when test="($extends = '$unknown') or ($extends = '$dispatched') or ($extends = '$errorinfo')">
+          <xsl:when test="($extends = '$unknown') or ($extends = '$errorinfo')">
             <xsl:value-of select="concat('public class ', $ifname, ' extends IUnknown
')" />
             <xsl:text>{

</xsl:text>
           </xsl:when>
diff --git a/src/VBox/Main/glue/initterm.cpp b/src/VBox/Main/glue/initterm.cpp
index 55af141..dbc493c 100644
--- a/src/VBox/Main/glue/initterm.cpp
+++ b/src/VBox/Main/glue/initterm.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -20,7 +20,7 @@
 
 # include <objbase.h>
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
 # include <stdlib.h>
 
@@ -172,7 +172,7 @@ DirectoryServiceProvider::GetFile(const char *aProp,
     if (NS_FAILED(rv))
         return rv;
 
-    return localFile->QueryInterface(NS_GET_IID (nsIFile), (void **)aRetval);
+    return localFile->QueryInterface(NS_GET_IID(nsIFile), (void **)aRetval);
 }
 
 /**
@@ -186,7 +186,7 @@ static bool volatile gIsXPCOMInitialized = false;
  */
 static unsigned int gXPCOMInitCount = 0;
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
 /**
  *  The COM main thread handle. (The first caller of com::Initialize().)
@@ -198,7 +198,7 @@ static RTTHREAD volatile gCOMMainThread = NIL_RTTHREAD;
  */
 static uint32_t gCOMMainInitCount = 0;
 
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
 
 /**
@@ -294,7 +294,7 @@ HRESULT Initialize(bool fGui)
     if (SUCCEEDED(rc))
         gCOMMainInitCount = 1;
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
     /* Unused here */
     NOREF(fGui);
@@ -498,7 +498,7 @@ HRESULT Initialize(bool fGui)
         }
     }
 
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
     AssertComRCReturnRC(rc);
 
@@ -536,7 +536,7 @@ HRESULT Shutdown()
 
     CoUninitialize();
 
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 
     nsCOMPtr<nsIEventQueue> eventQ;
     rc = NS_GetMainEventQ(getter_AddRefs(eventQ));
diff --git a/src/VBox/Main/idl/VirtualBox.xidl b/src/VBox/Main/idl/VirtualBox.xidl
index 9e65d3e..6f2739c 100644
--- a/src/VBox/Main/idl/VirtualBox.xidl
+++ b/src/VBox/Main/idl/VirtualBox.xidl
@@ -2,7 +2,7 @@
 
 <!--
 
-    Copyright (C) 2006-2013 Oracle Corporation
+    Copyright (C) 2006-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -2819,6 +2819,18 @@
       <desc>Export DVD images. Default is not to export them as it is rarely
       needed for typical VMs.</desc>
     </const>
+    <const name="StripAllMACs"      value="3">
+      <desc>Do not export any MAC address information. Default is to keep them
+      to avoid losing information which can cause trouble after import, at the
+      price of risking duplicate MAC addresses, if the import options are used
+      to keep them.</desc>
+    </const>
+    <const name="StripAllNonNATMACs" value="4">
+      <desc>Do not export any MAC address information, except for adapters
+      using NAT. Default is to keep them to avoid losing information which can
+      cause trouble after import, at the price of risking duplicate MAC
+      addresses, if the import options are used to keep them.</desc>
+    </const>
 
   </enum>
 
@@ -4060,6 +4072,9 @@
     <const name="VBoxVGA"   value="1">
       <desc>Default VirtualBox VGA device.</desc>
     </const>
+    <const name="VMSVGA"    value="2">
+      <desc>VMware SVGA II device.</desc>
+    </const>
   </enum>
 
   <enum
diff --git a/src/VBox/Main/idl/apiwrap-server.xsl b/src/VBox/Main/idl/apiwrap-server.xsl
index 7beaaea..2f08e71 100644
--- a/src/VBox/Main/idl/apiwrap-server.xsl
+++ b/src/VBox/Main/idl/apiwrap-server.xsl
@@ -5,7 +5,7 @@
         XSLT stylesheet that generates C++ API wrappers (server side) from
         VirtualBox.xidl.
 
-     Copyright (C) 2010-2013 Oracle Corporation
+     Copyright (C) 2010-2014 Oracle Corporation
 
      This file is part of VirtualBox Open Source Edition (OSE), as
      available from http://www.virtualbox.org. This file is free software;
@@ -77,7 +77,7 @@ templates for file headers/footers
  */
 
 /**
- * Copyright (C) 2011-2013 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -97,7 +97,7 @@ templates for file headers/footers
     <xsl:value-of select="concat('        COM_INTERFACE_ENTRY(', $iface/@name, ')
')"/>
     <!-- now recurse to emit all base interfaces -->
     <xsl:variable name="extends" select="$iface/@extends"/>
-    <xsl:if test="$extends and not($extends='$unknown') and not($extends='$dispatched') and not($extends='$errorinfo')">
+    <xsl:if test="$extends and not($extends='$unknown') and not($extends='$errorinfo')">
         <xsl:call-template name="emitCOMInterfaces">
             <xsl:with-param name="iface" select="//interface[@name=$extends]"/>
         </xsl:call-template>
@@ -156,10 +156,41 @@ public:
 </xsl:text>
 </xsl:template>
 
+<xsl:template name="emitISupports">
+    <xsl:param name="classname"/>
+    <xsl:param name="extends"/>
+    <xsl:param name="depth"/>
+    <xsl:param name="interfacelist"/>
+
+    <xsl:choose>
+        <xsl:when test="$extends and not($extends='$unknown') and not($extends='$dispatched') and not($extends='$errorinfo')">
+            <xsl:variable name="newextends" select="//interface[@name=$extends]/@extends"/>
+            <xsl:variable name="newiflist" select="concat($interfacelist, ', ', $extends)"/>
+            <xsl:call-template name="emitISupports">
+                <xsl:with-param name="classname" select="$classname"/>
+                <xsl:with-param name="extends" select="$newextends"/>
+                <xsl:with-param name="depth" select="$depth + 1"/>
+                <xsl:with-param name="interfacelist" select="$newiflist"/>
+            </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:value-of select="concat('NS_IMPL_THREADSAFE_ISUPPORTS', $depth, '_CI(', $classname, ', ', $interfacelist, ')
')"/>
+        </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
 <xsl:template match="interface" mode="codefooter">
     <xsl:text>#ifdef VBOX_WITH_XPCOM
 </xsl:text>
-    <xsl:value-of select="concat('NS_DECL_CLASSINFO(', substring(@name, 2), 'Wrap)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(', substring(@name, 2), 'Wrap, ', @name, ')
')"/>
+    <xsl:value-of select="concat('NS_DECL_CLASSINFO(', substring(@name, 2), 'Wrap)
')"/>
+
+    <xsl:call-template name="emitISupports">
+        <xsl:with-param name="classname" select="concat(substring(@name, 2), 'Wrap')"/>
+        <xsl:with-param name="extends" select="@extends"/>
+        <xsl:with-param name="depth" select="1"/>
+        <xsl:with-param name="interfacelist" select="@name"/>
+    </xsl:call-template>
+
     <xsl:text>#endif // VBOX_WITH_XPCOM
 </xsl:text>
 </xsl:template>
@@ -843,7 +874,7 @@ public:
 
     <!-- first recurse to emit all base interfaces -->
     <xsl:variable name="extends" select="$iface/@extends"/>
-    <xsl:if test="$extends and not($extends='$unknown') and not($extends='$dispatched') and not($extends='$errorinfo')">
+    <xsl:if test="$extends and not($extends='$unknown') and not($extends='$errorinfo')">
         <xsl:call-template name="emitAttributes">
             <xsl:with-param name="iface" select="//interface[@name=$extends]"/>
             <xsl:with-param name="topclass" select="$topclass"/>
@@ -1098,7 +1129,7 @@ public:
 
     <!-- first recurse to emit all base interfaces -->
     <xsl:variable name="extends" select="$iface/@extends"/>
-    <xsl:if test="$extends and not($extends='$unknown') and not($extends='$dispatched') and not($extends='$errorinfo')">
+    <xsl:if test="$extends and not($extends='$unknown') and not($extends='$errorinfo')">
         <xsl:call-template name="emitMethods">
             <xsl:with-param name="iface" select="//interface[@name=$extends]"/>
             <xsl:with-param name="topclass" select="$topclass"/>
diff --git a/src/VBox/Main/idl/midl.xsl b/src/VBox/Main/idl/midl.xsl
index 0ded778..5ee2c30 100644
--- a/src/VBox/Main/idl/midl.xsl
+++ b/src/VBox/Main/idl/midl.xsl
@@ -5,7 +5,7 @@
  *  A template to generate a MS IDL compatible interface definition file
  *  from the generic interface definition expressed in XML.
 
-    Copyright (C) 2006-2012 Oracle Corporation
+    Copyright (C) 2006-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -206,7 +206,6 @@
   <xsl:text> : </xsl:text>
   <xsl:choose>
     <xsl:when test="@extends='$unknown'">IDispatch</xsl:when>
-    <xsl:when test="@extends='$dispatched'">IDispatch</xsl:when>
     <xsl:when test="@extends='$errorinfo'">IErrorInfo</xsl:when>
     <xsl:otherwise><xsl:value-of select="@extends"/></xsl:otherwise>
   </xsl:choose>
diff --git a/src/VBox/Main/idl/xpidl.xsl b/src/VBox/Main/idl/xpidl.xsl
index 4ad4538..8a8597b 100644
--- a/src/VBox/Main/idl/xpidl.xsl
+++ b/src/VBox/Main/idl/xpidl.xsl
@@ -5,7 +5,7 @@
  *  A template to generate a XPCOM IDL compatible interface definition file
  *  from the generic interface definition expressed in XML.
 
-    Copyright (C) 2006-2012 Oracle Corporation
+    Copyright (C) 2006-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -102,19 +102,6 @@
 #include "nsISupports.idl"
 #include "nsIException.idl"
 
-%{C++
-/**
- * For escaping compound expression so they don't cause trouble when -pedantic
- * is used.
- * @internal
- */
-#if defined(__cplusplus) && defined(__GNUC__)
-# define VBOX_GCC_EXTENSION __extension__
-#endif
-#ifndef VBOX_GCC_EXTENSION
-# define VBOX_GCC_EXTENSION
-#endif
-%}
 </xsl:text>
   <!-- native typedefs for the 'mod="ptr"' attribute -->
   <xsl:text>
@@ -199,8 +186,16 @@
  *  libraries
 -->
 <xsl:template match="library">
-  <!-- result codes -->
   <xsl:text>%{C++&#x0A;</xsl:text>
+  <xsl:text>#ifndef VBOX_EXTERN_C&#x0A;</xsl:text>
+  <xsl:text># ifdef __cplusplus&#x0A;</xsl:text>
+  <xsl:text>#  define VBOX_EXTERN_C extern "C"&#x0A;</xsl:text>
+  <xsl:text># else // !__cplusplus&#x0A;</xsl:text>
+  <xsl:text>#  define VBOX_EXTERN_C extern&#x0A;</xsl:text>
+  <xsl:text># endif // !__cplusplus&#x0A;</xsl:text>
+  <xsl:text>#endif // !VBOX_EXTERN_C&#x0A;</xsl:text>
+  <!-- result codes -->
+  <xsl:text>// result codes declared in API spec&#x0A;</xsl:text>
   <xsl:for-each select="result">
     <xsl:apply-templates select="."/>
   </xsl:for-each>
@@ -248,7 +243,6 @@
   <xsl:text> : </xsl:text>
   <xsl:choose>
       <xsl:when test="@extends='$unknown'">nsISupports</xsl:when>
-      <xsl:when test="@extends='$dispatched'">nsISupports</xsl:when>
       <xsl:when test="@extends='$errorinfo'">nsIException</xsl:when>
       <xsl:otherwise><xsl:value-of select="@extends"/></xsl:otherwise>
   </xsl:choose>
@@ -289,8 +283,12 @@
   <xsl:value-of select="@name"/>
   <xsl:text>_TO_BASE(base) COM_FORWARD_</xsl:text>
   <xsl:value-of select="@name"/>
-  <xsl:text>_TO (base::)&#x0A;</xsl:text>
+  <xsl:text>_TO (base::)&#x0A;&#x0A;</xsl:text>
   <!-- -->
+  <xsl:text>// for compatibility with Win32&#x0A;</xsl:text>
+  <xsl:text>VBOX_EXTERN_C const nsID IID_</xsl:text>
+  <xsl:value-of select="@name"/>
+  <xsl:text>;&#x0A;</xsl:text>
   <xsl:text>%}&#x0A;&#x0A;</xsl:text>
   <!-- end -->
 </xsl:template>
@@ -660,6 +658,11 @@
 <xsl:template match="module/class">
   <!-- class and contract id -->
   <xsl:text>%{C++&#x0A;</xsl:text>
+  <xsl:text>// Definitions for module </xsl:text>
+  <xsl:value-of select="../@name"/>
+  <xsl:text>, class </xsl:text>
+  <xsl:value-of select="@name"/>
+  <xsl:text>:&#x0A;</xsl:text>
   <xsl:text>#define NS_</xsl:text>
   <xsl:call-template name="uppercase">
     <xsl:with-param name="str" select="@name"/>
@@ -690,13 +693,9 @@
   <xsl:text>;1"&#x0A;</xsl:text>
   <!-- CLSID_xxx declarations for XPCOM, for compatibility with Win32 -->
   <xsl:text>// for compatibility with Win32&#x0A;</xsl:text>
-  <xsl:text>#define CLSID_</xsl:text>
+  <xsl:text>VBOX_EXTERN_C const nsCID CLSID_</xsl:text>
   <xsl:value-of select="@name"/>
-  <xsl:text> VBOX_GCC_EXTENSION (nsCID) NS_</xsl:text>
-  <xsl:call-template name="uppercase">
-    <xsl:with-param name="str" select="@name"/>
-  </xsl:call-template>
-  <xsl:text>_CID&#x0A;</xsl:text>
+  <xsl:text>;&#x0A;</xsl:text>
   <xsl:text>%}&#x0A;&#x0A;</xsl:text>
 </xsl:template>
 
diff --git a/src/VBox/Main/idl/xpidl_iid.xsl b/src/VBox/Main/idl/xpidl_iid.xsl
new file mode 100644
index 0000000..1e21608
--- /dev/null
+++ b/src/VBox/Main/idl/xpidl_iid.xsl
@@ -0,0 +1,154 @@
+<?xml version="1.0"?>
+<!-- $Id: xpidl_iid.xsl $ -->
+
+<!--
+ *  A template to generate a header file containing IIDs for XPCOM
+ *  from the generic interface definition expressed in XML.
+
+    Copyright (C) 2006-2014 Oracle Corporation
+
+    This file is part of VirtualBox Open Source Edition (OSE), as
+    available from http://www.virtualbox.org. This file is free software;
+    you can redistribute it and/or modify it under the terms of the GNU
+    General Public License (GPL) as published by the Free Software
+    Foundation, in version 2 as it comes in the "COPYING" file of the
+    VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+    hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+
+<xsl:strip-space elements="*"/>
+
+<!--
+//  templates
+/////////////////////////////////////////////////////////////////////////////
+-->
+
+
+<!--
+ *  not explicitly matched elements and attributes
+-->
+<xsl:template match="*"/>
+
+
+<!--
+ *  header
+-->
+<xsl:template match="/idl">
+  <xsl:text>
+/*
+ *  DO NOT EDIT! This is a generated file.
+ *
+ *  XPCOM C definitions for VirtualBox Main API (IIDs for COM interfaces)
+ *  generated from XIDL (XML interface definition).
+ *
+ *  Source    : src/VBox/Main/idl/VirtualBox.xidl
+ *  Generator : src/VBox/Main/idl/xpidl_iid.xsl
+ */
+
+#ifndef nsID_h__
+struct nsID
+{
+    unsigned int m0;
+    unsigned short m1;
+    unsigned short m2;
+    unsigned char m3[8];
+};
+
+typedef struct nsID nsID;
+typedef struct nsID nsIID;
+typedef struct nsID nsCID;
+#endif /* nsID_h__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+</xsl:text>
+  <xsl:apply-templates/>
+  <xsl:text>
+
+#ifdef __cplusplus
+}
+#endif
+
+</xsl:text>
+</xsl:template>
+
+
+<!--
+ *  ignore all |if|s except those for XPIDL target
+-->
+<xsl:template match="if">
+  <xsl:if test="@target='xpidl'">
+    <xsl:apply-templates/>
+  </xsl:if>
+</xsl:template>
+
+
+<!--
+ *  libraries
+-->
+<xsl:template match="library">
+  <xsl:apply-templates select="if | interface"/>
+  <xsl:apply-templates select="module"/>
+</xsl:template>
+
+
+<!--
+ *  interfaces
+-->
+<xsl:template match="interface">
+  <xsl:text>const nsID IID_</xsl:text>
+  <xsl:value-of select="@name"/>
+  <xsl:text> = {&#x0A;</xsl:text>
+  <xsl:text>    0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
+  <xsl:text>, \&#x0A;    </xsl:text>
+  <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
+  <xsl:text> } \&#x0A;};&#x0A;&#x0A;</xsl:text>
+</xsl:template>
+
+
+<!--
+ *  modules
+-->
+<xsl:template match="module">
+  <xsl:apply-templates select="class"/>
+</xsl:template>
+
+
+<!--
+ *  co-classes
+-->
+<xsl:template match="module/class">
+  <xsl:text>const nsCID CLSID_</xsl:text>
+  <xsl:value-of select="@name"/>
+  <xsl:text> = {&#x0A;</xsl:text>
+  <xsl:text>    0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
+  <xsl:text>, \&#x0A;    </xsl:text>
+  <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
+  <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
+  <xsl:text> } \&#x0A;};&#x0A;&#x0A;</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/src/VBox/Main/include/ApplianceImpl.h b/src/VBox/Main/include/ApplianceImpl.h
index f119edb..7080d14 100644
--- a/src/VBox/Main/include/ApplianceImpl.h
+++ b/src/VBox/Main/include/ApplianceImpl.h
@@ -1,7 +1,5 @@
 /* $Id: ApplianceImpl.h $ */
-
 /** @file
- *
  * VirtualBox COM class implementation
  */
 
@@ -260,8 +258,8 @@ struct VirtualSystemDescriptionEntry
     VirtualSystemDescriptionType_T type;    // type of this entry
     Utf8Str strRef;                         // reference number (hard disk controllers only)
     Utf8Str strOvf;                         // original OVF value (type-dependent)
-    Utf8Str strVboxSuggested;               // configuration value (type-dependent); original value suggested by interpret()
-    Utf8Str strVboxCurrent;                 // configuration value (type-dependent); current value, either from interpret() or setFinalValue()
+    Utf8Str strVBoxSuggested;               // configuration value (type-dependent); original value suggested by interpret()
+    Utf8Str strVBoxCurrent;                 // configuration value (type-dependent); current value, either from interpret() or setFinalValue()
     Utf8Str strExtraConfigSuggested;        // extra configuration key=value strings (type-dependent); original value suggested by interpret()
     Utf8Str strExtraConfigCurrent;          // extra configuration key=value strings (type-dependent); current value, either from interpret() or setFinalValue()
 
@@ -301,14 +299,14 @@ public:
     STDMETHOD(GetDescription)(ComSafeArrayOut(VirtualSystemDescriptionType_T, aTypes),
                               ComSafeArrayOut(BSTR, aRefs),
                               ComSafeArrayOut(BSTR, aOvfValues),
-                              ComSafeArrayOut(BSTR, aVboxValues),
+                              ComSafeArrayOut(BSTR, aVBoxValues),
                               ComSafeArrayOut(BSTR, aExtraConfigValues));
 
     STDMETHOD(GetDescriptionByType)(VirtualSystemDescriptionType_T aType,
                                     ComSafeArrayOut(VirtualSystemDescriptionType_T, aTypes),
                                     ComSafeArrayOut(BSTR, aRefs),
                                     ComSafeArrayOut(BSTR, aOvfValues),
-                                    ComSafeArrayOut(BSTR, aVboxValues),
+                                    ComSafeArrayOut(BSTR, aVBoxValues),
                                     ComSafeArrayOut(BSTR, aExtraConfigValues));
 
     STDMETHOD(GetValuesByType)(VirtualSystemDescriptionType_T aType,
@@ -316,26 +314,25 @@ public:
                                ComSafeArrayOut(BSTR, aValues));
 
     STDMETHOD(SetFinalValues)(ComSafeArrayIn(BOOL, aEnabled),
-                              ComSafeArrayIn(IN_BSTR, aVboxValues),
+                              ComSafeArrayIn(IN_BSTR, aVBoxValues),
                               ComSafeArrayIn(IN_BSTR, aExtraConfigValues));
 
     STDMETHOD(AddDescription)(VirtualSystemDescriptionType_T aType,
-                              IN_BSTR aVboxValue,
+                              IN_BSTR aVBoxValue,
                               IN_BSTR aExtraConfigValue);
 
     /* public methods only for internal purposes */
-
     void addEntry(VirtualSystemDescriptionType_T aType,
                   const Utf8Str &strRef,
                   const Utf8Str &aOvfValue,
-                  const Utf8Str &aVboxValue,
+                  const Utf8Str &aVBoxValue,
                   uint32_t ulSizeMB = 0,
                   const Utf8Str &strExtraConfig = "");
 
     std::list<VirtualSystemDescriptionEntry*> findByType(VirtualSystemDescriptionType_T aType);
     const VirtualSystemDescriptionEntry* findControllerFromID(uint32_t id);
 
-    void importVboxMachineXML(const xml::ElementNode &elmMachine);
+    void importVBoxMachineXML(const xml::ElementNode &elmMachine);
     const settings::MachineConfigFile* getMachineConfig() const;
 
     void removeByType(VirtualSystemDescriptionType_T aType);
@@ -348,5 +345,5 @@ private:
     friend class Machine;
 };
 
-#endif // ____H_APPLIANCEIMPL
+#endif // !____H_APPLIANCEIMPL
 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/ApplianceImplPrivate.h b/src/VBox/Main/include/ApplianceImplPrivate.h
index b620ba7..d36754a 100644
--- a/src/VBox/Main/include/ApplianceImplPrivate.h
+++ b/src/VBox/Main/include/ApplianceImplPrivate.h
@@ -1,5 +1,4 @@
 /** @file
- *
  * VirtualBox Appliance private data definitions
  */
 
diff --git a/src/VBox/Main/include/ConsoleImpl.h b/src/VBox/Main/include/ConsoleImpl.h
index 1bef0ec..220ff7b 100644
--- a/src/VBox/Main/include/ConsoleImpl.h
+++ b/src/VBox/Main/include/ConsoleImpl.h
@@ -545,7 +545,8 @@ private:
     int configCfgmOverlay(PCFGMNODE pRoot, IVirtualBox *pVirtualBox, IMachine *pMachine);
     int configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine);
 
-    int configGraphicsController(PCFGMNODE pDevices, const char *pcszDevice,
+    int configGraphicsController(PCFGMNODE pDevices,
+                                 const GraphicsControllerType_T graphicsController,
                                  BusAssignmentManager *pBusMgr,
                                  const ComPtr<IMachine> &pMachine,
                                  const ComPtr<IBIOSSettings> &biosSettings,
diff --git a/src/VBox/Main/include/DHCPServerImpl.h b/src/VBox/Main/include/DHCPServerImpl.h
index c740f16..f326405 100644
--- a/src/VBox/Main/include/DHCPServerImpl.h
+++ b/src/VBox/Main/include/DHCPServerImpl.h
@@ -124,26 +124,12 @@ public:
     STDMETHOD(Stop)();
 
 private:
+    struct Data;
+    Data *m;
     /** weak VirtualBox parent */
     VirtualBox * const      mVirtualBox;
-
     const Bstr mName;
 
-    struct Data
-    {
-        Data() : enabled(FALSE) {}
-
-        Bstr IPAddress;
-        Bstr lowerIP;
-        Bstr upperIP;
-
-        BOOL enabled;
-        DHCPServerRunner dhcp;
-
-        DhcpOptionMap GlobalDhcpOptions;
-        VmSlot2OptionsMap VmSlot2Options;
-    } m;
-
     DhcpOptionMap& findOptMapByVmNameSlot(const com::Utf8Str& aVmName,
                                           LONG Slot);
 };
diff --git a/src/VBox/Main/include/DisplayImpl.h b/src/VBox/Main/include/DisplayImpl.h
index 4e57f7d..b1239ca 100644
--- a/src/VBox/Main/include/DisplayImpl.h
+++ b/src/VBox/Main/include/DisplayImpl.h
@@ -26,6 +26,10 @@
 #include <VBox/VMMDev.h>
 #include <VBox/VBoxVideo.h>
 
+#ifdef VBOX_WITH_CROGL
+# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
+#endif
+
 class Console;
 struct VIDEORECCONTEXT;
 
@@ -101,6 +105,17 @@ typedef struct _DISPLAYFBINFO
     } vbvaSkippedRect;
     PVBVAHOSTFLAGS pVBVAHostFlags;
 #endif /* VBOX_WITH_HGSMI */
+
+#ifdef VBOX_WITH_CROGL
+    struct
+    {
+        bool fPending;
+        ULONG x;
+        ULONG y;
+        ULONG width;
+        ULONG height;
+    } pendingViewportInfo;
+#endif /* VBOX_WITH_CROGL */
 } DISPLAYFBINFO;
 
 class DisplayMouseInterface
@@ -112,6 +127,8 @@ public:
                                           int32_t *px2, int32_t *py2) = 0;
 };
 
+class VMMDev;
+
 class ATL_NO_VTABLE Display :
     public VirtualBoxBase,
     VBOX_SCRIPTABLE_IMPL(IEventListener),
@@ -149,12 +166,27 @@ public:
     int handleVHWACommandProcess(PVBOXVHWACMD pCommand);
 #endif
 #ifdef VBOX_WITH_CRHGSMI
-    void handleCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
-    void handleCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
+    int  handleCrCmdNotifyCmds();
+    void handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
+    void handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
 
     void handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
     void handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
 #endif
+
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+    void  handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
+    void  handleCrVRecScreenshotPerform(uint32_t uScreen,
+                                        uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBitsPerPixel,
+                                        uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
+                                        uint8_t *pu8BufferAddress, uint64_t u64TimeStamp);
+    bool handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp);
+    void handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp);
+    void handleVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
+#endif
+
+    int notifyCroglResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM);
+
     IFramebuffer *getFramebuffer()
     {
         return maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer;
@@ -209,6 +241,10 @@ private:
     void destructCrHgsmiData(void);
 #endif
 
+#ifdef VBOX_WITH_CROGL
+    void crViewportNotify(class VMMDev *pVMMDev, ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height);
+#endif
+
     static DECLCALLBACK(int)   changeFramebuffer(Display *that, IFramebuffer *aFB, unsigned uScreenId);
 
     static DECLCALLBACK(void*) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID);
@@ -228,6 +264,7 @@ private:
 #endif
 
 #ifdef VBOX_WITH_CRHGSMI
+    static DECLCALLBACK(int)  displayCrCmdNotifyCmds(PPDMIDISPLAYCONNECTOR pInterface);
     static DECLCALLBACK(void)  displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
     static DECLCALLBACK(void)  displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
 
@@ -245,6 +282,19 @@ private:
     static DECLCALLBACK(int)   displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha, uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy, const void *pvShape);
 #endif
 
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+    static DECLCALLBACK(void) displayCrVRecScreenshotPerform(void *pvCtx, uint32_t uScreen,
+                                                             uint32_t x, uint32_t y,
+                                                             uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
+                                                             uint32_t uGuestWidth, uint32_t uGuestHeight,
+                                                             uint8_t *pu8BufferAddress, uint64_t u64TimeStamp);
+    static DECLCALLBACK(bool) displayCrVRecScreenshotBegin(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp);
+    static DECLCALLBACK(void) displayCrVRecScreenshotEnd(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp);
+
+    static DECLCALLBACK(void)  displayVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
+    static DECLCALLBACK(void)  displayCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
+#endif
+
     static DECLCALLBACK(void)  displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser);
     static DECLCALLBACK(int)   displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
     static DECLCALLBACK(void)  displaySSMSave(PSSMHANDLE pSSM, void *pvUser);
@@ -279,6 +329,9 @@ private:
     VBVAMEMORY *mpPendingVbvaMemory;
     bool        mfPendingVideoAccelEnable;
     bool        mfMachineRunning;
+#ifdef VBOX_WITH_CROGL
+    bool        mfCrOglDataHidden;
+#endif
 
     uint8_t    *mpu8VbvaPartial;
     uint32_t    mcbVbvaPartial;
@@ -287,6 +340,11 @@ private:
     /* for fast host hgcm calls */
     HGCMCVSHANDLE mhCrOglSvc;
 #endif
+#ifdef VBOX_WITH_CROGL
+    CR_MAIN_INTERFACE mCrOglCallbacks;
+    volatile uint32_t mfCrOglVideoRecState;
+    CRVBOXHGCMTAKESCREENSHOT mCrOglScreenshotData;
+#endif
 
     bool vbvaFetchCmd(VBVACMDHDR **ppHdr, uint32_t *pcbCmd);
     void vbvaReleaseCmd(VBVACMDHDR *pHdr, int32_t cbCmd);
@@ -306,6 +364,10 @@ private:
 public:
     static int  displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height);
 
+#ifdef VBOX_WITH_CROGL
+    static BOOL  displayCheckTakeScreenshotCrOgl(Display *pDisplay, ULONG aScreenId, uint8_t *pu8Data, uint32_t u32Width, uint32_t u32Height);
+#endif
+
 private:
     static void InvalidateAndUpdateEMT(Display *pDisplay, unsigned uId, bool fUpdateAll);
     static int  drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address, ULONG x, ULONG y, ULONG width, ULONG height);
@@ -316,6 +378,10 @@ private:
     int  videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory);
     void videoAccelFlush(void);
 
+#ifdef VBOX_WITH_CROGL
+    int crOglWindowsShow(bool fShow);
+#endif
+
 #ifdef VBOX_WITH_HGSMI
     volatile uint32_t mu32UpdateVBVAFlags;
 #endif
diff --git a/src/VBox/Main/include/HostPower.h b/src/VBox/Main/include/HostPower.h
index 29aecf4..c7774c3 100644
--- a/src/VBox/Main/include/HostPower.h
+++ b/src/VBox/Main/include/HostPower.h
@@ -29,17 +29,13 @@
 
 class HostPowerService
 {
-public:
-
+  public:
     HostPowerService(VirtualBox *aVirtualBox);
     virtual ~HostPowerService();
-
     void notify(Reason_T aReason);
 
-protected:
-
+  protected:
     VirtualBox *mVirtualBox;
-
     std::vector<ComPtr<IInternalSessionControl> > mSessionControls;
 };
 
diff --git a/src/VBox/Main/include/Wrapper.h b/src/VBox/Main/include/Wrapper.h
index 36f8016..2381ea2 100644
--- a/src/VBox/Main/include/Wrapper.h
+++ b/src/VBox/Main/include/Wrapper.h
@@ -1,12 +1,10 @@
 /* $Id: Wrapper.h $ */
-
 /** @file
- *
  * VirtualBox COM: API wrapper helpers
  */
 
 /*
- * Copyright (C) 2012-2013 Oracle Corporation
+ * Copyright (C) 2012-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -150,10 +148,13 @@ public:
 
     ArrayBSTRInConverter(ComSafeArrayIn(IN_BSTR, aSrc))
     {
-        com::SafeArray<IN_BSTR> inArray(ComSafeArrayInArg(aSrc));
-        mArray.resize(inArray.size());
-        for (size_t i = 0; i < inArray.size(); i++)
-            mArray[i] = inArray[i];
+        if (!ComSafeArrayInIsNull(aSrc))
+        {
+            com::SafeArray<IN_BSTR> inArray(ComSafeArrayInArg(aSrc));
+            mArray.resize(inArray.size());
+            for (size_t i = 0; i < inArray.size(); i++)
+                mArray[i] = inArray[i];
+        }
     }
 
     ~ArrayBSTRInConverter()
@@ -382,10 +383,13 @@ public:
 
     ArrayComTypeInConverter(ComSafeArrayIn(A *, aSrc))
     {
-        com::SafeIfaceArray<A> inArray(ComSafeArrayInArg(aSrc));
-        mArray.resize(inArray.size());
-        for (size_t i = 0; i < inArray.size(); i++)
-            mArray[i] = inArray[i];
+        if (!ComSafeArrayInIsNull(aSrc))
+        {
+            com::SafeIfaceArray<A> inArray(ComSafeArrayInArg(aSrc));
+            mArray.resize(inArray.size());
+            for (size_t i = 0; i < inArray.size(); i++)
+                mArray[i] = inArray[i];
+        }
     }
 
     ~ArrayComTypeInConverter()
@@ -461,10 +465,13 @@ public:
 
     ArrayInConverter(ComSafeArrayIn(A, aSrc))
     {
-        com::SafeArray<A> inArray(ComSafeArrayInArg(aSrc));
-        mArray.resize(inArray.size());
-        for (size_t i = 0; i < inArray.size(); i++)
-            mArray[i] = inArray[i];
+        if (!ComSafeArrayInIsNull(aSrc))
+        {
+            com::SafeArray<A> inArray(ComSafeArrayInArg(aSrc));
+            mArray.resize(inArray.size());
+            for (size_t i = 0; i < inArray.size(); i++)
+                mArray[i] = inArray[i];
+        }
     }
 
     ~ArrayInConverter()
@@ -480,5 +487,5 @@ private:
     std::vector<A> mArray;
 };
 
-#endif // ____H_WRAPPER
+#endif // !____H_WRAPPER
 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/netif.h b/src/VBox/Main/include/netif.h
index b220987..bd61892 100644
--- a/src/VBox/Main/include/netif.h
+++ b/src/VBox/Main/include/netif.h
@@ -84,16 +84,16 @@ typedef NETIFINFO const *PCNETIFINFO;
 #endif
 
 int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list);
-int NetIfEnableStaticIpConfig(VirtualBox *pVbox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG aNewIp, ULONG aMask);
-int NetIfEnableStaticIpConfigV6(VirtualBox *pVbox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength);
-int NetIfEnableDynamicIpConfig(VirtualBox *pVbox, HostNetworkInterface * pIf);
-int NetIfCreateHostOnlyNetworkInterface (VirtualBox *pVbox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress, const char *pcszName = NULL);
-int NetIfRemoveHostOnlyNetworkInterface (VirtualBox *pVbox, IN_GUID aId, IProgress **aProgress);
+int NetIfEnableStaticIpConfig(VirtualBox *pVBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG aNewIp, ULONG aMask);
+int NetIfEnableStaticIpConfigV6(VirtualBox *pVBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength);
+int NetIfEnableDynamicIpConfig(VirtualBox *pVBox, HostNetworkInterface * pIf);
+int NetIfCreateHostOnlyNetworkInterface (VirtualBox *pVBox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress, const char *pcszName = NULL);
+int NetIfRemoveHostOnlyNetworkInterface (VirtualBox *pVBox, IN_GUID aId, IProgress **aProgress);
 int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *);
 int NetIfGetConfigByName(PNETIFINFO pInfo);
 int NetIfGetState(const char *pcszIfName, NETIFSTATUS *penmState);
 int NetIfGetLinkSpeed(const char *pcszIfName, uint32_t *puMbits);
-int NetIfDhcpRediscover(VirtualBox *pVbox, HostNetworkInterface * pIf);
+int NetIfDhcpRediscover(VirtualBox *pVBox, HostNetworkInterface * pIf);
 int NetIfAdpCtlOut(const char * pcszName, const char * pcszCmd, char *pszBuffer, size_t cBufSize);
 
 DECLINLINE(Bstr) composeIPv6Address(PRTNETADDRIPV6 aAddrPtr)
diff --git a/src/VBox/Main/include/ovfreader.h b/src/VBox/Main/include/ovfreader.h
index f0da200..8076930 100644
--- a/src/VBox/Main/include/ovfreader.h
+++ b/src/VBox/Main/include/ovfreader.h
@@ -252,7 +252,7 @@ struct DiskImage
                                     // space, but cannot be larger than iCapacity; -1 if not set)
     RTCString strFormat;              // value from DiskSection/Disk/@format
                 // typically http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized
-    RTCString uuidVbox;      // optional; if the file was exported by VirtualBox >= 3.2,
+    RTCString uuidVBox;      // optional; if the file was exported by VirtualBox >= 3.2,
                                     // then this has the UUID with which the disk was registered
 
     // fields from /References/File; the spec says the file reference from disk can be empty,
@@ -554,7 +554,7 @@ struct VirtualSystem
 
     CIMOSType_T         cimos;
     RTCString    strCimosDesc;           // readable description of the cimos type in the case of cimos = 0/1/102
-    RTCString    strTypeVbox;            // optional type from @vbox:ostype attribute (VirtualBox 4.0 or higher)
+    RTCString    strTypeVBox;            // optional type from @vbox:ostype attribute (VirtualBox 4.0 or higher)
 
     RTCString    strVirtualSystemType;   // generic hardware description; OVF says this can be something like "vmx-4" or "xen";
                                                 // VMware Workstation 6.5 is "vmx-07"
@@ -588,8 +588,7 @@ struct VirtualSystem
     RTCString    strProductUrl;          // product info if any; receives contents of VirtualSystem/ProductSection/ProductUrl
     RTCString    strVendorUrl;           // product info if any; receives contents of VirtualSystem/ProductSection/VendorUrl
 
-    const xml::ElementNode                      // pointer to <vbox:Machine> element under <VirtualSystem> element or NULL if not present
-                        *pelmVboxMachine;
+    const xml::ElementNode *pelmVBoxMachine; // pointer to <vbox:Machine> element under <VirtualSystem> element or NULL if not present
 
     VirtualSystem()
         : cimos(CIMOSType_CIMOS_Unknown),
@@ -598,7 +597,7 @@ struct VirtualSystem
           fHasFloppyDrive(false),
           fHasCdromDrive(false),
           fHasUsbController(false),
-          pelmVboxMachine(NULL)
+          pelmVBoxMachine(NULL)
     {
     }
 };
diff --git a/src/VBox/Main/src-all/Global.cpp b/src/VBox/Main/src-all/Global.cpp
index 6ceba0c..fdfac74 100644
--- a/src/VBox/Main/src-all/Global.cpp
+++ b/src/VBox/Main/src-all/Global.cpp
@@ -61,7 +61,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Win2k,            VBOXOSHINT_USBTABLET,
        168,  16,  4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Windows", "Microsoft Windows", "WindowsXP",          "Windows XP",
+    { "Windows", "Microsoft Windows", "WindowsXP",          "Windows XP (32 bit)",
       VBOXOSTYPE_WinXP,            VBOXOSHINT_USBTABLET,
        192,  16, 10 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -69,7 +69,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_WinXP_x64,       VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        192,  16, 10 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Windows", "Microsoft Windows", "Windows2003",        "Windows 2003",
+    { "Windows", "Microsoft Windows", "Windows2003",        "Windows 2003 (32 bit)",
       VBOXOSTYPE_Win2k3,           VBOXOSHINT_USBTABLET,
        256,  16, 20 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -77,7 +77,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Win2k3_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        256,  16, 20 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_HDA  },
-    { "Windows", "Microsoft Windows", "WindowsVista",       "Windows Vista",
+    { "Windows", "Microsoft Windows", "WindowsVista",       "Windows Vista (32 bit)",
       VBOXOSTYPE_WinVista,         VBOXOSHINT_USBTABLET,
        512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
@@ -85,7 +85,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_WinVista_x64,    VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
-    { "Windows", "Microsoft Windows", "Windows2008",        "Windows 2008",
+    { "Windows", "Microsoft Windows", "Windows2008",        "Windows 2008 (32 bit)",
       VBOXOSTYPE_Win2k8,           VBOXOSHINT_USBTABLET,
        512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
@@ -93,7 +93,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Win2k8_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
-    { "Windows", "Microsoft Windows", "Windows7",           "Windows 7",
+    { "Windows", "Microsoft Windows", "Windows7",           "Windows 7 (32 bit)",
       VBOXOSTYPE_Win7,             VBOXOSHINT_USBTABLET,
        512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
@@ -101,7 +101,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Win7_x64,        VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        512,  16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
-    { "Windows", "Microsoft Windows", "Windows8",           "Windows 8",
+    { "Windows", "Microsoft Windows", "Windows8",           "Windows 8 (32 bit)",
       VBOXOSTYPE_Win8,             VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET | VBOXOSHINT_PAE,
        1024,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
@@ -109,7 +109,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Win8_x64,        VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        2048,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
-    { "Windows", "Microsoft Windows", "Windows81",          "Windows 8.1",
+    { "Windows", "Microsoft Windows", "Windows81",          "Windows 8.1 (32 bit)",
       VBOXOSTYPE_Win8,             VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET | VBOXOSHINT_PAE,
        1024,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
@@ -121,7 +121,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Win2k12_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
        2048,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA  },
-    { "Windows", "Microsoft Windows", "WindowsNT",          "Other Windows",
+    { "Windows", "Microsoft Windows", "WindowsNT",          "Other Windows (32 bit)",
       VBOXOSTYPE_WinNT,           VBOXOSHINT_NONE,
        512,  16, 20 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -133,7 +133,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Linux22,         VBOXOSHINT_RTCUTC,
         64,   4,  2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Linux24",            "Linux 2.4",
+    { "Linux",   "Linux",             "Linux24",            "Linux 2.4 (32 bit)",
       VBOXOSTYPE_Linux24,         VBOXOSHINT_RTCUTC,
        128,   4,  4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -141,7 +141,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Linux24_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
        128,   4,  4 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Linux26",            "Linux 2.6 / 3.x",
+    { "Linux",   "Linux",             "Linux26",            "Linux 2.6 / 3.x (32 bit)",
       VBOXOSTYPE_Linux26,         VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        256,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -149,7 +149,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Linux26_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        256,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "ArchLinux",          "Arch Linux",
+    { "Linux",   "Linux",             "ArchLinux",          "Arch Linux (32 bit)",
       VBOXOSTYPE_ArchLinux,       VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -157,7 +157,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_ArchLinux_x64,   VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Debian",             "Debian",
+    { "Linux",   "Linux",             "Debian",             "Debian (32 bit)",
       VBOXOSTYPE_Debian,          VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -165,7 +165,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Debian_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97},
-    { "Linux",   "Linux",             "OpenSUSE",           "openSUSE",
+    { "Linux",   "Linux",             "OpenSUSE",           "openSUSE (32 bit)",
       VBOXOSTYPE_OpenSUSE,        VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -173,7 +173,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_OpenSUSE_x64,    VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Fedora",             "Fedora",
+    { "Linux",   "Linux",             "Fedora",             "Fedora (32 bit)",
       VBOXOSTYPE_FedoraCore,      VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        768,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -181,7 +181,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_FedoraCore_x64,  VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        768,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Gentoo",             "Gentoo",
+    { "Linux",   "Linux",             "Gentoo",             "Gentoo (32 bit)",
       VBOXOSTYPE_Gentoo,          VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -189,7 +189,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Gentoo_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Mandriva",           "Mandriva",
+    { "Linux",   "Linux",             "Mandriva",           "Mandriva (32 bit)",
       VBOXOSTYPE_Mandriva,        VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -197,7 +197,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Mandriva_x64,    VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "RedHat",             "Red Hat",
+    { "Linux",   "Linux",             "RedHat",             "Red Hat (32 bit)",
       VBOXOSTYPE_RedHat,          VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -205,7 +205,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_RedHat_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_PAE | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Turbolinux",         "Turbolinux",
+    { "Linux",   "Linux",             "Turbolinux",         "Turbolinux (32 bit)",
       VBOXOSTYPE_Turbolinux,      VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        384,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -213,7 +213,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Turbolinux_x64,  VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        384,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Ubuntu",             "Ubuntu",
+    { "Linux",   "Linux",             "Ubuntu",             "Ubuntu (32 bit)",
       VBOXOSTYPE_Ubuntu,          VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -221,7 +221,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Ubuntu_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Xandros",            "Xandros",
+    { "Linux",   "Linux",             "Xandros",            "Xandros (32 bit)",
       VBOXOSTYPE_Xandros,         VBOXOSHINT_RTCUTC,
        256,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -229,7 +229,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Xandros_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
        256,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Oracle",             "Oracle",
+    { "Linux",   "Linux",             "Oracle",             "Oracle (32 bit)",
       VBOXOSTYPE_Oracle,          VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE,
        512,  12, 12 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -237,7 +237,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Oracle_x64,      VBOXOSHINT_64BIT | VBOXOSHINT_PAE | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
        512,  12, 12 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Linux",   "Linux",             "Linux",              "Other Linux",
+    { "Linux",   "Linux",             "Linux",              "Other Linux (32 bit)",
       VBOXOSTYPE_Linux,           VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        256,  12,  8 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -245,7 +245,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Linux_x64,       VBOXOSHINT_64BIT | VBOXOSHINT_PAE | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
        512,  12,  8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Solaris", "Solaris",           "Solaris",            "Oracle Solaris 10 5/09 and earlier",
+    { "Solaris", "Solaris",           "Solaris",            "Oracle Solaris 10 5/09 and earlier (32 bit)",
       VBOXOSTYPE_Solaris,         VBOXOSHINT_NONE,
        768,  12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -253,7 +253,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Solaris_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
       1536,  12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "Solaris", "Solaris",           "OpenSolaris",        "Oracle Solaris 10 10/09 and later",
+    { "Solaris", "Solaris",           "OpenSolaris",        "Oracle Solaris 10 10/09 and later (32 bit)",
       VBOXOSTYPE_OpenSolaris,     VBOXOSHINT_USBTABLET,
        768,  12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -265,7 +265,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_Solaris11_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
       1536,  12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
         StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "BSD",     "BSD",               "FreeBSD",            "FreeBSD",
+    { "BSD",     "BSD",               "FreeBSD",            "FreeBSD (32 bit)",
       VBOXOSTYPE_FreeBSD,         VBOXOSHINT_NONE,
        128,   4,  2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -273,7 +273,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_FreeBSD_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
        128,   4,  2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "BSD",     "BSD",               "OpenBSD",            "OpenBSD",
+    { "BSD",     "BSD",               "OpenBSD",            "OpenBSD (32 bit)",
       VBOXOSTYPE_OpenBSD,         VBOXOSHINT_HWVIRTEX,
         64,   4,  2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -281,7 +281,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_OpenBSD_x64,     VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
         64,   4,  2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
-    { "BSD",     "BSD",               "NetBSD",             "NetBSD",
+    { "BSD",     "BSD",               "NetBSD",             "NetBSD (32 bit)",
       VBOXOSTYPE_NetBSD,          VBOXOSHINT_NONE,
         64,   4,  2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97  },
@@ -309,7 +309,7 @@ const Global::OSType Global::sOSTypes[] =
       VBOXOSTYPE_OS2,             VBOXOSHINT_HWVIRTEX | VBOXOSHINT_FLOPPY | VBOXOSHINT_NOUSB,
         96,   4,  2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
         StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16  },
-    { "MacOS",   "Mac OS X",          "MacOS",              "Mac OS X",
+    { "MacOS",   "Mac OS X",          "MacOS",              "Mac OS X (32 bit)",
       VBOXOSTYPE_MacOS,           VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_EFI | VBOXOSHINT_PAE
                                 | VBOXOSHINT_USBHID | VBOXOSHINT_HPET | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
       2048,   4, 20 * _1G64, NetworkAdapterType_I82545EM, 0,
@@ -321,7 +321,7 @@ const Global::OSType Global::sOSTypes[] =
       2048,   4, 20 * _1G64, NetworkAdapterType_I82545EM, 0,
       StorageControllerType_IntelAhci, StorageBus_SATA, StorageControllerType_IntelAhci, StorageBus_SATA,
       ChipsetType_ICH9, AudioControllerType_HDA  },
-    { "MacOS",   "Mac OS X",          "MacOS106",           "Mac OS X 10.6 Snow Leopard",
+    { "MacOS",   "Mac OS X",          "MacOS106",           "Mac OS X 10.6 Snow Leopard (32 bit)",
       VBOXOSTYPE_MacOS106,        VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_EFI | VBOXOSHINT_PAE
                                 | VBOXOSHINT_USBHID | VBOXOSHINT_HPET | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
       2048,   4, 20 * _1G64, NetworkAdapterType_I82545EM, 0,
diff --git a/src/VBox/Main/src-client/ConsoleImpl.cpp b/src/VBox/Main/src-client/ConsoleImpl.cpp
index 5fd97bf..78d97f7 100644
--- a/src/VBox/Main/src-client/ConsoleImpl.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl.cpp
@@ -6668,6 +6668,31 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
         else
             progressDesc = tr("Starting virtual machine");
 
+        Bstr savedStateFile;
+
+        /*
+         * Saved VMs will have to prove that their saved states seem kosher.
+         */
+        if (mMachineState == MachineState_Saved)
+        {
+            rc = mMachine->COMGETTER(StateFilePath)(savedStateFile.asOutParam());
+            if (FAILED(rc))
+                throw rc;
+            ComAssertRet(!savedStateFile.isEmpty(), E_FAIL);
+            int vrc = SSMR3ValidateFile(Utf8Str(savedStateFile).c_str(), false /* fChecksumIt */);
+            if (RT_FAILURE(vrc))
+                throw setError(VBOX_E_FILE_ERROR,
+                               tr("VM cannot start because the saved state file '%ls' is invalid (%Rrc). Delete the saved state prior to starting the VM"),
+                               savedStateFile.raw(), vrc);
+        }
+
+        /* Read console data, including console shared folders, stored in the
+         * saved state file (if not yet done).
+         */
+        rc = loadDataFromSavedState();
+        if (FAILED(rc))
+            throw rc;
+
         /* Check all types of shared folders and compose a single list */
         SharedFolderDataMap sharedFolders;
         {
@@ -6703,24 +6728,6 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
             }
         }
 
-        Bstr savedStateFile;
-
-        /*
-         * Saved VMs will have to prove that their saved states seem kosher.
-         */
-        if (mMachineState == MachineState_Saved)
-        {
-            rc = mMachine->COMGETTER(StateFilePath)(savedStateFile.asOutParam());
-            if (FAILED(rc))
-                throw rc;
-            ComAssertRet(!savedStateFile.isEmpty(), E_FAIL);
-            int vrc = SSMR3ValidateFile(Utf8Str(savedStateFile).c_str(), false /* fChecksumIt */);
-            if (RT_FAILURE(vrc))
-                throw setError(VBOX_E_FILE_ERROR,
-                               tr("VM cannot start because the saved state file '%ls' is invalid (%Rrc). Delete the saved state prior to starting the VM"),
-                               savedStateFile.raw(), vrc);
-        }
-
         /* Setup task object and thread to carry out the operaton
          * Asycnhronously */
         std::auto_ptr<VMPowerUpTask> task(new VMPowerUpTask(this, pPowerupProgress));
@@ -6984,11 +6991,6 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
         }
 #endif // 0
 
-        /* Read console data stored in the saved state file (if not yet done) */
-        rc = loadDataFromSavedState();
-        if (FAILED(rc))
-            throw rc;
-
         /* setup task object and thread to carry out the operation
          * asynchronously */
         if (aProgress){
diff --git a/src/VBox/Main/src-client/ConsoleImpl2.cpp b/src/VBox/Main/src-client/ConsoleImpl2.cpp
index 01d06a1..b762a06 100644
--- a/src/VBox/Main/src-client/ConsoleImpl2.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl2.cpp
@@ -506,20 +506,102 @@ static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, c
 }
 
 
-/** Helper that finds out the next SATA port used
+/** Helper that finds out the next HBA port used
  */
-static LONG GetNextUsedSataPort(LONG aSataPortUsed[30], LONG lBaseVal, uint32_t u32Size)
+static LONG GetNextUsedPort(LONG aPortUsed[30], LONG lBaseVal, uint32_t u32Size)
 {
     LONG lNextPortUsed = 30;
     for (size_t j = 0; j < u32Size; ++j)
     {
-        if (   aSataPortUsed[j] >  lBaseVal
-            && aSataPortUsed[j] <= lNextPortUsed)
-           lNextPortUsed = aSataPortUsed[j];
+        if (   aPortUsed[j] >  lBaseVal
+            && aPortUsed[j] <= lNextPortUsed)
+           lNextPortUsed = aPortUsed[j];
     }
     return lNextPortUsed;
 }
 
+#define MAX_BIOS_LUN_COUNT   4
+
+static int SetBiosDiskInfo(ComPtr<IMachine> pMachine, PCFGMNODE pCfg, PCFGMNODE pBiosCfg,
+                           Bstr controllerName, const char * const s_apszBiosConfig[4])
+{
+    HRESULT             hrc;
+#define MAX_DEVICES     30
+#define H()     AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE)
+
+    LONG lPortLUN[MAX_BIOS_LUN_COUNT];
+    LONG lPortUsed[MAX_DEVICES];
+    uint32_t u32HDCount = 0;
+
+    /* init to max value */
+    lPortLUN[0] = MAX_DEVICES;
+
+    com::SafeIfaceArray<IMediumAttachment> atts;
+    hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
+                                        ComSafeArrayAsOutParam(atts));  H();
+    size_t uNumAttachments = atts.size();
+    if (uNumAttachments > MAX_DEVICES)
+    {
+        LogRel(("Number of Attachments > Max=%d.\n", uNumAttachments));
+        uNumAttachments = MAX_DEVICES;
+    }
+
+    /* Find the relevant ports/IDs, i.e the ones to which a HD is attached. */
+    for (size_t j = 0; j < uNumAttachments; ++j)
+    {
+        IMediumAttachment *pMediumAtt = atts[j];
+        LONG lPortNum = 0;
+        hrc = pMediumAtt->COMGETTER(Port)(&lPortNum);                   H();
+        if (SUCCEEDED(hrc))
+        {
+            DeviceType_T lType;
+            hrc = pMediumAtt->COMGETTER(Type)(&lType);                    H();
+            if (SUCCEEDED(hrc) && lType == DeviceType_HardDisk)
+            {
+                /* find min port number used for HD */
+                if (lPortNum < lPortLUN[0])
+                    lPortLUN[0] = lPortNum;
+                lPortUsed[u32HDCount++] = lPortNum;
+                LogFlowFunc(("HD port Count=%d\n", u32HDCount));
+            }
+
+            /* Configure the hotpluggable flag for the port. */
+            BOOL fHotPluggable = FALSE;
+            hrc = pMediumAtt->COMGETTER(HotPluggable)(&fHotPluggable); H();
+            if (SUCCEEDED(hrc))
+            {
+                PCFGMNODE pPortCfg;
+                char szName[24];
+                RTStrPrintf(szName, sizeof(szName), "Port%d", lPortNum);
+
+                InsertConfigNode(pCfg, szName, &pPortCfg);
+                InsertConfigInteger(pPortCfg, "Hotpluggable", fHotPluggable ? 1 : 0);
+            }
+         }
+    }
+
+
+    /* Pick only the top 4 used HD Ports as CMOS doesn't have space
+     * to save details for all 30 ports
+     */
+    uint32_t u32MaxPortCount = MAX_BIOS_LUN_COUNT;
+    if (u32HDCount < MAX_BIOS_LUN_COUNT)
+        u32MaxPortCount = u32HDCount;
+    for (size_t j = 1; j < u32MaxPortCount; j++)
+        lPortLUN[j] = GetNextUsedPort(lPortUsed,
+                                      lPortLUN[j-1],
+                                       u32HDCount);
+    if (pBiosCfg)
+    {
+        for (size_t j = 0; j < u32MaxPortCount; j++)
+        {
+            InsertConfigInteger(pBiosCfg, s_apszBiosConfig[j], lPortLUN[j]);
+            LogFlowFunc(("Top %d HBA ports = %s, %d\n", j, s_apszBiosConfig[j], lPortLUN[j]));
+        }
+    }
+    return VINF_SUCCESS;
+}
+
 #ifdef VBOX_WITH_PCI_PASSTHROUGH
 HRESULT Console::attachRawPCIDevices(PUVM pUVM, BusAssignmentManager *pBusMgr, PCFGMNODE pDevices)
 {
@@ -1172,6 +1254,10 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
             hrc = bwGroups[i]->COMGETTER(Type)(&enmType);                                   H();
             hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec);                 H();
 
+            if (strName.isEmpty())
+                return VMR3SetError(pUVM, VERR_CFGM_NO_NODE, RT_SRC_POS,
+                                    N_("No bandwidth group name specified"));
+
             if (enmType == BandwidthGroupType_Disk)
             {
                 PCFGMNODE pBwGroup;
@@ -1203,6 +1289,7 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
         PCFGMNODE pLunL2 = NULL;        /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
         PCFGMNODE pBiosCfg = NULL;      /* /Devices/pcbios/0/Config/ */
         PCFGMNODE pNetBootCfg = NULL;   /* /Devices/pcbios/0/Config/NetBoot/ */
+        bool fHaveBiosScsiConfig = false;
 
         InsertConfigNode(pRoot, "Devices", &pDevices);
 
@@ -1431,7 +1518,10 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
             case GraphicsControllerType_Null:
                 break;
             case GraphicsControllerType_VBoxVGA:
-                rc = configGraphicsController(pDevices, "vga", pBusMgr, pMachine, biosSettings,
+#ifdef VBOX_WITH_VMSVGA
+            case GraphicsControllerType_VMSVGA:
+#endif
+                rc = configGraphicsController(pDevices, graphicsController, pBusMgr, pMachine, biosSettings,
                                               RT_BOOL(fHMEnabled));
                 if (FAILED(rc))
                     return rc;
@@ -1641,6 +1731,12 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
             InsertConfigInteger(pCtlInst, "Trusted",   1);
             InsertConfigNode(pCtlInst,    "Config",    &pCfg);
 
+            static const char * const apszBiosConfigScsi[MAX_BIOS_LUN_COUNT] =
+            { "ScsiLUN1", "ScsiLUN2", "ScsiLUN3", "ScsiLUN4" };
+
+            static const char * const apszBiosConfigSata[MAX_BIOS_LUN_COUNT] =
+            { "SataLUN1", "SataLUN2", "SataLUN3", "SataLUN4" };
+
             switch (enmCtrlType)
             {
                 case StorageControllerType_LsiLogic:
@@ -1649,6 +1745,18 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
 
                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
 
+                    /* BIOS configuration values, first controller only. */
+                    if (!pBusMgr->hasPCIDevice("lsilogicscsi", 1) && pBiosCfg)
+                    {
+                        if (!fHaveBiosScsiConfig)
+                        {
+                            fHaveBiosScsiConfig = true;
+                            InsertConfigString(pBiosCfg, "ScsiHardDiskDevice", "lsilogicscsi");
+
+                            hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigScsi);    H();
+                        }
+                    }
+
                     /* Attach the status driver */
                     Assert(cLedScsi >= 16);
                     attachStatusDriver(pCtlInst, &mapStorageLeds[iLedScsi], 0, 15,
@@ -1663,6 +1771,18 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
 
                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
 
+                    /* BIOS configuration values, first controller only. */
+                    if (!pBusMgr->hasPCIDevice("buslogic", 1) && pBiosCfg)
+                    {
+                        if (!fHaveBiosScsiConfig)
+                        {
+                            fHaveBiosScsiConfig = true;
+                            InsertConfigString(pBiosCfg, "ScsiHardDiskDevice", "buslogic");
+
+                            hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigScsi);    H();
+                        }
+                    }
+
                     /* Attach the status driver */
                     Assert(cLedScsi >= 16);
                     attachStatusDriver(pCtlInst, &mapStorageLeds[iLedScsi], 0, 15,
@@ -1683,76 +1803,12 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
                     /* Needed configuration values for the bios, only first controller. */
                     if (!pBusMgr->hasPCIDevice("ahci", 1))
                     {
-#define MAX_SATA_LUN_COUNT 4
-#define MAX_SATA_PORTS     30
-
-                        static const char * const s_apszBiosConfig[4] =
-                        { "SataLUN1", "SataLUN2", "SataLUN3", "SataLUN4" };
-
-                        LONG lPortLUN[MAX_SATA_LUN_COUNT];
-                        LONG lPortUsed[MAX_SATA_PORTS];
-                        uint32_t u32HDSataPortCount = 0;
-
-                        /* init to max value */
-                        lPortLUN[0] = MAX_SATA_PORTS;
-
                         if (pBiosCfg)
                         {
                             InsertConfigString(pBiosCfg, "SataHardDiskDevice", "ahci");
                         }
 
-                        com::SafeIfaceArray<IMediumAttachment> atts;
-                        hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
-                                                            ComSafeArrayAsOutParam(atts));  H();
-                        size_t uNumAttachments = atts.size();
-                        if (uNumAttachments > MAX_SATA_PORTS)
-                        {
-                            LogRel(("Number of Sata Port Attachments > Max=%d.\n", uNumAttachments));
-                            uNumAttachments =  MAX_SATA_PORTS;
-                        }
-
-                        /* find the relavant ports i.e Sata ports to which
-                         * HD is attached.
-                         */
-                        for (size_t j = 0; j < uNumAttachments; ++j)
-                        {
-                            IMediumAttachment *pMediumAtt = atts[j];
-                            LONG lPortNum = 0;
-                            hrc = pMediumAtt->COMGETTER(Port)(&lPortNum);                   H();
-                            if (SUCCEEDED(hrc))
-                            {
-                                DeviceType_T lType;
-                                hrc = pMediumAtt->COMGETTER(Type)(&lType);                    H();
-                                if (SUCCEEDED(hrc) && lType == DeviceType_HardDisk)
-                                {
-                                    /* find min port number used for HD */
-                                    if (lPortNum < lPortLUN[0])
-                                        lPortLUN[0] = lPortNum;
-                                    lPortUsed[u32HDSataPortCount++] = lPortNum;
-                                    LogFlowFunc(("HD Sata port Count=%d\n", u32HDSataPortCount));
-                                }
-                             }
-                        }
-
-
-                        /* Pick only the top 4 used HD Sata Ports as CMOS doesn't have space
-                         * to save details for every 30 ports
-                         */
-                        uint32_t u32MaxPortCount = MAX_SATA_LUN_COUNT;
-                        if (u32HDSataPortCount < MAX_SATA_LUN_COUNT)
-                            u32MaxPortCount = u32HDSataPortCount;
-                        for (size_t j = 1; j < u32MaxPortCount; j++)
-                            lPortLUN[j] = GetNextUsedSataPort(lPortUsed,
-                                                              lPortLUN[j-1],
-                                                              u32HDSataPortCount);
-                        if (pBiosCfg)
-                        {
-                            for (size_t j = 0; j < u32MaxPortCount; j++)
-                            {
-                                InsertConfigInteger(pBiosCfg, s_apszBiosConfig[j], lPortLUN[j]);
-                                LogFlowFunc(("Top %d ports = %s, %d\n", j, s_apszBiosConfig[j], lPortLUN[j]));
-                            }
-                        }
+                        hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigSata);    H();
                     }
 
                     /* Attach the status driver */
@@ -1811,6 +1867,22 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
                     InsertConfigString(pCfg,  "ControllerType", "SAS1068");
                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
 
+                    /* BIOS configuration values, first controller only. */
+                    if (!pBusMgr->hasPCIDevice("lsilogicsas", 1) && pBiosCfg)
+                    {
+                        if (!fHaveBiosScsiConfig)
+                        {
+                            fHaveBiosScsiConfig = true;
+                            InsertConfigString(pBiosCfg, "ScsiHardDiskDevice", "lsilogicsas");
+
+                            hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigScsi);    H();
+                        }
+                    }
+
+                    ULONG cPorts = 0;
+                    hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts);                          H();
+                    InsertConfigInteger(pCfg, "NumPorts", cPorts);
+
                     /* Attach the status driver */
                     Assert(cLedSas >= 8);
                     attachStatusDriver(pCtlInst, &mapStorageLeds[iLedSas], 0, 7,
@@ -3164,7 +3236,7 @@ int Console::configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMa
 }
 
 int Console::configGraphicsController(PCFGMNODE pDevices,
-                                      const char *pcszDevice,
+                                      const GraphicsControllerType_T graphicsController,
                                       BusAssignmentManager *pBusMgr,
                                       const ComPtr<IMachine> &pMachine,
                                       const ComPtr<IBIOSSettings> &biosSettings,
@@ -3176,6 +3248,7 @@ int Console::configGraphicsController(PCFGMNODE pDevices,
         PCFGMNODE pDev, pInst, pCfg, pLunL0;
         HRESULT hrc;
         Bstr    bstr;
+        const char *pcszDevice = "vga";
 
 #define H()         AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE)
         InsertConfigNode(pDevices, pcszDevice, &pDev);
@@ -3196,6 +3269,27 @@ int Console::configGraphicsController(PCFGMNODE pDevices,
         NOREF(fHMEnabled);
 #endif
 
+#ifdef VBOX_WITH_VMSVGA
+        if (graphicsController == GraphicsControllerType_VMSVGA)
+        {
+            InsertConfigInteger(pCfg, "VMSVGAEnabled", true);
+#ifdef VBOX_WITH_VMSVGA3D
+            IFramebuffer *pFramebuffer = getDisplay()->getFramebuffer();
+            if (pFramebuffer)
+            {
+                LONG64 winId = 0;
+                /* @todo deal with multimonitor setup */
+                Assert(cMonitorCount == 1);
+                hrc = pFramebuffer->COMGETTER(WinId)(&winId);
+                InsertConfigInteger(pCfg, "HostWindowId", winId);
+            }
+            BOOL f3DEnabled;
+            pMachine->COMGETTER(Accelerate3DEnabled)(&f3DEnabled);
+            InsertConfigInteger(pCfg, "VMSVGA3dEnabled", f3DEnabled);
+#endif
+        }
+#endif
+
         /* Custom VESA mode list */
         unsigned cModes = 0;
         for (unsigned iMode = 1; iMode <= 16; ++iMode)
@@ -4244,6 +4338,10 @@ int Console::configNetwork(const char *pszDevice,
                     if (!fValid)
                         continue;
 
+                    if (strName.isEmpty())
+                        VMSetError(VMR3GetVM(mpUVM), VERR_CFGM_NO_NODE, RT_SRC_POS,
+                                   N_("NAT redirection rule without a name"));
+
                     InsertConfigNode(pCfg, strName.c_str(), &pPF);
                     InsertConfigString(pPF, "Protocol", strProto);
 
diff --git a/src/VBox/Main/src-client/DisplayImpl.cpp b/src/VBox/Main/src-client/DisplayImpl.cpp
index 547104c..b627085 100644
--- a/src/VBox/Main/src-client/DisplayImpl.cpp
+++ b/src/VBox/Main/src-client/DisplayImpl.cpp
@@ -53,6 +53,14 @@
 # include "VideoRec.h"
 #endif
 
+#ifdef VBOX_WITH_CROGL
+typedef enum
+{
+    CRVREC_STATE_IDLE,
+    CRVREC_STATE_SUBMITTED
+} CRVREC_STATE;
+#endif
+
 /**
  * Display driver instance data.
  *
@@ -107,6 +115,9 @@ HRESULT Display::FinalConstruct()
     mfPendingVideoAccelEnable = false;
 
     mfMachineRunning = false;
+#ifdef VBOX_WITH_CROGL
+    mfCrOglDataHidden = false;
+#endif
 
     mpu8VbvaPartial = NULL;
     mcbVbvaPartial = 0;
@@ -138,6 +149,20 @@ HRESULT Display::FinalConstruct()
         maVideoRecEnabled[i] = true;
 #endif
 
+#ifdef VBOX_WITH_CRHGSMI
+    mhCrOglSvc = NULL;
+#endif
+#ifdef VBOX_WITH_CROGL
+    RT_ZERO(mCrOglCallbacks);
+    RT_ZERO(mCrOglScreenshotData);
+    mfCrOglVideoRecState = CRVREC_STATE_IDLE;
+    mCrOglScreenshotData.u32Screen = CRSCREEN_ALL;
+    mCrOglScreenshotData.pvContext = this;
+    mCrOglScreenshotData.pfnScreenshotBegin = displayCrVRecScreenshotBegin;
+    mCrOglScreenshotData.pfnScreenshotPerform = displayCrVRecScreenshotPerform;
+    mCrOglScreenshotData.pfnScreenshotEnd = displayCrVRecScreenshotEnd;
+#endif
+
     return BaseFinalConstruct();
 }
 
@@ -222,6 +247,47 @@ static int displayMakeThumbnail(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
     return rc;
 }
 
+#ifdef VBOX_WITH_CROGL
+typedef struct
+{
+    CRVBOXHGCMTAKESCREENSHOT Base;
+
+    /* 32bpp small RGB image. */
+    uint8_t *pu8Thumbnail;
+    uint32_t cbThumbnail;
+    uint32_t cxThumbnail;
+    uint32_t cyThumbnail;
+
+    /* PNG screenshot. */
+    uint8_t *pu8PNG;
+    uint32_t cbPNG;
+    uint32_t cxPNG;
+    uint32_t cyPNG;
+} VBOX_DISPLAY_SAVESCREENSHOT_DATA;
+
+static DECLCALLBACK(void) displaySaveScreenshotReport(void *pvCtx, uint32_t uScreen,
+        uint32_t x, uint32_t y, uint32_t uBitsPerPixel,
+        uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
+        uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
+{
+    VBOX_DISPLAY_SAVESCREENSHOT_DATA *pData = (VBOX_DISPLAY_SAVESCREENSHOT_DATA*)pvCtx;
+    displayMakeThumbnail(pu8BufferAddress, uGuestWidth, uGuestHeight, &pData->pu8Thumbnail, &pData->cbThumbnail, &pData->cxThumbnail, &pData->cyThumbnail);
+    int rc = DisplayMakePNG(pu8BufferAddress, uGuestWidth, uGuestHeight, &pData->pu8PNG, &pData->cbPNG, &pData->cxPNG, &pData->cyPNG, 1);
+    if (RT_FAILURE(rc))
+    {
+        AssertMsgFailed(("DisplayMakePNG failed %d\n", rc));
+        if (pData->pu8PNG)
+        {
+            RTMemFree(pData->pu8PNG);
+            pData->pu8PNG = NULL;
+        }
+        pData->cbPNG = 0;
+        pData->cxPNG = 0;
+        pData->cyPNG = 0;
+    }
+}
+#endif
+
 DECLCALLBACK(void)
 Display::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
 {
@@ -248,34 +314,96 @@ Display::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
         uint32_t cx = 0;
         uint32_t cy = 0;
 
-        /* SSM code is executed on EMT(0), therefore no need to use VMR3ReqCallWait. */
-        int rc = Display::displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
+#ifdef VBOX_WITH_CROGL
+        BOOL f3DSnapshot = FALSE;
+        BOOL is3denabled;
+        that->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+        if (is3denabled && that->mCrOglCallbacks.pfnHasData())
+        {
+            VMMDev *pVMMDev = that->mParent->getVMMDev();
+            if (pVMMDev)
+            {
+                VBOX_DISPLAY_SAVESCREENSHOT_DATA *pScreenshot = (VBOX_DISPLAY_SAVESCREENSHOT_DATA*)RTMemAllocZ(sizeof (*pScreenshot));
+                if (pScreenshot)
+                {
+                    /* screen id or CRSCREEN_ALL to specify all enabled */
+                    pScreenshot->Base.u32Screen = 0;
+                    pScreenshot->Base.u32Width = 0;
+                    pScreenshot->Base.u32Height = 0;
+                    pScreenshot->Base.u32Pitch = 0;
+                    pScreenshot->Base.pvBuffer = NULL;
+                    pScreenshot->Base.pvContext = pScreenshot;
+                    pScreenshot->Base.pfnScreenshotBegin = NULL;
+                    pScreenshot->Base.pfnScreenshotPerform = displaySaveScreenshotReport;
+                    pScreenshot->Base.pfnScreenshotEnd = NULL;
+
+                    VBOXHGCMSVCPARM parm;
+
+                    parm.type = VBOX_HGCM_SVC_PARM_PTR;
+                    parm.u.pointer.addr = &pScreenshot->Base;
+                    parm.u.pointer.size = sizeof (pScreenshot->Base);
+
+                    int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_TAKE_SCREENSHOT, 1, &parm);
+                    if (RT_SUCCESS(rc))
+                    {
+                        if (pScreenshot->pu8PNG)
+                        {
+                            pu8Thumbnail = pScreenshot->pu8Thumbnail;
+                            cbThumbnail = pScreenshot->cbThumbnail;
+                            cxThumbnail = pScreenshot->cxThumbnail;
+                            cyThumbnail = pScreenshot->cyThumbnail;
+
+                            /* PNG screenshot. */
+                            pu8PNG = pScreenshot->pu8PNG;
+                            cbPNG = pScreenshot->cbPNG;
+                            cxPNG = pScreenshot->cxPNG;
+                            cyPNG = pScreenshot->cyPNG;
+                            f3DSnapshot = TRUE;
+                        }
+                        else
+                            AssertMsgFailed(("no png\n"));
+                    }
+                    else
+                        AssertMsgFailed(("SHCRGL_HOST_FN_TAKE_SCREENSHOT failed %d\n", rc));
+
 
-        /*
-         * It is possible that success is returned but everything is 0 or NULL.
-         * (no display attached if a VM is running with VBoxHeadless on OSE for example)
-         */
-        if (RT_SUCCESS(rc) && pu8Data)
+                    RTMemFree(pScreenshot);
+                }
+            }
+        }
+
+        if (!f3DSnapshot)
+#endif
         {
-            Assert(cx && cy);
+            /* SSM code is executed on EMT(0), therefore no need to use VMR3ReqCallWait. */
+            int rc = Display::displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
 
-            /* Prepare a small thumbnail and a PNG screenshot. */
-            displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
-            rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
-            if (RT_FAILURE(rc))
+            /*
+             * It is possible that success is returned but everything is 0 or NULL.
+             * (no display attached if a VM is running with VBoxHeadless on OSE for example)
+             */
+            if (RT_SUCCESS(rc) && pu8Data)
             {
-                if (pu8PNG)
+                Assert(cx && cy);
+
+                /* Prepare a small thumbnail and a PNG screenshot. */
+                displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
+                rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
+                if (RT_FAILURE(rc))
                 {
-                    RTMemFree(pu8PNG);
-                    pu8PNG = NULL;
+                    if (pu8PNG)
+                    {
+                        RTMemFree(pu8PNG);
+                        pu8PNG = NULL;
+                    }
+                    cbPNG = 0;
+                    cxPNG = 0;
+                    cyPNG = 0;
                 }
-                cbPNG = 0;
-                cxPNG = 0;
-                cyPNG = 0;
-            }
 
-            /* This can be called from any thread. */
-            that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
+                /* This can be called from any thread. */
+                that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
+            }
         }
     }
     else
@@ -496,6 +624,9 @@ HRESULT Display::init(Console *aParent)
         RT_ZERO(maFramebuffers[ul].vbvaSkippedRect);
         maFramebuffers[ul].pVBVAHostFlags = NULL;
 #endif /* VBOX_WITH_HGSMI */
+#ifdef VBOX_WITH_CROGL
+        RT_ZERO(maFramebuffers[ul].pendingViewportInfo);
+#endif
     }
 
     {
@@ -590,6 +721,46 @@ int Display::registerSSM(PUVM pUVM)
     return VINF_SUCCESS;
 }
 
+#ifdef VBOX_WITH_CROGL
+int Display::crOglWindowsShow(bool fShow)
+{
+    if (!mfCrOglDataHidden == !!fShow)
+        return VINF_SUCCESS;
+
+    if (!mhCrOglSvc)
+    {
+        /* no 3D */
+#ifdef DEBUG
+        BOOL is3denabled;
+        mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+        Assert(!is3denabled);
+#endif
+        return VERR_INVALID_STATE;
+    }
+
+    VMMDev *pVMMDev = mParent->getVMMDev();
+    if (!pVMMDev)
+    {
+        AssertMsgFailed(("no vmmdev\n"));
+        return VERR_INVALID_STATE;
+    }
+
+    VBOXHGCMSVCPARM parm;
+
+    parm.type = VBOX_HGCM_SVC_PARM_32BIT;
+    parm.u.uint32 = (uint32_t)fShow;
+
+    int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_WINDOWS_SHOW, &parm, NULL, NULL);
+    if (RT_SUCCESS(rc))
+        mfCrOglDataHidden = !fShow;
+    else
+        AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc));
+
+    return rc;
+}
+#endif
+
+
 // IEventListener method
 STDMETHODIMP Display::HandleEvent(IEvent * aEvent)
 {
@@ -612,9 +783,20 @@ STDMETHODIMP Display::HandleEvent(IEvent * aEvent)
                 LogRelFlowFunc(("Machine is running.\n"));
 
                 mfMachineRunning = true;
+
+#ifdef VBOX_WITH_CROGL
+                crOglWindowsShow(true);
+#endif
             }
             else
+            {
                 mfMachineRunning = false;
+
+#ifdef VBOX_WITH_CROGL
+                if (machineState == MachineState_Paused)
+                    crOglWindowsShow(false);
+#endif
+            }
             break;
         }
         default:
@@ -652,6 +834,46 @@ static int callFramebufferResize (IFramebuffer *pFramebuffer, unsigned uScreenId
     return VINF_SUCCESS;
 }
 
+int Display::notifyCroglResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM)
+{
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+    BOOL is3denabled;
+    mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+
+    if (is3denabled)
+    {
+        int rc = VERR_INVALID_STATE;
+        if (mhCrOglSvc)
+        {
+            VMMDev *pVMMDev = mParent->getVMMDev();
+            if (pVMMDev)
+            {
+                CRVBOXHGCMDEVRESIZE *pData = (CRVBOXHGCMDEVRESIZE*)RTMemAlloc(sizeof (*pData));
+                if (pData)
+                {
+                    pData->Screen = *pScreen;
+                    pData->pvVRAM = pvVRAM;
+
+                    VBOXHGCMSVCPARM parm;
+
+                    parm.type = VBOX_HGCM_SVC_PARM_PTR;
+                    parm.u.pointer.addr = pData;
+                    parm.u.pointer.size = sizeof (*pData);
+
+                    rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_DEV_RESIZE, &parm, displayCrAsyncCmdCompletion, this);
+                    AssertRC(rc);
+                }
+                else
+                    rc = VERR_NO_MEMORY;
+            }
+        }
+
+        return rc;
+    }
+#endif /* #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) */
+    return VINF_SUCCESS;
+}
+
 /**
  *  Handles display resize event.
  *  Disables access to VGA device;
@@ -891,7 +1113,16 @@ void Display::handleResizeCompletedEMT (void)
 
                 VMMDev *pVMMDev = mParent->getVMMDev();
                 if (pVMMDev)
+                {
+#if 0
+                    if (mhCrOglSvc)
+                        pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SCREEN_CHANGED, &parm, NULL, NULL);
+                    else
+                        AssertMsgFailed(("mhCrOglSvc is NULL\n"));
+#else
                     pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
+#endif
+                }
             }
         }
 #endif /* VBOX_WITH_CROGL */
@@ -1207,15 +1438,27 @@ int Display::handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect)
     VMMDev *vmmDev = mParent->getVMMDev();
     if (is3denabled && vmmDev)
     {
-        VBOXHGCMSVCPARM parms[2];
+        if (mhCrOglSvc)
+        {
+            RTRECT *pRectsCopy = (RTRECT *)RTMemAlloc(  RT_MAX(cRect, 1)
+                                                             * sizeof (RTRECT));
+            if (pRectsCopy)
+            {
+                memcpy(pRectsCopy, pRect, cRect * sizeof (RTRECT));
+
+                VBOXHGCMSVCPARM parm;
 
-        parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
-        parms[0].u.pointer.addr = pRect;
-        parms[0].u.pointer.size = 0;  /* We don't actually care. */
-        parms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
-        parms[1].u.uint32 = cRect;
+                parm.type = VBOX_HGCM_SVC_PARM_PTR;
+                parm.u.pointer.addr = pRectsCopy;
+                parm.u.pointer.size = cRect * sizeof (RTRECT);
 
-        vmmDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VISIBLE_REGION, 2, &parms[0]);
+                vmmDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SET_VISIBLE_REGION, &parm, displayCrAsyncCmdCompletion, this);
+            }
+            else
+                AssertMsgFailed(("failed to allocate rects memory\n"));
+        }
+        else
+            AssertMsgFailed(("mhCrOglSvc is NULL\n"));
     }
 #endif
 
@@ -1630,7 +1873,7 @@ static void vbvaFetchBytes (VBVAMEMORY *pVbvaMemory, uint8_t *pu8Dst, uint32_t c
 {
     if (cbDst >= VBVA_RING_BUFFER_SIZE)
     {
-        AssertMsgFailed (("cbDst = 0x%08X, ring buffer size 0x%08X", cbDst, VBVA_RING_BUFFER_SIZE));
+        AssertMsgFailed (("cbDst = 0x%08X, ring buffer size 0x%08X\n", cbDst, VBVA_RING_BUFFER_SIZE));
         return;
     }
 
@@ -2170,7 +2413,16 @@ STDMETHODIMP Display::SetFramebuffer(ULONG aScreenId, IFramebuffer *aFramebuffer
                 alock.release();
 
                 if (pVMMDev)
-                    vrc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
+                {
+#if 0
+                    if (mhCrOglSvc)
+                        pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SCREEN_CHANGED, &parm, NULL, NULL);
+                    else
+                        AssertMsgFailed(("mhCrOglSvc is NULL\n"));
+#else
+                    pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
+#endif
+                }
                 /*ComAssertRCRet (vrc, E_FAIL);*/
 
                 alock.acquire();
@@ -2301,22 +2553,72 @@ STDMETHODIMP Display::SetSeamlessMode (BOOL enabled)
         VMMDev *vmmDev = mParent->getVMMDev();
         if (is3denabled && vmmDev)
         {
-            VBOXHGCMSVCPARM parms[2];
+            VBOXHGCMSVCPARM parm;
 
-            parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+            parm.type = VBOX_HGCM_SVC_PARM_PTR;
             /* NULL means disable */
-            parms[0].u.pointer.addr = NULL;
-            parms[0].u.pointer.size = 0;  /* We don't actually care. */
-            parms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
-            parms[1].u.uint32 = 0;
+            parm.u.pointer.addr = NULL;
+            parm.u.pointer.size = 0;  /* <- means null rects, NULL pRects address and 0 rects means "disable" */
+
+            if (mhCrOglSvc)
+                vmmDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SET_VISIBLE_REGION, &parm, NULL, NULL);
+            else
+                AssertMsgFailed(("mhCrOglSvc is NULL\n"));
 
-            vmmDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VISIBLE_REGION, 2, &parms[0]);
         }
     }
 #endif
     return S_OK;
 }
 
+#ifdef VBOX_WITH_CROGL
+BOOL Display::displayCheckTakeScreenshotCrOgl(Display *pDisplay, ULONG aScreenId, uint8_t *pu8Data, uint32_t u32Width, uint32_t u32Height)
+{
+    BOOL is3denabled;
+    pDisplay->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+    if (is3denabled && pDisplay->mCrOglCallbacks.pfnHasData())
+    {
+        VMMDev *pVMMDev = pDisplay->mParent->getVMMDev();
+        if (pVMMDev)
+        {
+            CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)RTMemAlloc(sizeof (*pScreenshot));
+            if (pScreenshot)
+            {
+                /* screen id or CRSCREEN_ALL to specify all enabled */
+                pScreenshot->u32Screen = aScreenId;
+                pScreenshot->u32Width = u32Width;
+                pScreenshot->u32Height = u32Height;
+                pScreenshot->u32Pitch = u32Width * 4;
+                pScreenshot->pvBuffer = pu8Data;
+                pScreenshot->pvContext = NULL;
+                pScreenshot->pfnScreenshotBegin = NULL;
+                pScreenshot->pfnScreenshotPerform = NULL;
+                pScreenshot->pfnScreenshotEnd = NULL;
+
+                VBOXHGCMSVCPARM parm;
+
+                parm.type = VBOX_HGCM_SVC_PARM_PTR;
+                parm.u.pointer.addr = pScreenshot;
+                parm.u.pointer.size = sizeof (*pScreenshot);
+
+                int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_TAKE_SCREENSHOT, 1, &parm);
+
+                RTMemFree(pScreenshot);
+
+                if (RT_SUCCESS(rc))
+                    return TRUE;
+                else
+                {
+                    AssertMsgFailed(("failed to get screenshot data from crOgl %d\n", rc));
+                    /* fall back to the non-3d mechanism */
+                }
+            }
+        }
+    }
+    return FALSE;
+}
+#endif
+
 int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height)
 {
     int rc;
@@ -2383,6 +2685,14 @@ int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_
                 else
                 {
                     RTMemFree(pu8Data);
+
+                    /* CopyRect can fail if VBVA was paused in VGA device, retry using the generic method. */
+                    if (   rc == VERR_INVALID_STATE
+                        && aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
+                    {
+                        rc = pDisplay->mpDrv->pUpPort->pfnTakeScreenshot(pDisplay->mpDrv->pUpPort,
+                                                                         ppu8Data, pcbData, pu32Width, pu32Height);
+                    }
                 }
             }
         }
@@ -2413,6 +2723,11 @@ static int displayTakeScreenshot(PUVM pUVM, Display *pDisplay, struct DRVMAINDIS
     uint32_t cy = 0;
     int vrc = VINF_SUCCESS;
 
+# if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+    if (Display::displayCheckTakeScreenshotCrOgl(pDisplay, aScreenId, (uint8_t*)address, width, height))
+        return VINF_SUCCESS;
+#endif
+
     int cRetries = 5;
 
     while (cRetries-- > 0)
@@ -3151,33 +3466,33 @@ STDMETHODIMP Display::CompleteVHWACommand(BYTE *pCommand)
 STDMETHODIMP Display::ViewportChanged(ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
 {
 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+
+    if (mcMonitors <= aScreenId)
+    {
+        AssertMsgFailed(("invalid screen id\n"));
+        return E_INVALIDARG;
+    }
+
     BOOL is3denabled;
     mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
 
     if (is3denabled)
     {
-        VBOXHGCMSVCPARM aParms[5];
-
-        aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
-        aParms[0].u.uint32 = aScreenId;
-
-        aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
-        aParms[1].u.uint32 = x;
-
-        aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
-        aParms[2].u.uint32 = y;
-
-
-        aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
-        aParms[3].u.uint32 = width;
-
-        aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
-        aParms[4].u.uint32 = height;
-
         VMMDev *pVMMDev = mParent->getVMMDev();
 
         if (pVMMDev)
-            pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
+        {
+            crViewportNotify(pVMMDev, aScreenId, x, y, width, height);
+        }
+        else
+        {
+            DISPLAYFBINFO *pFb = &maFramebuffers[aScreenId];
+            pFb->pendingViewportInfo.fPending = true;
+            pFb->pendingViewportInfo.x = x;
+            pFb->pendingViewportInfo.y = y;
+            pFb->pendingViewportInfo.width = width;
+            pFb->pendingViewportInfo.height = height;
+        }
     }
 #endif /* VBOX_WITH_CROGL && VBOX_WITH_HGCM */
     return S_OK;
@@ -3265,6 +3580,54 @@ int Display::updateDisplayData(void)
     return VINF_SUCCESS;
 }
 
+#ifdef VBOX_WITH_CROGL
+void Display::crViewportNotify(VMMDev *pVMMDev, ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
+{
+#if 0
+    VBOXHGCMSVCPARM parm;
+
+    CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)RTMemAlloc(sizeof (*pViewportInfo));
+    if(!pViewportInfo)
+    {
+        AssertMsgFailed(("RTMemAlloc failed!\n"));
+        return;
+    }
+
+    pViewportInfo->u32Screen = aScreenId;
+    pViewportInfo->x = x;
+    pViewportInfo->y = y;
+    pViewportInfo->width = width;
+    pViewportInfo->height = height;
+
+    parm.type = VBOX_HGCM_SVC_PARM_PTR;
+    parm.u.pointer.addr = pViewportInfo;
+    parm.u.pointer.size = sizeof (*pViewportInfo);
+
+    pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_VIEWPORT_CHANGED2, &parm, displayCrAsyncCmdCompletion, this);
+#else
+    VBOXHGCMSVCPARM aParms[5];
+
+    aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+    aParms[0].u.uint32 = aScreenId;
+
+    aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
+    aParms[1].u.uint32 = x;
+
+    aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
+    aParms[2].u.uint32 = y;
+
+
+    aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
+    aParms[3].u.uint32 = width;
+
+    aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
+    aParms[4].u.uint32 = height;
+
+    pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
+#endif
+}
+#endif
+
 #ifdef VBOX_WITH_CRHGSMI
 void Display::setupCrHgsmiData(void)
 {
@@ -3278,8 +3641,8 @@ void Display::setupCrHgsmiData(void)
     {
         Assert(mhCrOglSvc);
         /* setup command completion callback */
-        VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION Completion;
-        Completion.Hdr.enmType = VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION;
+        VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB Completion;
+        Completion.Hdr.enmType = VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB;
         Completion.Hdr.cbCmd = sizeof (Completion);
         Completion.hCompletion = mpDrv->pVBVACallbacks;
         Completion.pfnCompletion = mpDrv->pVBVACallbacks->pfnCrHgsmiCommandCompleteAsync;
@@ -3291,7 +3654,23 @@ void Display::setupCrHgsmiData(void)
 
         rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_CRHGSMI_CTL, 1, &parm);
         if (RT_SUCCESS(rc))
+        {
+            ULONG ul;
+
+            for (ul = 0; ul < mcMonitors; ul++)
+            {
+                DISPLAYFBINFO *pFb = &maFramebuffers[ul];
+                if (!pFb->pendingViewportInfo.fPending)
+                    continue;
+
+                crViewportNotify(pVMMDev, ul, pFb->pendingViewportInfo.x, pFb->pendingViewportInfo.y, pFb->pendingViewportInfo.width, pFb->pendingViewportInfo.height);
+                pFb->pendingViewportInfo.fPending = false;
+            }
+
+            mCrOglCallbacks = Completion.MainInterface;
+
             return;
+        }
 
         AssertMsgFailed(("VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION failed rc %d", rc));
     }
@@ -3515,42 +3894,86 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
 #ifdef VBOX_WITH_VPX
     if (VideoRecIsEnabled(pDisplay->mpVideoRecCtx))
     {
-        uint64_t u64Now = RTTimeProgramMilliTS();
-        for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
-        {
-            if (!pDisplay->maVideoRecEnabled[uScreenId])
-                continue;
-
-            DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
-
-            if (   !pFBInfo->pFramebuffer.isNull()
-                && !pFBInfo->fDisabled
-                && pFBInfo->u32ResizeStatus == ResizeStatus_Void)
+        do {
+# if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+            BOOL is3denabled;
+            pDisplay->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+            if (is3denabled)
             {
-                int rc;
-                if (   pFBInfo->fVBVAEnabled
-                    && pFBInfo->pu8FramebufferVRAM)
+                if (ASMAtomicCmpXchgU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_SUBMITTED, CRVREC_STATE_IDLE))
                 {
-                    rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
-                                              FramebufferPixelFormat_FOURCC_RGB,
-                                              pFBInfo->u16BitsPerPixel,
-                                              pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
-                                              pFBInfo->pu8FramebufferVRAM, u64Now);
+                    if (pDisplay->mCrOglCallbacks.pfnHasData())
+                    {
+                        /* submit */
+
+                        VBOXHGCMSVCPARM parm;
+
+                        parm.type = VBOX_HGCM_SVC_PARM_PTR;
+                        parm.u.pointer.addr = &pDisplay->mCrOglScreenshotData;
+                        parm.u.pointer.size = sizeof (pDisplay->mCrOglScreenshotData);
+
+                        VMMDev *pVMMDev = pDisplay->mParent->getVMMDev();
+                        if (pVMMDev)
+                        {
+                            int rc = pVMMDev->hgcmHostFastCallAsync(pDisplay->mhCrOglSvc, SHCRGL_HOST_FN_TAKE_SCREENSHOT, &parm, displayVRecCompletion, pDisplay);
+                            if (RT_SUCCESS(rc))
+                                break;
+                            else
+                                AssertMsgFailed(("hgcmHostFastCallAsync failed %f\n", rc));
+                        }
+                        else
+                            AssertMsgFailed(("no VMMDev\n"));
+                    }
+
+                    /* no 3D data available, or error has occured,
+                     * go the straight way */
+                    ASMAtomicWriteU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_IDLE);
                 }
                 else
                 {
-                    rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
-                                              FramebufferPixelFormat_FOURCC_RGB,
-                                              pDrv->IConnector.cBits,
-                                              pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
-                                              pDrv->IConnector.cy, pDrv->IConnector.pu8Data, u64Now);
-                }
-                if (rc == VINF_TRY_AGAIN)
+                    /* record request is still in progress, don't do anything */
                     break;
+                }
             }
-        }
+# endif /* VBOX_WITH_HGCM && VBOX_WITH_CROGL */
+
+            uint64_t u64Now = RTTimeProgramMilliTS();
+            for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
+            {
+                if (!pDisplay->maVideoRecEnabled[uScreenId])
+                    continue;
+
+                DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
+
+                if (   !pFBInfo->pFramebuffer.isNull()
+                    && !pFBInfo->fDisabled
+                    && pFBInfo->u32ResizeStatus == ResizeStatus_Void)
+                {
+                    int rc;
+                    if (   pFBInfo->fVBVAEnabled
+                        && pFBInfo->pu8FramebufferVRAM)
+                    {
+                        rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
+                                                  FramebufferPixelFormat_FOURCC_RGB,
+                                                  pFBInfo->u16BitsPerPixel,
+                                                  pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
+                                                  pFBInfo->pu8FramebufferVRAM, u64Now);
+                    }
+                    else
+                    {
+                        rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
+                                                  FramebufferPixelFormat_FOURCC_RGB,
+                                                  pDrv->IConnector.cBits,
+                                                  pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
+                                                  pDrv->IConnector.cy, pDrv->IConnector.pu8Data, u64Now);
+                    }
+                    if (rc == VINF_TRY_AGAIN)
+                        break;
+                }
+            }
+        } while (0);
     }
-#endif
+#endif /* VBOX_WITH_VPX */
 
 #ifdef DEBUG_sunlover
     STAM_PROFILE_STOP(&g_StatDisplayRefresh, a);
@@ -3877,7 +4300,29 @@ void Display::handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Functio
     mpDrv->pVBVACallbacks->pfnCrHgsmiControlCompleteAsync(mpDrv->pVBVACallbacks, (PVBOXVDMACMD_CHROMIUM_CTL)pParam->u.pointer.addr, result);
 }
 
-void Display::handleCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
+int Display::handleCrCmdNotifyCmds()
+{
+    int rc = VERR_INVALID_FUNCTION;
+
+    if (mhCrOglSvc)
+    {
+        VBOXHGCMSVCPARM dummy;
+        VMMDev *pVMMDev = mParent->getVMMDev();
+        if (pVMMDev)
+        {
+            /* no completion callback is specified with this call,
+             * the CrOgl code will complete the CrHgsmi command once it processes it */
+            rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS, &dummy, NULL, NULL);
+            AssertRC(rc);
+        }
+        else
+            rc = VERR_INVALID_STATE;
+    }
+
+    return rc;
+}
+
+void Display::handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
 {
     int rc = VERR_INVALID_FUNCTION;
     VBOXHGCMSVCPARM parm;
@@ -3905,7 +4350,7 @@ void Display::handleCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBO
     handleCrHgsmiCommandCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CMD, &parm);
 }
 
-void Display::handleCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
+void Display::handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
 {
     int rc = VERR_INVALID_FUNCTION;
     VBOXHGCMSVCPARM parm;
@@ -3931,19 +4376,25 @@ void Display::handleCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBO
     handleCrHgsmiControlCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm);
 }
 
+DECLCALLBACK(int)  Display::displayCrCmdNotifyCmds(PPDMIDISPLAYCONNECTOR pInterface)
+{
+    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
+
+    return pDrv->pDisplay->handleCrCmdNotifyCmds();
+}
 
 DECLCALLBACK(void) Display::displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
 {
     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
 
-    pDrv->pDisplay->handleCrHgsmiCommandProcess(pInterface, pCmd, cbCmd);
+    pDrv->pDisplay->handleCrHgsmiCommandProcess(pCmd, cbCmd);
 }
 
 DECLCALLBACK(void) Display::displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
 {
     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
 
-    pDrv->pDisplay->handleCrHgsmiControlProcess(pInterface, pCmd, cbCmd);
+    pDrv->pDisplay->handleCrHgsmiControlProcess(pCmd, cbCmd);
 }
 
 DECLCALLBACK(void) Display::displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
@@ -3960,6 +4411,89 @@ DECLCALLBACK(void) Display::displayCrHgsmiControlCompletion(int32_t result, uint
 }
 #endif
 
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+DECLCALLBACK(void)  Display::displayCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+    Display *pDisplay = (Display *)pvContext;
+    pDisplay->handleCrAsyncCmdCompletion(result, u32Function, pParam);
+}
+
+
+void  Display::handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
+{
+    if (pParam->type == VBOX_HGCM_SVC_PARM_PTR && pParam->u.pointer.addr)
+        RTMemFree(pParam->u.pointer.addr);
+}
+
+bool  Display::handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp)
+{
+# if VBOX_WITH_VPX
+    return VideoRecIsReady(mpVideoRecCtx, uScreen, u64TimeStamp);
+# else
+    return false;
+# endif
+}
+
+void  Display::handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp)
+{
+}
+
+void  Display::handleCrVRecScreenshotPerform(uint32_t uScreen,
+                                             uint32_t x, uint32_t y, uint32_t uPixelFormat,
+                                             uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
+                                             uint32_t uGuestWidth, uint32_t uGuestHeight,
+                                             uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
+{
+    Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
+# if VBOX_WITH_VPX
+    int rc = VideoRecCopyToIntBuf(mpVideoRecCtx, uScreen, x, y,
+                                  uPixelFormat,
+                                  uBitsPerPixel, uBytesPerLine,
+                                  uGuestWidth, uGuestHeight,
+                                  pu8BufferAddress, u64TimeStamp);
+    Assert(rc == VINF_SUCCESS /* || rc == VERR_TRY_AGAIN || rc == VINF_TRY_AGAIN*/);
+# endif
+}
+
+void  Display::handleVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+    Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
+    ASMAtomicWriteU32(&mfCrOglVideoRecState, CRVREC_STATE_IDLE);
+}
+
+DECLCALLBACK(void) Display::displayCrVRecScreenshotPerform(void *pvCtx, uint32_t uScreen,
+                                                           uint32_t x, uint32_t y,
+                                                           uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
+                                                           uint32_t uGuestWidth, uint32_t uGuestHeight,
+                                                           uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
+{
+    Display *pDisplay = (Display *)pvCtx;
+    pDisplay->handleCrVRecScreenshotPerform(uScreen,
+                                            x, y, FramebufferPixelFormat_FOURCC_RGB, uBitsPerPixel,
+                                            uBytesPerLine, uGuestWidth, uGuestHeight,
+                                            pu8BufferAddress, u64TimeStamp);
+}
+
+DECLCALLBACK(bool) Display::displayCrVRecScreenshotBegin(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
+{
+    Display *pDisplay = (Display *)pvCtx;
+    return pDisplay->handleCrVRecScreenshotBegin(uScreen, u64TimeStamp);
+}
+
+DECLCALLBACK(void) Display::displayCrVRecScreenshotEnd(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
+{
+    Display *pDisplay = (Display *)pvCtx;
+    pDisplay->handleCrVRecScreenshotEnd(uScreen, u64TimeStamp);
+}
+
+DECLCALLBACK(void)  Display::displayVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+    Display *pDisplay = (Display *)pvContext;
+    pDisplay->handleVRecCompletion(result, u32Function, pParam, pvContext);
+}
+
+#endif
+
 
 #ifdef VBOX_WITH_HGSMI
 DECLCALLBACK(int) Display::displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags)
@@ -4288,6 +4822,8 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
 
     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
     {
+        pThis->notifyCroglResize(pView, pScreen, pvVRAM);
+
         pFBInfo->fDisabled = true;
         pFBInfo->flags = pScreen->u16Flags;
 
@@ -4311,17 +4847,6 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
      */
     bool fResize = pFBInfo->fDisabled || pFBInfo->pFramebuffer.isNull();
 
-    if (pFBInfo->fDisabled)
-    {
-        pFBInfo->fDisabled = false;
-        fireGuestMonitorChangedEvent(pThis->mParent->getEventSource(),
-                                     GuestMonitorChangedEventType_Enabled,
-                                     pScreen->u32ViewIndex,
-                                     pScreen->i32OriginX, pScreen->i32OriginY,
-                                     pScreen->u32Width, pScreen->u32Height);
-        /* Continue to update pFBInfo. */
-    }
-
     /* Check if this is a real resize or a notification about the screen origin.
      * The guest uses this VBVAResize call for both.
      */
@@ -4335,6 +4860,20 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
     bool fNewOrigin =    pFBInfo->xOrigin != pScreen->i32OriginX
                       || pFBInfo->yOrigin != pScreen->i32OriginY;
 
+    if (fNewOrigin || fResize)
+        pThis->notifyCroglResize(pView, pScreen, pvVRAM);
+
+    if (pFBInfo->fDisabled)
+    {
+        pFBInfo->fDisabled = false;
+        fireGuestMonitorChangedEvent(pThis->mParent->getEventSource(),
+                                     GuestMonitorChangedEventType_Enabled,
+                                     pScreen->u32ViewIndex,
+                                     pScreen->i32OriginX, pScreen->i32OriginY,
+                                     pScreen->u32Width, pScreen->u32Height);
+        /* Continue to update pFBInfo. */
+    }
+
     pFBInfo->u32Offset = pView->u32ViewOffset; /* Not used in HGSMI. */
     pFBInfo->u32MaxFramebufferSize = pView->u32MaxScreenSize; /* Not used in HGSMI. */
     pFBInfo->u32InformationSize = 0; /* Not used in HGSMI. */
@@ -4360,27 +4899,6 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
                                      0, 0);
     }
 
-#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
-    if (fNewOrigin && !fResize)
-    {
-        BOOL is3denabled;
-        pThis->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
-
-        if (is3denabled)
-        {
-            VBOXHGCMSVCPARM parm;
-
-            parm.type = VBOX_HGCM_SVC_PARM_32BIT;
-            parm.u.uint32 = pScreen->u32ViewIndex;
-
-            VMMDev *pVMMDev = pThis->mParent->getVMMDev();
-
-            if (pVMMDev)
-                pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
-        }
-    }
-#endif /* VBOX_WITH_CROGL */
-
     if (!fResize)
     {
         /* No parameters of the framebuffer have actually changed. */
@@ -4516,6 +5034,7 @@ DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint
     pThis->IConnector.pfnVHWACommandProcess    = Display::displayVHWACommandProcess;
 #endif
 #ifdef VBOX_WITH_CRHGSMI
+    pThis->IConnector.pfnCrCmdNotifyCmds =  Display::displayCrCmdNotifyCmds;
     pThis->IConnector.pfnCrHgsmiCommandProcess = Display::displayCrHgsmiCommandProcess;
     pThis->IConnector.pfnCrHgsmiControlProcess = Display::displayCrHgsmiControlProcess;
 #endif
diff --git a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
index 0d83eb4..52d0cf9 100644
--- a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
+++ b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
@@ -248,15 +248,15 @@ Utf8Str GuestDirectory::guestErrorToString(int guestRc)
 }
 
 /**
- * Called by IGuestSession right before this directory gets 
- * removed from the public directory list. 
+ * Called by IGuestSession right before this directory gets
+ * removed from the public directory list.
  */
 int GuestDirectory::onRemove(void)
 {
     LogFlowThisFuncEnter();
 
     int vrc = VINF_SUCCESS;
-         
+
     LogFlowFuncLeaveRC(vrc);
     return vrc;
 }
diff --git a/src/VBox/Main/src-client/USBDeviceImpl.cpp b/src/VBox/Main/src-client/USBDeviceImpl.cpp
index f5c3c0b..023b697 100644
--- a/src/VBox/Main/src-client/USBDeviceImpl.cpp
+++ b/src/VBox/Main/src-client/USBDeviceImpl.cpp
@@ -82,10 +82,10 @@ HRESULT OUSBDevice::init(IUSBDevice *aUSBDevice)
     hrc = aUSBDevice->COMGETTER(Port)(&unconst(mData.port));
     ComAssertComRCRet(hrc, hrc);
 
-    hrc = aUSBDevice->COMGETTER(Port)(&unconst(mData.version));
+    hrc = aUSBDevice->COMGETTER(Version)(&unconst(mData.version));
     ComAssertComRCRet(hrc, hrc);
 
-    hrc = aUSBDevice->COMGETTER(Port)(&unconst(mData.portVersion));
+    hrc = aUSBDevice->COMGETTER(PortVersion)(&unconst(mData.portVersion));
     ComAssertComRCRet(hrc, hrc);
 
     hrc = aUSBDevice->COMGETTER(Remote)(&unconst(mData.remote));
diff --git a/src/VBox/Main/src-client/VideoRec.cpp b/src/VBox/Main/src-client/VideoRec.cpp
index cf6b6e6..f47527e 100644
--- a/src/VBox/Main/src-client/VideoRec.cpp
+++ b/src/VBox/Main/src-client/VideoRec.cpp
@@ -602,6 +602,34 @@ bool VideoRecIsEnabled(PVIDEORECCONTEXT pCtx)
 }
 
 /**
+ * VideoRec utility function to check if recording engine is ready to accept a new frame
+ * for the given screen.
+ *
+ * @returns true if recording engine is ready
+ * @param   pCtx   Pointer to video recording context.
+ * @param   uScreen screen id.
+ * @param   u64TimeStamp current time stamp
+ */
+bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp)
+{
+    uint32_t enmState = ASMAtomicReadU32(&g_enmState);
+    if (enmState != VIDREC_IDLE)
+        return false;
+
+    PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
+    if (!pStrm->fEnabled)
+        return false;
+
+    if (u64TimeStamp < pStrm->u64LastTimeStamp + pStrm->uDelay)
+        return false;
+
+    if (ASMAtomicReadBool(&pStrm->fRgbFilled))
+        return false;
+
+    return true;
+}
+
+/**
  * VideoRec utility function to encode the source image and write the encoded
  * image to target file.
  *
diff --git a/src/VBox/Main/src-client/VideoRec.h b/src/VBox/Main/src-client/VideoRec.h
index bfd67ed..7d0d6fa 100644
--- a/src/VBox/Main/src-client/VideoRec.h
+++ b/src/VBox/Main/src-client/VideoRec.h
@@ -31,8 +31,9 @@ void VideoRecContextClose(PVIDEORECCONTEXT pCtx);
 bool VideoRecIsEnabled(PVIDEORECCONTEXT pCtx);
 int  VideoRecCopyToIntBuf(PVIDEORECCONTEXT pCtx, uint32_t uScreen,
                           uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBitsPerPixel,
-                          uint32_t uBytesPerLine, uint32_t uGuestHeight, uint32_t uGuestWidth,
+                          uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
                           uint8_t *pu8BufferAddress, uint64_t u64TimeStamp);
+bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp);
 
 #endif /* !____H_VIDEOREC */
 
diff --git a/src/VBox/Main/src-server/ApplianceImpl.cpp b/src/VBox/Main/src-server/ApplianceImpl.cpp
index 3f48b04..4c498fd 100644
--- a/src/VBox/Main/src-server/ApplianceImpl.cpp
+++ b/src/VBox/Main/src-server/ApplianceImpl.cpp
@@ -1,6 +1,5 @@
 /* $Id: ApplianceImpl.cpp $ */
 /** @file
- *
  * IAppliance and IVirtualSystem COM class implementations.
  */
 
@@ -1273,13 +1272,13 @@ STDMETHODIMP VirtualSystemDescription::COMGETTER(Count)(ULONG *aCount)
 STDMETHODIMP VirtualSystemDescription::GetDescription(ComSafeArrayOut(VirtualSystemDescriptionType_T, aTypes),
                                                       ComSafeArrayOut(BSTR, aRefs),
                                                       ComSafeArrayOut(BSTR, aOrigValues),
-                                                      ComSafeArrayOut(BSTR, aVboxValues),
+                                                      ComSafeArrayOut(BSTR, aVBoxValues),
                                                       ComSafeArrayOut(BSTR, aExtraConfigValues))
 {
     if (ComSafeArrayOutIsNull(aTypes) ||
         ComSafeArrayOutIsNull(aRefs) ||
         ComSafeArrayOutIsNull(aOrigValues) ||
-        ComSafeArrayOutIsNull(aVboxValues) ||
+        ComSafeArrayOutIsNull(aVBoxValues) ||
         ComSafeArrayOutIsNull(aExtraConfigValues))
         return E_POINTER;
 
@@ -1292,7 +1291,7 @@ STDMETHODIMP VirtualSystemDescription::GetDescription(ComSafeArrayOut(VirtualSys
     com::SafeArray<VirtualSystemDescriptionType_T> sfaTypes(c);
     com::SafeArray<BSTR> sfaRefs(c);
     com::SafeArray<BSTR> sfaOrigValues(c);
-    com::SafeArray<BSTR> sfaVboxValues(c);
+    com::SafeArray<BSTR> sfaVBoxValues(c);
     com::SafeArray<BSTR> sfaExtraConfigValues(c);
 
     list<VirtualSystemDescriptionEntry>::const_iterator it;
@@ -1311,8 +1310,8 @@ STDMETHODIMP VirtualSystemDescription::GetDescription(ComSafeArrayOut(VirtualSys
         bstr = vsde.strOvf;
         bstr.cloneTo(&sfaOrigValues[i]);
 
-        bstr = vsde.strVboxCurrent;
-        bstr.cloneTo(&sfaVboxValues[i]);
+        bstr = vsde.strVBoxCurrent;
+        bstr.cloneTo(&sfaVBoxValues[i]);
 
         bstr = vsde.strExtraConfigCurrent;
         bstr.cloneTo(&sfaExtraConfigValues[i]);
@@ -1321,7 +1320,7 @@ STDMETHODIMP VirtualSystemDescription::GetDescription(ComSafeArrayOut(VirtualSys
     sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
     sfaRefs.detachTo(ComSafeArrayOutArg(aRefs));
     sfaOrigValues.detachTo(ComSafeArrayOutArg(aOrigValues));
-    sfaVboxValues.detachTo(ComSafeArrayOutArg(aVboxValues));
+    sfaVBoxValues.detachTo(ComSafeArrayOutArg(aVBoxValues));
     sfaExtraConfigValues.detachTo(ComSafeArrayOutArg(aExtraConfigValues));
 
     return S_OK;
@@ -1335,13 +1334,13 @@ STDMETHODIMP VirtualSystemDescription::GetDescriptionByType(VirtualSystemDescrip
                                                             ComSafeArrayOut(VirtualSystemDescriptionType_T, aTypes),
                                                             ComSafeArrayOut(BSTR, aRefs),
                                                             ComSafeArrayOut(BSTR, aOrigValues),
-                                                            ComSafeArrayOut(BSTR, aVboxValues),
+                                                            ComSafeArrayOut(BSTR, aVBoxValues),
                                                             ComSafeArrayOut(BSTR, aExtraConfigValues))
 {
     if (ComSafeArrayOutIsNull(aTypes) ||
         ComSafeArrayOutIsNull(aRefs) ||
         ComSafeArrayOutIsNull(aOrigValues) ||
-        ComSafeArrayOutIsNull(aVboxValues) ||
+        ComSafeArrayOutIsNull(aVBoxValues) ||
         ComSafeArrayOutIsNull(aExtraConfigValues))
         return E_POINTER;
 
@@ -1355,7 +1354,7 @@ STDMETHODIMP VirtualSystemDescription::GetDescriptionByType(VirtualSystemDescrip
     com::SafeArray<VirtualSystemDescriptionType_T> sfaTypes(c);
     com::SafeArray<BSTR> sfaRefs(c);
     com::SafeArray<BSTR> sfaOrigValues(c);
-    com::SafeArray<BSTR> sfaVboxValues(c);
+    com::SafeArray<BSTR> sfaVBoxValues(c);
     com::SafeArray<BSTR> sfaExtraConfigValues(c);
 
     list<VirtualSystemDescriptionEntry*>::const_iterator it;
@@ -1374,8 +1373,8 @@ STDMETHODIMP VirtualSystemDescription::GetDescriptionByType(VirtualSystemDescrip
         bstr = vsde->strOvf;
         bstr.cloneTo(&sfaOrigValues[i]);
 
-        bstr = vsde->strVboxCurrent;
-        bstr.cloneTo(&sfaVboxValues[i]);
+        bstr = vsde->strVBoxCurrent;
+        bstr.cloneTo(&sfaVBoxValues[i]);
 
         bstr = vsde->strExtraConfigCurrent;
         bstr.cloneTo(&sfaExtraConfigValues[i]);
@@ -1384,7 +1383,7 @@ STDMETHODIMP VirtualSystemDescription::GetDescriptionByType(VirtualSystemDescrip
     sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
     sfaRefs.detachTo(ComSafeArrayOutArg(aRefs));
     sfaOrigValues.detachTo(ComSafeArrayOutArg(aOrigValues));
-    sfaVboxValues.detachTo(ComSafeArrayOutArg(aVboxValues));
+    sfaVBoxValues.detachTo(ComSafeArrayOutArg(aVBoxValues));
     sfaExtraConfigValues.detachTo(ComSafeArrayOutArg(aExtraConfigValues));
 
     return S_OK;
@@ -1422,7 +1421,7 @@ STDMETHODIMP VirtualSystemDescription::GetValuesByType(VirtualSystemDescriptionT
         {
             case VirtualSystemDescriptionValueType_Reference: bstr = vsde->strRef; break;
             case VirtualSystemDescriptionValueType_Original: bstr = vsde->strOvf; break;
-            case VirtualSystemDescriptionValueType_Auto: bstr = vsde->strVboxCurrent; break;
+            case VirtualSystemDescriptionValueType_Auto: bstr = vsde->strVBoxCurrent; break;
             case VirtualSystemDescriptionValueType_ExtraConfig: bstr = vsde->strExtraConfigCurrent; break;
         }
 
@@ -1439,7 +1438,7 @@ STDMETHODIMP VirtualSystemDescription::GetValuesByType(VirtualSystemDescriptionT
  * @return
  */
 STDMETHODIMP VirtualSystemDescription::SetFinalValues(ComSafeArrayIn(BOOL, aEnabled),
-                                                      ComSafeArrayIn(IN_BSTR, argVboxValues),
+                                                      ComSafeArrayIn(IN_BSTR, argVBoxValues),
                                                       ComSafeArrayIn(IN_BSTR, argExtraConfigValues))
 {
 #ifndef RT_OS_WINDOWS
@@ -1447,7 +1446,7 @@ STDMETHODIMP VirtualSystemDescription::SetFinalValues(ComSafeArrayIn(BOOL, aEnab
 #endif /* RT_OS_WINDOWS */
 
     CheckComArgSafeArrayNotNull(aEnabled);
-    CheckComArgSafeArrayNotNull(argVboxValues);
+    CheckComArgSafeArrayNotNull(argVBoxValues);
     CheckComArgSafeArrayNotNull(argExtraConfigValues);
 
     AutoCaller autoCaller(this);
@@ -1456,11 +1455,11 @@ STDMETHODIMP VirtualSystemDescription::SetFinalValues(ComSafeArrayIn(BOOL, aEnab
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     com::SafeArray<BOOL> sfaEnabled(ComSafeArrayInArg(aEnabled));
-    com::SafeArray<IN_BSTR> sfaVboxValues(ComSafeArrayInArg(argVboxValues));
+    com::SafeArray<IN_BSTR> sfaVBoxValues(ComSafeArrayInArg(argVBoxValues));
     com::SafeArray<IN_BSTR> sfaExtraConfigValues(ComSafeArrayInArg(argExtraConfigValues));
 
     if (    (sfaEnabled.size() != m->llDescriptions.size())
-         || (sfaVboxValues.size() != m->llDescriptions.size())
+         || (sfaVBoxValues.size() != m->llDescriptions.size())
          || (sfaExtraConfigValues.size() != m->llDescriptions.size())
        )
         return E_INVALIDARG;
@@ -1475,7 +1474,7 @@ STDMETHODIMP VirtualSystemDescription::SetFinalValues(ComSafeArrayIn(BOOL, aEnab
 
         if (sfaEnabled[i])
         {
-            vsde.strVboxCurrent = sfaVboxValues[i];
+            vsde.strVBoxCurrent = sfaVBoxValues[i];
             vsde.strExtraConfigCurrent = sfaExtraConfigValues[i];
         }
         else
@@ -1490,7 +1489,7 @@ STDMETHODIMP VirtualSystemDescription::SetFinalValues(ComSafeArrayIn(BOOL, aEnab
  * @return
  */
 STDMETHODIMP VirtualSystemDescription::AddDescription(VirtualSystemDescriptionType_T aType,
-                                                      IN_BSTR aVboxValue,
+                                                      IN_BSTR aVBoxValue,
                                                       IN_BSTR aExtraConfigValue)
 {
     AutoCaller autoCaller(this);
@@ -1498,7 +1497,7 @@ STDMETHODIMP VirtualSystemDescription::AddDescription(VirtualSystemDescriptionTy
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    addEntry(aType, "", aVboxValue, aVboxValue, 0, aExtraConfigValue);
+    addEntry(aType, "", aVBoxValue, aVBoxValue, 0, aExtraConfigValue);
 
     return S_OK;
 }
@@ -1515,7 +1514,7 @@ STDMETHODIMP VirtualSystemDescription::AddDescription(VirtualSystemDescriptionTy
 void VirtualSystemDescription::addEntry(VirtualSystemDescriptionType_T aType,
                                         const Utf8Str &strRef,
                                         const Utf8Str &aOvfValue,
-                                        const Utf8Str &aVboxValue,
+                                        const Utf8Str &aVBoxValue,
                                         uint32_t ulSizeMB,
                                         const Utf8Str &strExtraConfig /*= ""*/)
 {
@@ -1524,9 +1523,9 @@ void VirtualSystemDescription::addEntry(VirtualSystemDescriptionType_T aType,
     vsde.type = aType;
     vsde.strRef = strRef;
     vsde.strOvf = aOvfValue;
-    vsde.strVboxSuggested           // remember original value
-        = vsde.strVboxCurrent       // and set current value which can be overridden by setFinalValues()
-        = aVboxValue;
+    vsde.strVBoxSuggested           // remember original value
+        = vsde.strVBoxCurrent       // and set current value which can be overridden by setFinalValues()
+        = aVBoxValue;
     vsde.strExtraConfigSuggested
         = vsde.strExtraConfigCurrent
         = strExtraConfig;
@@ -1621,7 +1620,7 @@ const VirtualSystemDescriptionEntry* VirtualSystemDescription::findControllerFro
  * @param elmMachine <vbox:Machine> element with attributes and subelements from some
  *                  DOM tree.
  */
-void VirtualSystemDescription::importVboxMachineXML(const xml::ElementNode &elmMachine)
+void VirtualSystemDescription::importVBoxMachineXML(const xml::ElementNode &elmMachine)
 {
     settings::MachineConfigFile *pConfig = NULL;
 
@@ -1643,7 +1642,7 @@ void VirtualSystemDescription::importVboxMachineXML(const xml::ElementNode &elmM
 }
 
 /**
- * Returns the machine config created by importVboxMachineXML() or NULL if there's none.
+ * Returns the machine config created by importVBoxMachineXML() or NULL if there's none.
  * @return
  */
 const settings::MachineConfigFile* VirtualSystemDescription::getMachineConfig() const
diff --git a/src/VBox/Main/src-server/ApplianceImplExport.cpp b/src/VBox/Main/src-server/ApplianceImplExport.cpp
index a1fa7da..5980e1c 100644
--- a/src/VBox/Main/src-server/ApplianceImplExport.cpp
+++ b/src/VBox/Main/src-server/ApplianceImplExport.cpp
@@ -1,11 +1,10 @@
 /* $Id: ApplianceImplExport.cpp $ */
 /** @file
- *
  * IAppliance and IVirtualSystem COM class implementations.
  */
 
 /*
- * Copyright (C) 2008-2013 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -211,41 +210,41 @@ STDMETHODIMP Machine::ExportTo(IAppliance *aAppliance, IN_BSTR location, IVirtua
 //     <const name="HardDiskControllerIDE" value="6" />
         if (!pIDEController.isNull())
         {
-            Utf8Str strVbox;
+            Utf8Str strVBox;
             StorageControllerType_T ctlr;
             rc = pIDEController->COMGETTER(ControllerType)(&ctlr);
             if (FAILED(rc)) throw rc;
             switch(ctlr)
             {
-                case StorageControllerType_PIIX3: strVbox = "PIIX3"; break;
-                case StorageControllerType_PIIX4: strVbox = "PIIX4"; break;
-                case StorageControllerType_ICH6: strVbox = "ICH6"; break;
+                case StorageControllerType_PIIX3: strVBox = "PIIX3"; break;
+                case StorageControllerType_PIIX4: strVBox = "PIIX4"; break;
+                case StorageControllerType_ICH6: strVBox = "ICH6"; break;
             }
 
-            if (strVbox.length())
+            if (strVBox.length())
             {
                 lIDEControllerPrimaryIndex = (int32_t)pNewDesc->m->llDescriptions.size();
                 pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerIDE,
                                    Utf8StrFmt("%d", lIDEControllerPrimaryIndex),        // strRef
-                                   strVbox,     // aOvfValue
-                                   strVbox);    // aVboxValue
+                                   strVBox,     // aOvfValue
+                                   strVBox);    // aVBoxValue
                 lIDEControllerSecondaryIndex = lIDEControllerPrimaryIndex + 1;
                 pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerIDE,
                                    Utf8StrFmt("%d", lIDEControllerSecondaryIndex),
-                                   strVbox,
-                                   strVbox);
+                                   strVBox,
+                                   strVBox);
             }
         }
 
 //     <const name="HardDiskControllerSATA" value="7" />
         if (!pSATAController.isNull())
         {
-            Utf8Str strVbox = "AHCI";
+            Utf8Str strVBox = "AHCI";
             lSATAControllerIndex = (int32_t)pNewDesc->m->llDescriptions.size();
             pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerSATA,
                                Utf8StrFmt("%d", lSATAControllerIndex),
-                               strVbox,
-                               strVbox);
+                               strVBox,
+                               strVBox);
         }
 
 //     <const name="HardDiskControllerSCSI" value="8" />
@@ -255,17 +254,17 @@ STDMETHODIMP Machine::ExportTo(IAppliance *aAppliance, IN_BSTR location, IVirtua
             rc = pSCSIController->COMGETTER(ControllerType)(&ctlr);
             if (SUCCEEDED(rc))
             {
-                Utf8Str strVbox = "LsiLogic";       // the default in VBox
+                Utf8Str strVBox = "LsiLogic";       // the default in VBox
                 switch(ctlr)
                 {
-                    case StorageControllerType_LsiLogic: strVbox = "LsiLogic"; break;
-                    case StorageControllerType_BusLogic: strVbox = "BusLogic"; break;
+                    case StorageControllerType_LsiLogic: strVBox = "LsiLogic"; break;
+                    case StorageControllerType_BusLogic: strVBox = "BusLogic"; break;
                 }
                 lSCSIControllerIndex = (int32_t)pNewDesc->m->llDescriptions.size();
                 pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerSCSI,
                                    Utf8StrFmt("%d", lSCSIControllerIndex),
-                                   strVbox,
-                                   strVbox);
+                                   strVBox,
+                                   strVBox);
             }
             else
                 throw rc;
@@ -275,12 +274,12 @@ STDMETHODIMP Machine::ExportTo(IAppliance *aAppliance, IN_BSTR location, IVirtua
         {
             // VirtualBox considers the SAS controller a class of its own but in OVF
             // it should be a SCSI controller
-            Utf8Str strVbox = "LsiLogicSas";
+            Utf8Str strVBox = "LsiLogicSas";
             lSCSIControllerIndex = (int32_t)pNewDesc->m->llDescriptions.size();
             pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerSAS,
                                Utf8StrFmt("%d", lSCSIControllerIndex),
-                               strVbox,
-                               strVbox);
+                               strVBox,
+                               strVBox);
         }
 
 //     <const name="HardDiskImage" value="9" />
@@ -883,7 +882,7 @@ void Appliance::buildXML(AutoWriteLockBase& writeLock,
         const VirtualSystemDescriptionEntry *pDiskEntry = itS->second;
 
         // source path: where the VBox image is
-        const Utf8Str &strSrcFilePath = pDiskEntry->strVboxCurrent;
+        const Utf8Str &strSrcFilePath = pDiskEntry->strVBoxCurrent;
         Bstr bstrSrcFilePath(strSrcFilePath);
 
         //skip empty Medium. There are no information to add into section <References> or <DiskSection>
@@ -1047,7 +1046,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
     std::list<VirtualSystemDescriptionEntry*> llName = vsdescThis->findByType(VirtualSystemDescriptionType_Name);
     if (!llName.size())
         throw setError(VBOX_E_NOT_SUPPORTED, tr("Missing VM name"));
-    Utf8Str &strVMName = llName.back()->strVboxCurrent;
+    Utf8Str &strVMName = llName.back()->strVBoxCurrent;
     pelmVirtualSystem->setAttribute("ovf:id", strVMName);
 
     // product info
@@ -1056,11 +1055,11 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
     std::list<VirtualSystemDescriptionEntry*> llVendor = vsdescThis->findByType(VirtualSystemDescriptionType_Vendor);
     std::list<VirtualSystemDescriptionEntry*> llVendorUrl = vsdescThis->findByType(VirtualSystemDescriptionType_VendorUrl);
     std::list<VirtualSystemDescriptionEntry*> llVersion = vsdescThis->findByType(VirtualSystemDescriptionType_Version);
-    bool fProduct = llProduct.size() && !llProduct.back()->strVboxCurrent.isEmpty();
-    bool fProductUrl = llProductUrl.size() && !llProductUrl.back()->strVboxCurrent.isEmpty();
-    bool fVendor = llVendor.size() && !llVendor.back()->strVboxCurrent.isEmpty();
-    bool fVendorUrl = llVendorUrl.size() && !llVendorUrl.back()->strVboxCurrent.isEmpty();
-    bool fVersion = llVersion.size() && !llVersion.back()->strVboxCurrent.isEmpty();
+    bool fProduct = llProduct.size() && !llProduct.back()->strVBoxCurrent.isEmpty();
+    bool fProductUrl = llProductUrl.size() && !llProductUrl.back()->strVBoxCurrent.isEmpty();
+    bool fVendor = llVendor.size() && !llVendor.back()->strVBoxCurrent.isEmpty();
+    bool fVendorUrl = llVendorUrl.size() && !llVendorUrl.back()->strVBoxCurrent.isEmpty();
+    bool fVersion = llVersion.size() && !llVersion.back()->strVBoxCurrent.isEmpty();
     if (fProduct ||
         fProductUrl ||
         fVersion ||
@@ -1087,21 +1086,21 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
 
         pelmAnnotationSection->createChild("Info")->addContent("Meta-information about the installed software");
         if (fProduct)
-            pelmAnnotationSection->createChild("Product")->addContent(llProduct.back()->strVboxCurrent);
+            pelmAnnotationSection->createChild("Product")->addContent(llProduct.back()->strVBoxCurrent);
         if (fVendor)
-            pelmAnnotationSection->createChild("Vendor")->addContent(llVendor.back()->strVboxCurrent);
+            pelmAnnotationSection->createChild("Vendor")->addContent(llVendor.back()->strVBoxCurrent);
         if (fVersion)
-            pelmAnnotationSection->createChild("Version")->addContent(llVersion.back()->strVboxCurrent);
+            pelmAnnotationSection->createChild("Version")->addContent(llVersion.back()->strVBoxCurrent);
         if (fProductUrl)
-            pelmAnnotationSection->createChild("ProductUrl")->addContent(llProductUrl.back()->strVboxCurrent);
+            pelmAnnotationSection->createChild("ProductUrl")->addContent(llProductUrl.back()->strVBoxCurrent);
         if (fVendorUrl)
-            pelmAnnotationSection->createChild("VendorUrl")->addContent(llVendorUrl.back()->strVboxCurrent);
+            pelmAnnotationSection->createChild("VendorUrl")->addContent(llVendorUrl.back()->strVBoxCurrent);
     }
 
     // description
     std::list<VirtualSystemDescriptionEntry*> llDescription = vsdescThis->findByType(VirtualSystemDescriptionType_Description);
     if (llDescription.size() &&
-        !llDescription.back()->strVboxCurrent.isEmpty())
+        !llDescription.back()->strVBoxCurrent.isEmpty())
     {
         /*  <Section ovf:required="false" xsi:type="ovf:AnnotationSection_Type">
                 <Info>A human-readable annotation</Info>
@@ -1118,13 +1117,13 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
             pelmAnnotationSection = pelmVirtualSystem->createChild("AnnotationSection");
 
         pelmAnnotationSection->createChild("Info")->addContent("A human-readable annotation");
-        pelmAnnotationSection->createChild("Annotation")->addContent(llDescription.back()->strVboxCurrent);
+        pelmAnnotationSection->createChild("Annotation")->addContent(llDescription.back()->strVBoxCurrent);
     }
 
     // license
     std::list<VirtualSystemDescriptionEntry*> llLicense = vsdescThis->findByType(VirtualSystemDescriptionType_License);
     if (llLicense.size() &&
-        !llLicense.back()->strVboxCurrent.isEmpty())
+        !llLicense.back()->strVBoxCurrent.isEmpty())
     {
         /* <EulaSection>
             <Info ovf:msgid="6">License agreement for the Virtual System.</Info>
@@ -1140,7 +1139,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
             pelmEulaSection = pelmVirtualSystem->createChild("EulaSection");
 
         pelmEulaSection->createChild("Info")->addContent("License agreement for the virtual system");
-        pelmEulaSection->createChild("License")->addContent(llLicense.back()->strVboxCurrent);
+        pelmEulaSection->createChild("License")->addContent(llLicense.back()->strVBoxCurrent);
     }
 
     // operating system
@@ -1169,7 +1168,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
     // add the VirtualBox ostype in a custom tag in a different namespace
     xml::ElementNode *pelmVBoxOSType = pelmOperatingSystemSection->createChild("vbox:OSType");
     pelmVBoxOSType->setAttribute("ovf:required", "false");
-    pelmVBoxOSType->addContent(pvsdeOS->strVboxCurrent);
+    pelmVBoxOSType->addContent(pvsdeOS->strVBoxCurrent);
 
     // <VirtualHardwareSection ovf:id="hw1" ovf:transport="iso">
     xml::ElementNode *pelmVirtualHardwareSection;
@@ -1239,7 +1238,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
         {
             const VirtualSystemDescriptionEntry &desc = *itD;
 
-            LogFlowFunc(("Loop %u: handling description entry ulIndex=%u, type=%s, strRef=%s, strOvf=%s, strVbox=%s, strExtraConfig=%s\n",
+            LogFlowFunc(("Loop %u: handling description entry ulIndex=%u, type=%s, strRef=%s, strOvf=%s, strVBox=%s, strExtraConfig=%s\n",
                          uLoop,
                          desc.ulIndex,
                          (  desc.type == VirtualSystemDescriptionType_HardDiskControllerIDE ? "HardDiskControllerIDE"
@@ -1250,7 +1249,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                           : Utf8StrFmt("%d", desc.type).c_str()),
                          desc.strRef.c_str(),
                          desc.strOvf.c_str(),
-                         desc.strVboxCurrent.c_str(),
+                         desc.strVBoxCurrent.c_str(),
                          desc.strExtraConfigCurrent.c_str()));
 
             ovf::ResourceType_T type = (ovf::ResourceType_T)0;      // if this becomes != 0 then we do stuff
@@ -1293,7 +1292,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                     {
                         strDescription = "Number of virtual CPUs";
                         type = ovf::ResourceType_Processor; // 3
-                        desc.strVboxCurrent.toInt(uTemp);
+                        desc.strVBoxCurrent.toInt(uTemp);
                         lVirtualQuantity = (int32_t)uTemp;
                         strCaption = Utf8StrFmt("%d virtual CPU", lVirtualQuantity);     // without this ovftool won't eat the item
                     }
@@ -1313,7 +1312,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                     {
                         strDescription = "Memory Size";
                         type = ovf::ResourceType_Memory; // 4
-                        desc.strVboxCurrent.toInt(uTemp);
+                        desc.strVBoxCurrent.toInt(uTemp);
                         lVirtualQuantity = (int32_t)(uTemp / _1M);
                         strAllocationUnits = "MegaBytes";
                         strCaption = Utf8StrFmt("%d MB of memory", lVirtualQuantity);     // without this ovftool won't eat the item
@@ -1333,7 +1332,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                     {
                         strDescription = "IDE Controller";
                         type = ovf::ResourceType_IDEController; // 5
-                        strResourceSubType = desc.strVboxCurrent;
+                        strResourceSubType = desc.strVBoxCurrent;
 
                         if (!lIDEPrimaryControllerIndex)
                         {
@@ -1379,13 +1378,13 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                         lAddress = 0;
                         lBusNumber = 0;
 
-                        if (    desc.strVboxCurrent.isEmpty()      // AHCI is the default in VirtualBox
-                             || (!desc.strVboxCurrent.compare("ahci", Utf8Str::CaseInsensitive))
+                        if (    desc.strVBoxCurrent.isEmpty()      // AHCI is the default in VirtualBox
+                             || (!desc.strVBoxCurrent.compare("ahci", Utf8Str::CaseInsensitive))
                            )
                             strResourceSubType = "AHCI";
                         else
                             throw setError(VBOX_E_NOT_SUPPORTED,
-                                            tr("Invalid config string \"%s\" in SATA controller"), desc.strVboxCurrent.c_str());
+                                            tr("Invalid config string \"%s\" in SATA controller"), desc.strVBoxCurrent.c_str());
 
                         // remember this ID
                         idSATAController = ulInstanceID;
@@ -1415,17 +1414,17 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                         lAddress = 0;
                         lBusNumber = 0;
 
-                        if (    desc.strVboxCurrent.isEmpty()      // LsiLogic is the default in VirtualBox
-                             || (!desc.strVboxCurrent.compare("lsilogic", Utf8Str::CaseInsensitive))
+                        if (    desc.strVBoxCurrent.isEmpty()      // LsiLogic is the default in VirtualBox
+                             || (!desc.strVBoxCurrent.compare("lsilogic", Utf8Str::CaseInsensitive))
                             )
                             strResourceSubType = "lsilogic";
-                        else if (!desc.strVboxCurrent.compare("buslogic", Utf8Str::CaseInsensitive))
+                        else if (!desc.strVBoxCurrent.compare("buslogic", Utf8Str::CaseInsensitive))
                             strResourceSubType = "buslogic";
-                        else if (!desc.strVboxCurrent.compare("lsilogicsas", Utf8Str::CaseInsensitive))
+                        else if (!desc.strVBoxCurrent.compare("lsilogicsas", Utf8Str::CaseInsensitive))
                             strResourceSubType = "lsilogicsas";
                         else
                             throw setError(VBOX_E_NOT_SUPPORTED,
-                                            tr("Invalid config string \"%s\" in SCSI/SAS controller"), desc.strVboxCurrent.c_str());
+                                            tr("Invalid config string \"%s\" in SCSI/SAS controller"), desc.strVBoxCurrent.c_str());
 
                         // remember this ID
                         idSCSIController = ulInstanceID;
@@ -1517,7 +1516,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                         lAutomaticAllocation = 1;
 
                         //skip empty Medium. There are no information to add into section <References> or <DiskSection>
-                        if (desc.strVboxCurrent.isNotEmpty())
+                        if (desc.strVBoxCurrent.isNotEmpty())
                         {
                             // the following references the "<Disks>" XML block
                             strHostResource = Utf8StrFmt("/disk/%s", strDiskID.c_str());
@@ -1575,7 +1574,7 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
                             * To be compatible with vmware & others we set
                             * PCNet32 for our PCNet types & E1000 for the
                             * E1000 cards. */
-                        switch (desc.strVboxCurrent.toInt32())
+                        switch (desc.strVBoxCurrent.toInt32())
                         {
                             case NetworkAdapterType_Am79C970A:
                             case NetworkAdapterType_Am79C973: strResourceSubType = "PCNet32"; break;
@@ -1827,9 +1826,24 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
         // fill the machine config
         vsdescThis->m->pMachine->copyMachineDataToSettings(*pConfig);
 
+        // Apply export tweaks to machine settings
+        bool fStripAllMACs = m->optListExport.contains(ExportOptions_StripAllMACs);
+        bool fStripAllNonNATMACs = m->optListExport.contains(ExportOptions_StripAllNonNATMACs);
+        if (fStripAllMACs || fStripAllNonNATMACs)
+        {
+            for (settings::NetworkAdaptersList::iterator it = pConfig->hardwareMachine.llNetworkAdapters.begin();
+                 it != pConfig->hardwareMachine.llNetworkAdapters.end();
+                 ++it)
+            {
+                settings::NetworkAdapter &nic = *it;
+                if (fStripAllMACs || (fStripAllNonNATMACs && nic.mode != NetworkAttachmentType_NAT))
+                    nic.strMACAddress.setNull();
+            }
+        }
+
         // write the machine config to the vbox:Machine element
         pConfig->buildMachineXML(*pelmVBoxMachine,
-                                   settings::MachineConfigFile::BuildMachineXML_WriteVboxVersionAttribute
+                                   settings::MachineConfigFile::BuildMachineXML_WriteVBoxVersionAttribute
                                  /*| settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia*/
                                  | settings::MachineConfigFile::BuildMachineXML_SuppressSavedState,
                                         // but not BuildMachineXML_IncludeSnapshots nor BuildMachineXML_MediaRegistry
@@ -2074,7 +2088,7 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
             const VirtualSystemDescriptionEntry *pDiskEntry = itS->second;
 
             // source path: where the VBox image is
-            const Utf8Str &strSrcFilePath = pDiskEntry->strVboxCurrent;
+            const Utf8Str &strSrcFilePath = pDiskEntry->strVBoxCurrent;
 
             //skip empty Medium. In common, It's may be empty CD/DVD
             if (strSrcFilePath.isEmpty())
@@ -2177,7 +2191,7 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
 
                         void *pvTmpBuf = 0;
                         size_t cbTmpSize = _1M;
-                        size_t cbAllWritten = 0;
+                        uint64_t cbAllWritten = 0;
                         uint64_t cbFile = 0;
                         size_t cbSize = 0;
 
diff --git a/src/VBox/Main/src-server/ApplianceImplImport.cpp b/src/VBox/Main/src-server/ApplianceImplImport.cpp
index d757080..1eada73 100644
--- a/src/VBox/Main/src-server/ApplianceImplImport.cpp
+++ b/src/VBox/Main/src-server/ApplianceImplImport.cpp
@@ -1,6 +1,5 @@
 /* $Id: ApplianceImplImport.cpp $ */
 /** @file
- *
  * IAppliance and IVirtualSystem COM class implementations.
  */
 
@@ -163,21 +162,21 @@ STDMETHODIMP Appliance::Interpret()
 
             // if the virtual system in OVF had a <vbox:Machine> element, have the
             // VirtualBox settings code parse that XML now
-            if (vsysThis.pelmVboxMachine)
-                pNewDesc->importVboxMachineXML(*vsysThis.pelmVboxMachine);
+            if (vsysThis.pelmVBoxMachine)
+                pNewDesc->importVBoxMachineXML(*vsysThis.pelmVBoxMachine);
 
             // Guest OS type
             // This is taken from one of three places, in this order:
             Utf8Str strOsTypeVBox;
             Utf8StrFmt strCIMOSType("%RU32", (uint32_t)vsysThis.cimos);
             // 1) If there is a <vbox:Machine>, then use the type from there.
-            if (   vsysThis.pelmVboxMachine
+            if (   vsysThis.pelmVBoxMachine
                 && pNewDesc->m->pConfig->machineUserData.strOsType.isNotEmpty()
                )
                 strOsTypeVBox = pNewDesc->m->pConfig->machineUserData.strOsType;
             // 2) Otherwise, if there is OperatingSystemSection/vbox:OSType, use that one.
-            else if (vsysThis.strTypeVbox.isNotEmpty())      // OVFReader has found vbox:OSType
-                strOsTypeVBox = vsysThis.strTypeVbox;
+            else if (vsysThis.strTypeVBox.isNotEmpty())      // OVFReader has found vbox:OSType
+                strOsTypeVBox = vsysThis.strTypeVBox;
             // 3) Otherwise, make a best guess what the vbox type is from the OVF (CIM) OS type.
             else
                 convertCIMOSType2VBoxOSType(strOsTypeVBox, vsysThis.cimos, vsysThis.strCimosDesc);
@@ -189,7 +188,7 @@ STDMETHODIMP Appliance::Interpret()
             /* VM name */
             Utf8Str nameVBox;
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
-            if (   vsysThis.pelmVboxMachine
+            if (   vsysThis.pelmVBoxMachine
                 && pNewDesc->m->pConfig->machineUserData.strName.isNotEmpty())
                 nameVBox = pNewDesc->m->pConfig->machineUserData.strName;
             else
@@ -272,7 +271,7 @@ STDMETHODIMP Appliance::Interpret()
             /* CPU count */
             ULONG cpuCountVBox;
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
-            if (   vsysThis.pelmVboxMachine
+            if (   vsysThis.pelmVBoxMachine
                 && pNewDesc->m->pConfig->hardwareMachine.cCPUs)
                 cpuCountVBox = pNewDesc->m->pConfig->hardwareMachine.cCPUs;
             else
@@ -295,7 +294,7 @@ STDMETHODIMP Appliance::Interpret()
             /* RAM */
             uint64_t ullMemSizeVBox;
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
-            if (   vsysThis.pelmVboxMachine
+            if (   vsysThis.pelmVBoxMachine
                 && pNewDesc->m->pConfig->hardwareMachine.ulMemorySizeMB)
                 ullMemSizeVBox = pNewDesc->m->pConfig->hardwareMachine.ulMemorySizeMB;
             else
@@ -330,7 +329,7 @@ STDMETHODIMP Appliance::Interpret()
             Utf8Str strSoundCard;
             Utf8Str strSoundCardOrig;
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
-            if (   vsysThis.pelmVboxMachine
+            if (   vsysThis.pelmVBoxMachine
                 && pNewDesc->m->pConfig->hardwareMachine.audioAdapter.fEnabled)
             {
                 strSoundCard = Utf8StrFmt("%RU32",
@@ -352,7 +351,7 @@ STDMETHODIMP Appliance::Interpret()
 #ifdef VBOX_WITH_USB
             /* USB Controller */
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
-            if (   (   vsysThis.pelmVboxMachine
+            if (   (   vsysThis.pelmVBoxMachine
                     && pNewDesc->m->pConfig->hardwareMachine.usbSettings.llUSBControllers.size() > 0)
                 || vsysThis.fHasUsbController)
                 pNewDesc->addEntry(VirtualSystemDescriptionType_USBController, "", "", "");
@@ -360,7 +359,7 @@ STDMETHODIMP Appliance::Interpret()
 
             /* Network Controller */
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
-            if (vsysThis.pelmVboxMachine)
+            if (vsysThis.pelmVBoxMachine)
             {
                 uint32_t maxNetworkAdapters = Global::getMaxNetworkAdapters(pNewDesc->m->pConfig->hardwareMachine.chipsetType);
 
@@ -472,7 +471,7 @@ STDMETHODIMP Appliance::Interpret()
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
             bool fFloppy = false;
             bool fDVD = false;
-            if (vsysThis.pelmVboxMachine)
+            if (vsysThis.pelmVBoxMachine)
             {
                 settings::StorageControllersList &llControllers = pNewDesc->m->pConfig->storageMachine.llStorageControllers;
                 settings::StorageControllersList::iterator it3;
@@ -536,7 +535,7 @@ STDMETHODIMP Appliance::Interpret()
                             pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerIDE,
                                                strControllerID,         // strRef
                                                hdc.strControllerType,   // aOvfValue
-                                               strType);                // aVboxValue
+                                               strType);                // aVBoxValue
                         }
                         else
                             /* Warn only once */
@@ -1424,9 +1423,12 @@ HRESULT Appliance::importImpl(const LocationInfo &locInfo,
 }
 
 /**
- * Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport()
- * and therefore runs on the OVF import worker thread. This creates one or more new machines according to the
- * VirtualSystemScription instances created by Appliance::Interpret().
+ * Actual worker code for importing OVF data into VirtualBox.
+ *
+ * This is called from Appliance::taskThreadImportOrExport() and therefore runs
+ * on the OVF import worker thread. This creates one or more new machines
+ * according to the VirtualSystemScription instances created by
+ * Appliance::Interpret().
  *
  * This runs in three contexts:
  *
@@ -1438,8 +1440,8 @@ HRESULT Appliance::importImpl(const LocationInfo &locInfo,
  * 3) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which
  *    called Appliance::importS3(), which called Appliance::importImpl(), which then called this again.
  *
- * @param pTask
- * @return
+ * @param   pTask       The OVF task data.
+ * @return  COM status code.
  */
 HRESULT Appliance::importFS(TaskOVF *pTask)
 {
@@ -1475,6 +1477,7 @@ HRESULT Appliance::importFS(TaskOVF *pTask)
         /* With _whatever_ error we've had, do a complete roll-back of
          * machines and disks we've created */
         writeLock.release();
+        ErrorInfoKeeper eik;
         for (list<Guid>::iterator itID = m->llGuidsMachinesCreated.begin();
              itID != m->llGuidsMachinesCreated.end();
              ++itID)
@@ -2541,6 +2544,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                                      PVDINTERFACEIO pCallbacks,
                                      PSHASTORAGE pStorage)
 {
+    LogFlowFuncEnter();
     HRESULT rc;
 
     // Get the instance of IGuestOSType which matches our string guest OS type so we
@@ -2664,7 +2668,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
         {
             const VirtualSystemDescriptionEntry* pvsys = *nwIt;
 
-            const Utf8Str &nwTypeVBox = pvsys->strVboxCurrent;
+            const Utf8Str &nwTypeVBox = pvsys->strVBoxCurrent;
             uint32_t tt1 = RTStrToUInt32(nwTypeVBox.c_str());
             ComPtr<INetworkAdapter> pNetworkAdapter;
             rc = pNewMachine->GetNetworkAdapter((ULONG)a, pNetworkAdapter.asOutParam());
@@ -2797,7 +2801,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
         rc = pNewMachine->AddStorageController(Bstr("IDE Controller").raw(), StorageBus_IDE, pController.asOutParam());
         if (FAILED(rc)) throw rc;
 
-        const char *pcszIDEType = vsdeHDCIDE.front()->strVboxCurrent.c_str();
+        const char *pcszIDEType = vsdeHDCIDE.front()->strVBoxCurrent.c_str();
         if (!strcmp(pcszIDEType, "PIIX3"))
             rc = pController->COMSETTER(ControllerType)(StorageControllerType_PIIX3);
         else if (!strcmp(pcszIDEType, "PIIX4"))
@@ -2819,7 +2823,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
     if (vsdeHDCSATA.size() > 0)
     {
         ComPtr<IStorageController> pController;
-        const Utf8Str &hdcVBox = vsdeHDCSATA.front()->strVboxCurrent;
+        const Utf8Str &hdcVBox = vsdeHDCSATA.front()->strVBoxCurrent;
         if (hdcVBox == "AHCI")
         {
             rc = pNewMachine->AddStorageController(Bstr("SATA Controller").raw(),
@@ -2844,7 +2848,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
         Bstr bstrName(L"SCSI Controller");
         StorageBus_T busType = StorageBus_SCSI;
         StorageControllerType_T controllerType;
-        const Utf8Str &hdcVBox = vsdeHDCSCSI.front()->strVboxCurrent;
+        const Utf8Str &hdcVBox = vsdeHDCSCSI.front()->strVBoxCurrent;
         if (hdcVBox == "LsiLogic")
             controllerType = StorageControllerType_LsiLogic;
         else if (hdcVBox == "LsiLogicSas")
@@ -2980,6 +2984,15 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
         // we need another try/catch block.
         try
         {
+#ifdef LOG_ENABLED
+            if (LogIsEnabled())
+            {
+                size_t i = 0;
+                for (list<VirtualSystemDescriptionEntry*>::const_iterator itHD = avsdeHDs.begin(); itHD != avsdeHDs.end(); ++itHD, i++)
+                    Log(("avsdeHDs[%zu]: strRef=%s\n", i, (*itHD)->strRef.c_str()));
+            }
+#endif
+
             // to attach things we need to open a session for the new machine
             rc = pNewMachine->LockMachine(stack.pSession, LockType_Write);
             if (FAILED(rc)) throw rc;
@@ -3001,6 +3014,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                 ovf::VirtualDisksMap::const_iterator itVDisk = vsysThis.mapVirtualDisks.begin();
 
                 VirtualSystemDescriptionEntry *vsdeTargetHD = 0;
+                Log(("diCurrent.strDiskId=%s\n", diCurrent.strDiskId.c_str()));
 
                 /*
                  *
@@ -3113,7 +3127,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                                 if (!vsdeTargetHD)
                                     /*
                                      * in this case it's an error because something wrong with OVF description file.
-                                     * May be VB imports OVA package with wrong file sequence inside the archive.
+                                     * May be VBox imports OVA package with wrong file sequence inside the archive.
                                      */
                                     throw setError(E_FAIL,
                                                    tr("Internal inconsistency looking up disk image '%s'"),
@@ -3150,10 +3164,10 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
 
                 ComObjPtr<Medium> pTargetHD;
 
-                Utf8Str savedVboxCurrent = vsdeTargetHD->strVboxCurrent;
+                Utf8Str savedVBoxCurrent = vsdeTargetHD->strVBoxCurrent;
 
                 importOneDiskImage(diCurrent,
-                                   &vsdeTargetHD->strVboxCurrent,
+                                   &vsdeTargetHD->strVBoxCurrent,
                                    pTargetHD,
                                    stack,
                                    pCallbacks,
@@ -3179,7 +3193,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                                             mhda.lDevice);
 
                 Log(("Attaching disk %s to port %d on device %d\n",
-                vsdeTargetHD->strVboxCurrent.c_str(), mhda.lControllerPort, mhda.lDevice));
+                vsdeTargetHD->strVBoxCurrent.c_str(), mhda.lControllerPort, mhda.lDevice));
 
                 Utf8Str vdf = typeOfVirtualDiskFormatFromURI(diCurrent.strFormat);
 
@@ -3187,7 +3201,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                 {
                     ComPtr<IMedium> dvdImage(pTargetHD);
 
-                    rc = mVirtualBox->OpenMedium(Bstr(vsdeTargetHD->strVboxCurrent).raw(),
+                    rc = mVirtualBox->OpenMedium(Bstr(vsdeTargetHD->strVBoxCurrent).raw(),
                                                  DeviceType_DVD,
                                                  AccessMode_ReadWrite,
                                                  false,
@@ -3223,7 +3237,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                     throw rc;
 
                 /* restore */
-                vsdeTargetHD->strVboxCurrent = savedVboxCurrent;
+                vsdeTargetHD->strVBoxCurrent = savedVBoxCurrent;
 
                 ++cImportedDisks;
 
@@ -3259,6 +3273,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
                 throw setError(aRC, "Unknown error during OVF import");
         }
     }
+    LogFlowFuncLeave();
 }
 
 /**
@@ -3296,6 +3311,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                                   PVDINTERFACEIO pCallbacks,
                                   PSHASTORAGE pStorage)
 {
+    LogFlowFuncEnter();
     Assert(vsdescThis->m->pConfig);
 
     HRESULT rc = S_OK;
@@ -3406,7 +3422,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                     if (it1->ulSlot == iSlot)
                     {
                         it1->fEnabled = true;
-                        it1->type = (NetworkAdapterType_T)vsdeNW->strVboxCurrent.toUInt32();
+                        it1->type = (NetworkAdapterType_T)vsdeNW->strVBoxCurrent.toUInt32();
                         break;
                     }
                 }
@@ -3521,7 +3537,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
             if (!vsdeTargetHD)
             {
                 /* possible case if a disk image belongs to other virtual system (OVF package with multiple VMs inside) */
-                LogWarning(("OVA/OVF import: Disk image %s was missed during import of VM %s\n", 
+                LogWarning(("OVA/OVF import: Disk image %s was missed during import of VM %s\n",
                             oit->first.c_str(), vmNameEntry->strOvf.c_str()));
                 ++oit;
                 continue;
@@ -3595,9 +3611,9 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                         }
                     }
                     if (!vsdeTargetHD)
-                        /* 
+                        /*
                          * in this case it's an error because something wrong with OVF description file.
-                         * May be VB imports OVA package with wrong file sequence inside the archive.
+                         * May be VBox imports OVA package with wrong file sequence inside the archive.
                          */
                         throw setError(E_FAIL,
                                        tr("Internal inconsistency looking up disk image '%s'"),
@@ -3668,7 +3684,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                     if (itDiskImage != stack.mapDisks.end())
                     {
                         const ovf::DiskImage &di = itDiskImage->second;
-                        d.uuid = Guid(di.uuidVbox);
+                        d.uuid = Guid(di.uuidVBox);
                     }
                     ++avsdeHDsIt;
                 }
@@ -3676,7 +3692,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                 // convert the Guid to string
                 strUuid = d.uuid.toString();
 
-                if (diCurrent.uuidVbox != strUuid)
+                if (diCurrent.uuidVBox != strUuid)
                 {
                     continue;
                 }
@@ -3684,10 +3700,10 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                 /*
                  * step 3: import disk
                  */
-                Utf8Str savedVboxCurrent = vsdeTargetHD->strVboxCurrent;
+                Utf8Str savedVBoxCurrent = vsdeTargetHD->strVBoxCurrent;
                 ComObjPtr<Medium> pTargetHD;
                 importOneDiskImage(diCurrent,
-                                   &vsdeTargetHD->strVboxCurrent,
+                                   &vsdeTargetHD->strVBoxCurrent,
                                    pTargetHD,
                                    stack,
                                    pCallbacks,
@@ -3701,7 +3717,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                 {
                     ComPtr<IMedium> dvdImage(pTargetHD);
 
-                    rc = mVirtualBox->OpenMedium(Bstr(vsdeTargetHD->strVboxCurrent).raw(),
+                    rc = mVirtualBox->OpenMedium(Bstr(vsdeTargetHD->strVBoxCurrent).raw(),
                                                  DeviceType_DVD,
                                                  AccessMode_ReadWrite,
                                                  false,
@@ -3723,7 +3739,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
                 }
 
                 /* restore */
-                vsdeTargetHD->strVboxCurrent = savedVboxCurrent;
+                vsdeTargetHD->strVBoxCurrent = savedVBoxCurrent;
 
                 d.uuid = hdId;
                 fFound = true;
@@ -3777,6 +3793,8 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
     rc = pNewMachine->COMGETTER(Id)(bstrNewMachineId.asOutParam());
     if (FAILED(rc)) throw rc;
     m->llGuidsMachinesCreated.push_back(Guid(bstrNewMachineId));
+
+    LogFlowFuncLeave();
 }
 
 void Appliance::importMachines(ImportStack &stack,
@@ -3828,7 +3846,7 @@ void Appliance::importMachines(ImportStack &stack,
         if (vsdeName.size() < 1)
             throw setError(VBOX_E_FILE_ERROR,
                            tr("Missing VM name"));
-        stack.strNameVBox = vsdeName.front()->strVboxCurrent;
+        stack.strNameVBox = vsdeName.front()->strVBoxCurrent;
 
         // have VirtualBox suggest where the filename would be placed so we can
         // put the disk images in the same directory
@@ -3842,6 +3860,7 @@ void Appliance::importMachines(ImportStack &stack,
         // and determine the machine folder from that
         stack.strMachineFolder = bstrMachineFilename;
         stack.strMachineFolder.stripFilename();
+        LogFunc(("i=%zu strName=%s bstrMachineFilename=%ls\n", i, stack.strNameVBox.c_str(), bstrMachineFilename.raw()));
 
         // guest OS type
         std::list<VirtualSystemDescriptionEntry*> vsdeOS;
@@ -3849,14 +3868,14 @@ void Appliance::importMachines(ImportStack &stack,
         if (vsdeOS.size() < 1)
             throw setError(VBOX_E_FILE_ERROR,
                            tr("Missing guest OS type"));
-        stack.strOsTypeVBox = vsdeOS.front()->strVboxCurrent;
+        stack.strOsTypeVBox = vsdeOS.front()->strVBoxCurrent;
 
         // CPU count
         std::list<VirtualSystemDescriptionEntry*> vsdeCPU = vsdescThis->findByType(VirtualSystemDescriptionType_CPU);
         if (vsdeCPU.size() != 1)
             throw setError(VBOX_E_FILE_ERROR, tr("CPU count missing"));
 
-        stack.cCPUs = vsdeCPU.front()->strVboxCurrent.toUInt32();
+        stack.cCPUs = vsdeCPU.front()->strVBoxCurrent.toUInt32();
         // We need HWVirt & IO-APIC if more than one CPU is requested
         if (stack.cCPUs > 1)
         {
@@ -3868,7 +3887,7 @@ void Appliance::importMachines(ImportStack &stack,
         std::list<VirtualSystemDescriptionEntry*> vsdeRAM = vsdescThis->findByType(VirtualSystemDescriptionType_Memory);
         if (vsdeRAM.size() != 1)
             throw setError(VBOX_E_FILE_ERROR, tr("RAM size missing"));
-        stack.ulMemorySizeMB = (ULONG)vsdeRAM.front()->strVboxCurrent.toUInt64();
+        stack.ulMemorySizeMB = (ULONG)vsdeRAM.front()->strVBoxCurrent.toUInt64();
 
 #ifdef VBOX_WITH_USB
         // USB controller
@@ -3881,12 +3900,12 @@ void Appliance::importMachines(ImportStack &stack,
         std::list<VirtualSystemDescriptionEntry*> vsdeAudioAdapter = vsdescThis->findByType(VirtualSystemDescriptionType_SoundCard);
         /* @todo: we support one audio adapter only */
         if (vsdeAudioAdapter.size() > 0)
-            stack.strAudioAdapter = vsdeAudioAdapter.front()->strVboxCurrent;
+            stack.strAudioAdapter = vsdeAudioAdapter.front()->strVBoxCurrent;
 
         // for the description of the new machine, always use the OVF entry, the user may have changed it in the import config
         std::list<VirtualSystemDescriptionEntry*> vsdeDescription = vsdescThis->findByType(VirtualSystemDescriptionType_Description);
         if (vsdeDescription.size())
-            stack.strDescription = vsdeDescription.front()->strVboxCurrent;
+            stack.strDescription = vsdeDescription.front()->strVBoxCurrent;
 
         // import vbox:machine or OVF now
         if (vsdescThis->m->pConfig)
diff --git a/src/VBox/Main/src-server/BandwidthControlImpl.cpp b/src/VBox/Main/src-server/BandwidthControlImpl.cpp
index 941b011..5235bb6 100644
--- a/src/VBox/Main/src-server/BandwidthControlImpl.cpp
+++ b/src/VBox/Main/src-server/BandwidthControlImpl.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -74,8 +74,6 @@ void BandwidthControl::FinalRelease()
  *
  * @returns COM result indicator.
  * @param aParent       Pointer to our parent object.
- * @param aName         Name of the storage controller.
- * @param aInstance     Instance number of the storage controller.
  */
 HRESULT BandwidthControl::init(Machine *aParent)
 {
@@ -149,7 +147,7 @@ HRESULT BandwidthControl::init(Machine *aParent,
 }
 
 /**
- *  Initializes the storage controller object given another guest object
+ *  Initializes the bandwidth control object given another guest object
  *  (a kind of copy constructor). This object makes a private copy of data
  *  of the original object passed as an argument.
  */
@@ -178,7 +176,7 @@ HRESULT BandwidthControl::initCopy(Machine *aParent, BandwidthControl *aThat)
     {
         ComObjPtr<BandwidthGroup> group;
         group.createObject();
-        group->init(this, *it);
+        group->initCopy(this, *it);
         m->llBandwidthGroups->push_back(group);
         ++ it;
     }
@@ -217,7 +215,7 @@ void BandwidthControl::copyFrom (BandwidthControl *aThat)
     AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
     AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
 
-    /* create private copies of all filters */
+    /* create private copies of all bandwidth groups */
     m->llBandwidthGroups.backup();
     m->llBandwidthGroups->clear();
     for (BandwidthGroupList::const_iterator it = aThat->m->llBandwidthGroups->begin();
@@ -287,7 +285,7 @@ void BandwidthControl::commit()
         {
             AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
 
-            /* Commit all changes to new controllers (this will reshare data with
+            /* Commit all changes to new groups (this will reshare data with
              * peers for those who have peers) */
             BandwidthGroupList *newList = new BandwidthGroupList();
             BandwidthGroupList::const_iterator it = m->llBandwidthGroups->begin();
@@ -315,7 +313,7 @@ void BandwidthControl::commit()
                 ++it;
             }
 
-            /* uninit old peer's controllers that are left */
+            /* uninit old peer's groups that are left */
             it = m->pPeer->m->llBandwidthGroups->begin();
             while (it != m->pPeer->m->llBandwidthGroups->end())
             {
@@ -323,7 +321,7 @@ void BandwidthControl::commit()
                 ++it;
             }
 
-            /* attach new list of controllers to our peer */
+            /* attach new list of groups to our peer */
             m->pPeer->m->llBandwidthGroups.attach(newList);
         }
         else
@@ -336,7 +334,7 @@ void BandwidthControl::commit()
     else
     {
         /* the list of groups itself is not changed,
-         * just commit changes to controllers themselves */
+         * just commit changes to groups themselves */
         commitBandwidthGroups = true;
     }
 
@@ -381,10 +379,10 @@ void BandwidthControl::uninit()
 }
 
 /**
- * Returns a storage controller object with the given name.
+ * Returns a bandwidth group object with the given name.
  *
- *  @param aName                 storage controller name to find
- *  @param aStorageController    where to return the found storage controller
+ *  @param aName                 bandwidth group name to find
+ *  @param aBandwidthGroup where to return the found bandwidth group
  *  @param aSetError             true to set extended error info on failure
  */
 HRESULT BandwidthControl::getBandwidthGroupByName(const Utf8Str &aName,
diff --git a/src/VBox/Main/src-server/BandwidthGroupImpl.cpp b/src/VBox/Main/src-server/BandwidthGroupImpl.cpp
index aef8f4c..22ba0c1 100644
--- a/src/VBox/Main/src-server/BandwidthGroupImpl.cpp
+++ b/src/VBox/Main/src-server/BandwidthGroupImpl.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -80,8 +80,9 @@ void BandwidthGroup::FinalRelease()
  *
  * @returns COM result indicator.
  * @param aParent       Pointer to our parent object.
- * @param aName         Name of the storage controller.
- * @param aInstance     Instance number of the storage controller.
+ * @param aName         Name of the bandwidth group.
+ * @param aType         Type of the bandwidth group (net, disk).
+ * @param aMaxBytesPerSec Maximum bandwidth for the bandwidth group.
  */
 HRESULT BandwidthGroup::init(BandwidthControl *aParent,
                              const Utf8Str &aName,
@@ -175,7 +176,7 @@ HRESULT BandwidthGroup::init(BandwidthControl *aParent,
 }
 
 /**
- *  Initializes the storage controller object given another guest object
+ *  Initializes the bandwidth group object given another guest object
  *  (a kind of copy constructor). This object makes a private copy of data
  *  of the original object passed as an argument.
  */
diff --git a/src/VBox/Main/src-server/DHCPServerImpl.cpp b/src/VBox/Main/src-server/DHCPServerImpl.cpp
index 7a46068..1cd7ce7 100644
--- a/src/VBox/Main/src-server/DHCPServerImpl.cpp
+++ b/src/VBox/Main/src-server/DHCPServerImpl.cpp
@@ -37,14 +37,36 @@ const std::string DHCPServerRunner::kDsrKeyLowerIp = "--lower-ip";
 const std::string DHCPServerRunner::kDsrKeyUpperIp = "--upper-ip";
 
 
+struct DHCPServer::Data
+{
+    Data() : enabled(FALSE) {}
+
+    Bstr IPAddress;
+    Bstr lowerIP;
+    Bstr upperIP;
+
+    BOOL enabled;
+    DHCPServerRunner dhcp;
+
+    DhcpOptionMap GlobalDhcpOptions;
+    VmSlot2OptionsMap VmSlot2Options;
+};
+
+
 DHCPServer::DHCPServer()
-    : mVirtualBox(NULL)
+  : m(NULL), mVirtualBox(NULL)
 {
+    m = new DHCPServer::Data();
 }
 
 
 DHCPServer::~DHCPServer()
 {
+    if (m)
+    {
+        delete m;
+        m = NULL;
+    }
 }
 
 
@@ -84,12 +106,12 @@ HRESULT DHCPServer::init(VirtualBox *aVirtualBox, IN_BSTR aName)
     unconst(mVirtualBox) = aVirtualBox;
 
     unconst(mName) = aName;
-    m.IPAddress = "0.0.0.0";
-    m.GlobalDhcpOptions.insert(DhcpOptValuePair(DhcpOpt_SubnetMask, Bstr("0.0.0.0")));
-    m.enabled = FALSE;
+    m->IPAddress = "0.0.0.0";
+    m->GlobalDhcpOptions.insert(DhcpOptValuePair(DhcpOpt_SubnetMask, Bstr("0.0.0.0")));
+    m->enabled = FALSE;
 
-    m.lowerIP = "0.0.0.0";
-    m.upperIP = "0.0.0.0";
+    m->lowerIP = "0.0.0.0";
+    m->upperIP = "0.0.0.0";
 
     /* Confirm a successful initialization */
     autoInitSpan.setSucceeded();
@@ -109,17 +131,17 @@ HRESULT DHCPServer::init(VirtualBox *aVirtualBox,
     unconst(mVirtualBox) = aVirtualBox;
 
     unconst(mName) = data.strNetworkName;
-    m.IPAddress = data.strIPAddress;
-    m.enabled = data.fEnabled;
-    m.lowerIP = data.strIPLower;
-    m.upperIP = data.strIPUpper;
+    m->IPAddress = data.strIPAddress;
+    m->enabled = data.fEnabled;
+    m->lowerIP = data.strIPLower;
+    m->upperIP = data.strIPUpper;
 
-    m.GlobalDhcpOptions.clear();
-    m.GlobalDhcpOptions.insert(data.GlobalDhcpOptions.begin(),
+    m->GlobalDhcpOptions.clear();
+    m->GlobalDhcpOptions.insert(data.GlobalDhcpOptions.begin(),
                                data.GlobalDhcpOptions.end());
 
-    m.VmSlot2Options.clear();
-    m.VmSlot2Options.insert(data.VmSlot2OptionsM.begin(),
+    m->VmSlot2Options.clear();
+    m->VmSlot2Options.insert(data.VmSlot2OptionsM.begin(),
                             data.VmSlot2OptionsM.end());
 
     autoInitSpan.setSucceeded();
@@ -136,19 +158,19 @@ HRESULT DHCPServer::saveSettings(settings::DHCPServer &data)
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     data.strNetworkName = mName;
-    data.strIPAddress = m.IPAddress;
+    data.strIPAddress = m->IPAddress;
 
-    data.fEnabled = !!m.enabled;
-    data.strIPLower = m.lowerIP;
-    data.strIPUpper = m.upperIP;
+    data.fEnabled = !!m->enabled;
+    data.strIPLower = m->lowerIP;
+    data.strIPUpper = m->upperIP;
 
     data.GlobalDhcpOptions.clear();
-    data.GlobalDhcpOptions.insert(m.GlobalDhcpOptions.begin(),
-                                  m.GlobalDhcpOptions.end());
+    data.GlobalDhcpOptions.insert(m->GlobalDhcpOptions.begin(),
+                                  m->GlobalDhcpOptions.end());
 
     data.VmSlot2OptionsM.clear();
-    data.VmSlot2OptionsM.insert(m.VmSlot2Options.begin(),
-                                m.VmSlot2Options.end());
+    data.VmSlot2OptionsM.insert(m->VmSlot2Options.begin(),
+                                m->VmSlot2Options.end());
 
     return S_OK;
 }
@@ -174,7 +196,7 @@ STDMETHODIMP DHCPServer::COMGETTER(Enabled) (BOOL *aEnabled)
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    *aEnabled = m.enabled;
+    *aEnabled = m->enabled;
 
     return S_OK;
 }
@@ -186,7 +208,7 @@ STDMETHODIMP DHCPServer::COMSETTER(Enabled) (BOOL aEnabled)
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-    m.enabled = aEnabled;
+    m->enabled = aEnabled;
 
     // save the global settings; for that we should hold only the VirtualBox lock
     alock.release();
@@ -204,7 +226,7 @@ STDMETHODIMP DHCPServer::COMGETTER(IPAddress) (BSTR *aIPAddress)
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    m.IPAddress.cloneTo(aIPAddress);
+    m->IPAddress.cloneTo(aIPAddress);
 
     return S_OK;
 }
@@ -217,7 +239,7 @@ STDMETHODIMP DHCPServer::COMGETTER(NetworkMask) (BSTR *aNetworkMask)
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    m.GlobalDhcpOptions[DhcpOpt_SubnetMask].cloneTo(aNetworkMask);
+    m->GlobalDhcpOptions[DhcpOpt_SubnetMask].cloneTo(aNetworkMask);
 
     return S_OK;
 }
@@ -230,7 +252,7 @@ STDMETHODIMP DHCPServer::COMGETTER(LowerIP) (BSTR *aIPAddress)
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    m.lowerIP.cloneTo(aIPAddress);
+    m->lowerIP.cloneTo(aIPAddress);
 
     return S_OK;
 }
@@ -243,7 +265,7 @@ STDMETHODIMP DHCPServer::COMGETTER(UpperIP) (BSTR *aIPAddress)
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    m.upperIP.cloneTo(aIPAddress);
+    m->upperIP.cloneTo(aIPAddress);
 
     return S_OK;
 }
@@ -260,11 +282,11 @@ STDMETHODIMP DHCPServer::SetConfiguration (IN_BSTR aIPAddress, IN_BSTR aNetworkM
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-    m.IPAddress = aIPAddress;
-    m.GlobalDhcpOptions[DhcpOpt_SubnetMask] = aNetworkMask;
+    m->IPAddress = aIPAddress;
+    m->GlobalDhcpOptions[DhcpOpt_SubnetMask] = aNetworkMask;
 
-    m.lowerIP = aLowerIP;
-    m.upperIP = aUpperIP;
+    m->lowerIP = aLowerIP;
+    m->upperIP = aUpperIP;
 
     // save the global settings; for that we should hold only the VirtualBox lock
     alock.release();
@@ -282,12 +304,12 @@ STDMETHODIMP DHCPServer::AddGlobalOption(DhcpOpt_T aOption, IN_BSTR aValue)
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    m.GlobalDhcpOptions.insert(
+    m->GlobalDhcpOptions.insert(
       DhcpOptValuePair(aOption, Utf8Str(aValue)));
 
     /* Indirect way to understand that we're on NAT network */
     if (aOption == DhcpOpt_Router)
-        m.dhcp.setOption(NetworkServiceRunner::kNsrKeyNeedMain, "on");
+        m->dhcp.setOption(NetworkServiceRunner::kNsrKeyNeedMain, "on");
 
     alock.release();
 
@@ -305,11 +327,11 @@ STDMETHODIMP DHCPServer::COMGETTER(GlobalOptions)(ComSafeArrayOut(BSTR, aValue))
 
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    SafeArray<BSTR> sf(m.GlobalDhcpOptions.size());
+    SafeArray<BSTR> sf(m->GlobalDhcpOptions.size());
     int i = 0;
 
-    for (DhcpOptIterator it = m.GlobalDhcpOptions.begin();
-         it != m.GlobalDhcpOptions.end(); ++it)
+    for (DhcpOptIterator it = m->GlobalDhcpOptions.begin();
+         it != m->GlobalDhcpOptions.end(); ++it)
     {
         Bstr(Utf8StrFmt("%d:%s", (*it).first, (*it).second.c_str())).detachTo(&sf[i]);
         i++;
@@ -330,10 +352,10 @@ STDMETHODIMP DHCPServer::COMGETTER(VmConfigs)(ComSafeArrayOut(BSTR, aValue))
 
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    SafeArray<BSTR> sf(m.VmSlot2Options.size());
-    VmSlot2OptionsIterator it = m.VmSlot2Options.begin();
+    SafeArray<BSTR> sf(m->VmSlot2Options.size());
+    VmSlot2OptionsIterator it = m->VmSlot2Options.begin();
     int i = 0;
-    for (;it != m.VmSlot2Options.end(); ++it)
+    for (;it != m->VmSlot2Options.end(); ++it)
     {
         Bstr(Utf8StrFmt("[%s]:%d",
                         it->first.VmName.c_str(),
@@ -353,7 +375,7 @@ STDMETHODIMP DHCPServer::AddVmSlotOption(IN_BSTR aVmName, LONG aSlot, DhcpOpt_T
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    m.VmSlot2Options[settings::VmNameSlotKey(
+    m->VmSlot2Options[settings::VmNameSlotKey(
           com::Utf8Str(aVmName),
           aSlot)][aOption] = com::Utf8Str(aValue);
 
@@ -427,8 +449,8 @@ STDMETHODIMP DHCPServer::GetMacOptions(IN_BSTR aMAC, ComSafeArrayOut(BSTR, aValu
     ComPtr<INetworkAdapter> nic;
 
     VmSlot2OptionsIterator it;
-    for(it = m.VmSlot2Options.begin();
-        it != m.VmSlot2Options.end();
+    for(it = m->VmSlot2Options.begin();
+        it != m->VmSlot2Options.end();
         ++it)
     {
 
@@ -475,17 +497,17 @@ STDMETHODIMP DHCPServer::COMGETTER(EventSource)(IEventSource **aEventSource)
 STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType)
 {
     /* Silently ignore attempts to run disabled servers. */
-    if (!m.enabled)
+    if (!m->enabled)
         return S_OK;
 
     /* Commmon Network Settings */
-    m.dhcp.setOption(NetworkServiceRunner::kNsrKeyNetwork, Utf8Str(aNetworkName).c_str());
+    m->dhcp.setOption(NetworkServiceRunner::kNsrKeyNetwork, Utf8Str(aNetworkName).c_str());
 
     Bstr tmp(aTrunkName);
 
     if (!tmp.isEmpty())
-        m.dhcp.setOption(NetworkServiceRunner::kNsrTrunkName, Utf8Str(tmp).c_str());
-    m.dhcp.setOption(NetworkServiceRunner::kNsrKeyTrunkType, Utf8Str(aTrunkType).c_str());
+        m->dhcp.setOption(NetworkServiceRunner::kNsrTrunkName, Utf8Str(tmp).c_str());
+    m->dhcp.setOption(NetworkServiceRunner::kNsrKeyTrunkType, Utf8Str(aTrunkType).c_str());
 
     /* XXX: should this MAC default initialization moved to NetworkServiceRunner? */
     char strMAC[32];
@@ -495,28 +517,28 @@ STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR
                  guid.raw()->au8[0],
                  guid.raw()->au8[1],
                  guid.raw()->au8[2]);
-    m.dhcp.setOption(NetworkServiceRunner::kNsrMacAddress, strMAC);
-    m.dhcp.setOption(NetworkServiceRunner::kNsrIpAddress,  Utf8Str(m.IPAddress).c_str());
-    m.dhcp.setOption(NetworkServiceRunner::kNsrIpNetmask, Utf8Str(m.GlobalDhcpOptions[DhcpOpt_SubnetMask]).c_str());
-    m.dhcp.setOption(DHCPServerRunner::kDsrKeyLowerIp, Utf8Str(m.lowerIP).c_str());
-    m.dhcp.setOption(DHCPServerRunner::kDsrKeyUpperIp, Utf8Str(m.upperIP).c_str());
+    m->dhcp.setOption(NetworkServiceRunner::kNsrMacAddress, strMAC);
+    m->dhcp.setOption(NetworkServiceRunner::kNsrIpAddress,  Utf8Str(m->IPAddress).c_str());
+    m->dhcp.setOption(NetworkServiceRunner::kNsrIpNetmask, Utf8Str(m->GlobalDhcpOptions[DhcpOpt_SubnetMask]).c_str());
+    m->dhcp.setOption(DHCPServerRunner::kDsrKeyLowerIp, Utf8Str(m->lowerIP).c_str());
+    m->dhcp.setOption(DHCPServerRunner::kDsrKeyUpperIp, Utf8Str(m->upperIP).c_str());
 
     /* XXX: This parameters Dhcp Server will fetch via API */
-    return RT_FAILURE(m.dhcp.start()) ? E_FAIL : S_OK;
-    //m.dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */
+    return RT_FAILURE(m->dhcp.start()) ? E_FAIL : S_OK;
+    //m->dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */
 }
 
 
 STDMETHODIMP DHCPServer::Stop (void)
 {
-    return RT_FAILURE(m.dhcp.stop()) ? E_FAIL : S_OK;
+    return RT_FAILURE(m->dhcp.stop()) ? E_FAIL : S_OK;
 }
 
 
 DhcpOptionMap& DHCPServer::findOptMapByVmNameSlot(const com::Utf8Str& aVmName,
                                                   LONG aSlot)
 {
-    return m.VmSlot2Options[settings::VmNameSlotKey(
+    return m->VmSlot2Options[settings::VmNameSlotKey(
           com::Utf8Str(aVmName),
           aSlot)];
 }
diff --git a/src/VBox/Main/src-server/HostDnsService.cpp b/src/VBox/Main/src-server/HostDnsService.cpp
index 0e5cbc5..d4cd3a0 100644
--- a/src/VBox/Main/src-server/HostDnsService.cpp
+++ b/src/VBox/Main/src-server/HostDnsService.cpp
@@ -21,6 +21,7 @@
 
 #include <iprt/cpp/utils.h>
 
+#include "Logging.h"
 #include "VirtualBoxImpl.h"
 #include <iprt/thread.h>
 #include <iprt/semaphore.h>
@@ -33,6 +34,8 @@
 
 static HostDnsMonitor *g_monitor;
 
+static void dumpHostDnsInformation(const HostDnsInformation&);
+static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&);
 
 /* Lockee */
 Lockee::Lockee()
@@ -79,8 +82,13 @@ inline static void detachVectorOfString(const std::vector<std::string>& v,
 
 struct HostDnsMonitor::Data
 {
+    Data(bool aThreaded):fThreaded(aThreaded){}
+
     std::vector<PCHostDnsMonitorProxy> proxies;
     HostDnsInformation info;
+    const bool fThreaded;
+    RTTHREAD hMonitoringThread;
+    RTSEMEVENT hDnsInitEvent;
 };
 
 struct HostDnsMonitorProxy::Data
@@ -108,9 +116,10 @@ struct HostDnsMonitorProxy::Data
 };
 
 
-HostDnsMonitor::HostDnsMonitor()
+HostDnsMonitor::HostDnsMonitor(bool fThreaded)
   : m(NULL)
 {
+   m = new HostDnsMonitor::Data(fThreaded);
 }
 
 HostDnsMonitor::~HostDnsMonitor()
@@ -197,11 +206,34 @@ void HostDnsMonitor::setInfo(const HostDnsInformation &info)
 
 HRESULT HostDnsMonitor::init()
 {
-    m = new HostDnsMonitor::Data();
+    if (m->fThreaded)
+    {
+        int rc = RTSemEventCreate(&m->hDnsInitEvent);
+        AssertRCReturn(rc, E_FAIL);
+
+        rc = RTThreadCreate(&m->hMonitoringThread,
+                            HostDnsMonitor::threadMonitoringRoutine,
+                            this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
+        AssertRCReturn(rc, E_FAIL);
+
+        RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
+    }
     return S_OK;
 }
 
 
+void HostDnsMonitor::monitorThreadInitializationDone()
+{
+    RTSemEventSignal(m->hDnsInitEvent);
+}
+
+
+int HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
+{
+    HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
+    return pThis->monitorWorker();
+}
+
 /* HostDnsMonitorProxy */
 HostDnsMonitorProxy::HostDnsMonitorProxy()
   : m(NULL)
@@ -240,6 +272,9 @@ HRESULT HostDnsMonitorProxy::GetNameServers(ComSafeArrayOut(BSTR, aNameServers))
     if (m->fModified)
         updateInfo();
 
+    LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
+    dumpHostDnsStrVector("Name Server", m->info->servers);
+
     detachVectorOfString(m->info->servers, ComSafeArrayOutArg(aNameServers));
 
     return S_OK;
@@ -253,6 +288,8 @@ HRESULT HostDnsMonitorProxy::GetDomainName(BSTR *aDomainName)
     if (m->fModified)
         updateInfo();
 
+    LogRel(("HostDnsMonitorProxy::GetDomainName:%s\n", m->info->domain.c_str()));
+
     Utf8Str(m->info->domain.c_str()).cloneTo(aDomainName);
 
     return S_OK;
@@ -266,6 +303,9 @@ HRESULT HostDnsMonitorProxy::GetSearchStrings(ComSafeArrayOut(BSTR, aSearchStrin
     if (m->fModified)
         updateInfo();
 
+    LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
+    dumpHostDnsStrVector("Search String", m->info->searchList);
+
     detachVectorOfString(m->info->searchList, ComSafeArrayOutArg(aSearchStrings));
 
     return S_OK;
@@ -287,9 +327,37 @@ void HostDnsMonitorProxy::updateInfo()
     HostDnsInformation *info = new HostDnsInformation(m->monitor->getInfo());
     HostDnsInformation *old = m->info;
 
+    LogRel(("HostDnsMonitorProxy: Host's DNS information updated:\n"));
+    dumpHostDnsInformation(*info);
+
     m->info = info;
     if (old)
+    {
+        LogRel(("HostDnsMonitorProxy: Old host information:\n"));
+        dumpHostDnsInformation(*old);
+
         delete old;
+    }
 
     m->fModified = false;
 }
+
+
+static void dumpHostDnsInformation(const HostDnsInformation& info)
+{
+    dumpHostDnsStrVector("DNS server", info.servers);
+    dumpHostDnsStrVector("SearchString", info.searchList);
+
+    if (!info.domain.empty())
+        LogRel(("DNS domain: %s\n", info.domain.c_str()));
+}
+
+
+static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
+{
+    int i = 0;
+    for (std::vector<std::string>::const_iterator it = v.begin();
+         it != v.end();
+         ++it, ++i)
+        LogRel(("%s %d: %s\n", prefix.c_str(), i, it->c_str()));
+}
diff --git a/src/VBox/Main/src-server/HostDnsService.h b/src/VBox/Main/src-server/HostDnsService.h
index 094f9da..56da78d 100644
--- a/src/VBox/Main/src-server/HostDnsService.h
+++ b/src/VBox/Main/src-server/HostDnsService.h
@@ -46,7 +46,7 @@ class Lockee
 class ALock
 {
   public:
-    ALock(const Lockee *l);
+    explicit ALock(const Lockee *l);
     ~ALock();
 
   private:
@@ -74,17 +74,26 @@ class HostDnsMonitor : public Lockee
     void addMonitorProxy(PCHostDnsMonitorProxy) const;
     void releaseMonitorProxy(PCHostDnsMonitorProxy) const;
     const HostDnsInformation &getInfo() const;
+    /* @note: method will wait till client call
+       HostDnsService::monitorThreadInitializationDone() */
     virtual HRESULT init();
 
   protected:
+    explicit HostDnsMonitor(bool fThreaded = false);
+    virtual ~HostDnsMonitor();
+
     void notifyAll() const;
     void setInfo(const HostDnsInformation &);
-    HostDnsMonitor();
-    virtual ~HostDnsMonitor();
+
+    /* this function used only if HostDnsMonitor::HostDnsMonitor(true) */
+    void monitorThreadInitializationDone();
+    virtual void monitorThreadShutdown() = 0;
+    virtual int monitorWorker() = 0;
 
   private:
     HostDnsMonitor(const HostDnsMonitor &);
     HostDnsMonitor& operator= (const HostDnsMonitor &);
+    static int threadMonitoringRoutine(RTTHREAD, void *);
 
   public:
     struct Data;
@@ -96,7 +105,7 @@ class HostDnsMonitor : public Lockee
  */
 class HostDnsMonitorProxy : public Lockee
 {
-  public:
+    public:
     HostDnsMonitorProxy();
     ~HostDnsMonitorProxy();
     void init(const HostDnsMonitor *aMonitor, const VirtualBox *aParent);
@@ -108,10 +117,10 @@ class HostDnsMonitorProxy : public Lockee
 
     bool operator==(PCHostDnsMonitorProxy&);
 
-  private:
+    private:
     void updateInfo();
 
-  private:
+    private:
     struct Data;
     Data *m;
 };
@@ -124,35 +133,54 @@ class HostDnsServiceDarwin : public HostDnsMonitor
     ~HostDnsServiceDarwin();
     HRESULT init();
 
-  private:
+    protected:
+    virtual void monitorThreadShutdown();
+    virtual int monitorWorker();
+
+    private:
     HRESULT updateInfo();
     static void hostDnsServiceStoreCallback(void *store, void *arrayRef, void *info);
+    struct Data;
+    Data *m;
 };
 # endif
 # ifdef RT_OS_WINDOWS
 class HostDnsServiceWin : public HostDnsMonitor
 {
-  public:
+    public:
     HostDnsServiceWin();
     ~HostDnsServiceWin();
     HRESULT init();
 
-  private:
+    protected:
+    virtual void monitorThreadShutdown();
+    virtual int monitorWorker();
+
+    private:
     void strList2List(std::vector<std::string>& lst, char *strLst);
     HRESULT updateInfo();
+
+    private:
+    struct Data;
+    Data *m;
 };
 # endif
 # if defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX) || defined(RT_OS_OS2) || defined(RT_OS_FREEBSD)
 class HostDnsServiceResolvConf: public HostDnsMonitor
 {
   public:
-    HostDnsServiceResolvConf() : m(NULL) {}
+    explicit HostDnsServiceResolvConf(bool fThreaded = false) : HostDnsMonitor(fThreaded), m(NULL) {}
     virtual ~HostDnsServiceResolvConf();
     virtual HRESULT init(const char *aResolvConfFileName);
-    const std::string& resolvConf();
+    const std::string& resolvConf() const;
 
   protected:
     HRESULT readResolvConf();
+    /* While not all hosts supports Hosts DNS change notifiaction
+     * default implementation offers return VERR_IGNORE.
+     */
+    virtual void monitorThreadShutdown() {}
+    virtual int monitorWorker() {return VERR_IGNORED;}
 
   protected:
     struct Data;
@@ -174,12 +202,13 @@ class HostDnsServiceSolaris : public HostDnsServiceResolvConf
 class HostDnsServiceLinux : public HostDnsServiceResolvConf
 {
   public:
-    HostDnsServiceLinux(){}
-    ~HostDnsServiceLinux();
-    HRESULT init() {return init("/etc/resolv.conf");}
-    HRESULT init(const char *aResolvConfFileName);
+    HostDnsServiceLinux():HostDnsServiceResolvConf(true){}
+    virtual ~HostDnsServiceLinux();
+    virtual HRESULT init(){ return HostDnsServiceResolvConf::init("/etc/resolv.conf");}
 
-    static int hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser);
+  protected:
+    virtual void monitorThreadShutdown();
+    virtual int monitorWorker();
 };
 
 #  elif defined(RT_OS_FREEBSD)
diff --git a/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp b/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp
index 931c7fd..3b2ceeb 100644
--- a/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp
+++ b/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp
@@ -24,6 +24,7 @@ typedef int socklen_t;
 #include <string>
 
 #include "HostDnsService.h"
+#include "../../Devices/Network/slirp/resolv_conf_parser.h"
 
 
 struct HostDnsServiceResolvConf::Data
@@ -33,37 +34,11 @@ struct HostDnsServiceResolvConf::Data
     std::string resolvConfFilename;
 };
 
-const std::string &HostDnsServiceResolvConf::resolvConf()
+const std::string& HostDnsServiceResolvConf::resolvConf() const
 {
     return m->resolvConfFilename;
 }
 
-static int fileGets(RTFILE File, void *pvBuf, size_t cbBufSize, size_t *pcbRead)
-{
-    size_t cbRead;
-    char bTest;
-    int rc = VERR_NO_MEMORY;
-    char *pu8Buf = (char *)pvBuf;
-    *pcbRead = 0;
-
-    while (   RT_SUCCESS(rc = RTFileRead(File, &bTest, 1, &cbRead))
-           && (pu8Buf - (char *)pvBuf) >= 0
-           && (size_t)(pu8Buf - (char *)pvBuf) < cbBufSize)
-    {
-        if (cbRead == 0)
-            return VERR_EOF;
-
-        if (bTest == '\r' || bTest == '\n')
-        {
-            *pu8Buf = 0;
-            return VINF_SUCCESS;
-        }
-        *pu8Buf = bTest;
-         pu8Buf++;
-        (*pcbRead)++;
-    }
-    return rc;
-}
 
 HostDnsServiceResolvConf::~HostDnsServiceResolvConf()
 {
@@ -76,64 +51,40 @@ HostDnsServiceResolvConf::~HostDnsServiceResolvConf()
 
 HRESULT HostDnsServiceResolvConf::init(const char *aResolvConfFileName)
 {
+    m = new Data(aResolvConfFileName);
+
     HostDnsMonitor::init();
 
-    m = new Data(aResolvConfFileName);
     readResolvConf();
 
     return S_OK;
 }
 
+
 HRESULT HostDnsServiceResolvConf::readResolvConf()
 {
-    char buff[256];
-    char buff2[256];
-    int cNameserversFound = 0;
-    bool fWarnTooManyDnsServers = false;
-    struct in_addr tmp_addr;
-    size_t bytes;
-    HostDnsInformation info;
-    RTFILE resolvConfFile;
+    struct rcp_state st;
+    
+    st.rcps_flags = RCPSF_NO_STR2IPCONV; 
+    int rc = rcp_parse(&st, m->resolvConfFilename.c_str());
+    if (rc == -1)
+        return S_OK;
 
-    int rc = RTFileOpen(&resolvConfFile, m->resolvConfFilename.c_str(),
-                        RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
-    AssertRCReturn(rc, E_FAIL);
-
-    while (    RT_SUCCESS(rc = fileGets(resolvConfFile, buff, sizeof(buff), &bytes))
-            && rc != VERR_EOF)
+    HostDnsInformation info;
+    for (unsigned i = 0; i != st.rcps_num_nameserver; ++i)
     {
-        if (   cNameserversFound == 4
-            && !fWarnTooManyDnsServers
-            && sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1)
-        {
-            fWarnTooManyDnsServers = true;
-            LogRel(("NAT: too many nameservers registered.\n"));
-        }
-        if (   sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1
-            && cNameserversFound < 4) /* Unix doesn't accept more than 4 name servers*/
-        {
-            if (!inet_aton(buff2, &tmp_addr))
-                continue;
-
-            info.servers.push_back(std::string(buff2));
-
-            cNameserversFound++;
-        }
-        if (   !strncmp(buff, "domain", 6) 
-            || !strncmp(buff, "search", 6))
-        {
-            char *tok;
-            char *saveptr;
-
-            tok = strtok_r(&buff[6], " \t\n", &saveptr);
-
-            if (tok != NULL)
-                info.domain = std::string(tok);
-        }
+        AssertBreak(st.rcps_str_nameserver[i]);
+        info.servers.push_back(st.rcps_str_nameserver[i]);
     }
+    
+    if (st.rcps_domain)
+        info.domain = st.rcps_domain;
 
-    RTFileClose(resolvConfFile);
-
+    for (unsigned i = 0; i != st.rcps_num_searchlist; ++i)
+    {
+        AssertBreak(st.rcps_searchlist[i]);
+        info.searchList.push_back(st.rcps_searchlist[i]);
+    }
     setInfo(info);
 
     return S_OK;
diff --git a/src/VBox/Main/src-server/HostPower.cpp b/src/VBox/Main/src-server/HostPower.cpp
index b838923..3146a7a 100644
--- a/src/VBox/Main/src-server/HostPower.cpp
+++ b/src/VBox/Main/src-server/HostPower.cpp
@@ -51,7 +51,7 @@ void HostPowerService::notify(Reason_T aReason)
     {
         case Reason_HostSuspend:
         {
-            LogFunc(("SUSPEND\n"));
+            LogFunc(("HOST SUSPEND\n"));
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
             /* Suspend performance sampling to avoid unnecessary callbacks due to jumps in time. */
@@ -79,14 +79,13 @@ void HostPowerService::notify(Reason_T aReason)
                 mSessionControls.push_back(pControl);
             }
 
-            LogFunc(("Suspended %d VMs\n", mSessionControls.size()));
-
+            LogRel(("Host suspending: Paused %d VMs\n", mSessionControls.size()));
             break;
         }
 
         case Reason_HostResume:
         {
-            LogFunc(("RESUME\n"));
+            LogFunc(("HOST RESUME\n"));
 
             size_t resumed = 0;
 
@@ -104,7 +103,7 @@ void HostPowerService::notify(Reason_T aReason)
                 ++resumed;
             }
 
-            LogFunc(("Resumed %d VMs\n", resumed));
+            LogRel(("Host resumed: Resumed %d VMs\n", resumed));
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
             /* Resume the performance sampling. */
@@ -115,7 +114,6 @@ void HostPowerService::notify(Reason_T aReason)
 #endif
 
             mSessionControls.clear();
-
             break;
         }
 
@@ -123,42 +121,74 @@ void HostPowerService::notify(Reason_T aReason)
         {
             LogFunc(("BATTERY LOW\n"));
 
-            mVirtualBox->getOpenedMachines(machines, &controls);
+            Bstr value;
+            rc = mVirtualBox->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(),
+                                           value.asOutParam());
+            int fGlobal = 0;
+            if (SUCCEEDED(rc) && !value.isEmpty())
+            {
+                if (value != "0")
+                    fGlobal = 1;
+                else if (value == "0")
+                    fGlobal = -1;
+            }
 
+            mVirtualBox->getOpenedMachines(machines, &controls);
             size_t saved = 0;
 
             /* save running VMs */
+            SessionMachinesList::const_iterator it2 = machines.begin();
             for (VirtualBox::InternalControlList::const_iterator it = controls.begin();
-                 it != controls.end();
-                 ++it)
+                 it != controls.end() && it2 != machines.end();
+                 ++it, ++it2)
             {
-                ComPtr<IInternalSessionControl> pControl = *it;
-
-                ComPtr<IProgress> progress;
-
-                /* note that SaveStateWithReason() will simply return a failure
-                 * if the VM is in an inappropriate state */
-                rc = pControl->SaveStateWithReason(Reason_HostBatteryLow, progress.asOutParam());
-                if (FAILED(rc))
-                    continue;
-
-                /* Wait until the operation has been completed. */
-                rc = progress->WaitForCompletion(-1);
-                if (SUCCEEDED(rc))
+                ComPtr<SessionMachine> pMachine = *it2;
+                rc = pMachine->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(),
+                                            value.asOutParam());
+                int fPerVM = 0;
+                if (SUCCEEDED(rc) && !value.isEmpty())
                 {
-                    LONG iRc;
-                    progress->COMGETTER(ResultCode)(&iRc);
-                    rc = iRc;
+                    /* per-VM overrides global */
+                    if (value != "0")
+                        fPerVM = 2;
+                    else if (value == "0")
+                        fPerVM = -2;
                 }
 
-                AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %Rhrc (%#08X)\n", rc, rc));
-
-                if (SUCCEEDED(rc))
-                    ++saved;
+                /* default is true */
+                if (fGlobal + fPerVM >= 0)
+                {
+                    ComPtr<IInternalSessionControl> pControl = *it;
+                    ComPtr<IProgress> progress;
+
+                    /* note that SaveStateWithReason() will simply return a failure
+                     * if the VM is in an inappropriate state */
+                    rc = pControl->SaveStateWithReason(Reason_HostBatteryLow, progress.asOutParam());
+                    if (FAILED(rc))
+                    {
+                        LogRel(("SaveState '%s' failed with %Rhrc\n", pMachine->getName().c_str(), rc));
+                        continue;
+                    }
+
+                    /* Wait until the operation has been completed. */
+                    rc = progress->WaitForCompletion(-1);
+                    if (SUCCEEDED(rc))
+                    {
+                        LONG iRc;
+                        progress->COMGETTER(ResultCode)(&iRc);
+                        rc = iRc;
+                    }
+
+                    AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %Rhrc (%#08X)\n", rc, rc));
+
+                    if (SUCCEEDED(rc))
+                    {
+                        LogRel(("SaveState '%s' succeeded\n", pMachine->getName().c_str()));
+                        ++saved;
+                    }
+                }
             }
-
-            LogFunc(("Saved %d VMs\n", saved));
-
+            LogRel(("Battery Low: saved %d VMs\n", saved));
             break;
         }
 
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 995c423..b8eea6f 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -571,6 +571,10 @@ HRESULT Machine::init(VirtualBox *aParent,
             autoInitSpan.setSucceeded();
         else
         {
+            /* Ignore all errors from unregistering, they would destroy
+             * the more interesting error information we already have,
+             * pinpointing the issue with the VM config. */
+            ErrorInfoKeeper eik;
             autoInitSpan.setLimited();
 
             // uninit media from this machine's media registry, or else
@@ -1933,6 +1937,9 @@ STDMETHODIMP Machine::COMSETTER(GraphicsControllerType)(GraphicsControllerType_T
     {
         case GraphicsControllerType_Null:
         case GraphicsControllerType_VBoxVGA:
+#ifdef VBOX_WITH_VMSVGA
+        case GraphicsControllerType_VMSVGA:
+#endif
             break;
         default:
             return setError(E_INVALIDARG, tr("The graphics controller type (%d) is invalid"), aGraphicsControllerType);
diff --git a/src/VBox/Main/src-server/NATNetworkImpl.cpp b/src/VBox/Main/src-server/NATNetworkImpl.cpp
index ce32d6b..c419420 100644
--- a/src/VBox/Main/src-server/NATNetworkImpl.cpp
+++ b/src/VBox/Main/src-server/NATNetworkImpl.cpp
@@ -869,7 +869,6 @@ STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
 
     if (!m->fEnabled) return S_OK;
 
-    m->NATRunner.setOption(NetworkServiceRunner::kNsrKeyNeedMain, "on");
     m->NATRunner.setOption(NetworkServiceRunner::kNsrKeyNetwork, Utf8Str(mName).c_str());
     m->NATRunner.setOption(NetworkServiceRunner::kNsrKeyTrunkType, Utf8Str(aTrunkType).c_str());
     m->NATRunner.setOption(NetworkServiceRunner::kNsrIpAddress, Utf8Str(m->IPv4Gateway).c_str());
@@ -893,15 +892,15 @@ STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
          * 5. call setConfiguration() and pass all required parameters
          * 6. start dhcp server.
          */
-        int rc = mVirtualBox->FindDHCPServerByNetworkName(mName.raw(),
+        HRESULT hrc = mVirtualBox->FindDHCPServerByNetworkName(mName.raw(),
                                                       m->dhcpServer.asOutParam());
-        switch (rc)
+        switch (hrc)
         {
             case E_INVALIDARG:
                 /* server haven't beeen found let create it then */
-                rc = mVirtualBox->CreateDHCPServer(mName.raw(),
+                hrc = mVirtualBox->CreateDHCPServer(mName.raw(),
                                                    m->dhcpServer.asOutParam());
-                if (FAILED(rc))
+                if (FAILED(hrc))
                   return E_FAIL;
                 /* breakthrough */
 
@@ -912,7 +911,7 @@ STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
                          Utf8Str(m->IPv4DhcpServerLowerIp.raw()).c_str(),
                          Utf8Str(m->IPv4DhcpServerUpperIp.raw()).c_str()));
 
-                rc = m->dhcpServer->COMSETTER(Enabled)(true);
+                hrc = m->dhcpServer->COMSETTER(Enabled)(true);
 
                 BSTR dhcpip = NULL;
                 BSTR netmask = NULL;
@@ -923,7 +922,7 @@ STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
                 m->IPv4NetworkMask.cloneTo(&netmask);
                 m->IPv4DhcpServerLowerIp.cloneTo(&lowerip);
                 m->IPv4DhcpServerUpperIp.cloneTo(&upperip);
-                rc = m->dhcpServer->SetConfiguration(dhcpip,
+                hrc = m->dhcpServer->SetConfiguration(dhcpip,
                                                      netmask,
                                                      lowerip,
                                                      upperip);
@@ -938,8 +937,8 @@ STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
         /* XXX: AddGlobalOption(DhcpOpt_Router,) - enables attachement of DhcpServer to Main. */
         m->dhcpServer->AddGlobalOption(DhcpOpt_Router, m->IPv4Gateway.raw());
 
-        rc = m->dhcpServer->Start(mName.raw(), Bstr("").raw(), aTrunkType);
-        if (FAILED(rc))
+        hrc = m->dhcpServer->Start(mName.raw(), Bstr("").raw(), aTrunkType);
+        if (FAILED(hrc))
         {
             m->dhcpServer.setNull();
             return E_FAIL;
diff --git a/src/VBox/Main/src-server/NetworkServiceRunner.cpp b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
index 6a3f6e7..14610e5 100644
--- a/src/VBox/Main/src-server/NetworkServiceRunner.cpp
+++ b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
@@ -43,7 +43,7 @@ struct NetworkServiceRunner::Data
 NetworkServiceRunner::NetworkServiceRunner(const char *aProcName)
 {
     m = new NetworkServiceRunner::Data(aProcName);
-    
+
 }
 
 
diff --git a/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp b/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp
index 4f35005..6e91e7e 100644
--- a/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp
+++ b/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp
@@ -31,69 +31,51 @@
 #include "../HostDnsService.h"
 
 
-
-SCDynamicStoreRef g_store;
-CFRunLoopSourceRef g_DnsWatcher;
-CFRunLoopRef g_RunLoopRef;
-RTTHREAD g_DnsMonitoringThread;
-RTSEMEVENT g_DnsInitEvent;
-
-static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
-
-static int hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
+struct HostDnsServiceDarwin::Data
 {
-    NOREF(ThreadSelf);
-    NOREF(pvUser);
-    g_RunLoopRef = CFRunLoopGetCurrent();
-    AssertReturn(g_RunLoopRef, VERR_INTERNAL_ERROR);
-
-    CFRetain(g_RunLoopRef);
-
-    CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
-                                                (const void **)&kStateNetworkGlobalDNSKey,
-                                                1, &kCFTypeArrayCallBacks);
-    if (!watchingArrayRef)
-    {
-        CFRelease(g_DnsWatcher);
-        return E_OUTOFMEMORY;
-    }
-
-    if(SCDynamicStoreSetNotificationKeys(g_store, watchingArrayRef, NULL))
-        CFRunLoopAddSource(CFRunLoopGetCurrent(), g_DnsWatcher, kCFRunLoopCommonModes);
-
-    CFRelease(watchingArrayRef);
+    SCDynamicStoreRef m_store;
+    CFRunLoopSourceRef m_DnsWatcher;
+    CFRunLoopRef m_RunLoopRef;
+    CFRunLoopSourceRef m_Stopper;
+    bool m_fStop;
+    RTSEMEVENT m_evtStop;
+    static void performShutdownCallback(void *);
+};
 
-    RTSemEventSignal(g_DnsInitEvent);
 
-    CFRunLoopRun();
+static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
 
-    CFRelease(g_RunLoopRef);
 
-    return VINF_SUCCESS;
+HostDnsServiceDarwin::HostDnsServiceDarwin():HostDnsMonitor(true),m(NULL)
+{
+    m = new HostDnsServiceDarwin::Data();
 }
 
 
-HostDnsServiceDarwin::HostDnsServiceDarwin(){}
-
-
 HostDnsServiceDarwin::~HostDnsServiceDarwin()
 {
-    if (g_RunLoopRef)
-        CFRunLoopStop(g_RunLoopRef);
+    if (!m)
+        return;
+
+    monitorThreadShutdown();
+
+    CFRelease(m->m_RunLoopRef);
+    
+    CFRelease(m->m_DnsWatcher);
+
+    CFRelease(m->m_store);
 
-    CFRelease(g_DnsWatcher);
+    RTSemEventDestroy(m->m_evtStop);
 
-    CFRelease(g_store);
+    delete m;
+    m = NULL;
 }
 
 
-void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *arg0, void *arg1, void *info)
+void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *, void *, void *info)
 {
     HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
 
-    NOREF(arg0); /* SCDynamicStore */
-    NOREF(arg1); /* CFArrayRef */
-
     ALock l(pThis);
     pThis->updateInfo();
     pThis->notifyAll();
@@ -107,33 +89,84 @@ HRESULT HostDnsServiceDarwin::init()
 
     ctx.info = this;
 
-    g_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
+    m->m_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
                                    (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
                                    &ctx);
-    AssertReturn(g_store, E_FAIL);
+    AssertReturn(m->m_store, E_FAIL);
 
-    g_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, g_store, 0);
-    if (!g_DnsWatcher)
+    m->m_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, m->m_store, 0);
+    if (!m->m_DnsWatcher)
         return E_OUTOFMEMORY;
 
+    int rc = RTSemEventCreate(&m->m_evtStop);
+    AssertRCReturn(rc, E_FAIL);
+
+    CFRunLoopSourceContext sctx;
+    RT_ZERO(sctx);
+    sctx.perform = HostDnsServiceDarwin::Data::performShutdownCallback;
+    m->m_Stopper = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sctx);
+    AssertReturn(m->m_Stopper, E_FAIL);
+
     HRESULT hrc = HostDnsMonitor::init();
     AssertComRCReturn(hrc, hrc);
 
-    int rc = RTSemEventCreate(&g_DnsInitEvent);
-    AssertRCReturn(rc, E_FAIL);
+    return updateInfo();
+}
 
-    rc = RTThreadCreate(&g_DnsMonitoringThread, hostMonitoringRoutine,
-                        this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
-    AssertRCReturn(rc, E_FAIL);
 
-    RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
-    return updateInfo();
+void HostDnsServiceDarwin::monitorThreadShutdown()
+{
+    ALock l(this);
+    if (!m->m_fStop)
+    {
+        CFRunLoopSourceSignal(m->m_Stopper);
+        CFRunLoopWakeUp(m->m_RunLoopRef);
+        
+        RTSemEventWait(m->m_evtStop, RT_INDEFINITE_WAIT);
+    }
+}
+
+
+int HostDnsServiceDarwin::monitorWorker()
+{
+    m->m_RunLoopRef = CFRunLoopGetCurrent();
+    AssertReturn(m->m_RunLoopRef, VERR_INTERNAL_ERROR);
+
+    CFRetain(m->m_RunLoopRef);
+
+    CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
+                                                (const void **)&kStateNetworkGlobalDNSKey,
+                                                1, &kCFTypeArrayCallBacks);
+    if (!watchingArrayRef)
+    {
+        CFRelease(m->m_DnsWatcher);
+        return E_OUTOFMEMORY;
+    }
+
+    if(SCDynamicStoreSetNotificationKeys(m->m_store, watchingArrayRef, NULL))
+        CFRunLoopAddSource(CFRunLoopGetCurrent(), m->m_DnsWatcher, kCFRunLoopCommonModes);
+
+    CFRelease(watchingArrayRef);
+
+    monitorThreadInitializationDone();
+
+    while (!m->m_fStop)
+    {
+        CFRunLoopRun();
+    }
+
+    CFRelease(m->m_RunLoopRef);
+
+    /* We're notifying stopper thread. */
+    RTSemEventSignal(m->m_evtStop);
+
+    return VINF_SUCCESS;
 }
 
 
 HRESULT HostDnsServiceDarwin::updateInfo()
 {
-    CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(g_store,
+    CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(m->m_store,
                                                             kStateNetworkGlobalDNSKey);
     /**
      * 0:vvl at nb-mbp-i7-2(0)# scutil
@@ -183,7 +216,7 @@ HRESULT HostDnsServiceDarwin::updateInfo()
                                                            CFStringGetSystemEncoding());
             if (!pszServerAddress)
                 continue;
-            
+
             info.servers.push_back(std::string(pszServerAddress));
         }
     }
@@ -215,3 +248,9 @@ HRESULT HostDnsServiceDarwin::updateInfo()
 
     return S_OK;
 }
+
+void HostDnsServiceDarwin::Data::performShutdownCallback(void *info)
+{
+    HostDnsServiceDarwin::Data *pThis = static_cast<HostDnsServiceDarwin::Data *>(info);
+    pThis->m_fStop = true;
+}
diff --git a/src/VBox/Main/src-server/generic/NetIf-generic.cpp b/src/VBox/Main/src-server/generic/NetIf-generic.cpp
index f3799c3..2f99585 100644
--- a/src/VBox/Main/src-server/generic/NetIf-generic.cpp
+++ b/src/VBox/Main/src-server/generic/NetIf-generic.cpp
@@ -363,7 +363,7 @@ int NetIfGetConfig(HostNetworkInterface * /* pIf */, NETIFINFO *)
     return VERR_NOT_IMPLEMENTED;
 }
 
-int NetIfDhcpRediscover(VirtualBox * /* pVbox */, HostNetworkInterface * /* pIf */)
+int NetIfDhcpRediscover(VirtualBox * /* pVBox */, HostNetworkInterface * /* pIf */)
 {
     return VERR_NOT_IMPLEMENTED;
 }
diff --git a/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp b/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp
index 6de507e..89de18d 100644
--- a/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp
+++ b/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp
@@ -32,6 +32,8 @@
 
 #include <fcntl.h>
 
+#include <linux/limits.h>
+
 #include <sys/inotify.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -41,10 +43,12 @@
 #include "../HostDnsService.h"
 
 
-static RTTHREAD g_DnsMonitoringThread;
-static RTSEMEVENT g_DnsInitEvent;
 static int g_DnsMonitorStop[2];
 
+static const std::string g_EtcFolder = "/etc";
+static const std::string g_ResolvConf = "resolv.conf";
+static const std::string g_ResolvConfFullPath = "/etc/resolv.conf";
+
 class FileDescriptor
 {
     public:
@@ -70,50 +74,24 @@ class AutoNotify:public FileDescriptor
         FileDescriptor::fd = inotify_init();
         AssertReturnVoid(FileDescriptor::fd != -1);
     }
-
 };
 
-
-class AutoWatcher:public FileDescriptor
+struct InotifyEventWithName
 {
-    public:
-    AutoWatcher(const AutoNotify& notifier, const std::string& filename, uint32_t mask = IN_CLOSE_WRITE)
-      :name(filename)
-    {
-        nfd = notifier.fileDescriptor();
-        fd = inotify_add_watch(nfd, name.c_str(), mask);
-        AssertMsgReturnVoid(fd != -1, ("failed to add watcher %s\n", name.c_str()));
-
-        int opt = fcntl(fd, F_GETFL);
-        opt |= O_NONBLOCK;
-        fcntl(fd, F_SETFL, opt);
-    }
-
-    ~AutoWatcher()
-    {
-        int rc = inotify_rm_watch(nfd, fd);
-        AssertMsgReturnVoid(rc != -1, ("Can't detach watcher %d from %d (%d: %s)\n", nfd, fd,
-                                       errno, strerror(errno)));
-    }
-
-    private:
-    std::string name;
-    int nfd;
+    struct inotify_event e;
+    char name[NAME_MAX];
 };
 
-
 HostDnsServiceLinux::~HostDnsServiceLinux()
 {
-    send(g_DnsMonitorStop[0], "", 1, 0);
+    monitorThreadShutdown();
 }
 
 
-int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
+int HostDnsServiceLinux::monitorWorker()
 {
-    NOREF(ThreadSelf);
+
     AutoNotify a;
-    HostDnsServiceLinux *dns = static_cast<HostDnsServiceLinux *>(pvUser);
-    AutoWatcher w(a, std::string(dns->resolvConf().c_str()));
 
     int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop);
     AssertMsgReturn(rc == 0, ("socketpair: failed (%d: %s)\n", errno, strerror(errno)), E_FAIL);
@@ -130,8 +108,26 @@ int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser
     polls[1].fd = g_DnsMonitorStop[1];
     polls[1].events = POLLIN;
 
-    RTSemEventSignal(g_DnsInitEvent);
-
+    monitorThreadInitializationDone();
+
+    int wd[2];
+    wd[0] = wd[1] = -1;
+    /* inotify inialization */
+    wd[0] = inotify_add_watch(a.fileDescriptor(),
+                              g_ResolvConfFullPath.c_str(), IN_CLOSE_WRITE|IN_DELETE_SELF);
+
+    /**
+     * If /etc/resolv.conf exists we want to listen for movements: because
+     * # mv /etc/resolv.conf ...
+     * won't arm IN_DELETE_SELF on wd[0] instead it will fire IN_MOVE_FROM on wd[1].
+     *
+     * Because on some distributions /etc/resolv.conf is link, wd[0] can't detect deletion,
+     * it's recognizible on directory level (wd[1]) only.
+     */
+    wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
+                              wd[0] == -1 ? IN_MOVED_TO|IN_CREATE : IN_MOVED_FROM|IN_DELETE);
+
+    struct InotifyEventWithName combo;
     while(true)
     {
         rc = poll(polls, 2, -1);
@@ -147,33 +143,91 @@ int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser
 
         if (polls[0].revents & POLLIN)
         {
-            dns->readResolvConf();
-            /* notifyAll() takes required locks */
-            dns->notifyAll();
-
-            polls[0].revents = 0;
-
-            inotify_event ev;
-            rc = read(a.fileDescriptor(), static_cast<void *>(&ev), sizeof(ev));
-            AssertMsg(rc == sizeof(ev) && ev.wd == w.fileDescriptor(), ("Hmm, debug me"));
+            RT_ZERO(combo);
+            ssize_t r = read(polls[0].fd, static_cast<void *>(&combo), sizeof(combo));
+
+            if (combo.e.wd == wd[0])
+            {
+                if (combo.e.mask & IN_CLOSE_WRITE)
+                {
+                    readResolvConf();
+                    /* notifyAll() takes required locks */
+                    notifyAll();
+                }
+                else if (combo.e.mask & IN_DELETE_SELF)
+                {
+                    inotify_rm_watch(a.fileDescriptor(), wd[0]); /* removes file watcher */
+                    inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
+                                      IN_MOVED_TO|IN_CREATE); /* alter folder watcher */
+                }
+                else if (combo.e.mask & IN_IGNORED)
+                {
+                    wd[0] = -1; /* we want receive any events on this watch */
+                }
+                else
+                {
+                    /**
+                     * It shouldn't happen, in release we will just ignore in debug
+                     * we will have to chance to look at into inotify_event
+                     */
+                    AssertMsgFailed(("Debug Me!!!"));
+                }
+            }
+            else if (combo.e.wd == wd[1])
+            {
+                if (   combo.e.mask & IN_MOVED_FROM
+                    || combo.e.mask & IN_DELETE)
+                {
+                    if (g_ResolvConf == combo.e.name)
+                    {
+                        /**
+                         * Our file has been moved so we should change watching mode.
+                         */
+                        inotify_rm_watch(a.fileDescriptor(), wd[0]);
+                        wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
+                                                  IN_MOVED_TO|IN_CREATE);
+                        AssertMsg(wd[1] != -1,
+                                  ("It shouldn't happen, further investigation is needed\n"));
+                    }
+                }
+                else
+                {
+                    AssertMsg(combo.e.mask & (IN_MOVED_TO|IN_CREATE),
+                              ("%RX32 event isn't expected, we are waiting for IN_MOVED|IN_CREATE\n",
+                               combo.e.mask));
+                    if (g_ResolvConf == combo.e.name)
+                    {
+                        AssertMsg(wd[0] == -1, ("We haven't removed file watcher first\n"));
+
+                        /* alter folder watcher*/
+                        wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
+                                                  IN_MOVED_FROM|IN_DELETE);
+                        AssertMsg(wd[1] != -1, ("It shouldn't happen.\n"));
+
+                        wd[0] = inotify_add_watch(a.fileDescriptor(),
+                                                  g_ResolvConfFullPath.c_str(),
+                                                  IN_CLOSE_WRITE | IN_DELETE_SELF);
+                        AssertMsg(wd[0] != -1, ("Adding watcher to file (%s) has been failed!\n",
+                                                g_ResolvConfFullPath.c_str()));
+
+                        /* Notify our listeners */
+                        readResolvConf();
+                        notifyAll();
+
+                    }
+                }
+            }
+            else
+            {
+                /* It shouldn't happen */
+                AssertMsgFailed(("Shouldn't happen! Please debug me!"));
+            }
         }
     }
 }
 
 
-HRESULT HostDnsServiceLinux::init(const char *aResolvConfFileName)
+void HostDnsServiceLinux::monitorThreadShutdown()
 {
-    HRESULT hrc = HostDnsServiceResolvConf::init(aResolvConfFileName);
-    AssertComRCReturnRC(hrc);
-
-    int rc = RTSemEventCreate(&g_DnsInitEvent);
-    AssertRCReturn(rc, E_FAIL);
-
-    rc = RTThreadCreate(&g_DnsMonitoringThread, HostDnsServiceLinux::hostMonitoringRoutine,
-                        this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
-    AssertRCReturn(rc, E_FAIL);
-
-    RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
-
-    return S_OK;
+    send(g_DnsMonitorStop[0], "", 1, 0);
 }
diff --git a/src/VBox/Main/src-server/os2/NetIf-os2.cpp b/src/VBox/Main/src-server/os2/NetIf-os2.cpp
index 49fd9c1..cac174a 100644
--- a/src/VBox/Main/src-server/os2/NetIf-os2.cpp
+++ b/src/VBox/Main/src-server/os2/NetIf-os2.cpp
@@ -33,23 +33,24 @@ int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list)
     return VERR_NOT_IMPLEMENTED;
 }
 
-int NetIfEnableStaticIpConfig(VirtualBox *pVbox, HostNetworkInterface * pIf, ULONG ip, ULONG mask)
+int NetIfEnableStaticIpConfig(VirtualBox *pVBox, HostNetworkInterface * pIf, ULONG ip, ULONG mask)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-int NetIfEnableStaticIpConfigV6(VirtualBox *pVbox, HostNetworkInterface * pIf, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
+int NetIfEnableStaticIpConfigV6(VirtualBox *pVBox, HostNetworkInterface * pIf, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-int NetIfEnableDynamicIpConfig(VirtualBox *pVbox, HostNetworkInterface * pIf)
+int NetIfEnableDynamicIpConfig(VirtualBox *pVBox, HostNetworkInterface * pIf)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
 
-int NetIfDhcpRediscover(VirtualBox *pVbox, HostNetworkInterface * pIf)
+int NetIfDhcpRediscover(VirtualBox *pVBox, HostNetworkInterface * pIf)
 {
     return VERR_NOT_IMPLEMENTED;
 }
+
diff --git a/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp b/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
index ae07ad6..1bd7223 100644
--- a/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
+++ b/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
@@ -12,22 +12,66 @@
 #include <vector>
 #include "../HostDnsService.h"
 
-static HKEY g_hKeyTcpipParameters;
+struct HostDnsServiceWin::Data
+{
+    HostDnsServiceWin::Data(){}
+    HKEY hKeyTcpipParameters;
+#define DATA_DNS_UPDATE_EVENT 0
+#define DATA_SHUTDOWN_EVENT   1
+#define DATA_MAX_EVENT        2
+    HANDLE haDataEvent[DATA_MAX_EVENT];
+};
+
+static inline int registerNotification(const HKEY& hKey, HANDLE& hEvent)
+{
+    LONG lrc = RegNotifyChangeKeyValue(hKey,
+                                       TRUE,
+                                       REG_NOTIFY_CHANGE_LAST_SET,
+                                       hEvent,
+                                       TRUE);
+    AssertMsgReturn(lrc == ERROR_SUCCESS,
+                    ("Failed to register event on the key. Please debug me!"),
+                    VERR_INTERNAL_ERROR);
+
+    return VINF_SUCCESS;
+}
 
-HostDnsServiceWin::HostDnsServiceWin()
+HostDnsServiceWin::HostDnsServiceWin():HostDnsMonitor(true), m(NULL)
 {
-    RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                 TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
-                 0, KEY_READ, &g_hKeyTcpipParameters);
+    m = new Data();
+
+    m->haDataEvent[DATA_DNS_UPDATE_EVENT] = CreateEvent(NULL,
+      TRUE, FALSE, NULL);
+    AssertReleaseMsg(m->haDataEvent[DATA_DNS_UPDATE_EVENT],
+      ("Failed to create event for DNS event (%d)\n", GetLastError()));
+
+    m->haDataEvent[DATA_SHUTDOWN_EVENT] = CreateEvent(NULL,
+      TRUE, FALSE, NULL);
+    AssertReleaseMsg(m->haDataEvent[DATA_SHUTDOWN_EVENT],
+      ("Failed to create event for Shutdown signal (%d)\n", GetLastError()));
+
+    LONG lrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+      TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
+      0, KEY_READ|KEY_NOTIFY, &m->hKeyTcpipParameters);
+    AssertReleaseMsg(lrc == ERROR_SUCCESS,
+      ("Failed to open Registry Key for read and update notifications (%d)\n",
+      GetLastError()));
 }
 
 
 HostDnsServiceWin::~HostDnsServiceWin()
 {
-    if (!g_hKeyTcpipParameters)
+    if (m && !m->hKeyTcpipParameters)
     {
-        RegCloseKey(g_hKeyTcpipParameters);
-        g_hKeyTcpipParameters = 0;
+        RegCloseKey(m->hKeyTcpipParameters);
+        m->hKeyTcpipParameters = 0;
+
+        CloseHandle(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
+        CloseHandle(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
+
+        delete m;
+
+        m = NULL;
     }
 }
 
@@ -41,6 +85,55 @@ HRESULT HostDnsServiceWin::init()
 }
 
 
+void HostDnsServiceWin::monitorThreadShutdown()
+{
+    SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
+}
+
+
+int HostDnsServiceWin::monitorWorker()
+{
+    registerNotification(m->hKeyTcpipParameters,
+                         m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
+
+    monitorThreadInitializationDone();
+
+    DWORD dwRc;
+    while (true)
+    {
+        dwRc = WaitForMultipleObjects(DATA_MAX_EVENT,
+                                      m->haDataEvent,
+                                      FALSE,
+                                      INFINITE);
+        AssertMsgReturn(dwRc != WAIT_FAILED,
+                        ("WaitForMultipleObjects failed (%d) to wait! Please debug",
+                         GetLastError()), VERR_INTERNAL_ERROR);
+
+        if ((dwRc - WAIT_OBJECT_0) == DATA_DNS_UPDATE_EVENT)
+        {
+            updateInfo();
+            notifyAll();
+            ResetEvent(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
+            registerNotification(m->hKeyTcpipParameters,
+                                 m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
+
+        }
+        else if ((dwRc - WAIT_OBJECT_0) == DATA_SHUTDOWN_EVENT)
+        {
+            break;
+        }
+        else
+        {
+            AssertMsgFailedReturn(
+              ("WaitForMultipleObjects returns out of bound index %d. Please debug!",
+                                   dwRc),
+              VERR_INTERNAL_ERROR);
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
 HRESULT HostDnsServiceWin::updateInfo()
 {
     HRESULT hrc;
@@ -61,7 +154,7 @@ HRESULT HostDnsServiceWin::updateInfo()
         BYTE keyData[1024];
         DWORD cbKeyData = sizeof(keyData);
 
-        hrc = RegEnumValueA(g_hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
+        hrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
                             &keyType, keyData, &cbKeyData);
         if (   hrc == ERROR_SUCCESS
             || hrc == ERROR_MORE_DATA)
@@ -112,7 +205,6 @@ HRESULT HostDnsServiceWin::updateInfo()
 }
 
 
-
 void HostDnsServiceWin::strList2List(std::vector<std::string>& lst, char *strLst)
 {
     char *next, *current;
diff --git a/src/VBox/Main/src-server/xpcom/server_module.cpp b/src/VBox/Main/src-server/xpcom/server_module.cpp
index e557405..11cf239 100644
--- a/src/VBox/Main/src-server/xpcom/server_module.cpp
+++ b/src/VBox/Main/src-server/xpcom/server_module.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -91,8 +91,8 @@ static bool IsVBoxSVCPathSet = false;
  *  in sync with macros used for VirtualBox in server.cpp for the same purpose.
  */
 
-NS_DECL_CLASSINFO (VirtualBox)
-NS_IMPL_CI_INTERFACE_GETTER1 (VirtualBox, IVirtualBox)
+NS_DECL_CLASSINFO(VirtualBox)
+NS_IMPL_CI_INTERFACE_GETTER1(VirtualBox, IVirtualBox)
 
 static nsresult vboxsvcSpawnDaemon(void)
 {
@@ -167,8 +167,8 @@ end:
  *  VirtualBox component defined on the server.
  */
 static NS_IMETHODIMP
-VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
-                       void **aResult)
+VirtualBoxConstructor(nsISupports *aOuter, REFNSIID aIID,
+                      void **aResult)
 {
     LogFlowFuncEnter();
 
@@ -188,25 +188,25 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
         {
             /* Get the directory containing XPCOM components -- the VBoxSVC
              * executable is expected in the parent directory. */
-            nsCOMPtr <nsIProperties> dirServ = do_GetService (NS_DIRECTORY_SERVICE_CONTRACTID, &rc);
+            nsCOMPtr<nsIProperties> dirServ = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rc);
             if (NS_SUCCEEDED(rc))
             {
-                nsCOMPtr <nsIFile> componentDir;
-                rc = dirServ->Get (NS_XPCOM_COMPONENT_DIR,
-                                   NS_GET_IID (nsIFile), getter_AddRefs (componentDir));
+                nsCOMPtr<nsIFile> componentDir;
+                rc = dirServ->Get(NS_XPCOM_COMPONENT_DIR,
+                                  NS_GET_IID(nsIFile), getter_AddRefs(componentDir));
 
                 if (NS_SUCCEEDED(rc))
                 {
                     nsCAutoString path;
-                    componentDir->GetNativePath (path);
+                    componentDir->GetNativePath(path);
 
-                    LogFlowFunc (("component directory = \"%s\"\n", path.get()));
-                    AssertBreakStmt (path.Length() + strlen (VBoxSVC_exe) < RTPATH_MAX,
-                                     rc = NS_ERROR_FAILURE);
+                    LogFlowFunc(("component directory = \"%s\"\n", path.get()));
+                    AssertBreakStmt(path.Length() + strlen(VBoxSVC_exe) < RTPATH_MAX,
+                                    rc = NS_ERROR_FAILURE);
 
 #if defined(RT_OS_SOLARIS) && defined(VBOX_WITH_HARDENING)
                     char achKernArch[128];
-                    int cbKernArch = sysinfo (SI_ARCHITECTURE_K, achKernArch, sizeof(achKernArch));
+                    int cbKernArch = sysinfo(SI_ARCHITECTURE_K, achKernArch, sizeof(achKernArch));
                     if (cbKernArch > 0)
                     {
                         sprintf(VBoxSVCPath, "/opt/VirtualBox/%s%s", achKernArch, VBoxSVC_exe);
@@ -215,9 +215,9 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
                     else
                         rc = NS_ERROR_UNEXPECTED;
 #else
-                    strcpy (VBoxSVCPath, path.get());
-                    RTPathStripFilename (VBoxSVCPath);
-                    strcat (VBoxSVCPath, VBoxSVC_exe);
+                    strcpy(VBoxSVCPath, path.get());
+                    RTPathStripFilename(VBoxSVCPath);
+                    strcat(VBoxSVCPath, VBoxSVC_exe);
 
                     IsVBoxSVCPathSet = true;
 #endif
@@ -227,7 +227,7 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
                 break;
         }
 
-        nsCOMPtr <ipcIService> ipcServ = do_GetService (IPC_SERVICE_CONTRACTID, &rc);
+        nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
         if (NS_FAILED(rc))
             break;
 
@@ -238,13 +238,13 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
 
         do
         {
-            LogFlowFunc (("Resolving server name \"%s\"...\n", VBOXSVC_IPC_NAME));
+            LogFlowFunc(("Resolving server name \"%s\"...\n", VBOXSVC_IPC_NAME));
 
             PRUint32 serverID = 0;
-            rc = ipcServ->ResolveClientName (VBOXSVC_IPC_NAME, &serverID);
+            rc = ipcServ->ResolveClientName(VBOXSVC_IPC_NAME, &serverID);
             if (NS_FAILED(rc))
             {
-                LogFlowFunc (("Starting server \"%s\"...\n", VBoxSVCPath));
+                LogFlowFunc(("Starting server \"%s\"...\n", VBoxSVCPath));
 
                 startedOnce = true;
 
@@ -255,8 +255,8 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
                 /* wait for the server process to establish a connection */
                 do
                 {
-                    RTThreadSleep (VBoxSVC_WaitSlice);
-                    rc = ipcServ->ResolveClientName (VBOXSVC_IPC_NAME, &serverID);
+                    RTThreadSleep(VBoxSVC_WaitSlice);
+                    rc = ipcServ->ResolveClientName(VBOXSVC_IPC_NAME, &serverID);
                     if (NS_SUCCEEDED(rc))
                         break;
                     if (timeLeft <= VBoxSVC_WaitSlice)
@@ -275,20 +275,20 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
                 }
             }
 
-            LogFlowFunc (("Connecting to server (ID=%d)...\n", serverID));
+            LogFlowFunc(("Connecting to server (ID=%d)...\n", serverID));
 
-            nsCOMPtr <ipcIDConnectService> dconServ =
-                do_GetService (IPC_DCONNECTSERVICE_CONTRACTID, &rc);
+            nsCOMPtr<ipcIDConnectService> dconServ =
+                do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
             if (NS_FAILED(rc))
                 break;
 
-            rc = dconServ->CreateInstance (serverID,
-                                           CLSID_VirtualBox,
-                                           aIID, aResult);
+            rc = dconServ->CreateInstance(serverID,
+                                          CLSID_VirtualBox,
+                                          aIID, aResult);
             if (NS_SUCCEEDED(rc))
                 break;
 
-            LogFlowFunc (("Failed to connect (rc=%Rhrc (%#08x))\n", rc, rc));
+            LogFlowFunc(("Failed to connect (rc=%Rhrc (%#08x))\n", rc, rc));
 
             /* It's possible that the server gets shut down after we
              * successfully resolve the server name but before it
@@ -297,12 +297,11 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
             if (!startedOnce)
             {
                 nsresult rc2 =
-                    ipcServ->ResolveClientName (VBOXSVC_IPC_NAME, &serverID);
+                    ipcServ->ResolveClientName(VBOXSVC_IPC_NAME, &serverID);
                 if (NS_SUCCEEDED(rc2))
                     break;
 
-                LogFlowFunc (("Server seems to have terminated before "
-                              "receiving our request. Will try again.\n"));
+                LogFlowFunc(("Server seems to have terminated before receiving our request. Will try again.\n"));
             }
             else
                 break;
@@ -311,7 +310,7 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
     }
     while (0);
 
-    LogFlowFunc (("rc=%Rhrc (%#08x), vrc=%Rrc\n", rc, rc, vrc));
+    LogFlowFunc(("rc=%Rhrc (%#08x), vrc=%Rrc\n", rc, rc, vrc));
     LogFlowFuncLeave();
 
     return rc;
@@ -330,19 +329,19 @@ VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
  * @return
  */
 static NS_IMETHODIMP
-VirtualBoxRegistration (nsIComponentManager *aCompMgr,
-                        nsIFile *aPath,
-                        const char *aLoaderStr,
-                        const char *aType,
-                        const nsModuleComponentInfo *aInfo)
+VirtualBoxRegistration(nsIComponentManager *aCompMgr,
+                       nsIFile *aPath,
+                       const char *aLoaderStr,
+                       const char *aType,
+                       const nsModuleComponentInfo *aInfo)
 {
     nsCAutoString modulePath;
-    aPath->GetNativePath (modulePath);
+    aPath->GetNativePath(modulePath);
     nsCAutoString moduleTarget;
-    aPath->GetNativeTarget (moduleTarget);
+    aPath->GetNativeTarget(moduleTarget);
 
-    LogFlowFunc (("aPath=%s, aTarget=%s, aLoaderStr=%s, aType=%s\n",
-                  modulePath.get(), moduleTarget.get(), aLoaderStr, aType));
+    LogFlowFunc(("aPath=%s, aTarget=%s, aLoaderStr=%s, aType=%s\n",
+                 modulePath.get(), moduleTarget.get(), aLoaderStr, aType));
 
     nsresult rc = NS_OK;
 
@@ -371,4 +370,4 @@ static const nsModuleComponentInfo components[] =
     }
 };
 
-NS_IMPL_NSGETMODULE (VirtualBox_Server_Module, components)
+NS_IMPL_NSGETMODULE(VirtualBox_Server_Module, components)
diff --git a/src/VBox/Main/testcase/tstAPI.cpp b/src/VBox/Main/testcase/tstAPI.cpp
index 6a4b210..a18499e 100644
--- a/src/VBox/Main/testcase/tstAPI.cpp
+++ b/src/VBox/Main/testcase/tstAPI.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -24,7 +24,6 @@
 #include <VBox/com/Guid.h>
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
 
 #include <VBox/com/VirtualBox.h>
 
@@ -369,11 +368,6 @@ int main(int argc, char *argv[])
     }
 #endif
 
-    // create the event queue
-    // (here it is necessary only to process remaining XPCOM/IPC events
-    // after the session is closed)
-    EventQueue eventQ;
-
 #if 0
     // the simplest COM API test
     ////////////////////////////////////////////////////////////////////////////
diff --git a/src/VBox/Main/testcase/tstOVF.cpp b/src/VBox/Main/testcase/tstOVF.cpp
index e2ad124..de8c808 100644
--- a/src/VBox/Main/testcase/tstOVF.cpp
+++ b/src/VBox/Main/testcase/tstOVF.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2010-2013 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -23,7 +23,6 @@
 #include <VBox/com/string.h>
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
 
 #include <iprt/initterm.h>
 #include <iprt/stream.h>
@@ -116,12 +115,12 @@ void importOVF(const char *pcszPrefix,
         com::SafeArray<VirtualSystemDescriptionType_T> aTypes;
         com::SafeArray<BSTR> aRefs;
         com::SafeArray<BSTR> aOvfValues;
-        com::SafeArray<BSTR> aVboxValues;
+        com::SafeArray<BSTR> aVBoxValues;
         com::SafeArray<BSTR> aExtraConfigValues;
         rc = pVSys->GetDescription(ComSafeArrayAsOutParam(aTypes),
                                    ComSafeArrayAsOutParam(aRefs),
                                    ComSafeArrayAsOutParam(aOvfValues),
-                                   ComSafeArrayAsOutParam(aVboxValues),
+                                   ComSafeArrayAsOutParam(aVBoxValues),
                                    ComSafeArrayAsOutParam(aExtraConfigValues));
         if (FAILED(rc)) throw MyError(rc, "VirtualSystemDescription::GetDescription() failed\n");
 
@@ -226,7 +225,7 @@ void importOVF(const char *pcszPrefix,
             RTPrintf("  vsys %2u item %2u: type %2d (%s), ovf: \"%ls\", vbox: \"%ls\", extra: \"%ls\"\n",
                      u, u2, t, pcszType,
                      aOvfValues[u2],
-                     aVboxValues[u2],
+                     aVBoxValues[u2],
                      aExtraConfigValues[u2]);
         }
     }
@@ -305,10 +304,6 @@ int main(int argc, char *argv[])
         rc = pSession.createInprocObject(CLSID_Session);
         if (FAILED(rc)) throw MyError(rc, "failed to create a session object!\n");
 
-        // create the event queue
-        // (here it is necessary only to process remaining XPCOM/IPC events after the session is closed)
-        EventQueue eventQ;
-
         // for each testcase, we will copy the dummy VMDK image to the subdirectory with the OVF testcase
         // so that the import will find the disks it expects; this is just for testing the import since
         // the imported machines will obviously not be usable.
diff --git a/src/VBox/Main/testcase/tstVBoxAPIXPCOM.cpp b/src/VBox/Main/testcase/tstVBoxAPIXPCOM.cpp
index 8374491..1ea16f6 100644
--- a/src/VBox/Main/testcase/tstVBoxAPIXPCOM.cpp
+++ b/src/VBox/Main/testcase/tstVBoxAPIXPCOM.cpp
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -79,7 +79,6 @@
 #include <VBox/com/Guid.h>
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
 
 #include <VBox/com/VirtualBox.h>
 
diff --git a/src/VBox/Main/webservice/websrv-cpp.xsl b/src/VBox/Main/webservice/websrv-cpp.xsl
index 0347658..32372e7 100644
--- a/src/VBox/Main/webservice/websrv-cpp.xsl
+++ b/src/VBox/Main/webservice/websrv-cpp.xsl
@@ -11,7 +11,7 @@
         See webservice/Makefile.kmk for an overview of all the things
         generated for the webservice.
 
-    Copyright (C) 2007-2013 Oracle Corporation
+    Copyright (C) 2007-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -65,7 +65,6 @@
 #include <VBox/com/array.h>
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
 #include <VBox/VBoxAuth.h>
 
 #include <iprt/assert.h>
diff --git a/src/VBox/Main/webservice/websrv-php.xsl b/src/VBox/Main/webservice/websrv-php.xsl
index aac27e1..42591dc 100644
--- a/src/VBox/Main/webservice/websrv-php.xsl
+++ b/src/VBox/Main/webservice/websrv-php.xsl
@@ -11,7 +11,7 @@
 
      Contributed by James Lucas (mjlucas at eng.uts.edu.au).
 
-    Copyright (C) 2008-2013 Oracle Corporation
+    Copyright (C) 2008-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -168,7 +168,7 @@
  */
 </xsl:text>
    <xsl:choose>
-      <xsl:when test="($extends = '$unknown') or ($extends = '$dispatched') or ($extends = '$errorinfo')">
+      <xsl:when test="($extends = '$unknown') or ($extends = '$errorinfo')">
          <xsl:value-of select="concat('class ', $ifname, ' extends VBox_ManagedObject
{
')" />
       </xsl:when>
       <xsl:when test="//interface[@name=$extends]">
@@ -360,7 +360,7 @@ class <xsl:value-of select="$ifname"/>Collection extends VBox_EnumCollection
 <xsl:text><?php
 
 /*
- * Copyright (C) 2008-2013 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * This file is part of a free software library; you can redistribute
  * it and/or modify it under the terms of the GNU Lesser General
diff --git a/src/VBox/Main/webservice/websrv-python.xsl b/src/VBox/Main/webservice/websrv-python.xsl
index f9d9be6..0198459 100644
--- a/src/VBox/Main/webservice/websrv-python.xsl
+++ b/src/VBox/Main/webservice/websrv-python.xsl
@@ -9,7 +9,7 @@
         VirtualBox.xidl. This Python file represents our
         web service API. Depends on WSDL file for actual SOAP bindings.
 
-    Copyright (C) 2008-2013 Oracle Corporation
+    Copyright (C) 2008-2014 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
     available from http://www.virtualbox.org. This file is free software;
@@ -51,7 +51,6 @@
     <xsl:when test="$type='result'">UnsignedInt</xsl:when>
     <xsl:when test="$type='octet'">Octet</xsl:when>
     <xsl:when test="$type='$unknown'">IUnknown</xsl:when>
-    <xsl:when test="$type='$dispatched'">IUnknown</xsl:when>
     <xsl:otherwise><xsl:value-of select="$type" /></xsl:otherwise>
   </xsl:choose>
 </xsl:template>
@@ -148,7 +147,7 @@ class <xsl:value-of select="$cname"/>:
   <xsl:param name="base" />
 
   <xsl:choose>
-    <xsl:when test="($base = '$unknown') or ($base = '$dispatched')">
+    <xsl:when test="($base = '$unknown')">
       <xsl:value-of select="'IUnknown'"/>
     </xsl:when>
     <xsl:when test="($base = '$errorinfo') ">
@@ -468,7 +467,7 @@ class <xsl:value-of select="@name"/>:
 </xsl:template>
 
 <xsl:template match="/">
-<xsl:text># Copyright (C) 2008-2011 Oracle Corporation
+<xsl:text># Copyright (C) 2008-2014 Oracle Corporation
 #
 # This file is part of a free software library; you can redistribute
 # it and/or modify it under the terms of the GNU Lesser General
diff --git a/src/VBox/Main/xml/Settings.cpp b/src/VBox/Main/xml/Settings.cpp
index 88cd197..3520c9c 100644
--- a/src/VBox/Main/xml/Settings.cpp
+++ b/src/VBox/Main/xml/Settings.cpp
@@ -2868,6 +2868,8 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
                 GraphicsControllerType_T type;
                 if (strGraphicsControllerType == "VBOXVGA")
                     type = GraphicsControllerType_VBoxVGA;
+                else if (strGraphicsControllerType == "VMSVGA")
+                    type = GraphicsControllerType_VMSVGA;
                 else if (strGraphicsControllerType == "NONE")
                     type = GraphicsControllerType_Null;
                 else
@@ -4125,6 +4127,7 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
         switch (hw.graphicsControllerType)
         {
             case GraphicsControllerType_VBoxVGA:            pcszGraphics = "VBoxVGA"; break;
+            case GraphicsControllerType_VMSVGA:             pcszGraphics = "VMSVGA"; break;
             default: /*case GraphicsControllerType_Null:*/  pcszGraphics = "None"; break;
         }
         pelmDisplay->setAttribute("controller", pcszGraphics);
@@ -5103,7 +5106,7 @@ void MachineConfigFile::buildSnapshotXML(uint32_t depth,
  *      that, if snapshots are present. Otherwise all snapshots are suppressed
  *      (when called from OVF).
  *
- *  --  BuildMachineXML_WriteVboxVersionAttribute: If set, add a settingsVersion
+ *  --  BuildMachineXML_WriteVBoxVersionAttribute: If set, add a settingsVersion
  *      attribute to the machine tag with the vbox settings version. This is for
  *      the OVF export case in which we don't have the settings version set in
  *      the root element.
@@ -5127,7 +5130,7 @@ void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
                                         uint32_t fl,
                                         std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
 {
-    if (fl & BuildMachineXML_WriteVboxVersionAttribute)
+    if (fl & BuildMachineXML_WriteVBoxVersionAttribute)
         // add settings version attribute to machine element
         setVersionAttribute(elmMachine);
 
@@ -5764,7 +5767,7 @@ void MachineConfigFile::write(const com::Utf8Str &strFilename)
         buildMachineXML(*pelmMachine,
                           MachineConfigFile::BuildMachineXML_IncludeSnapshots
                         | MachineConfigFile::BuildMachineXML_MediaRegistry,
-                            // but not BuildMachineXML_WriteVboxVersionAttribute
+                            // but not BuildMachineXML_WriteVBoxVersionAttribute
                         NULL); /* pllElementsWithUuidAttributes */
 
         // now go write the XML
diff --git a/src/VBox/Main/xml/ovfreader.cpp b/src/VBox/Main/xml/ovfreader.cpp
index a000195..3762083 100644
--- a/src/VBox/Main/xml/ovfreader.cpp
+++ b/src/VBox/Main/xml/ovfreader.cpp
@@ -226,7 +226,7 @@ void OVFReader::HandleDiskSection(const xml::ElementNode *pReferencesElem,
                 d.iPopulatedSize = -1;
 
             // optional vbox:uuid attribute (if OVF was exported by VirtualBox != 3.2)
-            pelmDisk->getAttributeValue("uuid", d.uuidVbox, "vbox");
+            pelmDisk->getAttributeValue("uuid", d.uuidVBox, "vbox");
 
             const char *pcszFileRef;
             if (pelmDisk->getAttributeValue("fileRef", pcszFileRef)) // optional
@@ -330,7 +330,7 @@ void OVFReader::HandleVirtualSystemContent(const xml::ElementNode *pelmVirtualSy
 
     // peek under the <VirtualSystem> node whether we have a <vbox:Machine> node;
     // that case case, the caller can completely ignore the OVF but only load the VBox machine XML
-    vsys.pelmVboxMachine = pelmVirtualSystem->findChildElementNS("vbox", "Machine");
+    vsys.pelmVBoxMachine = pelmVirtualSystem->findChildElementNS("vbox", "Machine");
 
     // now look for real OVF
     const xml::AttributeNode *pIdAttr = pelmVirtualSystem->findAttribute("id");
@@ -346,7 +346,7 @@ void OVFReader::HandleVirtualSystemContent(const xml::ElementNode *pelmVirtualSy
         if (!strcmp(pcszElemName, "Section"))       // OVF 0.9 used "Section" element always with a varying "type" attribute
         {
             const xml::AttributeNode *pTypeAttr = pelmThis->findAttribute("type");
-            if (!pTypeAttr)
+            if (pTypeAttr)
                 pcszTypeAttr = pTypeAttr->getValue();
             else
                 throw OVFLogicError(N_("Error reading \"%s\": element \"Section\" has no \"type\" attribute, line %d"),
@@ -808,7 +808,7 @@ void OVFReader::HandleVirtualSystemContent(const xml::ElementNode *pelmVirtualSy
             const xml::ElementNode *pelmVBoxOSType;
             if ((pelmVBoxOSType = pelmThis->findChildElementNS("vbox",            // namespace
                                                                "OSType")))        // element name
-                vsys.strTypeVbox = pelmVBoxOSType->getValue();
+                vsys.strTypeVBox = pelmVBoxOSType->getValue();
         }
         else if (    (!strcmp(pcszElemName, "AnnotationSection"))
                   || (!strcmp(pcszTypeAttr, "ovf:AnnotationSection_Type"))
diff --git a/src/VBox/NetworkServices/DHCP/ClientDataInt.h b/src/VBox/NetworkServices/DHCP/ClientDataInt.h
new file mode 100644
index 0000000..3c544ef
--- /dev/null
+++ b/src/VBox/NetworkServices/DHCP/ClientDataInt.h
@@ -0,0 +1,67 @@
+/* $Id: ClientDataInt.h $ */
+/** @file
+ * Config.h
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __CLIENT_DATA_INT_H__
+#define __CLIENT_DATA_INT_H__
+
+class ClientData
+{
+public:
+    ClientData()
+    {
+        m_address.u = 0;
+        m_network.u = 0;
+        fHasLease = false;
+        fHasClient = false;
+        fBinding = true;
+        u64TimestampBindingStarted = 0;
+        u64TimestampLeasingStarted = 0;
+        u32LeaseExpirationPeriod = 0;
+        u32BindExpirationPeriod = 0;
+        pCfg = NULL;
+
+    }
+    ~ClientData(){}
+
+    /* client information */
+    RTNETADDRIPV4 m_address;
+    RTNETADDRIPV4 m_network;
+    RTMAC m_mac;
+
+    bool fHasClient;
+
+    /* Lease part */
+    bool fHasLease;
+    /** lease isn't commited */
+    bool fBinding;
+
+    /** Timestamp when lease commited. */
+    uint64_t u64TimestampLeasingStarted;
+    /** Period when lease is expired in secs. */
+    uint32_t u32LeaseExpirationPeriod;
+
+    /** timestamp when lease was bound */
+    uint64_t u64TimestampBindingStarted;
+    /* Period when binding is expired in secs. */
+    uint32_t u32BindExpirationPeriod;
+
+    MapOptionId2RawOption options;
+
+    NetworkConfigEntity *pCfg;
+};
+
+#endif
diff --git a/src/VBox/NetworkServices/DHCP/Config.cpp b/src/VBox/NetworkServices/DHCP/Config.cpp
index 8ebb528..2c76b5e 100644
--- a/src/VBox/NetworkServices/DHCP/Config.cpp
+++ b/src/VBox/NetworkServices/DHCP/Config.cpp
@@ -1,10 +1,27 @@
 /* $Id: Config.cpp $ */
+/** @file
+ * Configuration for DHCP.
+ */
+
+/*
+ * Copyright (C) 2013-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
 
 /**
  * XXX: license.
  */
 
 #include <iprt/asm.h>
+#include <iprt/getopt.h>
 #include <iprt/net.h>
 #include <iprt/time.h>
 
@@ -18,6 +35,8 @@
 
 #include <iprt/cpp/xml.h>
 
+#define BASE_SERVICES_ONLY
+#include "../NetLib/VBoxNetBaseService.h"
 #include "../NetLib/VBoxNetLib.h"
 #include "../NetLib/shared_ptr.h"
 
@@ -27,54 +46,7 @@
 #include <string>
 
 #include "Config.h"
-
-/* types */
-class ClientData
-{
-public:
-    ClientData()
-    {
-        m_address.u = 0;
-        m_network.u = 0;
-        fHasLease = false;
-        fHasClient = false;
-        fBinding = true;
-        u64TimestampBindingStarted = 0;
-        u64TimestampLeasingStarted = 0;
-        u32LeaseExpirationPeriod = 0;
-        u32BindExpirationPeriod = 0;
-        pCfg = NULL;
-
-    }
-    ~ClientData(){}
-    
-    /* client information */
-    RTNETADDRIPV4 m_address;
-    RTNETADDRIPV4 m_network;
-    RTMAC m_mac;
-    
-    bool fHasClient;
-
-    /* Lease part */
-    bool fHasLease; 
-    /** lease isn't commited */
-    bool fBinding;
-
-    /** Timestamp when lease commited. */
-    uint64_t u64TimestampLeasingStarted;
-    /** Period when lease is expired in secs. */
-    uint32_t u32LeaseExpirationPeriod;
-
-    /** timestamp when lease was bound */
-    uint64_t u64TimestampBindingStarted;
-    /* Period when binding is expired in secs. */
-    uint32_t u32BindExpirationPeriod;
-
-    MapOptionId2RawOption options;
-
-    NetworkConfigEntity *pCfg;
-};
-
+#include "ClientDataInt.h"
 
 bool operator== (const Lease& lhs, const Lease& rhs)
 {
@@ -103,6 +75,12 @@ static ConfigurationManager *g_ConfigurationManager = ConfigurationManager::getC
 
 static NetworkManager *g_NetworkManager = NetworkManager::getNetworkManager();
 
+bool MACClientMatchCriteria::check(const Client& client) const
+{
+    return (client == m_mac);
+}
+
+
 int BaseConfigEntity::match(Client& client, BaseConfigEntity **cfg)
 {
     int iMatch = (m_criteria && m_criteria->check(client)? m_MatchLevel: 0);
@@ -165,10 +143,10 @@ struct ConfigurationManager::Data
 
     std::string          m_domainName;
     VecClient            m_clients;
-    std::string          m_leaseStorageFilename;
+    com::Utf8Str         m_leaseStorageFilename;
     bool                 fFileExists;
 };
-    
+
 ConfigurationManager *ConfigurationManager::getConfigurationManager()
 {
     if (!g_ConfigurationManager)
@@ -208,10 +186,10 @@ const std::string tagXMLLeaseOptions = "Options";
  *   </Lease>
  * </Leases>
  */
-int ConfigurationManager::loadFromFile(const std::string& leaseStorageFileName)
+int ConfigurationManager::loadFromFile(const com::Utf8Str& leaseStorageFileName)
 {
     m->m_leaseStorageFilename = leaseStorageFileName;
-    
+
     xml::XmlFileParser parser;
     xml::Document doc;
 
@@ -245,10 +223,10 @@ int ConfigurationManager::loadFromFile(const std::string& leaseStorageFileName)
     {
         if (!lease->nameEquals(tagXMLLease.c_str()))
             continue;
-        
+
         ClientData *data = new ClientData();
         Lease l(data);
-        if (l.fromXML(lease)) 
+        if (l.fromXML(lease))
         {
 
             m->m_allocations.insert(MapLease2Ip4AddressPair(l, l.getAddress()));
@@ -271,7 +249,7 @@ int ConfigurationManager::loadFromFile(const std::string& leaseStorageFileName)
 
 int ConfigurationManager::saveToFile()
 {
-    if (m->m_leaseStorageFilename.empty())
+    if (m->m_leaseStorageFilename.isEmpty())
         return VINF_SUCCESS;
 
     xml::Document doc;
@@ -279,7 +257,7 @@ int ConfigurationManager::saveToFile()
     xml::ElementNode *root = doc.createRootElement(tagXMLLeases.c_str());
     if (!root)
         return VERR_INTERNAL_ERROR;
-    
+
     root->setAttribute(tagXMLLeasesAttributeVersion.c_str(), tagXMLLeasesVersion_1_0.c_str());
 
     for(MapLease2Ip4AddressConstIterator it = m->m_allocations.begin();
@@ -425,7 +403,7 @@ Lease ConfigurationManager::allocateLease4Client(const Client& client, PCRTNETBO
         const Lease l = client.lease();
         if (l != Lease::NullLease)
         {
-            /* Here we should take lease from the m_allocation which was feed with leases 
+            /* Here we should take lease from the m_allocation which was feed with leases
              *  on start
              */
             if (l.isExpired())
@@ -513,7 +491,7 @@ int ConfigurationManager::expireLease4Client(Client& client)
 {
     Lease l = client.lease();
     AssertReturn(l != Lease::NullLease, VERR_INTERNAL_ERROR);
-    
+
     if (l.isInBindingPhase())
     {
 
@@ -528,11 +506,12 @@ int ConfigurationManager::expireLease4Client(Client& client)
         l.expire();
         return VINF_SUCCESS;
     }
-    
+
     l = Lease(client); /* re-new */
     return VINF_SUCCESS;
 }
 
+
 bool ConfigurationManager::isAddressTaken(const RTNETADDRIPV4& addr, Lease& lease)
 {
     MapLease2Ip4AddressIterator it;
@@ -554,6 +533,13 @@ bool ConfigurationManager::isAddressTaken(const RTNETADDRIPV4& addr, Lease& leas
 }
 
 
+bool ConfigurationManager::isAddressTaken(const RTNETADDRIPV4& addr)
+{
+    Lease ignore;
+    return isAddressTaken(addr, ignore);
+}
+
+
 NetworkConfigEntity *ConfigurationManager::addNetwork(NetworkConfigEntity *,
                                     const RTNETADDRIPV4& networkId,
                                     const RTNETADDRIPV4& netmask,
@@ -697,9 +683,7 @@ struct NetworkManager::Data
     {
         RT_ZERO(BootPReplyMsg);
         cbBooPReplyMsg = 0;
-        
-        m_pSession = NIL_RTR0PTR;
-        m_pIfBuf = NULL;
+
         m_OurAddress.u = 0;
         m_OurNetmask.u = 0;
         RT_ZERO(m_OurMac);
@@ -711,14 +695,10 @@ struct NetworkManager::Data
     } BootPReplyMsg;
     int cbBooPReplyMsg;
 
-    /* XXX: artifacts should be hidden or removed from here. */
-    PSUPDRVSESSION m_pSession;
-    INTNETIFHANDLE m_hIf;
-    PINTNETBUF m_pIfBuf;
-
     RTNETADDRIPV4 m_OurAddress;
     RTNETADDRIPV4 m_OurNetmask;
     RTMAC m_OurMac;
+    const VBoxNetHlpUDPService *m_service;
 };
 
 
@@ -744,6 +724,47 @@ NetworkManager *NetworkManager::getNetworkManager()
 }
 
 
+const RTNETADDRIPV4& NetworkManager::getOurAddress() const
+{
+    return m->m_OurAddress;
+}
+
+
+const RTNETADDRIPV4& NetworkManager::getOurNetmask() const
+{
+    return m->m_OurNetmask;
+}
+
+
+const RTMAC& NetworkManager::getOurMac() const
+{
+    return m->m_OurMac;
+}
+
+
+void NetworkManager::setOurAddress(const RTNETADDRIPV4& aAddress)
+{
+    m->m_OurAddress = aAddress;
+}
+
+
+void NetworkManager::setOurNetmask(const RTNETADDRIPV4& aNetmask)
+{
+    m->m_OurNetmask = aNetmask;
+}
+
+
+void NetworkManager::setOurMac(const RTMAC& aMac)
+{
+    m->m_OurMac = aMac;
+}
+
+
+void NetworkManager::setService(const VBoxNetHlpUDPService *srv)
+{
+    m->m_service = srv;
+}
+
 /**
  * Network manager creates DHCPOFFER datagramm
  */
@@ -767,7 +788,7 @@ int NetworkManager::offer4Client(const Client& client, uint32_t u32Xid,
     RawOption opt;
     RT_ZERO(opt);
 
-    std::vector<RawOption> extra(2);
+    std::vector<RawOption> extra;
     opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
     opt.au8RawOpt[0] = RTNET_DHCP_MT_OFFER;
     opt.cbRawOpt = 1;
@@ -783,12 +804,11 @@ int NetworkManager::offer4Client(const Client& client, uint32_t u32Xid,
 
     extra.push_back(opt);
 
-    processParameterReqList(client, pu8ReqList, cReqList);
+    processParameterReqList(client, pu8ReqList, cReqList, extra);
 
     return doReply(client, extra);
 }
 
-
 /**
  * Network manager creates DHCPACK
  */
@@ -798,7 +818,7 @@ int NetworkManager::ack(const Client& client, uint32_t u32Xid,
     RTNETADDRIPV4 address;
 
     prepareReplyPacket4Client(client, u32Xid);
-    
+
     Lease l = client.lease();
     address = l.getAddress();
     m->BootPReplyMsg.BootPHeader.bp_ciaddr =  address;
@@ -821,7 +841,7 @@ int NetworkManager::ack(const Client& client, uint32_t u32Xid,
     RawOption opt;
     RT_ZERO(opt);
 
-    std::vector<RawOption> extra(2);
+    std::vector<RawOption> extra;
     opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
     opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK;
     opt.cbRawOpt = 1;
@@ -836,12 +856,11 @@ int NetworkManager::ack(const Client& client, uint32_t u32Xid,
     opt.cbRawOpt = sizeof(RTNETADDRIPV4);
     extra.push_back(opt);
 
-    processParameterReqList(client, pu8ReqList, cReqList);
+    processParameterReqList(client, pu8ReqList, cReqList, extra);
 
     return doReply(client, extra);
 }
 
-
 /**
  * Network manager creates DHCPNAK
  */
@@ -874,60 +893,6 @@ int NetworkManager::nak(const Client& client, uint32_t u32Xid)
     return doReply(client, extra);
 }
 
-
-const RTNETADDRIPV4& NetworkManager::getOurAddress() const
-{
-    return m->m_OurAddress;
-}
-
-
-const RTNETADDRIPV4& NetworkManager::getOurNetmask() const
-{
-    return m->m_OurNetmask;
-}
-
-
-const RTMAC& NetworkManager::getOurMac() const
-{
-    return m->m_OurMac;
-}
-
-
-void NetworkManager::setOurAddress(const RTNETADDRIPV4& aAddress)
-{
-    m->m_OurAddress = aAddress;
-}
-
-
-void NetworkManager::setOurNetmask(const RTNETADDRIPV4& aNetmask)
-{
-    m->m_OurNetmask = aNetmask;
-}
-
-
-void NetworkManager::setOurMac(const RTMAC& aMac)
-{
-    m->m_OurMac = aMac;
-}
-
-
-void NetworkManager::setSession(PSUPDRVSESSION aSession)
-{
-    m->m_pSession = aSession;
-}
-
-
-void NetworkManager::setInterface(INTNETIFHANDLE aIf)
-{
-    m->m_hIf = aIf;
-}
-
-
-void NetworkManager::setRingBuffer(PINTNETBUF aBuf)
-{
-    m->m_pIfBuf = aBuf;
-}
-
 /**
  *
  */
@@ -976,10 +941,10 @@ int NetworkManager::doReply(const Client& client, const std::vector<RawOption>&
 
     Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m->m_OurAddress);
 
-    const Lease l = client.lease(); 
+    const Lease l = client.lease();
     const std::map<uint8_t, RawOption>& options = l.options();
 
-    for(std::vector<RawOption>::const_iterator it = extra.begin(); 
+    for(std::vector<RawOption>::const_iterator it = extra.begin();
         it != extra.end(); ++it)
     {
         if (!Cursor.begin(it->u8OptId, it->cbRawOpt))
@@ -988,7 +953,7 @@ int NetworkManager::doReply(const Client& client, const std::vector<RawOption>&
 
     }
 
-    for(std::map<uint8_t, RawOption>::const_iterator it = options.begin(); 
+    for(std::map<uint8_t, RawOption>::const_iterator it = options.begin();
         it != options.end(); ++it)
     {
         if (!Cursor.begin(it->second.u8OptId, it->second.cbRawOpt))
@@ -1003,7 +968,7 @@ int NetworkManager::doReply(const Client& client, const std::vector<RawOption>&
      */
 #if 0
     /** @todo need to see someone set this flag to check that it's correct. */
-    if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST))  
+    if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST))
     {
         rc = VBoxNetUDPUnicast(m_pSession,
                                m_hIf,
@@ -1018,14 +983,10 @@ int NetworkManager::doReply(const Client& client, const std::vector<RawOption>&
     }
     else
 #endif
-        rc = VBoxNetUDPBroadcast(m->m_pSession,
-                                 m->m_hIf,
-                                 m->m_pIfBuf,
-                                 m->m_OurAddress,
-                                 &m->m_OurMac,
-                                 RTNETIPV4_PORT_BOOTPS,               /* sender */
-                                 RTNETIPV4_PORT_BOOTPC,
-                                 &m->BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
+        rc = m->m_service->hlpUDPBroadcast(RTNETIPV4_PORT_BOOTPS,               /* sender */
+                                           RTNETIPV4_PORT_BOOTPC,
+                                           &m->BootPReplyMsg,
+                                           RTNET_DHCP_NORMAL_SIZE);
 
     AssertRCReturn(rc,rc);
 
@@ -1033,27 +994,24 @@ int NetworkManager::doReply(const Client& client, const std::vector<RawOption>&
 }
 
 
-int NetworkManager::processParameterReqList(const Client& client, uint8_t *pu8ReqList, int cReqList)
+int NetworkManager::processParameterReqList(const Client& client, const uint8_t *pu8ReqList, 
+                                            int cReqList, std::vector<RawOption>& extra)
 {
-    /* request parameter list */
-    RawOption opt;
-    int idxParam = 0;
+    const Lease l = client.lease();
 
-    uint8_t *pReqList = pu8ReqList;
-    
-    const Lease const_l = client.lease();
-    Lease l = Lease(const_l);
-    
     const NetworkConfigEntity *pNetCfg = l.getConfig();
 
-    for (idxParam = 0; idxParam < cReqList; ++idxParam)
+    /* request parameter list */
+    RawOption opt;
+    bool fIgnore;
+    uint8_t u8Req;
+    for (int idxParam = 0; idxParam < cReqList; ++idxParam)
     {
-
-        bool fIgnore = false;
+        fIgnore = false;
         RT_ZERO(opt);
-        opt.u8OptId = pReqList[idxParam];
+        u8Req = opt.u8OptId = pu8ReqList[idxParam];
 
-        switch(pReqList[idxParam])
+        switch(u8Req)
         {
             case RTNET_DHCP_OPT_SUBNET_MASK:
                 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
@@ -1065,7 +1023,7 @@ int NetworkManager::processParameterReqList(const Client& client, uint8_t *pu8Re
             case RTNET_DHCP_OPT_DNS:
                 {
                     const Ipv4AddressContainer lst =
-                      g_ConfigurationManager->getAddressList(pReqList[idxParam]);
+                      g_ConfigurationManager->getAddressList(u8Req);
                     PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
 
                     for (Ipv4AddressConstIterator it = lst.begin();
@@ -1083,7 +1041,7 @@ int NetworkManager::processParameterReqList(const Client& client, uint8_t *pu8Re
                 break;
             case RTNET_DHCP_OPT_DOMAIN_NAME:
                 {
-                    std::string domainName = g_ConfigurationManager->getString(pReqList[idxParam]);
+                    std::string domainName = g_ConfigurationManager->getString(u8Req);
                     if (domainName == g_ConfigurationManager->m_noString)
                     {
                         fIgnore = true;
@@ -1097,28 +1055,19 @@ int NetworkManager::processParameterReqList(const Client& client, uint8_t *pu8Re
                 }
                 break;
             default:
-                Log(("opt: %d is ignored\n", pReqList[idxParam]));
+                Log(("opt: %d is ignored\n", u8Req));
                 fIgnore = true;
                 break;
         }
 
         if (!fIgnore)
-            l.options().insert(std::map<uint8_t, RawOption>::value_type(opt.u8OptId, opt));
+            extra.push_back(opt);
 
     }
 
     return VINF_SUCCESS;
 }
 
-/* Utility */
-bool operator== (const RTMAC& lhs, const RTMAC& rhs)
-{
-    return (   lhs.au16[0] == rhs.au16[0]
-            && lhs.au16[1] == rhs.au16[1]
-            && lhs.au16[2] == rhs.au16[2]);
-}
-
-
 /* Client */
 Client::Client()
 {
@@ -1279,12 +1228,6 @@ const MapOptionId2RawOption& Lease::options() const
 }
 
 
-MapOptionId2RawOption& Lease::options()
-{
-    return m->options;
-}
-
-
 Lease::Lease(ClientData *pd):m(SharedPtr<ClientData>(pd)){}
 
 
@@ -1296,20 +1239,20 @@ bool Lease::toXML(xml::ElementNode *node) const
     valueAddition = node->setAttribute(tagXMLLeaseAttributeNetwork.c_str(), com::Utf8StrFmt("%RTnaipv4", m->m_network));
     if (!valueAddition) return false;
 
-    xml::ElementNode *address = node->createChild(tagXMLLeaseAddress.c_str()); 
+    xml::ElementNode *address = node->createChild(tagXMLLeaseAddress.c_str());
     if (!address) return false;
 
     valueAddition = address->setAttribute(tagXMLAddressAttributeValue.c_str(), com::Utf8StrFmt("%RTnaipv4", m->m_address));
     if (!valueAddition) return false;
 
-    xml::ElementNode *time = node->createChild(tagXMLLeaseTime.c_str()); 
+    xml::ElementNode *time = node->createChild(tagXMLLeaseTime.c_str());
     if (!time) return false;
 
-    valueAddition = time->setAttribute(tagXMLTimeAttributeIssued.c_str(), 
+    valueAddition = time->setAttribute(tagXMLTimeAttributeIssued.c_str(),
                                        m->u64TimestampLeasingStarted);
     if (!valueAddition) return false;
 
-    valueAddition = time->setAttribute(tagXMLTimeAttributeExpiration.c_str(), 
+    valueAddition = time->setAttribute(tagXMLTimeAttributeExpiration.c_str(),
                                        m->u32LeaseExpirationPeriod);
     if (!valueAddition) return false;
 
@@ -1338,17 +1281,17 @@ bool Lease::fromXML(const xml::ElementNode *node)
     valueExists = address->getAttributeValue(tagXMLAddressAttributeValue.c_str(), addressValue);
     if (!valueExists) return false;
     rc = RTNetStrToIPv4Addr(addressValue.c_str(), &m->m_address);
-    
+
     /* Time */
     const xml::ElementNode *time = node->findChildElement(tagXMLLeaseTime.c_str());
     if (!time) return false;
 
-    valueExists = time->getAttributeValue(tagXMLTimeAttributeIssued.c_str(), 
+    valueExists = time->getAttributeValue(tagXMLTimeAttributeIssued.c_str(),
                                           &m->u64TimestampLeasingStarted);
     if (!valueExists) return false;
     m->fBinding = false;
-    
-    valueExists = time->getAttributeValue(tagXMLTimeAttributeExpiration.c_str(), 
+
+    valueExists = time->getAttributeValue(tagXMLTimeAttributeExpiration.c_str(),
                                           &m->u32LeaseExpirationPeriod);
     if (!valueExists) return false;
 
@@ -1359,5 +1302,4 @@ bool Lease::fromXML(const xml::ElementNode *node)
 
 const Lease Lease::NullLease;
 
-
 const Client Client::NullClient;
diff --git a/src/VBox/NetworkServices/DHCP/Config.h b/src/VBox/NetworkServices/DHCP/Config.h
index 51072b5..7d20a72 100644
--- a/src/VBox/NetworkServices/DHCP/Config.h
+++ b/src/VBox/NetworkServices/DHCP/Config.h
@@ -4,16 +4,14 @@
  */
 
 #ifndef _CONFIG_H_
-# define _CONFIG_H_
+#define _CONFIG_H_
 
 #include <iprt/asm-math.h>
 #include <iprt/cpp/utils.h>
+#include <VBox/com/string.h>
 
+#include "../NetLib/cpp/utils.h"
 
-static bool operator <(const RTNETADDRIPV4& a, const RTNETADDRIPV4& b)
-{
-    return (RT_N2H_U32(a.u) < RT_N2H_U32(b.u));
-}
 
 static bool operator > (const RTNETADDRIPV4& a, const RTNETADDRIPV4& b)
 {
@@ -67,7 +65,7 @@ class Client
     void dump();
 
     Lease lease();
-    const Lease lease() const; 
+    const Lease lease() const;
 
     public:
     static const Client NullClient;
@@ -111,7 +109,7 @@ class Lease
     void phaseStart(uint64_t u64Start);
     bool isInBindingPhase() const;
     /* returns 0 if in binding state */
-    uint64_t issued() const; 
+    uint64_t issued() const;
 
     void setExpiration(uint32_t);
     uint32_t getExpiration() const;
@@ -123,7 +121,6 @@ class Lease
     void setConfig(NetworkConfigEntity *);
 
     const MapOptionId2RawOption& options() const;
-    MapOptionId2RawOption& options();
 
     bool toXML(xml::ElementNode *) const;
     bool fromXML(const xml::ElementNode *);
@@ -153,7 +150,6 @@ typedef MapLease2Ip4Address::iterator MapLease2Ip4AddressIterator;
 typedef MapLease2Ip4Address::const_iterator MapLease2Ip4AddressConstIterator;
 typedef MapLease2Ip4Address::value_type MapLease2Ip4AddressPair;
 
-
 /**
  *
  */
@@ -217,10 +213,7 @@ class MACClientMatchCriteria: public ClientMatchCriteria
 public:
     MACClientMatchCriteria(const RTMAC& mac):m_mac(mac){}
 
-    virtual bool check(const Client& client) const
-    {
-        return (client == m_mac);
-    }
+    virtual bool check(const Client& client) const;
 
 private:
     RTMAC m_mac;
@@ -422,7 +415,7 @@ public:
     static ConfigurationManager* getConfigurationManager();
     static int extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt);
 
-    int loadFromFile(const std::string&);
+    int loadFromFile(const com::Utf8Str&);
     int saveToFile();
     /**
      *
@@ -468,11 +461,7 @@ private:
 
     ~ConfigurationManager();
     bool isAddressTaken(const RTNETADDRIPV4& addr, Lease& lease);
-    bool isAddressTaken(const RTNETADDRIPV4& addr)
-    {
-        Lease ignore;
-        return isAddressTaken(addr, ignore);
-    }
+    bool isAddressTaken(const RTNETADDRIPV4& addr);
 
 public:
     /* nulls */
@@ -490,10 +479,6 @@ class NetworkManager
 public:
     static NetworkManager *getNetworkManager();
 
-    int offer4Client(const Client& lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
-    int ack(const Client& lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
-    int nak(const Client& lease, uint32_t u32Xid);
-
     const RTNETADDRIPV4& getOurAddress() const;
     const RTNETADDRIPV4& getOurNetmask() const;
     const RTMAC& getOurMac() const;
@@ -502,17 +487,23 @@ public:
     void setOurNetmask(const RTNETADDRIPV4& aNetmask);
     void setOurMac(const RTMAC& aMac);
 
-    void setSession(PSUPDRVSESSION);
-    void setInterface(INTNETIFHANDLE);
-    void setRingBuffer(PINTNETBUF);
+    bool handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb);
+    bool handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb);
+    bool handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb);
+    bool handleDhcpReqRelease(PCRTNETBOOTP pDhcpMsg, size_t cb);
 
+    void setService(const VBoxNetHlpUDPService *);
 private:
     NetworkManager();
     ~NetworkManager();
 
+    int offer4Client(const Client& lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
+    int ack(const Client& lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
+    int nak(const Client& lease, uint32_t u32Xid);
+
     int prepareReplyPacket4Client(const Client& client, uint32_t u32Xid);
     int doReply(const Client& client, const std::vector<RawOption>& extra);
-    int processParameterReqList(const Client& client, uint8_t *pu8ReqList, int cReqList);
+    int processParameterReqList(const Client& client, const uint8_t *pu8ReqList, int cReqList, std::vector<RawOption>& extra);
 
 private:
     struct Data;
@@ -521,8 +512,6 @@ private:
 };
 
 
-
-
 extern const ClientMatchCriteria *g_AnyClient;
 extern RootConfigEntity *g_RootConfig;
 extern const NullConfigEntity *g_NullConfig;
diff --git a/src/VBox/NetworkServices/DHCP/Makefile.kmk b/src/VBox/NetworkServices/DHCP/Makefile.kmk
index 965a4ea..623b9d9 100644
--- a/src/VBox/NetworkServices/DHCP/Makefile.kmk
+++ b/src/VBox/NetworkServices/DHCP/Makefile.kmk
@@ -44,10 +44,12 @@ VBoxNetDHCP_TEMPLATE := VBOX$(if-expr defined(VBOX_WITH_HARDENING),MAINDLL,MAINC
 VBoxNetDHCP_SOURCES = \
 	VBoxNetDHCP.cpp \
 	Config.cpp \
+	NetworkManagerDhcp.cpp \
 	../NetLib/VBoxNetIntIf.cpp \
 	../NetLib/VBoxNetUDP.cpp \
 	../NetLib/VBoxNetARP.cpp \
-	../NetLib/VBoxNetBaseService.cpp
+	../NetLib/VBoxNetBaseService.cpp \
+	../NetLib/ComHostUtils.cpp
 VBoxNetDHCP_LIBS = \
 	$(LIB_RUNTIME)
 VBoxNetDHCP_LDFLAGS.win = /SUBSYSTEM:windows
diff --git a/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp b/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp
new file mode 100644
index 0000000..415e635
--- /dev/null
+++ b/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp
@@ -0,0 +1,188 @@
+/* $Id: NetworkManagerDhcp.cpp $ */
+/** @file
+ * NetworkManagerDhcp - Network Manager part handling Dhcp.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <iprt/asm.h>
+#include <iprt/cdefs.h>
+#include <iprt/getopt.h>
+#include <iprt/net.h>
+#include <iprt/param.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/time.h>
+#include <iprt/string.h>
+
+#include "../NetLib/shared_ptr.h"
+
+#include <vector>
+#include <list>
+#include <string>
+#include <map>
+
+#include <VBox/sup.h>
+#include <VBox/intnet.h>
+
+#define BASE_SERVICES_ONLY
+#include "../NetLib/VBoxNetBaseService.h"
+#include "Config.h"
+#include "ClientDataInt.h"
+
+/**
+ * The client is requesting an offer.
+ *
+ * @returns true.
+ *
+ * @param   pDhcpMsg    The message.
+ * @param   cb          The message size.
+ */
+bool NetworkManager::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb)
+{
+    RawOption opt;
+    memset(&opt, 0, sizeof(RawOption));
+    /* 1. Find client */
+    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
+    Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);
+
+    /* 2. Find/Bind lease for client */
+    Lease lease = confManager->allocateLease4Client(client, pDhcpMsg, cb);
+    AssertReturn(lease != Lease::NullLease, VINF_SUCCESS);
+
+    int rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
+
+    /* 3. Send of offer */
+
+    lease.bindingPhase(true);
+    lease.phaseStart(RTTimeMilliTS());
+    lease.setExpiration(300); /* 3 min. */
+    offer4Client(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * The client is requesting an offer.
+ *
+ * @returns true.
+ *
+ * @param   pDhcpMsg    The message.
+ * @param   cb          The message size.
+ */
+bool NetworkManager::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)
+{
+    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
+
+    /* 1. find client */
+    Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);
+
+    /* 2. find bound lease */
+    Lease l = client.lease();
+    if (l != Lease::NullLease)
+    {
+
+        if (l.isExpired())
+        {
+            /* send client to INIT state */
+            Client c(client);
+            nak(client, pDhcpMsg->bp_xid);
+            confManager->expireLease4Client(c);
+            return true;
+        }
+        else {
+            /* XXX: Validate request */
+            RawOption opt;
+            RT_ZERO(opt);
+
+            Client c(client);
+            int rc = confManager->commitLease4Client(c);
+            AssertRCReturn(rc, false);
+
+            rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
+            AssertRCReturn(rc, false);
+
+            ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
+        }
+    }
+    else
+    {
+        nak(client, pDhcpMsg->bp_xid);
+    }
+    return true;
+}
+
+
+/**
+ * The client is declining an offer we've made.
+ *
+ * @returns true.
+ *
+ * @param   pDhcpMsg    The message.
+ * @param   cb          The message size.
+ */
+bool NetworkManager::handleDhcpReqDecline(PCRTNETBOOTP, size_t)
+{
+    /** @todo Probably need to match the server IP here to work correctly with
+     *        other servers. */
+
+    /*
+     * The client is supposed to pass us option 50, requested address,
+     * from the offer. We also match the lease state. Apparently the
+     * MAC address is not supposed to be checked here.
+     */
+
+    /** @todo this is not required in the initial implementation, do it later. */
+    return true;
+}
+
+
+/**
+ * The client is releasing its lease - good boy.
+ *
+ * @returns true.
+ *
+ * @param   pDhcpMsg    The message.
+ * @param   cb          The message size.
+ */
+bool NetworkManager::handleDhcpReqRelease(PCRTNETBOOTP, size_t)
+{
+    /** @todo Probably need to match the server IP here to work correctly with
+     *        other servers. */
+
+    /*
+     * The client may pass us option 61, client identifier, which we should
+     * use to find the lease by.
+     *
+     * We're matching MAC address and lease state as well.
+     */
+
+    /*
+     * If no client identifier or if we couldn't find a lease by using it,
+     * we will try look it up by the client IP address.
+     */
+
+
+    /*
+     * If found, release it.
+     */
+
+
+    /** @todo this is not required in the initial implementation, do it later. */
+    return true;
+}
+
diff --git a/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp b/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
index 9802245..39ddff8 100644
--- a/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
+++ b/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
@@ -63,6 +63,7 @@
 #include <map>
 
 #include "../NetLib/VBoxNetBaseService.h"
+#include "../NetLib/utils.h"
 
 #ifdef RT_OS_WINDOWS /* WinMain */
 # include <Windows.h>
@@ -84,16 +85,18 @@
 /**
  * DHCP server instance.
  */
-class VBoxNetDhcp: public VBoxNetBaseService
+class VBoxNetDhcp: public VBoxNetBaseService, public NATNetworkEventAdapter
 {
 public:
     VBoxNetDhcp();
     virtual ~VBoxNetDhcp();
 
     int                 init();
-    int                 run(void);
     void                usage(void) { /* XXX: document options */ };
     int                 parseOpt(int rc, const RTGETOPTUNION& getOptVal);
+    int                 processFrame(void *, size_t) {return VERR_IGNORED; };
+    int                 processGSO(PCPDMNETWORKGSO, size_t) {return VERR_IGNORED; };
+    int                 processUDP(void *, size_t);
 
 protected:
     bool                handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb);
@@ -108,6 +111,8 @@ protected:
 private:
     int initNoMain();
     int initWithMain();
+    HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);
+    int fetchAndUpdateDnsInfo();
 
 protected:
     /** @name The DHCP server specific configuration data members.
@@ -126,6 +131,8 @@ protected:
 
     ComPtr<INATNetwork> m_NATNetwork;
 
+    /** Listener for Host DNS changes */
+    ComPtr<NATNetworkListenerImpl> m_vboxListener;
     /*
      * We will ignore cmd line parameters IFF there will be some DHCP specific arguments
      * otherwise all paramters will come from Main.
@@ -153,6 +160,22 @@ protected:
     /** @} */
 };
 
+
+static inline int configGetBoundryAddress(const ComDhcpServerPtr& dhcp, bool fUpperBoundry, RTNETADDRIPV4& boundryAddress)
+{
+    boundryAddress.u = INADDR_ANY;
+
+    HRESULT hrc;
+    com::Bstr strAddress;
+    if (fUpperBoundry)
+        hrc = dhcp->COMGETTER(UpperIP)(strAddress.asOutParam());
+    else
+        hrc = dhcp->COMGETTER(LowerIP)(strAddress.asOutParam());
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    return RTNetStrToIPv4Addr(com::Utf8Str(strAddress).c_str(), &boundryAddress);
+}
+
 /*******************************************************************************
 *   Global Variables                                                           *
 *******************************************************************************/
@@ -172,27 +195,25 @@ static RTGETOPTDEF g_aOptionDefs[] =
 /**
  * Construct a DHCP server with a default configuration.
  */
-VBoxNetDhcp::VBoxNetDhcp()
+VBoxNetDhcp::VBoxNetDhcp():VBoxNetBaseService("VBoxNetDhcp", "VBoxNetDhcp")
 {
-    m_Name                  = "VBoxNetDhcp";
-    m_Network               = "VBoxNetDhcp";
-    m_TrunkName             = "";
-    m_enmTrunkType          = kIntNetTrunkType_WhateverNone;
-    m_MacAddress.au8[0]     = 0x08;
-    m_MacAddress.au8[1]     = 0x00;
-    m_MacAddress.au8[2]     = 0x27;
-    m_MacAddress.au8[3]     = 0x40;
-    m_MacAddress.au8[4]     = 0x41;
-    m_MacAddress.au8[5]     = 0x42;
-    m_Ipv4Address.u         = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  5)));
-
-    m_pSession              = NIL_RTR0PTR;
-    m_cbSendBuf             =  8192;
-    m_cbRecvBuf             = 51200; /** @todo tune to 64 KB with help from SrvIntR0 */
-    m_hIf                   = INTNET_HANDLE_INVALID;
-    m_pIfBuf                = NULL;
-
-    m_cVerbosity            = 0;
+    /*   m_enmTrunkType          = kIntNetTrunkType_WhateverNone; */
+    RTMAC mac;
+    mac.au8[0]     = 0x08;
+    mac.au8[1]     = 0x00;
+    mac.au8[2]     = 0x27;
+    mac.au8[3]     = 0x40;
+    mac.au8[4]     = 0x41;
+    mac.au8[5]     = 0x42;
+    setMacAddress(mac);
+
+    RTNETADDRIPV4 address;
+    address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  5)));
+    setIpv4Address(address);
+
+    setSendBufSize(8 * _1K);
+    setRecvBufSize(50 * _1K);
+
     m_uCurMsgType           = UINT8_MAX;
     m_cbCurMsg              = 0;
     m_pCurMsg               = NULL;
@@ -201,27 +222,7 @@ VBoxNetDhcp::VBoxNetDhcp()
     m_fIgnoreCmdLineParameters = true;
 
     for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i)
-        m_vecOptionDefs.push_back(&g_aOptionDefs[i]);
-
-#if 0 /* enable to hack the code without a mile long argument list. */
-    VBoxNetDhcpCfg *pDefCfg = new VBoxNetDhcpCfg();
-    pDefCfg->m_LowerAddr.u    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,100)));
-    pDefCfg->m_UpperAddr.u    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,250)));
-    pDefCfg->m_SubnetMask.u   = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(255,255,255,  0)));
-    RTNETADDRIPV4 Addr;
-    Addr.u                    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  1)));
-    pDefCfg->m_Routers.push_back(Addr);
-    Addr.u                    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  2)));
-    pDefCfg->m_DNSes.push_back(Addr);
-    pDefCfg->m_DomainName     = "vboxnetdhcp.org";
-# if 0
-    pDefCfg->m_cSecLease      = 60*60; /* 1 hour */
-# else
-    pDefCfg->m_cSecLease      = 30; /* sec */
-# endif
-    pDefCfg->m_TftpServer     = "10.0.2.3"; //??
-    this->addConfig(pDefCfg);
-#endif
+        addCommandLineOption(&g_aOptionDefs[i]);
 }
 
 
@@ -256,7 +257,7 @@ int VBoxNetDhcp::parseOpt(int rc, const RTGETOPTUNION& Val)
     {
         case 'l':
         case 'u':
-        case 'g': 
+        case 'g':
         {
             char buf[17];
             RTStrPrintf(buf, 17, "%RTnaipv4", Val.IPv4Addr.u);
@@ -285,10 +286,11 @@ int VBoxNetDhcp::init()
 
     NetworkManager *netManager = NetworkManager::getNetworkManager();
 
-    netManager->setOurAddress(m_Ipv4Address);
-    netManager->setOurNetmask(m_Ipv4Netmask);
-    netManager->setOurMac(m_MacAddress);
-    
+    netManager->setOurAddress(getIpv4Address());
+    netManager->setOurNetmask(getIpv4Netmask());
+    netManager->setOurMac(getMacAddress());
+    netManager->setService(this);
+
     if (isMainNeeded())
         rc = initWithMain();
     else
@@ -299,85 +301,31 @@ int VBoxNetDhcp::init()
     return VINF_SUCCESS;
 }
 
-/**
- * Runs the DHCP server.
- *
- * @returns exit code + error message to stderr on failure, won't return on
- *          success (you must kill this process).
- */
-int VBoxNetDhcp::run(void)
-{
 
-    /* XXX: shortcut should be hidden from network manager */
-    NetworkManager *netManager = NetworkManager::getNetworkManager();
-    netManager->setSession(m_pSession);
-    netManager->setInterface(m_hIf);
-    netManager->setRingBuffer(m_pIfBuf);
+int  VBoxNetDhcp::processUDP(void *pv, size_t cbPv)
+{
+    PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
+    m_pCurMsg  = pDhcpMsg;
+    m_cbCurMsg = cbPv;
 
-    /*
-     * The loop.
-     */
-    PINTNETRINGBUF  pRingBuf = &m_pIfBuf->Recv;
-    for (;;)
+    uint8_t uMsgType;
+    if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cbPv, &uMsgType))
     {
-        /*
-         * Wait for a packet to become available.
-         */
-        INTNETIFWAITREQ WaitReq;
-        WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-        WaitReq.Hdr.cbReq = sizeof(WaitReq);
-        WaitReq.pSession = m_pSession;
-        WaitReq.hIf = m_hIf;
-        WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */  /** @todo fix interruptability in SrvIntNet! */
-        int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
-        if (RT_FAILURE(rc))
+        m_uCurMsgType = uMsgType;
         {
-            if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
-                continue;
-            RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc);
-            return 1;
-        }
-
-        /*
-         * Process the receive buffer.
-         */
-        while (IntNetRingHasMoreToRead(pRingBuf))
-        {
-            size_t  cb;
-            void   *pv = VBoxNetUDPMatch(m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m_MacAddress,
-                                         VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST | VBOXNETUDP_MATCH_CHECKSUM
-                                         | (m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
-                                         &m_CurHdrs, &cb);
-            if (pv && cb)
-            {
-                PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
-                m_pCurMsg  = pDhcpMsg;
-                m_cbCurMsg = cb;
-
-                uint8_t uMsgType;
-                if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cb, &uMsgType))
-                {
-                    m_uCurMsgType = uMsgType;
-                    handleDhcpMsg(uMsgType, pDhcpMsg, cb);
-                    m_uCurMsgType = UINT8_MAX;
-                }
-                else
-                    debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
-
-                m_pCurMsg = NULL;
-                m_cbCurMsg = 0;
-            }
-            else if (VBoxNetArpHandleIt(m_pSession, m_hIf, m_pIfBuf, &m_MacAddress, m_Ipv4Address))
-            {
-                /* nothing */
-            }
-
-            /* Advance to the next frame. */
-            IntNetRingSkipFrame(pRingBuf);
+            /* To avoid fight with event processing thread */
+            VBoxNetALock(this);
+            handleDhcpMsg(uMsgType, pDhcpMsg, cbPv);
         }
+        m_uCurMsgType = UINT8_MAX;
     }
+    else
+        debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
+
+    m_pCurMsg = NULL;
+    m_cbCurMsg = 0;
 
-    return 0;
+    return VINF_SUCCESS;
 }
 
 
@@ -393,19 +341,21 @@ bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t
 {
     if (pDhcpMsg->bp_op == RTNETBOOTP_OP_REQUEST)
     {
+        NetworkManager *networkManager = NetworkManager::getNetworkManager();
+
         switch (uMsgType)
         {
             case RTNET_DHCP_MT_DISCOVER:
-                return handleDhcpReqDiscover(pDhcpMsg, cb);
+                return networkManager->handleDhcpReqDiscover(pDhcpMsg, cb);
 
             case RTNET_DHCP_MT_REQUEST:
-                return handleDhcpReqRequest(pDhcpMsg, cb);
+                return networkManager->handleDhcpReqRequest(pDhcpMsg, cb);
 
             case RTNET_DHCP_MT_DECLINE:
-                return handleDhcpReqDecline(pDhcpMsg, cb);
+                return networkManager->handleDhcpReqDecline(pDhcpMsg, cb);
 
             case RTNET_DHCP_MT_RELEASE:
-                return handleDhcpReqRelease(pDhcpMsg, cb);
+                return networkManager->handleDhcpReqRelease(pDhcpMsg, cb);
 
             case RTNET_DHCP_MT_INFORM:
                 debugPrint(0, true, "Should we handle this?");
@@ -419,155 +369,6 @@ bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t
     return false;
 }
 
-
-/**
- * The client is requesting an offer.
- *
- * @returns true.
- *
- * @param   pDhcpMsg    The message.
- * @param   cb          The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
-    RawOption opt;
-    memset(&opt, 0, sizeof(RawOption));
-    /* 1. Find client */
-    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
-    Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);
-
-    /* 2. Find/Bind lease for client */
-    Lease lease = confManager->allocateLease4Client(client, pDhcpMsg, cb);
-    AssertReturn(lease != Lease::NullLease, VINF_SUCCESS);
-
-    int rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
-
-    /* 3. Send of offer */
-    NetworkManager *networkManager = NetworkManager::getNetworkManager();
-
-    lease.bindingPhase(true);
-    lease.phaseStart(RTTimeMilliTS());
-    lease.setExpiration(300); /* 3 min. */
-    networkManager->offer4Client(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * The client is requesting an offer.
- *
- * @returns true.
- *
- * @param   pDhcpMsg    The message.
- * @param   cb          The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
-    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
-    NetworkManager *networkManager = NetworkManager::getNetworkManager();
-
-    /* 1. find client */
-    Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);
-
-    /* 2. find bound lease */
-    Lease l = client.lease();
-    if (l != Lease::NullLease)
-    {
-
-        if (l.isExpired())
-        {
-            /* send client to INIT state */
-            Client c(client);
-            networkManager->nak(client, pDhcpMsg->bp_xid);
-            confManager->expireLease4Client(c);
-            return true;
-        }
-        else {
-            /* XXX: Validate request */
-            RawOption opt;
-            RT_ZERO(opt);
-
-            Client c(client);
-            int rc = confManager->commitLease4Client(c);
-            AssertRCReturn(rc, false);
-
-            rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
-            AssertRCReturn(rc, false);
-
-            networkManager->ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
-        }
-    }
-    else
-    {
-        networkManager->nak(client, pDhcpMsg->bp_xid);
-    }
-    return true;
-}
-
-
-/**
- * The client is declining an offer we've made.
- *
- * @returns true.
- *
- * @param   pDhcpMsg    The message.
- * @param   cb          The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqDecline(PCRTNETBOOTP, size_t)
-{
-    /** @todo Probably need to match the server IP here to work correctly with
-     *        other servers. */
-
-    /*
-     * The client is supposed to pass us option 50, requested address,
-     * from the offer. We also match the lease state. Apparently the
-     * MAC address is not supposed to be checked here.
-     */
-
-    /** @todo this is not required in the initial implementation, do it later. */
-    debugPrint(1, true, "DECLINE is not implemented");
-    return true;
-}
-
-
-/**
- * The client is releasing its lease - good boy.
- *
- * @returns true.
- *
- * @param   pDhcpMsg    The message.
- * @param   cb          The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqRelease(PCRTNETBOOTP, size_t)
-{
-    /** @todo Probably need to match the server IP here to work correctly with
-     *        other servers. */
-
-    /*
-     * The client may pass us option 61, client identifier, which we should
-     * use to find the lease by.
-     *
-     * We're matching MAC address and lease state as well.
-     */
-
-    /*
-     * If no client identifier or if we couldn't find a lease by using it,
-     * we will try look it up by the client IP address.
-     */
-
-
-    /*
-     * If found, release it.
-     */
-
-
-    /** @todo this is not required in the initial implementation, do it later. */
-    debugPrint(1, true, "RELEASE is not implemented");
-    return true;
-}
-
-
 /**
  * Print debug message depending on the m_cVerbosity level.
  *
@@ -645,9 +446,10 @@ int VBoxNetDhcp::initNoMain()
 {
     CmdParameterIterator it;
 
+    RTNETADDRIPV4 address = getIpv4Address();
+    RTNETADDRIPV4 netmask = getIpv4Netmask();
     RTNETADDRIPV4 networkId;
-    networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u;
-    RTNETADDRIPV4 netmask = m_Ipv4Netmask;
+    networkId.u = address.u & netmask.u;
 
     RTNETADDRIPV4 UpperAddress;
     RTNETADDRIPV4 LowerAddress = networkId;
@@ -666,15 +468,15 @@ int VBoxNetDhcp::initNoMain()
                 break;
             case 'b':
                 break;
-                    
+
         }
     }
-        
+
     ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
     AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
     confManager->addNetwork(unconst(g_RootConfig),
                             networkId,
-                            m_Ipv4Netmask,
+                            netmask,
                             LowerAddress,
                             UpperAddress);
 
@@ -688,25 +490,21 @@ int VBoxNetDhcp::initWithMain()
      * and listener for Dhcp configuration events
      */
     AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
+    std::string networkName = getNetwork();
 
-    HRESULT hrc = virtualbox->FindDHCPServerByNetworkName(com::Bstr(m_Network.c_str()).raw(),
-                                                  m_DhcpServer.asOutParam());
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-
-    hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_Network.c_str()).raw(),
-                                           m_NATNetwork.asOutParam());
+    int rc = findDhcpServer(virtualbox, networkName, m_DhcpServer);
+    AssertRCReturn(rc, rc);
 
-    BOOL fNeedDhcpServer = false;
-    if (FAILED(m_NATNetwork->COMGETTER(NeedDhcpServer)(&fNeedDhcpServer)))
-        return VERR_INTERNAL_ERROR;
+    rc = findNatNetwork(virtualbox, networkName, m_NATNetwork);
+    AssertRCReturn(rc, rc);
 
+    BOOL fNeedDhcpServer = isDhcpRequired(m_NATNetwork);
     if (!fNeedDhcpServer)
         return VERR_CANCELLED;
 
     RTNETADDRIPV4 gateway;
     com::Bstr strGateway;
-
-    hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
+    HRESULT hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
     AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
     RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);
 
@@ -714,121 +512,93 @@ int VBoxNetDhcp::initWithMain()
     AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
     confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);
 
-    unsigned int i;
-    unsigned int count_strs;
-    com::SafeArray<BSTR> strs;
-    std::map<RTNETADDRIPV4, uint32_t> MapIp4Addr2Off;
-
-    hrc = m_NATNetwork->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));
-    if (   SUCCEEDED(hrc)
-           && (count_strs = strs.size()))
-    {
-        for (i = 0; i < count_strs; ++i)
-        {
-            char szAddr[17];
-            RTNETADDRIPV4 ip4addr;
-            char *pszTerm;
-            uint32_t u32Off;
-            com::Utf8Str strLo2Off(strs[i]);
-            const char *pszLo2Off = strLo2Off.c_str();
-
-            RT_ZERO(szAddr);
-
-            pszTerm = RTStrStr(pszLo2Off, "=");
-
-            if (   pszTerm
-                   && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN)
-            {
-                memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));
-                int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);
-                if (RT_SUCCESS(rc))
-                {
-                    u32Off = RTStrToUInt32(pszTerm + 1);
-                    if (u32Off != 0)
-                        MapIp4Addr2Off.insert(
-                          std::map<RTNETADDRIPV4,uint32_t>::value_type(ip4addr, u32Off));
-                }
-            }
-        }
-    }
-
-    strs.setNull();
-    ComPtr<IHost> host;
-    if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))
-    {
-        if (SUCCEEDED(host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs))))
-        {
-            RTNETADDRIPV4 addr;
-
-            confManager->flushAddressList(RTNET_DHCP_OPT_DNS);
-            int rc;
-            for (i = 0; i < strs.size(); ++i)
-            {
-                rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);
-                if (RT_SUCCESS(rc))
-                {
-                    if (addr.au8[0] == 127)
-                    {
-                        if (MapIp4Addr2Off[addr] != 0)
-                        {
-                            addr.u = RT_H2N_U32(RT_N2H_U32(m_Ipv4Address.u & m_Ipv4Netmask.u)
-                                                + MapIp4Addr2Off[addr]);
-                        }
-                        else
-                            continue;
-                    }
-
-                    confManager->addToAddressList(RTNET_DHCP_OPT_DNS, addr);
-                }
-            }
-        }
+    rc = fetchAndUpdateDnsInfo();
+    AssertMsgRCReturn(rc, ("Wasn't able to fetch Dns info"), rc);
 
-        strs.setNull();
-#if 0
-        if (SUCCEEDED(host->COMGETTER(SearchStrings)(ComSafeArrayAsOutParam(strs)))) 
-        {
-            /* XXX: todo. */;
-        }
-        strs.setNull();
-#endif
-        com::Bstr domain;
-        if (SUCCEEDED(host->COMGETTER(DomainName)(domain.asOutParam())))
-            confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, std::string(com::Utf8Str(domain).c_str()));
-    }
+    ComEventTypeArray aVBoxEvents;
+    aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
+    rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
+    AssertRCReturn(rc, rc);
 
-    com::Bstr strUpperIp, strLowerIp;
-    
     RTNETADDRIPV4 LowerAddress;
-    RTNETADDRIPV4 UpperAddress;
-
-    hrc = m_DhcpServer->COMGETTER(UpperIP)(strUpperIp.asOutParam());
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-    RTNetStrToIPv4Addr(com::Utf8Str(strUpperIp).c_str(), &UpperAddress);
+    rc = configGetBoundryAddress(m_DhcpServer, false, LowerAddress);
+    AssertMsgRCReturn(rc, ("can't get lower boundrary adderss'"),rc);
 
+    RTNETADDRIPV4 UpperAddress;
+    rc = configGetBoundryAddress(m_DhcpServer, true, UpperAddress);
+    AssertMsgRCReturn(rc, ("can't get upper boundrary adderss'"),rc);
 
-    hrc = m_DhcpServer->COMGETTER(LowerIP)(strLowerIp.asOutParam());
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-    RTNetStrToIPv4Addr(com::Utf8Str(strLowerIp).c_str(), &LowerAddress);
-
-    RTNETADDRIPV4 networkId;
-    networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u;
+    RTNETADDRIPV4 address = getIpv4Address();
+    RTNETADDRIPV4 netmask = getIpv4Netmask();
+    RTNETADDRIPV4 networkId = networkid(address, netmask);
     std::string name = std::string("default");
 
     confManager->addNetwork(unconst(g_RootConfig),
                             networkId,
-                            m_Ipv4Netmask,
+                            netmask,
                             LowerAddress,
                             UpperAddress);
 
     com::Bstr bstr;
     hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
-    std::string strXmlLeaseFile(com::Utf8StrFmt("%ls%c%s.leases",
-                                                bstr.raw(), RTPATH_DELIMITER, m_Network.c_str()).c_str());
+    com::Utf8StrFmt strXmlLeaseFile("%ls%c%s.leases",
+                                    bstr.raw(), RTPATH_DELIMITER, networkName.c_str());
     confManager->loadFromFile(strXmlLeaseFile);
 
     return VINF_SUCCESS;
 }
 
+
+int VBoxNetDhcp::fetchAndUpdateDnsInfo()
+{
+    ComHostPtr host;
+    if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))
+    {
+        AddressToOffsetMapping mapIp4Addr2Off;
+        int rc = localMappings(m_NATNetwork, mapIp4Addr2Off);
+        /* XXX: here could be several cases: 1. COM error, 2. not found (empty) 3. ? */
+        AssertMsgRCReturn(rc, ("Can't fetch local mappings"), rc);
+
+        RTNETADDRIPV4 address = getIpv4Address();
+        RTNETADDRIPV4 netmask = getIpv4Netmask();
+
+        AddressList nameservers;
+        rc = hostDnsServers(host, networkid(address, netmask), mapIp4Addr2Off, nameservers);
+        AssertMsgRCReturn(rc, ("Debug me!!!"), rc);
+        /* XXX: Search strings */
+
+        std::string domain;
+        rc = hostDnsDomain(host, domain);
+        AssertMsgRCReturn(rc, ("Debug me!!"), rc);
+
+        {
+            VBoxNetALock(this);
+            ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
+            confManager->flushAddressList(RTNET_DHCP_OPT_DNS);
+
+            for (AddressList::iterator it = nameservers.begin(); it != nameservers.end(); ++it)
+                confManager->addToAddressList(RTNET_DHCP_OPT_DNS, *it);
+
+            confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, domain);
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+HRESULT VBoxNetDhcp::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
+{
+    switch(aEventType)
+    {
+        case VBoxEventType_OnHostNameResolutionConfigurationChange:
+            fetchAndUpdateDnsInfo();
+            break;
+    }
+
+    return S_OK;
+}
+
 /**
  *  Entry point.
  */
diff --git a/src/VBox/NetworkServices/NAT/Makefile.kmk b/src/VBox/NetworkServices/NAT/Makefile.kmk
index 0a0adfb..619494f 100644
--- a/src/VBox/NetworkServices/NAT/Makefile.kmk
+++ b/src/VBox/NetworkServices/NAT/Makefile.kmk
@@ -41,15 +41,27 @@ VBoxNetLwipNAT_TEMPLATE =
 VBoxNetLwipNAT_TEMPLATE := VBOXMAIN$(if-expr defined(VBOX_WITH_HARDENING),DLL,CLIENTEXE)
 VBoxNetLwipNAT_NAME = VBoxNetNAT
 VBoxNetLwipNAT_DEFS += ${LWIP_DEFS} IPv6
+# VBoxNetLwipNAT_DEFS.linux += WITH_VALGRIND # instrument lwip memp.c
 VBoxNetLwipNAT_DEFS.win += VBOX_COM_OUTOFPROC_MODULE _WIN32_WINNT=0x501 # Windows XP
 VBoxNetLwipNAT_SOURCES += VBoxNetLwipNAT.cpp	\
 	../NetLib/VBoxNetBaseService.cpp \
-	../NetLib/VBoxNetPortForwardString.cpp
+	../NetLib/VBoxNetPortForwardString.cpp \
+	../NetLib/VBoxNetIntIf.cpp \
+	../NetLib/VBoxNetUDP.cpp \
+	../NetLib/VBoxNetARP.cpp \
+	../NetLib/ComHostUtils.cpp
+
 VBoxNetLwipNAT_LIBS = \
 	$(LIB_RUNTIME)
 VBoxNetLwipNAT_LIBS.solaris += socket nsl
 VBoxNetLwipNAT_LDFLAGS.win = /SUBSYSTEM:windows
 
+# Convince Solaris headers to expose socket stuff we need.  600 would
+# also work, but <sys/feature_tests.h> insists on C99 for it and so
+# explodes for C++.  Note that for 500 it insists on NOT using C99, so
+# when some day we decide to use -std=c99 we are in for some fun.
+VBoxNetLwipNAT_DEFS.solaris += _XOPEN_SOURCE=500 __EXTENSIONS__=1
+
 VBoxNetLwipNAT_SOURCES += \
     proxy_pollmgr.c \
     proxy_rtadvd.c \
@@ -64,6 +76,22 @@ VBoxNetLwipNAT_SOURCES += \
     proxy_dhcp6ds.c \
     proxy_tftpd.c
 
+ifeq ($(KBUILD_TARGET),win)
+ # unprivileged Icmp API
+ VBoxNetLwipNAT_SOURCES += pxping_win.c
+else
+ # raw sockets
+ VBoxNetLwipNAT_SOURCES += pxping.c
+endif
+
+# ifeq ($(VBOX_WITH_HARDENING),)
+#  ifn1of ($(KBUILD_TARGET), darwin win)
+#   # helper for debugging unprivileged
+#   VBoxNetLwipNAT_DEFS += VBOX_RAWSOCK_DEBUG_HELPER
+#   VBoxNetLwipNAT_SOURCES += getrawsock.c
+#  endif
+# endif
+
 VBoxNetLwipNAT_SOURCES.darwin  += rtmon_bsd.c
 VBoxNetLwipNAT_SOURCES.freebsd += rtmon_bsd.c
 VBoxNetLwipNAT_SOURCES.linux   += rtmon_linux.c
diff --git a/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp b/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
index 3c3d2c3..a8ccc06 100644
--- a/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
+++ b/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
@@ -17,6 +17,7 @@
 
 #include "winutils.h"
 
+#include <VBox/com/assert.h>
 #include <VBox/com/com.h>
 #include <VBox/com/listeners.h>
 #include <VBox/com/string.h>
@@ -25,7 +26,6 @@
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
 #include <VBox/com/VirtualBox.h>
-#include <VBox/com/NativeEventQueue.h>
 
 #include <iprt/net.h>
 #include <iprt/initterm.h>
@@ -63,13 +63,19 @@
 # include <sys/poll.h>
 # include <sys/socket.h>
 # include <netinet/in.h>
+# ifdef RT_OS_LINUX
+#  include <linux/icmp.h>       /* ICMP_FILTER */
+# endif
+# include <netinet/icmp6.h>
 #endif
 
+#include <map>
 #include <vector>
 #include <string>
 
 #include "../NetLib/VBoxNetLib.h"
 #include "../NetLib/VBoxNetBaseService.h"
+#include "../NetLib/utils.h"
 #include "VBoxLwipCore.h"
 
 extern "C"
@@ -81,20 +87,12 @@ extern "C"
 # define LWIP_SOCKET 0
 #endif
 #include "lwip/sys.h"
-#include "lwip/stats.h"
-#include "lwip/mem.h"
-#include "lwip/memp.h"
 #include "lwip/pbuf.h"
 #include "lwip/netif.h"
-#include "lwip/api.h"
-#include "lwip/tcp_impl.h"
-#include "ipv6/lwip/ethip6.h"
+#include "lwip/ethip6.h"
 #include "lwip/nd6.h"           // for proxy_na_hook
 #include "lwip/mld6.h"
-#include "lwip/udp.h"
-#include "lwip/tcp.h"
 #include "lwip/tcpip.h"
-#include "lwip/sockets.h"
 #include "netif/etharp.h"
 
 #include "proxy.h"
@@ -102,6 +100,18 @@ extern "C"
 #include "portfwd.h"
 }
 
+
+#if defined(VBOX_RAWSOCK_DEBUG_HELPER)          \
+    && (defined(VBOX_WITH_HARDENING)            \
+        || defined(RT_OS_WINDOWS)               \
+        || defined(RT_OS_DARWIN))
+# error Have you forgotten to turn off VBOX_RAWSOCK_DEBUG_HELPER?
+#endif
+
+#ifdef VBOX_RAWSOCK_DEBUG_HELPER
+extern "C" int getrawsock(int type);
+#endif
+
 #include "../NetLib/VBoxPortForwardString.h"
 
 static RTGETOPTDEF g_aGetOptDef[] =
@@ -120,53 +130,25 @@ typedef std::vector<NATSEVICEPORTFORWARDRULE> VECNATSERVICEPF;
 typedef VECNATSERVICEPF::iterator ITERATORNATSERVICEPF;
 typedef VECNATSERVICEPF::const_iterator CITERATORNATSERVICEPF;
 
-
-class VBoxNetLwipNAT;
-
-
-class NATNetworkListener
-{
-public:
-    NATNetworkListener():m_pNAT(NULL){}
-
-    HRESULT init(VBoxNetLwipNAT *pNAT)
-    {
-        AssertPtrReturn(pNAT, E_INVALIDARG);
-
-        m_pNAT = pNAT;
-        return S_OK;
-    }
-
-    HRESULT init()
-    {
-        m_pNAT = NULL;
-        return S_OK;
-    }
-
-    void uninit() { m_pNAT = NULL; }
-
-    STDMETHOD(HandleEvent)(VBoxEventType_T aEventType, IEvent *pEvent);
-
-private:
-    VBoxNetLwipNAT *m_pNAT;
-};
-typedef ListenerImpl<NATNetworkListener, VBoxNetLwipNAT *> NATNetworkListenerImpl;
-VBOX_LISTENER_DECLARE(NATNetworkListenerImpl)
+static int fetchNatPortForwardRules(const ComNatPtr&, bool, VECNATSERVICEPF&);
 
 
-class VBoxNetLwipNAT: public VBoxNetBaseService
+class VBoxNetLwipNAT: public VBoxNetBaseService, public NATNetworkEventAdapter
 {
     friend class NATNetworkListener;
   public:
-    VBoxNetLwipNAT();
+    VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6);
     virtual ~VBoxNetLwipNAT();
     void usage(){                /* @todo: should be implemented */ };
     int run();
     virtual int init(void);
-    /* @todo: when configuration would be really needed */
     virtual int parseOpt(int rc, const RTGETOPTUNION& getOptVal);
     /* VBoxNetNAT always needs Main */
     virtual bool isMainNeeded() const { return true; }
+    virtual int processFrame(void *, size_t);
+    virtual int processGSO(PCPDMNETWORKGSO, size_t);
+    virtual int processUDP(void *, size_t) { return VERR_IGNORED; }
+
    private:
     struct proxy_options m_ProxyOptions;
     struct sockaddr_in m_src4;
@@ -179,23 +161,19 @@ class VBoxNetLwipNAT: public VBoxNetBaseService
 
     uint16_t m_u16Mtu;
     netif m_LwipNetIf;
-    /* Queues */
-    RTREQQUEUE  hReqIntNet;
-    /* thread where we're waiting for a frames, no semaphores needed */
-    RTTHREAD hThrIntNetRecv;
 
     /* Our NAT network descriptor in Main */
     ComPtr<INATNetwork> m_net;
-    ComObjPtr<NATNetworkListenerImpl> m_listener;
+    ComNatListenerPtr m_listener;
 
     ComPtr<IHost> m_host;
-    ComObjPtr<NATNetworkListenerImpl> m_vboxListener;
+    ComNatListenerPtr m_vboxListener;
+    static INTNETSEG aXmitSeg[64];
 
-    STDMETHOD(HandleEvent)(VBoxEventType_T aEventType, IEvent *pEvent);
+    HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);
 
     const char **getHostNameservers();
 
-    RTSEMEVENT hSemSVC;
     /* Only for debug needs, by default NAT service should load rules from SVC
      * on startup, and then on sync them on events.
      */
@@ -205,7 +183,6 @@ class VBoxNetLwipNAT: public VBoxNetBaseService
     static err_t netifInit(netif *pNetif);
     static err_t netifLinkoutput(netif *pNetif, pbuf *pBuf);
     static int intNetThreadRecv(RTTHREAD, void *);
-    static void vboxNetLwipNATProcessXmit(void);
 
     VECNATSERVICEPF m_vecPortForwardRule4;
     VECNATSERVICEPF m_vecPortForwardRule6;
@@ -216,18 +193,12 @@ class VBoxNetLwipNAT: public VBoxNetBaseService
 
 
 static VBoxNetLwipNAT *g_pLwipNat;
+INTNETSEG VBoxNetLwipNAT::aXmitSeg[64];
 
-STDMETHODIMP NATNetworkListener::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
-{
-    if (m_pNAT)
-        return m_pNAT->HandleEvent(aEventType, pEvent);
-    else
-        return E_FAIL;
-}
-
-
-
-STDMETHODIMP VBoxNetLwipNAT::HandleEvent(VBoxEventType_T aEventType,
+/**
+ * @note: this work on Event thread.
+ */
+HRESULT VBoxNetLwipNAT::HandleEvent(VBoxEventType_T aEventType,
                                                   IEvent *pEvent)
 {
     HRESULT hrc = S_OK;
@@ -257,7 +228,7 @@ STDMETHODIMP VBoxNetLwipNAT::HandleEvent(VBoxEventType_T aEventType,
 
             break;
         }
-        
+
         case VBoxEventType_OnNATNetworkPortForward:
         {
             com::Bstr name, strHostAddr, strGuestAddr;
@@ -414,14 +385,16 @@ void VBoxNetLwipNAT::onLwipTcpIpInit(void* arg)
     proxy_ip6_divert_hook = pxremap_ip6_divert;
 
     /* lwip thread */
-    RTNETADDRIPV4 IpNetwork;
-    IpNetwork.u = g_pLwipNat->m_Ipv4Address.u & g_pLwipNat->m_Ipv4Netmask.u;
+    RTNETADDRIPV4 network;
+    RTNETADDRIPV4 address = g_pLwipNat->getIpv4Address();
+    RTNETADDRIPV4 netmask = g_pLwipNat->getIpv4Netmask();
+    network.u = address.u & netmask.u;
 
     ip_addr LwipIpAddr, LwipIpNetMask, LwipIpNetwork;
 
-    memcpy(&LwipIpAddr, &g_pLwipNat->m_Ipv4Address, sizeof(ip_addr));
-    memcpy(&LwipIpNetMask, &g_pLwipNat->m_Ipv4Netmask, sizeof(ip_addr));
-    memcpy(&LwipIpNetwork, &IpNetwork, sizeof(ip_addr));
+    memcpy(&LwipIpAddr, &address, sizeof(ip_addr));
+    memcpy(&LwipIpNetMask, &netmask, sizeof(ip_addr));
+    memcpy(&LwipIpNetwork, &network, sizeof(ip_addr));
 
     netif *pNetif = netif_add(&g_pLwipNat->m_LwipNetIf /* Lwip Interface */,
                               &LwipIpAddr /* IP address*/,
@@ -507,7 +480,8 @@ err_t VBoxNetLwipNAT::netifInit(netif *pNetif)
 
 
     pNetif->hwaddr_len = sizeof(RTMAC);
-    memcpy(pNetif->hwaddr, &pNat->m_MacAddress, sizeof(RTMAC));
+    RTMAC mac = g_pLwipNat->getMacAddress();
+    memcpy(pNetif->hwaddr, &mac, sizeof(RTMAC));
 
     pNat->m_u16Mtu = 1500; // XXX: FIXME
     pNetif->mtu = pNat->m_u16Mtu;
@@ -552,225 +526,46 @@ err_t VBoxNetLwipNAT::netifInit(netif *pNetif)
 }
 
 
-/**
- * Intnet-recv thread
- */
-int VBoxNetLwipNAT::intNetThreadRecv(RTTHREAD, void *)
-{
-    int rc = VINF_SUCCESS;
-
-    /* 1. initialization and connection */
-    HRESULT hrc = com::Initialize();
-    if (FAILED(hrc))
-        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM!");
-
-    /* Well we're ready */
-    PINTNETRINGBUF  pRingBuf = &g_pLwipNat->m_pIfBuf->Recv;
-
-    for (;;)
-    {
-        /*
-         * Wait for a packet to become available.
-         */
-        /* 2. waiting for request for */
-        rc = g_pLwipNat->waitForIntNetEvent(2000);
-        if (RT_FAILURE(rc))
-        {
-            if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
-            {
-                /* do we want interrupt anyone ??? */
-                continue;
-            }
-            LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
-            AssertRCReturn(rc,ERR_IF);
-        }
-
-        /*
-         * Process the receive buffer.
-         */
-        PCINTNETHDR pHdr;
-
-        while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
-        {
-            uint8_t const u8Type = pHdr->u8Type;
-            size_t         cbFrame = pHdr->cbFrame;
-            uint8_t        *pu8Frame = NULL;
-            pbuf           *pPbufHdr = NULL;
-            pbuf           *pPbuf = NULL;
-            switch (u8Type)
-            {
-
-                case INTNETHDR_TYPE_FRAME:
-                    /* @todo:should it be really here?
-                     * Well well well, we're accessing lwip code here
-                     */
-                    pPbufHdr = pPbuf = pbuf_alloc(PBUF_RAW, pHdr->cbFrame, PBUF_POOL);
-                    if (!pPbuf)
-                    {
-                        LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame));
-                        break;
-                    }
-                    Assert(pPbufHdr->tot_len == cbFrame);
-                    pu8Frame = (uint8_t *)IntNetHdrGetFramePtr(pHdr, g_pLwipNat->m_pIfBuf);
-                    while(pPbuf)
-                    {
-                        memcpy(pPbuf->payload, pu8Frame, pPbuf->len);
-                        pu8Frame += pPbuf->len;
-                        pPbuf = pPbuf->next;
-                    }
-
-                    g_pLwipNat->m_LwipNetIf.input(pPbufHdr, &g_pLwipNat->m_LwipNetIf);
-
-                    AssertReleaseRC(rc);
-                    break;
-                case INTNETHDR_TYPE_GSO:
-                  {
-                      PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr,
-                                                                    g_pLwipNat->m_pIfBuf);
-                      if (!PDMNetGsoIsValid(pGso, cbFrame,
-                                            cbFrame - sizeof(PDMNETWORKGSO)))
-                          break;
-                      cbFrame -= sizeof(PDMNETWORKGSO);
-                      uint8_t         abHdrScratch[256];
-                      uint32_t const  cSegs = PDMNetGsoCalcSegmentCount(pGso,
-                                                                        cbFrame);
-                      for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
-                      {
-                          uint32_t cbSegFrame;
-                          void    *pvSegFrame =
-                            PDMNetGsoCarveSegmentQD(pGso,
-                                                    (uint8_t *)(pGso + 1),
-                                                    cbFrame,
-                                                    abHdrScratch,
-                                                    iSeg,
-                                                    cSegs,
-                                                    &cbSegFrame);
-
-                          pPbuf = pbuf_alloc(PBUF_RAW, cbSegFrame, PBUF_POOL);
-                          if (!pPbuf)
-                          {
-                              LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbSegFrame));
-                              break;
-                          }
-                          Assert(   !pPbuf->next
-                                 && pPbuf->len == cbSegFrame);
-                          memcpy(pPbuf->payload, pvSegFrame, cbSegFrame);
-                          g_pLwipNat->m_LwipNetIf.input(pPbuf, &g_pLwipNat->m_LwipNetIf);
-
-                      }
-
-                  }
-                  break;
-                case INTNETHDR_TYPE_PADDING:
-                    break;
-                default:
-                    STAM_REL_COUNTER_INC(&g_pLwipNat->m_pIfBuf->cStatBadFrames);
-                    break;
-            }
-            IntNetRingSkipFrame(&g_pLwipNat->m_pIfBuf->Recv);
-
-        } /* loop */
-    }
-    /* 3. deinitilization and termination */
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-
-/**
- *
- */
-void VBoxNetLwipNAT::vboxNetLwipNATProcessXmit()
-{
-    int rc = VINF_SUCCESS;
-    INTNETIFSENDREQ SendReq;
-    SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-    SendReq.Hdr.cbReq    = sizeof(SendReq);
-    SendReq.pSession     = g_pLwipNat->m_pSession;
-    SendReq.hIf          = g_pLwipNat->m_hIf;
-    rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
-    AssertRC(rc);
-}
-
-
 err_t VBoxNetLwipNAT::netifLinkoutput(netif *pNetif, pbuf *pPBuf)
 {
-    int rc = VINF_SUCCESS;
-    err_t rcLwip = ERR_OK;
     AssertPtrReturn(pNetif, ERR_ARG);
     AssertPtrReturn(pPBuf, ERR_ARG);
     AssertReturn((void *)g_pLwipNat == pNetif->state, ERR_ARG);
+
     LogFlowFunc(("ENTER: pNetif[%c%c%d], pPbuf:%p\n",
                  pNetif->name[0],
                  pNetif->name[1],
                  pNetif->num,
                  pPBuf));
 
-    /*
-     * We're on the lwip thread ...
-     * try accure Xmit lock (actually we DO accure the lock ... )
-     * 1. we've entered csXmit so we should create frame
-     *   1.a. Frame creation success see 2.
-     *   1.b. (hm ... what about queue processing in place)
-     *   1.c. 2nd attempt create frame
-     *   1.d. Unlock the Xmit
-     *   1.e. goto BUSY.1
-     * 2. Copy pbuf to the frame
-     * 3. Send
-     * 4. leave csXmit & return.
-     *
-     * @todo: perhaps we can use it for optimization,
-     * e.g. drop UDP and reoccure lock on TCP NOTE: now BUSY is unachievable!
-     * Otherwise (BUSY)
-     * 1. Unbuffered (drop)
-     * (buffered)
-     * 1. Copy pbuf to entermediate buffer.
-     * 2. Add call buffer to the queue
-     * 3. return.
-     */
-    /* see p.1 */
-    rc = VINF_SUCCESS;
-    PINTNETHDR pHdr = NULL;
-    uint8_t *pu8Frame = NULL;
-    int offFrame = 0;
-    int idxSg = 0;
-    struct pbuf *pPBufPtr = pPBuf;
-    /* Allocate frame, and pad it if required. */
-    rc = IntNetRingAllocateFrame(&g_pLwipNat->m_pIfBuf->Send, pPBuf->tot_len, &pHdr, (void **)&pu8Frame);
-    if (RT_SUCCESS(rc))
-    {
-        /* see p. 2 */
-        while (pPBufPtr)
-        {
-            memcpy(&pu8Frame[offFrame], pPBufPtr->payload, pPBufPtr->len);
-            offFrame += pPBufPtr->len;
-            pPBufPtr = pPBufPtr->next;
-        }
-    }
-    if (RT_FAILURE(rc))
+    RT_ZERO(VBoxNetLwipNAT::aXmitSeg);
+    
+    size_t idx = 0;
+    for (struct pbuf *q = pPBuf; q != NULL; q = q->next, ++idx)
     {
-        /* Could it be that some frames are still in the ring buffer */
-        /* 1.c */
-        AssertMsgFailed(("Debug Me!"));
+        AssertReturn(idx < RT_ELEMENTS(VBoxNetLwipNAT::aXmitSeg), ERR_MEM);
+        VBoxNetLwipNAT::aXmitSeg[idx].pv = q->payload; 
+        VBoxNetLwipNAT::aXmitSeg[idx].cb = q->len;
     }
 
-    /* Commit - what really this function do  */
-    IntNetRingCommitFrameEx(&g_pLwipNat->m_pIfBuf->Send, pHdr, pPBuf->tot_len);
+    int rc = g_pLwipNat->sendBufferOnWire(VBoxNetLwipNAT::aXmitSeg, idx, pPBuf->tot_len);
+    AssertRCReturn(rc, ERR_IF);
 
-    g_pLwipNat->vboxNetLwipNATProcessXmit();
+    g_pLwipNat->flushWire();
 
-    AssertRCReturn(rc, ERR_IF);
-    LogFlowFunc(("LEAVE: %d\n", rcLwip));
-    return rcLwip;
+    LogFlowFunc(("LEAVE: %d\n", ERR_OK));
+    return ERR_OK;
 }
 
 
-VBoxNetLwipNAT::VBoxNetLwipNAT()
+VBoxNetLwipNAT::VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6) : VBoxNetBaseService("VBoxNetNAT", "nat-network")
 {
     LogFlowFuncEnter();
 
     m_ProxyOptions.ipv6_enabled = 0;
     m_ProxyOptions.ipv6_defroute = 0;
+    m_ProxyOptions.icmpsock4 = icmpsock4;
+    m_ProxyOptions.icmpsock6 = icmpsock6;
     m_ProxyOptions.tftp_root = NULL;
     m_ProxyOptions.src4 = NULL;
     m_ProxyOptions.src6 = NULL;
@@ -786,21 +581,27 @@ VBoxNetLwipNAT::VBoxNetLwipNAT()
 
     m_LwipNetIf.name[0] = 'N';
     m_LwipNetIf.name[1] = 'T';
-    m_MacAddress.au8[0] = 0x52;
-    m_MacAddress.au8[1] = 0x54;
-    m_MacAddress.au8[2] = 0;
-    m_MacAddress.au8[3] = 0x12;
-    m_MacAddress.au8[4] = 0x35;
-    m_MacAddress.au8[5] = 0;
-    m_Ipv4Address.u     = RT_MAKE_U32_FROM_U8( 10,  0,  2,  2); // NB: big-endian
-    m_Ipv4Netmask.u     = RT_H2N_U32_C(0xffffff00);
+
+    RTMAC mac;
+    mac.au8[0] = 0x52;
+    mac.au8[1] = 0x54;
+    mac.au8[2] = 0;
+    mac.au8[3] = 0x12;
+    mac.au8[4] = 0x35;
+    mac.au8[5] = 0;
+    setMacAddress(mac);
+
+    RTNETADDRIPV4 address;
+    address.u     = RT_MAKE_U32_FROM_U8( 10,  0,  2,  2); // NB: big-endian
+    setIpv4Address(address);
+
+    address.u     = RT_H2N_U32_C(0xffffff00);
+    setIpv4Netmask(address);
 
     fDontLoadRulesOnStartup = false;
 
     for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
-        m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
-
-    m_enmTrunkType = kIntNetTrunkType_SrvNat;
+        addCommandLineOption(&g_aGetOptDef[i]);
 
     LogFlowFuncLeave();
 }
@@ -888,58 +689,37 @@ int VBoxNetLwipNAT::natServiceProcessRegisteredPf(VECNATSERVICEPF& vecRules){
 }
 
 
+/** This method executed on main thread, only at the end threr're one threads started explcitly (LWIP and later in ::run()
+ * RECV)
+ */
 int VBoxNetLwipNAT::init()
 {
-    HRESULT hrc;
     LogFlowFuncEnter();
 
-
     /* virtualbox initialized in super class */
-
     int rc = ::VBoxNetBaseService::init();
     AssertRCReturn(rc, rc);
 
-    hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_Network.c_str()).raw(),
-                                                  m_net.asOutParam());
-    AssertComRCReturn(hrc, VERR_NOT_FOUND);
-
-    hrc = m_listener.createObject();
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-
-    hrc = m_listener->init(new NATNetworkListener(), this);
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-
-    ComPtr<IEventSource> esNet;
-    hrc = m_net->COMGETTER(EventSource)(esNet.asOutParam());
-    AssertComRC(hrc);
+    std::string networkName = getNetwork();
+    rc = findNatNetwork(virtualbox, networkName, m_net);
+    AssertRCReturn(rc, rc);
 
-    com::SafeArray<VBoxEventType_T> aNetEvents;
+    ComEventTypeArray aNetEvents;
     aNetEvents.push_back(VBoxEventType_OnNATNetworkPortForward);
     aNetEvents.push_back(VBoxEventType_OnNATNetworkSetting);
-    hrc = esNet->RegisterListener(m_listener, ComSafeArrayAsInParam(aNetEvents), true);
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+    rc = createNatListener(m_listener, virtualbox, this, aNetEvents);
+    AssertRCReturn(rc, rc);
 
 
     // resolver changes are reported on vbox but are retrieved from
     // host so stash a pointer for future lookups
-    hrc = virtualbox->COMGETTER(Host)(m_host.asOutParam());
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-
-    hrc = m_vboxListener.createObject();
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-
-    hrc = m_vboxListener->init(new NATNetworkListener(), this);
+    HRESULT hrc = virtualbox->COMGETTER(Host)(m_host.asOutParam());
     AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
 
-    ComPtr<IEventSource> esVBox;
-    hrc = virtualbox->COMGETTER(EventSource)(esVBox.asOutParam());
-    AssertComRC(hrc);
-
-    com::SafeArray<VBoxEventType_T> aVBoxEvents;
+    ComEventTypeArray aVBoxEvents;
     aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
-    hrc = esVBox->RegisterListener(m_vboxListener, ComSafeArrayAsInParam(aVBoxEvents), true);
-    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-
+    rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
+    AssertRCReturn(rc, rc);
 
     BOOL fIPv6Enabled = FALSE;
     hrc = m_net->COMGETTER(IPv6Enabled)(&fIPv6Enabled);
@@ -956,7 +736,7 @@ int VBoxNetLwipNAT::init()
     m_ProxyOptions.ipv6_defroute = fIPv6DefaultRoute;
 
 
-    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4",m_Network.c_str());
+    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str());
     com::Bstr bstrSourceIpX;
     hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIpX.asOutParam());
     if (SUCCEEDED(hrc))
@@ -976,77 +756,25 @@ int VBoxNetLwipNAT::init()
 
     if (!fDontLoadRulesOnStartup)
     {
-        /* XXX: extract function and do not duplicate */
-        com::SafeArray<BSTR> rules;
-        hrc = m_net->COMGETTER(PortForwardRules4)(ComSafeArrayAsOutParam(rules));
-        Assert(SUCCEEDED(hrc));
-
-        size_t idxRules = 0;
-        for (idxRules = 0; idxRules < rules.size(); ++idxRules)
-        {
-            Log(("%d-rule: %ls\n", idxRules, rules[idxRules]));
-            NATSEVICEPORTFORWARDRULE Rule;
-            RT_ZERO(Rule);
-            rc = netPfStrToPf(com::Utf8Str(rules[idxRules]).c_str(), 0, &Rule.Pfr);
-            AssertRC(rc);
-            m_vecPortForwardRule4.push_back(Rule);
-        }
-
-        rules.setNull();
-        hrc = m_net->COMGETTER(PortForwardRules6)(ComSafeArrayAsOutParam(rules));
-        Assert(SUCCEEDED(hrc));
-
-        for (idxRules = 0; idxRules < rules.size(); ++idxRules)
-        {
-            Log(("%d-rule: %ls\n", idxRules, rules[idxRules]));
-            NATSEVICEPORTFORWARDRULE Rule;
-            netPfStrToPf(com::Utf8Str(rules[idxRules]).c_str(), 1, &Rule.Pfr);
-            m_vecPortForwardRule6.push_back(Rule);
-        }
+        fetchNatPortForwardRules(m_net, false, m_vecPortForwardRule4);
+        fetchNatPortForwardRules(m_net, true, m_vecPortForwardRule6);
     } /* if (!fDontLoadRulesOnStartup) */
 
-    com::SafeArray<BSTR> strs;
-    int count_strs;
-    hrc = m_net->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));
-    if (   SUCCEEDED(hrc)
-           && (count_strs = strs.size()))
+    AddressToOffsetMapping tmp;
+    rc = localMappings(m_net, tmp);
+    if (RT_SUCCESS(rc) && tmp.size() != 0)
     {
-        unsigned int j = 0;
-        int i;
-
-        for (i = 0; i < count_strs && j < RT_ELEMENTS(m_lo2off); ++i)
+        unsigned long i = 0;
+        for (AddressToOffsetMapping::iterator it = tmp.begin();
+             it != tmp.end() && i < RT_ELEMENTS(m_lo2off);
+             ++it, ++i)
         {
-            char szAddr[17];
-            RTNETADDRIPV4 ip4addr;
-            char *pszTerm;
-            uint32_t u32Off;
-            com::Utf8Str strLo2Off(strs[i]);
-            const char *pszLo2Off = strLo2Off.c_str();
-
-            RT_ZERO(szAddr);
-
-            pszTerm = RTStrStr(pszLo2Off, "=");
-
-            if (   !pszTerm
-                || (pszTerm - pszLo2Off) >= 17)
-                continue;
-
-            memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));
-            rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);
-            if (RT_FAILURE(rc))
-                continue;
-
-            u32Off = RTStrToUInt32(pszTerm + 1);
-            if (u32Off == 0)
-                continue;
-
-            ip4_addr_set_u32(&m_lo2off[j].loaddr, ip4addr.u);
-            m_lo2off[j].off = u32Off;
-            ++j;
+            ip4_addr_set_u32(&m_lo2off[i].loaddr, it->first.u);
+            m_lo2off[i].off = it->second;
         }
 
         m_loOptDescriptor.lomap = m_lo2off;
-        m_loOptDescriptor.num_lomap = j;
+        m_loOptDescriptor.num_lomap = i;
         m_ProxyOptions.lomap_desc = &m_loOptDescriptor;
     }
 
@@ -1067,26 +795,10 @@ int VBoxNetLwipNAT::init()
 
     /* end of COM initialization */
 
-    rc = RTSemEventCreate(&hSemSVC);
-    AssertRCReturn(rc, rc);
-
-    rc = RTReqQueueCreate(&hReqIntNet);
-    AssertRCReturn(rc, rc);
-
     g_pLwipNat->tryGoOnline();
+    /* this starts LWIP thread */
     vboxLwipCoreInitialize(VBoxNetLwipNAT::onLwipTcpIpInit, this);
 
-    rc = RTThreadCreate(&g_pLwipNat->hThrIntNetRecv, /* thread handle*/
-                        VBoxNetLwipNAT::intNetThreadRecv,  /* routine */
-                        NULL, /* user data */
-                        128 * _1K, /* stack size */
-                        RTTHREADTYPE_IO, /* type */
-                        0, /* flags, @todo: waitable ?*/
-                        "INTNET-RECV");
-    AssertRCReturn(rc,rc);
-
-
-
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
@@ -1168,18 +880,70 @@ int VBoxNetLwipNAT::parseOpt(int rc, const RTGETOPTUNION& Val)
 }
 
 
-int VBoxNetLwipNAT::run()
+int VBoxNetLwipNAT::processFrame(void *pvFrame, size_t cbFrame)
 {
-    /* EventQueue processing from VBoxHeadless.cpp */
-    com::NativeEventQueue         *gEventQ = NULL;
-    gEventQ = com::NativeEventQueue::getMainEventQueue();
-    while(true)
+    AssertReturn(pvFrame && cbFrame, VERR_INVALID_PARAMETER);
+
+    struct  pbuf *pPbufHdr, *pPbuf;
+    pPbufHdr = pPbuf = pbuf_alloc(PBUF_RAW, cbFrame, PBUF_POOL);
+
+    AssertMsgReturn(pPbuf, ("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame), VERR_INTERNAL_ERROR);
+    AssertReturn(pPbufHdr->tot_len == cbFrame, VERR_INTERNAL_ERROR);
+                    
+    uint8_t *pu8Frame = (uint8_t *)pvFrame;
+    while(pPbuf)
     {
-        /* XXX:todo: graceful termination */
-        gEventQ->processEventQueue(0);
-        gEventQ->processEventQueue(500);
+        memcpy(pPbuf->payload, pu8Frame, pPbuf->len);
+        pu8Frame += pPbuf->len;
+        pPbuf = pPbuf->next;
     }
 
+    m_LwipNetIf.input(pPbufHdr, &m_LwipNetIf);
+    
+    return VINF_SUCCESS;
+}
+
+
+int VBoxNetLwipNAT::processGSO(PCPDMNETWORKGSO pGso, size_t cbFrame)
+{
+    if (!PDMNetGsoIsValid(pGso, cbFrame,
+                          cbFrame - sizeof(PDMNETWORKGSO)))
+        return VERR_INVALID_PARAMETER;
+
+    cbFrame -= sizeof(PDMNETWORKGSO);
+    uint8_t         abHdrScratch[256];
+    uint32_t const  cSegs = PDMNetGsoCalcSegmentCount(pGso,
+                                                      cbFrame);
+    for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
+    {
+        uint32_t cbSegFrame;
+        void    *pvSegFrame =
+          PDMNetGsoCarveSegmentQD(pGso,
+                                  (uint8_t *)(pGso + 1),
+                                  cbFrame,
+                                  abHdrScratch,
+                                  iSeg,
+                                  cSegs,
+                                  &cbSegFrame);
+
+        struct pbuf *pPbuf = pbuf_alloc(PBUF_RAW, cbSegFrame, PBUF_POOL);
+
+        AssertMsgReturn(pPbuf, ("NAT: Can't allocate send buffer cbFrame=%u\n", cbSegFrame), VERR_INTERNAL_ERROR);
+        AssertReturn(!pPbuf->next && pPbuf->len == cbSegFrame, VERR_INTERNAL_ERROR);
+
+        memcpy(pPbuf->payload, pvSegFrame, cbSegFrame);
+        m_LwipNetIf.input(pPbuf, &g_pLwipNat->m_LwipNetIf);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+int VBoxNetLwipNAT::run()
+{
+    /* Father starts receiving thread and enter event loop. */
+    VBoxNetBaseService::run();
+
     vboxLwipCoreFinalize(VBoxNetLwipNAT::onLwipTcpIpFini, this);
 
     m_vecPortForwardRule4.clear();
@@ -1210,6 +974,79 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
     }
 #endif
 
+    SOCKET icmpsock4 = INVALID_SOCKET;
+    SOCKET icmpsock6 = INVALID_SOCKET;
+#ifndef RT_OS_DARWIN
+    const int icmpstype = SOCK_RAW;
+#else
+    /* on OS X it's not privileged */
+    const int icmpstype = SOCK_DGRAM;
+#endif
+
+    icmpsock4 = socket(AF_INET, icmpstype, IPPROTO_ICMP);
+    if (icmpsock4 == INVALID_SOCKET)
+    {
+        perror("IPPROTO_ICMP");
+#ifdef VBOX_RAWSOCK_DEBUG_HELPER
+        icmpsock4 = getrawsock(AF_INET);
+#endif
+    }
+
+    if (icmpsock4 != INVALID_SOCKET)
+    {
+#ifdef ICMP_FILTER              //  Linux specific
+        struct icmp_filter flt = {
+            ~(uint32_t)(
+                  (1U << ICMP_ECHOREPLY)
+                | (1U << ICMP_DEST_UNREACH)
+                | (1U << ICMP_TIME_EXCEEDED)
+            )
+        };
+
+        int status = setsockopt(icmpsock4, SOL_RAW, ICMP_FILTER,
+                                &flt, sizeof(flt));
+        if (status < 0)
+        {
+            perror("ICMP_FILTER");
+        }
+#endif
+    }
+
+    icmpsock6 = socket(AF_INET6, icmpstype, IPPROTO_ICMPV6);
+    if (icmpsock6 == INVALID_SOCKET)
+    {
+        perror("IPPROTO_ICMPV6");
+#ifdef VBOX_RAWSOCK_DEBUG_HELPER
+        icmpsock6 = getrawsock(AF_INET6);
+#endif
+    }
+
+    if (icmpsock6 != INVALID_SOCKET)
+    {
+#ifdef ICMP6_FILTER             // Windows doesn't support RFC 3542 API
+        /*
+         * XXX: We do this here for now, not in pxping.c, to avoid
+         * name clashes between lwIP and system headers.
+         */
+        struct icmp6_filter flt;
+        ICMP6_FILTER_SETBLOCKALL(&flt);
+
+        ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &flt);
+
+        ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &flt);
+        ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &flt);
+        ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &flt);
+        ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &flt);
+
+        int status = setsockopt(icmpsock6, IPPROTO_ICMPV6, ICMP6_FILTER,
+                                &flt, sizeof(flt));
+        if (status < 0)
+        {
+            perror("ICMP6_FILTER");
+        }
+#endif
+    }
+
     HRESULT hrc = com::Initialize();
 #ifdef VBOX_WITH_XPCOM
     if (hrc == NS_ERROR_FILE_ACCESS_DENIED)
@@ -1223,7 +1060,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
     if (FAILED(hrc))
         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM!");
 
-    g_pLwipNat = new VBoxNetLwipNAT();
+    g_pLwipNat = new VBoxNetLwipNAT(icmpsock4, icmpsock6);
 
     Log2(("NAT: initialization\n"));
     int rc = g_pLwipNat->parseArgs(argc - 1, argv + 1);
@@ -1242,6 +1079,33 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
 }
 
 
+static int fetchNatPortForwardRules(const ComNatPtr& nat, bool fIsIPv6, VECNATSERVICEPF& vec)
+{
+    HRESULT hrc;
+    com::SafeArray<BSTR> rules;
+    if (fIsIPv6)
+        hrc = nat->COMGETTER(PortForwardRules6)(ComSafeArrayAsOutParam(rules));
+    else
+        hrc = nat->COMGETTER(PortForwardRules4)(ComSafeArrayAsOutParam(rules));
+    AssertReturn(SUCCEEDED(hrc), VERR_INTERNAL_ERROR);
+
+    NATSEVICEPORTFORWARDRULE Rule;
+    for (size_t idxRules = 0; idxRules < rules.size(); ++idxRules)
+    {
+        Log(("%d-%s rule: %ls\n", idxRules, (fIsIPv6 ? "IPv6" : "IPv4"), rules[idxRules]));
+        RT_ZERO(Rule);
+
+        int rc = netPfStrToPf(com::Utf8Str(rules[idxRules]).c_str(), 0, &Rule.Pfr);
+        if (RT_FAILURE(rc))
+            continue;
+
+        vec.push_back(Rule);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
 #ifndef VBOX_WITH_HARDENING
 
 int main(int argc, char **argv, char **envp)
@@ -1355,4 +1219,3 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
 # endif /* RT_OS_WINDOWS */
 
 #endif /* !VBOX_WITH_HARDENING */
-
diff --git a/src/VBox/NetworkServices/NAT/fwtcp.c b/src/VBox/NetworkServices/NAT/fwtcp.c
index b51ffb9..fa0fde4 100644
--- a/src/VBox/NetworkServices/NAT/fwtcp.c
+++ b/src/VBox/NetworkServices/NAT/fwtcp.c
@@ -124,7 +124,7 @@ fwtcp_del(struct fwspec *fwspec)
     fwtcp->pmhdl.slot = -1;
 
     closesocket(fwtcp->sock);
-    fwtcp->sock = -1;
+    fwtcp->sock = INVALID_SOCKET;
 
     /* let pending msg_connect be processed before we delete fwtcp */
     proxy_lwip_post(&fwtcp->msg_delete);
diff --git a/src/VBox/NetworkServices/NAT/fwudp.c b/src/VBox/NetworkServices/NAT/fwudp.c
index 72f26c7..1cc256f 100644
--- a/src/VBox/NetworkServices/NAT/fwudp.c
+++ b/src/VBox/NetworkServices/NAT/fwudp.c
@@ -486,6 +486,7 @@ fwudp_pcb_forward_outbound(struct fwudp *fwudp, struct udp_pcb *pcb,
     }
 
     proxy_sendto(fwudp->sock, p, &peer, namelen);
+    pbuf_free(p);
 }
 
 
diff --git a/src/VBox/NetworkServices/NAT/portfwd.c b/src/VBox/NetworkServices/NAT/portfwd.c
index 7ea39d6..c579caf 100644
--- a/src/VBox/NetworkServices/NAT/portfwd.c
+++ b/src/VBox/NetworkServices/NAT/portfwd.c
@@ -136,7 +136,6 @@ fwspec_set(struct fwspec *fwspec, int sdom, int stype,
     struct addrinfo hints;
     struct addrinfo *ai;
     int status;
-    void *src_addr, *dst_addr;
 
     LWIP_ASSERT1(sdom == PF_INET || sdom == PF_INET6);
     LWIP_ASSERT1(stype == SOCK_STREAM || stype == SOCK_DGRAM);
diff --git a/src/VBox/NetworkServices/NAT/proxy.c b/src/VBox/NetworkServices/NAT/proxy.c
index c8e20b0..537ae85 100644
--- a/src/VBox/NetworkServices/NAT/proxy.c
+++ b/src/VBox/NetworkServices/NAT/proxy.c
@@ -85,6 +85,8 @@ proxy_init(struct netif *proxy_netif, struct proxy_options *opts)
 
     pxdns_init(proxy_netif);
 
+    pxping_init(proxy_netif, opts->icmpsock4, opts->icmpsock6);
+
     pollmgr_tid = sys_thread_new("pollmgr_thread",
                                  pollmgr_thread, NULL,
                                  DEFAULT_THREAD_STACKSIZE,
@@ -397,21 +399,23 @@ proxy_reset_socket(SOCKET s)
 }
 
 
-void
+int
 proxy_sendto(SOCKET sock, struct pbuf *p, void *name, size_t namelen)
 {
     struct pbuf *q;
     size_t i, clen;
 #ifndef RT_OS_WINDOWS
     struct msghdr mh;
+    ssize_t nsent;
 #else
+    DWORD nsent;
     int rc;
 #endif
     IOVEC fixiov[8];     /* fixed size (typical case) */
     const size_t fixiovsize = sizeof(fixiov)/sizeof(fixiov[0]);
     IOVEC *dyniov;       /* dynamically sized */
     IOVEC *iov;
-    ssize_t nsent;
+    int error = 0;
 
     /*
      * Static iov[] is usually enough since UDP protocols use small
@@ -424,6 +428,7 @@ proxy_sendto(SOCKET sock, struct pbuf *p, void *name, size_t namelen)
          */
         dyniov = (IOVEC *)malloc(clen * sizeof(*dyniov));
         if (dyniov == NULL) {
+            error = -errno;
             goto out;
         }
         iov = dyniov;
@@ -450,14 +455,17 @@ proxy_sendto(SOCKET sock, struct pbuf *p, void *name, size_t namelen)
 
     nsent = sendmsg(sock, &mh, 0);
     if (nsent < 0) {
+        error = -errno;
         DPRINTF(("%s: fd %d: sendmsg errno %d\n",
                  __func__, sock, errno));
     }
 #else
-    rc = WSASendTo(sock, iov, (DWORD)clen, (DWORD *)&nsent, 0, name, (int)namelen, NULL, NULL);
+    rc = WSASendTo(sock, iov, (DWORD)clen, &nsent, 0,
+                   name, (int)namelen, NULL, NULL);
     if (rc == SOCKET_ERROR) {
          DPRINTF(("%s: fd %d: sendmsg errno %d\n",
                   __func__, sock, WSAGetLastError()));
+         error = -WSAGetLastError();
     }
 #endif
 
@@ -465,7 +473,7 @@ proxy_sendto(SOCKET sock, struct pbuf *p, void *name, size_t namelen)
     if (dyniov != NULL) {
         free(dyniov);
     }
-    pbuf_free(p);
+    return error;
 }
 
 
diff --git a/src/VBox/NetworkServices/NAT/proxy.h b/src/VBox/NetworkServices/NAT/proxy.h
index eab10c5..20df34b 100644
--- a/src/VBox/NetworkServices/NAT/proxy.h
+++ b/src/VBox/NetworkServices/NAT/proxy.h
@@ -32,6 +32,8 @@ struct ip4_lomap_desc
 struct proxy_options {
     int ipv6_enabled;
     int ipv6_defroute;
+    SOCKET icmpsock4;
+    SOCKET icmpsock6;
     const char *tftp_root;
     const struct sockaddr_in *src4;
     const struct sockaddr_in6 *src6;
@@ -46,7 +48,7 @@ void proxy_init(struct netif *, struct proxy_options *);
 SOCKET proxy_connected_socket(int, int, ipX_addr_t *, u16_t);
 SOCKET proxy_bound_socket(int, int, struct sockaddr *);
 void proxy_reset_socket(SOCKET);
-void proxy_sendto(SOCKET, struct pbuf *, void *, size_t);
+int proxy_sendto(SOCKET, struct pbuf *, void *, size_t);
 void proxy_lwip_post(struct tcpip_msg *);
 const char *proxy_lwip_strerr(err_t);
 
@@ -73,6 +75,9 @@ void pxudp_init(void);
 err_t pxdns_init(struct netif *);
 void pxdns_set_nameservers(void *);
 
+/* pxping.c */
+err_t pxping_init(struct netif *, SOCKET, SOCKET);
+
 
 #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
 # define HAVE_SA_LEN 0
diff --git a/src/VBox/NetworkServices/NAT/proxy_pollmgr.c b/src/VBox/NetworkServices/NAT/proxy_pollmgr.c
index f222d6f..054eceb 100644
--- a/src/VBox/NetworkServices/NAT/proxy_pollmgr.c
+++ b/src/VBox/NetworkServices/NAT/proxy_pollmgr.c
@@ -120,7 +120,7 @@ pollmgr_init(void)
     pollmgr.nfds = POLLMGR_SLOT_STATIC_COUNT;
 
     for (i = 0; i < pollmgr.capacity; ++i) {
-        pollmgr.fds[i].fd = -1;
+        pollmgr.fds[i].fd = INVALID_SOCKET;
         pollmgr.fds[i].events = 0;
         pollmgr.fds[i].revents = 0;
     }
@@ -199,7 +199,7 @@ pollmgr_add(struct pollmgr_handler *handler, SOCKET fd, int events)
         pollmgr.capacity = newcap;
 
         for (i = pollmgr.nfds; i < newcap; ++i) {
-            newfds[i].fd = -1;
+            newfds[i].fd = INVALID_SOCKET;
             newfds[i].events = 0;
             newfds[i].revents = 0;
             newhdls[i] = NULL;
diff --git a/src/VBox/NetworkServices/NAT/proxy_rtadvd.c b/src/VBox/NetworkServices/NAT/proxy_rtadvd.c
index 1eba619..f3a1086 100644
--- a/src/VBox/NetworkServices/NAT/proxy_rtadvd.c
+++ b/src/VBox/NetworkServices/NAT/proxy_rtadvd.c
@@ -198,7 +198,7 @@ rtadvd_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip6_addr_t *addr)
 
     lladdr_opt = NULL;
     while (p->len > 0) {
-        unsigned int optlen;
+        int optlen;
 
         if (p->len < 8) {
             ICMP6_STATS_INC(icmp6.lenerr);
diff --git a/src/VBox/NetworkServices/NAT/pxdns.c b/src/VBox/NetworkServices/NAT/pxdns.c
index 417c364..2f3b19f 100644
--- a/src/VBox/NetworkServices/NAT/pxdns.c
+++ b/src/VBox/NetworkServices/NAT/pxdns.c
@@ -93,6 +93,7 @@ struct pxdns {
 
 #define TIMEOUT 5
     size_t timeout_slot;
+    u32_t timeout_mask;
     struct request *timeout_list[TIMEOUT];
 
 #define HASHSIZE 10
@@ -144,6 +145,11 @@ struct request {
     struct request *next_timeout;
 
     /**
+     * Slot in pxdns::timeout_list
+     */
+    size_t timeout_slot;
+
+    /**
      * Pbuf with reply received on pollmgr thread.
      */
     struct pbuf *reply;
@@ -251,6 +257,7 @@ pxdns_init(struct netif *proxy_netif)
     sys_mutex_new(&pxdns->lock);
 
     pxdns->timeout_slot = 0;
+    pxdns->timeout_mask = 0;
 
     /* NB: assumes pollmgr thread is not running yet */
     pollmgr_add(&pxdns->pmhdl4, pxdns->sock4, POLLIN);
@@ -258,8 +265,6 @@ pxdns_init(struct netif *proxy_netif)
         pollmgr_add(&pxdns->pmhdl6, pxdns->sock6, POLLIN);
     }
 
-    sys_timeout(1 * 1000, pxdns_timer, pxdns);
-
     return ERR_OK;
 
   err_cleanup_pcb:
@@ -417,14 +422,23 @@ static void
 pxdns_timeout_add(struct pxdns *pxdns, struct request *req)
 {
     struct request **chain;
+    u32_t omask;
 
     LWIP_ASSERT1(req->pprev_timeout == NULL);
-    chain = &pxdns->timeout_list[pxdns->timeout_slot];
+
+    req->timeout_slot = pxdns->timeout_slot;
+    chain = &pxdns->timeout_list[req->timeout_slot];
     if ((req->next_timeout = *chain) != NULL) {
         (*chain)->pprev_timeout = &req->next_timeout;
     }
     *chain = req;
     req->pprev_timeout = chain;
+
+    omask = pxdns->timeout_mask;
+    pxdns->timeout_mask |= 1U << req->timeout_slot;
+    if (omask == 0) {
+        sys_timeout(1 * 1000, pxdns_timer, pxdns);
+    }
 }
 
 
@@ -447,6 +461,7 @@ static void
 pxdns_timeout_del(struct pxdns *pxdns, struct request *req)
 {
     LWIP_ASSERT1(req->pprev_timeout != NULL);
+    LWIP_ASSERT1(req->timeout_slot < TIMEOUT);
 
     if (req->next_timeout != NULL) {
         req->next_timeout->pprev_timeout = req->pprev_timeout;
@@ -454,6 +469,11 @@ pxdns_timeout_del(struct pxdns *pxdns, struct request *req)
     *req->pprev_timeout = req->next_timeout;
     req->pprev_timeout = NULL;
     req->next_timeout = NULL;
+
+    if (pxdns->timeout_list[req->timeout_slot] == NULL) {
+        pxdns->timeout_mask &= ~(1U << req->timeout_slot);
+        /* may be on pollmgr thread so no sys_untimeout */
+    }
 }
 
 
@@ -525,6 +545,7 @@ pxdns_timer(void *arg)
 {
     struct pxdns *pxdns = (struct pxdns *)arg;
     struct request **chain, *req;
+    u32_t mask;
 
     sys_mutex_lock(&pxdns->lock);
 
@@ -556,9 +577,19 @@ pxdns_timer(void *arg)
         pxdns_request_free(expired);
     }
 
+    if (pxdns->timeout_list[pxdns->timeout_slot] == NULL) {
+        pxdns->timeout_mask &= ~(1U << pxdns->timeout_slot);
+    }
+    else {
+        pxdns->timeout_mask |= 1U << pxdns->timeout_slot;
+    }
+    mask = pxdns->timeout_mask;
+
     sys_mutex_unlock(&pxdns->lock);
 
-    sys_timeout(1 * 1000, pxdns_timer, pxdns);
+    if (mask != 0) {
+        sys_timeout(1 * 1000, pxdns_timer, pxdns);
+    }
 }
 
 
diff --git a/src/VBox/NetworkServices/NAT/pxping.c b/src/VBox/NetworkServices/NAT/pxping.c
new file mode 100644
index 0000000..0c3672d
--- /dev/null
+++ b/src/VBox/NetworkServices/NAT/pxping.c
@@ -0,0 +1,1937 @@
+/* -*- indent-tabs-mode: nil; -*- */
+
+#include "winutils.h"
+#include "proxy.h"
+#include "proxy_pollmgr.h"
+#include "pxremap.h"
+
+#ifndef RT_OS_WINDOWS
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef RT_OS_DARWIN
+# define __APPLE_USE_RFC_3542
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>          /* XXX: inet_ntop */
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#else
+#include <iprt/stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "winpoll.h"
+#endif
+
+#include "lwip/opt.h"
+
+#include "lwip/sys.h"
+#include "lwip/tcpip.h"
+#include "lwip/inet_chksum.h"
+#include "lwip/ip.h"
+#include "lwip/icmp.h"
+
+#if defined(RT_OS_LINUX) && !defined(__USE_GNU)
+#if __GLIBC_PREREQ(2, 8)
+/*
+ * XXX: This is gross.  in6_pktinfo is now hidden behind _GNU_SOURCE
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=6775
+ *
+ * But in older glibc versions, e.g. RHEL5, it is not!  I don't want
+ * to deal with _GNU_SOURCE now, so as a kludge check for glibc
+ * version.  It seems the __USE_GNU guard was introduced in 2.8.
+ */
+struct in6_pktinfo {
+    struct in6_addr ipi6_addr;
+    unsigned int ipi6_ifindex;
+};
+#endif  /* __GLIBC_PREREQ */
+#endif  /* RT_OS_LINUX && !__USE_GNU */
+
+
+/* forward */
+struct ping_pcb;
+
+
+/**
+ * Global state for ping proxy collected in one entity to minimize
+ * globals.  There's only one instance of this structure.
+ *
+ * Raw ICMP sockets are promiscuous, so it doesn't make sense to have
+ * multiple.  If this code ever needs to support multiple netifs, the
+ * netif member should be exiled into "pcb".
+ */
+struct pxping {
+    SOCKET sock4;
+
+#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
+#   define DF_WITH_IP_HDRINCL
+    int hdrincl;
+#else
+    int df;
+#endif
+    int ttl;
+    int tos;
+
+    SOCKET sock6;
+#ifdef RT_OS_WINDOWS
+    LPFN_WSARECVMSG pfWSARecvMsg6;
+#endif
+    int hopl;
+
+    struct pollmgr_handler pmhdl4;
+    struct pollmgr_handler pmhdl6;
+
+    struct netif *netif;
+
+    /**
+     * Protect lwIP and pmgr accesses to the list of pcbs.
+     */
+    sys_mutex_t lock;
+
+    /*
+     * We need to find pcbs both from the guest side and from the host
+     * side.  If we need to support industrial grade ping throughput,
+     * we will need two pcb hashes.  For now, a short linked list
+     * should be enough.  Cf. pxping_pcb_for_request() and
+     * pxping_pcb_for_reply().
+     */
+#define PXPING_MAX_PCBS 8
+    size_t npcbs;
+    struct ping_pcb *pcbs;
+
+#define TIMEOUT 5
+    int timer_active;
+    size_t timeout_slot;
+    struct ping_pcb *timeout_list[TIMEOUT];
+};
+
+
+/**
+ * Quasi PCB for ping.
+ */
+struct ping_pcb {
+    ipX_addr_t src;
+    ipX_addr_t dst;
+
+    u8_t is_ipv6;
+    u8_t is_mapped;
+
+    u16_t guest_id;
+    u16_t host_id;
+
+    /**
+     * Desired slot in pxping::timeout_list.  See pxping_timer().
+     */
+    size_t timeout_slot;
+
+    /**
+     * Chaining for pxping::timeout_list
+     */
+    struct ping_pcb **pprev_timeout;
+    struct ping_pcb *next_timeout;
+
+    /**
+     * Chaining for pxping::pcbs
+     */
+    struct ping_pcb *next;
+
+    union {
+        struct sockaddr_in sin;
+        struct sockaddr_in6 sin6;
+    } peer;
+};
+
+
+/**
+ * lwIP thread callback message for IPv4 ping.
+ *
+ * We pass raw IP datagram for ip_output_if() so we only need pbuf and
+ * netif (from pxping).
+ */
+struct ping_msg {
+    struct tcpip_msg msg;
+    struct pxping *pxping;
+    struct pbuf *p;
+};
+
+
+/**
+ * lwIP thread callback message for IPv6 ping.
+ *
+ * We cannot obtain raw IPv6 datagram from host without extra trouble,
+ * so we pass ICMPv6 payload in pbuf and also other parameters to
+ * ip6_output_if().
+ */
+struct ping6_msg {
+    struct tcpip_msg msg;
+    struct pxping *pxping;
+    struct pbuf *p;
+    ip6_addr_t src, dst;
+    int hopl, tclass;
+};
+
+
+#ifdef RT_OS_WINDOWS
+static int pxping_init_windows(struct pxping *pxping);
+#endif
+static void pxping_recv4(void *arg, struct pbuf *p);
+static void pxping_recv6(void *arg, struct pbuf *p);
+
+static void pxping_timer(void *arg);
+static void pxping_timer_needed(struct pxping *pxping);
+
+static struct ping_pcb *pxping_pcb_for_request(struct pxping *pxping,
+                                               int is_ipv6,
+                                               ipX_addr_t *src, ipX_addr_t *dst,
+                                               u16_t guest_id);
+static struct ping_pcb *pxping_pcb_for_reply(struct pxping *pxping, int is_ipv6,
+                                             ipX_addr_t *dst, u16_t host_id);
+
+static struct ping_pcb *pxping_pcb_allocate(struct pxping *pxping);
+static void pxping_pcb_register(struct pxping *pxping, struct ping_pcb *pcb);
+static void pxping_pcb_deregister(struct pxping *pxping, struct ping_pcb *pcb);
+static void pxping_pcb_delete(struct pxping *pxping, struct ping_pcb *pcb);
+static void pxping_timeout_add(struct pxping *pxping, struct ping_pcb *pcb);
+static void pxping_timeout_del(struct pxping *pxping, struct ping_pcb *pcb);
+static void pxping_pcb_debug_print(struct ping_pcb *pcb);
+
+static int pxping_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents);
+
+static void pxping_pmgr_icmp4(struct pxping *pxping);
+static void pxping_pmgr_icmp4_echo(struct pxping *pxping,
+                                   u16_t iplen, struct sockaddr_in *peer);
+static void pxping_pmgr_icmp4_error(struct pxping *pxping,
+                                    u16_t iplen, struct sockaddr_in *peer);
+static void pxping_pmgr_icmp6(struct pxping *pxping);
+static void pxping_pmgr_icmp6_echo(struct pxping *pxping,
+                                   ip6_addr_t *src, ip6_addr_t *dst,
+                                   int hopl, int tclass, u16_t icmplen);
+static void pxping_pmgr_icmp6_error(struct pxping *pxping,
+                                    ip6_addr_t *src, ip6_addr_t *dst,
+                                    int hopl, int tclass, u16_t icmplen);
+
+static void pxping_pmgr_forward_inbound(struct pxping *pxping, u16_t iplen);
+static void pxping_pcb_forward_inbound(void *arg);
+
+static void pxping_pmgr_forward_inbound6(struct pxping *pxping,
+                                         ip6_addr_t *src, ip6_addr_t *dst,
+                                         u8_t hopl, u8_t tclass,
+                                         u16_t icmplen);
+static void pxping_pcb_forward_inbound6(void *arg);
+
+/*
+ * NB: This is not documented except in RTFS.
+ *
+ * If ip_output_if() is passed dest == NULL then it treats p as
+ * complete IP packet with payload pointing to the IP header.  It does
+ * not build IP header, ignores all header-related arguments, fetches
+ * real destination from the header in the pbuf and outputs pbuf to
+ * the specified netif.
+ */
+#define ip_raw_output_if(p, netif)                      \
+    (ip_output_if((p), NULL, NULL, 0, 0, 0, (netif)))
+
+
+
+static struct pxping g_pxping;
+
+
+err_t
+pxping_init(struct netif *netif, SOCKET sock4, SOCKET sock6)
+{
+    const int on = 1;
+    int status;
+
+    if (sock4 == INVALID_SOCKET && sock6 == INVALID_SOCKET) {
+        return ERR_VAL;
+    }
+
+    g_pxping.netif = netif;
+    sys_mutex_new(&g_pxping.lock);
+
+    g_pxping.sock4 = sock4;
+    if (g_pxping.sock4 != INVALID_SOCKET) {
+#ifdef DF_WITH_IP_HDRINCL
+        g_pxping.hdrincl = -1;
+#else
+        g_pxping.df = -1;
+#endif
+        g_pxping.ttl = -1;
+        g_pxping.tos = 0;
+
+#ifdef RT_OS_LINUX
+        {
+            const int dont = IP_PMTUDISC_DONT;
+            status = setsockopt(sock4, IPPROTO_IP, IP_MTU_DISCOVER,
+                                &dont, sizeof(dont));
+            if (status != 0) {
+                perror("IP_MTU_DISCOVER");
+            }
+        }
+#endif /* RT_OS_LINUX */
+
+        g_pxping.pmhdl4.callback = pxping_pmgr_pump;
+        g_pxping.pmhdl4.data = (void *)&g_pxping;
+        g_pxping.pmhdl4.slot = -1;
+        pollmgr_add(&g_pxping.pmhdl4, g_pxping.sock4, POLLIN);
+
+        ping_proxy_accept(pxping_recv4, &g_pxping);
+    }
+
+    g_pxping.sock6 = sock6;
+#ifdef RT_OS_WINDOWS
+    /* we need recvmsg */
+    if (g_pxping.sock6 != INVALID_SOCKET) {
+        status = pxping_init_windows(&g_pxping);
+        if (status == SOCKET_ERROR) {
+            g_pxping.sock6 = INVALID_SOCKET;
+            /* close(sock6); */
+        }
+    }
+#endif
+    if (g_pxping.sock6 != INVALID_SOCKET) {
+        g_pxping.hopl = -1;
+
+#if !defined(IPV6_RECVPKTINFO)
+#define IPV6_RECVPKTINFO (IPV6_PKTINFO)
+#endif
+        status = setsockopt(sock6, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+                            (const char *)&on, sizeof(on));
+        if (status < 0) {
+            perror("IPV6_RECVPKTINFO");
+            /* XXX: for now this is fatal */
+        }
+
+#if !defined(IPV6_RECVHOPLIMIT)
+#define IPV6_RECVHOPLIMIT (IPV6_HOPLIMIT)
+#endif
+        status = setsockopt(sock6, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
+                            (const char *)&on, sizeof(on));
+        if (status < 0) {
+            perror("IPV6_RECVHOPLIMIT");
+        }
+
+#ifdef IPV6_RECVTCLASS  /* new in RFC 3542, there's no RFC 2292 counterpart */
+        /* TODO: IPV6_RECVTCLASS */
+#endif
+
+        g_pxping.pmhdl6.callback = pxping_pmgr_pump;
+        g_pxping.pmhdl6.data = (void *)&g_pxping;
+        g_pxping.pmhdl6.slot = -1;
+        pollmgr_add(&g_pxping.pmhdl6, g_pxping.sock6, POLLIN);
+
+        ping6_proxy_accept(pxping_recv6, &g_pxping);
+    }
+
+    return ERR_OK;
+}
+
+
+#ifdef RT_OS_WINDOWS
+static int
+pxping_init_windows(struct pxping *pxping)
+{
+    GUID WSARecvMsgGUID = WSAID_WSARECVMSG;
+    DWORD nread;
+    int status;
+
+    pxping->pfWSARecvMsg6 = NULL;
+    status = WSAIoctl(pxping->sock6,
+                      SIO_GET_EXTENSION_FUNCTION_POINTER,
+                      &WSARecvMsgGUID, sizeof(WSARecvMsgGUID),
+                      &pxping->pfWSARecvMsg6, sizeof(pxping->pfWSARecvMsg6),
+                      &nread,
+                      NULL, NULL);
+    return status;
+}
+#endif  /* RT_OS_WINDOWS */
+
+
+static u32_t
+chksum_delta_16(u16_t oval, u16_t nval)
+{
+    u32_t sum = (u16_t)~oval;
+    sum += nval;
+    return sum;
+}
+
+
+static u32_t
+chksum_update_16(u16_t *oldp, u16_t nval)
+{
+    u32_t sum = chksum_delta_16(*oldp, nval);
+    *oldp = nval;
+    return sum;
+}
+
+
+static u32_t
+chksum_delta_32(u32_t oval, u32_t nval)
+{
+    u32_t sum = ~oval;
+    sum = FOLD_U32T(sum);
+    sum += FOLD_U32T(nval);
+    return sum;
+}
+
+
+static u32_t
+chksum_update_32(u32_t *oldp, u32_t nval)
+{
+    u32_t sum = chksum_delta_32(*oldp, nval);
+    *oldp = nval;
+    return sum;
+}
+
+
+static u32_t
+chksum_delta_ipv6(const ip6_addr_t *oldp, const ip6_addr_t *newp)
+{
+    u32_t sum;
+
+    sum  = chksum_delta_32(oldp->addr[0], newp->addr[0]);
+    sum += chksum_delta_32(oldp->addr[1], newp->addr[1]);
+    sum += chksum_delta_32(oldp->addr[2], newp->addr[2]);
+    sum += chksum_delta_32(oldp->addr[3], newp->addr[3]);
+
+    return sum;
+}
+
+
+static u32_t
+chksum_update_ipv6(ip6_addr_t *oldp, const ip6_addr_t *newp)
+{
+    u32_t sum;
+
+    sum  = chksum_update_32(&oldp->addr[0], newp->addr[0]);
+    sum += chksum_update_32(&oldp->addr[1], newp->addr[1]);
+    sum += chksum_update_32(&oldp->addr[2], newp->addr[2]);
+    sum += chksum_update_32(&oldp->addr[3], newp->addr[3]);
+
+    return sum;
+}
+
+
+/**
+ * ICMP Echo Request in pbuf "p" is to be proxied.
+ */
+static void
+pxping_recv4(void *arg, struct pbuf *p)
+{
+    struct pxping *pxping = (struct pxping *)arg;
+    struct ping_pcb *pcb;
+#ifdef DF_WITH_IP_HDRINCL
+    struct ip_hdr iph_orig;
+#endif
+    struct icmp_echo_hdr icmph_orig;
+    struct ip_hdr *iph;
+    struct icmp_echo_hdr *icmph;
+    int df, ttl, tos;
+    u32_t sum;
+    u16_t iphlen;
+    int status;
+
+    iphlen = ip_current_header_tot_len();
+    if (iphlen != IP_HLEN) {    /* we don't do options */
+        pbuf_free(p);
+        return;
+    }
+
+    iph = (/* UNCONST */ struct ip_hdr *)ip_current_header();
+    icmph = (struct icmp_echo_hdr *)p->payload;
+
+    pcb = pxping_pcb_for_request(pxping, 0,
+                                 ipX_current_src_addr(),
+                                 ipX_current_dest_addr(),
+                                 icmph->id);
+    if (pcb == NULL) {
+        pbuf_free(p);
+        return;
+    }
+
+    pxping_pcb_debug_print(pcb); /* XXX */
+    DPRINTF((" seq %d len %u ttl %d\n",
+             ntohs(icmph->seqno), (unsigned int)p->tot_len,
+             IPH_TTL(iph)));
+
+    ttl = IPH_TTL(iph);
+    if (!pcb->is_mapped) {
+        if (RT_UNLIKELY(ttl == 1)) {
+            status = pbuf_header(p, iphlen); /* back to IP header */
+            if (RT_LIKELY(status == 0)) {
+                icmp_time_exceeded(p, ICMP_TE_TTL);
+            }
+            pbuf_free(p);
+            return;
+        }
+        --ttl;
+    }
+
+    /*
+     * OS X doesn't provide a socket option to control fragmentation.
+     * Solaris doesn't provide IP_DONTFRAG on all releases we support.
+     * In this case we have to use IP_HDRINCL.  We don't want to use
+     * it always since it doesn't handle fragmentation (but that's ok
+     * for DF) and Windows doesn't do automatic source address
+     * selection with IP_HDRINCL.
+     */
+    df = (IPH_OFFSET(iph) & PP_HTONS(IP_DF)) != 0;
+
+#ifdef DF_WITH_IP_HDRINCL
+    if (df != pxping->hdrincl) {
+        status = setsockopt(pxping->sock4, IPPROTO_IP, IP_HDRINCL,
+                            &df, sizeof(df));
+        if (RT_LIKELY(status == 0)) {
+            pxping->hdrincl = df;
+        }
+        else {
+            perror("IP_HDRINCL");
+        }
+    }
+
+    if (pxping->hdrincl) {
+        status = pbuf_header(p, iphlen); /* back to IP header */
+        if (RT_UNLIKELY(status != 0)) {
+            pbuf_free(p);
+            return;
+        }
+
+        /* we will overwrite IP header, save original for ICMP errors */
+        memcpy(&iph_orig, iph, iphlen);
+
+        if (g_proxy_options->src4 != NULL) {
+            memcpy(&iph->src, &g_proxy_options->src4->sin_addr,
+                   sizeof(g_proxy_options->src4->sin_addr));
+        }
+        else {
+            /* let the kernel select suitable source address */
+            memset(&iph->src, 0, sizeof(iph->src));
+        }
+
+        IPH_TTL_SET(iph, ttl);  /* already decremented */
+        IPH_ID_SET(iph, 0);     /* kernel will set one */
+#ifdef RT_OS_DARWIN
+        /* wants ip_offset and ip_len fields in host order */
+        IPH_OFFSET_SET(iph, ntohs(IPH_OFFSET(iph)));
+        IPH_LEN_SET(iph, ntohs(IPH_LEN(iph)));
+        /* wants checksum of everything (sic!), in host order */
+        sum = inet_chksum_pbuf(p);
+        IPH_CHKSUM_SET(iph, sum);
+#else /* !RT_OS_DARWIN  */
+        IPH_CHKSUM_SET(iph, 0); /* kernel will recalculate */
+#endif
+    }
+    else /* !pxping->hdrincl */
+#endif   /* DF_WITH_IP_HDRINCL */
+    {
+#if !defined(DF_WITH_IP_HDRINCL)
+        /* control DF flag via setsockopt(2) */
+#define USE_DF_OPTION(_Optname)                         \
+        const int dfopt = _Optname;                     \
+        const char * const dfoptname = #_Optname;
+#if   defined(RT_OS_LINUX)
+        USE_DF_OPTION(IP_MTU_DISCOVER);
+        df = df ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
+#elif defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
+        USE_DF_OPTION(IP_DONTFRAG);
+#elif defined(RT_OS_WINDOWS)
+        USE_DF_OPTION(IP_DONTFRAGMENT);
+#endif
+        if (df != pxping->df) {
+            status = setsockopt(pxping->sock4, IPPROTO_IP, dfopt,
+                                (char *)&df, sizeof(df));
+            if (RT_LIKELY(status == 0)) {
+                pxping->df = df;
+            }
+            else {
+                perror(dfoptname);
+            }
+        }
+#endif /* !DF_WITH_IP_HDRINCL */
+
+        if (ttl != pxping->ttl) {
+            status = setsockopt(pxping->sock4, IPPROTO_IP, IP_TTL,
+                                (char *)&ttl, sizeof(ttl));
+            if (RT_LIKELY(status == 0)) {
+                pxping->ttl = ttl;
+            }
+            else {
+                perror("IP_TTL");
+            }
+        }
+
+        tos = IPH_TOS(iph);
+        if (tos != pxping->tos) {
+            status = setsockopt(pxping->sock4, IPPROTO_IP, IP_TOS,
+                                (char *)&tos, sizeof(tos));
+            if (RT_LIKELY(status == 0)) {
+                pxping->tos = tos;
+            }
+            else {
+                perror("IP_TOS");
+            }
+        }
+    }
+
+    /* rewrite ICMP echo header */
+    memcpy(&icmph_orig, icmph, sizeof(*icmph));
+    sum = (u16_t)~icmph->chksum;
+    sum += chksum_update_16(&icmph->id, pcb->host_id);
+    sum = FOLD_U32T(sum);
+    icmph->chksum = ~sum;
+
+    status = proxy_sendto(pxping->sock4, p,
+                          &pcb->peer.sin, sizeof(pcb->peer.sin));
+    if (status != 0) {
+        int error = -status;
+        DPRINTF(("%s: sendto errno %d\n", __func__, error));
+
+#ifdef DF_WITH_IP_HDRINCL
+        if (pxping->hdrincl) {
+            /* restore original IP header */
+            memcpy(iph, &iph_orig, iphlen);
+        }
+        else
+#endif
+        {
+            status = pbuf_header(p, iphlen); /* back to IP header */
+            if (RT_UNLIKELY(status != 0)) {
+                pbuf_free(p);
+                return;
+            }
+        }
+
+        /* restore original ICMP header */
+        memcpy(icmph, &icmph_orig, sizeof(*icmph));
+
+        /*
+         * Some ICMP errors may be generated by the kernel and we read
+         * them from the socket and forward them normally, hence the
+         * ifdefs below.
+         */
+        switch (error) {
+
+#if !( defined(RT_OS_SOLARIS)                                   \
+    || (defined(RT_OS_LINUX) && !defined(DF_WITH_IP_HDRINCL))   \
+    )
+        case EMSGSIZE:
+            icmp_dest_unreach(p, ICMP_DUR_FRAG);
+            break;
+#endif
+
+        case ENETDOWN:
+        case ENETUNREACH:
+            icmp_dest_unreach(p, ICMP_DUR_NET);
+            break;
+
+        case EHOSTDOWN:
+        case EHOSTUNREACH:
+            icmp_dest_unreach(p, ICMP_DUR_HOST);
+            break;
+        }
+    }
+
+    pbuf_free(p);
+}
+
+
+/**
+ * ICMPv6 Echo Request in pbuf "p" is to be proxied.
+ */
+static void
+pxping_recv6(void *arg, struct pbuf *p)
+{
+    struct pxping *pxping = (struct pxping *)arg;
+    struct ping_pcb *pcb;
+    struct ip6_hdr *iph;
+    struct icmp6_echo_hdr *icmph;
+    int hopl;
+    u16_t iphlen;
+    u16_t id, seq;
+    int status;
+
+    iph = (/* UNCONST */ struct ip6_hdr *)ip6_current_header();
+    iphlen = ip_current_header_tot_len();
+
+    icmph = (struct icmp6_echo_hdr *)p->payload;
+
+    id  = icmph->id;
+    seq = icmph->seqno;
+
+    pcb = pxping_pcb_for_request(pxping, 1,
+                                 ipX_current_src_addr(),
+                                 ipX_current_dest_addr(),
+                                 id);
+    if (pcb == NULL) {
+        pbuf_free(p);
+        return;
+    }
+
+    pxping_pcb_debug_print(pcb); /* XXX */
+    DPRINTF((" seq %d len %u hopl %d\n",
+             ntohs(seq), (unsigned int)p->tot_len,
+             IP6H_HOPLIM(iph)));
+
+    hopl = IP6H_HOPLIM(iph);
+    if (!pcb->is_mapped) {
+        if (hopl == 1) {
+            status = pbuf_header(p, iphlen); /* back to IP header */
+            if (RT_LIKELY(status == 0)) {
+                icmp6_time_exceeded(p, ICMP6_TE_HL);
+            }
+            pbuf_free(p);
+            return;
+        }
+        --hopl;
+    }
+
+    /*
+     * Rewrite ICMPv6 echo header.  We don't need to recompute the
+     * checksum since, unlike IPv4, checksum includes pseudo-header.
+     * OS computes checksum for us on send() since it needs to select
+     * source address.
+     */
+    icmph->id = pcb->host_id;
+
+    /* TODO: use control messages to save a syscall? */
+    if (hopl != pxping->hopl) {
+        status = setsockopt(pxping->sock6, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+                            (char *)&hopl, sizeof(hopl));
+        if (status == 0) {
+            pxping->hopl = hopl;
+        }
+        else {
+            perror("IPV6_HOPLIMIT");
+        }
+    }
+
+    status = proxy_sendto(pxping->sock6, p,
+                          &pcb->peer.sin6, sizeof(pcb->peer.sin6));
+    if (status != 0) {
+        int error = -status;
+        DPRINTF(("%s: sendto errno %d\n", __func__, error));
+
+        status = pbuf_header(p, iphlen); /* back to IP header */
+        if (RT_UNLIKELY(status != 0)) {
+            pbuf_free(p);
+            return;
+        }
+
+        /* restore original ICMP header */
+        icmph->id = pcb->guest_id;
+
+        switch (error) {
+        case EACCES:
+            icmp6_dest_unreach(p, ICMP6_DUR_PROHIBITED);
+            break;
+
+#ifdef ENONET
+        case ENONET:
+#endif
+        case ENETDOWN:
+        case ENETUNREACH:
+        case EHOSTDOWN:
+        case EHOSTUNREACH:
+            icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
+            break;
+        }
+    }
+
+    pbuf_free(p);
+}
+
+
+static void
+pxping_pcb_debug_print(struct ping_pcb *pcb)
+{
+    char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+    const char *addrstr;
+    int sdom = pcb->is_ipv6 ? AF_INET6 : AF_INET;
+
+    DPRINTF(("ping %p:", (void *)pcb));
+
+    addrstr = inet_ntop(sdom, (void *)&pcb->src, addrbuf, sizeof(addrbuf));
+    DPRINTF((" %s", addrstr));
+
+    DPRINTF((" ->"));
+
+    addrstr = inet_ntop(sdom, (void *)&pcb->dst, addrbuf, sizeof(addrbuf));
+    DPRINTF((" %s", addrstr));
+
+    DPRINTF((" id %04x->%04x", ntohs(pcb->guest_id), ntohs(pcb->host_id)));
+}
+
+
+static struct ping_pcb *
+pxping_pcb_allocate(struct pxping *pxping)
+{
+    struct ping_pcb *pcb;
+
+    if (pxping->npcbs >= PXPING_MAX_PCBS) {
+        return NULL;
+    }
+
+    pcb = (struct ping_pcb *)malloc(sizeof(*pcb));
+    if (pcb == NULL) {
+        return NULL;
+    }
+
+    ++pxping->npcbs;
+    return pcb;
+}
+
+
+static void
+pxping_pcb_delete(struct pxping *pxping, struct ping_pcb *pcb)
+{
+    LWIP_ASSERT1(pxping->npcbs > 0);
+    LWIP_ASSERT1(pcb->next == NULL);
+    LWIP_ASSERT1(pcb->pprev_timeout == NULL);
+
+    DPRINTF(("%s: ping %p\n", __func__, (void *)pcb));
+
+    --pxping->npcbs;
+    free(pcb);
+}
+
+
+static void
+pxping_timeout_add(struct pxping *pxping, struct ping_pcb *pcb)
+{
+    struct ping_pcb **chain;
+
+    LWIP_ASSERT1(pcb->pprev_timeout == NULL);
+
+    chain = &pxping->timeout_list[pcb->timeout_slot];
+    if ((pcb->next_timeout = *chain) != NULL) {
+        (*chain)->pprev_timeout = &pcb->next_timeout;
+    }
+    *chain = pcb;
+    pcb->pprev_timeout = chain;
+}
+
+
+static void
+pxping_timeout_del(struct pxping *pxping, struct ping_pcb *pcb)
+{
+    LWIP_UNUSED_ARG(pxping);
+
+    LWIP_ASSERT1(pcb->pprev_timeout != NULL);
+    if (pcb->next_timeout != NULL) {
+        pcb->next_timeout->pprev_timeout = pcb->pprev_timeout;
+    }
+    *pcb->pprev_timeout = pcb->next_timeout;
+    pcb->pprev_timeout = NULL;
+    pcb->next_timeout = NULL;
+}
+
+
+static void
+pxping_pcb_register(struct pxping *pxping, struct ping_pcb *pcb)
+{
+    pcb->next = pxping->pcbs;
+    pxping->pcbs = pcb;
+
+    pxping_timeout_add(pxping, pcb);
+}
+
+
+static void
+pxping_pcb_deregister(struct pxping *pxping, struct ping_pcb *pcb)
+{
+    struct ping_pcb **p;
+
+    for (p = &pxping->pcbs; *p != NULL; p = &(*p)->next) {
+        if (*p == pcb) {
+            *p = pcb->next;
+            pcb->next = NULL;
+            break;
+        }
+    }
+
+    pxping_timeout_del(pxping, pcb);
+}
+
+
+static struct ping_pcb *
+pxping_pcb_for_request(struct pxping *pxping,
+                       int is_ipv6, ipX_addr_t *src, ipX_addr_t *dst,
+                       u16_t guest_id)
+{
+    struct ping_pcb *pcb;
+
+    /* on lwip thread, so no concurrent updates */
+    for (pcb = pxping->pcbs; pcb != NULL; pcb = pcb->next) {
+        if (pcb->guest_id == guest_id
+            && pcb->is_ipv6 == is_ipv6
+            && ipX_addr_cmp(is_ipv6, &pcb->dst, dst)
+            && ipX_addr_cmp(is_ipv6, &pcb->src, src))
+        {
+            break;
+        }
+    }
+
+    if (pcb == NULL) {
+        int mapped;
+
+        pcb = pxping_pcb_allocate(pxping);
+        if (pcb == NULL) {
+            return NULL;
+        }
+
+        pcb->is_ipv6 = is_ipv6;
+        ipX_addr_copy(is_ipv6, pcb->src, *src);
+        ipX_addr_copy(is_ipv6, pcb->dst, *dst);
+
+        pcb->guest_id = guest_id;
+#ifdef RT_OS_WINDOWS
+# define random() (rand())
+#endif
+        pcb->host_id = random() & 0xffffUL;
+
+        pcb->pprev_timeout = NULL;
+        pcb->next_timeout = NULL;
+
+        if (is_ipv6) {
+            pcb->peer.sin6.sin6_family = AF_INET6;
+#if HAVE_SA_LEN
+            pcb->peer.sin6.sin6_len = sizeof(pcb->peer.sin6);
+#endif
+            pcb->peer.sin6.sin6_port = htons(IPPROTO_ICMPV6);
+            pcb->peer.sin6.sin6_flowinfo = 0;
+            mapped = pxremap_outbound_ip6((ip6_addr_t *)&pcb->peer.sin6.sin6_addr,
+                                          ipX_2_ip6(&pcb->dst));
+        }
+        else {
+            pcb->peer.sin.sin_family = AF_INET;
+#if HAVE_SA_LEN
+            pcb->peer.sin.sin_len = sizeof(pcb->peer.sin);
+#endif
+            pcb->peer.sin.sin_port = htons(IPPROTO_ICMP);
+            mapped = pxremap_outbound_ip4((ip_addr_t *)&pcb->peer.sin.sin_addr,
+                                          ipX_2_ip(&pcb->dst));
+        }
+
+        if (mapped == PXREMAP_FAILED) {
+            free(pcb);
+            return NULL;
+        }
+        else {
+            pcb->is_mapped = (mapped == PXREMAP_MAPPED);
+        }
+
+        pcb->timeout_slot = pxping->timeout_slot;
+
+        sys_mutex_lock(&pxping->lock);
+        pxping_pcb_register(pxping, pcb);
+        sys_mutex_unlock(&pxping->lock);
+
+        pxping_pcb_debug_print(pcb); /* XXX */
+        DPRINTF((" - created\n"));
+
+        pxping_timer_needed(pxping);
+    }
+    else {
+        /* just bump up expiration timeout lazily */
+        pxping_pcb_debug_print(pcb); /* XXX */
+        DPRINTF((" - slot %d -> %d\n",
+                 (unsigned int)pcb->timeout_slot,
+                 (unsigned int)pxping->timeout_slot));
+        pcb->timeout_slot = pxping->timeout_slot;
+    }
+
+    return pcb;
+}
+
+
+/**
+ * Called on pollmgr thread.  Caller must do the locking since caller
+ * is going to use the returned pcb, which needs to be protected from
+ * being expired by pxping_timer() on lwip thread.
+ */
+static struct ping_pcb *
+pxping_pcb_for_reply(struct pxping *pxping,
+                     int is_ipv6, ipX_addr_t *dst, u16_t host_id)
+{
+    struct ping_pcb *pcb;
+
+    for (pcb = pxping->pcbs; pcb != NULL; pcb = pcb->next) {
+        if (pcb->host_id == host_id
+            && pcb->is_ipv6 == is_ipv6
+            /* XXX: allow broadcast pings? */
+            && ipX_addr_cmp(is_ipv6, &pcb->dst, dst))
+        {
+            return pcb;
+        }
+    }
+
+    return NULL;
+}
+
+
+static void
+pxping_timer(void *arg)
+{
+    struct pxping *pxping = (struct pxping *)arg;
+    struct ping_pcb **chain, *pcb;
+
+    pxping->timer_active = 0;
+
+    /*
+     * New slot points to the list of pcbs to check for expiration.
+     */
+    LWIP_ASSERT1(pxping->timeout_slot < TIMEOUT);
+    if (++pxping->timeout_slot == TIMEOUT) {
+        pxping->timeout_slot = 0;
+    }
+
+    chain = &pxping->timeout_list[pxping->timeout_slot];
+    pcb = *chain;
+
+    /* protect from pollmgr concurrent reads */
+    sys_mutex_lock(&pxping->lock);
+
+    while (pcb != NULL) {
+        struct ping_pcb *xpcb = pcb;
+        pcb = pcb->next_timeout;
+
+        if (xpcb->timeout_slot == pxping->timeout_slot) {
+            /* expired */
+            pxping_pcb_deregister(pxping, xpcb);
+            pxping_pcb_delete(pxping, xpcb);
+        }
+        else {
+            /*
+             * If there was another request, we updated timeout_slot
+             * but delayed actually moving the pcb until now.
+             */
+            pxping_timeout_del(pxping, xpcb); /* from current slot */
+            pxping_timeout_add(pxping, xpcb); /* to new slot */
+        }
+    }
+
+    sys_mutex_unlock(&pxping->lock);
+    pxping_timer_needed(pxping);
+}
+
+
+static void
+pxping_timer_needed(struct pxping *pxping)
+{
+    if (!pxping->timer_active && pxping->pcbs != NULL) {
+        pxping->timer_active = 1;
+        sys_timeout(1 * 1000, pxping_timer, pxping);
+    }
+}
+
+
+static int
+pxping_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents)
+{
+    struct pxping *pxping;
+
+    pxping = (struct pxping *)handler->data;
+    LWIP_ASSERT1(fd == pxping->sock4 || fd == pxping->sock6);
+
+    if (revents & ~(POLLIN|POLLERR)) {
+        DPRINTF0(("%s: unexpected revents 0x%x\n", __func__, revents));
+        return POLLIN;
+    }
+
+    if (revents & POLLERR) {
+        int sockerr = -1;
+        socklen_t optlen = (socklen_t)sizeof(sockerr);
+        int status;
+
+        status = getsockopt(fd, SOL_SOCKET,
+                            SO_ERROR, (char *)&sockerr, &optlen);
+        if (status < 0) {
+            DPRINTF(("%s: sock %d: SO_ERROR failed with errno %d\n",
+                     __func__, fd, errno));
+        }
+        else {
+            DPRINTF(("%s: sock %d: errno %d\n",
+                     __func__, fd, sockerr));
+        }
+    }
+
+    if ((revents & POLLIN) == 0) {
+        return POLLIN;
+    }
+
+    if (fd == pxping->sock4) {
+        pxping_pmgr_icmp4(pxping);
+    }
+    else /* fd == pxping->sock6 */ {
+        pxping_pmgr_icmp6(pxping);
+    }
+
+    return POLLIN;
+}
+
+
+/**
+ * Process incoming ICMP message for the host.
+ * NB: we will get a lot of spam here and have to sift through it.
+ */
+static void
+pxping_pmgr_icmp4(struct pxping *pxping)
+{
+    struct sockaddr_in sin;
+    socklen_t salen = sizeof(sin);
+    ssize_t nread;
+    struct ip_hdr *iph;
+    struct icmp_echo_hdr *icmph;
+    u16_t iplen;
+
+    memset(&sin, 0, sizeof(sin));
+
+    /*
+     * Reads from raw IPv4 sockets deliver complete IP datagrams with
+     * IP header included.
+     */
+    nread = recvfrom(pxping->sock4, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0,
+                     (struct sockaddr *)&sin, &salen);
+    if (nread < 0) {
+        perror(__func__);
+        return;
+    }
+
+    if (nread < IP_HLEN) {
+        DPRINTF2(("%s: read %d bytes, IP header truncated\n",
+                  __func__, (unsigned int)nread));
+        return;
+    }
+
+    iph = (struct ip_hdr *)pollmgr_udpbuf;
+
+    /* match version */
+    if (IPH_V(iph) != 4) {
+        DPRINTF2(("%s: unexpected IP version %d\n", __func__, IPH_V(iph)));
+        return;
+    }
+
+    /* no fragmentation */
+    if ((IPH_OFFSET(iph) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
+        DPRINTF2(("%s: dropping fragmented datagram\n", __func__));
+        return;
+    }
+
+    /* no options */
+    if (IPH_HL(iph) * 4 != IP_HLEN) {
+        DPRINTF2(("%s: dropping datagram with options (IP header length %d)\n",
+                  __func__, IPH_HL(iph) * 4));
+        return;
+    }
+
+    if (IPH_PROTO(iph) != IP_PROTO_ICMP) {
+        DPRINTF2(("%s: unexpected protocol %d\n", __func__, IPH_PROTO(iph)));
+        return;
+    }
+
+    iplen = IPH_LEN(iph);
+#if !defined(RT_OS_DARWIN)
+    /* darwin reports IPH_LEN in host byte order */
+    iplen = ntohs(iplen);
+#endif
+#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
+    /* darwin and solaris change IPH_LEN to payload length only */
+    iplen += IP_HLEN;           /* we verified there are no options */
+    IPH_LEN(iph) = htons(iplen);
+#endif
+    if (nread < iplen) {
+        DPRINTF2(("%s: read %d bytes but total length is %d bytes\n",
+                  __func__, (unsigned int)nread, (unsigned int)iplen));
+        return;
+    }
+
+    if (iplen < IP_HLEN + ICMP_HLEN) {
+        DPRINTF2(("%s: IP length %d bytes, ICMP header truncated\n",
+                  __func__, iplen));
+        return;
+    }
+
+    icmph = (struct icmp_echo_hdr *)(pollmgr_udpbuf + IP_HLEN);
+    if (ICMPH_TYPE(icmph) == ICMP_ER) {
+        pxping_pmgr_icmp4_echo(pxping, iplen, &sin);
+    }
+    else if (ICMPH_TYPE(icmph) == ICMP_DUR || ICMPH_TYPE(icmph) == ICMP_TE) {
+        pxping_pmgr_icmp4_error(pxping, iplen, &sin);
+    }
+#if 1
+    else {
+        DPRINTF2(("%s: ignoring ICMP type %d\n", __func__, ICMPH_TYPE(icmph)));
+    }
+#endif
+}
+
+
+/**
+ * Check if this incoming ICMP echo reply is for one of our pings and
+ * forward it to the guest.
+ */
+static void
+pxping_pmgr_icmp4_echo(struct pxping *pxping,
+                       u16_t iplen, struct sockaddr_in *peer)
+{
+    struct ip_hdr *iph;
+    struct icmp_echo_hdr *icmph;
+    u16_t id, seq;
+    ip_addr_t guest_ip, target_ip;
+    int mapped;
+    struct ping_pcb *pcb;
+    u16_t guest_id;
+    u32_t sum;
+
+    iph = (struct ip_hdr *)pollmgr_udpbuf;
+    icmph = (struct icmp_echo_hdr *)(pollmgr_udpbuf + IP_HLEN);
+
+    id  = icmph->id;
+    seq = icmph->seqno;
+
+    {
+        char addrbuf[sizeof "255.255.255.255"];
+        const char *addrstr;
+
+        addrstr = inet_ntop(AF_INET, &peer->sin_addr, addrbuf, sizeof(addrbuf));
+        DPRINTF(("<--- PING %s id 0x%x seq %d\n",
+                 addrstr, ntohs(id), ntohs(seq)));
+    }
+
+
+    /*
+     * Is this a reply to one of our pings?
+     */
+
+    ip_addr_copy(target_ip, iph->src);
+    mapped = pxremap_inbound_ip4(&target_ip, &target_ip);
+    if (mapped == PXREMAP_FAILED) {
+        return;
+    }
+    if (mapped == PXREMAP_ASIS && IPH_TTL(iph) == 1) {
+        DPRINTF2(("%s: dropping packet with ttl 1\n", __func__));
+        return;
+    }
+
+    sys_mutex_lock(&pxping->lock);
+    pcb = pxping_pcb_for_reply(pxping, 0, ip_2_ipX(&target_ip), id);
+    if (pcb == NULL) {
+        sys_mutex_unlock(&pxping->lock);
+        DPRINTF2(("%s: no match\n", __func__));
+        return;
+    }
+
+    DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb));
+
+    /* save info before unlocking since pcb may expire */
+    ip_addr_copy(guest_ip, *ipX_2_ip(&pcb->src));
+    guest_id = pcb->guest_id;
+
+    sys_mutex_unlock(&pxping->lock);
+
+
+    /*
+     * Rewrite headers and forward to guest.
+     */
+
+    /* rewrite ICMP echo header */
+    sum = (u16_t)~icmph->chksum;
+    sum += chksum_update_16(&icmph->id, guest_id);
+    sum = FOLD_U32T(sum);
+    icmph->chksum = ~sum;
+
+    /* rewrite IP header */
+    sum = (u16_t)~IPH_CHKSUM(iph);
+    sum += chksum_update_32((u32_t *)&iph->dest,
+                                ip4_addr_get_u32(&guest_ip));
+    if (mapped == PXREMAP_MAPPED) {
+        sum += chksum_update_32((u32_t *)&iph->src,
+                                    ip4_addr_get_u32(&target_ip));
+    }
+    else {
+        IPH_TTL_SET(iph, IPH_TTL(iph) - 1);
+        sum += PP_NTOHS(~0x0100);
+    }
+    sum = FOLD_U32T(sum);
+    IPH_CHKSUM_SET(iph, ~sum);
+
+    pxping_pmgr_forward_inbound(pxping, iplen);
+}
+
+
+/**
+ * Check if this incoming ICMP error (destination unreachable or time
+ * exceeded) is about one of our pings and forward it to the guest.
+ */
+static void
+pxping_pmgr_icmp4_error(struct pxping *pxping,
+                        u16_t iplen, struct sockaddr_in *peer)
+{
+    struct ip_hdr *iph, *oiph;
+    struct icmp_echo_hdr *icmph, *oicmph;
+    u16_t oipoff, oiphlen, oiplen;
+    u16_t id, seq;
+    ip_addr_t guest_ip, target_ip, error_ip;
+    int target_mapped, error_mapped;
+    struct ping_pcb *pcb;
+    u16_t guest_id;
+    u32_t sum;
+
+    iph = (struct ip_hdr *)pollmgr_udpbuf;
+    icmph = (struct icmp_echo_hdr *)(pollmgr_udpbuf + IP_HLEN);
+
+    /*
+     * Inner IP datagram is not checked by the kernel and may be
+     * anything, possibly malicious.
+     */
+
+    oipoff = IP_HLEN + ICMP_HLEN;
+    oiplen = iplen - oipoff; /* NB: truncated length, not IPH_LEN(oiph) */
+    if (oiplen < IP_HLEN) {
+        DPRINTF2(("%s: original datagram truncated to %d bytes\n",
+                  __func__, oiplen));
+    }
+
+    /* IP header of the original message */
+    oiph = (struct ip_hdr *)(pollmgr_udpbuf + oipoff);
+
+    /* match version */
+    if (IPH_V(oiph) != 4) {
+        DPRINTF2(("%s: unexpected IP version %d\n", __func__, IPH_V(oiph)));
+        return;
+    }
+
+    /* can't match fragments except the first one */
+    if ((IPH_OFFSET(oiph) & PP_HTONS(IP_OFFMASK)) != 0) {
+        DPRINTF2(("%s: ignoring fragment with offset %d\n",
+                  __func__, ntohs(IPH_OFFSET(oiph) & PP_HTONS(IP_OFFMASK))));
+        return;
+    }
+
+    if (IPH_PROTO(oiph) != IP_PROTO_ICMP) {
+#if 0
+        /* don't spam with every "destination unreachable" in the system */
+        DPRINTF2(("%s: ignoring protocol %d\n", __func__, IPH_PROTO(oiph)));
+#endif
+        return;
+    }
+
+    oiphlen = IPH_HL(oiph) * 4;
+    if (oiplen < oiphlen + ICMP_HLEN) {
+        DPRINTF2(("%s: original datagram truncated to %d bytes\n",
+                  __func__, oiplen));
+        return;
+    }
+
+    oicmph = (struct icmp_echo_hdr *)(pollmgr_udpbuf + oipoff + oiphlen);
+    if (ICMPH_TYPE(oicmph) != ICMP_ECHO) {
+        DPRINTF2(("%s: ignoring ICMP error for original ICMP type %d\n",
+                  __func__, ICMPH_TYPE(oicmph)));
+        return;
+    }
+
+    id  = oicmph->id;
+    seq = oicmph->seqno;
+
+    {
+        char addrbuf[sizeof "255.255.255.255"];
+        const char *addrstr;
+
+        addrstr = inet_ntop(AF_INET, &oiph->dest, addrbuf, sizeof(addrbuf));
+        DPRINTF2(("%s: ping %s id 0x%x seq %d",
+                  __func__, addrstr, ntohs(id), ntohs(seq)));
+        if (ICMPH_TYPE(icmph) == ICMP_DUR) {
+            DPRINTF2((" unreachable (code %d)\n", ICMPH_CODE(icmph)));
+        }
+        else {
+            DPRINTF2((" time exceeded\n"));
+        }
+    }
+
+
+    /*
+     * Is the inner (failed) datagram one of our pings?
+     */
+
+    ip_addr_copy(target_ip, oiph->dest); /* inner (failed) */
+    target_mapped = pxremap_inbound_ip4(&target_ip, &target_ip);
+    if (target_mapped == PXREMAP_FAILED) {
+        return;
+    }
+
+    sys_mutex_lock(&pxping->lock);
+    pcb = pxping_pcb_for_reply(pxping, 0, ip_2_ipX(&target_ip), id);
+    if (pcb == NULL) {
+        sys_mutex_unlock(&pxping->lock);
+        DPRINTF2(("%s: no match\n", __func__));
+        return;
+    }
+
+    DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb));
+
+    /* save info before unlocking since pcb may expire */
+    ip_addr_copy(guest_ip, *ipX_2_ip(&pcb->src));
+    guest_id = pcb->guest_id;
+
+    sys_mutex_unlock(&pxping->lock);
+
+
+    /*
+     * Rewrite both inner and outer headers and forward to guest.
+     * Note that the checksum of the outer ICMP error message is
+     * preserved by the changes we do to inner headers.
+     */
+
+    ip_addr_copy(error_ip, iph->src); /* node that reports the error */
+    error_mapped = pxremap_inbound_ip4(&error_ip, &error_ip);
+    if (error_mapped == PXREMAP_FAILED) {
+        return;
+    }
+    if (error_mapped == PXREMAP_ASIS && IPH_TTL(iph) == 1) {
+        DPRINTF2(("%s: dropping packet with ttl 1\n", __func__));
+        return;
+    }
+
+    /* rewrite inner ICMP echo header */
+    sum = (u16_t)~oicmph->chksum;
+    sum += chksum_update_16(&oicmph->id, guest_id);
+    sum = FOLD_U32T(sum);
+    oicmph->chksum = ~sum;
+
+    /* rewrite inner IP header */
+    sum = (u16_t)~IPH_CHKSUM(oiph);
+    sum += chksum_update_32((u32_t *)&oiph->src, ip4_addr_get_u32(&guest_ip));
+    if (target_mapped == PXREMAP_MAPPED) {
+        sum += chksum_update_32((u32_t *)&oiph->dest, ip4_addr_get_u32(&target_ip));
+    }
+    sum = FOLD_U32T(sum);
+    IPH_CHKSUM_SET(oiph, ~sum);
+
+    /* rewrite outer IP header */
+    sum = (u16_t)~IPH_CHKSUM(iph);
+    sum += chksum_update_32((u32_t *)&iph->dest, ip4_addr_get_u32(&guest_ip));
+    if (error_mapped == PXREMAP_MAPPED) {
+        sum += chksum_update_32((u32_t *)&iph->src, ip4_addr_get_u32(&error_ip));
+    }
+    else {
+        IPH_TTL_SET(iph, IPH_TTL(iph) - 1);
+        sum += PP_NTOHS(~0x0100);
+    }
+    sum = FOLD_U32T(sum);
+    IPH_CHKSUM_SET(iph, ~sum);
+
+    pxping_pmgr_forward_inbound(pxping, iplen);
+}
+
+
+/**
+ * Process incoming ICMPv6 message for the host.
+ * NB: we will get a lot of spam here and have to sift through it.
+ */
+static void
+pxping_pmgr_icmp6(struct pxping *pxping)
+{
+#ifndef RT_OS_WINDOWS
+    struct msghdr mh;
+    ssize_t nread;
+#else
+    WSAMSG mh;
+    DWORD nread;
+#endif
+    IOVEC iov[1];
+    static u8_t cmsgbuf[128];
+    struct cmsghdr *cmh;
+    struct sockaddr_in6 sin6;
+    socklen_t salen = sizeof(sin6);
+    struct icmp6_echo_hdr *icmph;
+    struct in6_pktinfo *pktinfo;
+    int hopl, tclass;
+    int status;
+
+    char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+    const char *addrstr;
+
+    /*
+     * Reads from raw IPv6 sockets deliver only the payload.  Full
+     * headers are available via recvmsg(2)/cmsg(3).
+     */
+    IOVEC_SET_BASE(iov[0], pollmgr_udpbuf);
+    IOVEC_SET_LEN(iov[0], sizeof(pollmgr_udpbuf));
+
+    memset(&mh, 0, sizeof(mh));
+#ifndef RT_OS_WINDOWS
+    mh.msg_name = &sin6;
+    mh.msg_namelen = sizeof(sin6);
+    mh.msg_iov = iov;
+    mh.msg_iovlen = 1;
+    mh.msg_control = cmsgbuf;
+    mh.msg_controllen = sizeof(cmsgbuf);
+    mh.msg_flags = 0;
+
+    nread = recvmsg(pxping->sock6, &mh, 0);
+    if (nread < 0) {
+        perror(__func__);
+        return;
+    }
+#else  /* RT_OS_WINDOWS */
+    mh.name = (LPSOCKADDR)&sin6;
+    mh.namelen = sizeof(sin6);
+    mh.lpBuffers = iov;
+    mh.dwBufferCount = 1;
+    mh.Control.buf = cmsgbuf;
+    mh.Control.len = sizeof(cmsgbuf);
+    mh.dwFlags = 0;
+
+    status = (*pxping->pfWSARecvMsg6)(pxping->sock6, &mh, &nread, NULL, NULL);
+    if (status == SOCKET_ERROR) {
+        DPRINTF2(("%s: error %d\n", __func__, WSAGetLastError()));
+        return;
+    }
+#endif
+
+    icmph = (struct icmp6_echo_hdr *)pollmgr_udpbuf;
+
+    addrstr = inet_ntop(AF_INET6, (void *)&sin6.sin6_addr,
+                        addrbuf, sizeof(addrbuf));
+    DPRINTF2(("%s: %s ICMPv6: ", __func__, addrstr));
+
+    if (icmph->type == ICMP6_TYPE_EREP) {
+        DPRINTF2(("echo reply %04x %u\n",
+                  (unsigned int)icmph->id, (unsigned int)icmph->seqno));
+    }
+    else { /* XXX */
+        if (icmph->type == ICMP6_TYPE_EREQ) {
+            DPRINTF2(("echo request %04x %u\n",
+                      (unsigned int)icmph->id, (unsigned int)icmph->seqno));
+        }
+        else if (icmph->type == ICMP6_TYPE_DUR) {
+            DPRINTF2(("destination unreachable\n"));
+        }
+        else if (icmph->type == ICMP6_TYPE_PTB) {
+            DPRINTF2(("packet too big\n"));
+        }
+        else if (icmph->type == ICMP6_TYPE_TE) {
+            DPRINTF2(("time exceeded\n"));
+        }
+        else if (icmph->type == ICMP6_TYPE_PP) {
+            DPRINTF2(("parameter problem\n"));
+        }
+        else {
+            DPRINTF2(("type %d len %u\n", icmph->type, (unsigned int)nread));
+        }
+
+        if (icmph->type >= ICMP6_TYPE_EREQ) {
+            return;             /* informational message */
+        }
+    }
+
+    pktinfo = NULL;
+    hopl = -1;
+    tclass = -1;
+    for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) {
+        if (cmh->cmsg_len == 0)
+            break;
+
+        if (cmh->cmsg_level == IPPROTO_IPV6
+            && cmh->cmsg_type == IPV6_HOPLIMIT
+            && cmh->cmsg_len == CMSG_LEN(sizeof(int)))
+        {
+            hopl = *(int *)CMSG_DATA(cmh);
+            DPRINTF2(("hoplimit = %d\n", hopl));
+        }
+
+        if (cmh->cmsg_level == IPPROTO_IPV6
+            && cmh->cmsg_type == IPV6_PKTINFO
+            && cmh->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
+        {
+            pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmh);
+            DPRINTF2(("pktinfo found\n"));
+        }
+    }
+
+    if (pktinfo == NULL) {
+        /*
+         * ip6_output_if() doesn't do checksum for us so we need to
+         * manually recompute it - for this we must know the
+         * destination address of the pseudo-header that we will
+         * rewrite with guest's address.  (TODO: yeah, yeah, we can
+         * compute it from scratch...)
+         */
+        DPRINTF2(("%s: unable to get pktinfo\n", __func__));
+        return;
+    }
+
+    if (hopl < 0) {
+        hopl = LWIP_ICMP6_HL;
+    }
+
+    if (icmph->type == ICMP6_TYPE_EREP) {
+        pxping_pmgr_icmp6_echo(pxping,
+                               (ip6_addr_t *)&sin6.sin6_addr,
+                               (ip6_addr_t *)&pktinfo->ipi6_addr,
+                               hopl, tclass, (u16_t)nread);
+    }
+    else if (icmph->type < ICMP6_TYPE_EREQ) {
+        pxping_pmgr_icmp6_error(pxping,
+                                (ip6_addr_t *)&sin6.sin6_addr,
+                                (ip6_addr_t *)&pktinfo->ipi6_addr,
+                                hopl, tclass, (u16_t)nread);
+    }
+}
+
+
+/**
+ * Check if this incoming ICMPv6 echo reply is for one of our pings
+ * and forward it to the guest.
+ */
+static void
+pxping_pmgr_icmp6_echo(struct pxping *pxping,
+                       ip6_addr_t *src, ip6_addr_t *dst,
+                       int hopl, int tclass, u16_t icmplen)
+{
+    struct icmp6_echo_hdr *icmph;
+    ip6_addr_t guest_ip, target_ip;
+    int mapped;
+    struct ping_pcb *pcb;
+    u16_t id, guest_id;
+    u32_t sum;
+
+    ip6_addr_copy(target_ip, *src);
+    mapped = pxremap_inbound_ip6(&target_ip, &target_ip);
+    if (mapped == PXREMAP_FAILED) {
+        return;
+    }
+    else if (mapped == PXREMAP_ASIS) {
+        if (hopl == 1) {
+            DPRINTF2(("%s: dropping packet with ttl 1\n", __func__));
+            return;
+        }
+        --hopl;
+    }
+
+    icmph = (struct icmp6_echo_hdr *)pollmgr_udpbuf;
+    id = icmph->id;
+
+    sys_mutex_lock(&pxping->lock);
+    pcb = pxping_pcb_for_reply(pxping, 1, ip6_2_ipX(&target_ip), id);
+    if (pcb == NULL) {
+        sys_mutex_unlock(&pxping->lock);
+        DPRINTF2(("%s: no match\n", __func__));
+        return;
+    }
+
+    DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb));
+
+    /* save info before unlocking since pcb may expire */
+    ip6_addr_copy(guest_ip, *ipX_2_ip6(&pcb->src));
+    guest_id = pcb->guest_id;
+
+    sys_mutex_unlock(&pxping->lock);
+
+    /* rewrite ICMPv6 echo header */
+    sum = (u16_t)~icmph->chksum;
+    sum += chksum_update_16(&icmph->id, guest_id);
+    sum += chksum_delta_ipv6(dst, &guest_ip); /* pseudo */
+    if (mapped) {
+        sum += chksum_delta_ipv6(src, &target_ip); /* pseudo */
+    }
+    sum = FOLD_U32T(sum);
+    icmph->chksum = ~sum;
+
+    pxping_pmgr_forward_inbound6(pxping,
+                                 &target_ip, /* echo reply src */
+                                 &guest_ip, /* echo reply dst */
+                                 hopl, tclass, icmplen);
+}
+
+
+/**
+ * Check if this incoming ICMPv6 error is about one of our pings and
+ * forward it to the guest.
+ */
+static void
+pxping_pmgr_icmp6_error(struct pxping *pxping,
+                        ip6_addr_t *src, ip6_addr_t *dst,
+                        int hopl, int tclass, u16_t icmplen)
+{
+    struct icmp6_hdr *icmph;
+    u8_t *bufptr;
+    size_t buflen, hlen;
+    int proto;
+    struct ip6_hdr *oiph;
+    struct icmp6_echo_hdr *oicmph;
+    struct ping_pcb *pcb;
+    ip6_addr_t guest_ip, target_ip, error_ip;
+    int target_mapped, error_mapped;
+    u16_t guest_id;
+    u32_t sum;
+
+    icmph = (struct icmp6_hdr *)pollmgr_udpbuf;
+
+    /*
+     * Inner IP datagram is not checked by the kernel and may be
+     * anything, possibly malicious.
+     */
+    oiph = NULL;
+    oicmph = NULL;
+
+    bufptr = pollmgr_udpbuf;
+    buflen = icmplen;
+
+    hlen = sizeof(*icmph);
+    proto = IP6_NEXTH_ENCAPS; /* i.e. IPv6, lwIP's name is unfortuate */
+    for (;;) {
+        if (hlen > buflen) {
+            DPRINTF2(("truncated datagram inside ICMPv6 error message is too short\n"));
+            return;
+        }
+        buflen -= hlen;
+        bufptr += hlen;
+
+        if (proto == IP6_NEXTH_ENCAPS && oiph == NULL) { /* outermost IPv6 */
+            oiph = (struct ip6_hdr *)bufptr;
+            if (IP6H_V(oiph) != 6) {
+                DPRINTF2(("%s: unexpected IP version %d\n", __func__, IP6H_V(oiph)));
+                return;
+            }
+
+            proto = IP6H_NEXTH(oiph);
+            hlen = IP6_HLEN;
+        }
+        else if (proto == IP6_NEXTH_ICMP6) {
+            oicmph = (struct icmp6_echo_hdr *)bufptr;
+            break;
+        }
+        else if (proto == IP6_NEXTH_ROUTING
+                 || proto == IP6_NEXTH_HOPBYHOP
+                 || proto == IP6_NEXTH_DESTOPTS)
+        {
+            proto = bufptr[0];
+            hlen = (bufptr[1] + 1) * 8;
+        }
+        else {
+            DPRINTF2(("%s: stopping at protocol %d\n", __func__, proto));
+            break;
+        }
+    }
+
+    if (oiph == NULL || oicmph == NULL) {
+        return;
+    }
+
+    if (buflen < sizeof(*oicmph)) {
+        DPRINTF2(("%s: original ICMPv6 is truncated too short\n", __func__));
+        return;
+    }
+
+    if (oicmph->type != ICMP6_TYPE_EREQ) {
+        DPRINTF2(("%s: ignoring original ICMPv6 type %d\n", __func__, oicmph->type));
+        return;
+    }
+
+    memcpy(&target_ip, &oiph->dest, sizeof(target_ip)); /* inner (failed) */
+    target_mapped = pxremap_inbound_ip6(&target_ip, &target_ip);
+    if (target_mapped == PXREMAP_FAILED) {
+        return;
+    }
+
+    sys_mutex_lock(&pxping->lock);
+    pcb = pxping_pcb_for_reply(pxping, 1, ip_2_ipX(&target_ip), oicmph->id);
+    if (pcb == NULL) {
+        sys_mutex_unlock(&pxping->lock);
+        DPRINTF2(("%s: no match\n", __func__));
+        return;
+    }
+
+    DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb));
+
+    /* save info before unlocking since pcb may expire */
+    ip6_addr_copy(guest_ip, *ipX_2_ip6(&pcb->src));
+    guest_id = pcb->guest_id;
+
+    sys_mutex_unlock(&pxping->lock);
+
+
+    /*
+     * Rewrite inner and outer headers and forward to guest.  Note
+     * that IPv6 has no IP header checksum, but uses pseudo-header for
+     * ICMPv6, so we update both in one go, adjusting ICMPv6 checksum
+     * as we rewrite IP header.
+     */
+
+    ip6_addr_copy(error_ip, *src); /* node that reports the error */
+    error_mapped = pxremap_inbound_ip6(&error_ip, &error_ip);
+    if (error_mapped == PXREMAP_FAILED) {
+        return;
+    }
+    if (error_mapped == PXREMAP_ASIS && hopl == 1) {
+        DPRINTF2(("%s: dropping packet with ttl 1\n", __func__));
+        return;
+    }
+
+    /* rewrite inner ICMPv6 echo header and inner IPv6 header */
+    sum = (u16_t)~oicmph->chksum;
+    sum += chksum_update_16(&oicmph->id, guest_id);
+    sum += chksum_update_ipv6((ip6_addr_t *)&oiph->src, &guest_ip);
+    if (target_mapped) {
+        sum += chksum_delta_ipv6((ip6_addr_t *)&oiph->dest, &target_ip);
+    }
+    sum = FOLD_U32T(sum);
+    oicmph->chksum = ~sum;
+
+    /* rewrite outer ICMPv6 error header */
+    sum = (u16_t)~icmph->chksum;
+    sum += chksum_delta_ipv6(dst, &guest_ip); /* pseudo */
+    if (error_mapped) {
+        sum += chksum_delta_ipv6(src, &error_ip); /* pseudo */
+    }
+    sum = FOLD_U32T(sum);
+    icmph->chksum = ~sum;
+
+    pxping_pmgr_forward_inbound6(pxping,
+                                 &error_ip, /* error src */
+                                 &guest_ip, /* error dst */
+                                 hopl, tclass, icmplen);
+}
+
+
+/**
+ * Hand off ICMP datagram to the lwip thread where it will be
+ * forwarded to the guest.
+ *
+ * We no longer need ping_pcb.  The pcb may get expired on the lwip
+ * thread, but we have already patched necessary information into the
+ * datagram.
+ */
+static void
+pxping_pmgr_forward_inbound(struct pxping *pxping, u16_t iplen)
+{
+    struct pbuf *p;
+    struct ping_msg *msg;
+    err_t error;
+
+    p = pbuf_alloc(PBUF_LINK, iplen, PBUF_RAM);
+    if (p == NULL) {
+        DPRINTF(("%s: pbuf_alloc(%d) failed\n",
+                 __func__, (unsigned int)iplen));
+        return;
+    }
+
+    error = pbuf_take(p, pollmgr_udpbuf, iplen);
+    if (error != ERR_OK) {
+        DPRINTF(("%s: pbuf_take(%d) failed\n",
+                 __func__, (unsigned int)iplen));
+        pbuf_free(p);
+        return;
+    }
+
+    msg = (struct ping_msg *)malloc(sizeof(*msg));
+    if (msg == NULL) {
+        pbuf_free(p);
+        return;
+    }
+
+    msg->msg.type = TCPIP_MSG_CALLBACK_STATIC;
+    msg->msg.sem = NULL;
+    msg->msg.msg.cb.function = pxping_pcb_forward_inbound;
+    msg->msg.msg.cb.ctx = (void *)msg;
+
+    msg->pxping = pxping;
+    msg->p = p;
+
+    proxy_lwip_post(&msg->msg);
+}
+
+
+static void
+pxping_pcb_forward_inbound(void *arg)
+{
+    struct ping_msg *msg = (struct ping_msg *)arg;
+    err_t error;
+
+    LWIP_ASSERT1(msg != NULL);
+    LWIP_ASSERT1(msg->pxping != NULL);
+    LWIP_ASSERT1(msg->p != NULL);
+
+    error = ip_raw_output_if(msg->p, msg->pxping->netif);
+    if (error != ERR_OK) {
+        DPRINTF(("%s: ip_output_if: %s\n",
+                 __func__, proxy_lwip_strerr(error)));
+    }
+    pbuf_free(msg->p);
+    free(msg);
+}
+
+
+static void
+pxping_pmgr_forward_inbound6(struct pxping *pxping,
+                             ip6_addr_t *src, ip6_addr_t *dst,
+                             u8_t hopl, u8_t tclass,
+                             u16_t icmplen)
+{
+    struct pbuf *p;
+    struct ping6_msg *msg;
+
+    err_t error;
+
+    p = pbuf_alloc(PBUF_IP, icmplen, PBUF_RAM);
+    if (p == NULL) {
+        DPRINTF(("%s: pbuf_alloc(%d) failed\n",
+                 __func__, (unsigned int)icmplen));
+        return;
+    }
+
+    error = pbuf_take(p, pollmgr_udpbuf, icmplen);
+    if (error != ERR_OK) {
+        DPRINTF(("%s: pbuf_take(%d) failed\n",
+                 __func__, (unsigned int)icmplen));
+        pbuf_free(p);
+        return;
+    }
+
+    msg = (struct ping6_msg *)malloc(sizeof(*msg));
+    if (msg == NULL) {
+        pbuf_free(p);
+        return;
+    }
+
+    msg->msg.type = TCPIP_MSG_CALLBACK_STATIC;
+    msg->msg.sem = NULL;
+    msg->msg.msg.cb.function = pxping_pcb_forward_inbound6;
+    msg->msg.msg.cb.ctx = (void *)msg;
+
+    msg->pxping = pxping;
+    msg->p = p;
+    ip6_addr_copy(msg->src, *src);
+    ip6_addr_copy(msg->dst, *dst);
+    msg->hopl = hopl;
+    msg->tclass = tclass;
+
+    proxy_lwip_post(&msg->msg);
+}
+
+
+static void
+pxping_pcb_forward_inbound6(void *arg)
+{
+    struct ping6_msg *msg = (struct ping6_msg *)arg;
+    err_t error;
+
+    LWIP_ASSERT1(msg != NULL);
+    LWIP_ASSERT1(msg->pxping != NULL);
+    LWIP_ASSERT1(msg->p != NULL);
+
+    error = ip6_output_if(msg->p,
+                          &msg->src, &msg->dst, msg->hopl, msg->tclass,
+                          IP6_NEXTH_ICMP6, msg->pxping->netif);
+    if (error != ERR_OK) {
+        DPRINTF(("%s: ip6_output_if: %s\n",
+                 __func__, proxy_lwip_strerr(error)));
+    }
+    pbuf_free(msg->p);
+    free(msg);
+}
diff --git a/src/VBox/NetworkServices/NAT/pxping_win.c b/src/VBox/NetworkServices/NAT/pxping_win.c
new file mode 100644
index 0000000..58eb9c8
--- /dev/null
+++ b/src/VBox/NetworkServices/NAT/pxping_win.c
@@ -0,0 +1,629 @@
+/* -*- indent-tabs-mode: nil; -*- */
+
+#include "winutils.h"
+#include "proxy.h"
+#include "pxremap.h"
+
+#include "lwip/ip.h"
+#include "lwip/icmp.h"
+#include "lwip/inet_chksum.h"
+
+/* XXX: lwIP names conflict with winsock <iphlpapi.h> */
+#undef IP_STATS
+#undef ICMP_STATS
+#undef TCP_STATS
+#undef UDP_STATS
+#undef IP6_STATS
+
+#include <winternl.h>           /* for PIO_APC_ROUTINE &c */
+#include <iphlpapi.h>
+#include <icmpapi.h>
+
+#include <stdio.h>
+
+
+struct pxping {
+    /*
+     * We use single ICMP handle for all pings.  This means that all
+     * proxied pings will have the same id and share single sequence
+     * of sequence numbers.
+     */
+    HANDLE hdl4;
+    HANDLE hdl6;
+
+    struct netif *netif;
+
+    /*
+     * On Windows XP and Windows Server 2003 IcmpSendEcho2() callback
+     * is FARPROC, but starting from Vista it's PIO_APC_ROUTINE with
+     * two extra arguments.  Callbacks use WINAPI (stdcall) calling
+     * convention with callee responsible for popping the arguments,
+     * so to avoid stack corruption we check windows version at run
+     * time and provide correct callback.
+     */
+    void *callback4;
+    void *callback6;
+};
+
+
+struct pong4 {
+    struct netif *netif;
+
+    struct ip_hdr reqiph;
+    struct icmp_echo_hdr reqicmph;
+
+    size_t bufsize;
+    u8_t buf[1];
+};
+
+
+struct pong6 {
+    struct netif *netif;
+
+    ip6_addr_t reqsrc;
+    struct icmp6_echo_hdr reqicmph;
+    size_t reqsize;
+
+    size_t bufsize;
+    u8_t buf[1];
+};
+
+
+static void pxping_recv4(void *arg, struct pbuf *p);
+static void pxping_recv6(void *arg, struct pbuf *p);
+
+static VOID WINAPI pxping_icmp4_callback_old(void *);
+static VOID WINAPI pxping_icmp4_callback_apc(void *, PIO_STATUS_BLOCK, ULONG);
+static void pxping_icmp4_callback(struct pong4 *pong);
+
+static VOID WINAPI pxping_icmp6_callback_old(void *);
+static VOID WINAPI pxping_icmp6_callback_apc(void *, PIO_STATUS_BLOCK, ULONG);
+static void pxping_icmp6_callback(struct pong6 *pong);
+
+
+struct pxping g_pxping;
+
+
+err_t
+pxping_init(struct netif *netif, SOCKET sock4, SOCKET sock6)
+{
+    OSVERSIONINFO osvi;
+    int status;
+
+    LWIP_UNUSED_ARG(sock4);
+    LWIP_UNUSED_ARG(sock6);
+
+    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    status = GetVersionEx(&osvi);
+    if (status == 0) {
+        return ERR_ARG;
+    }
+
+    if (osvi.dwMajorVersion >= 6) {
+        g_pxping.callback4 = (void *)pxping_icmp4_callback_apc;
+        g_pxping.callback6 = (void *)pxping_icmp6_callback_apc;
+    }
+    else {
+        g_pxping.callback4 = (void *)pxping_icmp4_callback_old;
+        g_pxping.callback6 = (void *)pxping_icmp6_callback_old;
+    }
+
+
+    g_pxping.hdl4 = IcmpCreateFile();
+    if (g_pxping.hdl4 != INVALID_HANDLE_VALUE) {
+        ping_proxy_accept(pxping_recv4, &g_pxping);
+    }
+    else {
+        DPRINTF(("IcmpCreateFile: error %d\n", GetLastError()));
+    }
+
+    g_pxping.hdl6 = Icmp6CreateFile();
+    if (g_pxping.hdl6 != INVALID_HANDLE_VALUE) {
+        ping6_proxy_accept(pxping_recv6, &g_pxping);
+    }
+    else {
+        DPRINTF(("Icmp6CreateFile: error %d\n", GetLastError()));
+    }
+
+    if (g_pxping.hdl4 == INVALID_HANDLE_VALUE
+        && g_pxping.hdl6 == INVALID_HANDLE_VALUE)
+    {
+        return ERR_ARG;
+    }
+
+    g_pxping.netif = netif;
+
+    return ERR_OK;
+}
+
+
+/**
+ * ICMP Echo Request in pbuf "p" is to be proxied.
+ */
+static void
+pxping_recv4(void *arg, struct pbuf *p)
+{
+    struct pxping *pxping = (struct pxping *)arg;
+    const struct ip_hdr *iph;
+    const struct icmp_echo_hdr *icmph;
+    u16_t iphlen;
+    size_t bufsize;
+    struct pong4 *pong;
+    IPAddr dst;
+    int mapped;
+    int ttl;
+    IP_OPTION_INFORMATION opts;
+    void *reqdata;
+    size_t reqsize;
+    int status;
+
+    pong = NULL;
+
+    iphlen = ip_current_header_tot_len();
+    if (RT_UNLIKELY(iphlen != IP_HLEN)) { /* we don't do options */
+        goto out;
+    }
+
+    iph = (const struct ip_hdr *)ip_current_header();
+    icmph = (const struct icmp_echo_hdr *)p->payload;
+
+    mapped = pxremap_outbound_ip4((ip_addr_t *)&dst, (ip_addr_t *)&iph->dest);
+    if (RT_UNLIKELY(mapped == PXREMAP_FAILED)) {
+        goto out;
+    }
+
+    ttl = IPH_TTL(iph);
+    if (mapped == PXREMAP_ASIS) {
+        if (RT_UNLIKELY(ttl == 1)) {
+            status = pbuf_header(p, iphlen); /* back to IP header */
+            if (RT_LIKELY(status == 0)) {
+                icmp_time_exceeded(p, ICMP_TE_TTL);
+            }
+            goto out;
+        }
+        --ttl;
+    }
+
+    status = pbuf_header(p, -(u16_t)sizeof(*icmph)); /* to ping payload */
+    if (RT_UNLIKELY(status != 0)) {
+        goto out;
+    }
+
+    bufsize = sizeof(ICMP_ECHO_REPLY) + p->tot_len;
+    pong = (struct pong4 *)malloc(sizeof(*pong) - sizeof(pong->buf) + bufsize);
+    if (RT_UNLIKELY(pong == NULL)) {
+        goto out;
+    }
+    pong->bufsize = bufsize;
+    pong->netif = pxping->netif;
+
+    memcpy(&pong->reqiph, iph, sizeof(*iph));
+    memcpy(&pong->reqicmph, icmph, sizeof(*icmph));
+
+    reqsize = p->tot_len;
+    if (p->next == NULL) {
+        /* single pbuf can be directly used as request data source */
+        reqdata = p->payload;
+    }
+    else {
+        /* data from pbuf chain must be concatenated */
+        pbuf_copy_partial(p, pong->buf, p->tot_len, 0);
+        reqdata = pong->buf;
+    }
+
+    opts.Ttl = ttl;
+    opts.Tos = IPH_TOS(iph); /* affected by DisableUserTOSSetting key */
+    opts.Flags = (IPH_OFFSET(iph) & PP_HTONS(IP_DF)) != 0 ? IP_FLAG_DF : 0;
+    opts.OptionsSize = 0;
+    opts.OptionsData = 0;
+
+    status = IcmpSendEcho2(pxping->hdl4, NULL,
+                           pxping->callback4, pong,
+                           dst, reqdata, (WORD)reqsize, &opts,
+                           pong->buf, (DWORD)pong->bufsize,
+                           5 * 1000 /* ms */);
+
+    if (RT_UNLIKELY(status != 0)) {
+        DPRINTF(("IcmpSendEcho2: unexpected status %d\n", status));
+        goto out;
+    }
+    else if ((status = GetLastError()) != ERROR_IO_PENDING) {
+        int code;
+
+        DPRINTF(("IcmpSendEcho2: error %d\n", status));
+        switch (status) {
+        case ERROR_NETWORK_UNREACHABLE:
+            code = ICMP_DUR_NET;
+            break;
+        case ERROR_HOST_UNREACHABLE:
+            code = ICMP_DUR_HOST;
+            break;
+        default:
+            code = -1;
+            break;
+        }
+
+        if (code != -1) {
+            /* move payload back to IP header */
+            status = pbuf_header(p, (u16_t)(sizeof(*icmph) + iphlen));
+            if (RT_LIKELY(status == 0)) {
+                icmp_dest_unreach(p, code);
+            }
+        }
+        goto out;
+    }
+
+    pong = NULL;                /* callback owns it now */
+  out:
+    if (pong != NULL) {
+        free(pong);
+    }
+    pbuf_free(p);
+}
+
+
+static VOID WINAPI
+pxping_icmp4_callback_apc(void *ctx, PIO_STATUS_BLOCK iob, ULONG reserved)
+{
+    struct pong4 *pong = (struct pong4 *)ctx;
+    LWIP_UNUSED_ARG(iob);
+    LWIP_UNUSED_ARG(reserved);
+
+    if (pong != NULL) {
+        pxping_icmp4_callback(pong);
+        free(pong);
+    }
+}
+
+
+static VOID WINAPI
+pxping_icmp4_callback_old(void *ctx)
+{
+    struct pong4 *pong = (struct pong4 *)ctx;
+
+    if (pong != NULL) {
+        pxping_icmp4_callback(pong);
+        free(pong);
+    }
+}
+
+
+static void
+pxping_icmp4_callback(struct pong4 *pong)
+{
+    ICMP_ECHO_REPLY *reply;
+    DWORD nreplies;
+    size_t icmplen;
+    struct pbuf *p;
+    struct icmp_echo_hdr *icmph;
+    ip_addr_t src;
+    int mapped;
+
+    nreplies = IcmpParseReplies(pong->buf, (DWORD)pong->bufsize);
+    if (nreplies <= 0) {
+        DWORD error = GetLastError();
+        if (error == IP_REQ_TIMED_OUT) {
+            DPRINTF2(("pong4: %p timed out\n", (void *)pong));
+        }
+        else {
+            DPRINTF(("pong4: %p: IcmpParseReplies: error %d\n",
+                     (void *)pong, error));
+        }
+        return;
+    }
+
+    reply = (ICMP_ECHO_REPLY *)pong->buf;
+
+    if (reply->Options.OptionsSize != 0) { /* don't do options */
+        return;
+    }
+
+    mapped = pxremap_inbound_ip4(&src, (ip_addr_t *)&reply->Address);
+    if (mapped == PXREMAP_FAILED) {
+        return;
+    }
+    if (mapped == PXREMAP_ASIS) {
+        if (reply->Options.Ttl == 1) {
+            return;
+        }
+        --reply->Options.Ttl;
+    }
+
+    if (reply->Status == IP_SUCCESS) {
+        icmplen = sizeof(struct icmp_echo_hdr) + reply->DataSize;
+        if ((reply->Options.Flags & IP_FLAG_DF) != 0
+            && IP_HLEN + icmplen > pong->netif->mtu)
+        {
+            return;
+        }
+
+        p = pbuf_alloc(PBUF_IP, (u16_t)icmplen, PBUF_RAM);
+        if (RT_UNLIKELY(p == NULL)) {
+            return;
+        }
+
+        icmph = (struct icmp_echo_hdr *)p->payload;
+        icmph->type = ICMP_ER;
+        icmph->code = 0;
+        icmph->chksum = 0;
+        icmph->id = pong->reqicmph.id;
+        icmph->seqno = pong->reqicmph.seqno;
+
+        memcpy((u8_t *)p->payload + sizeof(*icmph),
+               reply->Data, reply->DataSize);
+    }
+    else {
+        u8_t type, code;
+
+        switch (reply->Status) {
+        case IP_DEST_NET_UNREACHABLE:
+            type = ICMP_DUR; code = ICMP_DUR_NET;
+            break;
+        case IP_DEST_HOST_UNREACHABLE:
+            type = ICMP_DUR; code = ICMP_DUR_HOST;
+            break;
+        case IP_DEST_PROT_UNREACHABLE:
+            type = ICMP_DUR; code = ICMP_DUR_PROTO;
+            break;
+        case IP_PACKET_TOO_BIG:
+            type = ICMP_DUR; code = ICMP_DUR_FRAG;
+            break;
+        case IP_SOURCE_QUENCH:
+            type = ICMP_SQ; code = 0;
+            break;
+        case IP_TTL_EXPIRED_TRANSIT:
+            type = ICMP_TE; code = ICMP_TE_TTL;
+            break;
+        case IP_TTL_EXPIRED_REASSEM:
+            type = ICMP_TE; code = ICMP_TE_FRAG;
+            break;
+        default:
+            DPRINTF(("pong4: reply status %d, dropped\n", reply->Status));
+            return;
+        }
+
+        DPRINTF(("pong4: reply status %d -> type %d/code %d\n",
+                 reply->Status, type, code));
+
+        icmplen = sizeof(*icmph) + sizeof(pong->reqiph) + sizeof(pong->reqicmph);
+
+        p = pbuf_alloc(PBUF_IP, (u16_t)icmplen, PBUF_RAM);
+        if (RT_UNLIKELY(p == NULL)) {
+            return;
+        }
+
+        icmph = (struct icmp_echo_hdr *)p->payload;
+        icmph->type = type;
+        icmph->code = code;
+        icmph->chksum = 0;
+        icmph->id = 0;
+        icmph->seqno = 0;
+
+        /*
+         * XXX: we don't know the TTL of the request at the time this
+         * ICMP error was generated (we can guess it was 1 for ttl
+         * exceeded, but don't bother faking it).
+         */
+        memcpy((u8_t *)p->payload + sizeof(*icmph),
+               &pong->reqiph, sizeof(pong->reqiph));
+
+        memcpy((u8_t *)p->payload + sizeof(*icmph) + sizeof(pong->reqiph),
+               &pong->reqicmph, sizeof(pong->reqicmph));
+    }
+
+    icmph->chksum = inet_chksum(p->payload, (u16_t)icmplen);
+    ip_output_if(p, &src,
+                 (ip_addr_t *)&pong->reqiph.src, /* dst */
+                 reply->Options.Ttl,
+                 reply->Options.Tos,
+                 IPPROTO_ICMP,
+                 pong->netif);
+    pbuf_free(p);
+}
+
+
+static void
+pxping_recv6(void *arg, struct pbuf *p)
+{
+    struct pxping *pxping = (struct pxping *)arg;
+    struct icmp6_echo_hdr *icmph;
+    size_t bufsize;
+    struct pong6 *pong;
+    int mapped;
+    void *reqdata;
+    size_t reqsize;
+    struct sockaddr_in6 src, dst;
+    int hopl;
+    IP_OPTION_INFORMATION opts;
+    int status;
+
+    pong = NULL;
+
+    icmph = (struct icmp6_echo_hdr *)p->payload;
+
+    memset(&dst, 0, sizeof(dst));
+    dst.sin6_family = AF_INET6;
+    mapped = pxremap_outbound_ip6((ip6_addr_t *)&dst.sin6_addr,
+                                  ip6_current_dest_addr());
+    if (RT_UNLIKELY(mapped == PXREMAP_FAILED)) {
+        goto out;
+    }
+
+    hopl = IP6H_HOPLIM(ip6_current_header());
+    if (mapped == PXREMAP_ASIS) {
+        if (RT_UNLIKELY(hopl == 1)) {
+            status = pbuf_header(p, ip_current_header_tot_len());
+            if (RT_LIKELY(status == 0)) {
+                icmp6_time_exceeded(p, ICMP6_TE_HL);
+            }
+            goto out;
+        }
+        --hopl;
+    }
+
+    status = pbuf_header(p, -(u16_t)sizeof(*icmph)); /* to ping payload */
+    if (RT_UNLIKELY(status != 0)) {
+        goto out;
+    }
+
+    bufsize = sizeof(ICMPV6_ECHO_REPLY) + p->tot_len;
+    pong = (struct pong6 *)malloc(sizeof(*pong) - sizeof(pong->buf) + bufsize);
+    if (RT_UNLIKELY(pong == NULL)) {
+        goto out;
+    }
+    pong->bufsize = bufsize;
+    pong->netif = pxping->netif;
+
+    ip6_addr_copy(pong->reqsrc, *ip6_current_src_addr());
+    memcpy(&pong->reqicmph, icmph, sizeof(*icmph));
+
+    memset(pong->buf, 0xa5, pong->bufsize);
+
+    pong->reqsize = reqsize = p->tot_len;
+    if (p->next == NULL) {
+        /* single pbuf can be directly used as request data source */
+        reqdata = p->payload;
+    }
+    else {
+        /* data from pbuf chain must be concatenated */
+        pbuf_copy_partial(p, pong->buf, p->tot_len, 0);
+        reqdata = pong->buf;
+    }
+
+    memset(&src, 0, sizeof(src));
+    src.sin6_family = AF_INET6;
+    src.sin6_addr = in6addr_any; /* let the OS select host source address */
+
+    memset(&opts, 0, sizeof(opts));
+    opts.Ttl = hopl;
+
+    status = Icmp6SendEcho2(pxping->hdl6, NULL,
+                            pxping->callback6, pong,
+                            &src, &dst, reqdata, (WORD)reqsize, &opts,
+                            pong->buf, (DWORD)pong->bufsize,
+                            5 * 1000 /* ms */);
+
+    if (RT_UNLIKELY(status != 0)) {
+        DPRINTF(("Icmp6SendEcho2: unexpected status %d\n", status));
+        goto out;
+    }
+    else if ((status = GetLastError()) != ERROR_IO_PENDING) {
+        int code;
+
+        DPRINTF(("Icmp6SendEcho2: error %d\n", status));
+        switch (status) {
+        case ERROR_NETWORK_UNREACHABLE:
+        case ERROR_HOST_UNREACHABLE:
+            code = ICMP6_DUR_NO_ROUTE;
+            break;
+        default:
+            code = -1;
+            break;
+        }
+
+        if (code != -1) {
+            /* move payload back to IP header */
+            status = pbuf_header(p, (u16_t)(sizeof(*icmph)
+                                            + ip_current_header_tot_len()));
+            if (RT_LIKELY(status == 0)) {
+                icmp6_dest_unreach(p, code);
+            }
+        }
+        goto out;
+    }
+    
+    pong = NULL;                /* callback owns it now */
+  out:
+    if (pong != NULL) {
+        free(pong);
+    }
+    pbuf_free(p);
+}
+
+
+static VOID WINAPI
+pxping_icmp6_callback_apc(void *ctx, PIO_STATUS_BLOCK iob, ULONG reserved)
+{
+    struct pong6 *pong = (struct pong6 *)ctx;
+    LWIP_UNUSED_ARG(iob);
+    LWIP_UNUSED_ARG(reserved);
+
+    if (pong != NULL) {
+        pxping_icmp6_callback(pong);
+        free(pong);
+    }
+}
+
+
+static VOID WINAPI
+pxping_icmp6_callback_old(void *ctx)
+{
+    struct pong6 *pong = (struct pong6 *)ctx;
+
+    if (pong != NULL) {
+        pxping_icmp6_callback(pong);
+        free(pong);
+    }
+}
+
+
+static void
+pxping_icmp6_callback(struct pong6 *pong)
+{
+    DWORD nreplies;
+    ICMPV6_ECHO_REPLY *reply;
+    struct pbuf *p;
+    struct icmp6_echo_hdr *icmph;
+    size_t icmplen;
+    ip6_addr_t src;
+    int mapped;
+
+    nreplies = Icmp6ParseReplies(pong->buf, (DWORD)pong->bufsize);
+    if (nreplies <= 0) {
+        DWORD error = GetLastError();
+        if (error == IP_REQ_TIMED_OUT) {
+            DPRINTF2(("pong6: %p timed out\n", (void *)pong));
+        }
+        else {
+            DPRINTF(("pong6: %p: Icmp6ParseReplies: error %d\n",
+                     (void *)pong, error));
+        }
+        return;
+    }
+
+    reply = (ICMPV6_ECHO_REPLY *)pong->buf;
+
+    mapped = pxremap_inbound_ip6(&src, (ip6_addr_t *)reply->Address.sin6_addr);
+    if (mapped == PXREMAP_FAILED) {
+        return;
+    }
+
+    /*
+     * Reply data follows ICMPV6_ECHO_REPLY structure in memory, but
+     * it doesn't tell us its size.  Assume it's equal the size of the
+     * request.
+     */
+    icmplen = sizeof(*icmph) + pong->reqsize;
+    p = pbuf_alloc(PBUF_IP, (u16_t)icmplen, PBUF_RAM);
+    if (RT_UNLIKELY(p == NULL)) {
+        return;
+    }
+
+    icmph = (struct icmp6_echo_hdr *)p->payload;
+    icmph->type = ICMP6_TYPE_EREP;
+    icmph->code = 0;
+    icmph->chksum = 0;
+    icmph->id = pong->reqicmph.id;
+    icmph->seqno = pong->reqicmph.seqno;
+
+    memcpy((u8_t *)p->payload + sizeof(*icmph),
+           pong->buf + sizeof(*reply), pong->reqsize);
+
+    icmph->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len,
+                                      &src, &pong->reqsrc);
+    ip6_output_if(p, /* :src */ &src, /* :dst */ &pong->reqsrc,
+                  LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6,
+                  pong->netif);
+    pbuf_free(p);
+}
diff --git a/src/VBox/NetworkServices/NAT/pxremap.c b/src/VBox/NetworkServices/NAT/pxremap.c
index b84d763..616bad9 100644
--- a/src/VBox/NetworkServices/NAT/pxremap.c
+++ b/src/VBox/NetworkServices/NAT/pxremap.c
@@ -31,7 +31,6 @@
 static int
 proxy_ip4_is_mapped_loopback(struct netif *netif, const ip_addr_t *dst, ip_addr_t *lo)
 {
-    ip_addr_t net;
     u32_t off;
     const struct ip4_lomap *lomap;
     size_t i;
diff --git a/src/VBox/NetworkServices/NAT/pxtcp.c b/src/VBox/NetworkServices/NAT/pxtcp.c
index 35f42eb..8bdc558 100644
--- a/src/VBox/NetworkServices/NAT/pxtcp.c
+++ b/src/VBox/NetworkServices/NAT/pxtcp.c
@@ -738,9 +738,7 @@ pxtcp_pcb_delete_pxtcp(void *ctx)
      * to close the socket.
      */
     if (pxtcp->sock != INVALID_SOCKET) {
-        int status = closesocket(pxtcp->sock);
-        DPRINTF(("%s:%d=closesocket(%d)\n", __func__, status, pxtcp->sock));
-
+        closesocket(pxtcp->sock);
         pxtcp->sock = INVALID_SOCKET;
     }
 
@@ -1108,8 +1106,7 @@ pxtcp_pmgr_connect(struct pollmgr_handler *handler, SOCKET fd, int revents)
             }
             s = pxtcp->sock;
             pxtcp->sock = INVALID_SOCKET;
-            status = closesocket(s);
-            DPRINTF(("%s: %d closesocket: %ld\n", status, s));
+            closesocket(s);
         }
         return pxtcp_schedule_reject(pxtcp);
     }
@@ -1552,7 +1549,7 @@ pxtcp_pcb_forward_outbound(struct pxtcp *pxtcp, struct pbuf *p)
         }
         if (qoff > 0) {
             /* advance payload pointer past the forwarded part */
-          pbuf_header(q, -(s16_t)qoff);
+            pbuf_header(q, -(s16_t)qoff);
         }
         pxtcp->unsent = q;
 
diff --git a/src/VBox/NetworkServices/NAT/pxudp.c b/src/VBox/NetworkServices/NAT/pxudp.c
index 6e8e63a..9213c7a 100644
--- a/src/VBox/NetworkServices/NAT/pxudp.c
+++ b/src/VBox/NetworkServices/NAT/pxudp.c
@@ -501,6 +501,7 @@ pxudp_pcb_forward_outbound(struct pxudp *pxudp, struct pbuf *p,
     }
 
     proxy_sendto(pxudp->sock, p, NULL, 0);
+    pbuf_free(p);
 }
 
 
diff --git a/src/VBox/NetworkServices/NAT/winutils.h b/src/VBox/NetworkServices/NAT/winutils.h
index dafd733..281c0c6 100644
--- a/src/VBox/NetworkServices/NAT/winutils.h
+++ b/src/VBox/NetworkServices/NAT/winutils.h
@@ -5,6 +5,7 @@
 #  include <iprt/cdefs.h>
 #  include <WinSock2.h>
 #  include <ws2tcpip.h>
+#  include <mswsock.h>
 #  include <Windows.h>
 #  include <iprt/err.h>
 #  include <iprt/net.h>
@@ -34,7 +35,49 @@
 #  define errx err
 #  define __func__ __FUNCTION__
 #  define __attribute__(x) /* IGNORE */
-#  define inet_ntop(dom, pvaddr, pstrbuf, cbstrbuf) InetNtop((dom),(pvaddr),(pstrbuf),(cbstrbuf))
+
+/*
+ * XXX: inet_ntop() is only available starting from Vista.
+ */
+DECLINLINE(PCSTR)
+inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize)
+{
+    DWORD size = (DWORD)StringBufSize;
+    int status;
+
+    if (Family == AF_INET)
+    {
+        struct sockaddr_in sin;
+        memset(&sin, 0, sizeof(sin));
+        sin.sin_family = AF_INET;
+        memcpy(&sin.sin_addr, pAddr, sizeof(sin.sin_addr));
+        sin.sin_port = 0;
+        status = WSAAddressToStringA((LPSOCKADDR)&sin, sizeof(sin), NULL,
+                                     pStringBuf, &size);
+    }
+    else if (Family == AF_INET6)
+    {
+        struct sockaddr_in6 sin6;
+        memset(&sin6, 0, sizeof(sin6));
+        sin6.sin6_family = AF_INET6;
+        memcpy(&sin6.sin6_addr, pAddr, sizeof(sin6.sin6_addr));
+        sin6.sin6_port = 0;
+        status = WSAAddressToStringA((LPSOCKADDR)&sin6, sizeof(sin6), NULL,
+                                     pStringBuf, &size);
+    }
+    else
+    {
+        WSASetLastError(WSAEAFNOSUPPORT);
+        return NULL;
+    }
+
+    if (status == SOCKET_ERROR)
+    {
+        return NULL;
+    }
+
+    return pStringBuf;
+}
 
 
 /**
@@ -55,14 +98,19 @@
 /* Missing errno codes */
 
 /**
- * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx#WSAEHOSTDOWN
- * Corresponds to WSAEHOSTDOWN (10064) WSAGetLastError()
- */
-#  define EHOSTDOWN WSAEHOSTDOWN
-/**
- * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx#WSAEHOSTUNREACH
+ * "Windows Sockets Error Codes" obtained with WSAGetLastError().
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
  */
-#  define EHOSTUNREAH WSAEHOSTUNREACH
+#  undef  EMSGSIZE
+#  define EMSGSIZE              WSAEMSGSIZE
+#  undef  ENETDOWN
+#  define ENETDOWN              WSAENETDOWN
+#  undef  ENETUNREACH
+#  define ENETUNREACH           WSAENETUNREACH
+#  undef  EHOSTDOWN
+#  define EHOSTDOWN             WSAEHOSTDOWN
+#  undef  EHOSTUNREACH
+#  define EHOSTUNREACH          WSAEHOSTUNREACH
 
 /**
  * parameters to shutdown (2) with Winsock2
@@ -72,8 +120,6 @@
 #  define SHUT_WR SD_SEND
 #  define SHUT_RDWR SD_BOTH
 
-typedef int socklen_t;
-
 typedef ULONG nfds_t;
 
 typedef WSABUF IOVEC;
@@ -84,6 +130,19 @@ typedef WSABUF IOVEC;
 #  define IOVEC_GET_LEN(iov) ((iov).len)
 #  define IOVEC_SET_LEN(iov, l) ((iov).len = (ULONG)(l))
 
+#if _WIN32_WINNT < 0x0600
+/* otherwise defined the other way around in ws2def.h */
+#define cmsghdr _WSACMSGHDR
+
+#undef CMSG_DATA       /* wincrypt.h can byte my shiny metal #undef */
+#define CMSG_DATA WSA_CMSG_DATA
+#define CMSG_LEN WSA_CMSG_LEN
+#define CMSG_SPACE WSA_CMSG_SPACE
+
+#define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
+#define CMSG_NXTHDR WSA_CMSG_NXTHDR
+#endif  /* _WIN32_WINNT < 0x0600 - provide unglified CMSG names */
+
 RT_C_DECLS_BEGIN
 int RTWinSocketPair(int domain, int type, int protocol, SOCKET socket_vector[2]);
 RT_C_DECLS_END
diff --git a/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp b/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp
new file mode 100644
index 0000000..3345236
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp
@@ -0,0 +1,215 @@
+/* $Id: ComHostUtils.cpp $ */
+/** @file
+ * ComHostUtils.cpp
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#ifdef RT_OS_WINDOWS
+# define VBOX_COM_OUTOFPROC_MODULE
+#endif
+#include <VBox/com/com.h>
+#include <VBox/com/listeners.h>
+#include <VBox/com/string.h>
+#include <VBox/com/Guid.h>
+#include <VBox/com/array.h>
+#include <VBox/com/ErrorInfo.h>
+#include <VBox/com/errorprint.h>
+#include <VBox/com/EventQueue.h>
+#include <VBox/com/VirtualBox.h>
+
+#include <iprt/alloca.h>
+#include <iprt/buildconfig.h>
+#include <iprt/err.h>
+#include <iprt/net.h>                   /* must come before getopt */
+#include <iprt/getopt.h>
+#include <iprt/initterm.h>
+#include <iprt/message.h>
+#include <iprt/param.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/time.h>
+#include <iprt/string.h>
+
+
+#include "../NetLib/VBoxNetLib.h"
+#include "../NetLib/shared_ptr.h"
+
+#include <vector>
+#include <list>
+#include <string>
+#include <map>
+
+#include "../NetLib/VBoxNetBaseService.h"
+
+#ifdef RT_OS_WINDOWS /* WinMain */
+# include <Windows.h>
+# include <stdlib.h>
+# ifdef INET_ADDRSTRLEN
+/* On Windows INET_ADDRSTRLEN defined as 22 Ws2ipdef.h, because it include port number */
+#  undef INET_ADDRSTRLEN
+# endif
+# define INET_ADDRSTRLEN 16
+#else
+# include <netinet/in.h>
+#endif
+
+#include "utils.h"
+
+
+VBOX_LISTENER_DECLARE(NATNetworkListenerImpl)
+
+
+int localMappings(const ComNatPtr& nat, AddressToOffsetMapping& mapping)
+{
+    mapping.clear();
+
+    ComBstrArray strs;
+    int cStrs;
+    HRESULT hrc = nat->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));
+    if (   SUCCEEDED(hrc)
+        && (cStrs = strs.size()))
+    {
+        for (int i = 0; i < cStrs; ++i)
+        {
+            char szAddr[17];
+            RTNETADDRIPV4 ip4addr;
+            char *pszTerm;
+            uint32_t u32Off;
+            com::Utf8Str strLo2Off(strs[i]);
+            const char *pszLo2Off = strLo2Off.c_str();
+
+            RT_ZERO(szAddr);
+
+            pszTerm = RTStrStr(pszLo2Off, "=");
+
+            if (   pszTerm
+                   && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN)
+            {
+                memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));
+                int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);
+                if (RT_SUCCESS(rc))
+                {
+                    u32Off = RTStrToUInt32(pszTerm + 1);
+                    if (u32Off != 0)
+                        mapping.insert(
+                          AddressToOffsetMapping::value_type(ip4addr, u32Off));
+                }
+            }
+        }
+    }
+    else
+        return VERR_NOT_FOUND;
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * @note: const dropped here, because of map<K,V>::operator[] which isn't const, map<K,V>::at() has const
+ * variant but it's C++11.
+ */
+int hostDnsServers(const ComHostPtr& host, const RTNETADDRIPV4& networkid,
+                   /*const*/ AddressToOffsetMapping& mapping, AddressList& servers)
+{
+    servers.clear();
+
+    ComBstrArray strs;
+    if (SUCCEEDED(host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs))))
+    {
+        RTNETADDRIPV4 addr;
+        int rc;
+
+        for (unsigned int i = 0; i < strs.size(); ++i)
+        {
+            rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);
+            if (RT_SUCCESS(rc))
+            {
+                if (addr.au8[0] == 127)
+                {
+                    /* XXX: here we want map<K,V>::at(const K& k) const */
+                    if (mapping[addr] != 0)
+                    {
+                        addr.u = RT_H2N_U32(RT_N2H_U32(networkid.u)
+                                            + mapping[addr]);
+                    }
+                    else
+                        continue; /* XXX: Warning here (local mapping wasn't registered) */
+                }
+
+                servers.push_back(addr);
+            }
+        }
+    }
+    else
+        return VERR_NOT_FOUND;
+
+    return VINF_SUCCESS;
+}
+
+
+int hostDnsSearchList(const ComHostPtr& host, std::vector<std::string>& strings)
+{
+    strings.clear();
+
+    ComBstrArray strs;
+    if (SUCCEEDED(host->COMGETTER(SearchStrings)(ComSafeArrayAsOutParam(strs))))
+    {
+        for (unsigned int i = 0; i < strs.size(); ++i)
+        {
+            strings.push_back(com::Utf8Str(strs[i]).c_str());
+        }
+    }
+    else
+        return VERR_NOT_FOUND;
+
+    return VINF_SUCCESS;
+}
+
+
+int hostDnsDomain(const ComHostPtr& host, std::string& domainStr)
+{
+    com::Bstr domain;
+    if (SUCCEEDED(host->COMGETTER(DomainName)(domain.asOutParam())))
+    {
+        domainStr = com::Utf8Str(domain).c_str();
+        return VINF_SUCCESS;
+    }
+
+    return VERR_NOT_FOUND;
+}
+
+
+int createNatListener(ComNatListenerPtr& listener, const ComVirtualBoxPtr& vboxptr,
+                      NATNetworkEventAdapter *adapter, /* const */ ComEventTypeArray& events)
+{
+    ComObjPtr<NATNetworkListenerImpl> obj;
+    HRESULT hrc = obj.createObject();
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    hrc = obj->init(new NATNetworkListener(), adapter);
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    ComPtr<IEventSource> esVBox;
+    hrc = vboxptr->COMGETTER(EventSource)(esVBox.asOutParam());
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    listener = obj;
+
+    hrc = esVBox->RegisterListener(listener, ComSafeArrayAsInParam(events), true);
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    return VINF_SUCCESS;
+}
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
index 9634a36..0a01075 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
@@ -28,8 +28,8 @@
 #include <VBox/com/array.h>
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
 #include <VBox/com/VirtualBox.h>
+#include <VBox/com/NativeEventQueue.h>
 
 #include <iprt/alloca.h>
 #include <iprt/buildconfig.h>
@@ -43,6 +43,7 @@
 #include <iprt/stream.h>
 #include <iprt/string.h>
 #include <iprt/time.h>
+#include <iprt/thread.h>
 #include <iprt/mem.h>
 #include <iprt/message.h>
 
@@ -70,6 +71,60 @@
 /*******************************************************************************
 *   Structures and Typedefs                                                    *
 *******************************************************************************/
+struct VBoxNetBaseService::Data
+{
+    Data(const std::string& aName, const std::string& aNetworkName):
+      m_Name(aName),
+      m_Network(aNetworkName),
+      m_enmTrunkType(kIntNetTrunkType_WhateverNone),
+      m_pSession(NIL_RTR0PTR),
+      m_cbSendBuf(128 * _1K),
+      m_cbRecvBuf(256 * _1K),
+      m_hIf(INTNET_HANDLE_INVALID),
+      m_pIfBuf(NULL),
+      m_cVerbosity(0),
+      m_fNeedMain(false),
+      m_EventQ(NULL),
+      m_hThrRecv(NIL_RTTHREAD),
+      fShutdown(false)
+    {
+        int rc = RTCritSectInit(&m_csThis);
+        AssertRC(rc);
+    };
+
+    std::string         m_Name;
+    std::string         m_Network;
+    std::string         m_TrunkName;
+    INTNETTRUNKTYPE     m_enmTrunkType;
+
+    RTMAC               m_MacAddress;
+    RTNETADDRIPV4       m_Ipv4Address;
+    RTNETADDRIPV4       m_Ipv4Netmask;
+
+    PSUPDRVSESSION      m_pSession;
+    uint32_t            m_cbSendBuf;
+    uint32_t            m_cbRecvBuf;
+    INTNETIFHANDLE      m_hIf;          /**< The handle to the network interface. */
+    PINTNETBUF          m_pIfBuf;       /**< Interface buffer. */
+
+    std::vector<PRTGETOPTDEF> m_vecOptionDefs;
+
+    int32_t             m_cVerbosity;
+
+    /* cs for syncing */
+    RTCRITSECT          m_csThis;
+
+    /* Controls whether service will connect SVC for runtime needs */
+    bool                m_fNeedMain;
+    /* Event Queue */
+    com::NativeEventQueue  *m_EventQ;
+
+    /** receiving thread, used only if main is used */
+    RTTHREAD m_hThrRecv;
+
+    bool fShutdown;
+    static int recvLoop(RTTHREAD, void *);
+};
 
 /*******************************************************************************
 *   Global Variables                                                           *
@@ -89,23 +144,25 @@ static RTGETOPTDEF g_aGetOptDef[] =
 };
 
 
-VBoxNetBaseService::VBoxNetBaseService()
+int VBoxNetBaseService::Data::recvLoop(RTTHREAD, void *pvUser)
 {
-    int rc = RTCritSectInit(&m_csThis);
-    AssertRC(rc);
-    /* numbers from DrvIntNet */
-    m_cbSendBuf             = 128 * _1K;
-    m_cbRecvBuf             = 256 * _1K;
-    m_hIf                   = INTNET_HANDLE_INVALID;
-    m_pIfBuf                = NULL;
+    VBoxNetBaseService *pThis = static_cast<VBoxNetBaseService *>(pvUser);
+
+    HRESULT hrc = com::Initialize();
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    pThis->doReceiveLoop();
 
-    m_cVerbosity            = 0;
-    m_Name                  = "VBoxNetNAT";
-    m_Network               = "intnet";
-    m_fNeedMain             = false;
+    return VINF_SUCCESS;
+}
+
+
+VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
+{
+    m = new VBoxNetBaseService::Data(aName, aNetworkName);
 
     for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
-        m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
+        m->m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
 }
 
 
@@ -114,24 +171,32 @@ VBoxNetBaseService::~VBoxNetBaseService()
     /*
      * Close the interface connection.
      */
-    if (m_hIf != INTNET_HANDLE_INVALID)
+    if (m != NULL)
     {
-        INTNETIFCLOSEREQ CloseReq;
-        CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-        CloseReq.Hdr.cbReq = sizeof(CloseReq);
-        CloseReq.pSession = m_pSession;
-        CloseReq.hIf = m_hIf;
-        m_hIf = INTNET_HANDLE_INVALID;
-        int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
-        AssertRC(rc);
-    }
+        shutdown();
+        if (m->m_hIf != INTNET_HANDLE_INVALID)
+        {
+            INTNETIFCLOSEREQ CloseReq;
+            CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+            CloseReq.Hdr.cbReq = sizeof(CloseReq);
+            CloseReq.pSession = m->m_pSession;
+            CloseReq.hIf = m->m_hIf;
+            m->m_hIf = INTNET_HANDLE_INVALID;
+            int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
+            AssertRC(rc);
+        }
 
-    if (m_pSession)
-    {
-        SUPR3Term(false /*fForced*/);
-        m_pSession = NIL_RTR0PTR;
+        if (m->m_pSession != NIL_RTR0PTR)
+        {
+            SUPR3Term(false /*fForced*/);
+            m->m_pSession = NIL_RTR0PTR;
+        }
+
+        RTCritSectDelete(&m->m_csThis);
+
+        delete m;
+        m = NULL;
     }
-    RTCritSectDelete(&m_csThis);
 }
 
 
@@ -150,6 +215,27 @@ int VBoxNetBaseService::init()
 }
 
 
+bool VBoxNetBaseService::isMainNeeded() const
+{
+    return m->m_fNeedMain;
+}
+
+
+int VBoxNetBaseService::run()
+{
+    /**
+     * If child class need Main we start receving thread which calls doReceiveLoop and enter to event polling loop
+     * and for the rest clients we do receiving on the current (main) thread.
+     */
+    if (isMainNeeded())
+        return startReceiveThreadAndEnterEventLoop();
+    else
+    {
+        doReceiveLoop();
+        return VINF_SUCCESS;
+    }
+}
+
 /**
  * Parse the arguments.
  *
@@ -163,7 +249,7 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
 
     RTGETOPTSTATE State;
     PRTGETOPTDEF paOptionArray = getOptionsPtr();
-    int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
+    int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
     AssertRCReturn(rc, 49);
 #if 0
     /* default initialization */
@@ -180,28 +266,28 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
         switch (rc)
         {
             case 'N': // --name
-                m_Name = Val.psz;
+                m->m_Name = Val.psz;
                 break;
 
             case 'n': // --network
-                m_Network = Val.psz;
+                m->m_Network = Val.psz;
                 break;
 
             case 't': //--trunk-name
-                m_TrunkName = Val.psz;
+                m->m_TrunkName = Val.psz;
                 break;
 
             case 'T': //--trunk-type
                 if (!strcmp(Val.psz, "none"))
-                    m_enmTrunkType = kIntNetTrunkType_None;
+                    m->m_enmTrunkType = kIntNetTrunkType_None;
                 else if (!strcmp(Val.psz, "whatever"))
-                    m_enmTrunkType = kIntNetTrunkType_WhateverNone;
+                    m->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
                 else if (!strcmp(Val.psz, "netflt"))
-                    m_enmTrunkType = kIntNetTrunkType_NetFlt;
+                    m->m_enmTrunkType = kIntNetTrunkType_NetFlt;
                 else if (!strcmp(Val.psz, "netadp"))
-                    m_enmTrunkType = kIntNetTrunkType_NetAdp;
+                    m->m_enmTrunkType = kIntNetTrunkType_NetAdp;
                 else if (!strcmp(Val.psz, "srvnat"))
-                    m_enmTrunkType = kIntNetTrunkType_SrvNat;
+                    m->m_enmTrunkType = kIntNetTrunkType_SrvNat;
                 else
                 {
                     RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
@@ -210,19 +296,19 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
                 break;
 
             case 'a': // --mac-address
-                m_MacAddress = Val.MacAddr;
+                m->m_MacAddress = Val.MacAddr;
                 break;
 
             case 'i': // --ip-address
-                m_Ipv4Address = Val.IPv4Addr;
+                m->m_Ipv4Address = Val.IPv4Addr;
                 break;
 
-            case 'm': // --netmask 
-                m_Ipv4Netmask = Val.IPv4Addr;
+            case 'm': // --netmask
+                m->m_Ipv4Netmask = Val.IPv4Addr;
                 break;
 
             case 'v': // --verbose
-                m_cVerbosity++;
+                m->m_cVerbosity++;
                 break;
 
             case 'V': // --version (missed)
@@ -230,7 +316,7 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
                 return 1;
 
             case 'M': // --need-main
-                m_fNeedMain = true;
+                m->m_fNeedMain = true;
                 break;
 
             case 'h': // --help (missed)
@@ -245,8 +331,8 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
                          RTBldCfgVersion(),
                          RTBldCfgRevision(),
                          RTProcShortName());
-                for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++)
-                    RTPrintf("    -%c, %s\n", m_vecOptionDefs[i]->iShort, m_vecOptionDefs[i]->pszLong);
+                for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
+                    RTPrintf("    -%c, %s\n", m->m_vecOptionDefs[i]->iShort, m->m_vecOptionDefs[i]->pszLong);
                 usage(); /* to print Service Specific usage */
                 return 1;
 
@@ -271,10 +357,10 @@ int VBoxNetBaseService::tryGoOnline(void)
     /*
      * Open the session, load ring-0 and issue the request.
      */
-    int rc = SUPR3Init(&m_pSession);
+    int rc = SUPR3Init(&m->m_pSession);
     if (RT_FAILURE(rc))
     {
-        m_pSession = NIL_RTR0PTR;
+        m->m_pSession = NIL_RTR0PTR;
         LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
         return 1;
     }
@@ -301,15 +387,15 @@ int VBoxNetBaseService::tryGoOnline(void)
     INTNETOPENREQ OpenReq;
     OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     OpenReq.Hdr.cbReq = sizeof(OpenReq);
-    OpenReq.pSession = m_pSession;
-    strncpy(OpenReq.szNetwork, m_Network.c_str(), sizeof(OpenReq.szNetwork));
+    OpenReq.pSession = m->m_pSession;
+    strncpy(OpenReq.szNetwork, m->m_Network.c_str(), sizeof(OpenReq.szNetwork));
     OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
-    strncpy(OpenReq.szTrunk, m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
+    strncpy(OpenReq.szTrunk, m->m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
     OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
-    OpenReq.enmTrunkType = m_enmTrunkType;
+    OpenReq.enmTrunkType = m->m_enmTrunkType;
     OpenReq.fFlags = 0; /** @todo check this */
-    OpenReq.cbSend = m_cbSendBuf;
-    OpenReq.cbRecv = m_cbRecvBuf;
+    OpenReq.cbSend = m->m_cbSendBuf;
+    OpenReq.cbRecv = m->m_cbRecvBuf;
     OpenReq.hIf = INTNET_HANDLE_INVALID;
 
     /*
@@ -322,8 +408,8 @@ int VBoxNetBaseService::tryGoOnline(void)
         Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
         goto bad;
     }
-    m_hIf = OpenReq.hIf;
-    Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m_hIf));
+    m->m_hIf = OpenReq.hIf;
+    Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
 
     /*
      * Get the ring-3 address of the shared interface buffer.
@@ -331,8 +417,8 @@ int VBoxNetBaseService::tryGoOnline(void)
     INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
     GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
-    GetBufferPtrsReq.pSession = m_pSession;
-    GetBufferPtrsReq.hIf = m_hIf;
+    GetBufferPtrsReq.pSession = m->m_pSession;
+    GetBufferPtrsReq.hIf = m->m_hIf;
     GetBufferPtrsReq.pRing3Buf = NULL;
     GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
@@ -344,7 +430,7 @@ int VBoxNetBaseService::tryGoOnline(void)
     pBuf = GetBufferPtrsReq.pRing3Buf;
     Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
                pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
-    m_pIfBuf = pBuf;
+    m->m_pIfBuf = pBuf;
 
     /*
      * Activate the interface.
@@ -352,8 +438,8 @@ int VBoxNetBaseService::tryGoOnline(void)
     INTNETIFSETACTIVEREQ ActiveReq;
     ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
-    ActiveReq.pSession = m_pSession;
-    ActiveReq.hIf = m_hIf;
+    ActiveReq.pSession = m->m_pSession;
+    ActiveReq.hIf = m->m_hIf;
     ActiveReq.fActive = true;
     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
     if (RT_SUCCESS(rc))
@@ -370,6 +456,21 @@ int VBoxNetBaseService::tryGoOnline(void)
 
 void VBoxNetBaseService::shutdown(void)
 {
+    syncEnter();
+    m->fShutdown = true;
+    syncLeave();
+}
+
+
+int VBoxNetBaseService::syncEnter()
+{
+    return RTCritSectEnter(&m->m_csThis);
+}
+
+
+int VBoxNetBaseService::syncLeave()
+{
+    return RTCritSectLeave(&m->m_csThis);
 }
 
 
@@ -380,8 +481,8 @@ int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
     LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
     WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     WaitReq.Hdr.cbReq = sizeof(WaitReq);
-    WaitReq.pSession = m_pSession;
-    WaitReq.hIf = m_hIf;
+    WaitReq.pSession = m->m_pSession;
+    WaitReq.hIf = m->m_hIf;
     WaitReq.cMillies = cMillis;
 
     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
@@ -392,26 +493,28 @@ int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
 /* S/G API */
 int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
 {
-    int rc = VINF_SUCCESS;
     PINTNETHDR pHdr = NULL;
     uint8_t *pu8Frame = NULL;
-    int offFrame = 0;
-    int idxSg = 0;
+
     /* Allocate frame */
-    rc = IntNetRingAllocateFrame(&m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
+    int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
     AssertRCReturn(rc, rc);
+
     /* Now we fill pvFrame with S/G above */
-    for (idxSg = 0; idxSg < cSg; ++idxSg)
+    int offFrame = 0;
+    for (int idxSg = 0; idxSg < cSg; ++idxSg)
     {
         memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
         offFrame+=pcSg[idxSg].cb;
     }
+
     /* Commit */
-    IntNetRingCommitFrame(&m_pIfBuf->Send, pHdr);
+    IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
 
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
+
 /**
  * forcible ask for send packet on the "wire"
  */
@@ -421,8 +524,8 @@ void VBoxNetBaseService::flushWire()
     INTNETIFSENDREQ SendReq;
     SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     SendReq.Hdr.cbReq    = sizeof(SendReq);
-    SendReq.pSession     = m_pSession;
-    SendReq.hIf          = m_hIf;
+    SendReq.pSession     = m->m_pSession;
+    SendReq.hIf          = m->m_hIf;
     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
     AssertRCReturnVoid(rc);
     LogFlowFuncLeave();
@@ -430,6 +533,239 @@ void VBoxNetBaseService::flushWire()
 }
 
 
+int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+                                         void const *pvData, size_t cbData) const
+{
+    return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
+                        m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
+                        uDstPort, pvData, cbData);
+
+}
+
+
+const std::string VBoxNetBaseService::getName() const
+{
+    return m->m_Name;
+}
+
+
+void VBoxNetBaseService::setName(const std::string& aName)
+{
+    m->m_Name = aName;
+}
+
+
+const std::string VBoxNetBaseService::getNetwork() const
+{
+    return m->m_Network;
+}
+
+
+void VBoxNetBaseService::setNetwork(const std::string& aNetwork)
+{
+    m->m_Network = aNetwork;
+}
+
+
+const RTMAC VBoxNetBaseService::getMacAddress() const
+{
+    return m->m_MacAddress;
+}
+
+
+void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
+{
+    m->m_MacAddress = aMac;
+}
+
+
+const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
+{
+    return m->m_Ipv4Address;
+}
+
+
+void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
+{
+    m->m_Ipv4Address = aAddress;
+}
+
+
+const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
+{
+    return m->m_Ipv4Netmask;
+}
+
+
+void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
+{
+    m->m_Ipv4Netmask = aNetmask;
+}
+
+
+uint32_t VBoxNetBaseService::getSendBufSize() const
+{
+    return m->m_cbSendBuf;
+}
+
+
+void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
+{
+    m->m_cbSendBuf = cbBuf;
+}
+
+
+uint32_t VBoxNetBaseService::getRecvBufSize() const
+{
+    return m->m_cbRecvBuf;
+}
+
+
+void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
+{
+    m->m_cbRecvBuf = cbBuf;
+}
+
+
+int32_t VBoxNetBaseService::getVerbosityLevel() const
+{
+    return m->m_cVerbosity;
+}
+
+
+void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
+{
+    m->m_cVerbosity = aVerbosity;
+}
+
+
+void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
+{
+    m->m_vecOptionDefs.push_back(optDef);
+}
+
+
+void VBoxNetBaseService::doReceiveLoop()
+{
+    int rc;
+    /* Well we're ready */
+    PINTNETRINGBUF  pRingBuf = &m->m_pIfBuf->Recv;
+
+    for (;;)
+    {
+        /*
+         * Wait for a packet to become available.
+         */
+        /* 2. waiting for request for */
+        rc = waitForIntNetEvent(2000);
+        if (RT_FAILURE(rc))
+        {
+            if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
+            {
+                /* do we want interrupt anyone ??? */
+                continue;
+            }
+            LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
+            AssertRCReturnVoid(rc);
+        }
+
+        /*
+         * Process the receive buffer.
+         */
+        PCINTNETHDR pHdr;
+
+        while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
+        {
+            uint8_t const u8Type = pHdr->u8Type;
+            size_t         cbFrame = pHdr->cbFrame;
+            switch (u8Type)
+            {
+
+                case INTNETHDR_TYPE_FRAME:
+                    {
+                        void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
+                        rc = processFrame(pvFrame, cbFrame);
+                        if (RT_FAILURE(rc) && rc == VERR_IGNORED)
+                        {
+                            /* XXX: UDP + ARP for DHCP */
+                            VBOXNETUDPHDRS Hdrs;
+                            size_t  cb;
+                            void   *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
+                                                         VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST
+                                                         | VBOXNETUDP_MATCH_CHECKSUM
+                                                         | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
+                                                         &Hdrs, &cb);
+                            if (pv && cb)
+                                processUDP(pv, cb);
+                            else
+                                VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
+                        }
+                    }
+                    break;
+                case INTNETHDR_TYPE_GSO:
+                  {
+                      PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
+                      rc = processGSO(pGso, cbFrame);
+                      if (RT_FAILURE(rc) && rc == VERR_IGNORED)
+                          break;
+                  }
+                  break;
+                case INTNETHDR_TYPE_PADDING:
+                    break;
+                default:
+                    break;
+            }
+            IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
+
+        } /* loop */
+    }
+
+}
+
+
+int VBoxNetBaseService::startReceiveThreadAndEnterEventLoop()
+{
+    AssertMsgReturn(isMainNeeded(), ("It's expected that we need Main"), VERR_INTERNAL_ERROR);
+
+    /* start receiving thread */
+    int rc = RTThreadCreate(&m->m_hThrRecv, /* thread handle*/
+                            &VBoxNetBaseService::Data::recvLoop,  /* routine */
+                            this, /* user data */
+                            128 * _1K, /* stack size */
+                            RTTHREADTYPE_IO, /* type */
+                            0, /* flags, @todo: waitable ?*/
+                            "RECV");
+    AssertRCReturn(rc,rc);
+
+    m->m_EventQ = com::NativeEventQueue::getMainEventQueue();
+    AssertPtrReturn(m->m_EventQ, VERR_INTERNAL_ERROR);
+
+    while(true)
+    {
+        m->m_EventQ->processEventQueue(0);
+
+        if (m->fShutdown)
+            break;
+
+        m->m_EventQ->processEventQueue(500);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
+{
+    if (iMinLevel <= m->m_cVerbosity)
+    {
+        va_list va;
+        va_start(va, pszFmt);
+        debugPrintV(iMinLevel, fMsg, pszFmt, va);
+        va_end(va);
+    }
+}
+
+
 /**
  * Print debug message depending on the m_cVerbosity level.
  *
@@ -440,7 +776,7 @@ void VBoxNetBaseService::flushWire()
  */
 void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
 {
-    if (iMinLevel <= m_cVerbosity)
+    if (iMinLevel <= m->m_cVerbosity)
     {
         va_list vaCopy;                 /* This dude is *very* special, thus the copy. */
         va_copy(vaCopy, va);
@@ -458,13 +794,13 @@ void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFm
 PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
 {
     PRTGETOPTDEF pOptArray = NULL;
-    pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m_vecOptionDefs.size());
+    pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
     if (!pOptArray)
         return NULL;
-    for (unsigned int i = 0; i < m_vecOptionDefs.size(); ++i)
+    for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
     {
-        PRTGETOPTDEF pOpt = m_vecOptionDefs[i];
-        memcpy(&pOptArray[i], m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
+        PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
+        memcpy(&pOptArray[i], m->m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
     }
     return pOptArray;
 }
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
index e9be798..a551bc8 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
@@ -19,30 +19,98 @@
 #define ___VBoxNetBaseService_h___
 
 #include <iprt/critsect.h>
-class VBoxNetBaseService
+
+
+class VBoxNetHlpUDPService
+{
+public:
+virtual int                 hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+                                        void const *pvData, size_t cbData) const = 0;
+};
+
+
+class VBoxNetLockee
+{
+public:
+    virtual int  syncEnter() = 0;
+    virtual int  syncLeave() = 0;
+};
+
+
+class VBoxNetALock
+{
+public:
+    VBoxNetALock(VBoxNetLockee *a_lck):m_lck(a_lck)
+    {
+        if (m_lck)
+            m_lck->syncEnter();
+    }
+
+    ~VBoxNetALock()
+    {
+        if (m_lck)
+            m_lck->syncLeave();
+    }
+
+private:
+    VBoxNetLockee *m_lck;
+};
+
+# ifndef BASE_SERVICES_ONLY
+class VBoxNetBaseService: public VBoxNetHlpUDPService, public VBoxNetLockee
 {
 public:
-    VBoxNetBaseService();
+    VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName);
     virtual ~VBoxNetBaseService();
     int                 parseArgs(int argc, char **argv);
     int                 tryGoOnline(void);
     void                shutdown(void);
-    int                 syncEnter() { return RTCritSectEnter(&this->m_csThis);}
-    int                 syncLeave() { return RTCritSectLeave(&this->m_csThis);}
+    int                 syncEnter();
+    int                 syncLeave();
     int                 waitForIntNetEvent(int cMillis);
     int                 sendBufferOnWire(PCINTNETSEG pSg, int cSg, size_t cbBuffer);
     void                flushWire();
 
+    virtual int         hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+                                        void const *pvData, size_t cbData) const;
     virtual void        usage(void) = 0;
-    virtual int         run(void) = 0;
     virtual int         parseOpt(int rc, const RTGETOPTUNION& getOptVal) = 0;
+    virtual int         processFrame(void *, size_t) = 0;
+    virtual int         processGSO(PCPDMNETWORKGSO, size_t) = 0;
+    virtual int         processUDP(void *, size_t) = 0;
+
 
     virtual int         init(void);
-    virtual bool        isMainNeeded() const { return m_fNeedMain; }
-    /* VirtualBox instance */
-    ComPtr<IVirtualBox> virtualbox;
+    virtual int         run(void);
+    virtual bool        isMainNeeded() const;
 
 protected:
+    const std::string getName() const;
+    void setName(const std::string&);
+
+    const std::string getNetwork() const;
+    void setNetwork(const std::string&);
+
+    const RTMAC getMacAddress() const;
+    void setMacAddress(const RTMAC&);
+
+    const RTNETADDRIPV4 getIpv4Address() const;
+    void setIpv4Address(const RTNETADDRIPV4&);
+
+    const RTNETADDRIPV4 getIpv4Netmask() const;
+    void setIpv4Netmask(const RTNETADDRIPV4&);
+
+    uint32_t getSendBufSize() const;
+    void setSendBufSize(uint32_t);
+
+    uint32_t getRecvBufSize() const;
+    void setRecvBufSize(uint32_t);
+
+    int32_t getVerbosityLevel() const;
+    void setVerbosityLevel(int32_t);
+
+    void addCommandLineOption(const PRTGETOPTDEF);
+
     /**
      * Print debug message depending on the m_cVerbosity level.
      *
@@ -51,49 +119,25 @@ protected:
      * @param   pszFmt          The message format string.
      * @param   ...             Optional arguments.
      */
-    void debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
-    {
-        if (iMinLevel <= m_cVerbosity)
-        {
-            va_list va;
-            va_start(va, pszFmt);
-            debugPrintV(iMinLevel, fMsg, pszFmt, va);
-            va_end(va);
-        }
-    }
-
+    void debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const;
     virtual void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
 
-    /** @name The server configuration data members.
-     * @{ */
-    std::string         m_Name;
-    std::string         m_Network;
-    std::string         m_TrunkName;
-    INTNETTRUNKTYPE     m_enmTrunkType;
-    RTMAC               m_MacAddress;
-    RTNETADDRIPV4       m_Ipv4Address;
-    RTNETADDRIPV4       m_Ipv4Netmask;
-    /** @} */
-    /** @name The network interface
-     * @{ */
-    PSUPDRVSESSION      m_pSession;
-    uint32_t            m_cbSendBuf;
-    uint32_t            m_cbRecvBuf;
-    INTNETIFHANDLE      m_hIf;          /**< The handle to the network interface. */
-    PINTNETBUF          m_pIfBuf;       /**< Interface buffer. */
-    std::vector<PRTGETOPTDEF> m_vecOptionDefs;
-    /** @} */
-    /** @name Debug stuff
-     * @{  */
-    int32_t             m_cVerbosity;
-private:
-    PRTGETOPTDEF getOptionsPtr();
+    private:
+    void doReceiveLoop();
 
-    /* cs for syncing */
-    RTCRITSECT          m_csThis;
-    /* Controls whether service will connect SVC for runtime needs */
-    bool                m_fNeedMain;
+    /** starts receiving thread and enter event polling loop. */
+    int startReceiveThreadAndEnterEventLoop();
 
-    /** @} */
+    protected:
+    /* VirtualBox instance */
+    ComPtr<IVirtualBox> virtualbox;
+
+    private:
+    struct Data;
+    Data *m;
+
+    private:
+    PRTGETOPTDEF getOptionsPtr();
 };
+# endif
 #endif
diff --git a/src/VBox/NetworkServices/NetLib/cpp/utils.h b/src/VBox/NetworkServices/NetLib/cpp/utils.h
new file mode 100644
index 0000000..21224b3
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/cpp/utils.h
@@ -0,0 +1,34 @@
+/* $Id$ */
+/** @file
+ * NetLib/cpp/utils.h
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef _NETLIB_CPP_UTILS_H_
+# define _NETLIB_CPP_UTILS_H_
+
+/* less operator for IPv4 addresess */
+static bool operator <(const RTNETADDRIPV4& a, const RTNETADDRIPV4& b)
+{
+    return (RT_N2H_U32(a.u) < RT_N2H_U32(b.u));
+}
+
+/*  Compares MAC addresses */
+static bool operator== (const RTMAC& lhs, const RTMAC& rhs)
+{
+    return (   lhs.au16[0] == rhs.au16[0]
+            && lhs.au16[1] == rhs.au16[1]
+            && lhs.au16[2] == rhs.au16[2]);
+}
+#endif
diff --git a/src/VBox/NetworkServices/NetLib/shared_ptr.h b/src/VBox/NetworkServices/NetLib/shared_ptr.h
index 8bdfcce..ad892de 100644
--- a/src/VBox/NetworkServices/NetLib/shared_ptr.h
+++ b/src/VBox/NetworkServices/NetLib/shared_ptr.h
@@ -2,10 +2,10 @@
 #define __SHARED_PTR_H__
 
 #ifdef __cplusplus
-template<typename T> 
+template<typename T>
 class SharedPtr
 {
-    struct imp 
+    struct imp
     {
         imp(T *pTrg = NULL, int cnt = 1): ptr(pTrg),refcnt(cnt){}
         ~imp() { if (ptr) delete ptr;}
@@ -14,13 +14,13 @@ class SharedPtr
         int refcnt;
     };
 
-    
+
     public:
     SharedPtr(T *t = NULL):p(NULL)
     {
         p = new imp(t);
     }
-    
+
     ~SharedPtr()
     {
         p->refcnt--;
@@ -39,9 +39,9 @@ class SharedPtr
     const SharedPtr& operator= (const SharedPtr& rhs)
     {
         if (p == rhs.p) return *this;
-        
+
         p->refcnt--;
-        if (p->refcnt == 0) 
+        if (p->refcnt == 0)
             delete p;
 
         p = rhs.p;
@@ -56,13 +56,13 @@ class SharedPtr
         return p->ptr;
     }
 
-    
+
     T *operator->()
     {
         return p->ptr;
     }
 
-    
+
     const T*operator->() const
     {
         return p->ptr;
@@ -78,4 +78,5 @@ class SharedPtr
     imp *p;
 };
 #endif
+
 #endif
diff --git a/src/VBox/NetworkServices/NetLib/utils.h b/src/VBox/NetworkServices/NetLib/utils.h
new file mode 100644
index 0000000..d96b5c0
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/utils.h
@@ -0,0 +1,133 @@
+/* $Id: utils.h $ */
+/** @file
+ * ComHostUtils.cpp
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#ifndef _NETLIB_UTILS_H_
+#define _NETLIB_UTILS_H_
+
+#include "cpp/utils.h"
+
+typedef ComPtr<IVirtualBox> ComVirtualBoxPtr;
+typedef ComPtr<IDHCPServer> ComDhcpServerPtr;
+typedef ComPtr<IHost> ComHostPtr;
+typedef ComPtr<INATNetwork> ComNatPtr;
+typedef com::SafeArray<BSTR> ComBstrArray;
+
+typedef std::vector<RTNETADDRIPV4> AddressList;
+typedef std::map<RTNETADDRIPV4, int> AddressToOffsetMapping;
+
+
+inline bool isDhcpRequired(const ComNatPtr& nat)
+{
+    BOOL fNeedDhcpServer = false;
+    if (FAILED(nat->COMGETTER(NeedDhcpServer)(&fNeedDhcpServer)))
+        return false;
+
+    return fNeedDhcpServer;
+}
+
+
+inline int findDhcpServer(const ComVirtualBoxPtr& vbox, const std::string& name, ComDhcpServerPtr& dhcp)
+{
+    HRESULT hrc = vbox->FindDHCPServerByNetworkName(com::Bstr(name.c_str()).raw(),
+                                                          dhcp.asOutParam());
+    AssertComRCReturn(hrc, VERR_NOT_FOUND);
+
+    return VINF_SUCCESS;
+}
+
+
+inline int findNatNetwork(const ComVirtualBoxPtr& vbox, const std::string& name, ComNatPtr& nat)
+{
+    HRESULT hrc = vbox->FindNATNetworkByName(com::Bstr(name.c_str()).raw(),
+                                                   nat.asOutParam());
+
+    AssertComRCReturn(hrc, VERR_NOT_FOUND);
+
+    return VINF_SUCCESS;
+}
+
+
+inline RTNETADDRIPV4 networkid(const RTNETADDRIPV4& addr, const RTNETADDRIPV4& netmask)
+{
+    RTNETADDRIPV4 netid;
+    netid.u = addr.u & netmask.u;
+    return netid;
+}
+
+
+int localMappings(const ComNatPtr&, AddressToOffsetMapping&);
+int hostDnsServers(const ComHostPtr&, const RTNETADDRIPV4&,/* const */ AddressToOffsetMapping&, AddressList&);
+int hostDnsSearchList(const ComHostPtr&, std::vector<std::string>&);
+int hostDnsDomain(const ComHostPtr&, std::string& domainStr);
+
+
+class NATNetworkEventAdapter
+{
+    public:
+    virtual HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent) = 0;
+};
+
+
+class NATNetworkListener
+{
+    public:
+    NATNetworkListener():m_pNAT(NULL){}
+
+    HRESULT init(NATNetworkEventAdapter *pNAT)
+    {
+        AssertPtrReturn(pNAT, E_INVALIDARG);
+
+        m_pNAT = pNAT;
+        return S_OK;
+    }
+
+    HRESULT init()
+    {
+        m_pNAT = NULL;
+        return S_OK;
+    }
+
+    void uninit() { m_pNAT = NULL; }
+
+    HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
+    {
+        if (m_pNAT)
+            return m_pNAT->HandleEvent(aEventType, pEvent);
+        else
+            return E_FAIL;
+    }
+
+    private:
+    NATNetworkEventAdapter *m_pNAT;
+};
+typedef ListenerImpl<NATNetworkListener, NATNetworkEventAdapter*> NATNetworkListenerImpl;
+
+# if VBOX_WITH_XPCOM
+class NS_CLASSINFO_NAME(NATNetworkListenerImpl);
+# endif
+
+typedef ComPtr<NATNetworkListenerImpl> ComNatListenerPtr;
+typedef com::SafeArray<VBoxEventType_T> ComEventTypeArray;
+
+/* XXX: const is commented out because of compilation erro on Windows host, but it's intended that this function
+ isn't modify event type array */
+int createNatListener(ComNatListenerPtr& listener, const ComVirtualBoxPtr& vboxptr,
+                      NATNetworkEventAdapter *adapter, /* const */ ComEventTypeArray& events);
+#endif
diff --git a/src/VBox/Resources/OSE/virtualbox.svg b/src/VBox/Resources/OSE/virtualbox.svg
new file mode 100644
index 0000000..64573ad
--- /dev/null
+++ b/src/VBox/Resources/OSE/virtualbox.svg
@@ -0,0 +1,960 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="128px" height="128px" viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
+<pattern  x="-357.703" y="360.184" width="69" height="69" patternUnits="userSpaceOnUse" id="Polka_Dot_Pattern" viewBox="2.125 -70.896 69 69" overflow="visible">
+	<g>
+		<polygon fill="none" points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896 		"/>
+		<polygon fill="#F6BB60" points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896 		"/>
+		<g>
+			<path fill="#FFFFFF" d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335
+				c-0.051,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+		</g>
+		<g>
+			<path fill="#FFFFFF" d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.063-0.165,0.128
+				c-0.051,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+		</g>
+		<path fill="#FFFFFF" d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.063-0.165,0.128
+			c-0.051,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+			c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+			c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+			c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+			c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337
+			c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+			c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626
+			c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+		<g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					C8.15-41.004,8.149-41.02,8.14-41.04"/>
+				<path fill="#FFFFFF" d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+			<g>
+				<path fill="#FFFFFF" d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239
+					c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+					C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+				<path fill="#FFFFFF" d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+					C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161
+					c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631
+					C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45
+					c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071
+					c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+					c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+					c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+					c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			</g>
+		</g>
+		<g>
+			<path fill="#FFFFFF" d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46
+				c-0.051,0.063-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				c-0.021,0.011-0.021-0.005-0.03-0.025"/>
+			<path fill="#FFFFFF" d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.063-0.165,0.128
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207
+				c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169
+				C15.81-2.74,15.809-2.756,15.8-2.776"/>
+			<path fill="#FFFFFF" d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46
+				c-0.05,0.063-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587
+				c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631
+				C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221
+				c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367
+				c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751
+				C8.15-2.74,8.149-2.756,8.14-2.776"/>
+			<path fill="#FFFFFF" d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46
+				C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161
+				c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631
+				C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45
+				c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419
+				c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337
+				c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367
+				c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751
+				C0.489-2.74,0.488-2.756,0.479-2.776"/>
+		</g>
+	</g>
+</pattern>
+<g>
+	<g>
+		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="64.0005" y1="123" x2="64.0005" y2="5.001">
+			<stop  offset="0" style="stop-color:#1E78E6"/>
+			<stop  offset="1" style="stop-color:#418CFF"/>
+		</linearGradient>
+		<path fill-rule="evenodd" clip-rule="evenodd" fill="url(#SVGID_1_)" d="M123,111.654c0,6.266-5.08,11.346-11.347,11.346H16.347
+			C10.08,123,5,117.92,5,111.654V16.346C5,10.08,10.08,5,16.347,5h95.307C117.92,5,123,10.08,123,16.346V111.654z"/>
+		<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M64.014,18.603H18.616v90.794h45.398h45.371V18.603H64.014z
+			 M102.01,101.996H64.014l-38.022-0.025l0.05-41.66h9.037l12.053,38.047L61.544,51.17l2.47,7.972l6.128,19.633l8.521-27.63
+			l8.648,27.582h14.698V101.996z M92.037,71.429L78.688,29.64l-8.598,29.451l-6.077-20.75l-2.519-8.676L47.158,76.959l-7.714-23.94
+			H26.042l0.028-26.964h37.944h37.97l0.025,45.374H92.037z"/>
+	</g>
+	<rect fill-rule="evenodd" clip-rule="evenodd" fill="none" width="128" height="128"/>
+</g>
+</svg>
diff --git a/src/VBox/Runtime/Makefile.kmk b/src/VBox/Runtime/Makefile.kmk
index 56c7533..eb7e12a 100644
--- a/src/VBox/Runtime/Makefile.kmk
+++ b/src/VBox/Runtime/Makefile.kmk
@@ -38,12 +38,6 @@ ifdef VBOX_ONLY_ADDITIONS
   #LIBRARIES.os2 += RuntimeGuestR0OS2Warp3
   LIBRARIES.win.x86 += RuntimeGuestR0NT4
  endif
- ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-  LIBRARIES.linux.amd64 += \
-      RuntimeGuestR3-x86 \
-      RuntimeGuestR3Mini-x86 \
-      RuntimeGuestR3Shared-x86
- endif
 
 else ifdef VBOX_ONLY_TESTSUITE
  #
@@ -93,12 +87,6 @@ else # !VBOX_ONLY_ADDITIONS && !VBOX_ONLY_TESTSUITE && !VBOX_ONLY_DOCS
  ifdef VBOX_WITH_ADDITIONS
   LIBRARIES += RuntimeGuestR3 RuntimeGuestR3Shared RuntimeGuestR3Mini
   LIBRARIES.win.amd64 += RuntimeGuestR3-x86 RuntimeGuestR3Shared-x86
-  ifneq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
-   LIBRARIES.linux.amd64 += \
-      RuntimeGuestR3-x86 \
-      RuntimeGuestR3Mini-x86 \
-      RuntimeGuestR3Shared-x86
-  endif
   ifdef VBOX_WITH_ADDITION_DRIVERS
    LIBRARIES += RuntimeGuestR0
   endif
@@ -545,15 +533,21 @@ endif
 
 # AMD64 / x86 assembly code.
 RuntimeR3_SOURCES.x86 += \
+	common/asm/ASMCpuIdExSlow.asm \
 	common/asm/ASMAtomicUoAndU64.asm \
 	common/asm/ASMAtomicUoAndU32.asm \
 	common/asm/ASMAtomicUoOrU64.asm \
-	common/asm/ASMAtomicUoOrU32.asm
+	common/asm/ASMAtomicUoOrU32.asm \
+	common/asm/ASMRdMsrEx.asm \
+	common/asm/ASMWrMsrEx.asm
 RuntimeR3_SOURCES.amd64 += \
+	common/asm/ASMCpuIdExSlow.asm \
 	common/asm/ASMAtomicUoAndU64.asm \
 	common/asm/ASMAtomicUoAndU32.asm \
 	common/asm/ASMAtomicUoOrU64.asm \
-	common/asm/ASMAtomicUoOrU32.asm
+	common/asm/ASMAtomicUoOrU32.asm \
+	common/asm/ASMRdMsrEx.asm \
+	common/asm/ASMWrMsrEx.asm
 
 # Some versions of GCC might require this.
 RuntimeR3_SOURCES.x86 += \
@@ -608,7 +602,7 @@ RuntimeR3_SOURCES.win = \
 	nt/RTErrConvertFromNtStatus.cpp \
  	r3/nt/fs-nt.cpp \
  	r3/nt/pathint-nt.cpp \
-	r3/posix/env-posix.cpp \
+	r3/win/env-win.cpp \
 	r3/win/RTHandleGetStandard-win.cpp \
 	r3/win/RTSystemQueryOSInfo-win.cpp \
 	r3/win/RTSystemShutdown-win.cpp \
@@ -1287,13 +1281,6 @@ RuntimeGuestR3Mini_SOURCES.win = \
 	win/errmsgwin.cpp \
 	win/RTErrConvertFromWin32.cpp
 
-#
-# RuntimeGuestR3Mini-x86 - Same as RuntimeGuestR3Mini, except that it's targeting x86.
-#
-RuntimeGuestR3Mini-x86_EXTENDS        := RuntimeGuestR3Mini
-RuntimeGuestR3Mini-x86_BLD_TRG_ARCH   := x86
-
-
 # VBox specific stuff.
 RuntimeGuestR3Mini_SOURCES += \
 	VBox/logbackdoor.cpp \
@@ -1676,15 +1663,21 @@ RuntimeR0_SOURCES += \
 endif
 
 RuntimeR0_SOURCES.x86 += \
+	common/asm/ASMCpuIdExSlow.asm \
 	common/asm/ASMAtomicUoAndU64.asm \
 	common/asm/ASMAtomicUoAndU32.asm \
 	common/asm/ASMAtomicUoOrU64.asm \
-	common/asm/ASMAtomicUoOrU32.asm
+	common/asm/ASMAtomicUoOrU32.asm \
+	common/asm/ASMRdMsrEx.asm \
+	common/asm/ASMWrMsrEx.asm
 RuntimeR0_SOURCES.amd64 += \
+	common/asm/ASMCpuIdExSlow.asm \
 	common/asm/ASMAtomicUoAndU64.asm \
 	common/asm/ASMAtomicUoAndU32.asm \
 	common/asm/ASMAtomicUoOrU64.asm \
-	common/asm/ASMAtomicUoOrU32.asm
+	common/asm/ASMAtomicUoOrU32.asm \
+	common/asm/ASMRdMsrEx.asm \
+	common/asm/ASMWrMsrEx.asm
 
 #if1of ($(KBUILD_TARGET_ARCH),amd64 x86)
 # RuntimeR0_SOURCES += common/time/timesupA.asm
@@ -1822,6 +1815,14 @@ RuntimeR0Drv_SOURCES    = \
 	r0drv/generic/semspinmutex-r0drv-generic.c \
 	VBox/log-vbox.cpp \
 
+RuntimeR0Drv_SOURCES.amd64 = \
+	common/asm/ASMRdMsrEx.asm \
+	common/asm/ASMWrMsrEx.asm
+RuntimeR0Drv_SOURCES.x86   = \
+	common/asm/ASMRdMsrEx.asm \
+	common/asm/ASMWrMsrEx.asm
+
+
 RuntimeR0Drv_SOURCES.linux = \
 	common/misc/thread.cpp \
 	common/string/strpbrk.cpp \
diff --git a/src/VBox/Runtime/common/asm/ASMCpuIdExSlow.asm b/src/VBox/Runtime/common/asm/ASMCpuIdExSlow.asm
new file mode 100644
index 0000000..53ef492
--- /dev/null
+++ b/src/VBox/Runtime/common/asm/ASMCpuIdExSlow.asm
@@ -0,0 +1,136 @@
+; $Id: ASMCpuIdExSlow.asm $
+;; @file
+; IPRT - ASMCpuIdExSlow().
+;
+
+;
+; Copyright (C) 2012-2013 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+;*******************************************************************************
+;* Header Files                                                                *
+;*******************************************************************************
+%include "iprt/asmdefs.mac"
+
+BEGINCODE
+
+;;
+; CPUID with EAX and ECX inputs, returning ALL output registers.
+;
+; @param    uOperator   x86:ebp+8   gcc:rdi      msc:rcx
+; @param    uInitEBX    x86:ebp+c   gcc:rsi      msc:rdx
+; @param    uInitECX    x86:ebp+10  gcc:rcx      msc:r8
+; @param    uInitEDX    x86:ebp+14  gcc:rdx      msc:r9
+; @param    pvEAX       x86:ebp+18  gcc:r8       msc:rbp+30h
+; @param    pvEBX       x86:ebp+1c  gcc:r9       msc:rbp+38h
+; @param    pvECX       x86:ebp+20  gcc:rbp+10h  msc:rbp+40h
+; @param    pvEDX       x86:ebp+24  gcc:rbp+18h  msc:rbp+48h
+;
+; @returns  EAX
+;
+BEGINPROC_EXPORTED ASMCpuIdExSlow
+        push    xBP
+        mov     xBP, xSP
+        push    xBX
+%ifdef RT_ARCH_X86
+        push    edi
+%endif
+
+%ifdef ASM_CALL64_MSC
+        mov     eax, ecx
+        mov     ebx, edx
+        mov     ecx, r8d
+        mov     edx, r9d
+        mov     r8,  [rbp + 30h]
+        mov     r9,  [rbp + 38h]
+        mov     r10, [rbp + 40h]
+        mov     r11, [rbp + 48h]
+%elifdef ASM_CALL64_GCC
+        mov     eax, edi
+        mov     ebx, esi
+        mov     r10, [rbp + 10h]
+        mov     r11, [rbp + 18h]
+%elifdef RT_ARCH_X86
+        mov     eax, [ebp + 08h]
+        mov     ebx, [ebp + 0ch]
+        mov     ecx, [ebp + 10h]
+        mov     edx, [ebp + 14h]
+        mov     edi, [ebp + 18h]
+%else
+ %error unsupported arch
+%endif
+
+        cpuid
+
+%ifdef RT_ARCH_AMD64
+        test    r8, r8
+        jz      .store_ebx
+        mov     [r8], eax
+%else
+        test    edi, edi
+        jz      .store_ebx
+        mov     [edi], eax
+%endif
+.store_ebx:
+
+%ifdef RT_ARCH_AMD64
+        test    r9, r9
+        jz      .store_ecx
+        mov     [r9], ebx
+%else
+        mov     edi, [ebp + 1ch]
+        test    edi, edi
+        jz      .store_ecx
+        mov     [edi], ebx
+%endif
+.store_ecx:
+
+%ifdef RT_ARCH_AMD64
+        test    r10, r10
+        jz      .store_edx
+        mov     [r10], ecx
+%else
+        mov     edi, [ebp + 20h]
+        test    edi, edi
+        jz      .store_edx
+        mov     [edi], ecx
+%endif
+.store_edx:
+
+%ifdef RT_ARCH_AMD64
+        test    r11, r11
+        jz      .done
+        mov     [r11], edx
+%else
+        mov     edi, [ebp + 24h]
+        test    edi, edi
+        jz      .done
+        mov     [edi], edx
+%endif
+.done:
+
+%ifdef RT_ARCH_X86
+        pop     edi
+%endif
+        pop     xBX
+        leave
+        ret
+ENDPROC ASMCpuIdExSlow
+
diff --git a/src/VBox/Runtime/common/asm/ASMRdMsrEx.asm b/src/VBox/Runtime/common/asm/ASMRdMsrEx.asm
new file mode 100644
index 0000000..6913562
--- /dev/null
+++ b/src/VBox/Runtime/common/asm/ASMRdMsrEx.asm
@@ -0,0 +1,84 @@
+; $Id: ASMRdMsrEx.asm $
+;; @file
+; IPRT - ASMRdMsrEx().
+;
+
+;
+; Copyright (C) 2013 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+;*******************************************************************************
+;* Header Files                                                                *
+;*******************************************************************************
+%include "iprt/asmdefs.mac"
+
+BEGINCODE
+
+;;
+; Special version of ASMRdMsr that allow specifying the rdi value.
+;
+; @param    uMsr    msc=rcx, gcc=rdi, x86=[ebp+8]   The MSR to read.
+; @param    uEdi    msc=rdx, gcc=rsi, x86=[ebp+12]  The EDI/RDI value.
+; @returns  MSR value in rax on amd64 and edx:eax on x86.
+;
+BEGINPROC_EXPORTED ASMRdMsrEx
+%ifdef ASM_CALL64_MSC
+proc_frame ASMRdMsrEx_DupWarningHack
+        push    rdi
+        [pushreg rdi]
+[endprolog]
+        and     ecx, ecx                ; serious paranoia
+        mov     rdi, rdx
+        xor     eax, eax
+        xor     edx, edx
+        rdmsr
+        pop     rdi
+        and     eax, eax                ; paranoia
+        shl     rdx, 32
+        or      rax, rdx
+        ret
+endproc_frame
+%elifdef ASM_CALL64_GCC
+        mov     ecx, edi
+        mov     rdi, rsi
+        xor     eax, eax
+        xor     edx, edx
+        rdmsr
+        and     eax, eax                ; paranoia
+        shl     rdx, 32
+        or      rax, rdx
+        ret
+%elifdef RT_ARCH_X86
+        push    ebp
+        mov     ebp, esp
+        push    edi
+        xor     eax, eax
+        xor     edx, edx
+        mov     ecx, [ebp + 8]
+        mov     edi, [esp + 12]
+        rdmsr
+        pop     edi
+        leave
+        ret
+%else
+ %error "Undefined arch?"
+%endif
+ENDPROC ASMRdMsrEx
+
diff --git a/src/VBox/Runtime/common/asm/ASMWrMsrEx.asm b/src/VBox/Runtime/common/asm/ASMWrMsrEx.asm
new file mode 100644
index 0000000..4feeaa9
--- /dev/null
+++ b/src/VBox/Runtime/common/asm/ASMWrMsrEx.asm
@@ -0,0 +1,79 @@
+; $Id: ASMWrMsrEx.asm $
+;; @file
+; IPRT - ASMWrMsrEx().
+;
+
+;
+; Copyright (C) 2013 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+;*******************************************************************************
+;* Header Files                                                                *
+;*******************************************************************************
+%include "iprt/asmdefs.mac"
+
+BEGINCODE
+
+;;
+; Special version of ASMRdMsr that allow specifying the rdi value.
+;
+; @param    uMsr    msc=rcx, gcc=rdi, x86=[ebp+8]   The MSR to read.
+; @param    uXDI    msc=rdx, gcc=rsi, x86=[ebp+12]  The EDI/RDI value.
+; @param    uValue  msc=r8,  gcc=rdx, x86=[ebp+16]  The 64-bit value to write.
+;
+BEGINPROC_EXPORTED ASMWrMsrEx
+%ifdef ASM_CALL64_MSC
+proc_frame ASMWrMsrEx_DupWarningHack
+        push    rdi
+        [pushreg rdi]
+[endprolog]
+        and     ecx, ecx                ; serious paranoia
+        mov     rdi, rdx
+        mov     eax, r8d
+        mov     rdx, r8
+        shr     rdx, 32
+        wrmsr
+        pop     rdi
+        ret
+endproc_frame
+%elifdef ASM_CALL64_GCC
+        mov     ecx, edi
+        mov     rdi, rsi
+        mov     eax, edx
+        shr     edx, 32
+        wrmsr
+        ret
+%elifdef RT_ARCH_X86
+        push    ebp
+        mov     ebp, esp
+        push    edi
+        mov     ecx, [ebp + 8]
+        mov     edi, [esp + 12]
+        mov     eax, [esp + 16]
+        mov     edx, [esp + 20]
+        wrmsr
+        pop     edi
+        leave
+        ret
+%else
+ %error "Undefined arch?"
+%endif
+ENDPROC ASMWrMsrEx
+
diff --git a/src/VBox/Runtime/common/checksum/manifest.cpp b/src/VBox/Runtime/common/checksum/manifest.cpp
index 52eb746..77d4d03 100644
--- a/src/VBox/Runtime/common/checksum/manifest.cpp
+++ b/src/VBox/Runtime/common/checksum/manifest.cpp
@@ -517,7 +517,6 @@ RTR3DECL(int) RTManifestVerifyFilesBuf(void *pvBuf, size_t cbSize, PRTMANIFESTTE
     }
     RTMemTmpFree(paFiles);
 
-    RTPrintf("rc = %Rrc\n", rc);
     return rc;
 }
 
diff --git a/src/VBox/Runtime/common/zip/tar.cpp b/src/VBox/Runtime/common/zip/tar.cpp
index 7d6589c..e2ced7e 100644
--- a/src/VBox/Runtime/common/zip/tar.cpp
+++ b/src/VBox/Runtime/common/zip/tar.cpp
@@ -40,6 +40,7 @@
 #include <iprt/string.h>
 
 #include "internal/magics.h"
+#include "tar.h"
 
 
 /******************************************************************************
@@ -268,29 +269,59 @@ DECLINLINE(uint64_t) rtTarRecToSize(PRTTARRECORD pRecord)
     return (uint64_t)cbSize;
 }
 
-DECLINLINE(int) rtTarCalcChkSum(PRTTARRECORD pRecord, uint32_t *pChkSum)
+/**
+ * Calculates the TAR header checksums and detects if it's all zeros.
+ *
+ * @returns true if all zeros, false if not.
+ * @param   pHdr                The header to checksum.
+ * @param   pi32Unsigned        Where to store the checksum calculated using
+ *                              unsigned chars.   This is the one POSIX
+ *                              specifies.
+ * @param   pi32Signed          Where to store the checksum calculated using
+ *                              signed chars.
+ *
+ * @remarks The reason why we calculate the checksum as both signed and unsigned
+ *          has to do with various the char C type being signed on some hosts
+ *          and unsigned on others.
+ *
+ * @remarks Borrowed from tarvfs.cpp.
+ */
+static bool rtZipTarCalcChkSum(PCRTZIPTARHDR pHdr, int32_t *pi32Unsigned, int32_t *pi32Signed)
 {
-    uint32_t check = 0;
-    uint32_t zero = 0;
-    for (size_t i = 0; i < sizeof(RTTARRECORD); ++i)
+    int32_t i32Unsigned = 0;
+    int32_t i32Signed   = 0;
+
+    /*
+     * Sum up the entire header.
+     */
+    const char *pch    = (const char *)pHdr;
+    const char *pchEnd = pch + sizeof(*pHdr);
+    do
     {
-        /* Calculate the sum of every byte from the header. The checksum field
-         * itself is counted as all blanks. */
-        if (   i <  RT_UOFFSETOF(RTTARRECORD, h.chksum)
-            || i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag))
-            check += pRecord->d[i];
-        else
-            check += ' ';
-        /* Additional check if all fields are zero, which indicate EOF. */
-        zero += pRecord->d[i];
-    }
+        i32Unsigned += *(unsigned char *)pch;
+        i32Signed   += *(signed   char *)pch;
+    } while (++pch != pchEnd);
 
-    /* EOF? */
-    if (!zero)
-        return VERR_TAR_END_OF_FILE;
+    /*
+     * Check if it's all zeros and replace the chksum field with spaces.
+     */
+    bool const fZeroHdr = i32Unsigned == 0;
 
-    *pChkSum = check;
-    return VINF_SUCCESS;
+    pch    = pHdr->Common.chksum;
+    pchEnd = pch + sizeof(pHdr->Common.chksum);
+    do
+    {
+        i32Unsigned -= *(unsigned char *)pch;
+        i32Signed   -= *(signed   char *)pch;
+    } while (++pch != pchEnd);
+
+    i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum);
+    i32Signed   += (signed   char)' ' * sizeof(pHdr->Common.chksum);
+
+    *pi32Unsigned = i32Unsigned;
+    if (pi32Signed)
+        *pi32Signed = i32Signed;
+    return fZeroHdr;
 }
 
 DECLINLINE(int) rtTarReadHeaderRecord(RTFILE hFile, PRTTARRECORD pRecord)
@@ -305,16 +336,16 @@ DECLINLINE(int) rtTarReadHeaderRecord(RTFILE hFile, PRTTARRECORD pRecord)
         return rc;
 
     /* Check for data integrity & an EOF record */
-    uint32_t check = 0;
-    rc = rtTarCalcChkSum(pRecord, &check);
-    /* EOF? */
-    if (RT_FAILURE(rc))
-        return rc;
+    int32_t iUnsignedChksum, iSignedChksum;
+    if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum))
+        return VERR_TAR_END_OF_FILE;
 
     /* Verify the checksum */
     uint32_t sum;
     rc = RTStrToUInt32Full(pRecord->h.chksum, 8, &sum);
-    if (RT_SUCCESS(rc) && sum == check)
+    if (   RT_SUCCESS(rc)
+        && (   sum == (uint32_t)iSignedChksum
+            || sum == (uint32_t)iUnsignedChksum) )
     {
         /* Make sure the strings are zero terminated. */
         pRecord->h.name[sizeof(pRecord->h.name) - 1]         = 0;
@@ -350,12 +381,12 @@ DECLINLINE(int) rtTarCreateHeaderRecord(PRTTARRECORD pRecord, const char *pszSrc
     pRecord->h.linkflag = LF_NORMAL;
 
     /* Create the checksum out of the new header */
-    uint32_t uChkSum = 0;
-    int rc = rtTarCalcChkSum(pRecord, &uChkSum);
-    if (RT_FAILURE(rc))
-        return rc;
+    int32_t iUnsignedChksum, iSignedChksum;
+    if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum))
+        return VERR_TAR_END_OF_FILE;
+
     /* Format the checksum */
-    RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", uChkSum);
+    RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", iUnsignedChksum);
 
     return VINF_SUCCESS;
 }
diff --git a/src/VBox/Runtime/generic/env-generic.cpp b/src/VBox/Runtime/generic/env-generic.cpp
index 04431b8..9afb4d8 100644
--- a/src/VBox/Runtime/generic/env-generic.cpp
+++ b/src/VBox/Runtime/generic/env-generic.cpp
@@ -56,11 +56,27 @@ RT_C_DECLS_END
 /*******************************************************************************
 *   Defined Constants And Macros                                               *
 *******************************************************************************/
+/** The allocation granularity of the RTENVINTERNAL::papszEnv memory. */
+#define RTENV_GROW_SIZE     16
+
 /** Macro that unlocks the specified environment block. */
 #define RTENV_LOCK(pEnvInt)     do { } while (0)
 /** Macro that unlocks the specified environment block. */
 #define RTENV_UNLOCK(pEnvInt)   do { } while (0)
 
+/** @def RTENV_HAVE_WENVIRON
+ * Indicates that we have a _wenviron variable with UTF-16 strings that we
+ * better use instead of the current-cp strings in environ. */
+#if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
+# define RTENV_HAVE_WENVIRON 1
+#endif
+
+/** @def RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API
+ * Indicates the RTEnv*Utf8 APIs are implemented. */
+#if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
+# define RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API 1
+#endif
+
 
 /*******************************************************************************
 *   Structures and Typedefs                                                    *
@@ -84,10 +100,10 @@ typedef struct RTENVINTERNAL
     /** Array of environment variables in the process CP.
      * This get (re-)constructed when RTEnvGetExecEnvP method is called. */
     char      **papszEnvOtherCP;
-} RTENVINTERNAL, *PRTENVINTERNAL;
 
-/** The allocation granularity of the RTENVINTERNAL::papszEnv memory. */
-#define RTENV_GROW_SIZE     16
+    /** The compare function we're using. */
+    DECLCALLBACKMEMBER(int, pfnCompare)(const char *psz1, const char *psz2, size_t cchMax);
+} RTENVINTERNAL, *PRTENVINTERNAL;
 
 
 /**
@@ -111,10 +127,12 @@ static const char * const *rtEnvDefault(void)
  * Internal worker that creates an environment handle with a specified capacity.
  *
  * @returns IPRT status code.
- * @param   ppIntEnv    Where to store the result.
- * @param   cAllocated  The initial array size.
+ * @param   ppIntEnv        Where to store the result.
+ * @param   cAllocated      The initial array size.
+ * @param   fCaseSensitive  Whether the environment block is case sensitive or
+ *                          not.
  */
-static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated)
+static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated, bool fCaseSensitive)
 {
     /*
      * Allocate environment handle.
@@ -126,6 +144,7 @@ static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated)
          * Pre-allocate the variable array.
          */
         pIntEnv->u32Magic = RTENV_MAGIC;
+        pIntEnv->pfnCompare = fCaseSensitive ? RTStrNCmp : RTStrNICmp;
         pIntEnv->papszEnvOtherCP = NULL;
         pIntEnv->cVars = 0;
         pIntEnv->cAllocated = RT_ALIGN_Z(RT_MAX(cAllocated, RTENV_GROW_SIZE), RTENV_GROW_SIZE);
@@ -146,7 +165,7 @@ static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated)
 RTDECL(int) RTEnvCreate(PRTENV pEnv)
 {
     AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
-    return rtEnvCreate(pEnv, RTENV_GROW_SIZE);
+    return rtEnvCreate(pEnv, RTENV_GROW_SIZE, false /*fCaseSensitive*/);
 }
 RT_EXPORT_SYMBOL(RTEnvCreate);
 
@@ -200,18 +219,36 @@ RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone)
     /*
      * Validate input and figure out how many variable to clone and where to get them.
      */
+    bool fCaseSensitive = true;
     size_t cVars;
     const char * const *papszEnv;
+#ifdef RTENV_HAVE_WENVIRON
+    PCRTUTF16 const * papwszEnv;
+#endif
     PRTENVINTERNAL pIntEnvToClone;
     AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
     if (EnvToClone == RTENV_DEFAULT)
     {
+        cVars = 0;
         pIntEnvToClone = NULL;
+#ifdef RTENV_HAVE_WENVIRON
+        papszEnv  = NULL;
+        papwszEnv = (PCRTUTF16 * const )_wenviron;
+        if (papwszEnv)
+            while (papwszEnv[cVars])
+                cVars++;
+#else
         papszEnv = rtEnvDefault();
-        cVars = 0;
         if (papszEnv)
             while (papszEnv[cVars])
                 cVars++;
+#endif
+
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+        /* DOS systems was case insensitive.  A prime example is the 'Path'
+           variable on windows which turns into the 'PATH' variable. */
+        fCaseSensitive = false;
+#endif
     }
     else
     {
@@ -228,7 +265,7 @@ RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone)
      * Create the duplicate.
      */
     PRTENVINTERNAL pIntEnv;
-    int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */);
+    int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive);
     if (RT_SUCCESS(rc))
     {
         pIntEnv->cVars = cVars;
@@ -239,7 +276,11 @@ RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone)
             size_t  iDst = 0;
             for (size_t iSrc = 0; iSrc < cVars; iSrc++)
             {
+#ifdef RTENV_HAVE_WENVIRON
+                int rc2 = RTUtf16ToUtf8(papwszEnv[iSrc], &pIntEnv->papszEnv[iDst]);
+#else
                 int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]);
+#endif
                 if (RT_SUCCESS(rc2))
                     iDst++;
                 else if (rc2 == VERR_NO_TRANSLATION)
@@ -318,6 +359,9 @@ RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
     int rc;
     if (Env == RTENV_DEFAULT)
     {
+#ifdef RT_OS_WINDOWS
+        rc = RTEnvSetUtf8(pszVar, pszValue);
+#else
         /*
          * Since RTEnvPut isn't UTF-8 clean and actually expects the strings
          * to be in the current code page (codeset), we'll do the necessary
@@ -336,6 +380,7 @@ RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
             }
             RTStrFree(pszVarOtherCP);
         }
+#endif
     }
     else
     {
@@ -363,7 +408,7 @@ RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
             rc = VINF_SUCCESS;
             size_t iVar;
             for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
-                if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
+                if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
                     &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
                     break;
             if (iVar < pIntEnv->cVars)
@@ -423,6 +468,9 @@ RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar)
     int rc;
     if (Env == RTENV_DEFAULT)
     {
+#ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API
+        rc = RTEnvUnsetUtf8(pszVar);
+#else
         /*
          * Since RTEnvUnset isn't UTF-8 clean and actually expects the strings
          * to be in the current code page (codeset), we'll do the necessary
@@ -435,6 +483,7 @@ RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar)
             rc = RTEnvUnset(pszVarOtherCP);
             RTStrFree(pszVarOtherCP);
         }
+#endif
     }
     else
     {
@@ -451,7 +500,7 @@ RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar)
         const size_t cchVar = strlen(pszVar);
         size_t iVar;
         for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
-            if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
+            if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
                 &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
             {
                 RTMemFree(pIntEnv->papszEnv[iVar]);
@@ -483,6 +532,9 @@ RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbV
     int rc;
     if (Env == RTENV_DEFAULT)
     {
+#ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API
+        rc = RTEnvGetUtf8(pszVar, pszValue, cbValue, pcchActual);
+#else
         /*
          * Since RTEnvGet isn't UTF-8 clean and actually expects the strings
          * to be in the current code page (codeset), we'll do the necessary
@@ -517,6 +569,7 @@ RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbV
             else
                 rc = VERR_ENV_VAR_NOT_FOUND;
         }
+#endif
     }
     else
     {
@@ -533,7 +586,7 @@ RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbV
         const size_t cchVar = strlen(pszVar);
         size_t iVar;
         for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
-            if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
+            if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
                 &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
             {
                 rc = VINF_SUCCESS;
@@ -554,7 +607,6 @@ RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbV
         RTENV_UNLOCK(pIntEnv);
     }
     return rc;
-
 }
 RT_EXPORT_SYMBOL(RTEnvGetEx);
 
@@ -563,9 +615,12 @@ RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar)
 {
     AssertPtrReturn(pszVar, false);
 
-    bool fExist = false;
+    bool fExists = false;
     if (Env == RTENV_DEFAULT)
     {
+#ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API
+        fExists = RTEnvExistsUtf8(pszVar);
+#else
         /*
          * Since RTEnvExist isn't UTF-8 clean and actually expects the strings
          * to be in the current code page (codeset), we'll do the necessary
@@ -575,9 +630,10 @@ RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar)
         int rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
         if (RT_SUCCESS(rc))
         {
-            fExist = RTEnvExist(pszVarOtherCP);
+            fExists = RTEnvExist(pszVarOtherCP);
             RTStrFree(pszVarOtherCP);
         }
+#endif
     }
     else
     {
@@ -592,16 +648,16 @@ RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar)
          */
         const size_t cchVar = strlen(pszVar);
         for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
-            if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
+            if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
                 &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
             {
-                fExist = true;
+                fExists = true;
                 break;
             }
 
         RTENV_UNLOCK(pIntEnv);
     }
-    return fExist;
+    return fExists;
 }
 RT_EXPORT_SYMBOL(RTEnvExistEx);
 
@@ -611,6 +667,7 @@ RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env)
     const char * const *papszRet;
     if (Env == RTENV_DEFAULT)
     {
+        /** @todo fix this API it's fundamentally wrong! */
         papszRet = rtEnvDefault();
         if (!papszRet)
         {
diff --git a/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
index 7a731dd..21e124b 100644
--- a/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
@@ -173,7 +173,7 @@ static PRTMEMHDR rtR0MemAllocExecVmArea(size_t cb)
 
     for (iPage = 0; iPage < cPages; iPage++)
     {
-        papPages[iPage] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+        papPages[iPage] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN);
         if (!papPages[iPage])
             break;
     }
@@ -383,15 +383,15 @@ RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
     cOrder = CalcPowerOf2Order(cPages);
 #if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32)
     /* ZONE_DMA32: 0-4GB */
-    paPages = alloc_pages(GFP_DMA32, cOrder);
+    paPages = alloc_pages(GFP_DMA32 | __GFP_NOWARN, cOrder);
     if (!paPages)
 #endif
 #ifdef RT_ARCH_AMD64
         /* ZONE_DMA; 0-16MB */
-        paPages = alloc_pages(GFP_DMA, cOrder);
+        paPages = alloc_pages(GFP_DMA | __GFP_NOWARN, cOrder);
 #else
         /* ZONE_NORMAL: 0-896MB */
-        paPages = alloc_pages(GFP_USER, cOrder);
+        paPages = alloc_pages(GFP_USER | __GFP_NOWARN, cOrder);
 #endif
     if (paPages)
     {
diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
index 6bf3c20..2840dd4 100644
--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
@@ -1,4 +1,4 @@
-/* $Revision: 90895 $ */
+/* $Revision: 91595 $ */
 /** @file
  * IPRT - Ring-0 Memory Objects, Linux.
  */
@@ -320,9 +320,9 @@ static int rtR0MemObjLinuxAllocPages(PRTR0MEMOBJLNX *ppMemLnx, RTR0MEMOBJTYPE en
         ||  cb <= PAGE_SIZE * 2)
     {
 # ifdef VBOX_USE_INSERT_PAGE
-        paPages = alloc_pages(fFlagsLnx |  __GFP_COMP, rtR0MemObjLinuxOrder(cPages));
+        paPages = alloc_pages(fFlagsLnx | __GFP_COMP | __GFP_NOWARN, rtR0MemObjLinuxOrder(cPages));
 # else
-        paPages = alloc_pages(fFlagsLnx, rtR0MemObjLinuxOrder(cPages));
+        paPages = alloc_pages(fFlagsLnx | __GFP_NOWARN, rtR0MemObjLinuxOrder(cPages));
 # endif
         if (paPages)
         {
@@ -341,7 +341,7 @@ static int rtR0MemObjLinuxAllocPages(PRTR0MEMOBJLNX *ppMemLnx, RTR0MEMOBJTYPE en
     {
         for (iPage = 0; iPage < cPages; iPage++)
         {
-            pMemLnx->apPages[iPage] = alloc_page(fFlagsLnx);
+            pMemLnx->apPages[iPage] = alloc_page(fFlagsLnx | __GFP_NOWARN);
             if (RT_UNLIKELY(!pMemLnx->apPages[iPage]))
             {
                 while (iPage-- > 0)
@@ -1170,7 +1170,7 @@ DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *
      * Allocate a dummy page and create a page pointer array for vmap such that
      * the dummy page is mapped all over the reserved area.
      */
-    pDummyPage = alloc_page(GFP_HIGHUSER);
+    pDummyPage = alloc_page(GFP_HIGHUSER | __GFP_NOWARN);
     if (!pDummyPage)
         return VERR_NO_MEMORY;
     papPages = RTMemAlloc(sizeof(*papPages) * cPages);
@@ -1407,7 +1407,7 @@ DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ p
     /*
      * Allocate a dummy page for use when mapping the memory.
      */
-    pDummyPage = alloc_page(GFP_USER);
+    pDummyPage = alloc_page(GFP_USER | __GFP_NOWARN);
     if (!pDummyPage)
         return VERR_NO_MEMORY;
     SetPageReserved(pDummyPage);
diff --git a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
index 5773cbb..a1791ee 100644
--- a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
+++ b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
@@ -150,6 +150,10 @@
 # define DEFINE_WAIT(name) DECLARE_WAITQUEUE(name, current)
 #endif
 
+#ifndef __GFP_NOWARN
+# define __GFP_NOWARN 0
+#endif
+
 /*
  * 2.4 / early 2.6 compatibility wrappers
  */
diff --git a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
index 9cfb601..922bd41 100644
--- a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
+++ b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
@@ -32,6 +32,9 @@
 # include <mach-o/dyld.h>
 #endif
 
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
 #include <iprt/string.h>
 #include <iprt/assert.h>
 #include <iprt/err.h>
@@ -48,7 +51,13 @@ DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
     const char *pszImageName = _dyld_get_image_name(0);
     AssertReturn(pszImageName, VERR_INTERNAL_ERROR);
 
-    int rc = rtPathFromNativeCopy(pszPath, cchPath, pszImageName, NULL);
+    char szTmpPath[PATH_MAX + 1];
+    const char *psz = realpath(pszImageName, szTmpPath);
+    int rc;
+    if (psz)
+        rc = rtPathFromNativeCopy(pszPath, cchPath, szTmpPath, NULL);
+    else
+        rc = RTErrConvertFromErrno(errno);
     AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, strlen(pszImageName), pszPath), rc);
 
     return VINF_SUCCESS;
diff --git a/src/VBox/Runtime/r3/linux/mp-linux.cpp b/src/VBox/Runtime/r3/linux/mp-linux.cpp
index 64087ac..210f75a 100644
--- a/src/VBox/Runtime/r3/linux/mp-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/mp-linux.cpp
@@ -184,18 +184,25 @@ RTDECL(RTCPUID) RTMpGetCoreCount(void)
 {
     RTCPUID     cMax      = rtMpLinuxMaxCpus();
     uint32_t   *paidCores = (uint32_t *)alloca(sizeof(paidCores[0]) * (cMax + 1));
+    uint32_t   *paidPckgs = (uint32_t *)alloca(sizeof(paidPckgs[0]) * (cMax + 1));
     uint32_t    cCores    = 0;
     for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
     {
         if (RTMpIsCpuPossible(idCpu))
         {
             uint32_t idCore = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/core_id", (int)idCpu);
+            uint32_t idPckg = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/physical_package_id", (int)idCpu);
             uint32_t i;
             for (i = 0; i < cCores; i++)
-                if (paidCores[i] == idCore)
+                if (   paidCores[i] == idCore
+                    && paidPckgs[i] == idPckg)
                     break;
             if (i >= cCores)
-                paidCores[cCores++] = idCore;
+            {
+                paidCores[cCores] = idCore;
+                paidPckgs[cCores] = idPckg;
+                cCores++;
+            }
         }
     }
     Assert(cCores > 0);
@@ -226,18 +233,25 @@ RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
 {
     RTCPUID     cMax      = rtMpLinuxMaxCpus();
     uint32_t   *paidCores = (uint32_t *)alloca(sizeof(paidCores[0]) * (cMax + 1));
+    uint32_t   *paidPckgs = (uint32_t *)alloca(sizeof(paidPckgs[0]) * (cMax + 1));
     uint32_t    cCores    = 0;
     for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
     {
         if (RTMpIsCpuOnline(idCpu))
         {
             uint32_t idCore = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/core_id", (int)idCpu);
+            uint32_t idPckg = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/physical_package_id", (int)idCpu);
             uint32_t i;
             for (i = 0; i < cCores; i++)
-                if (paidCores[i] == idCore)
+                if (   paidCores[i] == idCore
+                    && paidPckgs[i] == idPckg)
                     break;
             if (i >= cCores)
-                paidCores[cCores++] = idCore;
+            {
+                paidCores[cCores] = idCore;
+                paidPckgs[cCores] = idPckg;
+                cCores++;
+            }
         }
     }
     Assert(cCores > 0);
diff --git a/src/VBox/Runtime/r3/posix/env-posix.cpp b/src/VBox/Runtime/r3/posix/env-posix.cpp
index 9b099f7..cd4fdb1 100644
--- a/src/VBox/Runtime/r3/posix/env-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/env-posix.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -46,13 +46,19 @@
 #include "internal/alignmentchecks.h"
 
 
+RTDECL(bool) RTEnvExistsBad(const char *pszVar)
+{
+    return RTEnvGetBad(pszVar) != NULL;
+}
+
+
 RTDECL(bool) RTEnvExist(const char *pszVar)
 {
-    return RTEnvGet(pszVar) != NULL;
+    return RTEnvExistsBad(pszVar);
 }
 
 
-RTDECL(const char *) RTEnvGet(const char *pszVar)
+RTDECL(const char *) RTEnvGetBad(const char *pszVar)
 {
     IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */
     const char *pszValue = getenv(pszVar);
@@ -61,7 +67,13 @@ RTDECL(const char *) RTEnvGet(const char *pszVar)
 }
 
 
-RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
+RTDECL(const char *) RTEnvGet(const char *pszVar)
+{
+    return RTEnvGetBad(pszVar);
+}
+
+
+RTDECL(int) RTEnvPutBad(const char *pszVarEqualValue)
 {
     /** @todo putenv is a source memory leaks. deal with this on a per system basis. */
     if (!putenv((char *)pszVarEqualValue))
@@ -69,7 +81,14 @@ RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
     return RTErrConvertFromErrno(errno);
 }
 
-RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
+
+RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
+{
+    return RTEnvPutBad(pszVarEqualValue);
+}
+
+
+RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue)
 {
 #if defined(_MSC_VER)
     /* make a local copy and feed it to putenv. */
@@ -98,7 +117,12 @@ RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
 }
 
 
-RTDECL(int) RTEnvUnset(const char *pszVar)
+RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
+{
+    return RTEnvSetBad(pszVar, pszValue);
+}
+
+RTDECL(int) RTEnvUnsetBad(const char *pszVar)
 {
     AssertReturn(!strchr(pszVar, '='), VERR_INVALID_PARAMETER);
 
@@ -131,3 +155,8 @@ RTDECL(int) RTEnvUnset(const char *pszVar)
     return RTErrConvertFromErrno(errno);
 }
 
+RTDECL(int) RTEnvUnset(const char *pszVar)
+{
+    return RTEnvUnsetBad(pszVar);
+}
+
diff --git a/src/VBox/Runtime/r3/win/env-win.cpp b/src/VBox/Runtime/r3/win/env-win.cpp
new file mode 100644
index 0000000..030c6cd
--- /dev/null
+++ b/src/VBox/Runtime/r3/win/env-win.cpp
@@ -0,0 +1,268 @@
+/* $Id: env-win.cpp $ */
+/** @file
+ * IPRT - Environment, Posix.
+ */
+
+/*
+ * Copyright (C) 2006-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <iprt/env.h>
+
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+
+RTDECL(bool) RTEnvExistsBad(const char *pszVar)
+{
+    return RTEnvGetBad(pszVar) != NULL;
+}
+
+
+RTDECL(bool) RTEnvExist(const char *pszVar)
+{
+    return RTEnvExistsBad(pszVar);
+}
+
+
+RTDECL(bool) RTEnvExistsUtf8(const char *pszVar)
+{
+    PRTUTF16 pwszVar;
+    int rc = RTStrToUtf16(pszVar, &pwszVar);
+    AssertRCReturn(rc, false);
+    bool fRet = _wgetenv(pwszVar) != NULL;
+    RTUtf16Free(pwszVar);
+    return fRet;
+}
+
+
+RTDECL(const char *) RTEnvGetBad(const char *pszVar)
+{
+    return getenv(pszVar);
+}
+
+
+RTDECL(const char *) RTEnvGet(const char *pszVar)
+{
+    return RTEnvGetBad(pszVar);
+}
+
+RTDECL(int) RTEnvGetUtf8(const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
+{
+    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
+    AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
+    AssertReturn(pszValue || !cbValue, VERR_INVALID_PARAMETER);
+    AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
+    AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
+
+    if (pcchActual)
+        *pcchActual = 0;
+
+    PRTUTF16 pwszVar;
+    int rc = RTStrToUtf16(pszVar, &pwszVar);
+    AssertRCReturn(rc, false);
+
+    /** @todo Consider _wgetenv_s or GetEnvironmentVariableW here to avoid the
+     *        potential race with a concurrent _wputenv/_putenv. */
+    PCRTUTF16 pwszValue = _wgetenv(pwszVar);
+    RTUtf16Free(pwszVar);
+    if (pwszValue)
+    {
+        if (cbValue)
+            rc = RTUtf16ToUtf8Ex(pwszValue, RTSTR_MAX, &pszValue, cbValue, pcchActual);
+        else
+            rc = RTUtf16CalcUtf8LenEx(pwszValue, RTSTR_MAX, pcchActual);
+    }
+    else
+        rc = VERR_ENV_VAR_NOT_FOUND;
+    return rc;
+}
+
+
+RTDECL(int) RTEnvPutBad(const char *pszVarEqualValue)
+{
+    /** @todo putenv is a source memory leaks. deal with this on a per system basis. */
+    if (!putenv((char *)pszVarEqualValue))
+        return 0;
+    return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
+{
+    return RTEnvPutBad(pszVarEqualValue);
+}
+
+
+RTDECL(int) RTEnvPutUtf8(const char *pszVarEqualValue)
+{
+    PRTUTF16 pwszVarEqualValue;
+    int rc = RTStrToUtf16(pszVarEqualValue, &pwszVarEqualValue);
+    if (RT_SUCCESS(rc))
+    {
+        if (!_wputenv(pwszVarEqualValue))
+            rc = VINF_SUCCESS;
+        else
+            rc = RTErrConvertFromErrno(errno);
+        RTUtf16Free(pwszVarEqualValue);
+    }
+    return rc;
+}
+
+
+
+RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue)
+{
+    /* make a local copy and feed it to putenv. */
+    const size_t cchVar = strlen(pszVar);
+    const size_t cchValue = strlen(pszValue);
+    char *pszTmp = (char *)alloca(cchVar + cchValue + 2 + !*pszValue);
+    memcpy(pszTmp, pszVar, cchVar);
+    pszTmp[cchVar] = '=';
+    if (*pszValue)
+        memcpy(pszTmp + cchVar + 1, pszValue, cchValue + 1);
+    else
+    {
+        pszTmp[cchVar + 1] = ' '; /* wrong, but putenv will remove it otherwise. */
+        pszTmp[cchVar + 2] = '\0';
+    }
+
+    if (!putenv(pszTmp))
+        return 0;
+    return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
+{
+    return RTEnvSetBad(pszVar, pszValue);
+}
+
+RTDECL(int) RTEnvSetUtf8(const char *pszVar, const char *pszValue)
+{
+    size_t cwcVar;
+    int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar);
+    if (RT_SUCCESS(rc))
+    {
+        size_t cwcValue;
+        rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcValue);
+        if (RT_SUCCESS(rc))
+        {
+            PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + cwcValue + 1) * sizeof(RTUTF16));
+            if (pwszTmp)
+            {
+                rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL);
+                if (RT_SUCCESS(rc))
+                {
+                    PRTUTF16 pwszTmpValue = &pwszTmp[cwcVar];
+                    *pwszTmpValue++ = '=';
+                    rc = RTStrToUtf16Ex(pszValue, RTSTR_MAX, &pwszTmpValue, cwcValue + 1, NULL);
+                    if (RT_SUCCESS(rc))
+                    {
+                        if (!_wputenv(pwszTmp))
+                            rc = VINF_SUCCESS;
+                        else
+                            rc = RTErrConvertFromErrno(errno);
+                    }
+                }
+                RTMemTmpFree(pwszTmp);
+            }
+            else
+                rc = VERR_NO_TMP_MEMORY;
+        }
+    }
+    return rc;
+}
+
+
+RTDECL(int) RTEnvUnsetBad(const char *pszVar)
+{
+    AssertReturn(!strchr(pszVar, '='), VERR_INVALID_PARAMETER);
+
+    /*
+     * Check that it exists first.
+     */
+    if (!RTEnvExist(pszVar))
+        return VINF_ENV_VAR_NOT_FOUND;
+
+    /*
+     * Ok, try remove it.
+     */
+#ifdef RT_OS_WINDOWS
+    /* Use putenv(var=) since Windows does not have unsetenv(). */
+    size_t cchVar = strlen(pszVar);
+    char *pszBuf = (char *)alloca(cchVar + 2);
+    memcpy(pszBuf, pszVar, cchVar);
+    pszBuf[cchVar]     = '=';
+    pszBuf[cchVar + 1] = '\0';
+
+    if (!putenv(pszBuf))
+        return VINF_SUCCESS;
+
+#else
+    /* This is the preferred function as putenv() like used above does neither work on Solaris nor on Darwin. */
+    if (!unsetenv((char*)pszVar))
+        return VINF_SUCCESS;
+#endif
+
+    return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTEnvUnset(const char *pszVar)
+{
+    return RTEnvUnsetBad(pszVar);
+}
+
+
+RTDECL(int) RTEnvUnsetUtf8(const char *pszVar)
+{
+    size_t cwcVar;
+    int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar);
+    if (RT_SUCCESS(rc))
+    {
+        PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + 1) * sizeof(RTUTF16));
+        if (pwszTmp)
+        {
+            rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL);
+            if (RT_SUCCESS(rc))
+            {
+                pwszTmp[cwcVar] = '=';
+                pwszTmp[cwcVar + 1] = '\0';
+                if (!_wputenv(pwszTmp))
+                    rc = VINF_SUCCESS;
+                else
+                    rc = RTErrConvertFromErrno(errno);
+            }
+            RTMemTmpFree(pwszTmp);
+        }
+    }
+    return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/win/process-win.cpp b/src/VBox/Runtime/r3/win/process-win.cpp
index 246603e..41a8cbf 100644
--- a/src/VBox/Runtime/r3/win/process-win.cpp
+++ b/src/VBox/Runtime/r3/win/process-win.cpp
@@ -644,8 +644,10 @@ static int rtProcWinEnvironmentCreateInternal(VOID *pvBlock, RTENV hEnv, PRTUTF1
                     RTStrFree(pszEntry);
                 }
             }
+            else
+                break;
             pwch += RTUtf16Len(pwch) + 1;
-            if (*pwch)
+            if (!*pwch)
                 break;
         }
 
@@ -673,6 +675,9 @@ static int rtProcWinEnvironmentCreateInternal(VOID *pvBlock, RTENV hEnv, PRTUTF1
  */
 static int rtProcWinCreateEnvFromToken(HANDLE hToken, RTENV hEnv, PRTUTF16 *ppwszBlock)
 {
+    Assert(hToken);
+    Assert(hEnv != NIL_RTENV);
+
     RTLDRMOD hUserenv;
     int rc = RTLdrLoadSystem("Userenv.dll", true /*fNoUnload*/, &hUserenv);
     if (RT_SUCCESS(rc))
@@ -722,7 +727,7 @@ static int rtProcWinCreateEnvFromToken(HANDLE hToken, RTENV hEnv, PRTUTF16 *ppws
  * @param   ppwszBlock      Pointer to a pointer of the final UTF16 environment block.
  */
 static int rtProcWinCreateEnvFromAccount(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain,
-                                              RTENV hEnv, PRTUTF16 *ppwszBlock)
+                                         RTENV hEnv, PRTUTF16 *ppwszBlock)
 {
     HANDLE hToken;
     int rc = rtProcWinUserLogon(pwszUser, pwszPassword, pwszDomain, &hToken);
@@ -866,7 +871,7 @@ static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTU
              */
             phToken = fFound ? &hTokenUserDesktop : &hTokenLogon;
             RTLDRMOD hUserenv;
-            int rc = RTLdrLoadSystem("Userenv.dll", true /*fNoUnload*/, &hUserenv);
+            rc = RTLdrLoadSystem("Userenv.dll", true /*fNoUnload*/, &hUserenv);
             if (RT_SUCCESS(rc))
             {
                 PFNLOADUSERPROFILEW pfnLoadUserProfileW;
@@ -908,7 +913,9 @@ static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTU
                                                            NULL,         /* pThreadAttributes */
                                                            TRUE,         /* fInheritHandles */
                                                            dwCreationFlags,
-                                                           pwszzBlock,
+                                                           /** @todo Warn about exceeding 8192 bytes
+                                                            *        on XP and up. */
+                                                           pwszzBlock,   /* lpEnvironment */
                                                            NULL,         /* pCurrentDirectory */
                                                            pStartupInfo,
                                                            pProcInfo);
@@ -1057,7 +1064,6 @@ RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArg
     AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER);
     AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER);
     AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER);
-    /** @todo search the PATH (add flag for this). */
 
     /*
      * Initialize the globals.
@@ -1194,7 +1200,7 @@ RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArg
                  */
                 PROCESS_INFORMATION ProcInfo;
                 RT_ZERO(ProcInfo);
-                DWORD               dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
+                DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
                 if (fFlags & RTPROC_FLAGS_DETACHED)
                     dwCreationFlags |= DETACHED_PROCESS;
                 if (fFlags & RTPROC_FLAGS_NO_WINDOW)
diff --git a/src/VBox/Runtime/testcase/tstRTInlineAsm.cpp b/src/VBox/Runtime/testcase/tstRTInlineAsm.cpp
index c9aee92..c78a511 100644
--- a/src/VBox/Runtime/testcase/tstRTInlineAsm.cpp
+++ b/src/VBox/Runtime/testcase/tstRTInlineAsm.cpp
@@ -191,6 +191,16 @@ void tstASMCpuId(void)
     CHECKVAL(uECX2, s.uECX, "%x");
     CHECKVAL(uEDX2, s.uEDX, "%x");
 
+    uint32_t uEAX2 = s.uEAX - 1;
+    uint32_t uEBX2 = s.uEBX - 1;
+    uECX2 = s.uECX - 1;
+    uEDX2 = s.uEDX - 1;
+    ASMCpuIdExSlow(0, 0, 0, 0, &uEAX2, &uEBX2, &uECX2, &uEDX2);
+    CHECKVAL(uEAX2, s.uEAX, "%x");
+    CHECKVAL(uEBX2, s.uEBX, "%x");
+    CHECKVAL(uECX2, s.uECX, "%x");
+    CHECKVAL(uEDX2, s.uEDX, "%x");
+
     /*
      * Done testing, dump the information.
      */
diff --git a/src/VBox/Storage/testcase/Makefile.kmk b/src/VBox/Storage/testcase/Makefile.kmk
index 99de79b..9d44e45 100644
--- a/src/VBox/Storage/testcase/Makefile.kmk
+++ b/src/VBox/Storage/testcase/Makefile.kmk
@@ -115,7 +115,7 @@ if defined(VBOX_WITH_TESTCASES) || defined(VBOX_WITH_VBOX_IMG)
  ifeq ($(KBUILD_TARGET),linux)
   vbox-img_LIBS += crypt
   ifdef SDK_VBOX_LIBXML2_LIBS
-   vbox-img_LIBS += xml2 lzma
+   vbox-img_LIBS += xml2
   endif
  else if1of ($(KBUILD_TARGET),darwin freebsd)
   vbox-img_LIBS += iconv
diff --git a/src/VBox/VMM/Makefile.kmk b/src/VBox/VMM/Makefile.kmk
index ad566d0..15d348f 100644
--- a/src/VBox/VMM/Makefile.kmk
+++ b/src/VBox/VMM/Makefile.kmk
@@ -20,7 +20,7 @@ include $(KBUILD_PATH)/subheader.kmk
 
 # Include sub-makefiles.
 ifndef VBOX_ONLY_EXTPACKS
- include $(PATH_SUB_CURRENT)/Preload/Makefile.kmk
+ include $(PATH_SUB_CURRENT)/tools/Makefile.kmk
 endif
 include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk
 
@@ -76,6 +76,10 @@ ifdef IEM_VERIFICATION_MODE
  VMM_COMMON_DEFS += IEM_VERIFICATION_MODE IEM_VERIFICATION_MODE_FULL IEM_VERIFICATION_MODE_FULL_HM
 endif
 
+ifdef VBOX_WITH_NEW_MSR_CODE
+ VMM_COMMON_DEFS += VBOX_WITH_NEW_MSR_CODE
+endif
+
 
 #
 # The VMM DLL.
@@ -117,6 +121,8 @@ VBoxVMM_SOURCES  = \
 	VBoxVMM.d \
 	VMMR3/CFGM.cpp \
 	VMMR3/CPUM.cpp \
+	VMMR3/CPUMR3CpuId.cpp \
+	VMMR3/CPUMR3Db.cpp \
 	VMMR3/CPUMDbg.cpp \
 	VMMR3/DBGF.cpp \
 	VMMR3/DBGFAddr.cpp \
@@ -186,6 +192,7 @@ VBoxVMM_SOURCES  = \
 	VMMR3/PATMR3Dbg.cpp \
        ,) \
 	VMMAll/CPUMAllRegs.cpp \
+	VMMAll/CPUMAllMsrs.cpp \
 	VMMAll/CPUMStack.cpp \
 	VMMAll/DBGFAll.cpp \
 	VMMAll/HMAll.cpp \
@@ -437,6 +444,7 @@ if defined(VBOX_WITH_RAW_MODE) && !defined(VBOX_ONLY_EXTPACKS)
  	VMMRZ/PGMRZDynMap.cpp \
  	VMMRZ/VMMRZ.cpp \
  	VMMAll/CPUMAllRegs.cpp \
+	VMMAll/CPUMAllMsrs.cpp \
  	VMMAll/DBGFAll.cpp \
 	VMMAll/IEMAll.cpp \
 	VMMAll/IEMAllAImpl.asm \
@@ -539,6 +547,7 @@ ifndef VBOX_ONLY_EXTPACKS
  	VMMRZ/DBGFRZ.cpp \
  	VMMRZ/VMMRZ.cpp \
  	VMMAll/CPUMAllRegs.cpp \
+	VMMAll/CPUMAllMsrs.cpp \
  	VMMAll/CPUMStack.cpp \
  	VMMAll/DBGFAll.cpp \
  	VMMAll/EMAll.cpp \
@@ -609,9 +618,11 @@ ifndef VBOX_ONLY_EXTPACKS
  #
  LIBRARIES += SSMStandalone
  SSMStandalone_TEMPLATE = VBOXR3EXE
- SSMStandalone_DEFS     = IN_VMM_R3 IN_VMM_STATIC SSM_STANDALONE
+ SSMStandalone_DEFS     = IN_VMM_R3 IN_VMM_STATIC SSM_STANDALONE CPUM_DB_STANDALONE
  SSMStandalone_INCS     = include
- SSMStandalone_SOURCES  = VMMR3/SSM.cpp
+ SSMStandalone_SOURCES  = \
+ 	VMMR3/SSM.cpp \
+ 	VMMR3/CPUMR3Db.cpp
 endif # !VBOX_ONLY_EXTPACKS
 
 
@@ -703,6 +714,11 @@ else
 endif
 endif # bird wants good stacks
 
+
+# Alias the CPU database entries.
+$(foreach base,$(notdir $(basename $(wildcard $(PATH_SUB_CURRENT)/VMMR3/cpus/*.h))), $(eval $(base).o $(base).obj: CPUMR3Db.o))
+
+
 include $(FILE_KBUILD_SUB_FOOTER)
 
 
@@ -731,3 +747,4 @@ IEMAllCImplStrInstr.cpp.o IEMAllCImplStrInstr.cpp.obj: IEMAll.o
 PAEand32Bit.o PAEand32Bit.obj:                 PAETo32Bit.o   PAEToPAE.o   32BitTo32Bit.o PAETo32Bit.o
 LegacyandAMD64.o LegacyandAMD64.obj:           32BitToAMD64.o PAEToAMD64.o
 AMD64andLegacy.o AMD64andLegacy.obj:           AMD64To32Bit.o AMD64ToPAE.o
+
diff --git a/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp b/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp
new file mode 100644
index 0000000..9e1a40c
--- /dev/null
+++ b/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp
@@ -0,0 +1,5506 @@
+/* $Id: CPUMAllMsrs.cpp $ */
+/** @file
+ * CPUM - CPU MSR Registers.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_CPUM
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/pdmapi.h>
+#include <VBox/vmm/hm.h>
+#include <VBox/vmm/tm.h>
+#include "CPUMInternal.h"
+#include <VBox/vmm/vm.h>
+#include <VBox/err.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/**
+ * Validates the CPUMMSRRANGE::offCpumCpu value and declares a local variable
+ * pointing to it.
+ *
+ * ASSUMES sizeof(a_Type) is a power of two and that the member is aligned
+ * correctly.
+ */
+#define CPUM_MSR_ASSERT_CPUMCPU_OFFSET_RETURN(a_pVCpu, a_pRange, a_Type, a_VarName) \
+    AssertMsgReturn(   (a_pRange)->offCpumCpu >= 8 \
+                    && (a_pRange)->offCpumCpu < sizeof(CPUMCPU) \
+                    && !((a_pRange)->offCpumCpu & (RT_MIN(sizeof(a_Type), 8) - 1)) \
+                    , ("offCpumCpu=%#x %s\n", (a_pRange)->offCpumCpu, (a_pRange)->szName), \
+                    VERR_CPUM_MSR_BAD_CPUMCPU_OFFSET); \
+    a_Type *a_VarName = (a_Type *)((uintptr_t)&(a_pVCpu)->cpum.s + (a_pRange)->offCpumCpu)
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+
+/**
+ * Implements reading one or more MSRs.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_CPUM_RAISE_GP_0 on failure (invalid MSR).
+ *
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR we're reading.
+ * @param   pRange      The MSR range descriptor.
+ * @param   puValue     Where to return the value.
+ */
+typedef DECLCALLBACK(int) FNCPUMRDMSR(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
+/** Pointer to a RDMSR worker for a specific MSR or range of MSRs.  */
+typedef FNCPUMRDMSR *PFNCPUMRDMSR;
+
+
+/**
+ * Implements writing one or more MSRs.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_CPUM_RAISE_GP_0 on failure.
+ *
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR we're writing.
+ * @param   pRange      The MSR range descriptor.
+ * @param   uValue      The value to set, ignored bits masked.
+ * @param   uRawValue   The raw value with the ignored bits not masked.
+ */
+typedef DECLCALLBACK(int) FNCPUMWRMSR(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue);
+/** Pointer to a WRMSR worker for a specific MSR or range of MSRs.  */
+typedef FNCPUMWRMSR *PFNCPUMWRMSR;
+
+
+
+/*
+ * Generic functions.
+ * Generic functions.
+ * Generic functions.
+ */
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_FixedValue(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IgnoreWrite(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    Log(("CPUM: Ignoring WRMSR %#x (%s), %#llx\n", idMsr, pRange->szName, uValue));
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_WriteOnly(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_ReadOnly(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    Assert(pRange->fWrGpMask == UINT64_MAX);
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+
+
+/*
+ * IA32
+ * IA32
+ * IA32
+ */
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32P5McAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0; /** @todo implement machine check injection. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32P5McAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement machine check injection. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32P5McType(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0; /** @todo implement machine check injection. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32P5McType(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement machine check injection. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32TimestampCounter(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = TMCpuTickGet(pVCpu);
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32TimestampCounter(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    TMCpuTickSet(pVCpu->CTX_SUFF(pVM), pVCpu, uValue);
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32ApicBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+    if (   !pVM->cpum.s.GuestFeatures.fApic
+        && !pVM->cpum.s.GuestFeatures.fX2Apic)
+    {
+        Log(("CPUM: %s, apic not present -> GP\n", pRange->szName));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+
+    *puValue = pVCpu->cpum.s.Guest.msrApicBase;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32ApicBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    int rc = PDMApicSetBase(pVCpu, uValue);
+    if (rc != VINF_SUCCESS)
+        rc = VERR_CPUM_RAISE_GP_0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32FeatureControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 1; /* Locked, no VT-X, no SYSENTER micromanagement. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32FeatureControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32BiosSignId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo fake microcode update. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32BiosSignId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /* Normally, zero is written to Ia32BiosSignId before reading it in order
+       to select the signature instead of the BBL_CR_D3 behaviour.  The GP mask
+       of the database entry should take care of most illegal writes for now, so
+       just ignore all writes atm. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32BiosUpdateTrigger(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Fake bios update trigger better.  The value is the address to an
+     *        update package, I think.  We should probably GP if it's invalid. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32SmmMonitorCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32SmmMonitorCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo SMM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PmcN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo check CPUID leaf 0ah. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PmcN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo check CPUID leaf 0ah. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MonitorFilterLineSize(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo return 0x1000 if we try emulate mwait 100% correctly. */
+    *puValue = 0x40; /** @todo Change to CPU cache line size. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MonitorFilterLineSize(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo should remember writes, though it's supposedly something only a BIOS
+     * would write so, it's not extremely important. */
+    return VINF_SUCCESS;
+}
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MPerf(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Read MPERF: Adjust against previously written MPERF value.  Is TSC
+     *        what we want? */
+    *puValue = TMCpuTickGet(pVCpu);
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MPerf(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Write MPERF: Calc adjustment. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32APerf(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Read APERF: Adjust against previously written MPERF value.  Is TSC
+     *        what we want? */
+    *puValue = TMCpuTickGet(pVCpu);
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32APerf(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Write APERF: Calc adjustment. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MtrrCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /* This is currently a bit weird. :-) */
+    uint8_t const   cVariableRangeRegs              = 0;
+    bool const      fSystemManagementRangeRegisters = false;
+    bool const      fFixedRangeRegisters            = false;
+    bool const      fWriteCombiningType             = false;
+    *puValue = cVariableRangeRegs
+             | (fFixedRangeRegisters            ? RT_BIT_64(8)  : 0)
+             | (fWriteCombiningType             ? RT_BIT_64(10) : 0)
+             | (fSystemManagementRangeRegisters ? RT_BIT_64(11) : 0);
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MtrrPhysBaseN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement variable MTRR storage. */
+    Assert(pRange->uValue == (idMsr - 0x200) / 2);
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MtrrPhysBaseN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /*
+     * Validate the value.
+     */
+    Assert(pRange->uValue == (idMsr - 0x200) / 2);
+
+    if ((uValue & 0xff) >= 7)
+    {
+        Log(("CPUM: Invalid type set writing MTRR PhysBase MSR %#x: %#llx (%#llx)\n", idMsr, uValue, uValue & 0xff));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+
+    uint64_t fInvPhysMask = ~(RT_BIT_64(pVCpu->CTX_SUFF(pVM)->cpum.s.GuestFeatures.cMaxPhysAddrWidth) - 1U);
+    if (fInvPhysMask & uValue)
+    {
+        Log(("CPUM: Invalid physical address bits set writing MTRR PhysBase MSR %#x: %#llx (%#llx)\n",
+             idMsr, uValue, uValue & fInvPhysMask));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+
+    /*
+     * Store it.
+     */
+    /** @todo Implement variable MTRR storage. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MtrrPhysMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement variable MTRR storage. */
+    Assert(pRange->uValue == (idMsr - 0x200) / 2);
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MtrrPhysMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /*
+     * Validate the value.
+     */
+    Assert(pRange->uValue == (idMsr - 0x200) / 2);
+
+    uint64_t fInvPhysMask = ~(RT_BIT_64(pVCpu->CTX_SUFF(pVM)->cpum.s.GuestFeatures.cMaxPhysAddrWidth) - 1U);
+    if (fInvPhysMask & uValue)
+    {
+        Log(("CPUM: Invalid physical address bits set writing MTRR PhysMask MSR %#x: %#llx (%#llx)\n",
+             idMsr, uValue, uValue & fInvPhysMask));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+
+    /*
+     * Store it.
+     */
+    /** @todo Implement variable MTRR storage. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MtrrFixed(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    CPUM_MSR_ASSERT_CPUMCPU_OFFSET_RETURN(pVCpu, pRange, uint64_t, puFixedMtrr);
+    *puValue = *puFixedMtrr;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MtrrFixed(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    CPUM_MSR_ASSERT_CPUMCPU_OFFSET_RETURN(pVCpu, pRange, uint64_t, puFixedMtrr);
+    for (uint32_t cShift = 0; cShift < 63; cShift += 8)
+    {
+        uint8_t uType = (uint8_t)(uValue >> cShift);
+        if (uType >= 7)
+        {
+            Log(("CPUM: Invalid MTRR type at %u:%u in fixed range (%#x/%s): %#llx (%#llx)\n",
+                 cShift + 7, cShift, idMsr, pRange->szName, uValue, uType));
+            return VERR_CPUM_RAISE_GP_0;
+        }
+    }
+    *puFixedMtrr = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MtrrDefType(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.GuestMsrs.msr.MtrrDefType;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MtrrDefType(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    if ((uValue & 0xff) >= 7)
+    {
+        Log(("CPUM: Invalid MTRR default type value: %#llx (%#llx)\n", pRange->szName, uValue, uValue & 0xff));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+
+    pVCpu->cpum.s.GuestMsrs.msr.MtrrDefType = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32Pat(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrPAT;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32Pat(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.Guest.msrPAT = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32SysEnterCs(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.SysEnter.cs;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32SysEnterCs(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /* Note! We used to mask this by 0xffff, but turns out real HW doesn't and
+             there are generally 32-bit working bits backing this register. */
+    pVCpu->cpum.s.Guest.SysEnter.cs = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32SysEnterEsp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.SysEnter.esp;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32SysEnterEsp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    if (X86_IS_CANONICAL(uValue))
+    {
+        pVCpu->cpum.s.Guest.SysEnter.esp = uValue;
+        return VINF_SUCCESS;
+    }
+    Log(("CPUM: IA32_SYSENTER_ESP not canonical! %#llx\n", uValue));
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32SysEnterEip(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.SysEnter.eip;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32SysEnterEip(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    if (X86_IS_CANONICAL(uValue))
+    {
+        pVCpu->cpum.s.Guest.SysEnter.eip = uValue;
+        return VINF_SUCCESS;
+    }
+    Log(("CPUM: IA32_SYSENTER_EIP not canonical! %#llx\n", uValue));
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32McgCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+#if 0 /** @todo implement machine checks. */
+    *puValue = pRange->uValue & (RT_BIT_64(8) | 0);
+#else
+    *puValue = 0;
+#endif
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32McgStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement machine checks. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32McgStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement machine checks. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32McgCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement machine checks. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32McgCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement machine checks. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32DebugCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_DEBUGCTL. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32DebugCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_DEBUGCTL. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32SmrrPhysBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement intel SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32SmrrPhysBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement intel SMM. */
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32SmrrPhysMask(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement intel SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32SmrrPhysMask(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement intel SMM. */
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PlatformDcaCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement intel direct cache access (DCA)?? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PlatformDcaCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement intel direct cache access (DCA)?? */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32CpuDcaCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement intel direct cache access (DCA)?? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32Dca0Cap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement intel direct cache access (DCA)?? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32Dca0Cap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement intel direct cache access (DCA)?? */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfEvtSelN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_PERFEVTSEL0+. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfEvtSelN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_PERFEVTSEL0+. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_PERFSTATUS. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /* Pentium4 allows writing, but all bits are ignored. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_PERFCTL. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_PERFCTL. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32FixedCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_FIXED_CTRn (fixed performance counters). */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32FixedCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_FIXED_CTRn (fixed performance counters). */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfCapabilities(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfCapabilities(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32FixedCtrCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32FixedCtrCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfGlobalStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfGlobalStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfGlobalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfGlobalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PerfGlobalOvfCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PerfGlobalOvfCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32PebsEnable(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32PebsEnable(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32ClockModulation(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_CLOCK_MODULATION. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32ClockModulation(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_CLOCK_MODULATION. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32ThermInterrupt(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_THERM_INTERRUPT. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32ThermInterrupt(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_THERM_STATUS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32ThermStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_THERM_STATUS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32ThermStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_THERM_INTERRUPT. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32Therm2Ctl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_THERM2_CTL. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32Therm2Ctl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement IA32_THERM2_CTL. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32MiscEnable(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.GuestMsrs.msr.MiscEnable;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32MiscEnable(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+#ifdef LOG_ENABLED
+    uint64_t const uOld = pVCpu->cpum.s.GuestMsrs.msr.MiscEnable;
+#endif
+
+    /* Unsupported bits are generally ignored and stripped by the MSR range
+       entry that got us here. So, we just need to preserve fixed bits. */
+    pVCpu->cpum.s.GuestMsrs.msr.MiscEnable = uValue
+                                           | MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL
+                                           | MSR_IA32_MISC_ENABLE_BTS_UNAVAIL;
+
+    Log(("CPUM: IA32_MISC_ENABLE; old=%#llx written=%#llx => %#llx\n",
+         uOld, uValue,  pVCpu->cpum.s.GuestMsrs.msr.MiscEnable));
+
+    /** @todo Wire IA32_MISC_ENABLE bit 22 to our NT 4 CPUID trick. */
+    /** @todo Wire up MSR_IA32_MISC_ENABLE_XD_DISABLE. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32McCtlStatusAddrMiscN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement machine check exception injection. */
+    switch (idMsr & 3)
+    {
+        case 0:
+        case 1:
+            *puValue = 0;
+            break;
+
+        /* The ADDR and MISC registers aren't accessible since the
+           corresponding STATUS bits are zero. */
+        case 2:
+            Log(("CPUM: Reading IA32_MCi_ADDR %#x -> #GP\n", idMsr));
+            return VERR_CPUM_RAISE_GP_0;
+        case 3:
+            Log(("CPUM: Reading IA32_MCi_MISC %#x -> #GP\n", idMsr));
+            return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32McCtlStatusAddrMiscN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    switch (idMsr & 3)
+    {
+        case 0:
+            /* Ignore writes to the CTL register. */
+            break;
+
+        case 1:
+            /* According to specs, the STATUS register can only be written to
+               with the value 0.  VBoxCpuReport thinks different for a
+               Pentium M Dothan, but implementing according to specs now. */
+            if (uValue != 0)
+            {
+                Log(("CPUM: Writing non-zero value (%#llx) to IA32_MCi_STATUS %#x -> #GP\n", uValue, idMsr));
+                return VERR_CPUM_RAISE_GP_0;
+            }
+            break;
+
+        /* Specs states that ADDR and MISC can be cleared by writing zeros.
+           Writing 1s will GP.  Need to figure out how this relates to the
+           ADDRV and MISCV status flags.  If writing is independent of those
+           bits, we need to know whether the CPU really implements them since
+           that is exposed by writing 0 to them.
+           Implementing the solution with the fewer GPs for now. */
+        case 2:
+            if (uValue != 0)
+            {
+                Log(("CPUM: Writing non-zero value (%#llx) to IA32_MCi_ADDR %#x -> #GP\n", uValue, idMsr));
+                return VERR_CPUM_RAISE_GP_0;
+            }
+            break;
+        case 3:
+            if (uValue != 0)
+            {
+                Log(("CPUM: Writing non-zero value (%#llx) to IA32_MCi_MISC %#x -> #GP\n", uValue, idMsr));
+                return VERR_CPUM_RAISE_GP_0;
+            }
+            break;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32McNCtl2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement machine check exception injection. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32McNCtl2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Implement machine check exception injection. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32DsArea(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement IA32_DS_AREA. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32DsArea(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32TscDeadline(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement TSC deadline timer. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32TscDeadline(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement TSC deadline timer. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32X2ApicN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    int rc = PDMApicReadMSR(pVCpu->CTX_SUFF(pVM), pVCpu->idCpu, idMsr, puValue);
+    if (rc != VINF_SUCCESS)
+    {
+        Log(("CPUM: X2APIC %#x read => %Rrc => #GP\n", idMsr, rc));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32X2ApicN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    int rc = PDMApicWriteMSR(pVCpu->CTX_SUFF(pVM), pVCpu->idCpu, idMsr, uValue);
+    if (rc != VINF_SUCCESS)
+    {
+        Log(("CPUM: X2APIC %#x write %#llx => %Rrc => #GP\n", idMsr, rc, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32DebugInterface(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo IA32_DEBUG_INTERFACE (no docs)  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Ia32DebugInterface(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo IA32_DEBUG_INTERFACE (no docs)  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxPinbasedCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxProcbasedCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxExitCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxEntryCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxMisc(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxCr0Fixed0(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxCr0Fixed1(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxCr4Fixed0(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxCr4Fixed1(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxVmcsEnum(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxProcBasedCtls2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxEptVpidCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxTruePinbasedCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxTrueProcbasedCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxTrueExitCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Ia32VmxTrueEntryCtls(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+
+
+
+
+
+
+
+
+/*
+ * AMD64
+ * AMD64
+ * AMD64
+ */
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64Efer(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrEFER;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64Efer(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    PVM             pVM          = pVCpu->CTX_SUFF(pVM);
+    uint64_t const  uOldEfer     = pVCpu->cpum.s.Guest.msrEFER;
+    uint32_t const  fExtFeatures = pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
+                                 ? pVM->cpum.s.aGuestCpuIdExt[1].edx
+                                 : 0;
+    uint64_t        fMask        = 0;
+
+    /* Filter out those bits the guest is allowed to change. (e.g. LMA is read-only) */
+    if (fExtFeatures & X86_CPUID_EXT_FEATURE_EDX_NX)
+        fMask |= MSR_K6_EFER_NXE;
+    if (fExtFeatures & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE)
+        fMask |= MSR_K6_EFER_LME;
+    if (fExtFeatures & X86_CPUID_EXT_FEATURE_EDX_SYSCALL)
+        fMask |= MSR_K6_EFER_SCE;
+    if (fExtFeatures & X86_CPUID_AMD_FEATURE_EDX_FFXSR)
+        fMask |= MSR_K6_EFER_FFXSR;
+
+    /* Check for illegal MSR_K6_EFER_LME transitions: not allowed to change LME if
+       paging is enabled. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
+    if (   (uOldEfer & MSR_K6_EFER_LME) != (uValue & fMask & MSR_K6_EFER_LME)
+        && (pVCpu->cpum.s.Guest.cr0 & X86_CR0_PG))
+    {
+        Log(("CPUM: Illegal MSR_K6_EFER_LME change: paging is enabled!!\n"));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+
+    /* There are a few more: e.g. MSR_K6_EFER_LMSLE */
+    AssertMsg(!(uValue & ~(MSR_K6_EFER_NXE | MSR_K6_EFER_LME | MSR_K6_EFER_LMA /* ignored anyway */ | MSR_K6_EFER_SCE | MSR_K6_EFER_FFXSR)),
+              ("Unexpected value %RX64\n", uValue));
+    pVCpu->cpum.s.Guest.msrEFER = (uOldEfer & ~fMask) | (uValue & fMask);
+
+    /* AMD64 Architecture Programmer's Manual: 15.15 TLB Control; flush the TLB
+       if MSR_K6_EFER_NXE, MSR_K6_EFER_LME or MSR_K6_EFER_LMA are changed. */
+    if (   (uOldEfer                    & (MSR_K6_EFER_NXE | MSR_K6_EFER_LME | MSR_K6_EFER_LMA))
+        != (pVCpu->cpum.s.Guest.msrEFER & (MSR_K6_EFER_NXE | MSR_K6_EFER_LME | MSR_K6_EFER_LMA)))
+    {
+        /// @todo PGMFlushTLB(pVCpu, cr3, true /*fGlobal*/);
+        HMFlushTLB(pVCpu);
+
+        /* Notify PGM about NXE changes. */
+        if (   (uOldEfer                    & MSR_K6_EFER_NXE)
+            != (pVCpu->cpum.s.Guest.msrEFER & MSR_K6_EFER_NXE))
+            PGMNotifyNxeChanged(pVCpu, !(uOldEfer & MSR_K6_EFER_NXE));
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64SyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrSTAR;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64SyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.Guest.msrSTAR = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64LongSyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrLSTAR;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64LongSyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    pVCpu->cpum.s.Guest.msrLSTAR = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64CompSyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrCSTAR;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64CompSyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    pVCpu->cpum.s.Guest.msrCSTAR = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64SyscallFlagMask(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrSFMASK;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64SyscallFlagMask(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.Guest.msrSFMASK = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64FsBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.fs.u64Base;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64FsBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.Guest.fs.u64Base = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64GsBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.gs.u64Base;
+    return VINF_SUCCESS;
+}
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64GsBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.Guest.gs.u64Base = uValue;
+    return VINF_SUCCESS;
+}
+
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64KernelGsBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.Guest.msrKERNELGSBASE;
+    return VINF_SUCCESS;
+}
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64KernelGsBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.Guest.msrKERNELGSBASE = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Amd64TscAux(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.GuestMsrs.msr.TscAux;
+    return VINF_SUCCESS;
+}
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Amd64TscAux(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    pVCpu->cpum.s.GuestMsrs.msr.TscAux = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/*
+ * Intel specific
+ * Intel specific
+ * Intel specific
+ */
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelEblCrPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo recalc clock frequency ratio? */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelEblCrPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Write EBL_CR_POWERON: Remember written bits. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelP4EbcHardPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo P4 hard power on config */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelP4EbcHardPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo P4 hard power on config */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelP4EbcSoftPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo P4 soft power on config  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelP4EbcSoftPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo P4 soft power on config */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelP4EbcFrequencyId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo P4 bus frequency config  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelP4EbcFrequencyId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo P4 bus frequency config  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelPlatformInfo100MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+
+    /* Just indicate a fixed TSC, no turbo boost, no programmable anything. */
+    uint64_t uTscHz = TMCpuTicksPerSecond(pVM);
+    uint8_t  uTsc100MHz = (uint8_t)(uTscHz / UINT32_C(100000000));
+    *puValue = ((uint32_t)uTsc100MHz << 8)   /* TSC invariant frequency. */
+             | ((uint64_t)uTsc100MHz << 40); /* The max turbo frequency. */
+
+    /* Ivy bridge has a minimum operating ratio as well. */
+    if (true) /** @todo detect sandy bridge. */
+        *puValue |= (uint64_t)uTsc100MHz << 48;
+
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelPlatformInfo133MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /* Just indicate a fixed TSC, no turbo boost, no programmable anything. */
+    uint64_t uTscHz = TMCpuTicksPerSecond(pVCpu->CTX_SUFF(pVM));
+    uint8_t  uTsc133MHz = (uint8_t)(uTscHz / UINT32_C(133333333));
+    *puValue = ((uint32_t)uTsc133MHz << 8)   /* TSC invariant frequency. */
+             | ((uint64_t)uTsc133MHz << 40); /* The max turbo frequency. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelFlexRatio100MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    uint64_t uValue = pRange->uValue & ~UINT64_C(0x1ff00);
+
+    uint64_t uTscHz = TMCpuTicksPerSecond(pVCpu->CTX_SUFF(pVM));
+    uint8_t  uTsc100MHz = (uint8_t)(uTscHz / UINT32_C(100000000));
+    uValue |= (uint32_t)uTsc100MHz << 8;
+
+    *puValue = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelFlexRatio100MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement writing MSR_FLEX_RATIO. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelFlexRatio133MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    uint64_t uValue = pRange->uValue & ~UINT64_C(0x1ff00);
+
+    uint64_t uTscHz = TMCpuTicksPerSecond(pVCpu->CTX_SUFF(pVM));
+    uint8_t  uTsc133MHz = (uint8_t)(uTscHz / UINT32_C(133333333));
+    uValue |= (uint32_t)uTsc133MHz << 8;
+
+    *puValue = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelFlexRatio133MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement writing MSR_FLEX_RATIO. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelPkgCStConfigControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pVCpu->cpum.s.GuestMsrs.msr.PkgCStateCfgCtrl;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelPkgCStConfigControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    if (pVCpu->cpum.s.GuestMsrs.msr.PkgCStateCfgCtrl & RT_BIT_64(15))
+    {
+        Log(("CPUM: WRMDR %#x (%s), %#llx: Write protected -> #GP\n", idMsr, pRange->szName, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+#if 0 /** @todo check what real (old) hardware does. */
+    if ((uValue & 7) >= 5)
+    {
+        Log(("CPUM: WRMDR %#x (%s), %#llx: Invalid limit (%d) -> #GP\n", idMsr, pRange->szName, uValue, (uint32_t)(uValue & 7)));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+#endif
+    pVCpu->cpum.s.GuestMsrs.msr.PkgCStateCfgCtrl = uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelPmgIoCaptureBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement I/O mwait wakeup. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelPmgIoCaptureBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement I/O mwait wakeup. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelLastBranchFromToN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last branch records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelLastBranchFromToN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last branch records. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelLastBranchFromN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last branch records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelLastBranchFromN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last branch records. */
+    /** @todo Probing indicates that bit 63 is settable on SandyBridge, at least
+     *        if the rest of the bits are zero.  Automatic sign extending?
+     *        Investigate! */
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelLastBranchToN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last branch records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelLastBranchToN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last branch records. */
+    /** @todo Probing indicates that bit 63 is settable on SandyBridge, at least
+     *        if the rest of the bits are zero.  Automatic sign extending?
+     *        Investigate! */
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelLastBranchTos(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last branch records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelLastBranchTos(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last branch records. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelBblCrCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelBblCrCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelBblCrCtl3(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelBblCrCtl3(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7TemperatureTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7TemperatureTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7MsrOffCoreResponseN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo machine check. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7MsrOffCoreResponseN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo machine check. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7MiscPwrMgmt(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7MiscPwrMgmt(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelP6CrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    int rc = CPUMGetGuestCRx(pVCpu, pRange->uValue, puValue);
+    AssertRC(rc);
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelP6CrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /* This CRx interface differs from the MOV CRx, GReg interface in that
+       #GP(0) isn't raised if unsupported bits are written to.  Instead they
+       are simply ignored and masked off. (Pentium M Dothan)  */
+    /** @todo Implement MSR_P6_CRx writing.  Too much effort for very little, if
+     *        any, gain. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCpuId1FeatureMaskEcdx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement CPUID masking.  */
+    *puValue = UINT64_MAX;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCpuId1FeatureMaskEcdx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement CPUID masking.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCpuId1FeatureMaskEax(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement CPUID masking.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCpuId1FeatureMaskEax(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement CPUID masking.  */
+    return VINF_SUCCESS;
+}
+
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCpuId80000001FeatureMaskEcdx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement CPUID masking.  */
+    *puValue = UINT64_MAX;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCpuId80000001FeatureMaskEcdx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement CPUID masking.  */
+    return VINF_SUCCESS;
+}
+
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyAesNiCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement AES-NI.  */
+    *puValue = 3;  /* Bit 0 is lock bit, bit 1 disables AES-NI. That's what they say. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7SandyAesNiCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement AES-NI.  */
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7TurboRatioLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement intel C states.  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7TurboRatioLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement intel C states.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7LbrSelect(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last-branch-records.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7LbrSelect(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last-branch-records.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyErrorControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement memory error injection (MSR_ERROR_CONTROL).  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7SandyErrorControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement memory error injection (MSR_ERROR_CONTROL).  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7VirtualLegacyWireCap(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement memory VLW?  */
+    *puValue = pRange->uValue;
+    /* Note: A20M is known to be bit 1 as this was disclosed in spec update
+       AAJ49/AAK51/????, which documents the inversion of this bit.  The
+       Sandy bridge CPU here has value 0x74, so it probably doesn't have a BIOS
+       that correct things.  Some guesses at the other bits:
+                 bit 2 = INTR
+                 bit 4 = SMI
+                 bit 5 = INIT
+                 bit 6 = NMI */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7PowerCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7PowerCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel power management  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyPebsNumAlt(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel performance counters.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7SandyPebsNumAlt(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel performance counters.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7PebsLdLat(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel performance counters.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7PebsLdLat(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel performance counters.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7PkgCnResidencyN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7CoreCnResidencyN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyVrCurrentConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Figure out what MSR_VR_CURRENT_CONFIG & MSR_VR_MISC_CONFIG are.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7SandyVrCurrentConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Figure out what MSR_VR_CURRENT_CONFIG & MSR_VR_MISC_CONFIG are.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyVrMiscConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Figure out what MSR_VR_CURRENT_CONFIG & MSR_VR_MISC_CONFIG are.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7SandyVrMiscConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Figure out what MSR_VR_CURRENT_CONFIG & MSR_VR_MISC_CONFIG are.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyRaplPowerUnit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyPkgCnIrtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7SandyPkgCnIrtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel power management.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7SandyPkgC2Residency(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPkgPowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7RaplPkgPowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel RAPL.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPkgEnergyStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPkgPerfStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPkgPowerInfo(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplDramPowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7RaplDramPowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel RAPL.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplDramEnergyStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplDramPerfStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplDramPowerInfo(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp0PowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7RaplPp0PowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel RAPL.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp0EnergyStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp0Policy(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7RaplPp0Policy(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel RAPL.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp0PerfStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp1PowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7RaplPp1PowerLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel RAPL.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp1EnergyStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7RaplPp1Policy(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel RAPL.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7RaplPp1Policy(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel RAPL.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7IvyConfigTdpNominal(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7IvyConfigTdpLevel1(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7IvyConfigTdpLevel2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7IvyConfigTdpControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7IvyConfigTdpControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel power management.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7IvyTurboActivationRatio(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo intel power management.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7IvyTurboActivationRatio(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo intel power management.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncPerfGlobalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncPerfGlobalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncPerfGlobalStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncPerfGlobalStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncPerfGlobalOvfCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncPerfGlobalOvfCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncPerfFixedCtrCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncPerfFixedCtrCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncPerfFixedCtr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncPerfFixedCtr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncCBoxConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncArbPerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncArbPerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelI7UncArbPerfEvtSelN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo uncore msrs.  */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelI7UncArbPerfEvtSelN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo uncore msrs.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCore2EmttmCrTablesN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement enhanced multi thread termal monitoring? */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCore2EmttmCrTablesN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement enhanced multi thread termal monitoring? */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCore2SmmCStMiscInfo(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo SMM & C-states? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCore2SmmCStMiscInfo(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo SMM & C-states? */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCore1ExtConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Core1&2 EXT_CONFIG (whatever that is)? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCore1ExtConfig(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Core1&2 EXT_CONFIG (whatever that is)? */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCore1DtsCalControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Core1&2(?) DTS_CAL_CTRL (whatever that is)? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCore1DtsCalControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Core1&2(?) DTS_CAL_CTRL (whatever that is)? */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_IntelCore2PeciControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Core2+ platform environment control interface control register? */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_IntelCore2PeciControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Core2+ platform environment control interface control register? */
+    return VINF_SUCCESS;
+}
+
+
+
+/*
+ * Multiple vendor P6 MSRs.
+ * Multiple vendor P6 MSRs.
+ * Multiple vendor P6 MSRs.
+ *
+ * These MSRs were introduced with the P6 but not elevated to architectural
+ * MSRs, despite other vendors implementing them.
+ */
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_P6LastBranchFromIp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /* AMD seems to just record RIP, while intel claims to record RIP+CS.BASE
+       if I read the docs correctly, thus the need for separate functions. */
+    /** @todo implement last branch records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_P6LastBranchToIp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last branch records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_P6LastIntFromIp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last exception records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_P6LastIntFromIp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last exception records. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_P6LastIntToIp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo implement last exception records. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_P6LastIntToIp(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo implement last exception records. */
+    return VINF_SUCCESS;
+}
+
+
+
+/*
+ * AMD specific
+ * AMD specific
+ * AMD specific
+ */
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hTscRate(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement TscRateMsr */
+    *puValue = RT_MAKE_U64(0, 1); /* 1.0 = reset value. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hTscRate(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Implement TscRateMsr */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hLwpCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement AMD LWP? (Instructions: LWPINS, LWPVAL, LLWPCB, SLWPCB) */
+    /* Note: Only listes in BKDG for Family 15H. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hLwpCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Implement AMD LWP? (Instructions: LWPINS, LWPVAL, LLWPCB, SLWPCB) */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hLwpCbAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Implement AMD LWP? (Instructions: LWPINS, LWPVAL, LLWPCB, SLWPCB) */
+    /* Note: Only listes in BKDG for Family 15H. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hLwpCbAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Implement AMD LWP? (Instructions: LWPINS, LWPVAL, LLWPCB, SLWPCB) */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hMc4MiscN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo machine check. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hMc4MiscN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo machine check. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8PerfCtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD performance events. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8PerfCtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD performance events. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8PerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD performance events. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8PerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD performance events. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SysCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SYS_CFG */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SysCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SYS_CFG */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8HwCr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD HW_CFG */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8HwCr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD HW_CFG */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8IorrBaseN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IorrMask/IorrBase */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8IorrBaseN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IorrMask/IorrBase */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8IorrMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IorrMask/IorrBase */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8IorrMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IorrMask/IorrBase */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8TopOfMemN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    *puValue = 0;
+    /** @todo return 4GB - RamHoleSize here for TOPMEM. Figure out what to return
+     *        for TOPMEM2. */
+    //if (pRange->uValue == 0)
+    //    *puValue = _4G - RamHoleSize;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8TopOfMemN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD TOPMEM and TOPMEM2/TOM2. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8NbCfg1(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD NB_CFG1 */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8NbCfg1(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD NB_CFG1 */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8McXcptRedir(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo machine check. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8McXcptRedir(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo machine check. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8CpuNameN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), pRange->uValue / 2 + 0x80000001, 0);
+    if (pLeaf)
+    {
+        if (!(pRange->uValue & 1))
+            *puValue = RT_MAKE_U64(pLeaf->uEax, pLeaf->uEbx);
+        else
+            *puValue = RT_MAKE_U64(pLeaf->uEcx, pLeaf->uEdx);
+    }
+    else
+        *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8CpuNameN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Remember guest programmed CPU name. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8HwThermalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD HTC. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8HwThermalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD HTC. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SwThermalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD STC. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SwThermalCtrl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD STC. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8FidVidControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD FIDVID_CTL. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8FidVidControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD FIDVID_CTL. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8FidVidStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD FIDVID_STATUS. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8McCtlMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD MC. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8McCtlMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD MC. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmiOnIoTrapN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM/SMI and I/O trap. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmiOnIoTrapN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM/SMI and I/O trap. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmiOnIoTrapCtlSts(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM/SMI and I/O trap. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmiOnIoTrapCtlSts(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM/SMI and I/O trap. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8IntPendingMessage(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Interrupt pending message. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8IntPendingMessage(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Interrupt pending message. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmiTriggerIoCycle(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM/SMI and trigger I/O cycle. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmiTriggerIoCycle(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM/SMI and trigger I/O cycle. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hMmioCfgBaseAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD MMIO Configuration base address. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hMmioCfgBaseAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD MMIO Configuration base address. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hTrapCtlMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD 0xc0010059. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hTrapCtlMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD 0xc0010059. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hPStateCurLimit(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD P-states. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hPStateControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD P-states. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hPStateControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD P-states. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hPStateStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD P-states. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hPStateStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD P-states. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hPStateN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD P-states. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hPStateN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD P-states. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hCofVidControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD P-states. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hCofVidControl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD P-states. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hCofVidStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD P-states. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hCofVidStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /* Note! Writing 0 seems to not GP, not sure if it does anything to the value... */
+    /** @todo AMD P-states. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hCStateIoBaseAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD C-states. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hCStateIoBaseAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD C-states. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hCpuWatchdogTimer(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD machine checks. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hCpuWatchdogTimer(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD machine checks. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmmBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmmBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmmAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmmAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM. */
+    return VINF_SUCCESS;
+}
+
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmmMask(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmmMask(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8VmCr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SVM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8VmCr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SVM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8IgnNe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IGNNE\# control. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8IgnNe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IGNNE\# control. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8SmmCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8SmmCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8VmHSavePa(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SVM. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8VmHSavePa(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SVM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hVmLockKey(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SVM. */
+    *puValue = 0; /* RAZ */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hVmLockKey(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SVM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hSmmLockKey(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM. */
+    *puValue = 0; /* RAZ */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hSmmLockKey(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hLocalSmiStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD SMM/SMI. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hLocalSmiStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD SMM/SMI. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hOsVisWrkIdLength(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD OS visible workaround. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hOsVisWrkIdLength(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD OS visible workaround. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hOsVisWrkStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD OS visible workaround. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hOsVisWrkStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD OS visible workaround. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam16hL2IPerfCtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD L2I performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam16hL2IPerfCtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD L2I performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam16hL2IPerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD L2I performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam16hL2IPerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD L2I performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hNorthbridgePerfCtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD Northbridge performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hNorthbridgePerfCtlN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD Northbridge performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hNorthbridgePerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD Northbridge performance counters. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hNorthbridgePerfCtrN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD Northbridge performance counters. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7MicrocodeCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus. Need to be explored and verify K7 presence. */
+    /** @todo Undocumented register only seen mentioned in fam15h erratum \#608. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7MicrocodeCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo Undocumented register only seen mentioned in fam15h erratum \#608. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7ClusterIdMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus. Need to be explored and verify K7 presence. */
+    /** @todo Undocumented register only seen mentioned in fam16h BKDG r3.00 when
+     *        describing EBL_CR_POWERON. */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7ClusterIdMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo Undocumented register only seen mentioned in fam16h BKDG r3.00 when
+     *        describing EBL_CR_POWERON. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8CpuIdCtlStd07hEbax(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000007, 0);
+    if (pLeaf)
+        *puValue = RT_MAKE_U64(pLeaf->uEbx, pLeaf->uEax);
+    else
+        *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8CpuIdCtlStd07hEbax(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Changing CPUID leaf 7/0. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8CpuIdCtlStd06hEcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000006, 0);
+    if (pLeaf)
+        *puValue = pLeaf->uEcx;
+    else
+        *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8CpuIdCtlStd06hEcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Changing CPUID leaf 6. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8CpuIdCtlStd01hEdcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000001, 0);
+    if (pLeaf)
+        *puValue = RT_MAKE_U64(pLeaf->uEdx, pLeaf->uEcx);
+    else
+        *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8CpuIdCtlStd01hEdcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Changing CPUID leaf 0x80000001. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8CpuIdCtlExt01hEdcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x80000001, 0);
+    if (pLeaf)
+        *puValue = RT_MAKE_U64(pLeaf->uEdx, pLeaf->uEcx);
+    else
+        *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8CpuIdCtlExt01hEdcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Changing CPUID leaf 0x80000001. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK8PatchLevel(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Fake AMD microcode patching.  */
+    *puValue = pRange->uValue;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK8PatchLoader(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Fake AMD microcode patching.  */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7DebugStatusMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7DebugStatusMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7BHTraceBaseMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7BHTraceBaseMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7BHTracePtrMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7BHTracePtrMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7BHTraceLimitMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7BHTraceLimitMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7HardwareDebugToolCfgMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7HardwareDebugToolCfgMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7FastFlushCountMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7FastFlushCountMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo undocumented */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7NodeId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD node ID and bios scratch. */
+    *puValue = 0; /* nodeid = 0; nodes-per-cpu = 1 */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7NodeId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD node ID and bios scratch. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7DrXAddrMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD DRx address masking (range breakpoints). */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7DrXAddrMaskN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD DRx address masking (range breakpoints). */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7Dr0DataMatchMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD undocument debugging features. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7Dr0DataMatchMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD undocument debugging features. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7Dr0DataMaskMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD undocument debugging features. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7Dr0DataMaskMaybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD undocument debugging features. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7LoadStoreCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD load-store config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7LoadStoreCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD load-store config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7InstrCacheCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD instruction cache config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7InstrCacheCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD instruction cache config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7DataCacheCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD data cache config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7DataCacheCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD data cache config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7BusUnitCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD bus unit config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7BusUnitCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo AMD bus unit config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdK7DebugCtl2Maybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo Undocument AMD debug control register \#2. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdK7DebugCtl2Maybe(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo Allegedly requiring edi=0x9c5a203a when execuing rdmsr/wrmsr on older
+     *  cpus.  Need to be explored and verify K7 presence.  */
+    /** @todo Undocument AMD debug control register \#2. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hFpuCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD FPU config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hFpuCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD FPU config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hDecoderCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD decoder config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hDecoderCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD decoder config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hBusUnitCfg2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /* Note! 10h and 16h */
+    /** @todo AMD bus unit  config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hBusUnitCfg2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /* Note! 10h and 16h */
+    /** @todo AMD bus unit config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hCombUnitCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD unit config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hCombUnitCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD unit config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hCombUnitCfg2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD unit config 2. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hCombUnitCfg2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD unit config 2. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hCombUnitCfg3(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD combined unit config 3. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hCombUnitCfg3(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD combined unit config 3. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hExecUnitCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD execution unit config. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hExecUnitCfg(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD execution unit config. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam15hLoadStoreCfg2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD load-store config 2. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam15hLoadStoreCfg2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD load-store config 2. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsFetchCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsFetchCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsFetchLinAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsFetchLinAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsFetchPhysAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsFetchPhysAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsOpExecCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsOpExecCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsOpRip(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsOpRip(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsOpData(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsOpData(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsOpData2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsOpData2(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsOpData3(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsOpData3(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsDcLinAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsDcLinAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsDcPhysAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsDcPhysAddr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam10hIbsCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam10hIbsCtl(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_AmdFam14hIbsBrTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    /** @todo AMD IBS. */
+    *puValue = 0;
+    return VINF_SUCCESS;
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_AmdFam14hIbsBrTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    /** @todo AMD IBS. */
+    if (!X86_IS_CANONICAL(uValue))
+    {
+        Log(("CPUM: wrmsr %s(%#x), %#llx -> %#GP - not canonical\n", pRange->szName, idMsr, uValue));
+        return VERR_CPUM_RAISE_GP_0;
+    }
+    return VINF_SUCCESS;
+}
+
+
+
+/**
+ * MSR read function table.
+ */
+static const PFNCPUMRDMSR g_aCpumRdMsrFns[kCpumMsrRdFn_End] =
+{
+    NULL, /* Invalid */
+    cpumMsrRd_FixedValue,
+    NULL, /* Alias */
+    cpumMsrRd_WriteOnly,
+    cpumMsrRd_Ia32P5McAddr,
+    cpumMsrRd_Ia32P5McType,
+    cpumMsrRd_Ia32TimestampCounter,
+    cpumMsrRd_Ia32ApicBase,
+    cpumMsrRd_Ia32FeatureControl,
+    cpumMsrRd_Ia32BiosSignId,
+    cpumMsrRd_Ia32SmmMonitorCtl,
+    cpumMsrRd_Ia32PmcN,
+    cpumMsrRd_Ia32MonitorFilterLineSize,
+    cpumMsrRd_Ia32MPerf,
+    cpumMsrRd_Ia32APerf,
+    cpumMsrRd_Ia32MtrrCap,
+    cpumMsrRd_Ia32MtrrPhysBaseN,
+    cpumMsrRd_Ia32MtrrPhysMaskN,
+    cpumMsrRd_Ia32MtrrFixed,
+    cpumMsrRd_Ia32MtrrDefType,
+    cpumMsrRd_Ia32Pat,
+    cpumMsrRd_Ia32SysEnterCs,
+    cpumMsrRd_Ia32SysEnterEsp,
+    cpumMsrRd_Ia32SysEnterEip,
+    cpumMsrRd_Ia32McgCap,
+    cpumMsrRd_Ia32McgStatus,
+    cpumMsrRd_Ia32McgCtl,
+    cpumMsrRd_Ia32DebugCtl,
+    cpumMsrRd_Ia32SmrrPhysBase,
+    cpumMsrRd_Ia32SmrrPhysMask,
+    cpumMsrRd_Ia32PlatformDcaCap,
+    cpumMsrRd_Ia32CpuDcaCap,
+    cpumMsrRd_Ia32Dca0Cap,
+    cpumMsrRd_Ia32PerfEvtSelN,
+    cpumMsrRd_Ia32PerfStatus,
+    cpumMsrRd_Ia32PerfCtl,
+    cpumMsrRd_Ia32FixedCtrN,
+    cpumMsrRd_Ia32PerfCapabilities,
+    cpumMsrRd_Ia32FixedCtrCtrl,
+    cpumMsrRd_Ia32PerfGlobalStatus,
+    cpumMsrRd_Ia32PerfGlobalCtrl,
+    cpumMsrRd_Ia32PerfGlobalOvfCtrl,
+    cpumMsrRd_Ia32PebsEnable,
+    cpumMsrRd_Ia32ClockModulation,
+    cpumMsrRd_Ia32ThermInterrupt,
+    cpumMsrRd_Ia32ThermStatus,
+    cpumMsrRd_Ia32Therm2Ctl,
+    cpumMsrRd_Ia32MiscEnable,
+    cpumMsrRd_Ia32McCtlStatusAddrMiscN,
+    cpumMsrRd_Ia32McNCtl2,
+    cpumMsrRd_Ia32DsArea,
+    cpumMsrRd_Ia32TscDeadline,
+    cpumMsrRd_Ia32X2ApicN,
+    cpumMsrRd_Ia32DebugInterface,
+    cpumMsrRd_Ia32VmxBase,
+    cpumMsrRd_Ia32VmxPinbasedCtls,
+    cpumMsrRd_Ia32VmxProcbasedCtls,
+    cpumMsrRd_Ia32VmxExitCtls,
+    cpumMsrRd_Ia32VmxEntryCtls,
+    cpumMsrRd_Ia32VmxMisc,
+    cpumMsrRd_Ia32VmxCr0Fixed0,
+    cpumMsrRd_Ia32VmxCr0Fixed1,
+    cpumMsrRd_Ia32VmxCr4Fixed0,
+    cpumMsrRd_Ia32VmxCr4Fixed1,
+    cpumMsrRd_Ia32VmxVmcsEnum,
+    cpumMsrRd_Ia32VmxProcBasedCtls2,
+    cpumMsrRd_Ia32VmxEptVpidCap,
+    cpumMsrRd_Ia32VmxTruePinbasedCtls,
+    cpumMsrRd_Ia32VmxTrueProcbasedCtls,
+    cpumMsrRd_Ia32VmxTrueExitCtls,
+    cpumMsrRd_Ia32VmxTrueEntryCtls,
+
+    cpumMsrRd_Amd64Efer,
+    cpumMsrRd_Amd64SyscallTarget,
+    cpumMsrRd_Amd64LongSyscallTarget,
+    cpumMsrRd_Amd64CompSyscallTarget,
+    cpumMsrRd_Amd64SyscallFlagMask,
+    cpumMsrRd_Amd64FsBase,
+    cpumMsrRd_Amd64GsBase,
+    cpumMsrRd_Amd64KernelGsBase,
+    cpumMsrRd_Amd64TscAux,
+
+    cpumMsrRd_IntelEblCrPowerOn,
+    cpumMsrRd_IntelP4EbcHardPowerOn,
+    cpumMsrRd_IntelP4EbcSoftPowerOn,
+    cpumMsrRd_IntelP4EbcFrequencyId,
+    cpumMsrRd_IntelPlatformInfo100MHz,
+    cpumMsrRd_IntelPlatformInfo133MHz,
+    cpumMsrRd_IntelFlexRatio100MHz,
+    cpumMsrRd_IntelFlexRatio133MHz,
+    cpumMsrRd_IntelPkgCStConfigControl,
+    cpumMsrRd_IntelPmgIoCaptureBase,
+    cpumMsrRd_IntelLastBranchFromToN,
+    cpumMsrRd_IntelLastBranchFromN,
+    cpumMsrRd_IntelLastBranchToN,
+    cpumMsrRd_IntelLastBranchTos,
+    cpumMsrRd_IntelBblCrCtl,
+    cpumMsrRd_IntelBblCrCtl3,
+    cpumMsrRd_IntelI7TemperatureTarget,
+    cpumMsrRd_IntelI7MsrOffCoreResponseN,
+    cpumMsrRd_IntelI7MiscPwrMgmt,
+    cpumMsrRd_IntelP6CrN,
+    cpumMsrRd_IntelCpuId1FeatureMaskEcdx,
+    cpumMsrRd_IntelCpuId1FeatureMaskEax,
+    cpumMsrRd_IntelCpuId80000001FeatureMaskEcdx,
+    cpumMsrRd_IntelI7SandyAesNiCtl,
+    cpumMsrRd_IntelI7TurboRatioLimit,
+    cpumMsrRd_IntelI7LbrSelect,
+    cpumMsrRd_IntelI7SandyErrorControl,
+    cpumMsrRd_IntelI7VirtualLegacyWireCap,
+    cpumMsrRd_IntelI7PowerCtl,
+    cpumMsrRd_IntelI7SandyPebsNumAlt,
+    cpumMsrRd_IntelI7PebsLdLat,
+    cpumMsrRd_IntelI7PkgCnResidencyN,
+    cpumMsrRd_IntelI7CoreCnResidencyN,
+    cpumMsrRd_IntelI7SandyVrCurrentConfig,
+    cpumMsrRd_IntelI7SandyVrMiscConfig,
+    cpumMsrRd_IntelI7SandyRaplPowerUnit,
+    cpumMsrRd_IntelI7SandyPkgCnIrtlN,
+    cpumMsrRd_IntelI7SandyPkgC2Residency,
+    cpumMsrRd_IntelI7RaplPkgPowerLimit,
+    cpumMsrRd_IntelI7RaplPkgEnergyStatus,
+    cpumMsrRd_IntelI7RaplPkgPerfStatus,
+    cpumMsrRd_IntelI7RaplPkgPowerInfo,
+    cpumMsrRd_IntelI7RaplDramPowerLimit,
+    cpumMsrRd_IntelI7RaplDramEnergyStatus,
+    cpumMsrRd_IntelI7RaplDramPerfStatus,
+    cpumMsrRd_IntelI7RaplDramPowerInfo,
+    cpumMsrRd_IntelI7RaplPp0PowerLimit,
+    cpumMsrRd_IntelI7RaplPp0EnergyStatus,
+    cpumMsrRd_IntelI7RaplPp0Policy,
+    cpumMsrRd_IntelI7RaplPp0PerfStatus,
+    cpumMsrRd_IntelI7RaplPp1PowerLimit,
+    cpumMsrRd_IntelI7RaplPp1EnergyStatus,
+    cpumMsrRd_IntelI7RaplPp1Policy,
+    cpumMsrRd_IntelI7IvyConfigTdpNominal,
+    cpumMsrRd_IntelI7IvyConfigTdpLevel1,
+    cpumMsrRd_IntelI7IvyConfigTdpLevel2,
+    cpumMsrRd_IntelI7IvyConfigTdpControl,
+    cpumMsrRd_IntelI7IvyTurboActivationRatio,
+    cpumMsrRd_IntelI7UncPerfGlobalCtrl,
+    cpumMsrRd_IntelI7UncPerfGlobalStatus,
+    cpumMsrRd_IntelI7UncPerfGlobalOvfCtrl,
+    cpumMsrRd_IntelI7UncPerfFixedCtrCtrl,
+    cpumMsrRd_IntelI7UncPerfFixedCtr,
+    cpumMsrRd_IntelI7UncCBoxConfig,
+    cpumMsrRd_IntelI7UncArbPerfCtrN,
+    cpumMsrRd_IntelI7UncArbPerfEvtSelN,
+    cpumMsrRd_IntelCore2EmttmCrTablesN,
+    cpumMsrRd_IntelCore2SmmCStMiscInfo,
+    cpumMsrRd_IntelCore1ExtConfig,
+    cpumMsrRd_IntelCore1DtsCalControl,
+    cpumMsrRd_IntelCore2PeciControl,
+
+    cpumMsrRd_P6LastBranchFromIp,
+    cpumMsrRd_P6LastBranchToIp,
+    cpumMsrRd_P6LastIntFromIp,
+    cpumMsrRd_P6LastIntToIp,
+
+    cpumMsrRd_AmdFam15hTscRate,
+    cpumMsrRd_AmdFam15hLwpCfg,
+    cpumMsrRd_AmdFam15hLwpCbAddr,
+    cpumMsrRd_AmdFam10hMc4MiscN,
+    cpumMsrRd_AmdK8PerfCtlN,
+    cpumMsrRd_AmdK8PerfCtrN,
+    cpumMsrRd_AmdK8SysCfg,
+    cpumMsrRd_AmdK8HwCr,
+    cpumMsrRd_AmdK8IorrBaseN,
+    cpumMsrRd_AmdK8IorrMaskN,
+    cpumMsrRd_AmdK8TopOfMemN,
+    cpumMsrRd_AmdK8NbCfg1,
+    cpumMsrRd_AmdK8McXcptRedir,
+    cpumMsrRd_AmdK8CpuNameN,
+    cpumMsrRd_AmdK8HwThermalCtrl,
+    cpumMsrRd_AmdK8SwThermalCtrl,
+    cpumMsrRd_AmdK8FidVidControl,
+    cpumMsrRd_AmdK8FidVidStatus,
+    cpumMsrRd_AmdK8McCtlMaskN,
+    cpumMsrRd_AmdK8SmiOnIoTrapN,
+    cpumMsrRd_AmdK8SmiOnIoTrapCtlSts,
+    cpumMsrRd_AmdK8IntPendingMessage,
+    cpumMsrRd_AmdK8SmiTriggerIoCycle,
+    cpumMsrRd_AmdFam10hMmioCfgBaseAddr,
+    cpumMsrRd_AmdFam10hTrapCtlMaybe,
+    cpumMsrRd_AmdFam10hPStateCurLimit,
+    cpumMsrRd_AmdFam10hPStateControl,
+    cpumMsrRd_AmdFam10hPStateStatus,
+    cpumMsrRd_AmdFam10hPStateN,
+    cpumMsrRd_AmdFam10hCofVidControl,
+    cpumMsrRd_AmdFam10hCofVidStatus,
+    cpumMsrRd_AmdFam10hCStateIoBaseAddr,
+    cpumMsrRd_AmdFam10hCpuWatchdogTimer,
+    cpumMsrRd_AmdK8SmmBase,
+    cpumMsrRd_AmdK8SmmAddr,
+    cpumMsrRd_AmdK8SmmMask,
+    cpumMsrRd_AmdK8VmCr,
+    cpumMsrRd_AmdK8IgnNe,
+    cpumMsrRd_AmdK8SmmCtl,
+    cpumMsrRd_AmdK8VmHSavePa,
+    cpumMsrRd_AmdFam10hVmLockKey,
+    cpumMsrRd_AmdFam10hSmmLockKey,
+    cpumMsrRd_AmdFam10hLocalSmiStatus,
+    cpumMsrRd_AmdFam10hOsVisWrkIdLength,
+    cpumMsrRd_AmdFam10hOsVisWrkStatus,
+    cpumMsrRd_AmdFam16hL2IPerfCtlN,
+    cpumMsrRd_AmdFam16hL2IPerfCtrN,
+    cpumMsrRd_AmdFam15hNorthbridgePerfCtlN,
+    cpumMsrRd_AmdFam15hNorthbridgePerfCtrN,
+    cpumMsrRd_AmdK7MicrocodeCtl,
+    cpumMsrRd_AmdK7ClusterIdMaybe,
+    cpumMsrRd_AmdK8CpuIdCtlStd07hEbax,
+    cpumMsrRd_AmdK8CpuIdCtlStd06hEcx,
+    cpumMsrRd_AmdK8CpuIdCtlStd01hEdcx,
+    cpumMsrRd_AmdK8CpuIdCtlExt01hEdcx,
+    cpumMsrRd_AmdK8PatchLevel,
+    cpumMsrRd_AmdK7DebugStatusMaybe,
+    cpumMsrRd_AmdK7BHTraceBaseMaybe,
+    cpumMsrRd_AmdK7BHTracePtrMaybe,
+    cpumMsrRd_AmdK7BHTraceLimitMaybe,
+    cpumMsrRd_AmdK7HardwareDebugToolCfgMaybe,
+    cpumMsrRd_AmdK7FastFlushCountMaybe,
+    cpumMsrRd_AmdK7NodeId,
+    cpumMsrRd_AmdK7DrXAddrMaskN,
+    cpumMsrRd_AmdK7Dr0DataMatchMaybe,
+    cpumMsrRd_AmdK7Dr0DataMaskMaybe,
+    cpumMsrRd_AmdK7LoadStoreCfg,
+    cpumMsrRd_AmdK7InstrCacheCfg,
+    cpumMsrRd_AmdK7DataCacheCfg,
+    cpumMsrRd_AmdK7BusUnitCfg,
+    cpumMsrRd_AmdK7DebugCtl2Maybe,
+    cpumMsrRd_AmdFam15hFpuCfg,
+    cpumMsrRd_AmdFam15hDecoderCfg,
+    cpumMsrRd_AmdFam10hBusUnitCfg2,
+    cpumMsrRd_AmdFam15hCombUnitCfg,
+    cpumMsrRd_AmdFam15hCombUnitCfg2,
+    cpumMsrRd_AmdFam15hCombUnitCfg3,
+    cpumMsrRd_AmdFam15hExecUnitCfg,
+    cpumMsrRd_AmdFam15hLoadStoreCfg2,
+    cpumMsrRd_AmdFam10hIbsFetchCtl,
+    cpumMsrRd_AmdFam10hIbsFetchLinAddr,
+    cpumMsrRd_AmdFam10hIbsFetchPhysAddr,
+    cpumMsrRd_AmdFam10hIbsOpExecCtl,
+    cpumMsrRd_AmdFam10hIbsOpRip,
+    cpumMsrRd_AmdFam10hIbsOpData,
+    cpumMsrRd_AmdFam10hIbsOpData2,
+    cpumMsrRd_AmdFam10hIbsOpData3,
+    cpumMsrRd_AmdFam10hIbsDcLinAddr,
+    cpumMsrRd_AmdFam10hIbsDcPhysAddr,
+    cpumMsrRd_AmdFam10hIbsCtl,
+    cpumMsrRd_AmdFam14hIbsBrTarget,
+};
+
+
+/**
+ * MSR write function table.
+ */
+static const PFNCPUMWRMSR g_aCpumWrMsrFns[kCpumMsrWrFn_End] =
+{
+    NULL, /* Invalid */
+    cpumMsrWr_IgnoreWrite,
+    cpumMsrWr_ReadOnly,
+    NULL, /* Alias */
+    cpumMsrWr_Ia32P5McAddr,
+    cpumMsrWr_Ia32P5McType,
+    cpumMsrWr_Ia32TimestampCounter,
+    cpumMsrWr_Ia32ApicBase,
+    cpumMsrWr_Ia32FeatureControl,
+    cpumMsrWr_Ia32BiosSignId,
+    cpumMsrWr_Ia32BiosUpdateTrigger,
+    cpumMsrWr_Ia32SmmMonitorCtl,
+    cpumMsrWr_Ia32PmcN,
+    cpumMsrWr_Ia32MonitorFilterLineSize,
+    cpumMsrWr_Ia32MPerf,
+    cpumMsrWr_Ia32APerf,
+    cpumMsrWr_Ia32MtrrPhysBaseN,
+    cpumMsrWr_Ia32MtrrPhysMaskN,
+    cpumMsrWr_Ia32MtrrFixed,
+    cpumMsrWr_Ia32MtrrDefType,
+    cpumMsrWr_Ia32Pat,
+    cpumMsrWr_Ia32SysEnterCs,
+    cpumMsrWr_Ia32SysEnterEsp,
+    cpumMsrWr_Ia32SysEnterEip,
+    cpumMsrWr_Ia32McgStatus,
+    cpumMsrWr_Ia32McgCtl,
+    cpumMsrWr_Ia32DebugCtl,
+    cpumMsrWr_Ia32SmrrPhysBase,
+    cpumMsrWr_Ia32SmrrPhysMask,
+    cpumMsrWr_Ia32PlatformDcaCap,
+    cpumMsrWr_Ia32Dca0Cap,
+    cpumMsrWr_Ia32PerfEvtSelN,
+    cpumMsrWr_Ia32PerfStatus,
+    cpumMsrWr_Ia32PerfCtl,
+    cpumMsrWr_Ia32FixedCtrN,
+    cpumMsrWr_Ia32PerfCapabilities,
+    cpumMsrWr_Ia32FixedCtrCtrl,
+    cpumMsrWr_Ia32PerfGlobalStatus,
+    cpumMsrWr_Ia32PerfGlobalCtrl,
+    cpumMsrWr_Ia32PerfGlobalOvfCtrl,
+    cpumMsrWr_Ia32PebsEnable,
+    cpumMsrWr_Ia32ClockModulation,
+    cpumMsrWr_Ia32ThermInterrupt,
+    cpumMsrWr_Ia32ThermStatus,
+    cpumMsrWr_Ia32Therm2Ctl,
+    cpumMsrWr_Ia32MiscEnable,
+    cpumMsrWr_Ia32McCtlStatusAddrMiscN,
+    cpumMsrWr_Ia32McNCtl2,
+    cpumMsrWr_Ia32DsArea,
+    cpumMsrWr_Ia32TscDeadline,
+    cpumMsrWr_Ia32X2ApicN,
+    cpumMsrWr_Ia32DebugInterface,
+
+    cpumMsrWr_Amd64Efer,
+    cpumMsrWr_Amd64SyscallTarget,
+    cpumMsrWr_Amd64LongSyscallTarget,
+    cpumMsrWr_Amd64CompSyscallTarget,
+    cpumMsrWr_Amd64SyscallFlagMask,
+    cpumMsrWr_Amd64FsBase,
+    cpumMsrWr_Amd64GsBase,
+    cpumMsrWr_Amd64KernelGsBase,
+    cpumMsrWr_Amd64TscAux,
+
+    cpumMsrWr_IntelEblCrPowerOn,
+    cpumMsrWr_IntelP4EbcHardPowerOn,
+    cpumMsrWr_IntelP4EbcSoftPowerOn,
+    cpumMsrWr_IntelP4EbcFrequencyId,
+    cpumMsrWr_IntelFlexRatio100MHz,
+    cpumMsrWr_IntelFlexRatio133MHz,
+    cpumMsrWr_IntelPkgCStConfigControl,
+    cpumMsrWr_IntelPmgIoCaptureBase,
+    cpumMsrWr_IntelLastBranchFromToN,
+    cpumMsrWr_IntelLastBranchFromN,
+    cpumMsrWr_IntelLastBranchToN,
+    cpumMsrWr_IntelLastBranchTos,
+    cpumMsrWr_IntelBblCrCtl,
+    cpumMsrWr_IntelBblCrCtl3,
+    cpumMsrWr_IntelI7TemperatureTarget,
+    cpumMsrWr_IntelI7MsrOffCoreResponseN,
+    cpumMsrWr_IntelI7MiscPwrMgmt,
+    cpumMsrWr_IntelP6CrN,
+    cpumMsrWr_IntelCpuId1FeatureMaskEcdx,
+    cpumMsrWr_IntelCpuId1FeatureMaskEax,
+    cpumMsrWr_IntelCpuId80000001FeatureMaskEcdx,
+    cpumMsrWr_IntelI7SandyAesNiCtl,
+    cpumMsrWr_IntelI7TurboRatioLimit,
+    cpumMsrWr_IntelI7LbrSelect,
+    cpumMsrWr_IntelI7SandyErrorControl,
+    cpumMsrWr_IntelI7PowerCtl,
+    cpumMsrWr_IntelI7SandyPebsNumAlt,
+    cpumMsrWr_IntelI7PebsLdLat,
+    cpumMsrWr_IntelI7SandyVrCurrentConfig,
+    cpumMsrWr_IntelI7SandyVrMiscConfig,
+    cpumMsrWr_IntelI7SandyPkgCnIrtlN,
+    cpumMsrWr_IntelI7RaplPkgPowerLimit,
+    cpumMsrWr_IntelI7RaplDramPowerLimit,
+    cpumMsrWr_IntelI7RaplPp0PowerLimit,
+    cpumMsrWr_IntelI7RaplPp0Policy,
+    cpumMsrWr_IntelI7RaplPp1PowerLimit,
+    cpumMsrWr_IntelI7RaplPp1Policy,
+    cpumMsrWr_IntelI7IvyConfigTdpControl,
+    cpumMsrWr_IntelI7IvyTurboActivationRatio,
+    cpumMsrWr_IntelI7UncPerfGlobalCtrl,
+    cpumMsrWr_IntelI7UncPerfGlobalStatus,
+    cpumMsrWr_IntelI7UncPerfGlobalOvfCtrl,
+    cpumMsrWr_IntelI7UncPerfFixedCtrCtrl,
+    cpumMsrWr_IntelI7UncPerfFixedCtr,
+    cpumMsrWr_IntelI7UncArbPerfCtrN,
+    cpumMsrWr_IntelI7UncArbPerfEvtSelN,
+    cpumMsrWr_IntelCore2EmttmCrTablesN,
+    cpumMsrWr_IntelCore2SmmCStMiscInfo,
+    cpumMsrWr_IntelCore1ExtConfig,
+    cpumMsrWr_IntelCore1DtsCalControl,
+    cpumMsrWr_IntelCore2PeciControl,
+
+    cpumMsrWr_P6LastIntFromIp,
+    cpumMsrWr_P6LastIntToIp,
+
+    cpumMsrWr_AmdFam15hTscRate,
+    cpumMsrWr_AmdFam15hLwpCfg,
+    cpumMsrWr_AmdFam15hLwpCbAddr,
+    cpumMsrWr_AmdFam10hMc4MiscN,
+    cpumMsrWr_AmdK8PerfCtlN,
+    cpumMsrWr_AmdK8PerfCtrN,
+    cpumMsrWr_AmdK8SysCfg,
+    cpumMsrWr_AmdK8HwCr,
+    cpumMsrWr_AmdK8IorrBaseN,
+    cpumMsrWr_AmdK8IorrMaskN,
+    cpumMsrWr_AmdK8TopOfMemN,
+    cpumMsrWr_AmdK8NbCfg1,
+    cpumMsrWr_AmdK8McXcptRedir,
+    cpumMsrWr_AmdK8CpuNameN,
+    cpumMsrWr_AmdK8HwThermalCtrl,
+    cpumMsrWr_AmdK8SwThermalCtrl,
+    cpumMsrWr_AmdK8FidVidControl,
+    cpumMsrWr_AmdK8McCtlMaskN,
+    cpumMsrWr_AmdK8SmiOnIoTrapN,
+    cpumMsrWr_AmdK8SmiOnIoTrapCtlSts,
+    cpumMsrWr_AmdK8IntPendingMessage,
+    cpumMsrWr_AmdK8SmiTriggerIoCycle,
+    cpumMsrWr_AmdFam10hMmioCfgBaseAddr,
+    cpumMsrWr_AmdFam10hTrapCtlMaybe,
+    cpumMsrWr_AmdFam10hPStateControl,
+    cpumMsrWr_AmdFam10hPStateStatus,
+    cpumMsrWr_AmdFam10hPStateN,
+    cpumMsrWr_AmdFam10hCofVidControl,
+    cpumMsrWr_AmdFam10hCofVidStatus,
+    cpumMsrWr_AmdFam10hCStateIoBaseAddr,
+    cpumMsrWr_AmdFam10hCpuWatchdogTimer,
+    cpumMsrWr_AmdK8SmmBase,
+    cpumMsrWr_AmdK8SmmAddr,
+    cpumMsrWr_AmdK8SmmMask,
+    cpumMsrWr_AmdK8VmCr,
+    cpumMsrWr_AmdK8IgnNe,
+    cpumMsrWr_AmdK8SmmCtl,
+    cpumMsrWr_AmdK8VmHSavePa,
+    cpumMsrWr_AmdFam10hVmLockKey,
+    cpumMsrWr_AmdFam10hSmmLockKey,
+    cpumMsrWr_AmdFam10hLocalSmiStatus,
+    cpumMsrWr_AmdFam10hOsVisWrkIdLength,
+    cpumMsrWr_AmdFam10hOsVisWrkStatus,
+    cpumMsrWr_AmdFam16hL2IPerfCtlN,
+    cpumMsrWr_AmdFam16hL2IPerfCtrN,
+    cpumMsrWr_AmdFam15hNorthbridgePerfCtlN,
+    cpumMsrWr_AmdFam15hNorthbridgePerfCtrN,
+    cpumMsrWr_AmdK7MicrocodeCtl,
+    cpumMsrWr_AmdK7ClusterIdMaybe,
+    cpumMsrWr_AmdK8CpuIdCtlStd07hEbax,
+    cpumMsrWr_AmdK8CpuIdCtlStd06hEcx,
+    cpumMsrWr_AmdK8CpuIdCtlStd01hEdcx,
+    cpumMsrWr_AmdK8CpuIdCtlExt01hEdcx,
+    cpumMsrWr_AmdK8PatchLoader,
+    cpumMsrWr_AmdK7DebugStatusMaybe,
+    cpumMsrWr_AmdK7BHTraceBaseMaybe,
+    cpumMsrWr_AmdK7BHTracePtrMaybe,
+    cpumMsrWr_AmdK7BHTraceLimitMaybe,
+    cpumMsrWr_AmdK7HardwareDebugToolCfgMaybe,
+    cpumMsrWr_AmdK7FastFlushCountMaybe,
+    cpumMsrWr_AmdK7NodeId,
+    cpumMsrWr_AmdK7DrXAddrMaskN,
+    cpumMsrWr_AmdK7Dr0DataMatchMaybe,
+    cpumMsrWr_AmdK7Dr0DataMaskMaybe,
+    cpumMsrWr_AmdK7LoadStoreCfg,
+    cpumMsrWr_AmdK7InstrCacheCfg,
+    cpumMsrWr_AmdK7DataCacheCfg,
+    cpumMsrWr_AmdK7BusUnitCfg,
+    cpumMsrWr_AmdK7DebugCtl2Maybe,
+    cpumMsrWr_AmdFam15hFpuCfg,
+    cpumMsrWr_AmdFam15hDecoderCfg,
+    cpumMsrWr_AmdFam10hBusUnitCfg2,
+    cpumMsrWr_AmdFam15hCombUnitCfg,
+    cpumMsrWr_AmdFam15hCombUnitCfg2,
+    cpumMsrWr_AmdFam15hCombUnitCfg3,
+    cpumMsrWr_AmdFam15hExecUnitCfg,
+    cpumMsrWr_AmdFam15hLoadStoreCfg2,
+    cpumMsrWr_AmdFam10hIbsFetchCtl,
+    cpumMsrWr_AmdFam10hIbsFetchLinAddr,
+    cpumMsrWr_AmdFam10hIbsFetchPhysAddr,
+    cpumMsrWr_AmdFam10hIbsOpExecCtl,
+    cpumMsrWr_AmdFam10hIbsOpRip,
+    cpumMsrWr_AmdFam10hIbsOpData,
+    cpumMsrWr_AmdFam10hIbsOpData2,
+    cpumMsrWr_AmdFam10hIbsOpData3,
+    cpumMsrWr_AmdFam10hIbsDcLinAddr,
+    cpumMsrWr_AmdFam10hIbsDcPhysAddr,
+    cpumMsrWr_AmdFam10hIbsCtl,
+    cpumMsrWr_AmdFam14hIbsBrTarget,
+};
+
+
+/**
+ * Looks up the range for the given MSR.
+ *
+ * @returns Pointer to the range if found, NULL if not.
+ * @param   pVM                 The cross context VM structure.
+ * @param   idMsr               The MSR to look up.
+ */
+# ifndef IN_RING3
+static
+# endif
+PCPUMMSRRANGE cpumLookupMsrRange(PVM pVM, uint32_t idMsr)
+{
+    /*
+     * Binary lookup.
+     */
+    uint32_t        cRanges   = pVM->cpum.s.GuestInfo.cMsrRanges;
+    if (!cRanges)
+        return NULL;
+    PCPUMMSRRANGE   paRanges  = pVM->cpum.s.GuestInfo.CTX_SUFF(paMsrRanges);
+    for (;;)
+    {
+        uint32_t i = cRanges / 2;
+        if (idMsr < paRanges[i].uFirst)
+        {
+            if (i == 0)
+                break;
+            cRanges = i;
+        }
+        else if (idMsr > paRanges[i].uLast)
+        {
+            i++;
+            if (i >= cRanges)
+                break;
+            cRanges -= i;
+            paRanges = &paRanges[i];
+        }
+        else
+        {
+            if (paRanges[i].enmRdFn == kCpumMsrRdFn_MsrAlias)
+                return cpumLookupMsrRange(pVM, paRanges[i].uValue);
+            return &paRanges[i];
+        }
+    }
+
+# ifdef VBOX_STRICT
+    /*
+     * Linear lookup to verify the above binary search.
+     */
+    uint32_t        cLeft = pVM->cpum.s.GuestInfo.cMsrRanges;
+    PCPUMMSRRANGE   pCur  = pVM->cpum.s.GuestInfo.CTX_SUFF(paMsrRanges);
+    while (cLeft-- > 0)
+    {
+        if (idMsr >= pCur->uFirst && idMsr <= pCur->uLast)
+        {
+            AssertFailed();
+            if (pCur->enmRdFn == kCpumMsrRdFn_MsrAlias)
+                return cpumLookupMsrRange(pVM, pCur->uValue);
+            return pCur;
+        }
+        pCur++;
+    }
+# endif
+    return NULL;
+}
+
+#ifdef VBOX_WITH_NEW_MSR_CODE
+
+/**
+ * Query a guest MSR.
+ *
+ * The caller is responsible for checking privilege if the call is the result of
+ * a RDMSR instruction.  We'll do the rest.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_CPUM_RAISE_GP_0 on failure (invalid MSR), the caller is
+ *          expected to take the appropriate actions. @a *puValue is set to 0.
+ * @param   pVCpu               Pointer to the VMCPU.
+ * @param   idMsr               The MSR.
+ * @param   puValue             Where to return the value.
+ *
+ * @remarks This will always return the right values, even when we're in the
+ *          recompiler.
+ */
+VMMDECL(int) CPUMQueryGuestMsr(PVMCPU pVCpu, uint32_t idMsr, uint64_t *puValue)
+{
+    *puValue = 0;
+
+    int             rc;
+    PVM             pVM    = pVCpu->CTX_SUFF(pVM);
+    PCPUMMSRRANGE   pRange = cpumLookupMsrRange(pVM, idMsr);
+    if (pRange)
+    {
+        CPUMMSRRDFN  enmRdFn = (CPUMMSRRDFN)pRange->enmRdFn;
+        AssertReturn(enmRdFn > kCpumMsrRdFn_Invalid && enmRdFn < kCpumMsrRdFn_End, VERR_CPUM_IPE_1);
+
+        PFNCPUMRDMSR pfnRdMsr = g_aCpumRdMsrFns[enmRdFn];
+        AssertReturn(pfnRdMsr, VERR_CPUM_IPE_2);
+
+        STAM_COUNTER_INC(&pRange->cReads);
+        STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReads);
+
+        rc = pfnRdMsr(pVCpu, idMsr, pRange, puValue);
+        if (RT_SUCCESS(rc))
+        {
+            Log2(("CPUM: RDMSR %#x (%s) -> %#llx\n", idMsr, pRange->szName, *puValue));
+            AssertMsg(rc == VINF_SUCCESS, ("%Rrc idMsr=%#x\n", rc, idMsr));
+        }
+        else if (rc == VERR_CPUM_RAISE_GP_0)
+        {
+            Log(("CPUM: RDMSR %#x (%s) -> #GP(0)\n", idMsr, pRange->szName));
+            STAM_COUNTER_INC(&pRange->cGps);
+            STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReadsRaiseGp);
+        }
+        else
+            Log(("CPUM: RDMSR %#x (%s) -> rc=%Rrc\n", idMsr, pRange->szName, rc));
+    }
+    else
+    {
+        Log(("CPUM: Unknown RDMSR %#x -> #GP(0)\n", idMsr));
+        STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReads);
+        STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReadsUnknown);
+        rc = VERR_CPUM_RAISE_GP_0;
+    }
+    return rc;
+}
+
+
+/**
+ * Writes to a guest MSR.
+ *
+ * The caller is responsible for checking privilege if the call is the result of
+ * a WRMSR instruction.  We'll do the rest.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_CPUM_RAISE_GP_0 on failure, the caller is expected to take the
+ *          appropriate actions.
+ *
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR id.
+ * @param   uValue      The value to set.
+ *
+ * @remarks Everyone changing MSR values, including the recompiler, shall do it
+ *          by calling this method.  This makes sure we have current values and
+ *          that we trigger all the right actions when something changes.
+ *
+ *          For performance reasons, this actually isn't entirely true for some
+ *          MSRs when in HM mode.  The code here and in HM must be aware of
+ *          this.
+ */
+VMMDECL(int) CPUMSetGuestMsr(PVMCPU pVCpu, uint32_t idMsr, uint64_t uValue)
+{
+    int             rc;
+    PVM             pVM    = pVCpu->CTX_SUFF(pVM);
+    PCPUMMSRRANGE   pRange = cpumLookupMsrRange(pVM, idMsr);
+    if (pRange)
+    {
+        STAM_COUNTER_INC(&pRange->cWrites);
+        STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrWrites);
+
+        if (!(uValue & pRange->fWrGpMask))
+        {
+            CPUMMSRWRFN  enmWrFn = (CPUMMSRWRFN)pRange->enmWrFn;
+            AssertReturn(enmWrFn > kCpumMsrWrFn_Invalid && enmWrFn < kCpumMsrWrFn_End, VERR_CPUM_IPE_1);
+
+            PFNCPUMWRMSR pfnWrMsr = g_aCpumWrMsrFns[enmWrFn];
+            AssertReturn(pfnWrMsr, VERR_CPUM_IPE_2);
+
+            uint64_t uValueAdjusted = uValue & ~pRange->fWrIgnMask;
+            if (uValueAdjusted != uValue)
+            {
+                STAM_COUNTER_INC(&pRange->cIgnoredBits);
+                STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrWritesToIgnoredBits);
+            }
+
+            rc = pfnWrMsr(pVCpu, idMsr, pRange, uValueAdjusted, uValue);
+            if (RT_SUCCESS(rc))
+            {
+                Log2(("CPUM: WRMSR %#x (%s), %#llx [%#llx]\n", idMsr, pRange->szName, uValueAdjusted, uValue));
+                AssertMsg(rc == VINF_SUCCESS, ("%Rrc idMsr=%#x\n", rc, idMsr));
+            }
+            else if (rc == VERR_CPUM_RAISE_GP_0)
+            {
+                Log(("CPUM: WRMSR %#x (%s), %#llx [%#llx] -> #GP(0)\n", idMsr, pRange->szName, uValueAdjusted, uValue));
+                STAM_COUNTER_INC(&pRange->cGps);
+                STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrWritesRaiseGp);
+            }
+            else
+                Log(("CPUM: WRMSR %#x (%s), %#llx [%#llx] -> rc=%Rrc\n", idMsr, pRange->szName, uValueAdjusted, uValue, rc));
+        }
+        else
+        {
+            Log(("CPUM: WRMSR %#x (%s), %#llx -> #GP(0) - invalid bits %#llx\n",
+                 idMsr, pRange->szName, uValue, uValue & pRange->fWrGpMask));
+            STAM_COUNTER_INC(&pRange->cGps);
+            STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrWritesRaiseGp);
+            rc = VERR_CPUM_RAISE_GP_0;
+        }
+    }
+    else
+    {
+        Log(("CPUM: Unknown WRMSR %#x, %#llx -> #GP(0)\n", idMsr, uValue));
+        STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrWrites);
+        STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrWritesUnknown);
+        rc = VERR_CPUM_RAISE_GP_0;
+    }
+    return rc;
+}
+
+#endif /* VBOX_WITH_NEW_MSR_CODE */
+
+
+#if defined(VBOX_STRICT) && defined(IN_RING3)
+/**
+ * Performs some checks on the static data related to MSRs.
+ *
+ * @returns VINF_SUCCESS on success, error on failure.
+ */
+int cpumR3MsrStrictInitChecks(void)
+{
+#define CPUM_ASSERT_RD_MSR_FN(a_Register) \
+        AssertReturn(g_aCpumRdMsrFns[kCpumMsrRdFn_##a_Register] == cpumMsrRd_##a_Register, VERR_CPUM_IPE_2);
+#define CPUM_ASSERT_WR_MSR_FN(a_Register) \
+        AssertReturn(g_aCpumWrMsrFns[kCpumMsrWrFn_##a_Register] == cpumMsrWr_##a_Register, VERR_CPUM_IPE_2);
+
+    AssertReturn(g_aCpumRdMsrFns[kCpumMsrRdFn_Invalid] == NULL, VERR_CPUM_IPE_2);
+    CPUM_ASSERT_RD_MSR_FN(FixedValue);
+    CPUM_ASSERT_RD_MSR_FN(WriteOnly);
+    CPUM_ASSERT_RD_MSR_FN(Ia32P5McAddr);
+    CPUM_ASSERT_RD_MSR_FN(Ia32P5McType);
+    CPUM_ASSERT_RD_MSR_FN(Ia32TimestampCounter);
+    CPUM_ASSERT_RD_MSR_FN(Ia32ApicBase);
+    CPUM_ASSERT_RD_MSR_FN(Ia32FeatureControl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32BiosSignId);
+    CPUM_ASSERT_RD_MSR_FN(Ia32SmmMonitorCtl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PmcN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MonitorFilterLineSize);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MPerf);
+    CPUM_ASSERT_RD_MSR_FN(Ia32APerf);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MtrrCap);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MtrrPhysBaseN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MtrrPhysMaskN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MtrrFixed);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MtrrDefType);
+    CPUM_ASSERT_RD_MSR_FN(Ia32Pat);
+    CPUM_ASSERT_RD_MSR_FN(Ia32SysEnterCs);
+    CPUM_ASSERT_RD_MSR_FN(Ia32SysEnterEsp);
+    CPUM_ASSERT_RD_MSR_FN(Ia32SysEnterEip);
+    CPUM_ASSERT_RD_MSR_FN(Ia32McgCap);
+    CPUM_ASSERT_RD_MSR_FN(Ia32McgStatus);
+    CPUM_ASSERT_RD_MSR_FN(Ia32McgCtl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32DebugCtl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32SmrrPhysBase);
+    CPUM_ASSERT_RD_MSR_FN(Ia32SmrrPhysMask);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PlatformDcaCap);
+    CPUM_ASSERT_RD_MSR_FN(Ia32CpuDcaCap);
+    CPUM_ASSERT_RD_MSR_FN(Ia32Dca0Cap);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfEvtSelN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfStatus);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfCtl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32FixedCtrN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfCapabilities);
+    CPUM_ASSERT_RD_MSR_FN(Ia32FixedCtrCtrl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfGlobalStatus);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfGlobalCtrl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PerfGlobalOvfCtrl);
+    CPUM_ASSERT_RD_MSR_FN(Ia32PebsEnable);
+    CPUM_ASSERT_RD_MSR_FN(Ia32ClockModulation);
+    CPUM_ASSERT_RD_MSR_FN(Ia32ThermInterrupt);
+    CPUM_ASSERT_RD_MSR_FN(Ia32ThermStatus);
+    CPUM_ASSERT_RD_MSR_FN(Ia32MiscEnable);
+    CPUM_ASSERT_RD_MSR_FN(Ia32McCtlStatusAddrMiscN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32McNCtl2);
+    CPUM_ASSERT_RD_MSR_FN(Ia32DsArea);
+    CPUM_ASSERT_RD_MSR_FN(Ia32TscDeadline);
+    CPUM_ASSERT_RD_MSR_FN(Ia32X2ApicN);
+    CPUM_ASSERT_RD_MSR_FN(Ia32DebugInterface);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxBase);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxPinbasedCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxProcbasedCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxExitCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxEntryCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxMisc);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxCr0Fixed0);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxCr0Fixed1);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxCr4Fixed0);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxCr4Fixed1);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxVmcsEnum);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxProcBasedCtls2);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxEptVpidCap);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxTruePinbasedCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxTrueProcbasedCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxTrueExitCtls);
+    CPUM_ASSERT_RD_MSR_FN(Ia32VmxTrueEntryCtls);
+
+    CPUM_ASSERT_RD_MSR_FN(Amd64Efer);
+    CPUM_ASSERT_RD_MSR_FN(Amd64SyscallTarget);
+    CPUM_ASSERT_RD_MSR_FN(Amd64LongSyscallTarget);
+    CPUM_ASSERT_RD_MSR_FN(Amd64CompSyscallTarget);
+    CPUM_ASSERT_RD_MSR_FN(Amd64SyscallFlagMask);
+    CPUM_ASSERT_RD_MSR_FN(Amd64FsBase);
+    CPUM_ASSERT_RD_MSR_FN(Amd64GsBase);
+    CPUM_ASSERT_RD_MSR_FN(Amd64KernelGsBase);
+    CPUM_ASSERT_RD_MSR_FN(Amd64TscAux);
+
+    CPUM_ASSERT_RD_MSR_FN(IntelEblCrPowerOn);
+    CPUM_ASSERT_RD_MSR_FN(IntelP4EbcHardPowerOn);
+    CPUM_ASSERT_RD_MSR_FN(IntelP4EbcSoftPowerOn);
+    CPUM_ASSERT_RD_MSR_FN(IntelP4EbcFrequencyId);
+    CPUM_ASSERT_RD_MSR_FN(IntelPlatformInfo100MHz);
+    CPUM_ASSERT_RD_MSR_FN(IntelPlatformInfo133MHz);
+    CPUM_ASSERT_RD_MSR_FN(IntelFlexRatio100MHz);
+    CPUM_ASSERT_RD_MSR_FN(IntelFlexRatio133MHz);
+    CPUM_ASSERT_RD_MSR_FN(IntelPkgCStConfigControl);
+    CPUM_ASSERT_RD_MSR_FN(IntelPmgIoCaptureBase);
+    CPUM_ASSERT_RD_MSR_FN(IntelLastBranchFromToN);
+    CPUM_ASSERT_RD_MSR_FN(IntelLastBranchFromN);
+    CPUM_ASSERT_RD_MSR_FN(IntelLastBranchToN);
+    CPUM_ASSERT_RD_MSR_FN(IntelLastBranchTos);
+    CPUM_ASSERT_RD_MSR_FN(IntelBblCrCtl);
+    CPUM_ASSERT_RD_MSR_FN(IntelBblCrCtl3);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7TemperatureTarget);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7MsrOffCoreResponseN);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7MiscPwrMgmt);
+    CPUM_ASSERT_RD_MSR_FN(IntelP6CrN);
+    CPUM_ASSERT_RD_MSR_FN(IntelCpuId1FeatureMaskEcdx);
+    CPUM_ASSERT_RD_MSR_FN(IntelCpuId1FeatureMaskEax);
+    CPUM_ASSERT_RD_MSR_FN(IntelCpuId80000001FeatureMaskEcdx);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyAesNiCtl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7TurboRatioLimit);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7LbrSelect);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyErrorControl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7VirtualLegacyWireCap);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7PowerCtl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyPebsNumAlt);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7PebsLdLat);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7PkgCnResidencyN);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7CoreCnResidencyN);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyVrCurrentConfig);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyVrMiscConfig);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyRaplPowerUnit);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyPkgCnIrtlN);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7SandyPkgC2Residency);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPkgPowerLimit);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPkgEnergyStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPkgPerfStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPkgPowerInfo);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplDramPowerLimit);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplDramEnergyStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplDramPerfStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplDramPowerInfo);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp0PowerLimit);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp0EnergyStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp0Policy);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp0PerfStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp1PowerLimit);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp1EnergyStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7RaplPp1Policy);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7IvyConfigTdpNominal);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7IvyConfigTdpLevel1);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7IvyConfigTdpLevel2);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7IvyConfigTdpControl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7IvyTurboActivationRatio);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncPerfGlobalCtrl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncPerfGlobalStatus);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncPerfGlobalOvfCtrl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncPerfFixedCtrCtrl);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncPerfFixedCtr);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncCBoxConfig);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncArbPerfCtrN);
+    CPUM_ASSERT_RD_MSR_FN(IntelI7UncArbPerfEvtSelN);
+    CPUM_ASSERT_RD_MSR_FN(IntelCore2EmttmCrTablesN);
+    CPUM_ASSERT_RD_MSR_FN(IntelCore2SmmCStMiscInfo);
+    CPUM_ASSERT_RD_MSR_FN(IntelCore1ExtConfig);
+    CPUM_ASSERT_RD_MSR_FN(IntelCore1DtsCalControl);
+    CPUM_ASSERT_RD_MSR_FN(IntelCore2PeciControl);
+
+    CPUM_ASSERT_RD_MSR_FN(P6LastBranchFromIp);
+    CPUM_ASSERT_RD_MSR_FN(P6LastBranchToIp);
+    CPUM_ASSERT_RD_MSR_FN(P6LastIntFromIp);
+    CPUM_ASSERT_RD_MSR_FN(P6LastIntToIp);
+
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hTscRate);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hLwpCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hLwpCbAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hMc4MiscN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8PerfCtlN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8PerfCtrN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SysCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8HwCr);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8IorrBaseN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8IorrMaskN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8TopOfMemN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8NbCfg1);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8McXcptRedir);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8CpuNameN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8HwThermalCtrl);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SwThermalCtrl);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8FidVidControl);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8FidVidStatus);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8McCtlMaskN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmiOnIoTrapN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmiOnIoTrapCtlSts);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8IntPendingMessage);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmiTriggerIoCycle);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hMmioCfgBaseAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hTrapCtlMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hPStateCurLimit);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hPStateControl);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hPStateStatus);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hPStateN);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hCofVidControl);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hCofVidStatus);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hCStateIoBaseAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hCpuWatchdogTimer);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmmBase);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmmAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmmMask);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8VmCr);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8IgnNe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8SmmCtl);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8VmHSavePa);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hVmLockKey);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hSmmLockKey);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hLocalSmiStatus);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hOsVisWrkIdLength);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hOsVisWrkStatus);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam16hL2IPerfCtlN);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam16hL2IPerfCtrN);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hNorthbridgePerfCtlN);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hNorthbridgePerfCtrN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7MicrocodeCtl);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7ClusterIdMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8CpuIdCtlStd07hEbax);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8CpuIdCtlStd06hEcx);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8CpuIdCtlStd01hEdcx);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8CpuIdCtlExt01hEdcx);
+    CPUM_ASSERT_RD_MSR_FN(AmdK8PatchLevel);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7DebugStatusMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7BHTraceBaseMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7BHTracePtrMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7BHTraceLimitMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7HardwareDebugToolCfgMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7FastFlushCountMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7NodeId);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7DrXAddrMaskN);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7Dr0DataMatchMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7Dr0DataMaskMaybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7LoadStoreCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7InstrCacheCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7DataCacheCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7BusUnitCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdK7DebugCtl2Maybe);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hFpuCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hDecoderCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hBusUnitCfg2);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hCombUnitCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hCombUnitCfg2);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hCombUnitCfg3);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hExecUnitCfg);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam15hLoadStoreCfg2);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsFetchCtl);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsFetchLinAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsFetchPhysAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsOpExecCtl);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsOpRip);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsOpData);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsOpData2);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsOpData3);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsDcLinAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsDcPhysAddr);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam10hIbsCtl);
+    CPUM_ASSERT_RD_MSR_FN(AmdFam14hIbsBrTarget);
+
+    AssertReturn(g_aCpumWrMsrFns[kCpumMsrWrFn_Invalid] == NULL, VERR_CPUM_IPE_2);
+    CPUM_ASSERT_WR_MSR_FN(Ia32P5McAddr);
+    CPUM_ASSERT_WR_MSR_FN(Ia32P5McType);
+    CPUM_ASSERT_WR_MSR_FN(Ia32TimestampCounter);
+    CPUM_ASSERT_WR_MSR_FN(Ia32ApicBase);
+    CPUM_ASSERT_WR_MSR_FN(Ia32FeatureControl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32BiosSignId);
+    CPUM_ASSERT_WR_MSR_FN(Ia32BiosUpdateTrigger);
+    CPUM_ASSERT_WR_MSR_FN(Ia32SmmMonitorCtl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PmcN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MonitorFilterLineSize);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MPerf);
+    CPUM_ASSERT_WR_MSR_FN(Ia32APerf);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MtrrPhysBaseN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MtrrPhysMaskN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MtrrFixed);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MtrrDefType);
+    CPUM_ASSERT_WR_MSR_FN(Ia32Pat);
+    CPUM_ASSERT_WR_MSR_FN(Ia32SysEnterCs);
+    CPUM_ASSERT_WR_MSR_FN(Ia32SysEnterEsp);
+    CPUM_ASSERT_WR_MSR_FN(Ia32SysEnterEip);
+    CPUM_ASSERT_WR_MSR_FN(Ia32McgStatus);
+    CPUM_ASSERT_WR_MSR_FN(Ia32McgCtl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32DebugCtl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32SmrrPhysBase);
+    CPUM_ASSERT_WR_MSR_FN(Ia32SmrrPhysMask);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PlatformDcaCap);
+    CPUM_ASSERT_WR_MSR_FN(Ia32Dca0Cap);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfEvtSelN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfStatus);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfCtl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32FixedCtrN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfCapabilities);
+    CPUM_ASSERT_WR_MSR_FN(Ia32FixedCtrCtrl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfGlobalStatus);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfGlobalCtrl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PerfGlobalOvfCtrl);
+    CPUM_ASSERT_WR_MSR_FN(Ia32PebsEnable);
+    CPUM_ASSERT_WR_MSR_FN(Ia32ClockModulation);
+    CPUM_ASSERT_WR_MSR_FN(Ia32ThermInterrupt);
+    CPUM_ASSERT_WR_MSR_FN(Ia32ThermStatus);
+    CPUM_ASSERT_WR_MSR_FN(Ia32MiscEnable);
+    CPUM_ASSERT_WR_MSR_FN(Ia32McCtlStatusAddrMiscN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32McNCtl2);
+    CPUM_ASSERT_WR_MSR_FN(Ia32DsArea);
+    CPUM_ASSERT_WR_MSR_FN(Ia32TscDeadline);
+    CPUM_ASSERT_WR_MSR_FN(Ia32X2ApicN);
+    CPUM_ASSERT_WR_MSR_FN(Ia32DebugInterface);
+
+    CPUM_ASSERT_WR_MSR_FN(Amd64Efer);
+    CPUM_ASSERT_WR_MSR_FN(Amd64SyscallTarget);
+    CPUM_ASSERT_WR_MSR_FN(Amd64LongSyscallTarget);
+    CPUM_ASSERT_WR_MSR_FN(Amd64CompSyscallTarget);
+    CPUM_ASSERT_WR_MSR_FN(Amd64SyscallFlagMask);
+    CPUM_ASSERT_WR_MSR_FN(Amd64FsBase);
+    CPUM_ASSERT_WR_MSR_FN(Amd64GsBase);
+    CPUM_ASSERT_WR_MSR_FN(Amd64KernelGsBase);
+    CPUM_ASSERT_WR_MSR_FN(Amd64TscAux);
+
+    CPUM_ASSERT_WR_MSR_FN(IntelEblCrPowerOn);
+    CPUM_ASSERT_WR_MSR_FN(IntelP4EbcHardPowerOn);
+    CPUM_ASSERT_WR_MSR_FN(IntelP4EbcSoftPowerOn);
+    CPUM_ASSERT_WR_MSR_FN(IntelP4EbcFrequencyId);
+    CPUM_ASSERT_WR_MSR_FN(IntelFlexRatio100MHz);
+    CPUM_ASSERT_WR_MSR_FN(IntelFlexRatio133MHz);
+    CPUM_ASSERT_WR_MSR_FN(IntelPkgCStConfigControl);
+    CPUM_ASSERT_WR_MSR_FN(IntelPmgIoCaptureBase);
+    CPUM_ASSERT_WR_MSR_FN(IntelLastBranchFromToN);
+    CPUM_ASSERT_WR_MSR_FN(IntelLastBranchFromN);
+    CPUM_ASSERT_WR_MSR_FN(IntelLastBranchToN);
+    CPUM_ASSERT_WR_MSR_FN(IntelLastBranchTos);
+    CPUM_ASSERT_WR_MSR_FN(IntelBblCrCtl);
+    CPUM_ASSERT_WR_MSR_FN(IntelBblCrCtl3);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7TemperatureTarget);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7MsrOffCoreResponseN);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7MiscPwrMgmt);
+    CPUM_ASSERT_WR_MSR_FN(IntelP6CrN);
+    CPUM_ASSERT_WR_MSR_FN(IntelCpuId1FeatureMaskEcdx);
+    CPUM_ASSERT_WR_MSR_FN(IntelCpuId1FeatureMaskEax);
+    CPUM_ASSERT_WR_MSR_FN(IntelCpuId80000001FeatureMaskEcdx);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7SandyAesNiCtl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7TurboRatioLimit);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7LbrSelect);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7SandyErrorControl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7PowerCtl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7SandyPebsNumAlt);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7PebsLdLat);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7SandyVrCurrentConfig);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7SandyVrMiscConfig);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7SandyPkgCnIrtlN);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7RaplPkgPowerLimit);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7RaplDramPowerLimit);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7RaplPp0PowerLimit);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7RaplPp0Policy);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7RaplPp1PowerLimit);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7RaplPp1Policy);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7IvyConfigTdpControl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7IvyTurboActivationRatio);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncPerfGlobalCtrl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncPerfGlobalStatus);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncPerfGlobalOvfCtrl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncPerfFixedCtrCtrl);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncPerfFixedCtr);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncArbPerfCtrN);
+    CPUM_ASSERT_WR_MSR_FN(IntelI7UncArbPerfEvtSelN);
+    CPUM_ASSERT_WR_MSR_FN(IntelCore2EmttmCrTablesN);
+    CPUM_ASSERT_WR_MSR_FN(IntelCore2SmmCStMiscInfo);
+    CPUM_ASSERT_WR_MSR_FN(IntelCore1ExtConfig);
+    CPUM_ASSERT_WR_MSR_FN(IntelCore1DtsCalControl);
+    CPUM_ASSERT_WR_MSR_FN(IntelCore2PeciControl);
+
+    CPUM_ASSERT_WR_MSR_FN(P6LastIntFromIp);
+    CPUM_ASSERT_WR_MSR_FN(P6LastIntToIp);
+
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hTscRate);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hLwpCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hLwpCbAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hMc4MiscN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8PerfCtlN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8PerfCtrN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SysCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8HwCr);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8IorrBaseN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8IorrMaskN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8TopOfMemN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8NbCfg1);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8McXcptRedir);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8CpuNameN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8HwThermalCtrl);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SwThermalCtrl);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8FidVidControl);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8McCtlMaskN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmiOnIoTrapN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmiOnIoTrapCtlSts);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8IntPendingMessage);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmiTriggerIoCycle);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hMmioCfgBaseAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hTrapCtlMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hPStateControl);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hPStateStatus);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hPStateN);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hCofVidControl);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hCofVidStatus);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hCStateIoBaseAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hCpuWatchdogTimer);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmmBase);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmmAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmmMask);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8VmCr);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8IgnNe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8SmmCtl);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8VmHSavePa);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hVmLockKey);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hSmmLockKey);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hLocalSmiStatus);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hOsVisWrkIdLength);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hOsVisWrkStatus);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam16hL2IPerfCtlN);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam16hL2IPerfCtrN);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hNorthbridgePerfCtlN);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hNorthbridgePerfCtrN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7MicrocodeCtl);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7ClusterIdMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8CpuIdCtlStd07hEbax);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8CpuIdCtlStd06hEcx);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8CpuIdCtlStd01hEdcx);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8CpuIdCtlExt01hEdcx);
+    CPUM_ASSERT_WR_MSR_FN(AmdK8PatchLoader);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7DebugStatusMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7BHTraceBaseMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7BHTracePtrMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7BHTraceLimitMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7HardwareDebugToolCfgMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7FastFlushCountMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7NodeId);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7DrXAddrMaskN);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7Dr0DataMatchMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7Dr0DataMaskMaybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7LoadStoreCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7InstrCacheCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7DataCacheCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7BusUnitCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdK7DebugCtl2Maybe);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hFpuCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hDecoderCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hBusUnitCfg2);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hCombUnitCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hCombUnitCfg2);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hCombUnitCfg3);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hExecUnitCfg);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam15hLoadStoreCfg2);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsFetchCtl);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsFetchLinAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsFetchPhysAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsOpExecCtl);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsOpRip);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsOpData);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsOpData2);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsOpData3);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsDcLinAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsDcPhysAddr);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam10hIbsCtl);
+    CPUM_ASSERT_WR_MSR_FN(AmdFam14hIbsBrTarget);
+
+    return VINF_SUCCESS;
+}
+#endif /* VBOX_STRICT && IN_RING3 */
+
+
+/**
+ * Gets the bus frequency.
+ *
+ * The bus frequency is used as a base in several MSRs that gives the CPU and
+ * other frequency ratios.
+ *
+ * @returns Bus frequency in Hz.
+ * @param   pVM                 Pointer to the shared VM structure.
+ */
+VMMDECL(uint64_t) CPUMGetGuestBusFrequency(PVM pVM)
+{
+    if (CPUMMICROARCH_IS_INTEL_CORE7(pVM->cpum.s.GuestFeatures.enmMicroarch))
+    {
+        return pVM->cpum.s.GuestFeatures.enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+            ? UINT64_C(100000000)  /* 100MHz */
+            : UINT64_C(133333333); /* 133MHz */
+    }
+
+    /* 133MHz */
+    return UINT64_C(133333333);
+}
+
+
+#ifdef IN_RING0
+
+/**
+ * Fast way for HM to access the MSR_K8_TSC_AUX register.
+ *
+ * @returns The register value.
+ * @param   pVCpu               Pointer to the cross context CPU structure for
+ *                              the calling EMT.
+ * @thread  EMT(pVCpu)
+ */
+VMMR0_INT_DECL(uint64_t) CPUMR0GetGuestTscAux(PVMCPU pVCpu)
+{
+    return pVCpu->cpum.s.GuestMsrs.msr.TscAux;
+}
+
+
+/**
+ * Fast way for HM to access the MSR_K8_TSC_AUX register.
+ *
+ * @param   pVCpu               Pointer to the cross context CPU structure for
+ *                              the calling EMT.
+ * @param   uValue              The new value.
+ * @thread  EMT(pVCpu)
+ */
+VMMR0_INT_DECL(void) CPUMR0SetGuestTscAux(PVMCPU pVCpu, uint64_t uValue)
+{
+    pVCpu->cpum.s.GuestMsrs.msr.TscAux = uValue;
+}
+
+#endif /* IN_RING0 */
diff --git a/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp b/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
index 9f43099..7a0b4c5 100644
--- a/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
+++ b/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
@@ -869,6 +869,7 @@ VMMDECL(void) CPUMSetGuestEFER(PVMCPU pVCpu, uint64_t val)
     pVCpu->cpum.s.Guest.msrEFER = val;
 }
 
+#ifndef VBOX_WITH_NEW_MSR_CODE
 
 /**
  * Worker for CPUMQueryGuestMsr().
@@ -1588,6 +1589,8 @@ VMMDECL(int) CPUMSetGuestMsr(PVMCPU pVCpu, uint32_t idMsr, uint64_t uValue)
     return rc;
 }
 
+#endif /* !VBOX_WITH_NEW_MSR_CODE */
+
 
 VMMDECL(RTGCPTR) CPUMGetGuestIDTR(PVMCPU pVCpu, uint16_t *pcbLimit)
 {
@@ -1856,6 +1859,66 @@ VMMDECL(uint64_t) CPUMGetGuestEFER(PVMCPU pVCpu)
 
 
 /**
+ * Looks up a CPUID leaf in the CPUID leaf array.
+ *
+ * @returns Pointer to the leaf if found, NULL if not.
+ *
+ * @param   pVM                 Pointer to the cross context VM structure.
+ * @param   uLeaf               The leaf to get.
+ * @param   uSubLeaf            The subleaf, if applicable.  Just pass 0 if it
+ *                              isn't.
+ */
+PCPUMCPUIDLEAF cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf)
+{
+    unsigned            iEnd     = pVM->cpum.s.GuestInfo.cCpuIdLeaves;
+    if (iEnd)
+    {
+        unsigned        iStart   = 0;
+        PCPUMCPUIDLEAF  paLeaves = pVM->cpum.s.GuestInfo.CTX_SUFF(paCpuIdLeaves);
+        for (;;)
+        {
+            unsigned i = iStart + (iEnd - iStart) / 2U;
+            if (uLeaf < paLeaves[i].uLeaf)
+            {
+                if (i <= iStart)
+                    return NULL;
+                iEnd = i;
+            }
+            else if (uLeaf > paLeaves[i].uLeaf)
+            {
+                i += 1;
+                if (i >= iEnd)
+                    return NULL;
+                iStart = i;
+            }
+            else
+            {
+                uSubLeaf &= paLeaves[i].fSubLeafMask;
+                if (uSubLeaf != paLeaves[i].uSubLeaf)
+                {
+                    /* Find the right subleaf.  We return the last one before
+                       uSubLeaf if we don't find an exact match. */
+                    if (uSubLeaf < paLeaves[i].uSubLeaf)
+                        while (   i > 0
+                               && uLeaf    == paLeaves[i].uLeaf
+                               && uSubLeaf  < paLeaves[i].uSubLeaf)
+                            i--;
+                    else
+                        while (   i + 1 < pVM->cpum.s.GuestInfo.cCpuIdLeaves
+                               && uLeaf    == paLeaves[i + 1].uLeaf
+                               && uSubLeaf >= paLeaves[i + 1].uSubLeaf)
+                            i++;
+                }
+                return &paLeaves[i];
+            }
+        }
+    }
+
+    return NULL;
+}
+
+
+/**
  * Gets a CPUID leaf.
  *
  * @param   pVCpu   Pointer to the VMCPU.
@@ -1898,7 +1961,7 @@ VMMDECL(void) CPUMGetGuestCpuId(PVMCPU pVCpu, uint32_t iLeaf, uint32_t *pEax, ui
 
     if (    iLeaf == 4
         &&  cCurrentCacheIndex < 3
-        &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_INTEL)
+        &&  pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL)
     {
         uint32_t type, level, sharing, linesize,
                  partitions, associativity, sets, cores;
@@ -1999,17 +2062,24 @@ VMMDECL(uint32_t) CPUMGetGuestCpuIdCentaurMax(PVM pVM)
  */
 VMMDECL(void) CPUMSetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
 {
+    PCPUMCPUIDLEAF pLeaf;
+
     switch (enmFeature)
     {
         /*
          * Set the APIC bit in both feature masks.
          */
         case CPUMCPUIDFEATURE_APIC:
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx |= X86_CPUID_FEATURE_EDX_APIC;
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
-                &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_AMD_FEATURE_EDX_APIC;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_APIC;
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   pLeaf
+                && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_AMD_FEATURE_EDX_APIC;
+
+            pVM->cpum.s.GuestFeatures.fApic = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled APIC\n"));
             break;
 
@@ -2017,8 +2087,10 @@ VMMDECL(void) CPUMSetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
         * Set the x2APIC bit in the standard feature mask.
         */
         case CPUMCPUIDFEATURE_X2APIC:
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].ecx |= X86_CPUID_FEATURE_ECX_X2APIC;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].ecx = pLeaf->uEcx |= X86_CPUID_FEATURE_ECX_X2APIC;
+            pVM->cpum.s.GuestFeatures.fX2Apic = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled x2APIC\n"));
             break;
 
@@ -2027,145 +2099,156 @@ VMMDECL(void) CPUMSetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
          * Assumes the caller knows what it's doing! (host must support these)
          */
         case CPUMCPUIDFEATURE_SEP:
-        {
-            if (!(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SEP))
+            if (!pVM->cpum.s.HostFeatures.fSysEnter)
             {
                 AssertMsgFailed(("ERROR: Can't turn on SEP when the host doesn't support it!!\n"));
                 return;
             }
 
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx |= X86_CPUID_FEATURE_EDX_SEP;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_SEP;
+            pVM->cpum.s.GuestFeatures.fSysEnter = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled SYSENTER/EXIT\n"));
             break;
-        }
 
         /*
          * Set the syscall/sysret bit in the extended feature mask.
          * Assumes the caller knows what it's doing! (host must support these)
          */
         case CPUMCPUIDFEATURE_SYSCALL:
-        {
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
-                ||  !(ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_SYSCALL))
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   !pLeaf
+                || !pVM->cpum.s.HostFeatures.fSysCall)
             {
 #if HC_ARCH_BITS == 32
-                /* X86_CPUID_EXT_FEATURE_EDX_SYSCALL not set it seems in 32 bits mode.
-                 * Even when the cpu is capable of doing so in 64 bits mode.
-                 */
-                if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
-                    ||  !(ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE)
-                    ||  !(ASMCpuId_EDX(1) & X86_CPUID_EXT_FEATURE_EDX_SYSCALL))
+                /* X86_CPUID_EXT_FEATURE_EDX_SYSCALL not set it seems in 32-bit
+                   mode by Intel, even when the cpu is capable of doing so in
+                   64-bit mode.  Long mode requires syscall support. */
+                if (!pVM->cpum.s.HostFeatures.fLongMode)
 #endif
                 {
                     LogRel(("CPUM: WARNING! Can't turn on SYSCALL/SYSRET when the host doesn't support it!\n"));
                     return;
                 }
             }
+
             /* Valid for both Intel and AMD CPUs, although only in 64 bits mode for Intel. */
-            pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_EXT_FEATURE_EDX_SYSCALL;
+            pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_EXT_FEATURE_EDX_SYSCALL;
+            pVM->cpum.s.GuestFeatures.fSysCall = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled SYSCALL/RET\n"));
             break;
-        }
 
         /*
          * Set the PAE bit in both feature masks.
          * Assumes the caller knows what it's doing! (host must support these)
          */
         case CPUMCPUIDFEATURE_PAE:
-        {
-            if (!(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PAE))
+            if (!pVM->cpum.s.HostFeatures.fPae)
             {
                 LogRel(("CPUM: WARNING! Can't turn on PAE when the host doesn't support it!\n"));
                 return;
             }
 
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx |= X86_CPUID_FEATURE_EDX_PAE;
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
-                &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_AMD_FEATURE_EDX_PAE;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_PAE;
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (    pLeaf
+                &&  pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_AMD_FEATURE_EDX_PAE;
+
+            pVM->cpum.s.GuestFeatures.fPae = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled PAE\n"));
             break;
-        }
 
         /*
          * Set the LONG MODE bit in the extended feature mask.
          * Assumes the caller knows what it's doing! (host must support these)
          */
         case CPUMCPUIDFEATURE_LONG_MODE:
-        {
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
-                ||  !(ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE))
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   !pLeaf
+                || !pVM->cpum.s.HostFeatures.fLongMode)
             {
                 LogRel(("CPUM: WARNING! Can't turn on LONG MODE when the host doesn't support it!\n"));
                 return;
             }
 
             /* Valid for both Intel and AMD. */
-            pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_EXT_FEATURE_EDX_LONG_MODE;
+            pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_EXT_FEATURE_EDX_LONG_MODE;
+            pVM->cpum.s.GuestFeatures.fLongMode = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled LONG MODE\n"));
             break;
-        }
 
         /*
          * Set the NX/XD bit in the extended feature mask.
          * Assumes the caller knows what it's doing! (host must support these)
          */
         case CPUMCPUIDFEATURE_NX:
-        {
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
-                ||  !(ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_NX))
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   !pLeaf
+                || !pVM->cpum.s.HostFeatures.fNoExecute)
             {
                 LogRel(("CPUM: WARNING! Can't turn on NX/XD when the host doesn't support it!\n"));
                 return;
             }
 
             /* Valid for both Intel and AMD. */
-            pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_EXT_FEATURE_EDX_NX;
+            pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_EXT_FEATURE_EDX_NX;
+            pVM->cpum.s.GuestFeatures.fNoExecute = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled NX\n"));
             break;
-        }
+
 
         /*
          * Set the LAHF/SAHF support in 64-bit mode.
          * Assumes the caller knows what it's doing! (host must support this)
          */
         case CPUMCPUIDFEATURE_LAHF:
-        {
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
-                ||  !(ASMCpuId_ECX(0x80000001) & X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF))
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   !pLeaf
+                || !pVM->cpum.s.HostFeatures.fLahfSahf)
             {
                 LogRel(("CPUM: WARNING! Can't turn on LAHF/SAHF when the host doesn't support it!\n"));
                 return;
             }
 
             /* Valid for both Intel and AMD. */
-            pVM->cpum.s.aGuestCpuIdExt[1].ecx |= X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF;
+            pVM->cpum.s.aGuestCpuIdExt[1].ecx = pLeaf->uEcx |= X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF;
+            pVM->cpum.s.GuestFeatures.fLahfSahf = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled LAHF/SAHF\n"));
             break;
-        }
 
+        /*
+         * Set the page attribute table bit.  This is alternative page level
+         * cache control that doesn't much matter when everything is
+         * virtualized, though it may when passing thru device memory.
+         */
         case CPUMCPUIDFEATURE_PAT:
-        {
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx |= X86_CPUID_FEATURE_EDX_PAT;
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
-                &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_AMD_FEATURE_EDX_PAT;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_PAT;
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   pLeaf
+                && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_AMD_FEATURE_EDX_PAT;
+
+            pVM->cpum.s.GuestFeatures.fPat = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled PAT\n"));
             break;
-        }
 
         /*
          * Set the RDTSCP support bit.
          * Assumes the caller knows what it's doing! (host must support this)
          */
         case CPUMCPUIDFEATURE_RDTSCP:
-        {
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
-                ||  !(ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP)
-                ||  pVM->cpum.s.u8PortableCpuIdLevel > 0)
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   !pLeaf
+                || !pVM->cpum.s.HostFeatures.fRdTscP
+                || pVM->cpum.s.u8PortableCpuIdLevel > 0)
             {
                 if (!pVM->cpum.s.u8PortableCpuIdLevel)
                     LogRel(("CPUM: WARNING! Can't turn on RDTSCP when the host doesn't support it!\n"));
@@ -2173,17 +2256,19 @@ VMMDECL(void) CPUMSetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
             }
 
             /* Valid for both Intel and AMD. */
-            pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_EXT_FEATURE_EDX_RDTSCP;
+            pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx |= X86_CPUID_EXT_FEATURE_EDX_RDTSCP;
+            pVM->cpum.s.HostFeatures.fRdTscP = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled RDTSCP.\n"));
             break;
-        }
 
        /*
         * Set the Hypervisor Present bit in the standard feature mask.
         */
         case CPUMCPUIDFEATURE_HVP:
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].ecx |= X86_CPUID_FEATURE_ECX_HVP;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].ecx = pLeaf->uEcx |= X86_CPUID_FEATURE_ECX_HVP;
+            pVM->cpum.s.GuestFeatures.fHypervisorPresent = 1;
             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled Hypervisor Present bit\n"));
             break;
 
@@ -2191,6 +2276,7 @@ VMMDECL(void) CPUMSetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
             AssertMsgFailed(("enmFeature=%d\n", enmFeature));
             break;
     }
+
     for (VMCPUID i = 0; i < pVM->cCpus; i++)
     {
         PVMCPU pVCpu = &pVM->aCpus[i];
@@ -2210,43 +2296,23 @@ VMMDECL(bool) CPUMGetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
 {
     switch (enmFeature)
     {
-        case CPUMCPUIDFEATURE_PAE:
-        {
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                return !!(pVM->cpum.s.aGuestCpuIdStd[1].edx & X86_CPUID_FEATURE_EDX_PAE);
-            break;
-        }
-
-        case CPUMCPUIDFEATURE_NX:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                return !!(pVM->cpum.s.aGuestCpuIdExt[1].edx & X86_CPUID_EXT_FEATURE_EDX_NX);
-        }
-
-        case CPUMCPUIDFEATURE_SYSCALL:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                return !!(pVM->cpum.s.aGuestCpuIdExt[1].edx & X86_CPUID_EXT_FEATURE_EDX_SYSCALL);
-        }
-
-        case CPUMCPUIDFEATURE_RDTSCP:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                return !!(pVM->cpum.s.aGuestCpuIdExt[1].edx & X86_CPUID_EXT_FEATURE_EDX_RDTSCP);
-            break;
-        }
-
-        case CPUMCPUIDFEATURE_LONG_MODE:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                return !!(pVM->cpum.s.aGuestCpuIdExt[1].edx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
-            break;
-        }
-
-        default:
-            AssertMsgFailed(("enmFeature=%d\n", enmFeature));
+        case CPUMCPUIDFEATURE_APIC:         return pVM->cpum.s.GuestFeatures.fApic;
+        case CPUMCPUIDFEATURE_X2APIC:       return pVM->cpum.s.GuestFeatures.fX2Apic;
+        case CPUMCPUIDFEATURE_SYSCALL:      return pVM->cpum.s.GuestFeatures.fSysCall;
+        case CPUMCPUIDFEATURE_SEP:          return pVM->cpum.s.GuestFeatures.fSysEnter;
+        case CPUMCPUIDFEATURE_PAE:          return pVM->cpum.s.GuestFeatures.fPae;
+        case CPUMCPUIDFEATURE_NX:           return pVM->cpum.s.GuestFeatures.fNoExecute;
+        case CPUMCPUIDFEATURE_LAHF:         return pVM->cpum.s.GuestFeatures.fLahfSahf;
+        case CPUMCPUIDFEATURE_LONG_MODE:    return pVM->cpum.s.GuestFeatures.fLongMode;
+        case CPUMCPUIDFEATURE_PAT:          return pVM->cpum.s.GuestFeatures.fPat;
+        case CPUMCPUIDFEATURE_RDTSCP:       return pVM->cpum.s.GuestFeatures.fRdTscP;
+        case CPUMCPUIDFEATURE_HVP:          return pVM->cpum.s.GuestFeatures.fHypervisorPresent;
+
+        case CPUMCPUIDFEATURE_INVALID:
+        case CPUMCPUIDFEATURE_32BIT_HACK:
             break;
     }
+    AssertFailed();
     return false;
 }
 
@@ -2259,82 +2325,93 @@ VMMDECL(bool) CPUMGetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
  */
 VMMDECL(void) CPUMClearGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
 {
+    PCPUMCPUIDLEAF pLeaf;
     switch (enmFeature)
     {
-        /*
-         * Set the APIC bit in both feature masks.
-         */
         case CPUMCPUIDFEATURE_APIC:
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx &= ~X86_CPUID_FEATURE_EDX_APIC;
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
-                &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx &= ~X86_CPUID_AMD_FEATURE_EDX_APIC;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_APIC;
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   pLeaf
+                && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx &= ~X86_CPUID_AMD_FEATURE_EDX_APIC;
+
+            pVM->cpum.s.GuestFeatures.fApic = 0;
             Log(("CPUM: ClearGuestCpuIdFeature: Disabled APIC\n"));
             break;
 
-        /*
-         * Clear the x2APIC bit in the standard feature mask.
-         */
         case CPUMCPUIDFEATURE_X2APIC:
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].ecx &= ~X86_CPUID_FEATURE_ECX_X2APIC;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].ecx = pLeaf->uEcx &= ~X86_CPUID_FEATURE_ECX_X2APIC;
+            pVM->cpum.s.GuestFeatures.fX2Apic = 0;
             Log(("CPUM: ClearGuestCpuIdFeature: Disabled x2APIC\n"));
             break;
 
         case CPUMCPUIDFEATURE_PAE:
-        {
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx &= ~X86_CPUID_FEATURE_EDX_PAE;
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
-                &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx &= ~X86_CPUID_AMD_FEATURE_EDX_PAE;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_PAE;
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   pLeaf
+                && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx &= ~X86_CPUID_AMD_FEATURE_EDX_PAE;
+
+            pVM->cpum.s.GuestFeatures.fPae = 0;
             Log(("CPUM: ClearGuestCpuIdFeature: Disabled PAE!\n"));
             break;
-        }
 
         case CPUMCPUIDFEATURE_PAT:
-        {
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].edx &= ~X86_CPUID_FEATURE_EDX_PAT;
-            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001
-                &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx &= ~X86_CPUID_AMD_FEATURE_EDX_PAT;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].edx = pLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_PAT;
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (   pLeaf
+                && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx &= ~X86_CPUID_AMD_FEATURE_EDX_PAT;
+
+            pVM->cpum.s.GuestFeatures.fPat = 0;
             Log(("CPUM: ClearGuestCpuIdFeature: Disabled PAT!\n"));
             break;
-        }
 
         case CPUMCPUIDFEATURE_LONG_MODE:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx &= ~X86_CPUID_EXT_FEATURE_EDX_LONG_MODE;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx &= ~X86_CPUID_EXT_FEATURE_EDX_LONG_MODE;
+            pVM->cpum.s.GuestFeatures.fLongMode = 0;
             break;
-        }
 
         case CPUMCPUIDFEATURE_LAHF:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                pVM->cpum.s.aGuestCpuIdExt[1].ecx &= ~X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdExt[1].ecx = pLeaf->uEcx &= ~X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF;
+            pVM->cpum.s.GuestFeatures.fLahfSahf = 0;
             break;
-        }
 
         case CPUMCPUIDFEATURE_RDTSCP:
-        {
-            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
-                pVM->cpum.s.aGuestCpuIdExt[1].edx &= ~X86_CPUID_EXT_FEATURE_EDX_RDTSCP;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdExt[1].edx = pLeaf->uEdx &= ~X86_CPUID_EXT_FEATURE_EDX_RDTSCP;
+            pVM->cpum.s.GuestFeatures.fRdTscP = 0;
             Log(("CPUM: ClearGuestCpuIdFeature: Disabled RDTSCP!\n"));
             break;
-        }
 
         case CPUMCPUIDFEATURE_HVP:
-            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
-                pVM->cpum.s.aGuestCpuIdStd[1].ecx &= ~X86_CPUID_FEATURE_ECX_HVP;
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001), 0);
+            if (pLeaf)
+                pVM->cpum.s.aGuestCpuIdStd[1].ecx = pLeaf->uEcx &= ~X86_CPUID_FEATURE_ECX_HVP;
+            pVM->cpum.s.GuestFeatures.fHypervisorPresent = 0;
             break;
 
         default:
             AssertMsgFailed(("enmFeature=%d\n", enmFeature));
             break;
     }
+
     for (VMCPUID i = 0; i < pVM->cCpus; i++)
     {
         PVMCPU pVCpu = &pVM->aCpus[i];
@@ -2351,7 +2428,7 @@ VMMDECL(void) CPUMClearGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature)
  */
 VMMDECL(CPUMCPUVENDOR) CPUMGetHostCpuVendor(PVM pVM)
 {
-    return pVM->cpum.s.enmHostCpuVendor;
+    return (CPUMCPUVENDOR)pVM->cpum.s.HostFeatures.enmCpuVendor;
 }
 
 
@@ -2363,7 +2440,7 @@ VMMDECL(CPUMCPUVENDOR) CPUMGetHostCpuVendor(PVM pVM)
  */
 VMMDECL(CPUMCPUVENDOR) CPUMGetGuestCpuVendor(PVM pVM)
 {
-    return pVM->cpum.s.enmGuestCpuVendor;
+    return (CPUMCPUVENDOR)pVM->cpum.s.GuestFeatures.enmCpuVendor;
 }
 
 
diff --git a/src/VBox/VMM/VMMAll/EMAll.cpp b/src/VBox/VMM/VMMAll/EMAll.cpp
index b8566e1..4c4a595 100644
--- a/src/VBox/VMM/VMMAll/EMAll.cpp
+++ b/src/VBox/VMM/VMMAll/EMAll.cpp
@@ -1817,23 +1817,34 @@ VMM_INT_DECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFra
 VMM_INT_DECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
 {
     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
-    uint64_t val;
+    uint64_t uNewDrX;
     int      rc;
     NOREF(pVM);
 
     if (CPUMIsGuestIn64BitCode(pVCpu))
-        rc = DISFetchReg64(pRegFrame, SrcRegGen, &val);
+        rc = DISFetchReg64(pRegFrame, SrcRegGen, &uNewDrX);
     else
     {
         uint32_t val32;
         rc = DISFetchReg32(pRegFrame, SrcRegGen, &val32);
-        val = val32;
+        uNewDrX = val32;
     }
 
     if (RT_SUCCESS(rc))
     {
+        if (DestRegDrx == 6)
+        {
+            uNewDrX |= X86_DR6_RA1_MASK;
+            uNewDrX &= ~X86_DR6_RAZ_MASK;
+        }
+        else if (DestRegDrx == 7)
+        {
+            uNewDrX |= X86_DR7_RA1_MASK;
+            uNewDrX &= ~X86_DR7_RAZ_MASK;
+        }
+
         /** @todo we don't fail if illegal bits are set/cleared for e.g. dr7 */
-        rc = CPUMSetGuestDRx(pVCpu, DestRegDrx, val);
+        rc = CPUMSetGuestDRx(pVCpu, DestRegDrx, uNewDrX);
         if (RT_SUCCESS(rc))
             return rc;
         AssertMsgFailed(("CPUMSetGuestDRx %d failed\n", DestRegDrx));
diff --git a/src/VBox/VMM/VMMAll/IEMAll.cpp b/src/VBox/VMM/VMMAll/IEMAll.cpp
index bb2df58..8f4c26a 100644
--- a/src/VBox/VMM/VMMAll/IEMAll.cpp
+++ b/src/VBox/VMM/VMMAll/IEMAll.cpp
@@ -333,7 +333,7 @@ typedef IEMSELDESC *PIEMSELDESC;
 /**
  * Check if the address is canonical.
  */
-#define IEM_IS_CANONICAL(a_u64Addr)         ((uint64_t)(a_u64Addr) + UINT64_C(0x800000000000) < UINT64_C(0x1000000000000))
+#define IEM_IS_CANONICAL(a_u64Addr)         X86_IS_CANONICAL(a_u64Addr)
 
 
 /*******************************************************************************
diff --git a/src/VBox/VMM/VMMAll/MMAll.cpp b/src/VBox/VMM/VMMAll/MMAll.cpp
index 321066d..88b9c4a 100644
--- a/src/VBox/VMM/VMMAll/MMAll.cpp
+++ b/src/VBox/VMM/VMMAll/MMAll.cpp
@@ -567,6 +567,10 @@ const char *mmGetTagName(MMTAG enmTag)
         TAG2STR(CFGM_STRING);
         TAG2STR(CFGM_USER);
 
+        TAG2STR(CPUM_CTX);
+        TAG2STR(CPUM_CPUID);
+        TAG2STR(CPUM_MSRS);
+
         TAG2STR(CSAM);
         TAG2STR(CSAM_PATCH);
 
diff --git a/src/VBox/VMM/VMMAll/MMAllHyper.cpp b/src/VBox/VMM/VMMAll/MMAllHyper.cpp
index 4dc2d1a..b62dd6d 100644
--- a/src/VBox/VMM/VMMAll/MMAllHyper.cpp
+++ b/src/VBox/VMM/VMMAll/MMAllHyper.cpp
@@ -321,14 +321,13 @@ static int mmHyperAllocInternal(PVM pVM, size_t cb, unsigned uAlignment, MMTAG e
     return VERR_MM_HYPER_NO_MEMORY;
 }
 
+
 /**
  * Wrapper for mmHyperAllocInternal
  */
 VMMDECL(int) MMHyperAlloc(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv)
 {
-    int rc;
-
-    rc = mmHyperLock(pVM);
+    int rc = mmHyperLock(pVM);
     AssertRCReturn(rc, rc);
 
     LogFlow(("MMHyperAlloc %x align=%x tag=%s\n", cb, uAlignment, mmGetTagName(enmTag)));
@@ -339,6 +338,19 @@ VMMDECL(int) MMHyperAlloc(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag,
     return rc;
 }
 
+
+/**
+ * Duplicates a block of memory.
+ */
+VMMDECL(int) MMHyperDupMem(PVM pVM, const void *pvSrc, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv)
+{
+    int rc = MMHyperAlloc(pVM, cb, uAlignment, enmTag, ppv);
+    if (RT_SUCCESS(rc))
+        memcpy(*ppv, pvSrc, cb);
+    return rc;
+}
+
+
 /**
  * Allocates a chunk of memory from the specified heap.
  * The caller validates the parameters of this request.
diff --git a/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp b/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp
index ab2d91e..db90379 100644
--- a/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp
+++ b/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp
@@ -111,7 +111,9 @@ DECL_FORCE_INLINE(int) pdmCritSectEnterFirst(PPDMCRITSECT pCritSect, RTNATIVETHR
 /**
  * Deals with the contended case in ring-3 and ring-0.
  *
- * @returns VINF_SUCCESS or VERR_SEM_DESTROYED.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_SEM_DESTROYED if destroyed.
+ *
  * @param   pCritSect           The critsect.
  * @param   hNativeSelf         The native thread handle.
  */
@@ -145,25 +147,53 @@ static int pdmR3R0CritSectEnterContended(PPDMCRITSECT pCritSect, RTNATIVETHREAD
 # endif
     for (;;)
     {
-# ifdef PDMCRITSECT_STRICT
+        /*
+         * Do the wait.
+         *
+         * In ring-3 this gets cluttered by lock validation and thread state
+         * maintainence.
+         *
+         * In ring-0 we have to deal with the possibility that the thread has
+         * been signalled and the interruptible wait function returning
+         * immediately.  In that case we do normal R0/RC rcBusy handling.
+         */
+# ifdef IN_RING3
+#  ifdef PDMCRITSECT_STRICT
         int rc9 = RTLockValidatorRecExclCheckBlocking(pCritSect->s.Core.pValidatorRec, hThreadSelf, pSrcPos,
                                                       !(pCritSect->s.Core.fFlags & RTCRITSECT_FLAGS_NO_NESTING),
                                                       RT_INDEFINITE_WAIT, RTTHREADSTATE_CRITSECT, true);
         if (RT_FAILURE(rc9))
             return rc9;
-# elif defined(IN_RING3)
+#  else
         RTThreadBlocking(hThreadSelf, RTTHREADSTATE_CRITSECT, true);
-# endif
+#  endif
         int rc = SUPSemEventWaitNoResume(pSession, hEvent, RT_INDEFINITE_WAIT);
-# ifdef IN_RING3
         RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_CRITSECT);
-# endif
+# else  /* IN_RING0 */
+        int rc = SUPSemEventWaitNoResume(pSession, hEvent, RT_INDEFINITE_WAIT);
+# endif /* IN_RING0 */
 
+        /*
+         * Deal with the return code and critsect destruction.
+         */
         if (RT_UNLIKELY(pCritSect->s.Core.u32Magic != RTCRITSECT_MAGIC))
             return VERR_SEM_DESTROYED;
         if (rc == VINF_SUCCESS)
             return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos);
         AssertMsg(rc == VERR_INTERRUPTED, ("rc=%Rrc\n", rc));
+
+# ifdef IN_RING0
+        /* Something is pending (signal, APC, debugger, whatever), just go back
+           to ring-3 so the kernel can deal with it when leaving kernel context.
+
+           Note! We've incremented cLockers already and cannot safely decrement
+                 it without creating a race with PDMCritSectLeave, resulting in
+                 spurious wakeups. */
+        PVM     pVM   = pCritSect->s.CTX_SUFF(pVM); AssertPtr(pVM);
+        PVMCPU  pVCpu = VMMGetCpu(pVM);             AssertPtr(pVCpu);
+        rc = VMMRZCallRing3(pVM, pVCpu, VMMCALLRING3_VM_R0_PREEMPT, NULL);
+        AssertRC(rc);
+# endif
     }
     /* won't get here */
 }
diff --git a/src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp b/src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp
index f7c5651..3f751a1 100644
--- a/src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp
+++ b/src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp
@@ -122,6 +122,22 @@ VMMDECL(uint32_t) PDMR3CritSectRwSetSubClass(PPDMCRITSECTRW pThis, uint32_t uSub
 #endif /* IN_RING3 */
 
 
+#ifdef IN_RING0
+/**
+ * Go back to ring-3 so the kernel can do signals, APCs and other fun things.
+ *
+ * @param   pThis       Pointer to the read/write critical section.
+ */
+static void pdmR0CritSectRwYieldToRing3(PPDMCRITSECTRW pThis)
+{
+    PVM     pVM   = pThis->s.CTX_SUFF(pVM);     AssertPtr(pVM);
+    PVMCPU  pVCpu = VMMGetCpu(pVM);             AssertPtr(pVCpu);
+    int rc = VMMRZCallRing3(pVM, pVCpu, VMMCALLRING3_VM_R0_PREEMPT, NULL);
+    AssertRC(rc);
+}
+#endif /* IN_RING0 */
+
+
 /**
  * Worker that enters a read/write critical section with shard access.
  *
@@ -264,11 +280,18 @@ static int pdmCritSectRwEnterShared(PPDMCRITSECTRW pThis, int rcBusy, bool fTryO
 #  endif
 # endif
                         {
-                            do
+                            for (;;)
+                            {
                                 rc = SUPSemEventMultiWaitNoResume(pThis->s.CTX_SUFF(pVM)->pSession,
                                                                   (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead,
                                                                   RT_INDEFINITE_WAIT);
-                            while (rc == VERR_INTERRUPTED && pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC);
+                                if (   rc != VERR_INTERRUPTED
+                                    || pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
+                                    break;
+# ifdef IN_RING0
+                                pdmR0CritSectRwYieldToRing3(pThis);
+# endif
+                            }
 # ifdef IN_RING3
                             RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
 # endif
@@ -816,11 +839,18 @@ static int pdmCritSectRwEnterExcl(PPDMCRITSECTRW pThis, int rcBusy, bool fTryOnl
 #  endif
 # endif
                 {
-                    do
+                    for (;;)
+                    {
                         rc = SUPSemEventWaitNoResume(pThis->s.CTX_SUFF(pVM)->pSession,
                                                      (SUPSEMEVENT)pThis->s.Core.hEvtWrite,
                                                      RT_INDEFINITE_WAIT);
-                    while (rc == VERR_INTERRUPTED && pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC);
+                        if (   rc != VERR_INTERRUPTED
+                            || pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
+                            break;
+# ifdef IN_RING0
+                        pdmR0CritSectRwYieldToRing3(pThis);
+# endif
+                    }
 # ifdef IN_RING3
                     RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
 # endif
diff --git a/src/VBox/VMM/VMMAll/SELMAll.cpp b/src/VBox/VMM/VMMAll/SELMAll.cpp
index b6faaf0..317727d 100644
--- a/src/VBox/VMM/VMMAll/SELMAll.cpp
+++ b/src/VBox/VMM/VMMAll/SELMAll.cpp
@@ -724,40 +724,27 @@ DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, R
         if (     pSRegCS->Attr.n.u1DescType == 1
             &&  (pSRegCS->Attr.n.u4Type & X86_SEL_TYPE_CODE))
         {
+            /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
+               (Intel� 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
+            if (    pSRegCS->Attr.n.u1Long
+                &&  CPUMIsGuestInLongMode(pVCpu))
+            {
+                *ppvFlat = Addr;
+                return VINF_SUCCESS;
+            }
+
             /*
-             * Check level.
+             * Limit check. Note that the limit in the hidden register is the
+             * final value. The granularity bit was included in its calculation.
              */
-            unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL);
-            if (    !(pSRegCS->Attr.n.u4Type & X86_SEL_TYPE_CONF)
-                ?   uLevel <= pSRegCS->Attr.n.u2Dpl
-                :   uLevel >= pSRegCS->Attr.n.u2Dpl /* hope I got this right now... */
-               )
+            uint32_t u32Limit = pSRegCS->u32Limit;
+            if ((RTGCUINTPTR)Addr <= u32Limit)
             {
-                /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
-                   (Intel� 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
-                if (    pSRegCS->Attr.n.u1Long
-                    &&  CPUMIsGuestInLongMode(pVCpu))
-                {
-                    *ppvFlat = Addr;
-                    return VINF_SUCCESS;
-                }
-
-                /*
-                 * Limit check. Note that the limit in the hidden register is the
-                 * final value. The granularity bit was included in its calculation.
-                 */
-                uint32_t u32Limit = pSRegCS->u32Limit;
-                if ((RTGCUINTPTR)Addr <= u32Limit)
-                {
-                    *ppvFlat = Addr + pSRegCS->u64Base;
-                    return VINF_SUCCESS;
-                }
-
-                return VERR_OUT_OF_SELECTOR_BOUNDS;
+                *ppvFlat = Addr + pSRegCS->u64Base;
+                return VINF_SUCCESS;
             }
-            Log(("selmValidateAndConvertCSAddrHidden: Invalid RPL Attr.n.u4Type=%x cpl=%x dpl=%x\n",
-                 pSRegCS->Attr.n.u4Type, uLevel, pSRegCS->Attr.n.u2Dpl));
-            return VERR_INVALID_RPL;
+
+            return VERR_OUT_OF_SELECTOR_BOUNDS;
         }
         return VERR_NOT_CODE_SELECTOR;
     }
diff --git a/src/VBox/VMM/VMMR0/CPUMR0.cpp b/src/VBox/VMM/VMMR0/CPUMR0.cpp
index 2f9f9b5..d428938 100644
--- a/src/VBox/VMM/VMMR0/CPUMR0.cpp
+++ b/src/VBox/VMM/VMMR0/CPUMR0.cpp
@@ -75,6 +75,25 @@ typedef struct CPUMHOSTLAPIC
 static CPUMHOSTLAPIC g_aLApics[RTCPUSET_MAX_CPUS];
 #endif
 
+/**
+ * CPUID bits to unify among all cores.
+ */
+static struct
+{
+    uint32_t uLeaf;  /**< Leaf to check. */
+    uint32_t ecx;    /**< which bits in ecx to unify between CPUs. */
+    uint32_t edx;    /**< which bits in edx to unify between CPUs. */
+}
+const g_aCpuidUnifyBits[] =
+{
+    {
+        0x00000001,
+        X86_CPUID_FEATURE_ECX_CX16 | X86_CPUID_FEATURE_ECX_MONITOR,
+        X86_CPUID_FEATURE_EDX_CX8
+    }
+};
+
+
 
 /*******************************************************************************
 *   Internal Functions                                                         *
@@ -113,6 +132,8 @@ VMMR0_INT_DECL(int) CPUMR0ModuleTerm(void)
 
 
 /**
+ *
+ *
  * Check the CPUID features of this particular CPU and disable relevant features
  * for the guest which do not exist on this CPU. We have seen systems where the
  * X86_CPUID_FEATURE_ECX_MONITOR feature flag is only set on some host CPUs, see
@@ -126,36 +147,32 @@ VMMR0_INT_DECL(int) CPUMR0ModuleTerm(void)
  */
 static DECLCALLBACK(void) cpumR0CheckCpuid(RTCPUID idCpu, void *pvUser1, void *pvUser2)
 {
-    struct
-    {
-        uint32_t uLeave; /* leave to check */
-        uint32_t ecx;    /* which bits in ecx to unify between CPUs */
-        uint32_t edx;    /* which bits in edx to unify between CPUs */
-    } aCpuidUnify[]
-    =
-    {
-        { 0x00000001, X86_CPUID_FEATURE_ECX_CX16
-                    | X86_CPUID_FEATURE_ECX_MONITOR,
-                      X86_CPUID_FEATURE_EDX_CX8 }
-    };
-    PVM pVM = (PVM)pvUser1;
-    PCPUM pCPUM = &pVM->cpum.s;
-    for (uint32_t i = 0; i < RT_ELEMENTS(aCpuidUnify); i++)
+    PVM     pVM   = (PVM)pvUser1;
+    PCPUM   pCPUM = &pVM->cpum.s;
+
+    NOREF(idCpu); NOREF(pvUser2);
+    for (uint32_t i = 0; i < RT_ELEMENTS(g_aCpuidUnifyBits); i++)
     {
-        uint32_t uLeave = aCpuidUnify[i].uLeave;
+        /* Note! Cannot use cpumCpuIdGetLeaf from here because we're not
+                 necessarily in the VM process context.  So, we using the
+                 legacy arrays as temporary storage. */
+
+        uint32_t   uLeaf = g_aCpuidUnifyBits[i].uLeaf;
+        PCPUMCPUID pLegacyLeaf;
+        if (uLeaf < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdStd))
+            pLegacyLeaf = &pVM->cpum.s.aGuestCpuIdStd[uLeaf];
+        else if (uLeaf - UINT32_C(0x80000000) < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdExt))
+            pLegacyLeaf = &pVM->cpum.s.aGuestCpuIdExt[uLeaf - UINT32_C(0x80000000)];
+        else if (uLeaf - UINT32_C(0xc0000000) < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdCentaur))
+            pLegacyLeaf = &pVM->cpum.s.aGuestCpuIdCentaur[uLeaf - UINT32_C(0xc0000000)];
+        else
+            continue;
+
         uint32_t eax, ebx, ecx, edx;
+        ASMCpuIdExSlow(uLeaf, 0, 0, 0, &eax, &ebx, &ecx, &edx);
 
-        ASMCpuId_Idx_ECX(uLeave, 0, &eax, &ebx, &ecx, &edx);
-        PCPUMCPUID paLeaves;
-        if (uLeave < 0x80000000)
-            paLeaves = &pCPUM->aGuestCpuIdStd[uLeave - 0x00000000];
-        else if (uLeave < 0xc0000000)
-            paLeaves = &pCPUM->aGuestCpuIdExt[uLeave - 0x80000000];
-        else
-            paLeaves = &pCPUM->aGuestCpuIdCentaur[uLeave - 0xc0000000];
-        /* unify important bits */
-        ASMAtomicAndU32(&paLeaves->ecx, ecx | ~aCpuidUnify[i].ecx);
-        ASMAtomicAndU32(&paLeaves->edx, edx | ~aCpuidUnify[i].edx);
+        ASMAtomicAndU32(&pLegacyLeaf->ecx, ecx | ~g_aCpuidUnifyBits[i].ecx);
+        ASMAtomicAndU32(&pLegacyLeaf->edx, edx | ~g_aCpuidUnifyBits[i].edx);
     }
 }
 
@@ -257,7 +274,38 @@ VMMR0_INT_DECL(int) CPUMR0InitVM(PVM pVM)
             }
         }
 
+        /*
+         * Unify/cross check some CPUID feature bits on all available CPU cores
+         * and threads.  We've seen CPUs where the monitor support differed.
+         *
+         * Because the hyper heap isn't always mapped into ring-0, we cannot
+         * access it from a RTMpOnAll callback.  We use the legacy CPUID arrays
+         * as temp ring-0 accessible memory instead, ASSUMING that they're all
+         * up to date when we get here.
+         */
         RTMpOnAll(cpumR0CheckCpuid, pVM, NULL);
+
+        for (uint32_t i = 0; i < RT_ELEMENTS(g_aCpuidUnifyBits); i++)
+        {
+            uint32_t        uLeaf = g_aCpuidUnifyBits[i].uLeaf;
+            PCPUMCPUIDLEAF  pLeaf = cpumCpuIdGetLeaf(pVM, uLeaf, 0);
+            if (pLeaf)
+            {
+                PCPUMCPUID pLegacyLeaf;
+                if (uLeaf < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdStd))
+                    pLegacyLeaf = &pVM->cpum.s.aGuestCpuIdStd[uLeaf];
+                else if (uLeaf - UINT32_C(0x80000000) < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdExt))
+                    pLegacyLeaf = &pVM->cpum.s.aGuestCpuIdExt[uLeaf - UINT32_C(0x80000000)];
+                else if (uLeaf - UINT32_C(0xc0000000) < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdCentaur))
+                    pLegacyLeaf = &pVM->cpum.s.aGuestCpuIdCentaur[uLeaf - UINT32_C(0xc0000000)];
+                else
+                    continue;
+
+                pLeaf->uEcx = pLegacyLeaf->ecx;
+                pLeaf->uEdx = pLegacyLeaf->edx;
+            }
+        }
+
     }
 
 
diff --git a/src/VBox/VMM/VMMR0/HMR0.cpp b/src/VBox/VMM/VMMR0/HMR0.cpp
index 169e32b..6908eb6 100644
--- a/src/VBox/VMM/VMMR0/HMR0.cpp
+++ b/src/VBox/VMM/VMMR0/HMR0.cpp
@@ -820,7 +820,7 @@ static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *p
     {
         if (fInSmxMode && !fSmxVmxAllowed)
             rc = VERR_VMX_MSR_SMX_VMXON_DISABLED;
-        else if (!fVmxAllowed)
+        else if (!fInSmxMode && !fVmxAllowed)
             rc = VERR_VMX_MSR_VMXON_DISABLED;
         else
             rc = VINF_SUCCESS;
diff --git a/src/VBox/VMM/VMMR0/HMSVMR0.cpp b/src/VBox/VMM/VMMR0/HMSVMR0.cpp
index c508ea7..c65e143 100644
--- a/src/VBox/VMM/VMMR0/HMSVMR0.cpp
+++ b/src/VBox/VMM/VMMR0/HMSVMR0.cpp
@@ -3008,11 +3008,11 @@ static void hmR0SvmPreRunGuestCommitted(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, PS
     if (    (pVM->hm.s.cpuid.u32AMDFeatureEDX & X86_CPUID_EXT_FEATURE_EDX_RDTSCP)
         && !(pVmcb->ctrl.u32InterceptCtrl2 & SVM_CTRL2_INTERCEPT_RDTSCP))
     {
+        /** @todo r=bird: I cannot find any place where the guest TSC_AUX value is
+         *        saved. */
         hmR0SvmSetMsrPermission(pVCpu, MSR_K8_TSC_AUX, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
         pVCpu->hm.s.u64HostTscAux = ASMRdMsr(MSR_K8_TSC_AUX);
-        uint64_t u64GuestTscAux = 0;
-        int rc2 = CPUMQueryGuestMsr(pVCpu, MSR_K8_TSC_AUX, &u64GuestTscAux);
-        AssertRC(rc2);
+        uint64_t u64GuestTscAux = CPUMR0GetGuestTscAux(pVCpu);
         if (u64GuestTscAux != pVCpu->hm.s.u64HostTscAux)
             ASMWrMsr(MSR_K8_TSC_AUX, u64GuestTscAux);
         pSvmTransient->fRestoreTscAuxMsr = true;
@@ -3084,7 +3084,7 @@ static void hmR0SvmPostRunGuest(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx, PSVMT
     if (pSvmTransient->fRestoreTscAuxMsr)
     {
         uint64_t u64GuestTscAux = ASMRdMsr(MSR_K8_TSC_AUX);
-        CPUMSetGuestMsr(pVCpu, MSR_K8_TSC_AUX, u64GuestTscAux);
+        CPUMR0SetGuestTscAux(pVCpu, u64GuestTscAux);
         if (u64GuestTscAux != pVCpu->hm.s.u64HostTscAux)
             ASMWrMsr(MSR_K8_TSC_AUX, pVCpu->hm.s.u64HostTscAux);
     }
diff --git a/src/VBox/VMM/VMMR0/HMVMXR0.cpp b/src/VBox/VMM/VMMR0/HMVMXR0.cpp
index 3d03412..4eaf7d9 100644
--- a/src/VBox/VMM/VMMR0/HMVMXR0.cpp
+++ b/src/VBox/VMM/VMMR0/HMVMXR0.cpp
@@ -4094,8 +4094,7 @@ static int hmR0VmxLoadGuestMsrs(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
         {
             pGuestMsr->u32Msr      = MSR_K8_TSC_AUX;
             pGuestMsr->u32Reserved = 0;
-            rc = CPUMQueryGuestMsr(pVCpu, MSR_K8_TSC_AUX, &pGuestMsr->u64Value);
-            AssertRCReturn(rc, rc);
+            pGuestMsr->u64Value    = CPUMR0GetGuestTscAux(pVCpu);
             pGuestMsr++; cGuestMsrs++;
         }
 
@@ -5546,7 +5545,7 @@ static int hmR0VmxSaveGuestAutoLoadStoreMsrs(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
             case MSR_K8_LSTAR:          pMixedCtx->msrLSTAR  = pMsr->u64Value;                   break;
             case MSR_K6_STAR:           pMixedCtx->msrSTAR   = pMsr->u64Value;                   break;
             case MSR_K8_SF_MASK:        pMixedCtx->msrSFMASK = pMsr->u64Value;                   break;
-            case MSR_K8_TSC_AUX:        CPUMSetGuestMsr(pVCpu, MSR_K8_TSC_AUX, pMsr->u64Value);  break;
+            case MSR_K8_TSC_AUX:        CPUMR0SetGuestTscAux(pVCpu, pMsr->u64Value);             break;
             case MSR_K8_KERNEL_GS_BASE: pMixedCtx->msrKERNELGSBASE = pMsr->u64Value;             break;
             case MSR_K6_EFER:           /* EFER can't be changed without causing a VM-exit. */   break;
             default:
@@ -7730,9 +7729,7 @@ static void hmR0VmxPreRunGuestCommitted(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCt
     if (pVCpu->hm.s.vmx.u32ProcCtls2 & VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP)
     {
         pVCpu->hm.s.u64HostTscAux = ASMRdMsr(MSR_K8_TSC_AUX);
-        uint64_t u64HostTscAux = 0;
-        int rc2 = CPUMQueryGuestMsr(pVCpu, MSR_K8_TSC_AUX, &u64HostTscAux);
-        AssertRC(rc2);
+        uint64_t u64HostTscAux = CPUMR0GetGuestTscAux(pVCpu);
         ASMWrMsr(MSR_K8_TSC_AUX, u64HostTscAux);
     }
 #endif
diff --git a/src/VBox/VMM/VMMR3/CPUM.cpp b/src/VBox/VMM/VMMR3/CPUM.cpp
index cd75102..dd81fc4 100644
--- a/src/VBox/VMM/VMMR3/CPUM.cpp
+++ b/src/VBox/VMM/VMMR3/CPUM.cpp
@@ -54,11 +54,12 @@
 #include <VBox/dis.h>
 #include <VBox/err.h>
 #include <VBox/log.h>
-#include <iprt/assert.h>
 #include <iprt/asm-amd64-x86.h>
-#include <iprt/string.h>
-#include <iprt/mp.h>
+#include <iprt/assert.h>
 #include <iprt/cpuset.h>
+#include <iprt/mem.h>
+#include <iprt/mp.h>
+#include <iprt/string.h>
 #include "internal/pgm.h"
 
 
@@ -114,7 +115,6 @@ typedef CPUMDUMPTYPE *PCPUMDUMPTYPE;
 /*******************************************************************************
 *   Internal Functions                                                         *
 *******************************************************************************/
-static CPUMCPUVENDOR cpumR3DetectVendor(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX);
 static int cpumR3CpuIdInit(PVM pVM);
 static DECLCALLBACK(int)  cpumR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
 static DECLCALLBACK(int)  cpumR3SaveExec(PVM pVM, PSSMHANDLE pSSM);
@@ -549,15 +549,12 @@ static const SSMFIELD g_aCpumCtxFieldsV16[] =
  */
 static void cpumR3CheckLeakyFpu(PVM pVM)
 {
-    uint32_t u32CpuVersion;
-    uint32_t u32Dummy;
-    ASMCpuId(1, &u32CpuVersion, &u32Dummy, &u32Dummy, &u32Dummy);
+    uint32_t u32CpuVersion = ASMCpuId_EAX(1);
     uint32_t const u32Family = u32CpuVersion >> 8;
     if (   u32Family >= 6      /* K7 and higher */
         && ASMIsAmdCpu())
     {
-        uint32_t cExt = 0;
-        ASMCpuId(0x80000000, &cExt, &u32Dummy, &u32Dummy, &u32Dummy);
+        uint32_t cExt = ASMCpuId_EAX(0x80000000);
         if (ASMIsValidExtRange(cExt))
         {
             uint32_t fExtFeaturesEDX = ASMCpuId_EDX(0x80000001);
@@ -583,7 +580,7 @@ VMMR3DECL(int) CPUMR3Init(PVM pVM)
     LogFlow(("CPUMR3Init\n"));
 
     /*
-     * Assert alignment and sizes.
+     * Assert alignment, sizes and tables.
      */
     AssertCompileMemberAlignment(VM, cpum.s, 32);
     AssertCompile(sizeof(pVM->cpum.s) <= sizeof(pVM->cpum.padding));
@@ -594,11 +591,16 @@ VMMR3DECL(int) CPUMR3Init(PVM pVM)
     AssertCompileMemberAlignment(VM, aCpus, 64);
     AssertCompileMemberAlignment(VMCPU, cpum.s, 64);
     AssertCompileMemberSizeAlignment(VM, aCpus[0].cpum.s, 64);
+#ifdef VBOX_STRICT
+    int rc2 = cpumR3MsrStrictInitChecks();
+    AssertRCReturn(rc2, rc2);
+#endif
 
     /* Calculate the offset from CPUM to CPUMCPU for the first CPU. */
     pVM->cpum.s.offCPUMCPU0 = RT_OFFSETOF(VM, aCpus[0].cpum) - RT_OFFSETOF(VM, cpum);
     Assert((uintptr_t)&pVM->cpum + pVM->cpum.s.offCPUMCPU0 == (uintptr_t)&pVM->aCpus[0].cpum);
 
+
     /* Calculate the offset from CPUMCPU to CPUM. */
     for (VMCPUID i = 0; i < pVM->cCpus; i++)
     {
@@ -649,13 +651,17 @@ VMMR3DECL(int) CPUMR3Init(PVM pVM)
         Log(("The CPU doesn't support SYSENTER/SYSEXIT!\n"));
 
     /*
-     * Detect the host CPU vendor.
-     * (The guest CPU vendor is re-detected later on.)
+     * Gather info about the host CPU.
      */
-    uint32_t uEAX, uEBX, uECX, uEDX;
-    ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
-    pVM->cpum.s.enmHostCpuVendor = cpumR3DetectVendor(uEAX, uEBX, uECX, uEDX);
-    pVM->cpum.s.enmGuestCpuVendor = pVM->cpum.s.enmHostCpuVendor;
+    PCPUMCPUIDLEAF  paLeaves;
+    uint32_t        cLeaves;
+    int rc = CPUMR3CpuIdCollectLeaves(&paLeaves, &cLeaves);
+    AssertLogRelRCReturn(rc, rc);
+
+    rc = cpumR3CpuIdExplodeFeatures(paLeaves, cLeaves, &pVM->cpum.s.HostFeatures);
+    RTMemFree(paLeaves);
+    AssertLogRelRCReturn(rc, rc);
+    pVM->cpum.s.GuestFeatures.enmCpuVendor = pVM->cpum.s.HostFeatures.enmCpuVendor;
 
     /*
      * Setup hypervisor startup values.
@@ -664,10 +670,10 @@ VMMR3DECL(int) CPUMR3Init(PVM pVM)
     /*
      * Register saved state data item.
      */
-    int rc = SSMR3RegisterInternal(pVM, "cpum", 1, CPUM_SAVED_STATE_VERSION, sizeof(CPUM),
-                                   NULL, cpumR3LiveExec, NULL,
-                                   NULL, cpumR3SaveExec, NULL,
-                                   cpumR3LoadPrep, cpumR3LoadExec, cpumR3LoadDone);
+    rc = SSMR3RegisterInternal(pVM, "cpum", 1, CPUM_SAVED_STATE_VERSION, sizeof(CPUM),
+                               NULL, cpumR3LiveExec, NULL,
+                               NULL, cpumR3SaveExec, NULL,
+                               cpumR3LoadPrep, cpumR3LoadExec, cpumR3LoadDone);
     if (RT_FAILURE(rc))
         return rc;
 
@@ -702,35 +708,178 @@ VMMR3DECL(int) CPUMR3Init(PVM pVM)
 
 
 /**
- * Detect the CPU vendor give n the
+ * Loads MSR range overrides.
  *
- * @returns The vendor.
- * @param   uEAX                EAX from CPUID(0).
- * @param   uEBX                EBX from CPUID(0).
- * @param   uECX                ECX from CPUID(0).
- * @param   uEDX                EDX from CPUID(0).
+ * This must be called before the MSR ranges are moved from the normal heap to
+ * the hyper heap!
+ *
+ * @returns VBox status code (VMSetError called).
+ * @param   pVM                 Pointer to the cross context VM structure
+ * @param   pMsrNode            The CFGM node with the MSR overrides.
  */
-static CPUMCPUVENDOR cpumR3DetectVendor(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+static int cpumR3LoadMsrOverrides(PVM pVM, PCFGMNODE pMsrNode)
 {
-    if (ASMIsValidStdRange(uEAX))
+    for (PCFGMNODE pNode = CFGMR3GetFirstChild(pMsrNode); pNode; pNode = CFGMR3GetNextChild(pNode))
     {
-        if (ASMIsAmdCpuEx(uEBX, uECX, uEDX))
-            return CPUMCPUVENDOR_AMD;
+        /*
+         * Assemble a valid MSR range.
+         */
+        CPUMMSRRANGE MsrRange;
+        MsrRange.offCpumCpu = 0;
+        MsrRange.fReserved  = 0;
+
+        int rc = CFGMR3GetName(pNode, MsrRange.szName, sizeof(MsrRange.szName));
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry (name is probably too long): %Rrc\n", rc);
+
+        rc = CFGMR3QueryU32(pNode, "First", &MsrRange.uFirst);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry '%s': Error querying mandatory 'First' value: %Rrc\n",
+                              MsrRange.szName, rc);
+
+        rc = CFGMR3QueryU32Def(pNode, "Last", &MsrRange.uLast, MsrRange.uFirst);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry '%s': Error querying 'Last' value: %Rrc\n",
+                              MsrRange.szName, rc);
 
-        if (ASMIsIntelCpuEx(uEBX, uECX, uEDX))
-            return CPUMCPUVENDOR_INTEL;
+        char szType[32];
+        rc = CFGMR3QueryStringDef(pNode, "Type", szType, sizeof(szType), "FixedValue");
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry '%s': Error querying 'Type' value: %Rrc\n",
+                              MsrRange.szName, rc);
+        if (!RTStrICmp(szType, "FixedValue"))
+        {
+            MsrRange.enmRdFn = kCpumMsrRdFn_FixedValue;
+            MsrRange.enmWrFn = kCpumMsrWrFn_IgnoreWrite;
 
-        if (ASMIsViaCentaurCpuEx(uEBX, uECX, uEDX))
-            return CPUMCPUVENDOR_VIA;
+            rc = CFGMR3QueryU64Def(pNode, "Value", &MsrRange.uValue, 0);
+            if (RT_FAILURE(rc))
+                return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry '%s': Error querying 'Value' value: %Rrc\n",
+                                  MsrRange.szName, rc);
 
-        /** @todo detect the other buggers... */
+            rc = CFGMR3QueryU64Def(pNode, "WrGpMask", &MsrRange.fWrGpMask, 0);
+            if (RT_FAILURE(rc))
+                return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry '%s': Error querying 'WrGpMask' value: %Rrc\n",
+                                  MsrRange.szName, rc);
+
+            rc = CFGMR3QueryU64Def(pNode, "WrIgnMask", &MsrRange.fWrIgnMask, 0);
+            if (RT_FAILURE(rc))
+                return VMSetError(pVM, rc, RT_SRC_POS, "Invalid MSR entry '%s': Error querying 'WrIgnMask' value: %Rrc\n",
+                                  MsrRange.szName, rc);
+        }
+        else
+            return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
+                              "Invalid MSR entry '%s': Unknown type '%s'\n", MsrRange.szName, szType);
+
+        /*
+         * Insert the range into the table (replaces/splits/shrinks existing
+         * MSR ranges).
+         */
+        rc = cpumR3MsrRangesInsert(&pVM->cpum.s.GuestInfo.paMsrRangesR3, &pVM->cpum.s.GuestInfo.cMsrRanges, &MsrRange);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Error adding MSR entry '%s': %Rrc\n", MsrRange.szName, rc);
     }
 
-    return CPUMCPUVENDOR_UNKNOWN;
+    return VINF_SUCCESS;
 }
 
 
 /**
+ * Loads CPUID leaf overrides.
+ *
+ * This must be called before the CPUID leaves are moved from the normal
+ * heap to the hyper heap!
+ *
+ * @returns VBox status code (VMSetError called).
+ * @param   pVM             Pointer to the cross context VM structure
+ * @param   pParentNode     The CFGM node with the CPUID leaves.
+ * @param   pszLabel        How to label the overrides we're loading.
+ */
+static int cpumR3LoadCpuIdOverrides(PVM pVM, PCFGMNODE pParentNode, const char *pszLabel)
+{
+    for (PCFGMNODE pNode = CFGMR3GetFirstChild(pParentNode); pNode; pNode = CFGMR3GetNextChild(pNode))
+    {
+        /*
+         * Get the leaf and subleaf numbers.
+         */
+        char szName[128];
+        int rc = CFGMR3GetName(pNode, szName, sizeof(szName));
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry (name is probably too long): %Rrc\n", pszLabel, rc);
+
+        /* The leaf number is either specified directly or thru the node name. */
+        uint32_t uLeaf;
+        rc = CFGMR3QueryU32(pNode, "Leaf", &uLeaf);
+        if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+        {
+            rc = RTStrToUInt32Full(szName, 16, &uLeaf);
+            if (rc != VINF_SUCCESS)
+                return VMSetError(pVM, VERR_INVALID_NAME, RT_SRC_POS,
+                                  "Invalid %s entry: Invalid leaf number: '%s' \n", pszLabel, szName);
+        }
+        else if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'Leaf' value: %Rrc\n",
+                              pszLabel, szName, rc);
+
+        uint32_t uSubLeaf;
+        rc = CFGMR3QueryU32Def(pNode, "SubLeaf", &uSubLeaf, 0);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'SubLeaf' value: %Rrc\n",
+                              pszLabel, szName, rc);
+
+        uint32_t fSubLeafMask;
+        rc = CFGMR3QueryU32Def(pNode, "SubLeafMask", &fSubLeafMask, 0);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'SubLeafMask' value: %Rrc\n",
+                              pszLabel, szName, rc);
+
+        /*
+         * Look up the specified leaf, since the output register values
+         * defaults to any existing values.  This allows overriding a single
+         * register, without needing to know the other values.
+         */
+        PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(pVM->cpum.s.GuestInfo.paCpuIdLeavesR3, pVM->cpum.s.GuestInfo.cCpuIdLeaves,
+                                                   uLeaf, uSubLeaf);
+        CPUMCPUIDLEAF   Leaf;
+        if (pLeaf)
+            Leaf = *pLeaf;
+        else
+            RT_ZERO(Leaf);
+        Leaf.uLeaf          = uLeaf;
+        Leaf.uSubLeaf       = uSubLeaf;
+        Leaf.fSubLeafMask   = fSubLeafMask;
+
+        rc = CFGMR3QueryU32Def(pNode, "eax", &Leaf.uEax, Leaf.uEax);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'eax' value: %Rrc\n",
+                              pszLabel, szName, rc);
+        rc = CFGMR3QueryU32Def(pNode, "ebx", &Leaf.uEbx, Leaf.uEbx);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'ebx' value: %Rrc\n",
+                              pszLabel, szName, rc);
+        rc = CFGMR3QueryU32Def(pNode, "ecx", &Leaf.uEcx, Leaf.uEcx);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'ecx' value: %Rrc\n",
+                              pszLabel, szName, rc);
+        rc = CFGMR3QueryU32Def(pNode, "edx", &Leaf.uEdx, Leaf.uEdx);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Invalid %s entry '%s': Error querying 'edx' value: %Rrc\n",
+                              pszLabel, szName, rc);
+
+        /*
+         * Insert the leaf into the table (replaces existing ones).
+         */
+        rc = cpumR3CpuIdInsert(&pVM->cpum.s.GuestInfo.paCpuIdLeavesR3, &pVM->cpum.s.GuestInfo.cCpuIdLeaves, &Leaf);
+        if (RT_FAILURE(rc))
+            return VMSetError(pVM, rc, RT_SRC_POS, "Error adding CPUID leaf entry '%s': %Rrc\n", szName, rc);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+
+/**
  * Fetches overrides for a CPUID leaf.
  *
  * @returns VBox status code.
@@ -809,7 +958,7 @@ static int cpumR3CpuIdInitHostSet(uint32_t uStart, PCPUMCPUID paLeaves, uint32_t
 {
     /* Using the ECX variant for all of them can't hurt... */
     for (uint32_t i = 0; i < cLeaves; i++)
-        ASMCpuId_Idx_ECX(uStart + i, 0, &paLeaves[i].eax, &paLeaves[i].ebx, &paLeaves[i].ecx, &paLeaves[i].edx);
+        ASMCpuIdExSlow(uStart + i, 0, 0, 0, &paLeaves[i].eax, &paLeaves[i].ebx, &paLeaves[i].ecx, &paLeaves[i].edx);
 
     /* Load CPUID leaf override; we currently don't care if the user
        specifies features the host CPU doesn't support. */
@@ -817,6 +966,68 @@ static int cpumR3CpuIdInitHostSet(uint32_t uStart, PCPUMCPUID paLeaves, uint32_t
 }
 
 
+static int cpumR3CpuIdInstallAndExplodeLeaves(PVM pVM, PCPUM pCPUM, PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves)
+{
+    /*
+     * Install the CPUID information.
+     */
+    int rc = MMHyperDupMem(pVM, paLeaves, sizeof(paLeaves[0]) * cLeaves, 32,
+                           MM_TAG_CPUM_CPUID, (void **)&pCPUM->GuestInfo.paCpuIdLeavesR3);
+
+    AssertLogRelRCReturn(rc, rc);
+
+    pCPUM->GuestInfo.paCpuIdLeavesR0 = MMHyperR3ToR0(pVM, pCPUM->GuestInfo.paCpuIdLeavesR3);
+    pCPUM->GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, pCPUM->GuestInfo.paCpuIdLeavesR3);
+    Assert(MMHyperR0ToR3(pVM, pCPUM->GuestInfo.paCpuIdLeavesR0) == (void *)pCPUM->GuestInfo.paCpuIdLeavesR3);
+    Assert(MMHyperRCToR3(pVM, pCPUM->GuestInfo.paCpuIdLeavesRC) == (void *)pCPUM->GuestInfo.paCpuIdLeavesR3);
+
+    /*
+     * Explode the guest CPU features.
+     */
+    rc = cpumR3CpuIdExplodeFeatures(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, &pCPUM->GuestFeatures);
+    AssertLogRelRCReturn(rc, rc);
+
+
+    /*
+     * Populate the legacy arrays.  Currently used for everything, later only
+     * for patch manager.
+     */
+    struct { PCPUMCPUID paCpuIds; uint32_t cCpuIds, uBase; } aOldRanges[] =
+    {
+        { pCPUM->aGuestCpuIdStd,        RT_ELEMENTS(pCPUM->aGuestCpuIdStd),     0x00000000 },
+        { pCPUM->aGuestCpuIdExt,        RT_ELEMENTS(pCPUM->aGuestCpuIdExt),     0x80000000 },
+        { pCPUM->aGuestCpuIdCentaur,    RT_ELEMENTS(pCPUM->aGuestCpuIdCentaur), 0xc0000000 },
+        { pCPUM->aGuestCpuIdHyper,      RT_ELEMENTS(pCPUM->aGuestCpuIdHyper),   0x40000000 },
+    };
+    for (uint32_t i = 0; i < RT_ELEMENTS(aOldRanges); i++)
+    {
+        uint32_t    cLeft       = aOldRanges[i].cCpuIds;
+        uint32_t    uLeaf       = aOldRanges[i].uBase + cLeft;
+        PCPUMCPUID  pLegacyLeaf = &aOldRanges[i].paCpuIds[cLeft];
+        while (cLeft-- > 0)
+        {
+            uLeaf--;
+            pLegacyLeaf--;
+
+            PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, uLeaf, 0);
+            if (pLeaf)
+            {
+                pLegacyLeaf->eax = pLeaf->uEax;
+                pLegacyLeaf->ebx = pLeaf->uEbx;
+                pLegacyLeaf->ecx = pLeaf->uEcx;
+                pLegacyLeaf->edx = pLeaf->uEdx;
+            }
+            else
+                *pLegacyLeaf = pCPUM->GuestInfo.DefCpuId;
+        }
+    }
+
+    pCPUM->GuestCpuIdDef = pCPUM->GuestInfo.DefCpuId;
+
+    return VINF_SUCCESS;
+}
+
+
 /**
  * Initializes the emulated CPU's cpuid information.
  *
@@ -827,20 +1038,19 @@ static int cpumR3CpuIdInit(PVM pVM)
 {
     PCPUM       pCPUM    = &pVM->cpum.s;
     PCFGMNODE   pCpumCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM");
-    uint32_t    i;
     int         rc;
 
-#define PORTABLE_CLEAR_BITS_WHEN(Lvl, LeafSuffReg, FeatNm, fMask, uValue) \
-    if (pCPUM->u8PortableCpuIdLevel >= (Lvl) && (pCPUM->aGuestCpuId##LeafSuffReg & (fMask)) == (uValue) ) \
+#define PORTABLE_CLEAR_BITS_WHEN(Lvl, a_pLeafReg, FeatNm, fMask, uValue) \
+    if ( pCPUM->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fMask)) == (uValue) ) \
     { \
-        LogRel(("PortableCpuId: " #LeafSuffReg "[" #FeatNm "]: %#x -> 0\n", pCPUM->aGuestCpuId##LeafSuffReg & (fMask))); \
-        pCPUM->aGuestCpuId##LeafSuffReg &= ~(uint32_t)(fMask); \
+        LogRel(("PortableCpuId: " #a_pLeafReg "[" #FeatNm "]: %#x -> 0\n", (a_pLeafReg) & (fMask))); \
+        (a_pLeafReg) &= ~(uint32_t)(fMask); \
     }
-#define PORTABLE_DISABLE_FEATURE_BIT(Lvl, LeafSuffReg, FeatNm, fBitMask) \
-    if (pCPUM->u8PortableCpuIdLevel >= (Lvl) && (pCPUM->aGuestCpuId##LeafSuffReg & (fBitMask)) ) \
+#define PORTABLE_DISABLE_FEATURE_BIT(Lvl, a_pLeafReg, FeatNm, fBitMask) \
+    if ( pCPUM->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fBitMask)) ) \
     { \
-        LogRel(("PortableCpuId: " #LeafSuffReg "[" #FeatNm "]: 1 -> 0\n")); \
-        pCPUM->aGuestCpuId##LeafSuffReg &= ~(uint32_t)(fBitMask); \
+        LogRel(("PortableCpuId: " #a_pLeafReg "[" #FeatNm "]: 1 -> 0\n")); \
+        (a_pLeafReg) &= ~(uint32_t)(fBitMask); \
     }
 
     /*
@@ -849,8 +1059,11 @@ static int cpumR3CpuIdInit(PVM pVM)
     /** @cfgm{CPUM/SyntheticCpu, boolean, false}
      * Enables the Synthetic CPU.  The Vendor ID and Processor Name are
      * completely overridden by VirtualBox custom strings.  Some
-     * CPUID information is withheld, like the cache info. */
-    rc = CFGMR3QueryBoolDef(pCpumCfg, "SyntheticCpu",  &pCPUM->fSyntheticCpu, false);
+     * CPUID information is withheld, like the cache info.
+     *
+     * This is obsoleted by PortableCpuIdLevel. */
+    bool fSyntheticCpu;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "SyntheticCpu",  &fSyntheticCpu, false);
     AssertRCReturn(rc, rc);
 
     /** @cfgm{CPUM/PortableCpuIdLevel, 8-bit, 0, 3, 0}
@@ -858,61 +1071,127 @@ static int cpumR3CpuIdInit(PVM pVM)
      * stripped.  The higher the value the more features gets stripped.  Higher
      * values should only be used when older CPUs are involved since it may
      * harm performance and maybe also cause problems with specific guests. */
-    rc = CFGMR3QueryU8Def(pCpumCfg, "PortableCpuIdLevel", &pCPUM->u8PortableCpuIdLevel, 0);
-    AssertRCReturn(rc, rc);
+    rc = CFGMR3QueryU8Def(pCpumCfg, "PortableCpuIdLevel", &pCPUM->u8PortableCpuIdLevel, fSyntheticCpu ? 1 : 0);
+    AssertLogRelRCReturn(rc, rc);
 
-    AssertLogRelReturn(!pCPUM->fSyntheticCpu || !pCPUM->u8PortableCpuIdLevel, VERR_CPUM_INCOMPATIBLE_CONFIG);
-
-    /*
-     * Get the host CPUID leaves and redetect the guest CPU vendor (could've
-     * been overridden).
-     */
-    /** @cfgm{CPUM/HostCPUID/[000000xx|800000xx|c000000x]/[eax|ebx|ecx|edx],32-bit}
-     * Overrides the host CPUID leaf values used for calculating the guest CPUID
-     * leaves.  This can be used to preserve the CPUID values when moving a VM to a
-     * different machine.  Another use is restricting (or extending) the feature set
-     * exposed to the guest. */
-    PCFGMNODE pHostOverrideCfg = CFGMR3GetChild(pCpumCfg, "HostCPUID");
-    rc = cpumR3CpuIdInitHostSet(UINT32_C(0x00000000), &pCPUM->aGuestCpuIdStd[0],     RT_ELEMENTS(pCPUM->aGuestCpuIdStd),     pHostOverrideCfg);
-    AssertRCReturn(rc, rc);
-    rc = cpumR3CpuIdInitHostSet(UINT32_C(0x80000000), &pCPUM->aGuestCpuIdExt[0],     RT_ELEMENTS(pCPUM->aGuestCpuIdExt),     pHostOverrideCfg);
-    AssertRCReturn(rc, rc);
-    rc = cpumR3CpuIdInitHostSet(UINT32_C(0xc0000000), &pCPUM->aGuestCpuIdCentaur[0], RT_ELEMENTS(pCPUM->aGuestCpuIdCentaur), pHostOverrideCfg);
-    AssertRCReturn(rc, rc);
-
-    pCPUM->enmGuestCpuVendor = cpumR3DetectVendor(pCPUM->aGuestCpuIdStd[0].eax, pCPUM->aGuestCpuIdStd[0].ebx,
-                                                  pCPUM->aGuestCpuIdStd[0].ecx, pCPUM->aGuestCpuIdStd[0].edx);
-
-    /*
-     * Determine the default leaf.
-     *
-     * Intel returns values of the highest standard function, while AMD
-     * returns zeros. VIA on the other hand seems to returning nothing or
-     * perhaps some random garbage, we don't try to duplicate this behavior.
-     */
-    ASMCpuId(pCPUM->aGuestCpuIdStd[0].eax + 10, /** @todo r=bird: Use the host value here in case of overrides and more than 10 leaves being stripped already. */
-             &pCPUM->GuestCpuIdDef.eax, &pCPUM->GuestCpuIdDef.ebx,
-             &pCPUM->GuestCpuIdDef.ecx, &pCPUM->GuestCpuIdDef.edx);
+    /** @cfgm{CPUM/GuestCpuName, string}
+     * The name of of the CPU we're to emulate.  The default is the host CPU.
+     * Note! CPUs other than "host" one is currently unsupported. */
+    char szCpuName[128];
+    rc = CFGMR3QueryStringDef(pCpumCfg, "GuestCpuName", szCpuName, sizeof(szCpuName), "host");
+    AssertLogRelRCReturn(rc, rc);
 
     /** @cfgm{/CPUM/CMPXCHG16B, boolean, false}
      * Expose CMPXCHG16B to the guest if supported by the host.
      */
     bool fCmpXchg16b;
-    rc = CFGMR3QueryBoolDef(pCpumCfg, "CMPXCHG16B", &fCmpXchg16b, false); AssertRCReturn(rc, rc);
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "CMPXCHG16B", &fCmpXchg16b, false);
+    AssertLogRelRCReturn(rc, rc);
 
     /** @cfgm{/CPUM/MONITOR, boolean, true}
      * Expose MONITOR/MWAIT instructions to the guest.
      */
     bool fMonitor;
-    rc = CFGMR3QueryBoolDef(pCpumCfg, "MONITOR", &fMonitor, true); AssertRCReturn(rc, rc);
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "MONITOR", &fMonitor, true);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/MWaitExtensions, boolean, false}
+     * Expose MWAIT extended features to the guest.  For now we expose just MWAIT
+     * break on interrupt feature (bit 1).
+     */
+    bool fMWaitExtensions;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "MWaitExtensions", &fMWaitExtensions, false);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/SSE4.1, boolean, false}
+     * Expose SSE4.1 to the guest if available.
+     */
+    bool fSse41;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "SSE4.1", &fSse41, false);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/SSE4.2, boolean, false}
+     * Expose SSE4.2 to the guest if available.
+     */
+    bool fSse42;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "SSE4.2", &fSse42, false);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/NT4LeafLimit, boolean, false}
+     * Limit the number of standard CPUID leaves to 0..3 to prevent NT4 from
+     * bugchecking with MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED (0x3e).
+     * This option corresponds somewhat to IA32_MISC_ENABLES.BOOT_NT4[bit 22].
+     */
+    bool fNt4LeafLimit;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "NT4LeafLimit", &fNt4LeafLimit, false);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/MaxIntelFamilyModelStep, uint32_t, UINT32_MAX}
+     * Restrict the reported CPU family+model+stepping of intel CPUs.  This is
+     * probably going to be a temporary hack, so don't depend on this.
+     * The 1st byte of the value is the stepping, the 2nd byte value is the model
+     * number and the 3rd byte value is the family, and the 4th value must be zero.
+     */
+    uint32_t uMaxIntelFamilyModelStep;
+    rc = CFGMR3QueryU32Def(pCpumCfg, "MaxIntelFamilyModelStep", &uMaxIntelFamilyModelStep, UINT32_MAX);
+    AssertLogRelRCReturn(rc, rc);
+
+    /*
+     * Get the guest CPU data from the database and/or the host.
+     */
+    rc = cpumR3DbGetCpuInfo(szCpuName, &pCPUM->GuestInfo);
+    if (RT_FAILURE(rc))
+        return rc == VERR_CPUM_DB_CPU_NOT_FOUND
+             ? VMSetError(pVM, rc, RT_SRC_POS,
+                          "Info on guest CPU '%s' could not be found. Please, select a different CPU.", szCpuName)
+             : rc;
+
+    /** @cfgm{CPUM/MSRs/[Name]/[First|Last|Type|Value|...],}
+     * Overrides the guest MSRs.
+     */
+    rc = cpumR3LoadMsrOverrides(pVM, CFGMR3GetChild(pCpumCfg, "MSRs"));
+
+    /** @cfgm{CPUM/HostCPUID/[000000xx|800000xx|c000000x]/[eax|ebx|ecx|edx],32-bit}
+     * Overrides the CPUID leaf values (from the host CPU usually) used for
+     * calculating the guest CPUID leaves.  This can be used to preserve the CPUID
+     * values when moving a VM to a different machine.  Another use is restricting
+     * (or extending) the feature set exposed to the guest. */
+    if (RT_SUCCESS(rc))
+        rc = cpumR3LoadCpuIdOverrides(pVM, CFGMR3GetChild(pCpumCfg, "HostCPUID"), "HostCPUID");
 
-    /* Cpuid 1 & 0x80000001:
+    if (RT_SUCCESS(rc) && CFGMR3GetChild(pCpumCfg, "CPUID")) /* 2nd override, now discontinued. */
+        rc = VMSetError(pVM, VERR_CFGM_CONFIG_UNKNOWN_NODE, RT_SRC_POS,
+                        "Found unsupported configuration node '/CPUM/CPUID/'. "
+                        "Please use IMachine::setCPUIDLeaf() instead.");
+
+    /*
+     * Pre-exploded the CPUID info.
+     */
+    if (RT_SUCCESS(rc))
+        rc = cpumR3CpuIdExplodeFeatures(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, &pCPUM->GuestFeatures);
+    if (RT_FAILURE(rc))
+    {
+        RTMemFree(pCPUM->GuestInfo.paCpuIdLeavesR3);
+        pCPUM->GuestInfo.paCpuIdLeavesR3 = NULL;
+        RTMemFree(pCPUM->GuestInfo.paMsrRangesR3);
+        pCPUM->GuestInfo.paMsrRangesR3 = NULL;
+        return rc;
+    }
+
+
+    /* ... split this function about here ... */
+
+
+    /* Cpuid 1:
      * Only report features we can support.
      *
      * Note! When enabling new features the Synthetic CPU and Portable CPUID
      *       options may require adjusting (i.e. stripping what was enabled).
      */
-    pCPUM->aGuestCpuIdStd[1].edx &= X86_CPUID_FEATURE_EDX_FPU
+    PCPUMCPUIDLEAF pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves,
+                                                        1, 0); /* Note! Must refetch when used later. */
+    AssertLogRelReturn(pStdFeatureLeaf, VERR_CPUM_IPE_2);
+    pStdFeatureLeaf->uEdx        &= X86_CPUID_FEATURE_EDX_FPU
                                   | X86_CPUID_FEATURE_EDX_VME
                                   | X86_CPUID_FEATURE_EDX_DE
                                   | X86_CPUID_FEATURE_EDX_PSE
@@ -943,7 +1222,7 @@ static int cpumR3CpuIdInit(PVM pVM)
                                   //| X86_CPUID_FEATURE_EDX_TM    - no thermal monitor.
                                   //| X86_CPUID_FEATURE_EDX_PBE   - no pending break enabled.
                                   | 0;
-    pCPUM->aGuestCpuIdStd[1].ecx &= 0
+    pStdFeatureLeaf->uEcx        &= 0
                                   | X86_CPUID_FEATURE_ECX_SSE3
                                   /* Can't properly emulate monitor & mwait with guest SMP; force the guest to use hlt for idling VCPUs. */
                                   | ((fMonitor && pVM->cCpus == 1) ? X86_CPUID_FEATURE_ECX_MONITOR : 0)
@@ -956,6 +1235,8 @@ static int cpumR3CpuIdInit(PVM pVM)
                                     | (fCmpXchg16b ? X86_CPUID_FEATURE_ECX_CX16 : 0)
                                   /* ECX Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */
                                   //| X86_CPUID_FEATURE_ECX_TPRUPDATE
+                                  | (fSse41 ? X86_CPUID_FEATURE_ECX_SSE4_1 : 0)
+                                  | (fSse42 ? X86_CPUID_FEATURE_ECX_SSE4_2 : 0)
                                   /* ECX Bit 21 - x2APIC support - not yet. */
                                   // | X86_CPUID_FEATURE_ECX_X2APIC
                                   /* ECX Bit 23 - POPCNT instruction. */
@@ -963,16 +1244,18 @@ static int cpumR3CpuIdInit(PVM pVM)
                                   | 0;
     if (pCPUM->u8PortableCpuIdLevel > 0)
     {
-        PORTABLE_CLEAR_BITS_WHEN(1, Std[1].eax, ProcessorType, (UINT32_C(3) << 12), (UINT32_C(2) << 12));
-        PORTABLE_DISABLE_FEATURE_BIT(1, Std[1].ecx, SSSE3, X86_CPUID_FEATURE_ECX_SSSE3);
-        PORTABLE_DISABLE_FEATURE_BIT(1, Std[1].ecx, SSE3,  X86_CPUID_FEATURE_ECX_SSE3);
-        PORTABLE_DISABLE_FEATURE_BIT(1, Std[1].ecx, CX16,  X86_CPUID_FEATURE_ECX_CX16);
-        PORTABLE_DISABLE_FEATURE_BIT(2, Std[1].edx, SSE2,  X86_CPUID_FEATURE_EDX_SSE2);
-        PORTABLE_DISABLE_FEATURE_BIT(3, Std[1].edx, SSE,   X86_CPUID_FEATURE_EDX_SSE);
-        PORTABLE_DISABLE_FEATURE_BIT(3, Std[1].edx, CLFSH, X86_CPUID_FEATURE_EDX_CLFSH);
-        PORTABLE_DISABLE_FEATURE_BIT(3, Std[1].edx, CMOV,  X86_CPUID_FEATURE_EDX_CMOV);
-
-        Assert(!(pCPUM->aGuestCpuIdStd[1].edx & (  X86_CPUID_FEATURE_EDX_SEP
+        PORTABLE_CLEAR_BITS_WHEN(1, pStdFeatureLeaf->uEax, ProcessorType, (UINT32_C(3) << 12), (UINT32_C(2) << 12));
+        PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSSE3, X86_CPUID_FEATURE_ECX_SSSE3);
+        PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE3,  X86_CPUID_FEATURE_ECX_SSE3);
+        PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE4_1, X86_CPUID_FEATURE_ECX_SSE4_1);
+        PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE4_2, X86_CPUID_FEATURE_ECX_SSE4_2);
+        PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, CX16,  X86_CPUID_FEATURE_ECX_CX16);
+        PORTABLE_DISABLE_FEATURE_BIT(2, pStdFeatureLeaf->uEdx, SSE2,  X86_CPUID_FEATURE_EDX_SSE2);
+        PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, SSE,   X86_CPUID_FEATURE_EDX_SSE);
+        PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, CLFSH, X86_CPUID_FEATURE_EDX_CLFSH);
+        PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, CMOV,  X86_CPUID_FEATURE_EDX_CMOV);
+
+        Assert(!(pStdFeatureLeaf->uEdx        & (  X86_CPUID_FEATURE_EDX_SEP
                                                  | X86_CPUID_FEATURE_EDX_PSN
                                                  | X86_CPUID_FEATURE_EDX_DS
                                                  | X86_CPUID_FEATURE_EDX_ACPI
@@ -980,7 +1263,7 @@ static int cpumR3CpuIdInit(PVM pVM)
                                                  | X86_CPUID_FEATURE_EDX_TM
                                                  | X86_CPUID_FEATURE_EDX_PBE
                                                  )));
-        Assert(!(pCPUM->aGuestCpuIdStd[1].ecx & (  X86_CPUID_FEATURE_ECX_PCLMUL
+        Assert(!(pStdFeatureLeaf->uEcx        & (  X86_CPUID_FEATURE_ECX_PCLMUL
                                                  | X86_CPUID_FEATURE_ECX_DTES64
                                                  | X86_CPUID_FEATURE_ECX_CPLDS
                                                  | X86_CPUID_FEATURE_ECX_VMX
@@ -1010,7 +1293,11 @@ static int cpumR3CpuIdInit(PVM pVM)
      *
      * ASSUMES that this is ALWAYS the AMD defined feature set if present.
      */
-    pCPUM->aGuestCpuIdExt[1].edx &= X86_CPUID_AMD_FEATURE_EDX_FPU
+    PCPUMCPUIDLEAF pExtFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves,
+                                                        UINT32_C(0x80000001), 0); /* Note! Must refetch when used later. */
+    if (pExtFeatureLeaf)
+    {
+        pExtFeatureLeaf->uEdx    &= X86_CPUID_AMD_FEATURE_EDX_FPU
                                   | X86_CPUID_AMD_FEATURE_EDX_VME
                                   | X86_CPUID_AMD_FEATURE_EDX_DE
                                   | X86_CPUID_AMD_FEATURE_EDX_PSE
@@ -1039,7 +1326,7 @@ static int cpumR3CpuIdInit(PVM pVM)
                                   | X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX
                                   | X86_CPUID_AMD_FEATURE_EDX_3DNOW
                                   | 0;
-    pCPUM->aGuestCpuIdExt[1].ecx &= 0
+        pExtFeatureLeaf->uEcx    &= 0
                                   //| X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF
                                   //| X86_CPUID_AMD_FEATURE_ECX_CMPL
                                   //| X86_CPUID_AMD_FEATURE_ECX_SVM    - not virtualized.
@@ -1056,113 +1343,54 @@ static int cpumR3CpuIdInit(PVM pVM)
                                   //| X86_CPUID_AMD_FEATURE_ECX_SKINIT
                                   //| X86_CPUID_AMD_FEATURE_ECX_WDT
                                   | 0;
-    if (pCPUM->u8PortableCpuIdLevel > 0)
-    {
-        PORTABLE_DISABLE_FEATURE_BIT(1, Ext[1].ecx, CR8L,       X86_CPUID_AMD_FEATURE_ECX_CR8L);
-        PORTABLE_DISABLE_FEATURE_BIT(1, Ext[1].edx, 3DNOW,      X86_CPUID_AMD_FEATURE_EDX_3DNOW);
-        PORTABLE_DISABLE_FEATURE_BIT(1, Ext[1].edx, 3DNOW_EX,   X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX);
-        PORTABLE_DISABLE_FEATURE_BIT(1, Ext[1].edx, FFXSR,      X86_CPUID_AMD_FEATURE_EDX_FFXSR);
-        PORTABLE_DISABLE_FEATURE_BIT(1, Ext[1].edx, RDTSCP,     X86_CPUID_EXT_FEATURE_EDX_RDTSCP);
-        PORTABLE_DISABLE_FEATURE_BIT(2, Ext[1].ecx, LAHF_SAHF,  X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF);
-        PORTABLE_DISABLE_FEATURE_BIT(3, Ext[1].ecx, CMOV,       X86_CPUID_AMD_FEATURE_EDX_CMOV);
-
-        Assert(!(pCPUM->aGuestCpuIdExt[1].ecx & (  X86_CPUID_AMD_FEATURE_ECX_CMPL
-                                                 | X86_CPUID_AMD_FEATURE_ECX_SVM
-                                                 | X86_CPUID_AMD_FEATURE_ECX_EXT_APIC
-                                                 | X86_CPUID_AMD_FEATURE_ECX_CR8L
-                                                 | X86_CPUID_AMD_FEATURE_ECX_ABM
-                                                 | X86_CPUID_AMD_FEATURE_ECX_SSE4A
-                                                 | X86_CPUID_AMD_FEATURE_ECX_MISALNSSE
-                                                 | X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF
-                                                 | X86_CPUID_AMD_FEATURE_ECX_OSVW
-                                                 | X86_CPUID_AMD_FEATURE_ECX_IBS
-                                                 | X86_CPUID_AMD_FEATURE_ECX_SSE5
-                                                 | X86_CPUID_AMD_FEATURE_ECX_SKINIT
-                                                 | X86_CPUID_AMD_FEATURE_ECX_WDT
-                                                 | UINT32_C(0xffffc000)
-                                                 )));
-        Assert(!(pCPUM->aGuestCpuIdExt[1].edx & (  RT_BIT(10)
-                                                 | X86_CPUID_EXT_FEATURE_EDX_SYSCALL
-                                                 | RT_BIT(18)
-                                                 | RT_BIT(19)
-                                                 | RT_BIT(21)
-                                                 | X86_CPUID_AMD_FEATURE_EDX_AXMMX
-                                                 | X86_CPUID_EXT_FEATURE_EDX_PAGE1GB
-                                                 | RT_BIT(28)
-                                                 )));
-    }
-
-    /*
-     * Apply the Synthetic CPU modifications. (TODO: move this up)
-     */
-    if (pCPUM->fSyntheticCpu)
-    {
-        static const char s_szVendor[13]    = "VirtualBox  ";
-        static const char s_szProcessor[48] = "VirtualBox SPARCx86 Processor v1000            "; /* includes null terminator */
-
-        pCPUM->enmGuestCpuVendor = CPUMCPUVENDOR_SYNTHETIC;
-
-        /* Limit the nr of standard leaves; 5 for monitor/mwait */
-        pCPUM->aGuestCpuIdStd[0].eax = RT_MIN(pCPUM->aGuestCpuIdStd[0].eax, 5);
-
-        /* 0: Vendor */
-        pCPUM->aGuestCpuIdStd[0].ebx = pCPUM->aGuestCpuIdExt[0].ebx = ((uint32_t *)s_szVendor)[0];
-        pCPUM->aGuestCpuIdStd[0].ecx = pCPUM->aGuestCpuIdExt[0].ecx = ((uint32_t *)s_szVendor)[2];
-        pCPUM->aGuestCpuIdStd[0].edx = pCPUM->aGuestCpuIdExt[0].edx = ((uint32_t *)s_szVendor)[1];
-
-        /* 1.eax: Version information.  family : model : stepping */
-        pCPUM->aGuestCpuIdStd[1].eax = (0xf << 8) + (0x1 << 4) + 1;
-
-        /* Leaves 2 - 4 are Intel only - zero them out */
-        memset(&pCPUM->aGuestCpuIdStd[2], 0, sizeof(pCPUM->aGuestCpuIdStd[2]));
-        memset(&pCPUM->aGuestCpuIdStd[3], 0, sizeof(pCPUM->aGuestCpuIdStd[3]));
-        memset(&pCPUM->aGuestCpuIdStd[4], 0, sizeof(pCPUM->aGuestCpuIdStd[4]));
-
-        /* Leaf 5 = monitor/mwait */
-
-        /* Limit the nr of extended leaves: 0x80000008 to include the max virtual and physical address size (64 bits guests). */
-        pCPUM->aGuestCpuIdExt[0].eax = RT_MIN(pCPUM->aGuestCpuIdExt[0].eax, 0x80000008);
-        /* AMD only - set to zero. */
-        pCPUM->aGuestCpuIdExt[0].ebx = pCPUM->aGuestCpuIdExt[0].ecx = pCPUM->aGuestCpuIdExt[0].edx = 0;
-
-        /* 0x800000001: shared feature bits are set dynamically. */
-        memset(&pCPUM->aGuestCpuIdExt[1], 0, sizeof(pCPUM->aGuestCpuIdExt[1]));
-
-        /* 0x800000002-4: Processor Name String Identifier. */
-        pCPUM->aGuestCpuIdExt[2].eax = ((uint32_t *)s_szProcessor)[0];
-        pCPUM->aGuestCpuIdExt[2].ebx = ((uint32_t *)s_szProcessor)[1];
-        pCPUM->aGuestCpuIdExt[2].ecx = ((uint32_t *)s_szProcessor)[2];
-        pCPUM->aGuestCpuIdExt[2].edx = ((uint32_t *)s_szProcessor)[3];
-        pCPUM->aGuestCpuIdExt[3].eax = ((uint32_t *)s_szProcessor)[4];
-        pCPUM->aGuestCpuIdExt[3].ebx = ((uint32_t *)s_szProcessor)[5];
-        pCPUM->aGuestCpuIdExt[3].ecx = ((uint32_t *)s_szProcessor)[6];
-        pCPUM->aGuestCpuIdExt[3].edx = ((uint32_t *)s_szProcessor)[7];
-        pCPUM->aGuestCpuIdExt[4].eax = ((uint32_t *)s_szProcessor)[8];
-        pCPUM->aGuestCpuIdExt[4].ebx = ((uint32_t *)s_szProcessor)[9];
-        pCPUM->aGuestCpuIdExt[4].ecx = ((uint32_t *)s_szProcessor)[10];
-        pCPUM->aGuestCpuIdExt[4].edx = ((uint32_t *)s_szProcessor)[11];
-
-        /* 0x800000005-7 - reserved -> zero */
-        memset(&pCPUM->aGuestCpuIdExt[5], 0, sizeof(pCPUM->aGuestCpuIdExt[5]));
-        memset(&pCPUM->aGuestCpuIdExt[6], 0, sizeof(pCPUM->aGuestCpuIdExt[6]));
-        memset(&pCPUM->aGuestCpuIdExt[7], 0, sizeof(pCPUM->aGuestCpuIdExt[7]));
-
-        /* 0x800000008: only the max virtual and physical address size. */
-        pCPUM->aGuestCpuIdExt[8].ecx = pCPUM->aGuestCpuIdExt[8].ebx = pCPUM->aGuestCpuIdExt[8].edx = 0;  /* reserved */
+        if (pCPUM->u8PortableCpuIdLevel > 0)
+        {
+            PORTABLE_DISABLE_FEATURE_BIT(1, pExtFeatureLeaf->uEcx, CR8L,       X86_CPUID_AMD_FEATURE_ECX_CR8L);
+            PORTABLE_DISABLE_FEATURE_BIT(1, pExtFeatureLeaf->uEdx, 3DNOW,      X86_CPUID_AMD_FEATURE_EDX_3DNOW);
+            PORTABLE_DISABLE_FEATURE_BIT(1, pExtFeatureLeaf->uEdx, 3DNOW_EX,   X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX);
+            PORTABLE_DISABLE_FEATURE_BIT(1, pExtFeatureLeaf->uEdx, FFXSR,      X86_CPUID_AMD_FEATURE_EDX_FFXSR);
+            PORTABLE_DISABLE_FEATURE_BIT(1, pExtFeatureLeaf->uEdx, RDTSCP,     X86_CPUID_EXT_FEATURE_EDX_RDTSCP);
+            PORTABLE_DISABLE_FEATURE_BIT(2, pExtFeatureLeaf->uEcx, LAHF_SAHF,  X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF);
+            PORTABLE_DISABLE_FEATURE_BIT(3, pExtFeatureLeaf->uEcx, CMOV,       X86_CPUID_AMD_FEATURE_EDX_CMOV);
+
+            Assert(!(pExtFeatureLeaf->uEcx & (  X86_CPUID_AMD_FEATURE_ECX_CMPL
+                                              | X86_CPUID_AMD_FEATURE_ECX_SVM
+                                              | X86_CPUID_AMD_FEATURE_ECX_EXT_APIC
+                                              | X86_CPUID_AMD_FEATURE_ECX_CR8L
+                                              | X86_CPUID_AMD_FEATURE_ECX_ABM
+                                              | X86_CPUID_AMD_FEATURE_ECX_SSE4A
+                                              | X86_CPUID_AMD_FEATURE_ECX_MISALNSSE
+                                              | X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF
+                                              | X86_CPUID_AMD_FEATURE_ECX_OSVW
+                                              | X86_CPUID_AMD_FEATURE_ECX_IBS
+                                              | X86_CPUID_AMD_FEATURE_ECX_SSE5
+                                              | X86_CPUID_AMD_FEATURE_ECX_SKINIT
+                                              | X86_CPUID_AMD_FEATURE_ECX_WDT
+                                              | UINT32_C(0xffffc000)
+                                              )));
+            Assert(!(pExtFeatureLeaf->uEdx & (  RT_BIT(10)
+                                              | X86_CPUID_EXT_FEATURE_EDX_SYSCALL
+                                              | RT_BIT(18)
+                                              | RT_BIT(19)
+                                              | RT_BIT(21)
+                                              | X86_CPUID_AMD_FEATURE_EDX_AXMMX
+                                              | X86_CPUID_EXT_FEATURE_EDX_PAGE1GB
+                                              | RT_BIT(28)
+                                              )));
+        }
     }
 
     /*
      * Hide HTT, multicode, SMP, whatever.
      * (APIC-ID := 0 and #LogCpus := 0)
      */
-    pCPUM->aGuestCpuIdStd[1].ebx &= 0x0000ffff;
+    pStdFeatureLeaf->uEbx &= 0x0000ffff;
 #ifdef VBOX_WITH_MULTI_CORE
-    if (    pCPUM->enmGuestCpuVendor != CPUMCPUVENDOR_SYNTHETIC
-        &&  pVM->cCpus > 1)
+    if (pVM->cCpus > 1)
     {
         /* If CPUID Fn0000_0001_EDX[HTT] = 1 then LogicalProcessorCount is the number of threads per CPU core times the number of CPU cores per processor */
-        pCPUM->aGuestCpuIdStd[1].ebx |= (pVM->cCpus << 16);
-        pCPUM->aGuestCpuIdStd[1].edx |= X86_CPUID_FEATURE_EDX_HTT;  /* necessary for hyper-threading *or* multi-core CPUs */
+        pStdFeatureLeaf->uEbx |= (pVM->cCpus << 16);
+        pStdFeatureLeaf->uEdx |= X86_CPUID_FEATURE_EDX_HTT;  /* necessary for hyper-threading *or* multi-core CPUs */
     }
 #endif
 
@@ -1172,12 +1400,13 @@ static int cpumR3CpuIdInit(PVM pVM)
      * VIA:   Reserved
      * Safe to expose; restrict the number of calls to 1 for the portable case.
      */
-    if (    pCPUM->u8PortableCpuIdLevel > 0
-        &&  pCPUM->aGuestCpuIdStd[0].eax >= 2
-        && (pCPUM->aGuestCpuIdStd[2].eax & 0xff) > 1)
+    PCPUMCPUIDLEAF pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 2, 0);
+    if (   pCPUM->u8PortableCpuIdLevel > 0
+        && pCurLeaf
+        && (pCurLeaf->uEax & 0xff) > 1)
     {
-        LogRel(("PortableCpuId: Std[2].al: %d -> 1\n", pCPUM->aGuestCpuIdStd[2].eax & 0xff));
-        pCPUM->aGuestCpuIdStd[2].eax &= UINT32_C(0xfffffffe);
+        LogRel(("PortableCpuId: Std[2].al: %d -> 1\n", pCurLeaf->uEax & 0xff));
+        pCurLeaf->uEax &= UINT32_C(0xfffffffe);
     }
 
     /* Cpuid 3:
@@ -1187,11 +1416,14 @@ static int cpumR3CpuIdInit(PVM pVM)
      * VIA:   Reserved
      * Safe to expose
      */
-    if (!(pCPUM->aGuestCpuIdStd[1].edx & X86_CPUID_FEATURE_EDX_PSN))
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 3, 0);
+    pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1, 0);
+    if (   !(pStdFeatureLeaf->uEdx & X86_CPUID_FEATURE_EDX_PSN)
+        && pCurLeaf)
     {
-        pCPUM->aGuestCpuIdStd[3].ecx = pCPUM->aGuestCpuIdStd[3].edx = 0;
+        pCurLeaf->uEcx = pCurLeaf->uEdx = 0;
         if (pCPUM->u8PortableCpuIdLevel > 0)
-            pCPUM->aGuestCpuIdStd[3].eax = pCPUM->aGuestCpuIdStd[3].ebx = 0;
+            pCurLeaf->uEax = pCurLeaf->uEbx = 0;
     }
 
     /* Cpuid 4:
@@ -1204,18 +1436,31 @@ static int cpumR3CpuIdInit(PVM pVM)
      *      Bits 31-26: Maximum number of processor cores in this physical package**
      * Note: These SMP values are constant regardless of ECX
      */
-    pCPUM->aGuestCpuIdStd[4].ecx = pCPUM->aGuestCpuIdStd[4].edx = 0;
-    pCPUM->aGuestCpuIdStd[4].eax = pCPUM->aGuestCpuIdStd[4].ebx = 0;
-#ifdef VBOX_WITH_MULTI_CORE
-    if (   pVM->cCpus > 1
-        && pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_INTEL)
+    CPUMCPUIDLEAF NewLeaf;
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 4, 0);
+    if (pCurLeaf)
     {
-        AssertReturn(pVM->cCpus <= 64, VERR_TOO_MANY_CPUS);
-        /* One logical processor with possibly multiple cores. */
-        /* See  http://www.intel.com/Assets/PDF/appnote/241618.pdf p. 29 */
-        pCPUM->aGuestCpuIdStd[4].eax |= ((pVM->cCpus - 1) << 26);   /* 6 bits only -> 64 cores! */
-    }
+        NewLeaf.uLeaf        = 4;
+        NewLeaf.uSubLeaf     = 0;
+        NewLeaf.fSubLeafMask = 0;
+        NewLeaf.uEax         = 0;
+        NewLeaf.uEbx         = 0;
+        NewLeaf.uEcx         = 0;
+        NewLeaf.uEdx         = 0;
+        NewLeaf.fFlags       = 0;
+#ifdef VBOX_WITH_MULTI_CORE
+        if (   pVM->cCpus > 1
+            && pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL)
+        {
+            AssertReturn(pVM->cCpus <= 64, VERR_TOO_MANY_CPUS);
+            /* One logical processor with possibly multiple cores. */
+            /* See  http://www.intel.com/Assets/PDF/appnote/241618.pdf p. 29 */
+            NewLeaf.uEax |= ((pVM->cCpus - 1) << 26);   /* 6 bits only -> 64 cores! */
+        }
 #endif
+        rc = cpumR3CpuIdInsert(&pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, &NewLeaf);
+        AssertLogRelRCReturn(rc, rc);
+    }
 
     /* Cpuid 5:     Monitor/mwait Leaf
      * Intel: ECX, EDX - reserved
@@ -1226,34 +1471,33 @@ static int cpumR3CpuIdInit(PVM pVM)
      * VIA:   Reserved
      * Safe to expose
      */
-    if (!(pCPUM->aGuestCpuIdStd[1].ecx & X86_CPUID_FEATURE_ECX_MONITOR))
-        pCPUM->aGuestCpuIdStd[5].eax = pCPUM->aGuestCpuIdStd[5].ebx = 0;
-
-    pCPUM->aGuestCpuIdStd[5].ecx = pCPUM->aGuestCpuIdStd[5].edx = 0;
-    /** @cfgm{/CPUM/MWaitExtensions, boolean, false}
-     * Expose MWAIT extended features to the guest.  For now we expose
-     * just MWAIT break on interrupt feature (bit 1).
-     */
-    bool fMWaitExtensions;
-    rc = CFGMR3QueryBoolDef(pCpumCfg, "MWaitExtensions", &fMWaitExtensions, false); AssertRCReturn(rc, rc);
-    if (fMWaitExtensions)
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 5, 0);
+    if (pCurLeaf)
     {
-        pCPUM->aGuestCpuIdStd[5].ecx = X86_CPUID_MWAIT_ECX_EXT | X86_CPUID_MWAIT_ECX_BREAKIRQIF0;
-        /** @todo: for now we just expose host's MWAIT C-states, although conceptually
-           it shall be part of our power management virtualization model */
+        pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1, 0);
+        if (!(pStdFeatureLeaf->uEcx & X86_CPUID_FEATURE_ECX_MONITOR))
+            pCurLeaf->uEax = pCurLeaf->uEbx = 0;
+
+        pCurLeaf->uEcx = pCurLeaf->uEdx = 0;
+        if (fMWaitExtensions)
+        {
+            pCurLeaf->uEcx = X86_CPUID_MWAIT_ECX_EXT | X86_CPUID_MWAIT_ECX_BREAKIRQIF0;
+            /** @todo: for now we just expose host's MWAIT C-states, although conceptually
+               it shall be part of our power management virtualization model */
 #if 0
-        /* MWAIT sub C-states */
-        pCPUM->aGuestCpuIdStd[5].edx =
-                (0 << 0)  /* 0 in C0 */ |
-                (2 << 4)  /* 2 in C1 */ |
-                (2 << 8)  /* 2 in C2 */ |
-                (2 << 12) /* 2 in C3 */ |
-                (0 << 16) /* 0 in C4 */
-                ;
+            /* MWAIT sub C-states */
+            pCurLeaf->uEdx =
+                    (0 << 0)  /* 0 in C0 */ |
+                    (2 << 4)  /* 2 in C1 */ |
+                    (2 << 8)  /* 2 in C2 */ |
+                    (2 << 12) /* 2 in C3 */ |
+                    (0 << 16) /* 0 in C4 */
+                    ;
 #endif
+        }
+        else
+            pCurLeaf->uEcx = pCurLeaf->uEdx = 0;
     }
-    else
-        pCPUM->aGuestCpuIdStd[5].ecx = pCPUM->aGuestCpuIdStd[5].edx = 0;
 
     /* Cpuid 0x800000005 & 0x800000006 contain information about L1, L2 & L3 cache and TLB identifiers.
      * Safe to pass on to the guest.
@@ -1272,16 +1516,17 @@ static int cpumR3CpuIdInit(PVM pVM)
      *                    EDX: Advanced Power Management Information
      * VIA:               Reserved
      */
-    if (pCPUM->aGuestCpuIdExt[0].eax >= UINT32_C(0x80000007))
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0x80000007), 0);
+    if (pCurLeaf)
     {
-        Assert(pVM->cpum.s.enmGuestCpuVendor != CPUMCPUVENDOR_INVALID);
+        Assert(pCPUM->GuestFeatures.enmCpuVendor != CPUMCPUVENDOR_INVALID);
 
-        pCPUM->aGuestCpuIdExt[7].eax = pCPUM->aGuestCpuIdExt[7].ebx = pCPUM->aGuestCpuIdExt[7].ecx = 0;
+        pCurLeaf->uEax = pCurLeaf->uEbx = pCurLeaf->uEcx = 0;
 
-        if (pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
+        if (pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
         {
             /* Only expose the TSC invariant capability bit to the guest. */
-            pCPUM->aGuestCpuIdExt[7].edx    &= 0
+            pCurLeaf->uEdx                  &= 0
                                             //| X86_CPUID_AMD_ADVPOWER_EDX_TS
                                             //| X86_CPUID_AMD_ADVPOWER_EDX_FID
                                             //| X86_CPUID_AMD_ADVPOWER_EDX_VID
@@ -1302,7 +1547,7 @@ static int cpumR3CpuIdInit(PVM pVM)
                                             | 0;
         }
         else
-            pCPUM->aGuestCpuIdExt[7].edx    = 0;
+            pCurLeaf->uEdx = 0;
     }
 
     /* Cpuid 0x800000008:
@@ -1314,55 +1559,62 @@ static int cpumR3CpuIdInit(PVM pVM)
      * VIA:               EAX: Virtual/Physical address Size
      *                    EBX, ECX, EDX - reserved
      */
-    if (pCPUM->aGuestCpuIdExt[0].eax >= UINT32_C(0x80000008))
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0x80000008), 0);
+    if (pCurLeaf)
     {
         /* Only expose the virtual and physical address sizes to the guest. */
-        pCPUM->aGuestCpuIdExt[8].eax &= UINT32_C(0x0000ffff);
-        pCPUM->aGuestCpuIdExt[8].ebx = pCPUM->aGuestCpuIdExt[8].edx = 0;  /* reserved */
+        pCurLeaf->uEax &= UINT32_C(0x0000ffff);
+        pCurLeaf->uEbx = pCurLeaf->uEdx = 0;  /* reserved */
         /* Set APICIdCoreIdSize to zero (use legacy method to determine the number of cores per cpu)
          * NC (0-7) Number of cores; 0 equals 1 core */
-        pCPUM->aGuestCpuIdExt[8].ecx = 0;
+        pCurLeaf->uEcx = 0;
 #ifdef VBOX_WITH_MULTI_CORE
         if (    pVM->cCpus > 1
-            &&  pVM->cpum.s.enmGuestCpuVendor == CPUMCPUVENDOR_AMD)
+            &&  pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD)
         {
             /* Legacy method to determine the number of cores. */
-            pCPUM->aGuestCpuIdExt[1].ecx |= X86_CPUID_AMD_FEATURE_ECX_CMPL;
-            pCPUM->aGuestCpuIdExt[8].ecx |= (pVM->cCpus - 1); /* NC: Number of CPU cores - 1; 8 bits */
+            pCurLeaf->uEcx |= (pVM->cCpus - 1); /* NC: Number of CPU cores - 1; 8 bits */
+            pExtFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves,
+                                                 UINT32_C(0x80000001), 0);
+            if (pExtFeatureLeaf)
+                pExtFeatureLeaf->uEcx |= X86_CPUID_AMD_FEATURE_ECX_CMPL;
         }
 #endif
     }
 
-    /** @cfgm{/CPUM/NT4LeafLimit, boolean, false}
-     * Limit the number of standard CPUID leaves to 0..3 to prevent NT4 from
-     * bugchecking with MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED (0x3e).
-     * This option corresponds somewhat to IA32_MISC_ENABLES.BOOT_NT4[bit 22].
-     */
-    bool fNt4LeafLimit;
-    rc = CFGMR3QueryBoolDef(pCpumCfg, "NT4LeafLimit", &fNt4LeafLimit, false); AssertRCReturn(rc, rc);
-    if (fNt4LeafLimit && pCPUM->aGuestCpuIdStd[0].eax > 3)
-        pCPUM->aGuestCpuIdStd[0].eax = 3;
 
     /*
-     * Limit it the number of entries and fill the remaining with the defaults.
+     * Limit it the number of entries, zapping the remainder.
      *
      * The limits are masking off stuff about power saving and similar, this
      * is perhaps a bit crudely done as there is probably some relatively harmless
      * info too in these leaves (like words about having a constant TSC).
      */
-    if (pCPUM->aGuestCpuIdStd[0].eax > 5)
-        pCPUM->aGuestCpuIdStd[0].eax = 5;
-    for (i = pCPUM->aGuestCpuIdStd[0].eax + 1; i < RT_ELEMENTS(pCPUM->aGuestCpuIdStd); i++)
-        pCPUM->aGuestCpuIdStd[i] = pCPUM->GuestCpuIdDef;
-
-    if (pCPUM->aGuestCpuIdExt[0].eax > UINT32_C(0x80000008))
-        pCPUM->aGuestCpuIdExt[0].eax = UINT32_C(0x80000008);
-    for (i = pCPUM->aGuestCpuIdExt[0].eax >= UINT32_C(0x80000000)
-           ? pCPUM->aGuestCpuIdExt[0].eax - UINT32_C(0x80000000) + 1
-           : 0;
-         i < RT_ELEMENTS(pCPUM->aGuestCpuIdExt);
-         i++)
-        pCPUM->aGuestCpuIdExt[i] = pCPUM->GuestCpuIdDef;
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 0, 0);
+    if (pCurLeaf)
+    {
+        if (pCurLeaf->uEax > 5)
+        {
+            pCurLeaf->uEax = 5;
+            cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves,
+                                   pCurLeaf->uEax + 1, UINT32_C(0x000fffff));
+        }
+
+        /* NT4 hack, no zapping of extra leaves here. */
+        if (fNt4LeafLimit && pCurLeaf->uEax > 3)
+            pCurLeaf->uEax = 3;
+    }
+
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0x80000000), 0);
+    if (pCurLeaf)
+    {
+        if (pCurLeaf->uEax > UINT32_C(0x80000008))
+        {
+            pCurLeaf->uEax = UINT32_C(0x80000008);
+            cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves,
+                                   pCurLeaf->uEax + 1, UINT32_C(0x800fffff));
+        }
+    }
 
     /*
      * Centaur stuff (VIA).
@@ -1372,19 +1624,25 @@ static int cpumR3CpuIdInit(PVM pVM)
      * let on about any of those... 0xc0000002 seems to be some
      * temperature/hz/++ stuff, include it as well (static).
      */
-    if (    pCPUM->aGuestCpuIdCentaur[0].eax >= UINT32_C(0xc0000000)
-        &&  pCPUM->aGuestCpuIdCentaur[0].eax <= UINT32_C(0xc0000004))
+    pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0xc0000000), 0);
+    if (pCurLeaf)
     {
-        pCPUM->aGuestCpuIdCentaur[0].eax = RT_MIN(pCPUM->aGuestCpuIdCentaur[0].eax, UINT32_C(0xc0000002));
-        pCPUM->aGuestCpuIdCentaur[1].edx = 0; /* all features hidden */
-        for (i = pCPUM->aGuestCpuIdCentaur[0].eax - UINT32_C(0xc0000000);
-             i < RT_ELEMENTS(pCPUM->aGuestCpuIdCentaur);
-             i++)
-            pCPUM->aGuestCpuIdCentaur[i] = pCPUM->GuestCpuIdDef;
+        if (   pCurLeaf->uEax >= UINT32_C(0xc0000000)
+            && pCurLeaf->uEax <= UINT32_C(0xc0000004))
+        {
+            pCurLeaf->uEax = RT_MIN(pCurLeaf->uEax, UINT32_C(0xc0000002));
+            cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves,
+                                   UINT32_C(0xc0000002), UINT32_C(0xc00fffff));
+
+            pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves,
+                                          UINT32_C(0xc0000001), 0);
+            if (pCurLeaf)
+                pCurLeaf->uEdx = 0; /* all features hidden */
+        }
+        else
+            cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves,
+                                   UINT32_C(0xc0000000), UINT32_C(0xc00fffff));
     }
-    else
-        for (i = 0; i < RT_ELEMENTS(pCPUM->aGuestCpuIdCentaur); i++)
-            pCPUM->aGuestCpuIdCentaur[i] = pCPUM->GuestCpuIdDef;
 
     /*
      * Hypervisor identification.
@@ -1393,34 +1651,39 @@ static int cpumR3CpuIdInit(PVM pVM)
      * 0x40000000 function returns 0x40000001 and identifying ourselves.
      * Currently we do not support any hypervisor-specific interface.
      */
-    pCPUM->aGuestCpuIdHyper[0].eax = UINT32_C(0x40000001);
-    pCPUM->aGuestCpuIdHyper[0].ebx = pCPUM->aGuestCpuIdHyper[0].ecx
-                                   = pCPUM->aGuestCpuIdHyper[0].edx = 0x786f4256;   /* 'VBox' */
-    pCPUM->aGuestCpuIdHyper[1].eax = 0x656e6f6e;                            /* 'none' */
-    pCPUM->aGuestCpuIdHyper[1].ebx = pCPUM->aGuestCpuIdHyper[1].ecx
-                                   = pCPUM->aGuestCpuIdHyper[1].edx = 0;    /* Reserved */
+    NewLeaf.uLeaf        = UINT32_C(0x40000000);
+    NewLeaf.uSubLeaf     = 0;
+    NewLeaf.fSubLeafMask = 0;
+    NewLeaf.uEax         = UINT32_C(0x40000001);
+    NewLeaf.uEbx         = 0x786f4256 /* 'VBox' */;
+    NewLeaf.uEcx         = 0x786f4256 /* 'VBox' */;
+    NewLeaf.uEdx         = 0x786f4256 /* 'VBox' */;
+    NewLeaf.fFlags       = 0;
+    rc = cpumR3CpuIdInsert(&pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, &NewLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    NewLeaf.uLeaf        = UINT32_C(0x40000001);
+    NewLeaf.uEax         = 0x656e6f6e;                            /* 'none' */
+    NewLeaf.uEbx         = 0;
+    NewLeaf.uEcx         = 0;
+    NewLeaf.uEdx         = 0;
+    NewLeaf.fFlags       = 0;
+    rc = cpumR3CpuIdInsert(&pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, &NewLeaf);
+    AssertLogRelRCReturn(rc, rc);
 
     /*
      * Mini CPU selection support for making Mac OS X happy.
      */
-    if (pCPUM->enmGuestCpuVendor == CPUMCPUVENDOR_INTEL)
+    if (pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL)
     {
-        /** @cfgm{/CPUM/MaxIntelFamilyModelStep, uint32_t, UINT32_MAX}
-         * Restrict the reported CPU family+model+stepping of intel CPUs.  This is
-         * probably going to be a temporary hack, so don't depend on this.
-         * The 1st byte of the value is the stepping, the 2nd byte value is the model
-         * number and the 3rd byte value is the family, and the 4th value must be zero.
-         */
-        uint32_t uMaxIntelFamilyModelStep;
-        rc = CFGMR3QueryU32Def(pCpumCfg, "MaxIntelFamilyModelStep", &uMaxIntelFamilyModelStep, UINT32_MAX);
-        AssertRCReturn(rc, rc);
-        uint32_t uCurIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(ASMGetCpuStepping(pCPUM->aGuestCpuIdStd[1].eax),
-                                                                ASMGetCpuModelIntel(pCPUM->aGuestCpuIdStd[1].eax),
-                                                                ASMGetCpuFamily(pCPUM->aGuestCpuIdStd[1].eax),
+        pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1, 0);
+        uint32_t uCurIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(ASMGetCpuStepping(pStdFeatureLeaf->uEax),
+                                                                ASMGetCpuModelIntel(pStdFeatureLeaf->uEax),
+                                                                ASMGetCpuFamily(pStdFeatureLeaf->uEax),
                                                                 0);
         if (uMaxIntelFamilyModelStep < uCurIntelFamilyModelStep)
         {
-            uint32_t uNew = pCPUM->aGuestCpuIdStd[1].eax & UINT32_C(0xf0003000);
+            uint32_t uNew = pStdFeatureLeaf->uEax & UINT32_C(0xf0003000);
             uNew |= RT_BYTE1(uMaxIntelFamilyModelStep) & 0xf; /* stepping */
             uNew |= (RT_BYTE2(uMaxIntelFamilyModelStep) & 0xf) << 4; /* 4 low model bits */
             uNew |= (RT_BYTE2(uMaxIntelFamilyModelStep) >> 4) << 16; /* 4 high model bits */
@@ -1428,45 +1691,62 @@ static int cpumR3CpuIdInit(PVM pVM)
             if (RT_BYTE3(uMaxIntelFamilyModelStep) > 0xf) /* 8 high family bits, using intel's suggested calculation. */
                 uNew |= ( (RT_BYTE3(uMaxIntelFamilyModelStep) - (RT_BYTE3(uMaxIntelFamilyModelStep) & 0xf)) & 0xff ) << 20;
             LogRel(("CPU: CPUID(0).EAX %#x -> %#x (uMaxIntelFamilyModelStep=%#x, uCurIntelFamilyModelStep=%#x\n",
-                    pCPUM->aGuestCpuIdStd[1].eax, uNew, uMaxIntelFamilyModelStep, uCurIntelFamilyModelStep));
-            pCPUM->aGuestCpuIdStd[1].eax = uNew;
+                    pStdFeatureLeaf->uEax, uNew, uMaxIntelFamilyModelStep, uCurIntelFamilyModelStep));
+            pStdFeatureLeaf->uEax = uNew;
         }
     }
 
     /*
-     * Load CPUID overrides from configuration.
-     * Note: Kind of redundant now, but allows unchanged overrides
+     * MSR fudging.
      */
-    /** @cfgm{CPUM/CPUID/[000000xx|800000xx|c000000x]/[eax|ebx|ecx|edx],32-bit}
-     * Overrides the CPUID leaf values. */
-    PCFGMNODE pOverrideCfg = CFGMR3GetChild(pCpumCfg, "CPUID");
-    rc = cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x00000000), &pCPUM->aGuestCpuIdStd[0],     RT_ELEMENTS(pCPUM->aGuestCpuIdStd),     pOverrideCfg);
-    AssertRCReturn(rc, rc);
-    rc = cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x80000000), &pCPUM->aGuestCpuIdExt[0],     RT_ELEMENTS(pCPUM->aGuestCpuIdExt),     pOverrideCfg);
-    AssertRCReturn(rc, rc);
-    rc = cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0xc0000000), &pCPUM->aGuestCpuIdCentaur[0], RT_ELEMENTS(pCPUM->aGuestCpuIdCentaur), pOverrideCfg);
-    AssertRCReturn(rc, rc);
+    /** @cfgm{CPUM/FudgeMSRs, boolean, true}
+     * Fudges some common MSRs if not present in the selected CPU database entry.
+     * This is for trying to keep VMs running when moved between different hosts
+     * and different CPU vendors. */
+    bool fEnable;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "FudgeMSRs", &fEnable, true);       AssertRCReturn(rc, rc);
+    if (fEnable)
+    {
+        rc = cpumR3MsrApplyFudge(pVM);
+        AssertLogRelRCReturn(rc, rc);
+    }
 
     /*
-     * Check if PAE was explicitely enabled by the user.
+     * Move the MSR and CPUID arrays over on the hypervisor heap, and explode
+     * guest CPU features again.
      */
-    bool fEnable;
+    void *pvFree = pCPUM->GuestInfo.paCpuIdLeavesR3;
+    int rc1 = cpumR3CpuIdInstallAndExplodeLeaves(pVM, pCPUM, pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves);
+    RTMemFree(pvFree);
+
+    pvFree = pCPUM->GuestInfo.paMsrRangesR3;
+    int rc2 = MMHyperDupMem(pVM, pvFree,
+                            sizeof(pCPUM->GuestInfo.paMsrRangesR3[0]) * pCPUM->GuestInfo.cMsrRanges, 32,
+                            MM_TAG_CPUM_MSRS, (void **)&pCPUM->GuestInfo.paMsrRangesR3);
+    RTMemFree(pvFree);
+    AssertLogRelRCReturn(rc1, rc1);
+    AssertLogRelRCReturn(rc2, rc2);
+
+    pCPUM->GuestInfo.paMsrRangesR0 = MMHyperR3ToR0(pVM, pCPUM->GuestInfo.paMsrRangesR3);
+    pCPUM->GuestInfo.paMsrRangesRC = MMHyperR3ToRC(pVM, pCPUM->GuestInfo.paMsrRangesR3);
+    cpumR3MsrRegStats(pVM);
+
+    /*
+     * Some more configuration that we're applying at the end of everything
+     * via the CPUMSetGuestCpuIdFeature API.
+     */
+
+    /* Check if PAE was explicitely enabled by the user. */
     rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "EnablePAE", &fEnable, false);      AssertRCReturn(rc, rc);
     if (fEnable)
         CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
 
-    /*
-     * We don't normally enable NX for raw-mode, so give the user a chance to
-     * force it on.
-     */
+    /* We don't normally enable NX for raw-mode, so give the user a chance to force it on. */
     rc = CFGMR3QueryBoolDef(pCpumCfg, "EnableNX", &fEnable, false);                 AssertRCReturn(rc, rc);
     if (fEnable)
         CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
 
-    /*
-     * We don't enable the Hypervisor Present bit by default, but it may
-     * be needed by some guests.
-     */
+    /* We don't enable the Hypervisor Present bit by default, but it may be needed by some guests. */
     rc = CFGMR3QueryBoolDef(pCpumCfg, "EnableHVP", &fEnable, false);                AssertRCReturn(rc, rc);
     if (fEnable)
         CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP);
@@ -1491,6 +1771,9 @@ VMMR3DECL(void) CPUMR3Relocate(PVM pVM)
 {
     LogFlow(("CPUMR3Relocate\n"));
 
+    pVM->cpum.s.GuestInfo.paMsrRangesRC   = MMHyperR3ToRC(pVM, pVM->cpum.s.GuestInfo.paMsrRangesR3);
+    pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, pVM->cpum.s.GuestInfo.paCpuIdLeavesR3);
+
     /* Recheck the guest DRx values in raw-mode. */
     for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
         CPUMRecalcHyperDRx(&pVM->aCpus[iCpu], UINT8_MAX, false);
@@ -1554,9 +1837,12 @@ VMMR3DECL(int) CPUMR3Term(PVM pVM)
  *
  * Used by CPUMR3Reset and CPU hot plugging.
  *
- * @param   pVCpu               Pointer to the VMCPU.
+ * @param   pVM         Pointer to the cross context VM structure.
+ * @param   pVCpu       Pointer to the cross context virtual CPU structure of
+ *                      the CPU that is being reset.  This may differ from the
+ *                      current EMT.
  */
-VMMR3DECL(void) CPUMR3ResetCpu(PVMCPU pVCpu)
+VMMR3DECL(void) CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
 {
     /** @todo anything different for VCPU > 0? */
     PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
@@ -1637,6 +1923,9 @@ VMMR3DECL(void) CPUMR3ResetCpu(PVMCPU pVCpu)
     pCtx->fpu.MXCSR_MASK            = 0xffff; /** @todo REM always changed this for us. Should probably check if the HW really
                                                         supports all bits, since a zero value here should be read as 0xffbf. */
 
+    /*
+     * MSRs.
+     */
     /* Init PAT MSR */
     pCtx->msrPAT                    = UINT64_C(0x0007040600070406); /** @todo correct? */
 
@@ -1644,10 +1933,26 @@ VMMR3DECL(void) CPUMR3ResetCpu(PVMCPU pVCpu)
      * The Intel docs don't mention it. */
     Assert(!pCtx->msrEFER);
 
+    /* IA32_MISC_ENABLE - not entirely sure what the init/reset state really
+       is supposed to be here, just trying provide useful/sensible values. */
+    PCPUMMSRRANGE pRange = cpumLookupMsrRange(pVM, MSR_IA32_MISC_ENABLE);
+    if (pRange)
+    {
+        pVCpu->cpum.s.GuestMsrs.msr.MiscEnable = MSR_IA32_MISC_ENABLE_BTS_UNAVAIL
+                                               | MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL
+                                               | (pVM->cpum.s.GuestFeatures.fMonitorMWait ? MSR_IA32_MISC_ENABLE_MONITOR : 0)
+                                               | MSR_IA32_MISC_ENABLE_FAST_STRINGS;
+        pRange->fWrIgnMask |= MSR_IA32_MISC_ENABLE_BTS_UNAVAIL
+                            | MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL;
+        pRange->fWrGpMask  &= ~pVCpu->cpum.s.GuestMsrs.msr.MiscEnable;
+    }
+
+    /** @todo Wire IA32_MISC_ENABLE bit 22 to our NT 4 CPUID trick. */
+
     /** @todo r=ramshankar: Currently broken for SMP as TMCpuTickSet() expects to be
      *        called from each EMT while we're getting called by CPUMR3Reset()
      *        iteratively on the same thread. Fix later.  */
-#if 0
+#if 0 /** @todo r=bird: This we will do in TM, not here. */
     /* TSC must be 0. Intel spec. Table 9-1. "IA-32 Processor States Following Power-up, Reset, or INIT." */
     CPUMSetGuestMsr(pVCpu, MSR_IA32_TSC, 0);
 #endif
@@ -1675,7 +1980,7 @@ VMMR3DECL(void) CPUMR3Reset(PVM pVM)
 {
     for (VMCPUID i = 0; i < pVM->cCpus; i++)
     {
-        CPUMR3ResetCpu(&pVM->aCpus[i]);
+        CPUMR3ResetCpu(pVM, &pVM->aCpus[i]);
 
 #ifdef VBOX_WITH_CRASHDUMP_MAGIC
         PCPUMCTX pCtx = &pVM->aCpus[i].cpum.s.Guest;
@@ -1718,18 +2023,73 @@ static void cpumR3SaveCpuId(PVM pVM, PSSMHANDLE pSSM)
      */
     CPUMCPUID   aRawStd[16];
     for (unsigned i = 0; i < RT_ELEMENTS(aRawStd); i++)
-        ASMCpuId(i, &aRawStd[i].eax, &aRawStd[i].ebx, &aRawStd[i].ecx, &aRawStd[i].edx);
+        ASMCpuIdExSlow(i, 0, 0, 0, &aRawStd[i].eax, &aRawStd[i].ebx, &aRawStd[i].ecx, &aRawStd[i].edx);
     SSMR3PutU32(pSSM, RT_ELEMENTS(aRawStd));
     SSMR3PutMem(pSSM, &aRawStd[0], sizeof(aRawStd));
 
     CPUMCPUID   aRawExt[32];
     for (unsigned i = 0; i < RT_ELEMENTS(aRawExt); i++)
-        ASMCpuId(i | UINT32_C(0x80000000), &aRawExt[i].eax, &aRawExt[i].ebx, &aRawExt[i].ecx, &aRawExt[i].edx);
+        ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0, &aRawExt[i].eax, &aRawExt[i].ebx, &aRawExt[i].ecx, &aRawExt[i].edx);
     SSMR3PutU32(pSSM, RT_ELEMENTS(aRawExt));
     SSMR3PutMem(pSSM, &aRawExt[0], sizeof(aRawExt));
 }
 
 
+static int cpumR3LoadCpuIdOneGuestArray(PSSMHANDLE pSSM, uint32_t uBase, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves)
+{
+    uint32_t cCpuIds;
+    int rc = SSMR3GetU32(pSSM, &cCpuIds);
+    if (RT_SUCCESS(rc))
+    {
+        if (cCpuIds < 64)
+        {
+            for (uint32_t i = 0; i < cCpuIds; i++)
+            {
+                CPUMCPUID CpuId;
+                rc = SSMR3GetMem(pSSM, &CpuId, sizeof(CpuId));
+                if (RT_FAILURE(rc))
+                    break;
+
+                CPUMCPUIDLEAF NewLeaf;
+                NewLeaf.uLeaf           = uBase + i;
+                NewLeaf.uSubLeaf        = 0;
+                NewLeaf.fSubLeafMask    = 0;
+                NewLeaf.uEax            = CpuId.eax;
+                NewLeaf.uEbx            = CpuId.ebx;
+                NewLeaf.uEcx            = CpuId.ecx;
+                NewLeaf.uEdx            = CpuId.edx;
+                NewLeaf.fFlags          = 0;
+                rc = cpumR3CpuIdInsert(ppaLeaves, pcLeaves, &NewLeaf);
+            }
+        }
+        else
+            rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
+    }
+    if (RT_FAILURE(rc))
+    {
+        RTMemFree(*ppaLeaves);
+        *ppaLeaves = NULL;
+        *pcLeaves = 0;
+    }
+    return rc;
+}
+
+
+static int cpumR3LoadCpuIdGuestArrays(PSSMHANDLE pSSM, uint32_t uVersion, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves)
+{
+    *ppaLeaves = NULL;
+    *pcLeaves = 0;
+
+    int rc = cpumR3LoadCpuIdOneGuestArray(pSSM, UINT32_C(0x00000000), ppaLeaves, pcLeaves);
+    if (RT_SUCCESS(rc))
+        rc = cpumR3LoadCpuIdOneGuestArray(pSSM, UINT32_C(0x80000000), ppaLeaves, pcLeaves);
+    if (RT_SUCCESS(rc))
+        rc = cpumR3LoadCpuIdOneGuestArray(pSSM, UINT32_C(0xc0000000), ppaLeaves, pcLeaves);
+
+    return rc;
+}
+
+
 /**
  * Loads the CPU ID leaves saved by pass 0.
  *
@@ -1811,7 +2171,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
         if (    (aGuestCpuId##set [1].reg & bit) \
             && !(aHostRaw##set [1].reg & bit) \
             && !(aHostOverride##set [1].reg & bit) \
-            && !(aGuestOverride##set [1].reg & bit) \
            ) \
         { \
             if (fStrictCpuIdChecks) \
@@ -1825,7 +2184,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
         if (    (aGuestCpuId##set [1].reg & bit) \
             && !(aHostRaw##set [1].reg & bit) \
             && !(aHostOverride##set [1].reg & bit) \
-            && !(aGuestOverride##set [1].reg & bit) \
            ) \
             LogRel(("CPUM: " #bit " is not supported by the host but has already exposed to the guest\n")); \
     } while (0)
@@ -1834,7 +2192,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
         if (    (aGuestCpuId##set [1].reg & bit) \
             && !(aHostRaw##set [1].reg & bit) \
             && !(aHostOverride##set [1].reg & bit) \
-            && !(aGuestOverride##set [1].reg & bit) \
            ) \
             LogRel(("CPUM: Warning - " #bit " is not supported by the host but already exposed to the guest. This may impact performance.\n")); \
     } while (0)
@@ -1847,7 +2204,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
             &&  fGuestAmd \
             && (!fGuestAmd || !(aHostRaw##set [1].reg & bit)) \
             && !(aHostOverride##set [1].reg & bit) \
-            && !(aGuestOverride##set [1].reg & bit) \
            ) \
         { \
             if (fStrictCpuIdChecks) \
@@ -1862,7 +2218,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
             &&  fGuestAmd \
             && (!fGuestAmd || !(aHostRaw##set [1].reg & bit)) \
             && !(aHostOverride##set [1].reg & bit) \
-            && !(aGuestOverride##set [1].reg & bit) \
            ) \
             LogRel(("CPUM: " #bit " is not supported by the host but has already exposed to the guest\n")); \
     } while (0)
@@ -1872,7 +2227,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
             &&  fGuestAmd \
             && (!fGuestAmd || !(aHostRaw##set [1].reg & bit)) \
             && !(aHostOverride##set [1].reg & bit) \
-            && !(aGuestOverride##set [1].reg & bit) \
            ) \
             LogRel(("CPUM: Warning - " #bit " is not supported by the host but already exposed to the guest. This may impact performance.\n")); \
     } while (0)
@@ -1887,7 +2241,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
                  ? aHostRawExt[1].reg      & (ExtBit) \
                  : aHostRawStd[1].reg      & (StdBit)) \
             && !(aHostOverrideExt[1].reg   & (ExtBit)) \
-            && !(aGuestOverrideExt[1].reg  & (ExtBit)) \
            ) \
         { \
             if (fStrictCpuIdChecks) \
@@ -1903,7 +2256,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
                  ? aHostRawExt[1].reg      & (ExtBit) \
                  : aHostRawStd[1].reg      & (StdBit)) \
             && !(aHostOverrideExt[1].reg   & (ExtBit)) \
-            && !(aGuestOverrideExt[1].reg  & (ExtBit)) \
            ) \
             LogRel(("CPUM: " #ExtBit " is not supported by the host but has already exposed to the guest\n")); \
     } while (0)
@@ -1914,7 +2266,6 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
                  ? aHostRawExt[1].reg      & (ExtBit) \
                  : aHostRawStd[1].reg      & (StdBit)) \
             && !(aHostOverrideExt[1].reg   & (ExtBit)) \
-            && !(aGuestOverrideExt[1].reg  & (ExtBit)) \
            ) \
             LogRel(("CPUM: Warning - " #ExtBit " is not supported by the host but already exposed to the guest. This may impact performance.\n")); \
     } while (0)
@@ -1923,26 +2274,12 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
     /*
      * Load them into stack buffers first.
      */
-    CPUMCPUID   aGuestCpuIdStd[RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdStd)];
-    uint32_t    cGuestCpuIdStd;
-    int rc = SSMR3GetU32(pSSM, &cGuestCpuIdStd); AssertRCReturn(rc, rc);
-    if (cGuestCpuIdStd > RT_ELEMENTS(aGuestCpuIdStd))
-        return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
-    SSMR3GetMem(pSSM, &aGuestCpuIdStd[0], cGuestCpuIdStd * sizeof(aGuestCpuIdStd[0]));
-
-    CPUMCPUID   aGuestCpuIdExt[RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdExt)];
-    uint32_t    cGuestCpuIdExt;
-    rc = SSMR3GetU32(pSSM, &cGuestCpuIdExt); AssertRCReturn(rc, rc);
-    if (cGuestCpuIdExt > RT_ELEMENTS(aGuestCpuIdExt))
-        return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
-    SSMR3GetMem(pSSM, &aGuestCpuIdExt[0], cGuestCpuIdExt * sizeof(aGuestCpuIdExt[0]));
+    PCPUMCPUIDLEAF paLeaves;
+    uint32_t       cLeaves;
+    int rc = cpumR3LoadCpuIdGuestArrays(pSSM, uVersion, &paLeaves, &cLeaves);
+    AssertRCReturn(rc, rc);
 
-    CPUMCPUID   aGuestCpuIdCentaur[RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdCentaur)];
-    uint32_t    cGuestCpuIdCentaur;
-    rc = SSMR3GetU32(pSSM, &cGuestCpuIdCentaur); AssertRCReturn(rc, rc);
-    if (cGuestCpuIdCentaur > RT_ELEMENTS(aGuestCpuIdCentaur))
-        return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
-    SSMR3GetMem(pSSM, &aGuestCpuIdCentaur[0], cGuestCpuIdCentaur * sizeof(aGuestCpuIdCentaur[0]));
+    /** @todo we'll be leaking paLeaves on error return... */
 
     CPUMCPUID   GuestCpuIdDef;
     rc = SSMR3GetMem(pSSM, &GuestCpuIdDef, sizeof(GuestCpuIdDef));
@@ -1953,7 +2290,10 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
     rc = SSMR3GetU32(pSSM, &cRawStd); AssertRCReturn(rc, rc);
     if (cRawStd > RT_ELEMENTS(aRawStd))
         return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
-    SSMR3GetMem(pSSM, &aRawStd[0], cRawStd * sizeof(aRawStd[0]));
+    rc = SSMR3GetMem(pSSM, &aRawStd[0], cRawStd * sizeof(aRawStd[0]));
+    AssertRCReturn(rc, rc);
+    for (uint32_t i = cRawStd; i < RT_ELEMENTS(aRawStd); i++)
+        ASMCpuIdExSlow(i, 0, 0, 0, &aRawStd[i].eax, &aRawStd[i].ebx, &aRawStd[i].ecx, &aRawStd[i].edx);
 
     CPUMCPUID   aRawExt[32];
     uint32_t    cRawExt;
@@ -1962,54 +2302,27 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
         return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
     rc = SSMR3GetMem(pSSM, &aRawExt[0], cRawExt * sizeof(aRawExt[0]));
     AssertRCReturn(rc, rc);
-
-    /*
-     * Note that we support restoring less than the current amount of standard
-     * leaves because we've been allowed more is newer version of VBox.
-     *
-     * So, pad new entries with the default.
-     */
-    for (uint32_t i = cGuestCpuIdStd; i < RT_ELEMENTS(aGuestCpuIdStd); i++)
-        aGuestCpuIdStd[i] = GuestCpuIdDef;
-
-    for (uint32_t i = cGuestCpuIdExt; i < RT_ELEMENTS(aGuestCpuIdExt); i++)
-        aGuestCpuIdExt[i] = GuestCpuIdDef;
-
-    for (uint32_t i = cGuestCpuIdCentaur; i < RT_ELEMENTS(aGuestCpuIdCentaur); i++)
-        aGuestCpuIdCentaur[i] = GuestCpuIdDef;
-
-    for (uint32_t i = cRawStd; i < RT_ELEMENTS(aRawStd); i++)
-        ASMCpuId(i, &aRawStd[i].eax, &aRawStd[i].ebx, &aRawStd[i].ecx, &aRawStd[i].edx);
-
     for (uint32_t i = cRawExt; i < RT_ELEMENTS(aRawExt); i++)
-        ASMCpuId(i | UINT32_C(0x80000000), &aRawExt[i].eax, &aRawExt[i].ebx, &aRawExt[i].ecx, &aRawExt[i].edx);
+        ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0, &aRawExt[i].eax, &aRawExt[i].ebx, &aRawExt[i].ecx, &aRawExt[i].edx);
 
     /*
      * Get the raw CPU IDs for the current host.
      */
     CPUMCPUID   aHostRawStd[16];
     for (unsigned i = 0; i < RT_ELEMENTS(aHostRawStd); i++)
-        ASMCpuId(i, &aHostRawStd[i].eax, &aHostRawStd[i].ebx, &aHostRawStd[i].ecx, &aHostRawStd[i].edx);
+        ASMCpuIdExSlow(i, 0, 0, 0, &aHostRawStd[i].eax, &aHostRawStd[i].ebx, &aHostRawStd[i].ecx, &aHostRawStd[i].edx);
 
     CPUMCPUID   aHostRawExt[32];
     for (unsigned i = 0; i < RT_ELEMENTS(aHostRawExt); i++)
-        ASMCpuId(i | UINT32_C(0x80000000), &aHostRawExt[i].eax, &aHostRawExt[i].ebx, &aHostRawExt[i].ecx, &aHostRawExt[i].edx);
+        ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0,
+                       &aHostRawExt[i].eax, &aHostRawExt[i].ebx, &aHostRawExt[i].ecx, &aHostRawExt[i].edx);
 
     /*
      * Get the host and guest overrides so we don't reject the state because
      * some feature was enabled thru these interfaces.
      * Note! We currently only need the feature leaves, so skip rest.
      */
-    PCFGMNODE   pOverrideCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM/CPUID");
-    CPUMCPUID   aGuestOverrideStd[2];
-    memcpy(&aGuestOverrideStd[0], &aHostRawStd[0], sizeof(aGuestOverrideStd));
-    cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x00000000), &aGuestOverrideStd[0], RT_ELEMENTS(aGuestOverrideStd), pOverrideCfg);
-
-    CPUMCPUID   aGuestOverrideExt[2];
-    memcpy(&aGuestOverrideExt[0], &aHostRawExt[0], sizeof(aGuestOverrideExt));
-    cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x80000000), &aGuestOverrideExt[0], RT_ELEMENTS(aGuestOverrideExt), pOverrideCfg);
-
-    pOverrideCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM/HostCPUID");
+    PCFGMNODE   pOverrideCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM/HostCPUID");
     CPUMCPUID   aHostOverrideStd[2];
     memcpy(&aHostOverrideStd[0], &aHostRawStd[0], sizeof(aHostOverrideStd));
     cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x00000000), &aHostOverrideStd[0], RT_ELEMENTS(aHostOverrideStd), pOverrideCfg);
@@ -2260,6 +2573,10 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
      *      "EMU"  - Possible to emulate, could be lots of work and very slow.
      *      "EMU?" - Can this be emulated?
      */
+    CPUMCPUID aGuestCpuIdStd[2];
+    RT_ZERO(aGuestCpuIdStd);
+    cpumR3CpuIdGetLeafLegacy(paLeaves, cLeaves, 1, 0, &aGuestCpuIdStd[1]);
+
     /* CPUID(1).ecx */
     CPUID_GST_FEATURE_RET(Std, ecx, X86_CPUID_FEATURE_ECX_SSE3);    // -> EMU
     CPUID_GST_FEATURE_RET(Std, ecx, X86_CPUID_FEATURE_ECX_PCLMUL);  // -> EMU?
@@ -2329,8 +2646,9 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
     CPUID_GST_FEATURE_RET(Std, edx, X86_CPUID_FEATURE_EDX_PBE);     // -> EMU?
 
     /* CPUID(0x80000000). */
-    if (    aGuestCpuIdExt[0].eax >= UINT32_C(0x80000001)
-        &&  aGuestCpuIdExt[0].eax <  UINT32_C(0x8000007f))
+    CPUMCPUID aGuestCpuIdExt[2];
+    RT_ZERO(aGuestCpuIdExt);
+    if (cpumR3CpuIdGetLeafLegacy(paLeaves, cLeaves, UINT32_C(0x80000001), 0, &aGuestCpuIdExt[1]))
     {
         /** @todo deal with no 0x80000001 on the host. */
         bool const fHostAmd  = ASMIsAmdCpuEx(aHostRawStd[0].ebx, aHostRawStd[0].ecx, aHostRawStd[0].edx);
@@ -2408,10 +2726,14 @@ static int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
     /*
      * We're good, commit the CPU ID leaves.
      */
-    memcpy(&pVM->cpum.s.aGuestCpuIdStd[0],     &aGuestCpuIdStd[0],     sizeof(aGuestCpuIdStd));
-    memcpy(&pVM->cpum.s.aGuestCpuIdExt[0],     &aGuestCpuIdExt[0],     sizeof(aGuestCpuIdExt));
-    memcpy(&pVM->cpum.s.aGuestCpuIdCentaur[0], &aGuestCpuIdCentaur[0], sizeof(aGuestCpuIdCentaur));
-    pVM->cpum.s.GuestCpuIdDef = GuestCpuIdDef;
+    MMHyperFree(pVM, pVM->cpum.s.GuestInfo.paCpuIdLeavesR3);
+    pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = NIL_RTR0PTR;
+    pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = NIL_RTRCPTR;
+    pVM->cpum.s.GuestInfo.DefCpuId = GuestCpuIdDef;
+    rc = cpumR3CpuIdInstallAndExplodeLeaves(pVM, &pVM->cpum.s, paLeaves, cLeaves);
+    RTMemFree(paLeaves);
+    AssertLogRelRCReturn(rc, rc);
+
 
 #undef CPUID_CHECK_RET
 #undef CPUID_CHECK_WRN
@@ -2699,8 +3021,8 @@ static DECLCALLBACK(int) cpumR3LoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVers
      */
     /** @todo we should check the 64 bits capabilities too! */
     uint32_t au32CpuId[8] = {0,0,0,0, 0,0,0,0};
-    ASMCpuId(0, &au32CpuId[0], &au32CpuId[1], &au32CpuId[2], &au32CpuId[3]);
-    ASMCpuId(1, &au32CpuId[4], &au32CpuId[5], &au32CpuId[6], &au32CpuId[7]);
+    ASMCpuIdExSlow(0, 0, 0, 0, &au32CpuId[0], &au32CpuId[1], &au32CpuId[2], &au32CpuId[3]);
+    ASMCpuIdExSlow(1, 0, 0, 0, &au32CpuId[4], &au32CpuId[5], &au32CpuId[6], &au32CpuId[7]);
     uint32_t au32CpuIdSaved[8];
     rc = SSMR3GetMem(pSSM, &au32CpuIdSaved[0], sizeof(au32CpuIdSaved));
     if (RT_SUCCESS(rc))
@@ -3384,7 +3706,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
 
     uint32_t    cStdHstMax;
     uint32_t    dummy;
-    ASMCpuId_Idx_ECX(0, 0, &cStdHstMax, &dummy, &dummy, &dummy);
+    ASMCpuIdExSlow(0, 0, 0, 0, &cStdHstMax, &dummy, &dummy, &dummy);
 
     unsigned    cStdLstMax = RT_MAX(RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdStd), cStdHstMax);
 
@@ -3396,7 +3718,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
         if (i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdStd))
         {
             Guest = pVM->cpum.s.aGuestCpuIdStd[i];
-            ASMCpuId_Idx_ECX(i, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+            ASMCpuIdExSlow(i, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
 
             pHlp->pfnPrintf(pHlp,
                             "Gst: %08x  %08x %08x %08x %08x%s\n"
@@ -3407,7 +3729,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
         }
         else
         {
-            ASMCpuId_Idx_ECX(i, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+            ASMCpuIdExSlow(i, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
 
             pHlp->pfnPrintf(pHlp,
                             "Hst: %08x  %08x %08x %08x %08x\n",
@@ -3528,12 +3850,12 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
             if (uECX & RT_BIT(28))  pHlp->pfnPrintf(pHlp, " AVX");
             if (uECX & RT_BIT(29))  pHlp->pfnPrintf(pHlp, " 29");
             if (uECX & RT_BIT(30))  pHlp->pfnPrintf(pHlp, " 30");
-            if (uECX & RT_BIT(31))  pHlp->pfnPrintf(pHlp, " 31");
+            if (uECX & RT_BIT(31))  pHlp->pfnPrintf(pHlp, " HVP");
             pHlp->pfnPrintf(pHlp, "\n");
         }
         else
         {
-            ASMCpuId(1, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+            ASMCpuIdExSlow(1, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
 
             X86CPUIDFEATEDX EdxHost  = *(PX86CPUIDFEATEDX)&Host.edx;
             X86CPUIDFEATECX EcxHost  = *(PX86CPUIDFEATECX)&Host.ecx;
@@ -3625,7 +3947,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
     for (unsigned i = 0; i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdExt); i++)
     {
         Guest = pVM->cpum.s.aGuestCpuIdExt[i];
-        ASMCpuId(0x80000000 | i, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+        ASMCpuIdExSlow(0x80000000 | i, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
 
         pHlp->pfnPrintf(pHlp,
                         "Gst: %08x  %08x %08x %08x %08x%s\n"
@@ -3722,7 +4044,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
         }
         else
         {
-            ASMCpuId(0x80000001, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+            ASMCpuIdExSlow(0x80000001, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
 
             uint32_t uEdxGst = Guest.edx;
             uint32_t uEdxHst = Host.edx;
@@ -3917,7 +4239,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
     for (unsigned i = 0; i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdCentaur); i++)
     {
         Guest = pVM->cpum.s.aGuestCpuIdCentaur[i];
-        ASMCpuId(0xc0000000 | i, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+        ASMCpuIdExSlow(0xc0000000 | i, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
 
         pHlp->pfnPrintf(pHlp,
                         "Gst: %08x  %08x %08x %08x %08x%s\n"
@@ -3940,7 +4262,7 @@ static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha
 
     if (iVerbosity && cCentaurMax >= 1)
     {
-        ASMCpuId(0xc0000001, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
+        ASMCpuIdExSlow(0xc0000001, 0, 0, 0, &Host.eax, &Host.ebx, &Host.ecx, &Host.edx);
         uint32_t uEdxGst = pVM->cpum.s.aGuestCpuIdCentaur[1].edx;
         uint32_t uEdxHst = Host.edx;
 
diff --git a/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp b/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
new file mode 100644
index 0000000..e3d6f9a
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
@@ -0,0 +1,1312 @@
+/* $Id: CPUMR3CpuId.cpp $ */
+/** @file
+ * CPUM - CPU ID part.
+ */
+
+/*
+ * Copyright (C) 2013-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_CPUM
+#include <VBox/vmm/cpum.h>
+#include "CPUMInternal.h"
+#include <VBox/vmm/vm.h>
+
+#include <VBox/err.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/ctype.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/**
+ * The intel pentium family.
+ */
+static const CPUMMICROARCH g_aenmIntelFamily06[] =
+{
+    /* [ 0(0x00)] = */ kCpumMicroarch_Intel_P6,           /* Pentium Pro A-step (says sandpile.org). */
+    /* [ 1(0x01)] = */ kCpumMicroarch_Intel_P6,           /* Pentium Pro */
+    /* [ 2(0x02)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [ 3(0x03)] = */ kCpumMicroarch_Intel_P6_II,        /* PII Klamath */
+    /* [ 4(0x04)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [ 5(0x05)] = */ kCpumMicroarch_Intel_P6_II,        /* PII Deschutes */
+    /* [ 6(0x06)] = */ kCpumMicroarch_Intel_P6_II,        /* Celeron Mendocino. */
+    /* [ 7(0x07)] = */ kCpumMicroarch_Intel_P6_III,       /* PIII Katmai. */
+    /* [ 8(0x08)] = */ kCpumMicroarch_Intel_P6_III,       /* PIII Coppermine (includes Celeron). */
+    /* [ 9(0x09)] = */ kCpumMicroarch_Intel_P6_M_Banias,  /* Pentium/Celeron M Banias. */
+    /* [10(0x0a)] = */ kCpumMicroarch_Intel_P6_III,       /* PIII Xeon */
+    /* [11(0x0b)] = */ kCpumMicroarch_Intel_P6_III,       /* PIII Tualatin (includes Celeron). */
+    /* [12(0x0c)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [13(0x0d)] = */ kCpumMicroarch_Intel_P6_M_Dothan,  /* Pentium/Celeron M Dothan. */
+    /* [14(0x0e)] = */ kCpumMicroarch_Intel_Core_Yonah,   /* Core Yonah (Enhanced Pentium M). */
+    /* [15(0x0f)] = */ kCpumMicroarch_Intel_Core2_Merom,  /* Merom */
+    /* [16(0x10)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [17(0x11)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [18(0x12)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [19(0x13)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [20(0x14)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [21(0x15)] = */ kCpumMicroarch_Intel_P6_M_Dothan,  /* Tolapai - System-on-a-chip. */
+    /* [22(0x16)] = */ kCpumMicroarch_Intel_Core2_Merom,
+    /* [23(0x17)] = */ kCpumMicroarch_Intel_Core2_Penryn,
+    /* [24(0x18)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [25(0x19)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [26(0x1a)] = */ kCpumMicroarch_Intel_Core7_Nehalem,
+    /* [27(0x1b)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [28(0x1c)] = */ kCpumMicroarch_Intel_Atom_Bonnell, /* Diamonville, Pineview, */
+    /* [29(0x1d)] = */ kCpumMicroarch_Intel_Core2_Penryn,
+    /* [30(0x1e)] = */ kCpumMicroarch_Intel_Core7_Nehalem, /* Clarksfield, Lynnfield, Jasper Forest. */
+    /* [31(0x1f)] = */ kCpumMicroarch_Intel_Core7_Nehalem, /* Only listed by sandpile.org.  2 cores ABD/HVD, whatever that means. */
+    /* [32(0x20)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [33(0x21)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [34(0x22)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [35(0x23)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [36(0x24)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [37(0x25)] = */ kCpumMicroarch_Intel_Core7_Westmere, /* Arrandale, Clarksdale. */
+    /* [38(0x26)] = */ kCpumMicroarch_Intel_Atom_Lincroft,
+    /* [39(0x27)] = */ kCpumMicroarch_Intel_Atom_Saltwell,
+    /* [40(0x28)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [41(0x29)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [42(0x2a)] = */ kCpumMicroarch_Intel_Core7_SandyBridge,
+    /* [43(0x2b)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [44(0x2c)] = */ kCpumMicroarch_Intel_Core7_Westmere, /* Gulftown, Westmere-EP. */
+    /* [45(0x2d)] = */ kCpumMicroarch_Intel_Core7_SandyBridge, /* SandyBridge-E, SandyBridge-EN, SandyBridge-EP. */
+    /* [46(0x2e)] = */ kCpumMicroarch_Intel_Core7_Nehalem,  /* Beckton (Xeon). */
+    /* [47(0x2f)] = */ kCpumMicroarch_Intel_Core7_Westmere, /* Westmere-EX. */
+    /* [48(0x30)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [49(0x31)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [50(0x32)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [51(0x33)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [52(0x34)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [53(0x35)] = */ kCpumMicroarch_Intel_Atom_Saltwell, /* ?? */
+    /* [54(0x36)] = */ kCpumMicroarch_Intel_Atom_Saltwell, /* Cedarview, ++ */
+    /* [55(0x37)] = */ kCpumMicroarch_Intel_Atom_Silvermont,
+    /* [56(0x38)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [57(0x39)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [58(0x3a)] = */ kCpumMicroarch_Intel_Core7_IvyBridge,
+    /* [59(0x3b)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [60(0x3c)] = */ kCpumMicroarch_Intel_Core7_Haswell,
+    /* [61(0x3d)] = */ kCpumMicroarch_Intel_Core7_Broadwell,
+    /* [62(0x3e)] = */ kCpumMicroarch_Intel_Core7_IvyBridge,
+    /* [63(0x3f)] = */ kCpumMicroarch_Intel_Core7_Haswell,
+    /* [64(0x40)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [65(0x41)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [66(0x42)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [67(0x43)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [68(0x44)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [69(0x45)] = */ kCpumMicroarch_Intel_Core7_Haswell,
+    /* [70(0x46)] = */ kCpumMicroarch_Intel_Core7_Haswell,
+    /* [71(0x47)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [72(0x48)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [73(0x49)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [74(0x4a)] = */ kCpumMicroarch_Intel_Atom_Silvermont,
+    /* [75(0x4b)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [76(0x4c)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [77(0x4d)] = */ kCpumMicroarch_Intel_Atom_Silvermont,
+    /* [78(0x4e)] = */ kCpumMicroarch_Intel_Unknown,
+    /* [79(0x4f)] = */ kCpumMicroarch_Intel_Unknown,
+};
+
+
+
+/**
+ * Figures out the (sub-)micro architecture given a bit of CPUID info.
+ *
+ * @returns Micro architecture.
+ * @param   enmVendor           The CPU vendor .
+ * @param   bFamily             The CPU family.
+ * @param   bModel              The CPU model.
+ * @param   bStepping           The CPU stepping.
+ */
+VMMR3DECL(CPUMMICROARCH) CPUMR3CpuIdDetermineMicroarchEx(CPUMCPUVENDOR enmVendor, uint8_t bFamily,
+                                                         uint8_t bModel, uint8_t bStepping)
+{
+    if (enmVendor == CPUMCPUVENDOR_AMD)
+    {
+        switch (bFamily)
+        {
+            case 0x02:  return kCpumMicroarch_AMD_Am286; /* Not really kosher... */
+            case 0x03:  return kCpumMicroarch_AMD_Am386;
+            case 0x23:  return kCpumMicroarch_AMD_Am386; /* SX*/
+            case 0x04:  return bModel < 14 ? kCpumMicroarch_AMD_Am486 : kCpumMicroarch_AMD_Am486Enh;
+            case 0x05:  return bModel <  6 ? kCpumMicroarch_AMD_K5    : kCpumMicroarch_AMD_K6; /* Genode LX is 0x0a, lump it with K6. */
+            case 0x06:
+                switch (bModel)
+                {
+                    case  0: kCpumMicroarch_AMD_K7_Palomino;
+                    case  1: kCpumMicroarch_AMD_K7_Palomino;
+                    case  2: kCpumMicroarch_AMD_K7_Palomino;
+                    case  3: kCpumMicroarch_AMD_K7_Spitfire;
+                    case  4: kCpumMicroarch_AMD_K7_Thunderbird;
+                    case  6: kCpumMicroarch_AMD_K7_Palomino;
+                    case  7: kCpumMicroarch_AMD_K7_Morgan;
+                    case  8: kCpumMicroarch_AMD_K7_Thoroughbred;
+                    case 10: kCpumMicroarch_AMD_K7_Barton; /* Thorton too. */
+                }
+                return kCpumMicroarch_AMD_K7_Unknown;
+            case 0x0f:
+                /*
+                 * This family is a friggin mess. Trying my best to make some
+                 * sense out of it. Too much happened in the 0x0f family to
+                 * lump it all together as K8 (130nm->90nm->65nm, AMD-V, ++).
+                 *
+                 * Emperical CPUID.01h.EAX evidence from revision guides, wikipedia,
+                 * cpu-world.com, and other places:
+                 *  - 130nm:
+                 *     - ClawHammer:    F7A/SH-CG, F5A/-CG, F4A/-CG, F50/-B0, F48/-C0, F58/-C0,
+                 *     - SledgeHammer:  F50/SH-B0, F48/-C0, F58/-C0, F4A/-CG, F5A/-CG, F7A/-CG, F51/-B3
+                 *     - Newcastle:     FC0/DH-CG (errum #180: FE0/DH-CG), FF0/DH-CG
+                 *     - Dublin:        FC0/-CG, FF0/-CG, F82/CH-CG, F4A/-CG, F48/SH-C0,
+                 *     - Odessa:        FC0/DH-CG (errum #180: FE0/DH-CG)
+                 *     - Paris:         FF0/DH-CG, FC0/DH-CG (errum #180: FE0/DH-CG),
+                 *  - 90nm:
+                 *     - Winchester:    10FF0/DH-D0, 20FF0/DH-E3.
+                 *     - Oakville:      10FC0/DH-D0.
+                 *     - Georgetown:    10FC0/DH-D0.
+                 *     - Sonora:        10FC0/DH-D0.
+                 *     - Venus:         20F71/SH-E4
+                 *     - Troy:          20F51/SH-E4
+                 *     - Athens:        20F51/SH-E4
+                 *     - San Diego:     20F71/SH-E4.
+                 *     - Lancaster:     20F42/SH-E5
+                 *     - Newark:        20F42/SH-E5.
+                 *     - Albany:        20FC2/DH-E6.
+                 *     - Roma:          20FC2/DH-E6.
+                 *     - Venice:        20FF0/DH-E3, 20FC2/DH-E6, 20FF2/DH-E6.
+                 *     - Palermo:       10FC0/DH-D0, 20FF0/DH-E3, 20FC0/DH-E3, 20FC2/DH-E6, 20FF2/DH-E6
+                 *  - 90nm introducing Dual core:
+                 *     - Denmark:       20F30/JH-E1, 20F32/JH-E6
+                 *     - Italy:         20F10/JH-E1, 20F12/JH-E6
+                 *     - Egypt:         20F10/JH-E1, 20F12/JH-E6
+                 *     - Toledo:        20F32/JH-E6, 30F72/DH-E6 (single code variant).
+                 *     - Manchester:    20FB1/BH-E4, 30FF2/BH-E4.
+                 *  - 90nm 2nd gen opteron ++, AMD-V introduced (might be missing in some cheeper models):
+                 *     - Santa Ana:     40F32/JH-F2, /-F3
+                 *     - Santa Rosa:    40F12/JH-F2, 40F13/JH-F3
+                 *     - Windsor:       40F32/JH-F2, 40F33/JH-F3, C0F13/JH-F3, 40FB2/BH-F2, ??20FB1/BH-E4??.
+                 *     - Manila:        50FF2/DH-F2, 40FF2/DH-F2
+                 *     - Orleans:       40FF2/DH-F2, 50FF2/DH-F2, 50FF3/DH-F3.
+                 *     - Keene:         40FC2/DH-F2.
+                 *     - Richmond:      40FC2/DH-F2
+                 *     - Taylor:        40F82/BH-F2
+                 *     - Trinidad:      40F82/BH-F2
+                 *
+                 *  - 65nm:
+                 *     - Brisbane:      60FB1/BH-G1, 60FB2/BH-G2.
+                 *     - Tyler:         60F81/BH-G1, 60F82/BH-G2.
+                 *     - Sparta:        70FF1/DH-G1, 70FF2/DH-G2.
+                 *     - Lima:          70FF1/DH-G1, 70FF2/DH-G2.
+                 *     - Sherman:       /-G1, 70FC2/DH-G2.
+                 *     - Huron:         70FF2/DH-G2.
+                 */
+                if (bModel < 0x10)
+                    return kCpumMicroarch_AMD_K8_130nm;
+                if (bModel >= 0x60 && bModel < 0x80)
+                    return kCpumMicroarch_AMD_K8_65nm;
+                if (bModel >= 0x40)
+                    return kCpumMicroarch_AMD_K8_90nm_AMDV;
+                switch (bModel)
+                {
+                    case 0x21:
+                    case 0x23:
+                    case 0x2b:
+                    case 0x2f:
+                    case 0x37:
+                    case 0x3f:
+                        return kCpumMicroarch_AMD_K8_90nm_DualCore;
+                }
+                return kCpumMicroarch_AMD_K8_90nm;
+            case 0x10:
+                return kCpumMicroarch_AMD_K10;
+            case 0x11:
+                return kCpumMicroarch_AMD_K10_Lion;
+            case 0x12:
+                return kCpumMicroarch_AMD_K10_Llano;
+            case 0x14:
+                return kCpumMicroarch_AMD_Bobcat;
+            case 0x15:
+                switch (bModel)
+                {
+                    case 0x00:  return kCpumMicroarch_AMD_15h_Bulldozer;    /* Any? prerelease? */
+                    case 0x01:  return kCpumMicroarch_AMD_15h_Bulldozer;    /* Opteron 4200, FX-81xx. */
+                    case 0x02:  return kCpumMicroarch_AMD_15h_Piledriver;   /* Opteron 4300, FX-83xx. */
+                    case 0x10:  return kCpumMicroarch_AMD_15h_Piledriver;   /* A10-5800K for e.g. */
+                    case 0x11:  /* ?? */
+                    case 0x12:  /* ?? */
+                    case 0x13:  return kCpumMicroarch_AMD_15h_Piledriver;   /* A10-6800K for e.g. */
+                }
+                return kCpumMicroarch_AMD_15h_Unknown;
+            case 0x16:
+                return kCpumMicroarch_AMD_Jaguar;
+
+        }
+        return kCpumMicroarch_AMD_Unknown;
+    }
+
+    if (enmVendor == CPUMCPUVENDOR_INTEL)
+    {
+        switch (bFamily)
+        {
+            case 3:
+                return kCpumMicroarch_Intel_80386;
+            case 4:
+                return kCpumMicroarch_Intel_80486;
+            case 5:
+                return kCpumMicroarch_Intel_P5;
+            case 6:
+                if (bModel < RT_ELEMENTS(g_aenmIntelFamily06))
+                    return g_aenmIntelFamily06[bModel];
+                return kCpumMicroarch_Intel_Atom_Unknown;
+            case 15:
+                switch (bModel)
+                {
+                    case 0:     return kCpumMicroarch_Intel_NB_Willamette;
+                    case 1:     return kCpumMicroarch_Intel_NB_Willamette;
+                    case 2:     return kCpumMicroarch_Intel_NB_Northwood;
+                    case 3:     return kCpumMicroarch_Intel_NB_Prescott;
+                    case 4:     return kCpumMicroarch_Intel_NB_Prescott2M; /* ?? */
+                    case 5:     return kCpumMicroarch_Intel_NB_Unknown; /*??*/
+                    case 6:     return kCpumMicroarch_Intel_NB_CedarMill;
+                    case 7:     return kCpumMicroarch_Intel_NB_Gallatin;
+                    default:    return kCpumMicroarch_Intel_NB_Unknown;
+                }
+                break;
+            /* The following are not kosher but kind of follow intuitively from 6, 5 & 4. */
+            case 1:
+                return kCpumMicroarch_Intel_8086;
+            case 2:
+                return kCpumMicroarch_Intel_80286;
+        }
+        return kCpumMicroarch_Intel_Unknown;
+    }
+
+    if (enmVendor == CPUMCPUVENDOR_VIA)
+    {
+        switch (bFamily)
+        {
+            case 5:
+                switch (bModel)
+                {
+                    case 1: return kCpumMicroarch_Centaur_C6;
+                    case 4: return kCpumMicroarch_Centaur_C6;
+                    case 8: return kCpumMicroarch_Centaur_C2;
+                    case 9: return kCpumMicroarch_Centaur_C3;
+                }
+                break;
+
+            case 6:
+                switch (bModel)
+                {
+                    case  5: return kCpumMicroarch_VIA_C3_M2;
+                    case  6: return kCpumMicroarch_VIA_C3_C5A;
+                    case  7: return bStepping < 8 ? kCpumMicroarch_VIA_C3_C5B : kCpumMicroarch_VIA_C3_C5C;
+                    case  8: return kCpumMicroarch_VIA_C3_C5N;
+                    case  9: return bStepping < 8 ? kCpumMicroarch_VIA_C3_C5XL : kCpumMicroarch_VIA_C3_C5P;
+                    case 10: return kCpumMicroarch_VIA_C7_C5J;
+                    case 15: return kCpumMicroarch_VIA_Isaiah;
+                }
+                break;
+        }
+        return kCpumMicroarch_VIA_Unknown;
+    }
+
+    if (enmVendor == CPUMCPUVENDOR_CYRIX)
+    {
+        switch (bFamily)
+        {
+            case 4:
+                switch (bModel)
+                {
+                    case 9: return kCpumMicroarch_Cyrix_5x86;
+                }
+                break;
+
+            case 5:
+                switch (bModel)
+                {
+                    case 2: return kCpumMicroarch_Cyrix_M1;
+                    case 4: return kCpumMicroarch_Cyrix_MediaGX;
+                    case 5: return kCpumMicroarch_Cyrix_MediaGXm;
+                }
+                break;
+
+            case 6:
+                switch (bModel)
+                {
+                    case 0: return kCpumMicroarch_Cyrix_M2;
+                }
+                break;
+
+        }
+        return kCpumMicroarch_Cyrix_Unknown;
+    }
+
+    return kCpumMicroarch_Unknown;
+}
+
+
+/**
+ * Translates a microarchitecture enum value to the corresponding string
+ * constant.
+ *
+ * @returns Read-only string constant (omits "kCpumMicroarch_" prefix). Returns
+ *          NULL if the value is invalid.
+ *
+ * @param   enmMicroarch    The enum value to convert.
+ */
+VMMR3DECL(const char *) CPUMR3MicroarchName(CPUMMICROARCH enmMicroarch)
+{
+    switch (enmMicroarch)
+    {
+#define CASE_RET_STR(enmValue)  case enmValue: return #enmValue + (sizeof("kCpumMicroarch_") - 1)
+        CASE_RET_STR(kCpumMicroarch_Intel_8086);
+        CASE_RET_STR(kCpumMicroarch_Intel_80186);
+        CASE_RET_STR(kCpumMicroarch_Intel_80286);
+        CASE_RET_STR(kCpumMicroarch_Intel_80386);
+        CASE_RET_STR(kCpumMicroarch_Intel_80486);
+        CASE_RET_STR(kCpumMicroarch_Intel_P5);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_P6);
+        CASE_RET_STR(kCpumMicroarch_Intel_P6_II);
+        CASE_RET_STR(kCpumMicroarch_Intel_P6_III);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_P6_M_Banias);
+        CASE_RET_STR(kCpumMicroarch_Intel_P6_M_Dothan);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core_Yonah);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_Core2_Merom);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core2_Penryn);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_Nehalem);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_Westmere);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_SandyBridge);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_IvyBridge);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_Haswell);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_Broadwell);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_Skylake);
+        CASE_RET_STR(kCpumMicroarch_Intel_Core7_Cannonlake);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Bonnell);
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Lincroft);
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Saltwell);
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Silvermont);
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Airmount);
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Goldmont);
+        CASE_RET_STR(kCpumMicroarch_Intel_Atom_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_Willamette);
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_Northwood);
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_Prescott);
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_Prescott2M);
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_CedarMill);
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_Gallatin);
+        CASE_RET_STR(kCpumMicroarch_Intel_NB_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_Intel_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_Am286);
+        CASE_RET_STR(kCpumMicroarch_AMD_Am386);
+        CASE_RET_STR(kCpumMicroarch_AMD_Am486);
+        CASE_RET_STR(kCpumMicroarch_AMD_Am486Enh);
+        CASE_RET_STR(kCpumMicroarch_AMD_K5);
+        CASE_RET_STR(kCpumMicroarch_AMD_K6);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Palomino);
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Spitfire);
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Thunderbird);
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Morgan);
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Thoroughbred);
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Barton);
+        CASE_RET_STR(kCpumMicroarch_AMD_K7_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_K8_130nm);
+        CASE_RET_STR(kCpumMicroarch_AMD_K8_90nm);
+        CASE_RET_STR(kCpumMicroarch_AMD_K8_90nm_DualCore);
+        CASE_RET_STR(kCpumMicroarch_AMD_K8_90nm_AMDV);
+        CASE_RET_STR(kCpumMicroarch_AMD_K8_65nm);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_K10);
+        CASE_RET_STR(kCpumMicroarch_AMD_K10_Lion);
+        CASE_RET_STR(kCpumMicroarch_AMD_K10_Llano);
+        CASE_RET_STR(kCpumMicroarch_AMD_Bobcat);
+        CASE_RET_STR(kCpumMicroarch_AMD_Jaguar);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_15h_Bulldozer);
+        CASE_RET_STR(kCpumMicroarch_AMD_15h_Piledriver);
+        CASE_RET_STR(kCpumMicroarch_AMD_15h_Steamroller);
+        CASE_RET_STR(kCpumMicroarch_AMD_15h_Excavator);
+        CASE_RET_STR(kCpumMicroarch_AMD_15h_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_16h_First);
+
+        CASE_RET_STR(kCpumMicroarch_AMD_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_Centaur_C6);
+        CASE_RET_STR(kCpumMicroarch_Centaur_C2);
+        CASE_RET_STR(kCpumMicroarch_Centaur_C3);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_M2);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_C5A);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_C5B);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_C5C);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_C5N);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_C5XL);
+        CASE_RET_STR(kCpumMicroarch_VIA_C3_C5P);
+        CASE_RET_STR(kCpumMicroarch_VIA_C7_C5J);
+        CASE_RET_STR(kCpumMicroarch_VIA_Isaiah);
+        CASE_RET_STR(kCpumMicroarch_VIA_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_Cyrix_5x86);
+        CASE_RET_STR(kCpumMicroarch_Cyrix_M1);
+        CASE_RET_STR(kCpumMicroarch_Cyrix_MediaGX);
+        CASE_RET_STR(kCpumMicroarch_Cyrix_MediaGXm);
+        CASE_RET_STR(kCpumMicroarch_Cyrix_M2);
+        CASE_RET_STR(kCpumMicroarch_Cyrix_Unknown);
+
+        CASE_RET_STR(kCpumMicroarch_Unknown);
+
+#undef CASE_RET_STR
+        case kCpumMicroarch_Invalid:
+        case kCpumMicroarch_Intel_End:
+        case kCpumMicroarch_Intel_Core7_End:
+        case kCpumMicroarch_Intel_Atom_End:
+        case kCpumMicroarch_Intel_P6_Core_Atom_End:
+        case kCpumMicroarch_Intel_NB_End:
+        case kCpumMicroarch_AMD_K7_End:
+        case kCpumMicroarch_AMD_K8_End:
+        case kCpumMicroarch_AMD_15h_End:
+        case kCpumMicroarch_AMD_16h_End:
+        case kCpumMicroarch_AMD_End:
+        case kCpumMicroarch_VIA_End:
+        case kCpumMicroarch_Cyrix_End:
+        case kCpumMicroarch_32BitHack:
+            break;
+        /* no default! */
+    }
+
+    return NULL;
+}
+
+
+
+/**
+ * Gets a matching leaf in the CPUID leaf array.
+ *
+ * @returns Pointer to the matching leaf, or NULL if not found.
+ * @param   paLeaves            The CPUID leaves to search.  This is sorted.
+ * @param   cLeaves             The number of leaves in the array.
+ * @param   uLeaf               The leaf to locate.
+ * @param   uSubLeaf            The subleaf to locate.  Pass 0 if no subleaves.
+ */
+PCPUMCPUIDLEAF cpumR3CpuIdGetLeaf(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf)
+{
+    /* Lazy bird does linear lookup here since this is only used for the
+       occational CPUID overrides. */
+    for (uint32_t i = 0; i < cLeaves; i++)
+        if (   paLeaves[i].uLeaf    == uLeaf
+            && paLeaves[i].uSubLeaf == (uSubLeaf & paLeaves[i].fSubLeafMask))
+            return &paLeaves[i];
+    return NULL;
+}
+
+
+/**
+ * Gets a matching leaf in the CPUID leaf array, converted to a CPUMCPUID.
+ *
+ * @returns true if found, false it not.
+ * @param   paLeaves            The CPUID leaves to search.  This is sorted.
+ * @param   cLeaves             The number of leaves in the array.
+ * @param   uLeaf               The leaf to locate.
+ * @param   uSubLeaf            The subleaf to locate.  Pass 0 if no subleaves.
+ * @param   pLegacy             The legacy output leaf.
+ */
+bool cpumR3CpuIdGetLeafLegacy(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf, PCPUMCPUID pLeagcy)
+{
+    PCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(paLeaves, cLeaves, uLeaf, uSubLeaf);
+    if (pLeaf)
+    {
+        pLeagcy->eax = pLeaf->uEax;
+        pLeagcy->ebx = pLeaf->uEbx;
+        pLeagcy->ecx = pLeaf->uEcx;
+        pLeagcy->edx = pLeaf->uEdx;
+        return true;
+    }
+    return false;
+}
+
+
+/**
+ * Ensures that the CPUID leaf array can hold one more leaf.
+ *
+ * @returns Pointer to the CPUID leaf array (*ppaLeaves) on success.  NULL on
+ *          failure.
+ * @param   ppaLeaves           Pointer to the variable holding the array
+ *                              pointer (input/output).
+ * @param   cLeaves             The current array size.
+ */
+static PCPUMCPUIDLEAF cpumR3CpuIdEnsureSpace(PCPUMCPUIDLEAF *ppaLeaves, uint32_t cLeaves)
+{
+    uint32_t cAllocated = RT_ALIGN(cLeaves, 16);
+    if (cLeaves + 1 > cAllocated)
+    {
+        void *pvNew = RTMemRealloc(*ppaLeaves, (cAllocated + 16) * sizeof(**ppaLeaves));
+        if (!pvNew)
+        {
+            RTMemFree(*ppaLeaves);
+            *ppaLeaves = NULL;
+            return NULL;
+        }
+        *ppaLeaves   = (PCPUMCPUIDLEAF)pvNew;
+    }
+    return *ppaLeaves;
+}
+
+
+/**
+ * Append a CPUID leaf or sub-leaf.
+ *
+ * ASSUMES linear insertion order, so we'll won't need to do any searching or
+ * replace anything.  Use cpumR3CpuIdInsert for those cases.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_MEMORY.  On error, *ppaLeaves is freed, so
+ *          the caller need do no more work.
+ * @param   ppaLeaves       Pointer to the the pointer to the array of sorted
+ *                          CPUID leaves and sub-leaves.
+ * @param   pcLeaves        Where we keep the leaf count for *ppaLeaves.
+ * @param   uLeaf           The leaf we're adding.
+ * @param   uSubLeaf        The sub-leaf number.
+ * @param   fSubLeafMask    The sub-leaf mask.
+ * @param   uEax            The EAX value.
+ * @param   uEbx            The EBX value.
+ * @param   uEcx            The ECX value.
+ * @param   uEdx            The EDX value.
+ * @param   fFlags          The flags.
+ */
+static int cpumR3CollectCpuIdInfoAddOne(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves,
+                                        uint32_t uLeaf, uint32_t uSubLeaf, uint32_t fSubLeafMask,
+                                        uint32_t uEax, uint32_t uEbx, uint32_t uEcx, uint32_t uEdx, uint32_t fFlags)
+{
+    if (!cpumR3CpuIdEnsureSpace(ppaLeaves, *pcLeaves))
+        return VERR_NO_MEMORY;
+
+    PCPUMCPUIDLEAF pNew = &(*ppaLeaves)[*pcLeaves];
+    Assert(   *pcLeaves == 0
+           || pNew[-1].uLeaf < uLeaf
+           || (pNew[-1].uLeaf == uLeaf && pNew[-1].uSubLeaf < uSubLeaf) );
+
+    pNew->uLeaf        = uLeaf;
+    pNew->uSubLeaf     = uSubLeaf;
+    pNew->fSubLeafMask = fSubLeafMask;
+    pNew->uEax         = uEax;
+    pNew->uEbx         = uEbx;
+    pNew->uEcx         = uEcx;
+    pNew->uEdx         = uEdx;
+    pNew->fFlags       = fFlags;
+
+    *pcLeaves += 1;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Inserts a CPU ID leaf, replacing any existing ones.
+ *
+ * When inserting a simple leaf where we already got a series of subleaves with
+ * the same leaf number (eax), the simple leaf will replace the whole series.
+ *
+ * This ASSUMES that the leave array is still on the normal heap and has only
+ * been allocated/reallocated by the cpumR3CpuIdEnsureSpace function.
+ *
+ * @returns VBox status code.
+ * @param   ppaLeaves       Pointer to the the pointer to the array of sorted
+ *                          CPUID leaves and sub-leaves.
+ * @param   pcLeaves        Where we keep the leaf count for *ppaLeaves.
+ * @param   pNewLeaf        Pointer to the data of the new leaf we're about to
+ *                          insert.
+ */
+int cpumR3CpuIdInsert(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves, PCPUMCPUIDLEAF pNewLeaf)
+{
+    PCPUMCPUIDLEAF  paLeaves = *ppaLeaves;
+    uint32_t        cLeaves  = *pcLeaves;
+
+    /*
+     * Validate the new leaf a little.
+     */
+    AssertReturn(!(pNewLeaf->fFlags & ~CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED), VERR_INVALID_FLAGS);
+    AssertReturn(pNewLeaf->fSubLeafMask != 0 || pNewLeaf->uSubLeaf == 0, VERR_INVALID_PARAMETER);
+    AssertReturn(RT_IS_POWER_OF_TWO(pNewLeaf->fSubLeafMask + 1), VERR_INVALID_PARAMETER);
+    AssertReturn((pNewLeaf->fSubLeafMask & pNewLeaf->uSubLeaf) == pNewLeaf->uSubLeaf, VERR_INVALID_PARAMETER);
+
+
+    /*
+     * Find insertion point. The lazy bird uses the same excuse as in
+     * cpumR3CpuIdGetLeaf().
+     */
+    uint32_t i = 0;
+    while (   i < cLeaves
+           && paLeaves[i].uLeaf < pNewLeaf->uLeaf)
+        i++;
+    if (   i < cLeaves
+        && paLeaves[i].uLeaf == pNewLeaf->uLeaf)
+    {
+        if (paLeaves[i].fSubLeafMask != pNewLeaf->fSubLeafMask)
+        {
+            /*
+             * The subleaf mask differs, replace all existing leaves with the
+             * same leaf number.
+             */
+            uint32_t c = 1;
+            while (   i + c < cLeaves
+                   && paLeaves[i + c].uSubLeaf == pNewLeaf->uLeaf)
+                c++;
+            if (c > 1 && i + c < cLeaves)
+            {
+                memmove(&paLeaves[i + c], &paLeaves[i + 1], (cLeaves - i - c) * sizeof(paLeaves[0]));
+                *pcLeaves = cLeaves -= c - 1;
+            }
+
+            paLeaves[i] = *pNewLeaf;
+            return VINF_SUCCESS;
+        }
+
+        /* Find subleaf insertion point. */
+        while (   i < cLeaves
+               && paLeaves[i].uSubLeaf < pNewLeaf->uSubLeaf)
+            i++;
+
+        /*
+         * If we've got an exactly matching leaf, replace it.
+         */
+        if (   paLeaves[i].uLeaf    == pNewLeaf->uLeaf
+            && paLeaves[i].uSubLeaf == pNewLeaf->uSubLeaf)
+        {
+            paLeaves[i] = *pNewLeaf;
+            return VINF_SUCCESS;
+        }
+    }
+
+    /*
+     * Adding a new leaf at 'i'.
+     */
+    paLeaves = cpumR3CpuIdEnsureSpace(ppaLeaves, cLeaves);
+    if (!paLeaves)
+        return VERR_NO_MEMORY;
+
+    if (i < cLeaves)
+        memmove(&paLeaves[i + 1], &paLeaves[i], (cLeaves - i) * sizeof(paLeaves[0]));
+    *pcLeaves += 1;
+    paLeaves[i] = *pNewLeaf;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Removes a range of CPUID leaves.
+ *
+ * This will not reallocate the array.
+ *
+ * @param   paLeaves        The array of sorted CPUID leaves and sub-leaves.
+ * @param   pcLeaves        Where we keep the leaf count for @a paLeaves.
+ * @param   uFirst          The first leaf.
+ * @param   uLast           The last leaf.
+ */
+void cpumR3CpuIdRemoveRange(PCPUMCPUIDLEAF paLeaves, uint32_t *pcLeaves, uint32_t uFirst, uint32_t uLast)
+{
+    uint32_t cLeaves = *pcLeaves;
+
+    Assert(uFirst <= uLast);
+
+    /*
+     * Find the first one.
+     */
+    uint32_t iFirst = 0;
+    while (   iFirst < cLeaves
+           && paLeaves[iFirst].uLeaf < uFirst)
+        iFirst++;
+
+    /*
+     * Find the end (last + 1).
+     */
+    uint32_t iEnd = iFirst;
+    while (   iEnd < cLeaves
+           && paLeaves[iEnd].uLeaf <= uLast)
+        iEnd++;
+
+    /*
+     * Adjust the array if anything needs removing.
+     */
+    if (iFirst < iEnd)
+    {
+        if (iEnd < cLeaves)
+            memmove(&paLeaves[iFirst], &paLeaves[iEnd], (cLeaves - iEnd) * sizeof(paLeaves[0]));
+        *pcLeaves = cLeaves -= (iEnd - iFirst);
+    }
+}
+
+
+
+/**
+ * Checks if ECX make a difference when reading a given CPUID leaf.
+ *
+ * @returns @c true if it does, @c false if it doesn't.
+ * @param   uLeaf               The leaf we're reading.
+ * @param   pcSubLeaves         Number of sub-leaves accessible via ECX.
+ * @param   pfFinalEcxUnchanged Whether ECX is passed thru when going beyond the
+ *                              final sub-leaf.
+ */
+static bool cpumR3IsEcxRelevantForCpuIdLeaf(uint32_t uLeaf, uint32_t *pcSubLeaves, bool *pfFinalEcxUnchanged)
+{
+    *pfFinalEcxUnchanged = false;
+
+    uint32_t auPrev[4];
+    ASMCpuIdExSlow(uLeaf, 0, 0, 0, &auPrev[0], &auPrev[1], &auPrev[2], &auPrev[3]);
+
+    /* Look for sub-leaves. */
+    uint32_t uSubLeaf = 1;
+    for (;;)
+    {
+        uint32_t auCur[4];
+        ASMCpuIdExSlow(uLeaf, 0, uSubLeaf, 0, &auCur[0], &auCur[1], &auCur[2], &auCur[3]);
+        if (memcmp(auCur, auPrev, sizeof(auCur)))
+            break;
+
+        /* Advance / give up. */
+        uSubLeaf++;
+        if (uSubLeaf >= 64)
+        {
+            *pcSubLeaves = 1;
+            return false;
+        }
+    }
+
+    /* Count sub-leaves. */
+    uSubLeaf = 0;
+    for (;;)
+    {
+        uint32_t auCur[4];
+        ASMCpuIdExSlow(uLeaf, 0, uSubLeaf, 0, &auCur[0], &auCur[1], &auCur[2], &auCur[3]);
+
+        /* Exactly when this terminates isn't quite consistent.  When working
+           0xb, we should probably only check if ebx == 0... */
+        if (   auCur[0] == 0
+            && auCur[1] == 0
+            && (auCur[2] == 0 || auCur[2] == uSubLeaf)
+            && (auCur[3] == 0 || uLeaf == 0xb) )
+        {
+            if (auCur[2] == uSubLeaf)
+                *pfFinalEcxUnchanged = true;
+            *pcSubLeaves = uSubLeaf + 1;
+            return true;
+        }
+
+        /* Advance / give up. */
+        uSubLeaf++;
+        if (uSubLeaf >= 128)
+        {
+            *pcSubLeaves = UINT32_MAX;
+            return true;
+        }
+    }
+}
+
+
+/**
+ * Collects CPUID leaves and sub-leaves, returning a sorted array of them.
+ *
+ * @returns VBox status code.
+ * @param   ppaLeaves           Where to return the array pointer on success.
+ *                              Use RTMemFree to release.
+ * @param   pcLeaves            Where to return the size of the array on
+ *                              success.
+ */
+VMMR3DECL(int) CPUMR3CpuIdCollectLeaves(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves)
+{
+    *ppaLeaves = NULL;
+    *pcLeaves = 0;
+
+    /*
+     * Try out various candidates. This must be sorted!
+     */
+    static struct { uint32_t uMsr; bool fSpecial; } const s_aCandidates[] =
+    {
+        { UINT32_C(0x00000000), false },
+        { UINT32_C(0x10000000), false },
+        { UINT32_C(0x20000000), false },
+        { UINT32_C(0x30000000), false },
+        { UINT32_C(0x40000000), false },
+        { UINT32_C(0x50000000), false },
+        { UINT32_C(0x60000000), false },
+        { UINT32_C(0x70000000), false },
+        { UINT32_C(0x80000000), false },
+        { UINT32_C(0x80860000), false },
+        { UINT32_C(0x8ffffffe), true  },
+        { UINT32_C(0x8fffffff), true  },
+        { UINT32_C(0x90000000), false },
+        { UINT32_C(0xa0000000), false },
+        { UINT32_C(0xb0000000), false },
+        { UINT32_C(0xc0000000), false },
+        { UINT32_C(0xd0000000), false },
+        { UINT32_C(0xe0000000), false },
+        { UINT32_C(0xf0000000), false },
+    };
+
+    for (uint32_t iOuter = 0; iOuter < RT_ELEMENTS(s_aCandidates); iOuter++)
+    {
+        uint32_t uLeaf = s_aCandidates[iOuter].uMsr;
+        uint32_t uEax, uEbx, uEcx, uEdx;
+        ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+
+        /*
+         * Does EAX look like a typical leaf count value?
+         */
+        if (   uEax         > uLeaf
+            && uEax - uLeaf < UINT32_C(0xff)) /* Adjust 0xff limit when exceeded by real HW. */
+        {
+            /* Yes, dump them. */
+            uint32_t cLeaves = uEax - uLeaf + 1;
+            while (cLeaves-- > 0)
+            {
+                /* Check three times here to reduce the chance of CPU migration
+                   resulting in false positives with things like the APIC ID. */
+                uint32_t cSubLeaves;
+                bool fFinalEcxUnchanged;
+                if (   cpumR3IsEcxRelevantForCpuIdLeaf(uLeaf, &cSubLeaves, &fFinalEcxUnchanged)
+                    && cpumR3IsEcxRelevantForCpuIdLeaf(uLeaf, &cSubLeaves, &fFinalEcxUnchanged)
+                    && cpumR3IsEcxRelevantForCpuIdLeaf(uLeaf, &cSubLeaves, &fFinalEcxUnchanged))
+                {
+                    if (cSubLeaves > 16)
+                    {
+                        /* This shouldn't happen.  But in case it does, file all
+                           relevant details in the release log. */
+                        LogRel(("CPUM: VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES! uLeaf=%#x cSubLeaves=%#x\n", uLeaf, cSubLeaves));
+                        LogRel(("------------------ dump of problematic subleaves ------------------\n"));
+                        for (uint32_t uSubLeaf = 0; uSubLeaf < 128; uSubLeaf++)
+                        {
+                            uint32_t auTmp[4];
+                            ASMCpuIdExSlow(uLeaf, 0, uSubLeaf, 0, &auTmp[0], &auTmp[1], &auTmp[2], &auTmp[3]);
+                            LogRel(("CPUM: %#010x, %#010x => %#010x %#010x %#010x %#010x\n",
+                                    uLeaf, uSubLeaf, auTmp[0], auTmp[1], auTmp[2], auTmp[3]));
+                        }
+                        LogRel(("----------------- dump of what we've found so far -----------------\n"));
+                        for (uint32_t i = 0 ; i < *pcLeaves; i++)
+                            LogRel(("CPUM: %#010x, %#010x/%#010x => %#010x %#010x %#010x %#010x\n",
+                                    (*ppaLeaves)[i].uLeaf, (*ppaLeaves)[i].uSubLeaf,  (*ppaLeaves)[i].fSubLeafMask,
+                                    (*ppaLeaves)[i].uEax, (*ppaLeaves)[i].uEbx, (*ppaLeaves)[i].uEcx, (*ppaLeaves)[i].uEdx));
+                        LogRel(("\nPlease create a defect on virtualbox.org and attach this log file!\n\n"));
+                        return VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES;
+                    }
+
+                    for (uint32_t uSubLeaf = 0; uSubLeaf < cSubLeaves; uSubLeaf++)
+                    {
+                        ASMCpuIdExSlow(uLeaf, 0, uSubLeaf, 0, &uEax, &uEbx, &uEcx, &uEdx);
+                        int rc = cpumR3CollectCpuIdInfoAddOne(ppaLeaves, pcLeaves,
+                                                              uLeaf, uSubLeaf, UINT32_MAX, uEax, uEbx, uEcx, uEdx,
+                                                              uSubLeaf + 1 == cSubLeaves && fFinalEcxUnchanged
+                                                              ? CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED : 0);
+                        if (RT_FAILURE(rc))
+                            return rc;
+                    }
+                }
+                else
+                {
+                    ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+                    int rc = cpumR3CollectCpuIdInfoAddOne(ppaLeaves, pcLeaves,
+                                                          uLeaf, 0, 0, uEax, uEbx, uEcx, uEdx, 0);
+                    if (RT_FAILURE(rc))
+                        return rc;
+                }
+
+                /* next */
+                uLeaf++;
+            }
+        }
+        /*
+         * Special CPUIDs needs special handling as they don't follow the
+         * leaf count principle used above.
+         */
+        else if (s_aCandidates[iOuter].fSpecial)
+        {
+            bool fKeep = false;
+            if (uLeaf == 0x8ffffffe && uEax == UINT32_C(0x00494544))
+                fKeep = true;
+            else if (   uLeaf == 0x8fffffff
+                     && RT_C_IS_PRINT(RT_BYTE1(uEax))
+                     && RT_C_IS_PRINT(RT_BYTE2(uEax))
+                     && RT_C_IS_PRINT(RT_BYTE3(uEax))
+                     && RT_C_IS_PRINT(RT_BYTE4(uEax))
+                     && RT_C_IS_PRINT(RT_BYTE1(uEbx))
+                     && RT_C_IS_PRINT(RT_BYTE2(uEbx))
+                     && RT_C_IS_PRINT(RT_BYTE3(uEbx))
+                     && RT_C_IS_PRINT(RT_BYTE4(uEbx))
+                     && RT_C_IS_PRINT(RT_BYTE1(uEcx))
+                     && RT_C_IS_PRINT(RT_BYTE2(uEcx))
+                     && RT_C_IS_PRINT(RT_BYTE3(uEcx))
+                     && RT_C_IS_PRINT(RT_BYTE4(uEcx))
+                     && RT_C_IS_PRINT(RT_BYTE1(uEdx))
+                     && RT_C_IS_PRINT(RT_BYTE2(uEdx))
+                     && RT_C_IS_PRINT(RT_BYTE3(uEdx))
+                     && RT_C_IS_PRINT(RT_BYTE4(uEdx)) )
+                fKeep = true;
+            if (fKeep)
+            {
+                int rc = cpumR3CollectCpuIdInfoAddOne(ppaLeaves, pcLeaves,
+                                                      uLeaf, 0, 0, uEax, uEbx, uEcx, uEdx, 0);
+                if (RT_FAILURE(rc))
+                    return rc;
+            }
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Determines the method the CPU uses to handle unknown CPUID leaves.
+ *
+ * @returns VBox status code.
+ * @param   penmUnknownMethod   Where to return the method.
+ * @param   pDefUnknown         Where to return default unknown values.  This
+ *                              will be set, even if the resulting method
+ *                              doesn't actually needs it.
+ */
+VMMR3DECL(int) CPUMR3CpuIdDetectUnknownLeafMethod(PCPUMUKNOWNCPUID penmUnknownMethod, PCPUMCPUID pDefUnknown)
+{
+    uint32_t uLastStd = ASMCpuId_EAX(0);
+    uint32_t uLastExt = ASMCpuId_EAX(0x80000000);
+    if (!ASMIsValidExtRange(uLastExt))
+        uLastExt = 0x80000000;
+
+    uint32_t auChecks[] =
+    {
+        uLastStd + 1,
+        uLastStd + 5,
+        uLastStd + 8,
+        uLastStd + 32,
+        uLastStd + 251,
+        uLastExt + 1,
+        uLastExt + 8,
+        uLastExt + 15,
+        uLastExt + 63,
+        uLastExt + 255,
+        0x7fbbffcc,
+        0x833f7872,
+        0xefff2353,
+        0x35779456,
+        0x1ef6d33e,
+    };
+
+    static const uint32_t s_auValues[] =
+    {
+        0xa95d2156,
+        0x00000001,
+        0x00000002,
+        0x00000008,
+        0x00000000,
+        0x55773399,
+        0x93401769,
+        0x12039587,
+    };
+
+    /*
+     * Simple method, all zeros.
+     */
+    *penmUnknownMethod = CPUMUKNOWNCPUID_DEFAULTS;
+    pDefUnknown->eax = 0;
+    pDefUnknown->ebx = 0;
+    pDefUnknown->ecx = 0;
+    pDefUnknown->edx = 0;
+
+    /*
+     * Intel has been observed returning the last standard leaf.
+     */
+    uint32_t auLast[4];
+    ASMCpuIdExSlow(uLastStd, 0, 0, 0, &auLast[0], &auLast[1], &auLast[2], &auLast[3]);
+
+    uint32_t cChecks = RT_ELEMENTS(auChecks);
+    while (cChecks > 0)
+    {
+        uint32_t auCur[4];
+        ASMCpuIdExSlow(auChecks[cChecks - 1], 0, 0, 0, &auCur[0], &auCur[1], &auCur[2], &auCur[3]);
+        if (memcmp(auCur, auLast, sizeof(auCur)))
+            break;
+        cChecks--;
+    }
+    if (cChecks == 0)
+    {
+        /* Now, what happens when the input changes? Esp. ECX. */
+        uint32_t cTotal       = 0;
+        uint32_t cSame        = 0;
+        uint32_t cLastWithEcx = 0;
+        uint32_t cNeither     = 0;
+        uint32_t cValues = RT_ELEMENTS(s_auValues);
+        while (cValues > 0)
+        {
+            uint32_t uValue = s_auValues[cValues - 1];
+            uint32_t auLastWithEcx[4];
+            ASMCpuIdExSlow(uLastStd, uValue, uValue, uValue,
+                           &auLastWithEcx[0], &auLastWithEcx[1], &auLastWithEcx[2], &auLastWithEcx[3]);
+
+            cChecks = RT_ELEMENTS(auChecks);
+            while (cChecks > 0)
+            {
+                uint32_t auCur[4];
+                ASMCpuIdExSlow(auChecks[cChecks - 1], uValue, uValue, uValue, &auCur[0], &auCur[1], &auCur[2], &auCur[3]);
+                if (!memcmp(auCur, auLast, sizeof(auCur)))
+                {
+                    cSame++;
+                    if (!memcmp(auCur, auLastWithEcx, sizeof(auCur)))
+                        cLastWithEcx++;
+                }
+                else if (!memcmp(auCur, auLastWithEcx, sizeof(auCur)))
+                    cLastWithEcx++;
+                else
+                    cNeither++;
+                cTotal++;
+                cChecks--;
+            }
+            cValues--;
+        }
+
+        Log(("CPUM: cNeither=%d cSame=%d cLastWithEcx=%d cTotal=%d\n", cNeither, cSame, cLastWithEcx, cTotal));
+        if (cSame == cTotal)
+            *penmUnknownMethod = CPUMUKNOWNCPUID_LAST_STD_LEAF;
+        else if (cLastWithEcx == cTotal)
+            *penmUnknownMethod = CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX;
+        else
+            *penmUnknownMethod = CPUMUKNOWNCPUID_LAST_STD_LEAF;
+        pDefUnknown->eax = auLast[0];
+        pDefUnknown->ebx = auLast[1];
+        pDefUnknown->ecx = auLast[2];
+        pDefUnknown->edx = auLast[3];
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Unchanged register values?
+     */
+    cChecks = RT_ELEMENTS(auChecks);
+    while (cChecks > 0)
+    {
+        uint32_t const  uLeaf   = auChecks[cChecks - 1];
+        uint32_t        cValues = RT_ELEMENTS(s_auValues);
+        while (cValues > 0)
+        {
+            uint32_t uValue = s_auValues[cValues - 1];
+            uint32_t auCur[4];
+            ASMCpuIdExSlow(uLeaf, uValue, uValue, uValue, &auCur[0], &auCur[1], &auCur[2], &auCur[3]);
+            if (   auCur[0] != uLeaf
+                || auCur[1] != uValue
+                || auCur[2] != uValue
+                || auCur[3] != uValue)
+                break;
+            cValues--;
+        }
+        if (cValues != 0)
+            break;
+        cChecks--;
+    }
+    if (cChecks == 0)
+    {
+        *penmUnknownMethod = CPUMUKNOWNCPUID_PASSTHRU;
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Just go with the simple method.
+     */
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Translates a unknow CPUID leaf method into the constant name (sans prefix).
+ *
+ * @returns Read only name string.
+ * @param   enmUnknownMethod    The method to translate.
+ */
+VMMR3DECL(const char *) CPUMR3CpuIdUnknownLeafMethodName(CPUMUKNOWNCPUID enmUnknownMethod)
+{
+    switch (enmUnknownMethod)
+    {
+        case CPUMUKNOWNCPUID_DEFAULTS:                  return "DEFAULTS";
+        case CPUMUKNOWNCPUID_LAST_STD_LEAF:             return "LAST_STD_LEAF";
+        case CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX:    return "LAST_STD_LEAF_WITH_ECX";
+        case CPUMUKNOWNCPUID_PASSTHRU:                  return "PASSTHRU";
+
+        case CPUMUKNOWNCPUID_INVALID:
+        case CPUMUKNOWNCPUID_END:
+        case CPUMUKNOWNCPUID_32BIT_HACK:
+            break;
+    }
+    return "Invalid-unknown-CPUID-method";
+}
+
+
+/**
+ * Detect the CPU vendor give n the
+ *
+ * @returns The vendor.
+ * @param   uEAX                EAX from CPUID(0).
+ * @param   uEBX                EBX from CPUID(0).
+ * @param   uECX                ECX from CPUID(0).
+ * @param   uEDX                EDX from CPUID(0).
+ */
+VMMR3DECL(CPUMCPUVENDOR) CPUMR3CpuIdDetectVendorEx(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+    if (ASMIsValidStdRange(uEAX))
+    {
+        if (ASMIsAmdCpuEx(uEBX, uECX, uEDX))
+            return CPUMCPUVENDOR_AMD;
+
+        if (ASMIsIntelCpuEx(uEBX, uECX, uEDX))
+            return CPUMCPUVENDOR_INTEL;
+
+        if (ASMIsViaCentaurCpuEx(uEBX, uECX, uEDX))
+            return CPUMCPUVENDOR_VIA;
+
+        if (   uEBX == UINT32_C(0x69727943) /* CyrixInstead */
+            && uECX == UINT32_C(0x64616574)
+            && uEDX == UINT32_C(0x736E4978))
+            return CPUMCPUVENDOR_CYRIX;
+
+        /* "Geode by NSC", example: family 5, model 9.  */
+
+        /** @todo detect the other buggers... */
+    }
+
+    return CPUMCPUVENDOR_UNKNOWN;
+}
+
+
+/**
+ * Translates a CPU vendor enum value into the corresponding string constant.
+ *
+ * The named can be prefixed with 'CPUMCPUVENDOR_' to construct a valid enum
+ * value name.  This can be useful when generating code.
+ *
+ * @returns Read only name string.
+ * @param   enmVendor           The CPU vendor value.
+ */
+VMMR3DECL(const char *) CPUMR3CpuVendorName(CPUMCPUVENDOR enmVendor)
+{
+    switch (enmVendor)
+    {
+        case CPUMCPUVENDOR_INTEL:       return "INTEL";
+        case CPUMCPUVENDOR_AMD:         return "AMD";
+        case CPUMCPUVENDOR_VIA:         return "VIA";
+        case CPUMCPUVENDOR_CYRIX:       return "CYRIX";
+        case CPUMCPUVENDOR_UNKNOWN:     return "UNKNOWN";
+
+        case CPUMCPUVENDOR_INVALID:
+        case CPUMCPUVENDOR_32BIT_HACK:
+            break;
+    }
+    return "Invalid-cpu-vendor";
+}
+
+
+static PCCPUMCPUIDLEAF cpumR3CpuIdFindLeaf(PCCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf)
+{
+    /* Could do binary search, doing linear now because I'm lazy. */
+    PCCPUMCPUIDLEAF pLeaf = paLeaves;
+    while (cLeaves-- > 0)
+    {
+        if (pLeaf->uLeaf == uLeaf)
+            return pLeaf;
+        pLeaf++;
+    }
+    return NULL;
+}
+
+
+int cpumR3CpuIdExplodeFeatures(PCCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, PCPUMFEATURES pFeatures)
+{
+    RT_ZERO(*pFeatures);
+    if (cLeaves >= 2)
+    {
+        AssertLogRelReturn(paLeaves[0].uLeaf == 0, VERR_CPUM_IPE_1);
+        AssertLogRelReturn(paLeaves[1].uLeaf == 1, VERR_CPUM_IPE_1);
+
+        pFeatures->enmCpuVendor = CPUMR3CpuIdDetectVendorEx(paLeaves[0].uEax,
+                                                            paLeaves[0].uEbx,
+                                                            paLeaves[0].uEcx,
+                                                            paLeaves[0].uEdx);
+        pFeatures->uFamily      = ASMGetCpuFamily(paLeaves[1].uEax);
+        pFeatures->uModel       = ASMGetCpuModel(paLeaves[1].uEax, pFeatures->enmCpuVendor == CPUMCPUVENDOR_INTEL);
+        pFeatures->uStepping    = ASMGetCpuStepping(paLeaves[1].uEax);
+        pFeatures->enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx((CPUMCPUVENDOR)pFeatures->enmCpuVendor,
+                                                                  pFeatures->uFamily,
+                                                                  pFeatures->uModel,
+                                                                  pFeatures->uStepping);
+
+        PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdFindLeaf(paLeaves, cLeaves, 0x80000008);
+        if (pLeaf)
+            pFeatures->cMaxPhysAddrWidth = pLeaf->uEax & 0xff;
+        else if (paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_PSE36)
+            pFeatures->cMaxPhysAddrWidth = 36;
+        else
+            pFeatures->cMaxPhysAddrWidth = 32;
+
+        /* Standard features. */
+        pFeatures->fMsr                 = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_MSR);
+        pFeatures->fApic                = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_APIC);
+        pFeatures->fX2Apic              = RT_BOOL(paLeaves[1].uEcx & X86_CPUID_FEATURE_ECX_X2APIC);
+        pFeatures->fPse                 = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_PSE);
+        pFeatures->fPse36               = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_PSE36);
+        pFeatures->fPae                 = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_PAE);
+        pFeatures->fPat                 = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_PAT);
+        pFeatures->fFxSaveRstor         = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_FXSR);
+        pFeatures->fSysEnter            = RT_BOOL(paLeaves[1].uEdx & X86_CPUID_FEATURE_EDX_SEP);
+        pFeatures->fHypervisorPresent   = RT_BOOL(paLeaves[1].uEcx & X86_CPUID_FEATURE_ECX_HVP);
+        pFeatures->fMonitorMWait        = RT_BOOL(paLeaves[1].uEcx & X86_CPUID_FEATURE_ECX_MONITOR);
+
+        /* Extended features. */
+        PCCPUMCPUIDLEAF const pExtLeaf  = cpumR3CpuIdFindLeaf(paLeaves, cLeaves, 0x80000001);
+        if (pExtLeaf)
+        {
+            pFeatures->fLongMode        = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
+            pFeatures->fSysCall         = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_EXT_FEATURE_EDX_SYSCALL);
+            pFeatures->fNoExecute       = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_EXT_FEATURE_EDX_NX);
+            pFeatures->fLahfSahf        = RT_BOOL(pExtLeaf->uEcx & X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF);
+            pFeatures->fRdTscP          = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_EXT_FEATURE_EDX_RDTSCP);
+        }
+
+        if (   pExtLeaf
+            && pFeatures->enmCpuVendor == CPUMCPUVENDOR_AMD)
+        {
+            /* AMD features. */
+            pFeatures->fMsr            |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_MSR);
+            pFeatures->fApic           |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_APIC);
+            pFeatures->fPse            |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_PSE);
+            pFeatures->fPse36          |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_PSE36);
+            pFeatures->fPae            |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_PAE);
+            pFeatures->fPat            |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_PAT);
+            pFeatures->fFxSaveRstor    |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_FXSR);
+        }
+
+        /*
+         * Quirks.
+         */
+        pFeatures->fLeakyFxSR = pExtLeaf
+                             && (pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_FFXSR)
+                             && pFeatures->enmCpuVendor == CPUMCPUVENDOR_AMD
+                             && pFeatures->uFamily >= 6 /* K7 and up */;
+    }
+    else
+        AssertLogRelReturn(cLeaves == 0, VERR_CPUM_IPE_1);
+    return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/VMM/VMMR3/CPUMR3Db.cpp b/src/VBox/VMM/VMMR3/CPUMR3Db.cpp
new file mode 100644
index 0000000..f6e3942
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/CPUMR3Db.cpp
@@ -0,0 +1,769 @@
+/* $Id: CPUMR3Db.cpp $ */
+/** @file
+ * CPUM - CPU database part.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_CPUM
+#include <VBox/vmm/cpum.h>
+#include "CPUMInternal.h"
+#include <VBox/vmm/vm.h>
+
+#include <VBox/err.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef struct CPUMDBENTRY
+{
+    /** The CPU name. */
+    const char     *pszName;
+    /** The full CPU name. */
+    const char     *pszFullName;
+    /** The CPU vendor (CPUMCPUVENDOR). */
+    uint8_t         enmVendor;
+    /** The CPU family. */
+    uint8_t         uFamily;
+    /** The CPU model. */
+    uint8_t         uModel;
+    /** The CPU stepping. */
+    uint8_t         uStepping;
+    /** The microarchitecture. */
+    CPUMMICROARCH   enmMicroarch;
+    /** Flags (TBD). */
+    uint32_t        fFlags;
+    /** The maximum physical address with of the CPU.  This should correspond to
+     * the value in CPUID leaf 0x80000008 when present. */
+    uint8_t         cMaxPhysAddrWidth;
+    /** Pointer to an array of CPUID leaves.  */
+    PCCPUMCPUIDLEAF paCpuIdLeaves;
+    /** The number of CPUID leaves in the array paCpuIdLeaves points to. */
+    uint32_t        cCpuIdLeaves;
+    /** The method used to deal with unknown CPUID leaves. */
+    CPUMUKNOWNCPUID enmUnknownCpuId;
+    /** The default unknown CPUID value. */
+    CPUMCPUID       DefUnknownCpuId;
+
+    /** MSR mask.  Several microarchitectures ignore higher bits of the    */
+    uint32_t        fMsrMask;
+
+    /** The number of ranges in the table pointed to b paMsrRanges. */
+    uint32_t        cMsrRanges;
+    /** MSR ranges for this CPU. */
+    PCCPUMMSRRANGE  paMsrRanges;
+} CPUMDBENTRY;
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+
+/** @def NULL_ALONE
+ * For eliminating an unnecessary data dependency in standalone builds (for
+ * VBoxSVC). */
+/** @def ZERO_ALONE
+ * For eliminating an unnecessary data size dependency in standalone builds (for
+ * VBoxSVC). */
+#ifndef CPUM_DB_STANDALONE
+# define NULL_ALONE(a_aTable)    a_aTable
+# define ZERO_ALONE(a_cTable)    a_cTable
+#else
+# define NULL_ALONE(a_aTable)    NULL
+# define ZERO_ALONE(a_cTable)    0
+#endif
+
+
+/** @name Short macros for the MSR range entries.
+ *
+ * These are rather cryptic, but this is to reduce the attack on the right
+ * margin.
+ *
+ * @{ */
+/** Alias one MSR onto another (a_uTarget). */
+#define MAL(a_uMsr, a_szName, a_uTarget) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_MsrAlias, kCpumMsrWrFn_MsrAlias, 0, a_uTarget, 0, 0, a_szName)
+/** Functions handles everything. */
+#define MFN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
+/** Functions handles everything, with GP mask. */
+#define MFG(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrGpMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, a_fWrGpMask, a_szName)
+/** Function handlers, read-only. */
+#define MFO(a_uMsr, a_szName, a_enmRdFnSuff) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_ReadOnly, 0, 0, 0, UINT64_MAX, a_szName)
+/** Function handlers, ignore all writes. */
+#define MFI(a_uMsr, a_szName, a_enmRdFnSuff) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_IgnoreWrite, 0, 0, UINT64_MAX, 0, a_szName)
+/** Function handlers, with value. */
+#define MFV(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, 0, 0, a_szName)
+/** Function handlers, with write ignore mask. */
+#define MFW(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrIgnMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, a_fWrIgnMask, 0, a_szName)
+/** Function handlers, extended version. */
+#define MFX(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
+/** Function handlers, with CPUMCPU storage variable. */
+#define MFS(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
+         RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, 0, 0, a_szName)
+/** Function handlers, with CPUMCPU storage variable, ignore mask and GP mask. */
+#define MFZ(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember, a_fWrIgnMask, a_fWrGpMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
+         RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, a_fWrIgnMask, a_fWrGpMask, a_szName)
+/** Read-only fixed value. */
+#define MVO(a_uMsr, a_szName, a_uValue) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
+/** Read-only fixed value, ignores all writes. */
+#define MVI(a_uMsr, a_szName, a_uValue) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
+/** Read fixed value, ignore writes outside GP mask. */
+#define MVG(a_uMsr, a_szName, a_uValue, a_fWrGpMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, 0, a_fWrGpMask, a_szName)
+/** Read fixed value, extended version with both GP and ignore masks. */
+#define MVX(a_uMsr, a_szName, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
+/** The short form, no CPUM backing. */
+#define MSN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
+    RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
+         a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
+
+/** Range: Functions handles everything. */
+#define RFN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
+    RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
+/** Range: Read fixed value, read-only. */
+#define RVO(a_uFirst, a_uLast, a_szName, a_uValue) \
+    RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
+/** Range: Read fixed value, ignore writes. */
+#define RVI(a_uFirst, a_uLast, a_szName, a_uValue) \
+    RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
+/** Range: The short form, no CPUM backing. */
+#define RSN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
+    RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
+         a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
+
+/** Internal form used by the macros. */
+#ifdef VBOX_WITH_STATISTICS
+# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
+    { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName, \
+      { 0 }, { 0 }, { 0 }, { 0 } }
+#else
+# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
+    { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName }
+#endif
+/** @} */
+
+
+#include "cpus/Intel_Core_i7_3960X.h"
+#include "cpus/Intel_Core_i5_3570.h"
+#include "cpus/Intel_Xeon_X5482_3_20GHz.h"
+#include "cpus/Intel_Pentium_M_processor_2_00GHz.h"
+#include "cpus/Intel_Pentium_4_3_00GHz.h"
+
+#include "cpus/AMD_FX_8150_Eight_Core.h"
+#include "cpus/AMD_Phenom_II_X6_1100T.h"
+#include "cpus/Quad_Core_AMD_Opteron_2384.h"
+#include "cpus/AMD_Athlon_64_3200.h"
+
+#include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
+
+
+
+/**
+ * The database entries.
+ *
+ * 1. The first entry is special.  It is the fallback for unknown
+ *    processors.  Thus, it better be pretty representative.
+ *
+ * 2. The first entry for a CPU vendor is likewise important as it is
+ *    the default entry for that vendor.
+ *
+ * Generally we put the most recent CPUs first, since these tend to have the
+ * most complicated and backwards compatible list of MSRs.
+ */
+static CPUMDBENTRY const * const g_apCpumDbEntries[] =
+{
+#ifdef VBOX_CPUDB_Intel_Core_i5_3570
+    &g_Entry_Intel_Core_i5_3570,
+#endif
+#ifdef VBOX_CPUDB_Intel_Core_i7_3960X
+    &g_Entry_Intel_Core_i7_3960X,
+#endif
+#ifdef Intel_Pentium_M_processor_2_00GHz
+    &g_Entry_Intel_Pentium_M_processor_2_00GHz,
+#endif
+#ifdef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz
+    &g_Entry_Intel_Xeon_X5482_3_20GHz,
+#endif
+#ifdef VBOX_CPUDB_Intel_Pentium_4_3_00GHz
+    &g_Entry_Intel_Pentium_4_3_00GHz,
+#endif
+
+#ifdef VBOX_CPUDB_AMD_FX_8150_Eight_Core
+    &g_Entry_AMD_FX_8150_Eight_Core,
+#endif
+#ifdef VBOX_CPUDB_AMD_Phenom_II_X6_1100T
+    &g_Entry_AMD_Phenom_II_X6_1100T,
+#endif
+#ifdef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384
+    &g_Entry_Quad_Core_AMD_Opteron_2384,
+#endif
+#ifdef VBOX_CPUDB_AMD_Athlon_64_3200
+    &g_Entry_AMD_Athlon_64_3200,
+#endif
+
+#ifdef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz
+    &g_Entry_VIA_QuadCore_L4700_1_2_GHz,
+#endif
+};
+
+
+#ifndef CPUM_DB_STANDALONE
+
+/**
+ * Binary search used by cpumR3MsrRangesInsert and has some special properties
+ * wrt to mismatches.
+ *
+ * @returns Insert location.
+ * @param   paMsrRanges         The MSR ranges to search.
+ * @param   cMsrRanges          The number of MSR ranges.
+ * @param   uMsr                What to search for.
+ */
+static uint32_t cpumR3MsrRangesBinSearch(PCCPUMMSRRANGE paMsrRanges, uint32_t cMsrRanges, uint32_t uMsr)
+{
+    if (!cMsrRanges)
+        return 0;
+
+    uint32_t iStart = 0;
+    uint32_t iLast  = cMsrRanges - 1;
+    for (;;)
+    {
+        uint32_t i = iStart + (iLast - iStart + 1) / 2;
+        if (   uMsr >= paMsrRanges[i].uFirst
+            && uMsr <= paMsrRanges[i].uLast)
+            return i;
+        if (uMsr < paMsrRanges[i].uFirst)
+        {
+            if (i <= iStart)
+                return i;
+            iLast = i - 1;
+        }
+        else
+        {
+            if (i >= iLast)
+            {
+                if (i < cMsrRanges)
+                    i++;
+                return i;
+            }
+            iStart = i + 1;
+        }
+    }
+}
+
+
+/**
+ * Ensures that there is space for at least @a cNewRanges in the table,
+ * reallocating the table if necessary.
+ *
+ * @returns Pointer to the MSR ranges on success, NULL on failure.  On failure
+ *          @a *ppaMsrRanges is freed and set to NULL.
+ * @param   ppaMsrRanges    The variable pointing to the ranges (input/output).
+ * @param   cMsrRanges      The current number of ranges.
+ * @param   cNewRanges      The number of ranges to be added.
+ */
+static PCPUMMSRRANGE cpumR3MsrRangesEnsureSpace(PCPUMMSRRANGE *ppaMsrRanges, uint32_t cMsrRanges, uint32_t cNewRanges)
+{
+    uint32_t cMsrRangesAllocated = RT_ALIGN_32(cMsrRanges, 16);
+    if (cMsrRangesAllocated < cMsrRanges + cNewRanges)
+    {
+        uint32_t cNew = RT_ALIGN_32(cMsrRanges + cNewRanges, 16);
+        void *pvNew = RTMemRealloc(*ppaMsrRanges, cNew * sizeof(**ppaMsrRanges));
+        if (!pvNew)
+        {
+            RTMemFree(*ppaMsrRanges);
+            *ppaMsrRanges = NULL;
+            return NULL;
+        }
+        *ppaMsrRanges = (PCPUMMSRRANGE)pvNew;
+    }
+    return *ppaMsrRanges;
+}
+
+
+/**
+ * Inserts a new MSR range in into an sorted MSR range array.
+ *
+ * If the new MSR range overlaps existing ranges, the existing ones will be
+ * adjusted/removed to fit in the new one.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_NO_MEMORY
+ *
+ * @param   ppaMsrRanges    The variable pointing to the ranges (input/output).
+ * @param   pcMsrRanges     The variable holding number of ranges.
+ * @param   pNewRange       The new range.
+ */
+int cpumR3MsrRangesInsert(PCPUMMSRRANGE *ppaMsrRanges, uint32_t *pcMsrRanges, PCCPUMMSRRANGE pNewRange)
+{
+    uint32_t        cMsrRanges  = *pcMsrRanges;
+    PCPUMMSRRANGE   paMsrRanges = *ppaMsrRanges;
+
+    Assert(pNewRange->uLast >= pNewRange->uFirst);
+    Assert(pNewRange->enmRdFn > kCpumMsrRdFn_Invalid && pNewRange->enmRdFn < kCpumMsrRdFn_End);
+    Assert(pNewRange->enmWrFn > kCpumMsrWrFn_Invalid && pNewRange->enmWrFn < kCpumMsrWrFn_End);
+
+    /*
+     * Optimize the linear insertion case where we add new entries at the end.
+     */
+    if (   cMsrRanges > 0
+        && paMsrRanges[cMsrRanges - 1].uLast < pNewRange->uFirst)
+    {
+        paMsrRanges = cpumR3MsrRangesEnsureSpace(ppaMsrRanges, cMsrRanges, 1);
+        if (!paMsrRanges)
+            return VERR_NO_MEMORY;
+        paMsrRanges[cMsrRanges] = *pNewRange;
+        *pcMsrRanges += 1;
+    }
+    else
+    {
+        uint32_t i = cpumR3MsrRangesBinSearch(paMsrRanges, cMsrRanges, pNewRange->uFirst);
+        Assert(i == cMsrRanges || pNewRange->uFirst <= paMsrRanges[i].uLast);
+        Assert(i == 0 || pNewRange->uFirst > paMsrRanges[i - 1].uLast);
+
+        /*
+         * Adding an entirely new entry?
+         */
+        if (   i >= cMsrRanges
+            || pNewRange->uLast < paMsrRanges[i].uFirst)
+        {
+            paMsrRanges = cpumR3MsrRangesEnsureSpace(ppaMsrRanges, cMsrRanges, 1);
+            if (!paMsrRanges)
+                return VERR_NO_MEMORY;
+            if (i < cMsrRanges)
+                memmove(&paMsrRanges[i + 1], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
+            paMsrRanges[i] = *pNewRange;
+            *pcMsrRanges += 1;
+        }
+        /*
+         * Replace existing entry?
+         */
+        else if (   pNewRange->uFirst == paMsrRanges[i].uFirst
+                 && pNewRange->uLast  == paMsrRanges[i].uLast)
+            paMsrRanges[i] = *pNewRange;
+        /*
+         * Splitting an existing entry?
+         */
+        else if (   pNewRange->uFirst > paMsrRanges[i].uFirst
+                 && pNewRange->uLast  < paMsrRanges[i].uLast)
+        {
+            paMsrRanges = cpumR3MsrRangesEnsureSpace(ppaMsrRanges, cMsrRanges, 2);
+            if (!paMsrRanges)
+                return VERR_NO_MEMORY;
+            if (i < cMsrRanges)
+                memmove(&paMsrRanges[i + 2], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
+            paMsrRanges[i + 1] = *pNewRange;
+            paMsrRanges[i + 2] = paMsrRanges[i];
+            paMsrRanges[i    ].uLast  = pNewRange->uFirst - 1;
+            paMsrRanges[i + 2].uFirst = pNewRange->uLast  + 1;
+            *pcMsrRanges += 2;
+        }
+        /*
+         * Complicated scenarios that can affect more than one range.
+         *
+         * The current code does not optimize memmove calls when replacing
+         * one or more existing ranges, because it's tedious to deal with and
+         * not expected to be a frequent usage scenario.
+         */
+        else
+        {
+            /* Adjust start of first match? */
+            if (   pNewRange->uFirst <= paMsrRanges[i].uFirst
+                && pNewRange->uLast  <  paMsrRanges[i].uLast)
+                paMsrRanges[i].uFirst = pNewRange->uLast + 1;
+            else
+            {
+                /* Adjust end of first match? */
+                if (pNewRange->uFirst > paMsrRanges[i].uFirst)
+                {
+                    Assert(paMsrRanges[i].uLast >= pNewRange->uFirst);
+                    paMsrRanges[i].uLast = pNewRange->uFirst - 1;
+                    i++;
+                }
+                /* Replace the whole first match (lazy bird). */
+                else
+                {
+                    if (i + 1 < cMsrRanges)
+                        memmove(&paMsrRanges[i], &paMsrRanges[i + 1], (cMsrRanges - i - 1) * sizeof(paMsrRanges[0]));
+                    cMsrRanges = *pcMsrRanges -= 1;
+                }
+
+                /* Do the new range affect more ranges? */
+                while (   i < cMsrRanges
+                       && pNewRange->uLast >= paMsrRanges[i].uFirst)
+                {
+                    if (pNewRange->uLast < paMsrRanges[i].uLast)
+                    {
+                        /* Adjust the start of it, then we're done. */
+                        paMsrRanges[i].uFirst = pNewRange->uLast + 1;
+                        break;
+                    }
+
+                    /* Remove it entirely. */
+                    if (i + 1 < cMsrRanges)
+                        memmove(&paMsrRanges[i], &paMsrRanges[i + 1], (cMsrRanges - i - 1) * sizeof(paMsrRanges[0]));
+                    cMsrRanges = *pcMsrRanges -= 1;
+                }
+            }
+
+            /* Now, perform a normal insertion. */
+            paMsrRanges = cpumR3MsrRangesEnsureSpace(ppaMsrRanges, cMsrRanges, 1);
+            if (!paMsrRanges)
+                return VERR_NO_MEMORY;
+            if (i < cMsrRanges)
+                memmove(&paMsrRanges[i + 1], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
+            paMsrRanges[i] = *pNewRange;
+            *pcMsrRanges += 1;
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for cpumR3MsrApplyFudge that applies one table.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 Pointer to the cross context VM structure.
+ * @param   paRanges            Array of MSRs to fudge.
+ * @param   cRanges             Number of MSRs in the array.
+ */
+static int cpumR3MsrApplyFudgeTable(PVM pVM, PCCPUMMSRRANGE paRanges, size_t cRanges)
+{
+    for (uint32_t i = 0; i < cRanges; i++)
+        if (!cpumLookupMsrRange(pVM, paRanges[i].uFirst))
+        {
+            LogRel(("CPUM: MSR fudge: %#010x %s\n", paRanges[i].uFirst, paRanges[i].szName));
+            int rc = cpumR3MsrRangesInsert(&pVM->cpum.s.GuestInfo.paMsrRangesR3, &pVM->cpum.s.GuestInfo.cMsrRanges,
+                                           &paRanges[i]);
+            if (RT_FAILURE(rc))
+                return rc;
+        }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Fudges the MSRs that guest are known to access in some odd cases.
+ *
+ * A typical example is a VM that has been moved between different hosts where
+ * for instance the cpu vendor differs.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 Pointer to the cross context VM structure.
+ */
+int cpumR3MsrApplyFudge(PVM pVM)
+{
+    /*
+     * Basic.
+     */
+    static CPUMMSRRANGE const s_aFudgeMsrs[] =
+    {
+        MFO(0x00000000, "IA32_P5_MC_ADDR",          Ia32P5McAddr),
+        MFX(0x00000001, "IA32_P5_MC_TYPE",          Ia32P5McType,   Ia32P5McType,   0, 0, UINT64_MAX),
+        MVO(0x00000017, "IA32_PLATFORM_ID",         0),
+        MFN(0x0000001b, "IA32_APIC_BASE",           Ia32ApicBase,   Ia32ApicBase),
+        MVI(0x0000008b, "BIOS_SIGN",                0),
+        MFX(0x000000fe, "IA32_MTRRCAP",             Ia32MtrrCap,    ReadOnly,       0x508, 0, 0),
+        MFX(0x00000179, "IA32_MCG_CAP",             Ia32McgCap,     ReadOnly,       0x005, 0, 0),
+        MFX(0x0000017a, "IA32_MCG_STATUS",          Ia32McgStatus,  Ia32McgStatus,  0, ~(uint64_t)UINT32_MAX, 0),
+        MFN(0x000001a0, "IA32_MISC_ENABLE",         Ia32MiscEnable, Ia32MiscEnable),
+        MFN(0x000001d9, "IA32_DEBUGCTL",            Ia32DebugCtl,   Ia32DebugCtl),
+        MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP",   P6LastBranchFromIp),
+        MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP",     P6LastBranchToIp),
+        MFO(0x000001dd, "P6_LAST_INT_FROM_IP",      P6LastIntFromIp),
+        MFO(0x000001de, "P6_LAST_INT_TO_IP",        P6LastIntToIp),
+        MFS(0x00000277, "IA32_PAT",                 Ia32Pat, Ia32Pat, Guest.msrPAT),
+        MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE",       Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, ~(uint64_t)0xc07),
+        MFN(0x00000400, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    };
+    int rc = cpumR3MsrApplyFudgeTable(pVM, &s_aFudgeMsrs[0], RT_ELEMENTS(s_aFudgeMsrs));
+    AssertLogRelRCReturn(rc, rc);
+
+    /*
+     * XP might mistake opterons and other newer CPUs for P4s.
+     */
+    if (pVM->cpum.s.GuestFeatures.uFamily >= 0xf)
+    {
+        static CPUMMSRRANGE const s_aP4FudgeMsrs[] =
+        {
+            MFX(0x0000002c, "P4_EBC_FREQUENCY_ID", IntelP4EbcFrequencyId, IntelP4EbcFrequencyId, 0xf12010f, UINT64_MAX, 0),
+        };
+        rc = cpumR3MsrApplyFudgeTable(pVM, &s_aP4FudgeMsrs[0], RT_ELEMENTS(s_aP4FudgeMsrs));
+        AssertLogRelRCReturn(rc, rc);
+    }
+
+    return rc;
+}
+
+
+int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
+{
+    CPUMDBENTRY const *pEntry = NULL;
+    int                rc;
+
+    if (!strcmp(pszName, "host"))
+    {
+        /*
+         * Create a CPU database entry for the host CPU.  This means getting
+         * the CPUID bits from the real CPU and grabbing the closest matching
+         * database entry for MSRs.
+         */
+        rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
+        if (RT_FAILURE(rc))
+            return rc;
+        rc = CPUMR3CpuIdCollectLeaves(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
+        if (RT_FAILURE(rc))
+            return rc;
+
+        /* Lookup database entry for MSRs. */
+        CPUMCPUVENDOR const enmVendor    = CPUMR3CpuIdDetectVendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
+                                                                     pInfo->paCpuIdLeavesR3[0].uEbx,
+                                                                     pInfo->paCpuIdLeavesR3[0].uEcx,
+                                                                     pInfo->paCpuIdLeavesR3[0].uEdx);
+        uint32_t      const uStd1Eax     = pInfo->paCpuIdLeavesR3[1].uEax;
+        uint8_t       const uFamily      = ASMGetCpuFamily(uStd1Eax);
+        uint8_t       const uModel       = ASMGetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
+        uint8_t       const uStepping    = ASMGetCpuStepping(uStd1Eax);
+        CPUMMICROARCH const enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(enmVendor, uFamily, uModel, uStepping);
+
+        for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
+        {
+            CPUMDBENTRY const *pCur = g_apCpumDbEntries[i];
+            if ((CPUMCPUVENDOR)pCur->enmVendor == enmVendor)
+            {
+                /* Match against Family, Microarch, model and stepping.  Except
+                   for family, always match the closer with preference given to
+                   the later/older ones. */
+                if (pCur->uFamily == uFamily)
+                {
+                    if (pCur->enmMicroarch == enmMicroarch)
+                    {
+                        if (pCur->uModel == uModel)
+                        {
+                            if (pCur->uStepping == uStepping)
+                            {
+                                /* Perfect match. */
+                                pEntry = pCur;
+                                break;
+                            }
+
+                            if (   !pEntry
+                                || pEntry->uModel       != uModel
+                                || pEntry->enmMicroarch != enmMicroarch
+                                || pEntry->uFamily      != uFamily)
+                                pEntry = pCur;
+                            else if (  pCur->uStepping >= uStepping
+                                     ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
+                                     : pCur->uStepping > pEntry->uStepping)
+                                     pEntry = pCur;
+                        }
+                        else if (   !pEntry
+                                 || pEntry->enmMicroarch != enmMicroarch
+                                 || pEntry->uFamily      != uFamily)
+                            pEntry = pCur;
+                        else if (  pCur->uModel >= uModel
+                                 ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
+                                 : pCur->uModel > pEntry->uModel)
+                            pEntry = pCur;
+                    }
+                    else if (   !pEntry
+                             || pEntry->uFamily != uFamily)
+                        pEntry = pCur;
+                    else if (  pCur->enmMicroarch >= enmMicroarch
+                             ? pCur->enmMicroarch < pEntry->enmMicroarch || pEntry->enmMicroarch < enmMicroarch
+                             : pCur->enmMicroarch > pEntry->enmMicroarch)
+                        pEntry = pCur;
+                }
+                /* We don't do closeness matching on family, we use the first
+                   entry for the CPU vendor instead. (P4 workaround.) */
+                else if (!pEntry)
+                    pEntry = pCur;
+            }
+        }
+
+        if (pEntry)
+            LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s).\n",
+                    CPUMR3CpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMR3MicroarchName(enmMicroarch),
+                    pEntry->pszName,  CPUMR3CpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor), pEntry->uFamily, pEntry->uModel,
+                    pEntry->uStepping, CPUMR3MicroarchName(pEntry->enmMicroarch) ));
+        else
+        {
+            pEntry = g_apCpumDbEntries[0];
+            LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'.\n",
+                    CPUMR3CpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMR3MicroarchName(enmMicroarch),
+                    pEntry->pszName));
+        }
+    }
+    else
+    {
+        /*
+         * We're supposed to be emulating a specific CPU that is included in
+         * our CPU database.  The CPUID tables needs to be copied onto the
+         * heap so the caller can modify them and so they can be freed like
+         * in the host case above.
+         */
+        for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
+            if (!strcmp(pszName, g_apCpumDbEntries[i]->pszName))
+            {
+                pEntry = g_apCpumDbEntries[i];
+                break;
+            }
+        if (!pEntry)
+        {
+            LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
+            return VERR_CPUM_DB_CPU_NOT_FOUND;
+        }
+
+        pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves;
+        if (pEntry->cCpuIdLeaves)
+        {
+            pInfo->paCpuIdLeavesR3 = (PCPUMCPUIDLEAF)RTMemDup(pEntry->paCpuIdLeaves,
+                                                              sizeof(pEntry->paCpuIdLeaves[0]) * pEntry->cCpuIdLeaves);
+            if (!pInfo->paCpuIdLeavesR3)
+                return VERR_NO_MEMORY;
+        }
+        else
+            pInfo->paCpuIdLeavesR3 = NULL;
+
+        pInfo->enmUnknownCpuIdMethod = pEntry->enmUnknownCpuId;
+        pInfo->DefCpuId         = pEntry->DefUnknownCpuId;
+
+        LogRel(("CPUM: Using CPU DB entry '%s' (%s %#x/%#x/%#x %s).\n",
+                pEntry->pszName, CPUMR3CpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor),
+                pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMR3MicroarchName(pEntry->enmMicroarch) ));
+    }
+
+    pInfo->fMsrMask             = pEntry->fMsrMask;
+    pInfo->iFirstExtCpuIdLeaf   = 0; /* Set by caller. */
+    pInfo->uPadding             = 0;
+    pInfo->paCpuIdLeavesR0      = NIL_RTR0PTR;
+    pInfo->paMsrRangesR0        = NIL_RTR0PTR;
+    pInfo->paCpuIdLeavesRC      = NIL_RTRCPTR;
+    pInfo->paMsrRangesRC        = NIL_RTRCPTR;
+
+    /*
+     * Copy the MSR range.
+     */
+    uint32_t        cMsrs   = 0;
+    PCPUMMSRRANGE   paMsrs  = NULL;
+
+    PCCPUMMSRRANGE  pCurMsr = pEntry->paMsrRanges;
+    uint32_t        cLeft   = pEntry->cMsrRanges;
+    while (cLeft-- > 0)
+    {
+        rc = cpumR3MsrRangesInsert(&paMsrs, &cMsrs, pCurMsr);
+        if (RT_FAILURE(rc))
+        {
+            Assert(!paMsrs); /* The above function frees this. */
+            RTMemFree(pInfo->paCpuIdLeavesR3);
+            pInfo->paCpuIdLeavesR3 = NULL;
+            return rc;
+        }
+        pCurMsr++;
+    }
+
+    pInfo->paMsrRangesR3   = paMsrs;
+    pInfo->cMsrRanges      = cMsrs;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Register statistics for the MSRs.
+ *
+ * This must not be called before the MSRs have been finalized and moved to the
+ * hyper heap.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 Pointer to the cross context VM structure.
+ */
+int cpumR3MsrRegStats(PVM pVM)
+{
+    /*
+     * Global statistics.
+     */
+    PCPUM pCpum = &pVM->cpum.s;
+    STAM_REL_REG(pVM, &pCpum->cMsrReads,                STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/Reads",
+                 STAMUNIT_OCCURENCES, "All RDMSRs making it to CPUM.");
+    STAM_REL_REG(pVM, &pCpum->cMsrReadsRaiseGp,         STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/ReadsRaisingGP",
+                 STAMUNIT_OCCURENCES, "RDMSR raising #GPs, except unknown MSRs.");
+    STAM_REL_REG(pVM, &pCpum->cMsrReadsUnknown,         STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/ReadsUnknown",
+                 STAMUNIT_OCCURENCES, "RDMSR on unknown MSRs (raises #GP).");
+    STAM_REL_REG(pVM, &pCpum->cMsrWrites,               STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/Writes",
+                 STAMUNIT_OCCURENCES, "All RDMSRs making it to CPUM.");
+    STAM_REL_REG(pVM, &pCpum->cMsrWritesRaiseGp,        STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesRaisingGP",
+                 STAMUNIT_OCCURENCES, "WRMSR raising #GPs, except unknown MSRs.");
+    STAM_REL_REG(pVM, &pCpum->cMsrWritesToIgnoredBits,  STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesToIgnoredBits",
+                 STAMUNIT_OCCURENCES, "Writing of ignored bits.");
+    STAM_REL_REG(pVM, &pCpum->cMsrWritesUnknown,        STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesUnknown",
+                 STAMUNIT_OCCURENCES, "WRMSR on unknown MSRs (raises #GP).");
+
+
+# ifdef VBOX_WITH_STATISTICS
+    /*
+     * Per range.
+     */
+    PCPUMMSRRANGE   paRanges = pVM->cpum.s.GuestInfo.paMsrRangesR3;
+    uint32_t        cRanges  = pVM->cpum.s.GuestInfo.cMsrRanges;
+    for (uint32_t i = 0; i < cRanges; i++)
+    {
+        char    szName[160];
+        ssize_t cchName;
+
+        if (paRanges[i].uFirst == paRanges[i].uLast)
+            cchName = RTStrPrintf(szName, sizeof(szName), "/CPUM/MSRs/%#010x-%s",
+                                  paRanges[i].uFirst, paRanges[i].szName);
+        else
+            cchName = RTStrPrintf(szName, sizeof(szName), "/CPUM/MSRs/%#010x-%#010x-%s",
+                                  paRanges[i].uFirst, paRanges[i].uLast, paRanges[i].szName);
+
+        RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-reads");
+        STAMR3Register(pVM, &paRanges[i].cReads, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES, "RDMSR");
+
+        RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-writes");
+        STAMR3Register(pVM, &paRanges[i].cWrites, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR");
+
+        RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-GPs");
+        STAMR3Register(pVM, &paRanges[i].cGps, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "#GPs");
+
+        RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-ign-bits-writes");
+        STAMR3Register(pVM, &paRanges[i].cIgnoredBits, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR w/ ignored bits");
+    }
+# endif /* VBOX_WITH_STATISTICS */
+
+    return VINF_SUCCESS;
+}
+
+#endif /* !CPUM_DB_STANDALONE */
+
diff --git a/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp b/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp
index 601b050..dbc2c00 100644
--- a/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp
+++ b/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp
@@ -176,14 +176,18 @@ int dbgfR3AsInit(PUVM pUVM)
     PCFGMNODE pCfgDbgf = CFGMR3GetChild(CFGMR3GetRootU(pUVM), "/DBGF");
     for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++)
     {
-        const char *pszEnvValue = RTEnvGet(s_aProps[i].pszEnvName);
-        if (pszEnvValue)
+        char szEnvValue[8192];
+        rc = RTEnvGetEx(RTENV_DEFAULT, s_aProps[i].pszEnvName, szEnvValue, sizeof(szEnvValue), NULL);
+        if (RT_SUCCESS(rc))
         {
-            rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, pszEnvValue);
+            rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, szEnvValue);
             if (RT_FAILURE(rc))
                 return VMR3SetError(pUVM, rc, RT_SRC_POS,
-                                    "DBGF Config Error: %s=%s -> %Rrc", s_aProps[i].pszEnvName, pszEnvValue, rc);
+                                    "DBGF Config Error: %s=%s -> %Rrc", s_aProps[i].pszEnvName, szEnvValue, rc);
         }
+        else if (rc != VERR_ENV_VAR_NOT_FOUND)
+            return VMR3SetError(pUVM, rc, RT_SRC_POS,
+                                "DBGF Config Error: Error querying env.var. %s: %Rrc", s_aProps[i].pszEnvName, rc);
 
         char *pszCfgValue;
         rc = CFGMR3QueryStringAllocDef(pCfgDbgf, s_aProps[i].pszCfgName, &pszCfgValue, NULL);
diff --git a/src/VBox/VMM/VMMR3/EM.cpp b/src/VBox/VMM/VMMR3/EM.cpp
index e6b5716..024cbec 100644
--- a/src/VBox/VMM/VMMR3/EM.cpp
+++ b/src/VBox/VMM/VMMR3/EM.cpp
@@ -2397,7 +2397,7 @@ VMMR3_INT_DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu)
                         REMR3Reset(pVM);
                         PGMR3ResetCpu(pVM, pVCpu);
                         TRPMR3ResetCpu(pVCpu);
-                        CPUMR3ResetCpu(pVCpu);
+                        CPUMR3ResetCpu(pVM, pVCpu);
                         EMR3ResetCpu(pVCpu);
                         HMR3ResetCpu(pVCpu);
                         pVCpu->em.s.enmState = emR3Reschedule(pVM, pVCpu, pVCpu->em.s.pCtx);
diff --git a/src/VBox/VMM/VMMR3/MMHyper.cpp b/src/VBox/VMM/VMMR3/MMHyper.cpp
index c6c1f07..9143d98 100644
--- a/src/VBox/VMM/VMMR3/MMHyper.cpp
+++ b/src/VBox/VMM/VMMR3/MMHyper.cpp
@@ -808,17 +808,14 @@ static int mmR3HyperHeapCreate(PVM pVM, const size_t cb, PMMHYPERHEAP *ppHeap, P
                               0 /*fFlags*/,
                               &pv,
 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
-                              HMIsEnabled(pVM) ? &pvR0 : NULL,
+                              &pvR0,
 #else
                               NULL,
 #endif
                               paPages);
     if (RT_SUCCESS(rc))
     {
-#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
-        if (!HMIsEnabled(pVM))
-            pvR0 = NIL_RTR0PTR;
-#else
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
         pvR0 = (uintptr_t)pv;
 #endif
         memset(pv, 0, cbAligned);
diff --git a/src/VBox/VMM/VMMR3/PGM.cpp b/src/VBox/VMM/VMMR3/PGM.cpp
index ed66a83..126a06d 100644
--- a/src/VBox/VMM/VMMR3/PGM.cpp
+++ b/src/VBox/VMM/VMMR3/PGM.cpp
@@ -2167,6 +2167,7 @@ VMMR3DECL(int) PGMR3InitFinalize(PVM pVM)
         pVM->pgm.s.HCPhysInvMmioPg |= UINT64_C(0x000f0000000000);
     }
 
+    /** @todo query from CPUM. */
     pVM->pgm.s.GCPhysInvAddrMask = 0;
     for (uint32_t iBit = cMaxPhysAddrWidth; iBit < 64; iBit++)
         pVM->pgm.s.GCPhysInvAddrMask |= RT_BIT_64(iBit);
diff --git a/src/VBox/VMM/VMMR3/VM.cpp b/src/VBox/VMM/VMMR3/VM.cpp
index adc8b9b..a13224b 100644
--- a/src/VBox/VMM/VMMR3/VM.cpp
+++ b/src/VBox/VMM/VMMR3/VM.cpp
@@ -4379,7 +4379,7 @@ static DECLCALLBACK(int) vmR3HotUnplugCpu(PVM pVM, VMCPUID idCpu)
     PGMR3ResetCpu(pVM, pVCpu);
     PDMR3ResetCpu(pVCpu);
     TRPMR3ResetCpu(pVCpu);
-    CPUMR3ResetCpu(pVCpu);
+    CPUMR3ResetCpu(pVM, pVCpu);
     EMR3ResetCpu(pVCpu);
     HMR3ResetCpu(pVCpu);
     return VINF_EM_WAIT_SIPI;
diff --git a/src/VBox/VMM/VMMR3/VMM.cpp b/src/VBox/VMM/VMMR3/VMM.cpp
index 510ec5d..c0a1400 100644
--- a/src/VBox/VMM/VMMR3/VMM.cpp
+++ b/src/VBox/VMM/VMMR3/VMM.cpp
@@ -1419,7 +1419,7 @@ DECLCALLBACK(int) vmmR3SendInitIpi(PVM pVM, VMCPUID idCpu)
     Log(("vmmR3SendInitIpi for VCPU %d\n", idCpu));
 
     PGMR3ResetCpu(pVM, pVCpu);
-    CPUMR3ResetCpu(pVCpu);
+    CPUMR3ResetCpu(pVM, pVCpu);
 
     return VINF_EM_WAIT_SIPI;
 }
@@ -1948,7 +1948,9 @@ VMMR3DECL(int) VMMR3CallRCV(PVM pVM, RTRCPTR RCPtrEntry, unsigned cArgs, va_list
                       cArgs        /* edx */
                       );
 
+#if 0
     memset(pVCpu->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */
+#endif
     PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVCpu->vmm.s.pbEMTStackR3 + VMM_STACK_SIZE) - cArgs;
     int i = cArgs;
     while (i-- > 0)
diff --git a/src/VBox/VMM/VMMR3/VMMTests.cpp b/src/VBox/VMM/VMMR3/VMMTests.cpp
index 5b3619e..066c3c3 100644
--- a/src/VBox/VMM/VMMR3/VMMTests.cpp
+++ b/src/VBox/VMM/VMMR3/VMMTests.cpp
@@ -52,6 +52,137 @@ static void vmmR3TestClearStack(PVMCPU pVCpu)
 
 #ifdef VBOX_WITH_RAW_MODE
 
+static int vmmR3ReportMsrRange(PVM pVM, uint32_t uMsr, uint64_t cMsrs, PRTSTREAM pReportStrm, uint32_t *pcMsrsFound)
+{
+    /*
+     * Preps.
+     */
+    RTRCPTR RCPtrEP;
+    int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "VMMRCTestReadMsrs", &RCPtrEP);
+    AssertMsgRCReturn(rc, ("Failed to resolved VMMRC.rc::VMMRCEntry(), rc=%Rrc\n", rc), rc);
+
+    uint32_t const      cMsrsPerCall = 16384;
+    uint32_t            cbResults = cMsrsPerCall * sizeof(VMMTESTMSRENTRY);
+    PVMMTESTMSRENTRY    paResults;
+    rc = MMHyperAlloc(pVM, cbResults, 0, MM_TAG_VMM, (void **)&paResults);
+    AssertMsgRCReturn(rc, ("Error allocating %#x bytes off the hyper heap: %Rrc\n", cbResults, rc), rc);
+    /*
+     * The loop.
+     */
+    RTRCPTR  RCPtrResults = MMHyperR3ToRC(pVM, paResults);
+    uint32_t cMsrsFound   = 0;
+    uint32_t uLastMsr     = uMsr;
+    uint64_t uNsTsStart   = RTTimeNanoTS();
+
+    for (;;)
+    {
+        if (   pReportStrm
+            && uMsr - uLastMsr > _64K
+            && (uMsr & (_4M - 1)) == 0)
+        {
+            if (uMsr - uLastMsr < 16U*_1M)
+                RTStrmFlush(pReportStrm);
+            RTPrintf("... %#010x [%u ns/msr] ...\n", uMsr, (RTTimeNanoTS() - uNsTsStart) / uMsr);
+        }
+
+        /*RT_BZERO(paResults, cbResults);*/
+        uint32_t const cBatch = RT_MIN(cMsrsPerCall, cMsrs);
+        rc = VMMR3CallRC(pVM, RCPtrEP, 4, pVM->pVMRC, uMsr, cBatch, RCPtrResults);
+        if (RT_FAILURE(rc))
+        {
+            RTPrintf("VMM: VMMR3CallRC failed rc=%Rrc, uMsr=%#x\n", rc, uMsr);
+            break;
+        }
+
+        for (uint32_t i = 0; i < cBatch; i++)
+            if (paResults[i].uMsr != UINT64_MAX)
+            {
+                if (paResults[i].uValue == 0)
+                {
+                    if (pReportStrm)
+                        RTStrmPrintf(pReportStrm,
+                                     "    MVO(%#010llx, \"MSR\", UINT64_C(%#018llx)),\n", paResults[i].uMsr, paResults[i].uValue);
+                    RTPrintf("%#010llx = 0\n", paResults[i].uMsr);
+                }
+                else
+                {
+                    if (pReportStrm)
+                        RTStrmPrintf(pReportStrm,
+                                     "    MVO(%#010llx, \"MSR\", UINT64_C(%#018llx)),\n", paResults[i].uMsr, paResults[i].uValue);
+                    RTPrintf("%#010llx = %#010x`%08x\n", paResults[i].uMsr,
+                             (uint32_t)(paResults[i].uValue >> 32), (uint32_t)paResults[i].uValue);
+                }
+                cMsrsFound++;
+                uLastMsr = paResults[i].uMsr;
+            }
+
+        /* Advance. */
+        if (cMsrs <= cMsrsPerCall)
+            break;
+        cMsrs -= cMsrsPerCall;
+        uMsr  += cMsrsPerCall;
+    }
+
+    *pcMsrsFound += cMsrsFound;
+    MMHyperFree(pVM, paResults);
+    return rc;
+}
+
+
+/**
+ * Produces a quick report of MSRs.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the cross context VM structure.
+ * @param   pReportStrm     Pointer to the report output stream. Optional.
+ * @param   fWithCpuId      Whether CPUID should be included.
+ */
+static int vmmR3DoMsrQuickReport(PVM pVM, PRTSTREAM pReportStrm, bool fWithCpuId)
+{
+    uint64_t uTsStart = RTTimeNanoTS();
+    RTPrintf("=== MSR Quick Report Start ===\n");
+    RTStrmFlush(g_pStdOut);
+    if (fWithCpuId)
+    {
+        DBGFR3InfoStdErr(pVM->pUVM, "cpuid", "verbose");
+        RTPrintf("\n");
+    }
+    if (pReportStrm)
+        RTStrmPrintf(pReportStrm, "\n\n{\n");
+
+    static struct { uint32_t uFirst, cMsrs; } const s_aRanges[] =
+    {
+        { 0x00000000, 0x00042000 },
+        { 0x10000000, 0x00001000 },
+        { 0x20000000, 0x00001000 },
+        { 0x40000000, 0x00012000 },
+        { 0x80000000, 0x00012000 },
+//   Need 0xc0000000..0xc001106f (at least), but trouble on solaris w/ 10h and 0fh family cpus:
+//      { 0xc0000000, 0x00022000 },
+        { 0xc0000000, 0x00010000 },
+        { 0xc0010000, 0x00001040 },
+        { 0xc0011040, 0x00004040 }, /* should cause trouble... */
+    };
+    uint32_t cMsrsFound = 0;
+    int rc = VINF_SUCCESS;
+    for (unsigned i = 0; i < RT_ELEMENTS(s_aRanges) && RT_SUCCESS(rc); i++)
+    {
+//if (i >= 3)
+//{
+//RTStrmFlush(g_pStdOut);
+//RTThreadSleep(40);
+//}
+        rc = vmmR3ReportMsrRange(pVM, s_aRanges[i].uFirst, s_aRanges[i].cMsrs, pReportStrm, &cMsrsFound);
+    }
+
+    if (pReportStrm)
+        RTStrmPrintf(pReportStrm, "}; /* %u (%#x) MSRs; rc=%Rrc */\n", cMsrsFound, cMsrsFound, rc);
+    RTPrintf("Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
+    RTPrintf("=== MSR Quick Report End (rc=%Rrc, %'llu ns) ===\n", rc, RTTimeNanoTS() - uTsStart);
+    return rc;
+}
+
+
 /**
  * Performs a testcase.
  *
@@ -467,6 +598,13 @@ VMMR3DECL(int) VMMDoTest(PVM pVM)
              i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration, TickMin));
 
         rc = VINF_SUCCESS;
+
+#if 0  /* drop this for now as it causes trouble on AMDs (Opteron 2384 and possibly others). */
+        /*
+         * A quick MSR report.
+         */
+        vmmR3DoMsrQuickReport(pVM, NULL, true);
+#endif
     }
     else
         AssertMsgFailed(("Failed to resolved VMMGC.gc::VMMGCEntry(), rc=%Rrc\n", rc));
@@ -617,3 +755,199 @@ VMMR3DECL(int) VMMDoHmTest(PVM pVM)
     return rc;
 }
 
+
+#ifdef VBOX_WITH_RAW_MODE
+
+/**
+ * Used by VMMDoBruteForceMsrs to dump the CPUID info of the host CPU as a
+ * prefix to the MSR report.
+ */
+static DECLCALLBACK(void) vmmDoPrintfVToStream(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list va)
+{
+    PRTSTREAM pOutStrm = ((PRTSTREAM *)pHlp)[-1];
+    RTStrmPrintfV(pOutStrm, pszFormat, va);
+}
+
+/**
+ * Used by VMMDoBruteForceMsrs to dump the CPUID info of the host CPU as a
+ * prefix to the MSR report.
+ */
+static DECLCALLBACK(void) vmmDoPrintfToStream(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    vmmDoPrintfVToStream(pHlp, pszFormat, va);
+    va_end(va);
+}
+
+#endif
+
+
+/**
+ * Uses raw-mode to query all possible MSRs on the real hardware.
+ *
+ * This generates a msr-report.txt file (appending, no overwriting) as well as
+ * writing the values and process to stdout.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+VMMR3DECL(int) VMMDoBruteForceMsrs(PVM pVM)
+{
+#ifdef VBOX_WITH_RAW_MODE
+    PRTSTREAM pOutStrm;
+    int rc = RTStrmOpen("msr-report.txt", "a", &pOutStrm);
+    if (RT_SUCCESS(rc))
+    {
+        /* Header */
+        struct
+        {
+            PRTSTREAM   pOutStrm;
+            DBGFINFOHLP Hlp;
+        } MyHlp = { pOutStrm, { vmmDoPrintfToStream, vmmDoPrintfVToStream } };
+        DBGFR3Info(pVM->pUVM, "cpuid", "verbose", &MyHlp.Hlp);
+        RTStrmPrintf(pOutStrm, "\n");
+
+        uint32_t cMsrsFound = 0;
+        vmmR3ReportMsrRange(pVM, 0, _4G, pOutStrm, &cMsrsFound);
+
+        RTStrmPrintf(pOutStrm, "Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
+        RTPrintf("Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
+
+        RTStrmClose(pOutStrm);
+    }
+    return rc;
+#else
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
+
+/**
+ * Uses raw-mode to query all known MSRS on the real hardware.
+ *
+ * This generates a known-msr-report.txt file (appending, no overwriting) as
+ * well as writing the values and process to stdout.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+VMMR3DECL(int) VMMDoKnownMsrs(PVM pVM)
+{
+#ifdef VBOX_WITH_RAW_MODE
+    PRTSTREAM pOutStrm;
+    int rc = RTStrmOpen("known-msr-report.txt", "a", &pOutStrm);
+    if (RT_SUCCESS(rc))
+    {
+        vmmR3DoMsrQuickReport(pVM, pOutStrm, false);
+        RTStrmClose(pOutStrm);
+    }
+    return rc;
+#else
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
+
+/**
+ * MSR experimentation.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+VMMR3DECL(int) VMMDoMsrExperiments(PVM pVM)
+{
+#ifdef VBOX_WITH_RAW_MODE
+    /*
+     * Preps.
+     */
+    RTRCPTR RCPtrEP;
+    int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "VMMRCTestTestWriteMsr", &RCPtrEP);
+    AssertMsgRCReturn(rc, ("Failed to resolved VMMRC.rc::VMMRCEntry(), rc=%Rrc\n", rc), rc);
+
+    uint64_t *pauValues;
+    rc = MMHyperAlloc(pVM, 2 * sizeof(uint64_t), 0, MM_TAG_VMM, (void **)&pauValues);
+    AssertMsgRCReturn(rc, ("Error allocating %#x bytes off the hyper heap: %Rrc\n", 2 * sizeof(uint64_t), rc), rc);
+    RTRCPTR RCPtrValues = MMHyperR3ToRC(pVM, pauValues);
+
+    /*
+     * Do the experiments.
+     */
+    uint32_t uMsr   = 0x00000277;
+    uint64_t uValue = UINT64_C(0x0007010600070106);
+#if 0
+    uValue &= ~(RT_BIT_64(17) | RT_BIT_64(16) | RT_BIT_64(15) | RT_BIT_64(14) | RT_BIT_64(13));
+    uValue |= RT_BIT_64(13);
+    rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                     RCPtrValues, RCPtrValues + sizeof(uint64_t));
+    RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
+             uMsr, pauValues[0], uValue, pauValues[1], rc);
+#elif 1
+    const uint64_t uOrgValue = uValue;
+    uint32_t       cChanges = 0;
+    for (int iBit = 63; iBit >= 58; iBit--)
+    {
+        uValue = uOrgValue & ~RT_BIT_64(iBit);
+        rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                         RCPtrValues, RCPtrValues + sizeof(uint64_t));
+        RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\nclear bit=%u -> %s\n",
+                 uMsr, pauValues[0], uValue, pauValues[1], rc, iBit,
+                 (pauValues[0] ^  pauValues[1]) & RT_BIT_64(iBit) ?  "changed" : "unchanged");
+        cChanges += RT_BOOL(pauValues[0] ^ pauValues[1]);
+
+        uValue = uOrgValue | RT_BIT_64(iBit);
+        rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                         RCPtrValues, RCPtrValues + sizeof(uint64_t));
+        RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\nset   bit=%u -> %s\n",
+                 uMsr, pauValues[0], uValue, pauValues[1], rc, iBit,
+                 (pauValues[0] ^  pauValues[1]) & RT_BIT_64(iBit) ?  "changed" : "unchanged");
+        cChanges += RT_BOOL(pauValues[0] ^ pauValues[1]);
+    }
+    RTPrintf("%u change(s)\n", cChanges);
+#else
+    uint64_t fWriteable = 0;
+    for (uint32_t i = 0; i <= 63; i++)
+    {
+        uValue = RT_BIT_64(i);
+# if 0
+        if (uValue & (0x7))
+            continue;
+# endif
+        rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                         RCPtrValues, RCPtrValues + sizeof(uint64_t));
+        RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
+                 uMsr, pauValues[0], uValue, pauValues[1], rc);
+        if (RT_SUCCESS(rc))
+            fWriteable |= RT_BIT_64(i);
+    }
+
+    uValue = 0;
+    rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                     RCPtrValues, RCPtrValues + sizeof(uint64_t));
+    RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
+             uMsr, pauValues[0], uValue, pauValues[1], rc);
+
+    uValue = UINT64_MAX;
+    rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                     RCPtrValues, RCPtrValues + sizeof(uint64_t));
+    RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
+             uMsr, pauValues[0], uValue, pauValues[1], rc);
+
+    uValue = fWriteable;
+    rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
+                     RCPtrValues, RCPtrValues + sizeof(uint64_t));
+    RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc [fWriteable]\n",
+             uMsr, pauValues[0], uValue, pauValues[1], rc);
+
+#endif
+
+    /*
+     * Cleanups.
+     */
+    MMHyperFree(pVM, pauValues);
+    return rc;
+#else
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
diff --git a/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h b/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h
new file mode 100644
index 0000000..ea7072b
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h
@@ -0,0 +1,219 @@
+/* $Id: AMD_Athlon_64_3200.h $ */
+/** @file
+ * CPU database entry "AMD Athlon 64 3200+".
+ * Generated at 2013-07-12T02:09:05Z by VBoxCpuReport v4.3.53r91376 on win.x86.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_AMD_Athlon_64_3200
+#define VBOX_CPUDB_AMD_Athlon_64_3200
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for AMD Athlon(tm) 64 Processor 3200+.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_AMD_Athlon_64_3200[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x00000f48, 0x00000800, 0x00000000, 0x078bfbff, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000018, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000f48, 0x0000010a, 0x00000000, 0xe1d3fbff, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20444d41, 0x6c687441, 0x74286e6f, 0x3620296d, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x72502034, 0x7365636f, 0x20726f73, 0x30303233, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x0000002b, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0xff08ff08, 0xff20ff20, 0x40020140, 0x40020140, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x42004200, 0x04008140, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003028, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000010, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000011, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000013, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000014, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000015, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000016, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000017, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000018, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8fffffff, 0x00000000, 0x00000000, 0x53275449, 0x4d414820, 0x2052454d, 0x454d4954, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for AMD Athlon(tm) 64 Processor 3200+.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_AMD_Athlon_64_3200[] = 
+{
+    MAL(0x00000000, "IA32_P5_MC_ADDR", 0x00000402),
+    MAL(0x00000001, "IA32_P5_MC_TYPE", 0x00000401),
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x28`4505cb65 */
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00900), 0, UINT64_C(0xffffff00000006ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFO(0x0000008b, "AMD_K8_PATCH_LEVEL", AmdK8PatchLevel), /* value=0x39 */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0x508, 0, 0), /* value=0x508 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x8 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x8059e000 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x81872950 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x105, 0, 0), /* value=0x105 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, UINT64_C(0xfffffffffffffff8), 0), /* value=0x0 */
+    MFX(0x0000017b, "IA32_MCG_CTL", Ia32McgCtl, Ia32McgCtl, 0, UINT64_C(0xffffffffffffffe0), 0), /* value=0x1f */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, UINT64_C(0xffffffffffffff80), 0x40), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0xffffffed`bf1be178 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xffff7f49`bf1bedec */
+    MFO(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp), /* value=0x0 */
+    MFO(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp), /* value=0x0 */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffffff00000007ff)), /* value=0xff`c0000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffffff0000000ff8)), /* value=0xf8000001 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffffff00000007ff)), /* value=0xff`fc000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RFN(0x00000400, 0x00000413, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0x800, 0xfe, UINT64_C(0xfffffffffffff200)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x0 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0x0 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0x0 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0x81913800 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0x0 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x0 */
+    RSN(0xc0010000, 0xc0010003, "AMD_K8_PERF_CTL_n", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x0, UINT64_C(0xffffffff00200000), 0),
+    RSN(0xc0010004, 0xc0010007, "AMD_K8_PERF_CTR_n", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x0, UINT64_C(0xffff000000000000), 0),
+    MFX(0xc0010010, "AMD_K8_SYS_CFG", AmdK8SysCfg, AmdK8SysCfg, 0x160601, UINT64_C(0xffffffffffc0f800), 0), /* value=0x160601 */
+    MFX(0xc0010015, "AMD_K8_HW_CFG", AmdK8HwCr, AmdK8HwCr, 0xc000000, UINT64_C(0xffffffff3ff00000), 0), /* value=0xc000000 */
+    MFW(0xc0010016, "AMD_K8_IORR_BASE_0", AmdK8IorrBaseN, AmdK8IorrBaseN, UINT64_C(0xffffff0000000fe7)), /* value=0x0 */
+    MFW(0xc0010017, "AMD_K8_IORR_MASK_0", AmdK8IorrMaskN, AmdK8IorrMaskN, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0xc0010018, "AMD_K8_IORR_BASE_1", AmdK8IorrBaseN, AmdK8IorrBaseN, 0x1, UINT64_C(0xffffff0000000fe7), 0), /* value=0xf8000018 */
+    MFX(0xc0010019, "AMD_K8_IORR_MASK_1", AmdK8IorrMaskN, AmdK8IorrMaskN, 0x1, UINT64_C(0xffffff00000007ff), 0), /* value=0xff`fc000800 */
+    MFW(0xc001001a, "AMD_K8_TOP_MEM", AmdK8TopOfMemN, AmdK8TopOfMemN, UINT64_C(0xffffff00007fffff)), /* value=0x40000000 */
+    MFX(0xc001001d, "AMD_K8_TOP_MEM2", AmdK8TopOfMemN, AmdK8TopOfMemN, 0x1, UINT64_C(0xffffff00007fffff), 0), /* value=0x0 */
+    MVI(0xc001001e, "AMD_K8_MANID", 0x20),
+    MFX(0xc001001f, "AMD_K8_NB_CFG1", AmdK8NbCfg1, AmdK8NbCfg1, 0, UINT64_C(0xffffff0000000000), 0), /* value=0x11`00000008 */
+    MFN(0xc0010020, "AMD_K8_PATCH_LOADER", WriteOnly, AmdK8PatchLoader),
+    MVX(0xc0010021, "AMD_K8_UNK_c001_0021", 0, UINT64_C(0xfffffffe00000000), 0),
+    MFX(0xc0010022, "AMD_K8_MC_XCPT_REDIR", AmdK8McXcptRedir, AmdK8McXcptRedir, 0, UINT64_C(0xfffffffeffffffff), 0), /* value=0x0 */
+    RFN(0xc0010030, 0xc0010035, "AMD_K8_CPU_NAME_n", AmdK8CpuNameN, AmdK8CpuNameN),
+    MFX(0xc001003e, "AMD_K8_HTC", AmdK8HwThermalCtrl, AmdK8HwThermalCtrl, 0, UINT64_MAX, 0), /* value=0x0 */
+    MFI(0xc001003f, "AMD_K8_STC", AmdK8SwThermalCtrl), /* value=0x0 */
+    MFX(0xc0010041, "AMD_K8_FIDVID_CTL", AmdK8FidVidControl, AmdK8FidVidControl, UINT64_C(0x4e200000000c), 0x33, UINT64_C(0xfff00000fffee0c0)), /* value=0x4e20`0000000c */
+    MFX(0xc0010042, "AMD_K8_FIDVID_STATUS", AmdK8FidVidStatus, ReadOnly, UINT64_C(0x200000c0c0c), 0, 0), /* value=0x200`000c0c0c */
+    MVO(0xc0010043, "AMD_K8_THERMTRIP_STATUS", 0x521020),
+    RFN(0xc0010044, 0xc0010048, "AMD_K8_MC_CTL_MASK_n", AmdK8McCtlMaskN, AmdK8McCtlMaskN),
+    RSN(0xc0010050, 0xc0010053, "AMD_K8_SMI_ON_IO_TRAP_n", AmdK8SmiOnIoTrapN, AmdK8SmiOnIoTrapN, 0x0, 0, UINT64_C(0x1f00000000000000)),
+    MFX(0xc0010054, "AMD_K8_SMI_ON_IO_TRAP_CTL_STS", AmdK8SmiOnIoTrapCtlSts, AmdK8SmiOnIoTrapCtlSts, 0, 0, UINT64_C(0xffffffffffff1f00)), /* value=0x0 */
+    MFX(0xc0010111, "AMD_K8_SMM_BASE", AmdK8SmmBase, AmdK8SmmBase, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x98000 */
+    MFX(0xc0010112, "AMD_K8_SMM_ADDR", AmdK8SmmAddr, AmdK8SmmAddr, 0, UINT64_C(0xffffff000001ffff), 0), /* value=0x0 */
+    MFX(0xc0010113, "AMD_K8_SMM_MASK", AmdK8SmmMask, AmdK8SmmMask, 0, UINT64_C(0xffffff00000188c0), 0), /* value=0x1 */
+    MVX(0xc0010114, "AMD_K8_UNK_c001_0114", 0, 0, UINT64_C(0xffffffffffffffe4)),
+    MVX(0xc0010115, "AMD_K8_UNK_c001_0115", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0xc0010116, "AMD_K8_UNK_c001_0116", 0, 0, UINT64_C(0xffff0000ffff0000)),
+    MVX(0xc0010117, "AMD_K8_UNK_c001_0117", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0xc0010118, "AMD_K8_UNK_c001_0118",0,0,0),
+    MVX(0xc0010119, "AMD_K8_UNK_c001_0119",0,0,0),
+    MVX(0xc001011a, "AMD_K8_UNK_c001_011a", 0, 0, UINT64_C(0xffffffff00000fff)),
+    MVX(0xc001011b, "AMD_K8_UNK_c001_011b", 0, 0, ~(uint64_t)UINT32_MAX),
+    MVX(0xc001011c, "AMD_K8_UNK_c001_011c", UINT32_C(0xdb1f5000), 0, UINT64_C(0xffffffff00000fff)),
+    MFX(0xc0011000, "AMD_K7_MCODE_CTL", AmdK7MicrocodeCtl, AmdK7MicrocodeCtl, 0, ~(uint64_t)UINT32_MAX, 0x204), /* value=0x0 */
+    MFX(0xc0011001, "AMD_K7_APIC_CLUSTER_ID", AmdK7ClusterIdMaybe, AmdK7ClusterIdMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0011004, "AMD_K8_CPUID_CTL_STD01", AmdK8CpuIdCtlStd01hEdcx, AmdK8CpuIdCtlStd01hEdcx, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x78bfbff */
+    MFX(0xc0011005, "AMD_K8_CPUID_CTL_EXT01", AmdK8CpuIdCtlExt01hEdcx, AmdK8CpuIdCtlExt01hEdcx, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0xf1f3fbff */
+    MFX(0xc0011006, "AMD_K7_DEBUG_STS?", AmdK7DebugStatusMaybe, AmdK7DebugStatusMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFN(0xc0011007, "AMD_K7_BH_TRACE_BASE?", AmdK7BHTraceBaseMaybe, AmdK7BHTraceBaseMaybe), /* value=0x0 */
+    MFN(0xc0011008, "AMD_K7_BH_TRACE_PTR?", AmdK7BHTracePtrMaybe, AmdK7BHTracePtrMaybe), /* value=0x0 */
+    MFN(0xc0011009, "AMD_K7_BH_TRACE_LIM?", AmdK7BHTraceLimitMaybe, AmdK7BHTraceLimitMaybe), /* value=0x0 */
+    MFX(0xc001100a, "AMD_K7_HDT_CFG?", AmdK7HardwareDebugToolCfgMaybe, AmdK7HardwareDebugToolCfgMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc001100b, "AMD_K7_FAST_FLUSH_COUNT?", AmdK7FastFlushCountMaybe, AmdK7FastFlushCountMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x7c0 */
+    MFX(0xc001100c, "AMD_K7_NODE_ID", AmdK7NodeId, AmdK7NodeId, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x20906 */
+    MVX(0xc001100d, "AMD_K8_LOGICAL_CPUS_NUM?", 0x10a, 0, 0),
+    MVX(0xc001100e, "AMD_K8_WRMSR_BP?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001100f, "AMD_K8_WRMSR_BP_MASK?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011010, "AMD_K8_BH_TRACE_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011011, "AMD_K8_BH_TRACE_USRD?", 0, 0, 0), /* value=0xc0011011`00000283 */
+    MVX(0xc0011014, "AMD_K8_XCPT_BP_RIP?", 0, 0, 0),
+    MVX(0xc0011015, "AMD_K8_XCPT_BP_RIP_MASK?", 0, 0, 0),
+    MVX(0xc0011016, "AMD_K8_COND_HDT_VAL?", 0, 0, 0),
+    MVX(0xc0011017, "AMD_K8_COND_HDT_VAL_MASK?", 0, 0, 0),
+    MVX(0xc0011018, "AMD_K8_XCPT_BP_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001101d, "AMD_K8_NB_BIST?", 0, UINT64_C(0xfffffffffc000000), 0),
+    MVI(0xc001101e, "AMD_K8_THERMTRIP_2?", 0x521020), /* Villain? */
+    MVX(0xc001101f, "AMD_K8_NB_CFG?", UINT64_C(0x1100000008), UINT64_C(0xffffff0000000000), 0),
+    MFX(0xc0011020, "AMD_K7_LS_CFG", AmdK7LoadStoreCfg, AmdK7LoadStoreCfg, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x1000 */
+    MFX(0xc0011021, "AMD_K7_IC_CFG", AmdK7InstrCacheCfg, AmdK7InstrCacheCfg, 0x800, ~(uint64_t)UINT32_MAX, 0), /* value=0x800 */
+    MFX(0xc0011022, "AMD_K7_DC_CFG", AmdK7DataCacheCfg, AmdK7DataCacheCfg, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x24000008 */
+    MFN(0xc0011023, "AMD_K7_BU_CFG", AmdK7BusUnitCfg, AmdK7BusUnitCfg), /* Villain? value=0x2020 */
+    MFX(0xc0011024, "AMD_K7_DEBUG_CTL_2?", AmdK7DebugCtl2Maybe, AmdK7DebugCtl2Maybe, 0, UINT64_C(0xffffffffffffff00), 0), /* value=0x0 */
+    MFN(0xc0011025, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMatchMaybe, AmdK7Dr0DataMatchMaybe), /* value=0x0 */
+    MFN(0xc0011026, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMaskMaybe, AmdK7Dr0DataMaskMaybe), /* value=0x0 */
+    MFX(0xc0011027, "AMD_K7_DR0_ADDR_MASK", AmdK7DrXAddrMaskN, AmdK7DrXAddrMaskN, 0x0, UINT64_C(0xfffffffffffff000), 0), /* value=0x0 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for AMD Athlon(tm) 64 Processor 3200+.
+ */
+static CPUMDBENTRY const g_Entry_AMD_Athlon_64_3200 = 
+{
+    /*.pszName          = */ "AMD Athlon 64 3200+",
+    /*.pszFullName      = */ "AMD Athlon(tm) 64 Processor 3200+",
+    /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
+    /*.uFamily          = */ 15,
+    /*.uModel           = */ 4,
+    /*.uStepping        = */ 8,
+    /*.enmMicroarch     = */ kCpumMicroarch_AMD_K8_130nm,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 40,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_AMD_Athlon_64_3200),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_Athlon_64_3200)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_DEFAULTS,
+    /*.DefUnknownCpuId  = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_AMD_Athlon_64_3200)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_AMD_Athlon_64_3200),
+};
+
+#endif /* !VBOX_DB_AMD_Athlon_64_3200 */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h b/src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h
new file mode 100644
index 0000000..8efb945
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h
@@ -0,0 +1,378 @@
+/* $Id: AMD_FX_8150_Eight_Core.h $ */
+/** @file
+ * CPU database entry "AMD FX-8150 Eight-Core".
+ * Generated at 2013-12-09T11:27:04Z by VBoxCpuReport v4.3.51r91084 on win.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_AMD_FX_8150_Eight_Core
+#define VBOX_CPUDB_AMD_FX_8150_Eight_Core
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for AMD FX(tm)-8150 Eight-Core Processor.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_AMD_FX_8150_Eight_Core[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x00600f12, 0x02080800, 0x1e98220b, 0x178bfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00000000, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0 },
+    { 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000d, 0x00000000, UINT32_MAX, 0x00000007, 0x00000340, 0x000003c0, 0x40000000, 0 },
+    { 0x0000000d, 0x00000001, UINT32_MAX, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x8000001e, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00600f12, 0x10000000, 0x01c9bfff, 0x2fd3fbff, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20444d41, 0x74285846, 0x382d296d, 0x20303531, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x68676945, 0x6f432d74, 0x50206572, 0x65636f72, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x726f7373, 0x20202020, 0x20202020, 0x00202020, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0xff20ff18, 0xff20ff30, 0x10040140, 0x40020140, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x64000000, 0x64004200, 0x08008140, 0x0040c140, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000003d9, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003030, 0x00000000, 0x00004007, 0x00000000, 0 },
+    { 0x80000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000a, 0x00000000, 0x00000000, 0x00000001, 0x00010000, 0x00000000, 0x000014ff, 0 },
+    { 0x8000000b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000010, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000011, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000013, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000014, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000015, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000016, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000017, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000018, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000019, 0x00000000, 0x00000000, 0xf020f018, 0x64000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001a, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001b, 0x00000000, 0x00000000, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001c, 0x00000000, 0x00000000, 0x00000000, 0x80032013, 0x00010200, 0x8000000f, 0 },
+    { 0x8000001d, 0x00000000, UINT32_MAX, 0x00000121, 0x00c0003f, 0x0000003f, 0x00000000, 0 },
+    { 0x8000001d, 0x00000001, UINT32_MAX, 0x00004122, 0x0040003f, 0x000001ff, 0x00000000, 0 },
+    { 0x8000001d, 0x00000002, UINT32_MAX, 0x00004143, 0x03c0003f, 0x000007ff, 0x00000001, 0 },
+    { 0x8000001d, 0x00000003, UINT32_MAX, 0x0001c163, 0x0fc0003f, 0x000007ff, 0x00000001, 0 },
+    { 0x8000001d, 0x00000004, UINT32_MAX, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001e, 0x00000000, 0x00000000, 0x00000012, 0x00000101, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for AMD FX(tm)-8150 Eight-Core Processor.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_AMD_FX_8150_Eight_Core[] = 
+{
+    MAL(0x00000000, "IA32_P5_MC_ADDR", 0x00000402),
+    MAL(0x00000001, "IA32_P5_MC_TYPE", 0x00000401),
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0, UINT64_C(0xffff0000000006ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MVO(0x0000008b, "BBL_CR_D3|BIOS_SIGN", 0x6000626),
+    MFN(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf),
+    MFN(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf),
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0x508, 0, 0), /* value=0x508 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x107, 0, 0), /* value=0x107 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, UINT64_C(0xfffffffffffffff8), 0), /* value=0x0 */
+    MFX(0x0000017b, "IA32_MCG_CTL", Ia32McgCtl, Ia32McgCtl, 0, UINT64_C(0xffffffffffffff88), 0), /* value=0x77 */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, UINT64_C(0xffffffffffffff80), 0x40), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0x0 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0x0 */
+    MFO(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp), /* value=0x0 */
+    MFO(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp), /* value=0x0 */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffff000000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`80000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffff000000000ff8)), /* value=0x80000006 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`c0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffff000000000ff8)), /* value=0xc0000006 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`f0000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffff000000000ff8)), /* value=0xcdf00000 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`fff00800 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffff000000000ff8)), /* value=0xce000000 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`fe000800 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RFN(0x00000400, 0x0000041b, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0x4d01, 0xfe, UINT64_C(0xffffffffffff8200)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xfffff800`02ed0bc0 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xfffff800`02ed0900 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x4700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0xfffe0000 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xfffff880`02f65000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x7ff`fffde000 */
+    MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0000104, "AMD_15H_TSC_RATE", AmdFam15hTscRate, AmdFam15hTscRate, 0, 0, UINT64_C(0xffffff0000000000)), /* value=0x1`00000000 */
+    MFX(0xc0000105, "AMD_15H_LWP_CFG", AmdFam15hLwpCfg, AmdFam15hLwpCfg, 0, UINT64_C(0xffff000000000001), 0x7ffffff0), /* value=0x0 */
+    MFX(0xc0000106, "AMD_15H_LWP_CBADDR", AmdFam15hLwpCbAddr, AmdFam15hLwpCbAddr, 0, 0, UINT64_MAX), /* value=0x0 */
+    RSN(0xc0000408, 0xc0000409, "AMD_10H_MC4_MISCn", AmdFam10hMc4MiscN, AmdFam10hMc4MiscN, 0, UINT64_C(0xff00f000ffffffff), 0),
+    RVI(0xc000040a, 0xc000040f, "AMD_10H_MC4_MISCn", 0),
+    MAL(0xc0010000, "AMD_K8_PERF_CTL_0", 0xc0010200),
+    MAL(0xc0010001, "AMD_K8_PERF_CTL_1", 0xc0010202),
+    MAL(0xc0010002, "AMD_K8_PERF_CTL_2", 0xc0010204),
+    MAL(0xc0010003, "AMD_K8_PERF_CTL_3", 0xc0010206),
+    MAL(0xc0010004, "AMD_K8_PERF_CTR_0", 0xc0010201),
+    MAL(0xc0010005, "AMD_K8_PERF_CTR_1", 0xc0010203),
+    MAL(0xc0010006, "AMD_K8_PERF_CTR_2", 0xc0010205),
+    MAL(0xc0010007, "AMD_K8_PERF_CTR_3", 0xc0010207),
+    MFX(0xc0010010, "AMD_K8_SYS_CFG", AmdK8SysCfg, AmdK8SysCfg, 0x740000, UINT64_C(0xffffffffff82ffff), 0), /* value=0x740000 */
+    MFX(0xc0010015, "AMD_K8_HW_CFG", AmdK8HwCr, AmdK8HwCr, 0, UINT64_C(0xffffffff01006020), 0), /* value=0x1001031 */
+    MFW(0xc0010016, "AMD_K8_IORR_BASE_0", AmdK8IorrBaseN, AmdK8IorrBaseN, UINT64_C(0xffff000000000fe7)), /* value=0x0 */
+    MFW(0xc0010017, "AMD_K8_IORR_MASK_0", AmdK8IorrMaskN, AmdK8IorrMaskN, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0xc0010018, "AMD_K8_IORR_BASE_1", AmdK8IorrBaseN, AmdK8IorrBaseN, 0x1, UINT64_C(0xffff000000000fe7), 0), /* value=0x0 */
+    MFX(0xc0010019, "AMD_K8_IORR_MASK_1", AmdK8IorrMaskN, AmdK8IorrMaskN, 0x1, UINT64_C(0xffff0000000007ff), 0), /* value=0x0 */
+    MFW(0xc001001a, "AMD_K8_TOP_MEM", AmdK8TopOfMemN, AmdK8TopOfMemN, UINT64_C(0xffff0000007fffff)), /* value=0xd0000000 */
+    MFX(0xc001001d, "AMD_K8_TOP_MEM2", AmdK8TopOfMemN, AmdK8TopOfMemN, 0x1, UINT64_C(0xffff0000007fffff), 0), /* value=0x4`2f000000 */
+    MFN(0xc001001f, "AMD_K8_NB_CFG1", AmdK8NbCfg1, AmdK8NbCfg1), /* value=0x400000`00810008 */
+    MFN(0xc0010020, "AMD_K8_PATCH_LOADER", WriteOnly, AmdK8PatchLoader),
+    MFX(0xc0010022, "AMD_K8_MC_XCPT_REDIR", AmdK8McXcptRedir, AmdK8McXcptRedir, 0, UINT64_C(0xffffffffffff0000), 0), /* value=0x0 */
+    MVO(0xc0010028, "AMD_K8_UNK_c001_0028", 0),
+    MVO(0xc0010029, "AMD_K8_UNK_c001_0029", 0),
+    MVO(0xc001002a, "AMD_K8_UNK_c001_002a", 0),
+    MVO(0xc001002b, "AMD_K8_UNK_c001_002b", 0),
+    MVO(0xc001002c, "AMD_K8_UNK_c001_002c", 0),
+    MVO(0xc001002d, "AMD_K8_UNK_c001_002d", 0),
+    RFN(0xc0010030, 0xc0010035, "AMD_K8_CPU_NAME_n", AmdK8CpuNameN, AmdK8CpuNameN),
+    MFX(0xc001003e, "AMD_K8_HTC", AmdK8HwThermalCtrl, AmdK8HwThermalCtrl, 0x664c0005, UINT64_C(0xffffffff90008838), 0), /* value=0x664c0005 */
+    MFX(0xc001003f, "AMD_K8_STC", AmdK8SwThermalCtrl, AmdK8SwThermalCtrl, 0, UINT64_C(0xffffffff9fffffdf), 0), /* value=0x60000000 */
+    MVO(0xc0010043, "AMD_K8_THERMTRIP_STATUS", 0x20),
+    MFX(0xc0010044, "AMD_K8_MC_CTL_MASK_0", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x0, UINT64_C(0xfffffffffffffc00), 0), /* value=0x0 */
+    MFX(0xc0010045, "AMD_K8_MC_CTL_MASK_1", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x1, UINT64_C(0xffffffffff004d01), 0), /* value=0x48080 */
+    MFX(0xc0010046, "AMD_K8_MC_CTL_MASK_2", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x2, UINT64_C(0xffffffffffff8000), 0), /* value=0x0 */
+    MFX(0xc0010047, "AMD_K8_MC_CTL_MASK_3", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x3, UINT64_MAX, 0), /* value=0x0 */
+    MFX(0xc0010048, "AMD_K8_MC_CTL_MASK_4", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x4, ~(uint64_t)UINT32_MAX, 0), /* value=0x780400 */
+    MFX(0xc0010049, "AMD_K8_MC_CTL_MASK_5", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x5, UINT64_C(0xffffffffffffe000), 0), /* value=0x0 */
+    MFX(0xc001004a, "AMD_K8_MC_CTL_MASK_6", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x6, UINT64_C(0xffffffffffffffc0), 0), /* value=0x0 */
+    RFN(0xc0010050, 0xc0010053, "AMD_K8_SMI_ON_IO_TRAP_n", AmdK8SmiOnIoTrapN, AmdK8SmiOnIoTrapN),
+    MFX(0xc0010054, "AMD_K8_SMI_ON_IO_TRAP_CTL_STS", AmdK8SmiOnIoTrapCtlSts, AmdK8SmiOnIoTrapCtlSts, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010055, "AMD_K8_INT_PENDING_MSG", AmdK8IntPendingMessage, AmdK8IntPendingMessage, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x20000800 */
+    MFX(0xc0010056, "AMD_K8_SMI_TRIGGER_IO_CYCLE", AmdK8SmiTriggerIoCycle, AmdK8SmiTriggerIoCycle, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x2000000 */
+    MFX(0xc0010058, "AMD_10H_MMIO_CFG_BASE_ADDR", AmdFam10hMmioCfgBaseAddr, AmdFam10hMmioCfgBaseAddr, 0, UINT64_C(0xffff0000000fffc0), 0), /* value=0xe0000021 */
+    MFX(0xc0010059, "AMD_10H_TRAP_CTL?", AmdFam10hTrapCtlMaybe, AmdFam10hTrapCtlMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVX(0xc001005a, "AMD_10H_UNK_c001_005a", 0, 0, 0),
+    MVX(0xc001005b, "AMD_10H_UNK_c001_005b", 0, 0, 0),
+    MVX(0xc001005c, "AMD_10H_UNK_c001_005c", 0, 0, 0),
+    MVX(0xc001005d, "AMD_10H_UNK_c001_005d", 0, 0, 0),
+    MVO(0xc0010060, "AMD_K8_BIST_RESULT", 0),
+    MFX(0xc0010061, "AMD_10H_P_ST_CUR_LIM", AmdFam10hPStateCurLimit, ReadOnly, 0x40, 0, 0), /* value=0x40 */
+    MFX(0xc0010062, "AMD_10H_P_ST_CTL", AmdFam10hPStateControl, AmdFam10hPStateControl, 0, 0, UINT64_C(0xfffffffffffffff8)), /* value=0x0 */
+    MFX(0xc0010063, "AMD_10H_P_ST_STS", AmdFam10hPStateStatus, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0xc0010064, "AMD_10H_P_ST_0", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x800001b10000161a), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x800001b1`0000161a */
+    MFX(0xc0010065, "AMD_10H_P_ST_1", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x800001b100001a17), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x800001b1`00001a17 */
+    MFX(0xc0010066, "AMD_10H_P_ST_2", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000017300003014), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x80000173`00003014 */
+    MFX(0xc0010067, "AMD_10H_P_ST_3", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000016300003a11), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x80000163`00003a11 */
+    MFX(0xc0010068, "AMD_10H_P_ST_4", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000014900004c0b), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x80000149`00004c0b */
+    MFX(0xc0010069, "AMD_10H_P_ST_5", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000013100006205), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x80000131`00006205 */
+    MFX(0xc001006a, "AMD_10H_P_ST_6", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x800001200000724c), UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x80000120`0000724c */
+    MFX(0xc001006b, "AMD_10H_P_ST_7", AmdFam10hPStateN, AmdFam10hPStateN, 0, UINT64_C(0x7ffffc00ffbf0000), 0), /* value=0x0 */
+    MFX(0xc0010070, "AMD_10H_COFVID_CTL", AmdFam10hCofVidControl, AmdFam10hCofVidControl, 0x40011a17, UINT64_C(0xffffffff00b80000), 0), /* value=0x40011a17 */
+    MFX(0xc0010071, "AMD_10H_COFVID_STS", AmdFam10hCofVidStatus, AmdFam10hCofVidStatus, UINT64_C(0x18000064006724c), UINT64_MAX, 0), /* value=0x1800006`4006724c */
+    MFX(0xc0010073, "AMD_10H_C_ST_IO_BASE_ADDR", AmdFam10hCStateIoBaseAddr, AmdFam10hCStateIoBaseAddr, 0, UINT64_C(0xffffffffffff0000), 0), /* value=0x814 */
+    MFX(0xc0010074, "AMD_10H_CPU_WD_TMR_CFG", AmdFam10hCpuWatchdogTimer, AmdFam10hCpuWatchdogTimer, 0, UINT64_C(0xffffffffffffff80), 0), /* value=0x0 */
+    MFX(0xc0010111, "AMD_K8_SMM_BASE", AmdK8SmmBase, AmdK8SmmBase, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0xcdef8800 */
+    MFX(0xc0010112, "AMD_K8_SMM_ADDR", AmdK8SmmAddr, AmdK8SmmAddr, 0, UINT64_C(0xffff00000001ffff), 0), /* value=0xcdf00000 */
+    MFX(0xc0010113, "AMD_K8_SMM_MASK", AmdK8SmmMask, AmdK8SmmMask, 0, UINT64_C(0xffff0000000188c0), 0), /* value=0xffff`fff00003 */
+    MFX(0xc0010114, "AMD_K8_VM_CR", AmdK8VmCr, AmdK8VmCr, 0, ~(uint64_t)UINT32_MAX, UINT32_C(0xffffffe0)), /* value=0x8 */
+    MFX(0xc0010115, "AMD_K8_IGNNE", AmdK8IgnNe, AmdK8IgnNe, 0, ~(uint64_t)UINT32_MAX, UINT32_C(0xfffffffe)), /* value=0x0 */
+    MFX(0xc0010117, "AMD_K8_VM_HSAVE_PA", AmdK8VmHSavePa, AmdK8VmHSavePa, 0, 0, UINT64_C(0xffff000000000fff)), /* value=0x0 */
+    MFN(0xc0010118, "AMD_10H_VM_LOCK_KEY", AmdFam10hVmLockKey, AmdFam10hVmLockKey), /* value=0x0 */
+    MFN(0xc0010119, "AMD_10H_SSM_LOCK_KEY", AmdFam10hSmmLockKey, AmdFam10hSmmLockKey), /* value=0x0 */
+    MFX(0xc001011a, "AMD_10H_LOCAL_SMI_STS", AmdFam10hLocalSmiStatus, AmdFam10hLocalSmiStatus, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010140, "AMD_10H_OSVW_ID_LEN", AmdFam10hOsVisWrkIdLength, AmdFam10hOsVisWrkIdLength, 0x4, 0, 0), /* value=0x4 */
+    MFN(0xc0010141, "AMD_10H_OSVW_STS", AmdFam10hOsVisWrkStatus, AmdFam10hOsVisWrkStatus), /* value=0x0 */
+    MFX(0xc0010200, "AMD_K8_PERF_CTL_0", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x0, UINT64_C(0xfffffcf000200000), 0), /* value=0x0 */
+    MFX(0xc0010201, "AMD_K8_PERF_CTR_0", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x0, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010202, "AMD_K8_PERF_CTL_1", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x1, UINT64_C(0xfffffcf000200000), 0), /* value=0x0 */
+    MFX(0xc0010203, "AMD_K8_PERF_CTR_1", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x1, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010204, "AMD_K8_PERF_CTL_2", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x2, UINT64_C(0xfffffcf000200000), 0), /* value=0x0 */
+    MFX(0xc0010205, "AMD_K8_PERF_CTR_2", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x2, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010206, "AMD_K8_PERF_CTL_3", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x3, UINT64_C(0xfffffcf000200000), 0), /* value=0x0 */
+    MFX(0xc0010207, "AMD_K8_PERF_CTR_3", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x3, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010208, "AMD_K8_PERF_CTL_4", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x4, UINT64_C(0xfffffcf000200000), 0), /* value=0x0 */
+    MFX(0xc0010209, "AMD_K8_PERF_CTR_4", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x4, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc001020a, "AMD_K8_PERF_CTL_5", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x5, UINT64_C(0xfffffcf000200000), 0), /* value=0x0 */
+    MFX(0xc001020b, "AMD_K8_PERF_CTR_5", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x5, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010240, "AMD_15H_NB_PERF_CTL_0", AmdFam15hNorthbridgePerfCtlN, AmdFam15hNorthbridgePerfCtlN, 0x0, UINT64_C(0xfffffe00ffa70000), 0), /* value=0x0 */
+    MFX(0xc0010241, "AMD_15H_NB_PERF_CTR_0", AmdFam15hNorthbridgePerfCtrN, AmdFam15hNorthbridgePerfCtrN, 0x0, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010242, "AMD_15H_NB_PERF_CTL_1", AmdFam15hNorthbridgePerfCtlN, AmdFam15hNorthbridgePerfCtlN, 0x1, UINT64_C(0xfffffe00ffa70000), 0), /* value=0x0 */
+    MFX(0xc0010243, "AMD_15H_NB_PERF_CTR_1", AmdFam15hNorthbridgePerfCtrN, AmdFam15hNorthbridgePerfCtrN, 0x1, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010244, "AMD_15H_NB_PERF_CTL_2", AmdFam15hNorthbridgePerfCtlN, AmdFam15hNorthbridgePerfCtlN, 0x2, UINT64_C(0xfffffe00ffa70000), 0), /* value=0x0 */
+    MFX(0xc0010245, "AMD_15H_NB_PERF_CTR_2", AmdFam15hNorthbridgePerfCtrN, AmdFam15hNorthbridgePerfCtrN, 0x2, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0010246, "AMD_15H_NB_PERF_CTL_3", AmdFam15hNorthbridgePerfCtlN, AmdFam15hNorthbridgePerfCtlN, 0x3, UINT64_C(0xfffffe00ffa70000), 0), /* value=0x0 */
+    MFX(0xc0010247, "AMD_15H_NB_PERF_CTR_3", AmdFam15hNorthbridgePerfCtrN, AmdFam15hNorthbridgePerfCtrN, 0x3, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFX(0xc0011000, "AMD_K7_MCODE_CTL", AmdK7MicrocodeCtl, AmdK7MicrocodeCtl, 0x30000, ~(uint64_t)UINT32_MAX, 0x204), /* value=0x30000 */
+    MFX(0xc0011001, "AMD_K7_APIC_CLUSTER_ID", AmdK7ClusterIdMaybe, AmdK7ClusterIdMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0011003, "AMD_K8_CPUID_CTL_STD06", AmdK8CpuIdCtlStd06hEcx, AmdK8CpuIdCtlStd06hEcx, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x1 */
+    MFN(0xc0011004, "AMD_K8_CPUID_CTL_STD01", AmdK8CpuIdCtlStd01hEdcx, AmdK8CpuIdCtlStd01hEdcx), /* value=0x1e98220b`178bfbff */
+    MFN(0xc0011005, "AMD_K8_CPUID_CTL_EXT01", AmdK8CpuIdCtlExt01hEdcx, AmdK8CpuIdCtlExt01hEdcx), /* value=0x1c9ffff`2fd3fbff */
+    MFX(0xc0011006, "AMD_K7_DEBUG_STS?", AmdK7DebugStatusMaybe, AmdK7DebugStatusMaybe, 0, UINT64_C(0xffffffff00000080), 0), /* value=0x10 */
+    MFN(0xc0011007, "AMD_K7_BH_TRACE_BASE?", AmdK7BHTraceBaseMaybe, AmdK7BHTraceBaseMaybe), /* value=0x0 */
+    MFN(0xc0011008, "AMD_K7_BH_TRACE_PTR?", AmdK7BHTracePtrMaybe, AmdK7BHTracePtrMaybe), /* value=0x0 */
+    MFN(0xc0011009, "AMD_K7_BH_TRACE_LIM?", AmdK7BHTraceLimitMaybe, AmdK7BHTraceLimitMaybe), /* value=0x0 */
+    MFX(0xc001100a, "AMD_K7_HDT_CFG?", AmdK7HardwareDebugToolCfgMaybe, AmdK7HardwareDebugToolCfgMaybe, 0, UINT64_C(0xffffffff00800000), 0), /* value=0x0 */
+    MFX(0xc001100b, "AMD_K7_FAST_FLUSH_COUNT?", AmdK7FastFlushCountMaybe, AmdK7FastFlushCountMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x7c0 */
+    MFX(0xc001100c, "AMD_K7_NODE_ID", AmdK7NodeId, AmdK7NodeId, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x80 */
+    MVX(0xc001100e, "AMD_K8_WRMSR_BP?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001100f, "AMD_K8_WRMSR_BP_MASK?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011010, "AMD_K8_BH_TRACE_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011011, "AMD_K8_BH_TRACE_USRD?", 0, 0, 0), /* value=0xfffffcf0`093634f0 */
+    MVI(0xc0011012, "AMD_K7_UNK_c001_1012", UINT32_MAX),
+    MVI(0xc0011013, "AMD_K7_UNK_c001_1013", UINT64_MAX),
+    MVX(0xc0011014, "AMD_K8_XCPT_BP_RIP?", 0, 0, 0),
+    MVX(0xc0011015, "AMD_K8_XCPT_BP_RIP_MASK?", 0, 0, 0),
+    MVX(0xc0011016, "AMD_K8_COND_HDT_VAL?", 0, 0, 0),
+    MVX(0xc0011017, "AMD_K8_COND_HDT_VAL_MASK?", 0, 0, 0),
+    MVX(0xc0011018, "AMD_K8_XCPT_BP_CTL?", 0, 0, 0),
+    MVX(0xc001101d, "AMD_K8_NB_BIST?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0xc001101e, "AMD_K8_THERMTRIP_2?", 0x20), /* Villain? */
+    MVX(0xc001101f, "AMD_K8_NB_CFG?", UINT64_C(0x40000000810008), 0, 0),
+    MFX(0xc0011020, "AMD_K7_LS_CFG", AmdK7LoadStoreCfg, AmdK7LoadStoreCfg, 0, UINT64_C(0x3fffedafbffe2a), 0), /* value=0x0 */
+    MFW(0xc0011021, "AMD_K7_IC_CFG", AmdK7InstrCacheCfg, AmdK7InstrCacheCfg, UINT64_C(0xffffff0000000000)), /* value=0x0 */
+    MFX(0xc0011022, "AMD_K7_DC_CFG", AmdK7DataCacheCfg, AmdK7DataCacheCfg, 0, UINT64_C(0x1ffffbfffff13e0), 0), /* value=0x0 */
+    MFX(0xc0011023, "AMD_15H_CU_CFG", AmdFam15hCombUnitCfg, AmdFam15hCombUnitCfg, 0x220, UINT64_C(0x3ff03c760042000), 0), /* value=0x80004000`00000220 */
+    MFX(0xc0011024, "AMD_K7_DEBUG_CTL_2?", AmdK7DebugCtl2Maybe, AmdK7DebugCtl2Maybe, 0, UINT64_C(0xfffffffffffffe04), 0), /* value=0x0 */
+    MFN(0xc0011025, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMatchMaybe, AmdK7Dr0DataMatchMaybe), /* value=0x0 */
+    MFN(0xc0011026, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMaskMaybe, AmdK7Dr0DataMaskMaybe), /* value=0x0 */
+    MFX(0xc0011027, "AMD_K7_DR0_ADDR_MASK", AmdK7DrXAddrMaskN, AmdK7DrXAddrMaskN, 0x0, UINT64_C(0xfffffffffffff000), 0), /* value=0x0 */
+    MFX(0xc0011028, "AMD_15H_FP_CFG", AmdFam15hFpuCfg, AmdFam15hFpuCfg, 0, UINT64_C(0xffffe000000000ff), 0), /* value=0x40`e91d0000 */
+    MFX(0xc0011029, "AMD_15H_DC_CFG", AmdFam15hDecoderCfg, AmdFam15hDecoderCfg, 0, UINT64_C(0xffffffffc0188001), 0), /* value=0x488400 */
+    MFX(0xc001102a, "AMD_15H_CU_CFG2", AmdFam15hCombUnitCfg2, AmdFam15hCombUnitCfg2, 0, UINT64_C(0xfffbfb8ff2fc623f), 0), /* value=0x40040`00000cc0 */
+    MFX(0xc001102b, "AMD_15H_CU_CFG3", AmdFam15hCombUnitCfg3, AmdFam15hCombUnitCfg3, 0, UINT64_C(0xffe0027afff00000), 0), /* value=0x33400`00002b93 */
+    MFX(0xc001102c, "AMD_15H_EX_CFG", AmdFam15hExecUnitCfg, AmdFam15hExecUnitCfg, 0x7aac0, UINT64_C(0xffb0c003fbe00024), 0), /* value=0x400`0007aac0 */
+    MFX(0xc0011030, "AMD_10H_IBS_FETCH_CTL", AmdFam10hIbsFetchCtl, AmdFam10hIbsFetchCtl, 0, UINT64_C(0xfdfeffffffff0000), 0), /* value=0x0 */
+    MFI(0xc0011031, "AMD_10H_IBS_FETCH_LIN_ADDR", AmdFam10hIbsFetchLinAddr), /* value=0x0 */
+    MFI(0xc0011032, "AMD_10H_IBS_FETCH_PHYS_ADDR", AmdFam10hIbsFetchPhysAddr), /* value=0x0 */
+    MFX(0xc0011033, "AMD_10H_IBS_OP_EXEC_CTL", AmdFam10hIbsOpExecCtl, AmdFam10hIbsOpExecCtl, 0, UINT64_C(0xf8000000f8010000), 0), /* value=0x0 */
+    MFN(0xc0011034, "AMD_10H_IBS_OP_RIP", AmdFam10hIbsOpRip, AmdFam10hIbsOpRip), /* value=0x0 */
+    MFX(0xc0011035, "AMD_10H_IBS_OP_DATA", AmdFam10hIbsOpData, AmdFam10hIbsOpData, 0, UINT64_C(0xffffffc000000000), 0), /* value=0x0 */
+    MFX(0xc0011036, "AMD_10H_IBS_OP_DATA2", AmdFam10hIbsOpData2, AmdFam10hIbsOpData2, 0, UINT64_C(0xffffffffffffffc8), 0), /* value=0x0 */
+    MFX(0xc0011037, "AMD_10H_IBS_OP_DATA3", AmdFam10hIbsOpData3, AmdFam10hIbsOpData3, 0, UINT64_C(0xffff0000fff00400), 0), /* value=0x0 */
+    MFN(0xc0011038, "AMD_10H_IBS_DC_LIN_ADDR", AmdFam10hIbsDcLinAddr, AmdFam10hIbsDcLinAddr), /* value=0x0 */
+    MFX(0xc0011039, "AMD_10H_IBS_DC_PHYS_ADDR", AmdFam10hIbsDcPhysAddr, AmdFam10hIbsDcPhysAddr, 0, UINT64_C(0xffff000000000000), 0), /* value=0x0 */
+    MFO(0xc001103a, "AMD_10H_IBS_CTL", AmdFam10hIbsCtl), /* value=0x100 */
+    MFN(0xc001103b, "AMD_14H_IBS_BR_TARGET", AmdFam14hIbsBrTarget, AmdFam14hIbsBrTarget), /* value=0x0 */
+    MVX(0xc0011040, "AMD_15H_UNK_c001_1040", 0, UINT64_C(0xffe0000000000003), 0),
+    MVX(0xc0011041, "AMD_15H_UNK_c001_1041", UINT64_C(0x99dd57b219), 0xa0c820, 0),
+    MVX(0xc0011042, "AMD_15H_UNK_c001_1042", 0, 0, 0),
+    MVX(0xc0011043, "AMD_15H_UNK_c001_1043", UINT64_C(0x300000438), 0, 0),
+    MVX(0xc0011044, "AMD_15H_UNK_c001_1044", UINT64_C(0x300000438), 0, 0),
+    MVX(0xc0011045, "AMD_15H_UNK_c001_1045", UINT64_C(0x300000420), 0, 0),
+    MVX(0xc0011046, "AMD_15H_UNK_c001_1046", UINT64_C(0x300000420), 0, 0),
+    MVX(0xc0011047, "AMD_15H_UNK_c001_1047", 0, UINT64_C(0xffff000000000000), 0),
+    MVX(0xc0011048, "AMD_15H_UNK_c001_1048", 0xc000001, UINT64_C(0xffff000000000000), 0),
+    MVX(0xc0011049, "AMD_15H_UNK_c001_1049", 0, UINT64_C(0xffff000000000000), 0),
+    MVX(0xc001104a, "AMD_15H_UNK_c001_104a", 0, UINT64_C(0xffff000000000000), 0),
+    MVX(0xc001104b, "AMD_15H_UNK_c001_104b", 0, 0, 0),
+    MVX(0xc001104c, "AMD_15H_UNK_c001_104c", 0, 0, 0),
+    MVX(0xc001104d, "AMD_15H_UNK_c001_104d", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001104e, "AMD_15H_UNK_c001_104e", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc001104f, "AMD_15H_UNK_c001_104f", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011050, "AMD_15H_UNK_c001_1050", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011051, "AMD_15H_UNK_c001_1051", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011052, "AMD_15H_UNK_c001_1052", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011053, "AMD_15H_UNK_c001_1053", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011054, "AMD_15H_UNK_c001_1054", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011055, "AMD_15H_UNK_c001_1055", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011056, "AMD_15H_UNK_c001_1056", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011057, "AMD_15H_UNK_c001_1057", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011058, "AMD_15H_UNK_c001_1058", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc0011059, "AMD_15H_UNK_c001_1059", 0, UINT64_C(0xfffffc0000000000), 0),
+    MVX(0xc001105a, "AMD_15H_UNK_c001_105a", UINT64_C(0x3060c183060c183), UINT64_C(0x8000000000000000), 0),
+    MVX(0xc001105b, "AMD_15H_UNK_c001_105b", UINT64_C(0x318c6318c60c183), UINT64_C(0xe000000000000000), 0),
+    MVX(0xc001105c, "AMD_15H_UNK_c001_105c", 0, UINT64_C(0xff00000000000000), 0),
+    MVX(0xc001105d, "AMD_15H_UNK_c001_105d", 0, UINT64_C(0xff00000000000000), 0),
+    MVX(0xc001105e, "AMD_15H_UNK_c001_105e", 0, UINT64_C(0xfffffffffffffc00), 0),
+    MVX(0xc001105f, "AMD_15H_UNK_c001_105f", 0, UINT64_C(0xffff000000000000), 0),
+    MVX(0xc0011060, "AMD_15H_UNK_c001_1060", 0, UINT64_C(0xffff000000000000), 0),
+    MVX(0xc0011061, "AMD_15H_UNK_c001_1061", 0, 0, 0),
+    MVX(0xc0011062, "AMD_15H_UNK_c001_1062", 0, UINT64_C(0xffffffffffffe000), 0),
+    MVX(0xc0011063, "AMD_15H_UNK_c001_1063", 0, UINT64_C(0xfffffffffffe4000), 0),
+    MVX(0xc0011064, "AMD_15H_UNK_c001_1064", 0x1, UINT64_C(0xfffffffffffff000), 0),
+    MVX(0xc0011065, "AMD_15H_UNK_c001_1065", 0x1, UINT64_C(0xfffffffff0000000), 0),
+    MVX(0xc0011066, "AMD_15H_UNK_c001_1066", 0, 0, 0),
+    MVX(0xc0011067, "AMD_15H_UNK_c001_1067", 0x1, UINT64_C(0xffffffffffffff80), 0),
+    MVX(0xc0011068, "AMD_15H_UNK_c001_1068", 0, 0, 0),
+    MVX(0xc0011069, "AMD_15H_UNK_c001_1069", 0, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0xc001106a, "AMD_15H_UNK_c001_106a", 0x1, 0, 0),
+    MVX(0xc001106b, "AMD_15H_UNK_c001_106b", 0, UINT64_C(0xfffffffffffffff0), 0),
+    MVX(0xc001106c, "AMD_15H_UNK_c001_106c", 0x1, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0xc001106d, "AMD_15H_UNK_c001_106d", 0x1, UINT64_C(0xf000000000000080), 0),
+    MVX(0xc001106e, "AMD_15H_UNK_c001_106e", 0x1, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0xc001106f, "AMD_15H_UNK_c001_106f", 0x1, UINT64_C(0xfffffffffffff800), 0),
+    MVI(0xc0011070, "AMD_15H_UNK_c001_1070", UINT64_C(0x20000000000)),
+    MVX(0xc0011071, "AMD_15H_UNK_c001_1071", 0x400000, UINT64_C(0xffffffff01ffffff), 0),
+    MVI(0xc0011072, "AMD_15H_UNK_c001_1072", UINT64_C(0x101592c00000021)),
+    MVI(0xc0011073, "AMD_15H_UNK_c001_1073", UINT64_C(0xec541c0050000000)),
+    MVX(0xc0011080, "AMD_15H_UNK_c001_1080", 0, 0, 0),
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for AMD FX(tm)-8150 Eight-Core Processor.
+ */
+static CPUMDBENTRY const g_Entry_AMD_FX_8150_Eight_Core = 
+{
+    /*.pszName          = */ "AMD FX-8150 Eight-Core",
+    /*.pszFullName      = */ "AMD FX(tm)-8150 Eight-Core Processor",
+    /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
+    /*.uFamily          = */ 21,
+    /*.uModel           = */ 1,
+    /*.uStepping        = */ 2,
+    /*.enmMicroarch     = */ kCpumMicroarch_AMD_15h_Bulldozer,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 48,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_AMD_FX_8150_Eight_Core),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_FX_8150_Eight_Core)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_DEFAULTS,
+    /*.DefUnknownCpuId  = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_AMD_FX_8150_Eight_Core)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_AMD_FX_8150_Eight_Core),
+};
+
+#endif /* !VBOX_DB_AMD_FX_8150_Eight_Core */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h b/src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h
new file mode 100644
index 0000000..fc9eb23
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h
@@ -0,0 +1,267 @@
+/* $Id: AMD_Phenom_II_X6_1100T.h $ */
+/** @file
+ * CPU database entry "AMD Phenom II X6 1100T".
+ * Generated at 2013-12-17T13:39:08Z by VBoxCpuReport v4.3.53r91360 on linux.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_AMD_Phenom_II_X6_1100T
+#define VBOX_CPUDB_AMD_Phenom_II_X6_1100T
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for AMD Phenom(tm) II X6 1100T Processor.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_AMD_Phenom_II_X6_1100T[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x00000006, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x00100fa0, 0x01060800, 0x00802009, 0x178bfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00000000, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x8000001b, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00100fa0, 0x100000a1, 0x000837ff, 0xefd3fbff, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20444d41, 0x6e656850, 0x74286d6f, 0x4920296d, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x36582049, 0x30313120, 0x50205430, 0x65636f72, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x726f7373, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0xff30ff10, 0xff30ff20, 0x40020140, 0x40020140, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x20800000, 0x42004200, 0x02008140, 0x0030b140, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000003f9, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003030, 0x00000000, 0x00003005, 0x00000000, 0 },
+    { 0x80000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000a, 0x00000000, 0x00000000, 0x00000001, 0x00000040, 0x00000000, 0x0000040f, 0 },
+    { 0x8000000b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000010, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000011, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000013, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000014, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000015, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000016, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000017, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000018, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000019, 0x00000000, 0x00000000, 0xf0300000, 0x60100000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001a, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001b, 0x00000000, 0x00000000, 0x0000001f, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for AMD Phenom(tm) II X6 1100T Processor.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_AMD_Phenom_II_X6_1100T[] = 
+{
+    MAL(0x00000000, "IA32_P5_MC_ADDR", 0x00000402),
+    MAL(0x00000001, "IA32_P5_MC_TYPE", 0x00000401),
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x6db`c482d0b9 */
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0, UINT64_C(0xffff0000000006ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MVO(0x0000008b, "BBL_CR_D3|BIOS_SIGN", 0x10000bf),
+    MFX(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf, 0, UINT64_C(0x8644930520000000), 0), /* value=0xa66664d9`32c329b1 */
+    MFN(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf), /* value=0x25`092f34be */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0x508, 0, 0), /* value=0x508 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x10 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x8174c700 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x106, 0, 0), /* value=0x106 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, UINT64_C(0xfffffffffffffff8), 0), /* value=0x0 */
+    MFX(0x0000017b, "IA32_MCG_CTL", Ia32McgCtl, Ia32McgCtl, 0, UINT64_C(0xffffffffffffffc0), 0), /* value=0x3f */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, UINT64_C(0xffffffffffffff80), 0x40), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0xffffefdf`00890004 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xffffeed0`c7b3ffbc */
+    MFO(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp), /* value=0x0 */
+    MFO(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp), /* value=0x0 */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffff000000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`00000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffff000000000ff8)), /* value=0xbdf00000 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`fff00800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffff000000000ff8)), /* value=0xbe000000 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`fe000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffff000000000ff8)), /* value=0xc0000000 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`c0000800 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RFN(0x00000400, 0x00000417, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0xfe, UINT64_C(0xffffffffffff8200)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xffffffff`8174b4f0 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xffffffff`8174c860 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x3700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0x7f01`3f916740 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xffff8804`3fc00000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0xf2c95840 */
+    MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RSN(0xc0000408, 0xc000040a, "AMD_10H_MC4_MISCn", AmdFam10hMc4MiscN, AmdFam10hMc4MiscN, 0, UINT64_C(0xff00f000ffffffff), 0),
+    RVI(0xc000040b, 0xc000040f, "AMD_10H_MC4_MISCn", 0),
+    RSN(0xc0010000, 0xc0010003, "AMD_K8_PERF_CTL_n", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x0, UINT64_C(0xfffffcf000200000), 0),
+    RSN(0xc0010004, 0xc0010007, "AMD_K8_PERF_CTR_n", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x0, UINT64_C(0xffff000000000000), 0),
+    MFX(0xc0010010, "AMD_K8_SYS_CFG", AmdK8SysCfg, AmdK8SysCfg, 0x760600, UINT64_C(0xffffffffff80f8ff), 0), /* value=0x760600 */
+    MFX(0xc0010015, "AMD_K8_HW_CFG", AmdK8HwCr, AmdK8HwCr, 0x1000031, UINT64_C(0xffffffff00006020), 0), /* value=0x1000031 */
+    MFW(0xc0010016, "AMD_K8_IORR_BASE_0", AmdK8IorrBaseN, AmdK8IorrBaseN, UINT64_C(0xffff000000000fe7)), /* value=0x3`40200000 */
+    MFW(0xc0010017, "AMD_K8_IORR_MASK_0", AmdK8IorrMaskN, AmdK8IorrMaskN, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0xc0010018, "AMD_K8_IORR_BASE_1", AmdK8IorrBaseN, AmdK8IorrBaseN, 0x1, UINT64_C(0xffff000000000fe7), 0), /* value=0x0 */
+    MFX(0xc0010019, "AMD_K8_IORR_MASK_1", AmdK8IorrMaskN, AmdK8IorrMaskN, 0x1, UINT64_C(0xffff0000000007ff), 0), /* value=0x0 */
+    MFW(0xc001001a, "AMD_K8_TOP_MEM", AmdK8TopOfMemN, AmdK8TopOfMemN, UINT64_C(0xffff0000007fffff)), /* value=0xc0000000 */
+    MFX(0xc001001d, "AMD_K8_TOP_MEM2", AmdK8TopOfMemN, AmdK8TopOfMemN, 0x1, UINT64_C(0xffff0000007fffff), 0), /* value=0x4`40000000 */
+    MFN(0xc001001f, "AMD_K8_NB_CFG1", AmdK8NbCfg1, AmdK8NbCfg1), /* value=0x584000`00000008 */
+    MFN(0xc0010020, "AMD_K8_PATCH_LOADER", WriteOnly, AmdK8PatchLoader),
+    MFN(0xc0010021, "AMD_10H_UNK_c001_0021", WriteOnly, IgnoreWrite),
+    MFX(0xc0010022, "AMD_K8_MC_XCPT_REDIR", AmdK8McXcptRedir, AmdK8McXcptRedir, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RFN(0xc0010030, 0xc0010035, "AMD_K8_CPU_NAME_n", AmdK8CpuNameN, AmdK8CpuNameN),
+    MFX(0xc001003e, "AMD_K8_HTC", AmdK8HwThermalCtrl, AmdK8HwThermalCtrl, 0x4a4c0005, UINT64_C(0xffffffffb0008838), 0), /* value=0x4a4c0005 */
+    MFX(0xc001003f, "AMD_K8_STC", AmdK8SwThermalCtrl, AmdK8SwThermalCtrl, 0, UINT64_C(0xffffffffc00088c0), 0), /* value=0x10000000 */
+    MVO(0xc0010043, "AMD_K8_THERMTRIP_STATUS", 0x1dc01430),
+    MFX(0xc0010044, "AMD_K8_MC_CTL_MASK_0", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x0, UINT64_C(0xffffffffffffff00), 0), /* value=0x80 */
+    MFX(0xc0010045, "AMD_K8_MC_CTL_MASK_1", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x1, ~(uint64_t)UINT32_MAX, 0), /* value=0x80 */
+    MFX(0xc0010046, "AMD_K8_MC_CTL_MASK_2", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x2, UINT64_C(0xfffffffffffff000), 0), /* value=0x200 */
+    MFX(0xc0010047, "AMD_K8_MC_CTL_MASK_3", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x3, UINT64_C(0xfffffffffffffffc), 0), /* value=0x0 */
+    MFX(0xc0010048, "AMD_K8_MC_CTL_MASK_4", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x4, UINT64_C(0xffffffffc0000000), 0), /* value=0x780400 */
+    MFX(0xc0010049, "AMD_K8_MC_CTL_MASK_5", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x5, UINT64_C(0xfffffffffffffffe), 0), /* value=0x0 */
+    RFN(0xc0010050, 0xc0010053, "AMD_K8_SMI_ON_IO_TRAP_n", AmdK8SmiOnIoTrapN, AmdK8SmiOnIoTrapN),
+    MFX(0xc0010054, "AMD_K8_SMI_ON_IO_TRAP_CTL_STS", AmdK8SmiOnIoTrapCtlSts, AmdK8SmiOnIoTrapCtlSts, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010055, "AMD_K8_INT_PENDING_MSG", AmdK8IntPendingMessage, AmdK8IntPendingMessage, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x14000815 */
+    MFX(0xc0010056, "AMD_K8_SMI_TRIGGER_IO_CYCLE", AmdK8SmiTriggerIoCycle, AmdK8SmiTriggerIoCycle, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x2000000 */
+    MFX(0xc0010058, "AMD_10H_MMIO_CFG_BASE_ADDR", AmdFam10hMmioCfgBaseAddr, AmdFam10hMmioCfgBaseAddr, 0, UINT64_C(0xffff0000000fffc0), 0), /* value=0xe0000021 */
+    MFX(0xc0010059, "AMD_10H_TRAP_CTL?", AmdFam10hTrapCtlMaybe, AmdFam10hTrapCtlMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVX(0xc001005a, "AMD_10H_UNK_c001_005a", 0, 0, 0),
+    MVX(0xc001005b, "AMD_10H_UNK_c001_005b", 0, 0, 0),
+    MVX(0xc001005c, "AMD_10H_UNK_c001_005c", 0, 0, 0),
+    MVX(0xc001005d, "AMD_10H_UNK_c001_005d", 0, 0, 0),
+    MVO(0xc0010060, "AMD_K8_BIST_RESULT", 0),
+    MFX(0xc0010061, "AMD_10H_P_ST_CUR_LIM", AmdFam10hPStateCurLimit, ReadOnly, 0x30, 0, 0), /* value=0x30 */
+    MFX(0xc0010062, "AMD_10H_P_ST_CTL", AmdFam10hPStateControl, AmdFam10hPStateControl, 0x3, 0, UINT64_C(0xfffffffffffffff8)), /* value=0x3 */
+    MFX(0xc0010063, "AMD_10H_P_ST_STS", AmdFam10hPStateStatus, ReadOnly, 0x3, 0, 0), /* value=0x3 */
+    MFX(0xc0010064, "AMD_10H_P_ST_0", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000019e40001015), 0, 0), /* value=0x8000019e`40001015 */
+    MFX(0xc0010065, "AMD_10H_P_ST_1", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000019f40002411), 0, 0), /* value=0x8000019f`40002411 */
+    MFX(0xc0010066, "AMD_10H_P_ST_2", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000017540002809), 0, 0), /* value=0x80000175`40002809 */
+    MFX(0xc0010067, "AMD_10H_P_ST_3", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000015540002c01), 0, 0), /* value=0x80000155`40002c01 */
+    MFX(0xc0010068, "AMD_10H_P_ST_4", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000013340003840), 0, 0), /* value=0x80000133`40003840 */
+    MFX(0xc0010070, "AMD_10H_COFVID_CTL", AmdFam10hCofVidControl, AmdFam10hCofVidControl, 0x40043840, UINT64_C(0xffffffff01b80000), 0), /* value=0x40043840 */
+    MFX(0xc0010071, "AMD_10H_COFVID_STS", AmdFam10hCofVidStatus, AmdFam10hCofVidStatus, UINT64_C(0x140043840), UINT64_MAX, 0), /* value=0x1`40043840 */
+    MFO(0xc0010073, "AMD_10H_C_ST_IO_BASE_ADDR", AmdFam10hCStateIoBaseAddr), /* value=0x814 */
+    MFX(0xc0010074, "AMD_10H_CPU_WD_TMR_CFG", AmdFam10hCpuWatchdogTimer, AmdFam10hCpuWatchdogTimer, 0, UINT64_C(0xffffffffffffff80), 0), /* value=0x0 */
+    MFX(0xc0010111, "AMD_K8_SMM_BASE", AmdK8SmmBase, AmdK8SmmBase, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0xbdef8000 */
+    MFX(0xc0010112, "AMD_K8_SMM_ADDR", AmdK8SmmAddr, AmdK8SmmAddr, 0, UINT64_C(0xffff00000001ffff), 0), /* value=0xbdf00000 */
+    MFX(0xc0010113, "AMD_K8_SMM_MASK", AmdK8SmmMask, AmdK8SmmMask, 0, UINT64_C(0xffff0000000188c0), 0), /* value=0xffff`fff00003 */
+    MFX(0xc0010114, "AMD_K8_VM_CR", AmdK8VmCr, AmdK8VmCr, 0, ~(uint64_t)UINT32_MAX, UINT32_C(0xffffffe0)), /* value=0x8 */
+    MFX(0xc0010115, "AMD_K8_IGNNE", AmdK8IgnNe, AmdK8IgnNe, 0, ~(uint64_t)UINT32_MAX, UINT32_C(0xfffffffe)), /* value=0x0 */
+    MFX(0xc0010117, "AMD_K8_VM_HSAVE_PA", AmdK8VmHSavePa, AmdK8VmHSavePa, 0, 0, UINT64_C(0xffff000000000fff)), /* value=0x0 */
+    MFN(0xc0010118, "AMD_10H_VM_LOCK_KEY", AmdFam10hVmLockKey, AmdFam10hVmLockKey), /* value=0x0 */
+    MFN(0xc0010119, "AMD_10H_SSM_LOCK_KEY", AmdFam10hSmmLockKey, AmdFam10hSmmLockKey), /* value=0x0 */
+    MFX(0xc001011a, "AMD_10H_LOCAL_SMI_STS", AmdFam10hLocalSmiStatus, AmdFam10hLocalSmiStatus, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010140, "AMD_10H_OSVW_ID_LEN", AmdFam10hOsVisWrkIdLength, AmdFam10hOsVisWrkIdLength, 0x4, 0, 0), /* value=0x4 */
+    MFX(0xc0010141, "AMD_10H_OSVW_STS", AmdFam10hOsVisWrkStatus, AmdFam10hOsVisWrkStatus, 0xe, 0, 0), /* value=0xe */
+    MFX(0xc0011000, "AMD_K7_MCODE_CTL", AmdK7MicrocodeCtl, AmdK7MicrocodeCtl, 0, ~(uint64_t)UINT32_MAX, 0x4), /* value=0x0 */
+    MFX(0xc0011001, "AMD_K7_APIC_CLUSTER_ID", AmdK7ClusterIdMaybe, AmdK7ClusterIdMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFN(0xc0011004, "AMD_K8_CPUID_CTL_STD01", AmdK8CpuIdCtlStd01hEdcx, AmdK8CpuIdCtlStd01hEdcx), /* value=0x802009`178bfbff */
+    MFN(0xc0011005, "AMD_K8_CPUID_CTL_EXT01", AmdK8CpuIdCtlExt01hEdcx, AmdK8CpuIdCtlExt01hEdcx), /* value=0x837ff`efd3fbff */
+    MFX(0xc0011006, "AMD_K7_DEBUG_STS?", AmdK7DebugStatusMaybe, AmdK7DebugStatusMaybe, 0, UINT64_C(0xffffffff00000080), 0), /* value=0x10 */
+    MFN(0xc0011007, "AMD_K7_BH_TRACE_BASE?", AmdK7BHTraceBaseMaybe, AmdK7BHTraceBaseMaybe), /* value=0x0 */
+    MFN(0xc0011008, "AMD_K7_BH_TRACE_PTR?", AmdK7BHTracePtrMaybe, AmdK7BHTracePtrMaybe), /* value=0x0 */
+    MFN(0xc0011009, "AMD_K7_BH_TRACE_LIM?", AmdK7BHTraceLimitMaybe, AmdK7BHTraceLimitMaybe), /* value=0x0 */
+    MFX(0xc001100a, "AMD_K7_HDT_CFG?", AmdK7HardwareDebugToolCfgMaybe, AmdK7HardwareDebugToolCfgMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc001100b, "AMD_K7_FAST_FLUSH_COUNT?", AmdK7FastFlushCountMaybe, AmdK7FastFlushCountMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x7c0 */
+    MFX(0xc001100c, "AMD_K7_NODE_ID", AmdK7NodeId, AmdK7NodeId, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVX(0xc001100d, "AMD_K8_LOGICAL_CPUS_NUM?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001100e, "AMD_K8_WRMSR_BP?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001100f, "AMD_K8_WRMSR_BP_MASK?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011010, "AMD_K8_BH_TRACE_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011011, "AMD_K8_BH_TRACE_USRD?", 0, 0, 0), /* value=0x259a5de0`ffffffff */
+    MVX(0xc0011014, "AMD_K8_XCPT_BP_RIP?", 0, 0, 0),
+    MVX(0xc0011015, "AMD_K8_XCPT_BP_RIP_MASK?", 0, 0, 0),
+    MVX(0xc0011016, "AMD_K8_COND_HDT_VAL?", 0, 0, 0),
+    MVX(0xc0011017, "AMD_K8_COND_HDT_VAL_MASK?", 0, 0, 0),
+    MVX(0xc0011018, "AMD_K8_XCPT_BP_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001101d, "AMD_K8_NB_BIST?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0xc001101e, "AMD_K8_THERMTRIP_2?", 0x1dc01430), /* Villain? */
+    MVX(0xc001101f, "AMD_K8_NB_CFG?", UINT64_C(0x58400000000008), 0, 0),
+    MFX(0xc0011020, "AMD_K7_LS_CFG", AmdK7LoadStoreCfg, AmdK7LoadStoreCfg, 0, UINT64_C(0xfffc012000000000), 0), /* value=0x20010`00001000 */
+    MFW(0xc0011021, "AMD_K7_IC_CFG", AmdK7InstrCacheCfg, AmdK7InstrCacheCfg, ~(uint64_t)UINT32_MAX), /* value=0x0 */
+    MFX(0xc0011022, "AMD_K7_DC_CFG", AmdK7DataCacheCfg, AmdK7DataCacheCfg, 0, UINT64_C(0xffc0000000000000), 0), /* value=0x9c`49000000 */
+    MFN(0xc0011023, "AMD_K7_BU_CFG", AmdK7BusUnitCfg, AmdK7BusUnitCfg), /* Villain? value=0x10200020 */
+    MFX(0xc0011024, "AMD_K7_DEBUG_CTL_2?", AmdK7DebugCtl2Maybe, AmdK7DebugCtl2Maybe, 0, UINT64_C(0xffffffffffffff00), 0), /* value=0x0 */
+    MFN(0xc0011025, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMatchMaybe, AmdK7Dr0DataMatchMaybe), /* value=0x0 */
+    MFN(0xc0011026, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMaskMaybe, AmdK7Dr0DataMaskMaybe), /* value=0x0 */
+    MFX(0xc0011027, "AMD_K7_DR0_ADDR_MASK", AmdK7DrXAddrMaskN, AmdK7DrXAddrMaskN, 0x0, UINT64_C(0xfffffffffffff000), 0), /* value=0x0 */
+    MVX(0xc0011028, "AMD_10H_UNK_c001_1028", 0, UINT64_C(0xfffffffffffffff8), 0),
+    MVX(0xc0011029, "AMD_10H_UNK_c001_1029", 0, ~(uint64_t)UINT32_MAX, 0),
+    MFX(0xc001102a, "AMD_10H_BU_CFG2", AmdFam10hBusUnitCfg2, AmdFam10hBusUnitCfg2, 0, UINT64_C(0xfff00000c0000000), 0), /* value=0x40050`01000040 */
+    MFX(0xc0011030, "AMD_10H_IBS_FETCH_CTL", AmdFam10hIbsFetchCtl, AmdFam10hIbsFetchCtl, 0, UINT64_C(0xfdfcffff00000000), 0), /* value=0x140003`00000000 */
+    MFI(0xc0011031, "AMD_10H_IBS_FETCH_LIN_ADDR", AmdFam10hIbsFetchLinAddr), /* value=0xffffffff`a08cf13e */
+    MFI(0xc0011032, "AMD_10H_IBS_FETCH_PHYS_ADDR", AmdFam10hIbsFetchPhysAddr), /* value=0x4`24ce313e */
+    MFX(0xc0011033, "AMD_10H_IBS_OP_EXEC_CTL", AmdFam10hIbsOpExecCtl, AmdFam10hIbsOpExecCtl, 0, UINT64_C(0xfffffffffff00000), 0), /* value=0x0 */
+    MFN(0xc0011034, "AMD_10H_IBS_OP_RIP", AmdFam10hIbsOpRip, AmdFam10hIbsOpRip), /* value=0x4d231923 */
+    MFI(0xc0011035, "AMD_10H_IBS_OP_DATA", AmdFam10hIbsOpData), /* value=0x12`7fc7bc0e */
+    MFX(0xc0011036, "AMD_10H_IBS_OP_DATA2", AmdFam10hIbsOpData2, AmdFam10hIbsOpData2, 0, UINT64_C(0xffffffffffffffc8), 0), /* value=0x0 */
+    MFI(0xc0011037, "AMD_10H_IBS_OP_DATA3", AmdFam10hIbsOpData3), /* value=0x0 */
+    MFX(0xc0011038, "AMD_10H_IBS_DC_LIN_ADDR", AmdFam10hIbsDcLinAddr, AmdFam10hIbsDcLinAddr, 0, UINT64_C(0x7fffffffffff), 0), /* value=0x0 */
+    MFI(0xc0011039, "AMD_10H_IBS_DC_PHYS_ADDR", AmdFam10hIbsDcPhysAddr), /* value=0x0 */
+    MFO(0xc001103a, "AMD_10H_IBS_CTL", AmdFam10hIbsCtl), /* value=0x101 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for AMD Phenom(tm) II X6 1100T Processor.
+ */
+static CPUMDBENTRY const g_Entry_AMD_Phenom_II_X6_1100T = 
+{
+    /*.pszName          = */ "AMD Phenom II X6 1100T",
+    /*.pszFullName      = */ "AMD Phenom(tm) II X6 1100T Processor",
+    /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
+    /*.uFamily          = */ 16,
+    /*.uModel           = */ 10,
+    /*.uStepping        = */ 0,
+    /*.enmMicroarch     = */ kCpumMicroarch_AMD_K10,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 48,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_AMD_Phenom_II_X6_1100T),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_Phenom_II_X6_1100T)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_DEFAULTS,
+    /*.DefUnknownCpuId  = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_AMD_Phenom_II_X6_1100T)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_AMD_Phenom_II_X6_1100T),
+};
+
+#endif /* !VBOX_DB_AMD_Phenom_II_X6_1100T */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h b/src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h
new file mode 100644
index 0000000..30d2c84
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h
@@ -0,0 +1,334 @@
+/* $Id: Intel_Core_i5_3570.h $ */
+/** @file
+ * CPU database entry "Intel Core i5-3570".
+ * Generated at 2013-12-13T16:13:56Z by VBoxCpuReport v4.3.53r91216 on linux.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Intel_Core_i5_3570
+#define VBOX_CPUDB_Intel_Core_i5_3570
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Intel_Core_i5_3570[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x000306a9, 0x04100800, 0x7fbae3ff, 0xbfebfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x1c004121, 0x01c0003f, 0x0000003f, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00001120, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000077, 0x00000002, 0x00000009, 0x00000000, 0 },
+    { 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000281, 0x00000000, 0x00000000, 0 },
+    { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000a, 0x00000000, 0x00000000, 0x07300803, 0x00000000, 0x00000000, 0x00000603, 0 },
+    { 0x0000000b, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000100, 0x00000004, 0 },
+    { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000d, 0x00000000, 0x00000000, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x28100800, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20202020, 0x20202020, 0x65746e49, 0x2952286c, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x726f4320, 0x4d542865, 0x35692029, 0x3735332d, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x50432030, 0x20402055, 0x30342e33, 0x007a4847, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01006040, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003024, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Intel_Core_i5_3570[] = 
+{
+    MFX(0x00000000, "IA32_P5_MC_ADDR", Ia32P5McAddr, Ia32P5McAddr, 0, UINT64_C(0xffffffffffffffe0), 0), /* value=0x1f */
+    MFX(0x00000001, "IA32_P5_MC_TYPE", Ia32P5McType, Ia32P5McType, 0, 0, UINT64_MAX), /* value=0x0 */
+    MFX(0x00000006, "IA32_MONITOR_FILTER_LINE_SIZE", Ia32MonitorFilterLineSize, Ia32MonitorFilterLineSize, 0, 0, UINT64_C(0xffffffffffff0000)), /* value=0x40 */
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x4293`b0a3f54a */
+    MVO(0x00000017, "IA32_PLATFORM_ID", UINT64_C(0x4000000000000)),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00c00), 0, UINT64_C(0xfffffff0000002ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MVX(0x0000002e, "I7_UNK_0000_002e", 0, 0x400, UINT64_C(0xfffffffffffffbff)),
+    MVX(0x00000033, "TEST_CTL", 0, 0, UINT64_C(0xffffffff7fffffff)),
+    MVO(0x00000034, "P6_UNK_0000_0034", 0x285),
+    MVO(0x00000035, "P6_UNK_0000_0035", 0x40004),
+    MVO(0x00000036, "I7_UNK_0000_0036", UINT64_C(0x1000000000105df2)),
+    MFO(0x0000003a, "IA32_FEATURE_CONTROL", Ia32FeatureControl), /* value=0x5 */
+    MVX(0x0000003e, "I7_UNK_0000_003e", 0x1, 0, UINT64_C(0xfffffffffffffffe)),
+    MFN(0x00000079, "IA32_BIOS_UPDT_TRIG", WriteOnly, IgnoreWrite),
+    MVX(0x0000008b, "BBL_CR_D3|BIOS_SIGN", UINT64_C(0x1900000000), 0x1, UINT32_C(0xfffffffe)),
+    MFO(0x0000009b, "IA32_SMM_MONITOR_CTL", Ia32SmmMonitorCtl), /* value=0x0 */
+    RSN(0x000000c1, 0x000000c8, "IA32_PMCn", Ia32PmcN, Ia32PmcN, 0x0, ~(uint64_t)UINT32_MAX, 0),
+    MFO(0x000000ce, "MSR_PLATFORM_INFO", IntelPlatformInfo100MHz), /* value=0x81010'e0012200*/
+    MFX(0x000000e2, "MSR_PKG_CST_CONFIG_CONTROL", IntelPkgCStConfigControl, IntelPkgCStConfigControl, 0, 0, UINT64_C(0xffffffffe1ffffff)), /* value=0x1e008403 */
+    MFX(0x000000e4, "MSR_PMG_IO_CAPTURE_BASE", IntelPmgIoCaptureBase, IntelPmgIoCaptureBase, 0, 0, UINT64_C(0xfffffffffff80000)), /* value=0x10414 */
+    MFN(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf), /* value=0x3a`2c710584 */
+    MFN(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf), /* value=0x39`f97c8410 */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0xd0a, 0, 0), /* value=0xd0a */
+    MVX(0x00000102, "I7_IB_UNK_0000_0102", 0, 0, UINT64_C(0xffffffff7fff8000)),
+    MVX(0x00000103, "I7_IB_UNK_0000_0103", 0, 0, UINT64_C(0xffffffffffffff00)),
+    MVX(0x00000104, "I7_IB_UNK_0000_0104", 0, 0, UINT64_C(0xfffffffffffffffe)),
+    MFN(0x00000132, "CPUID1_FEATURE_MASK", IntelCpuId1FeatureMaskEax, IntelCpuId1FeatureMaskEax), /* value=0xffffffff`ffffffff */
+    MFN(0x00000133, "CPUIDD_01_FEATURE_MASK", IntelCpuId1FeatureMaskEcdx, IntelCpuId1FeatureMaskEcdx), /* value=0xffffffff`ffffffff */
+    MFN(0x00000134, "CPUID80000001_FEATURE_MASK", IntelCpuId80000001FeatureMaskEcdx, IntelCpuId80000001FeatureMaskEcdx), /* value=0xffffffff`ffffffff */
+    MFX(0x0000013c, "I7_SB_AES_NI_CTL", IntelI7SandyAesNiCtl, IntelI7SandyAesNiCtl, 0, 0, UINT64_C(0xfffffffffffffffc)), /* value=0x0 */
+    MVX(0x00000140, "I7_IB_UNK_0000_0140", 0, 0, UINT64_C(0xfffffffffffffffe)),
+    MVX(0x00000142, "I7_IB_UNK_0000_0142", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x10 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffffff`8159cbe0 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0xc09, 0, 0), /* value=0xc09 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, 0, UINT64_C(0xfffffffffffffff8)), /* value=0x0 */
+    RSN(0x00000186, 0x0000018d, "IA32_PERFEVTSELn", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0x0, 0, UINT64_C(0xffffffff00080000)),
+    MFX(0x00000194, "CLOCK_FLEX_MAX", IntelFlexRatio100MHz, IntelFlexRatio100MHz, 0x190000, 0x1e00ff, UINT64_C(0xffffffffffe00000)),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, ReadOnly, UINT64_C(0x1d2400001000), 0, 0), /* value=0x1d24`00001000 */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0x1000, 0, 0), /* Might bite. value=0x1000 */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0, 0, UINT64_C(0xffffffffffffffe0)), /* value=0x0 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0x1000013, 0, UINT64_C(0xfffffffffe0000e8)), /* value=0x1000013 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, UINT32_C(0x884c0000), UINT32_C(0xf87f0fff), UINT64_C(0xffffffff0780f000)), /* value=0x884c0000 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, 0x850089, 0x1080, UINT64_C(0xffffffbbff3aef72)), /* value=0x850089 */
+    MFX(0x000001a2, "I7_MSR_TEMPERATURE_TARGET", IntelI7TemperatureTarget, IntelI7TemperatureTarget, 0x691400, 0xffff00, UINT64_C(0xfffffffff00000ff)), /* value=0x691400 */
+    MVX(0x000001a4, "I7_UNK_0000_01a4", 0, 0, UINT64_C(0xfffffffffffff7f0)),
+    RSN(0x000001a6, 0x000001a7, "I7_MSR_OFFCORE_RSP_n", IntelI7MsrOffCoreResponseN, IntelI7MsrOffCoreResponseN, 0x0, 0, UINT64_C(0xffffffc000007000)),
+    MVX(0x000001a8, "I7_UNK_0000_01a8", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFX(0x000001aa, "MSR_MISC_PWR_MGMT", IntelI7MiscPwrMgmt, IntelI7MiscPwrMgmt, 0, 0, UINT64_C(0xffffffffffbffffe)), /* value=0x400000 */
+    MFX(0x000001ad, "I7_MSR_TURBO_RATIO_LIMIT", IntelI7TurboRatioLimit, ReadOnly, 0x24252626, 0, 0), /* value=0x24252626 */
+    MVX(0x000001b0, "IA32_ENERGY_PERF_BIAS", 0x6, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x000001b1, "IA32_PACKAGE_THERM_STATUS", UINT32_C(0x88490000), UINT32_C(0xf87f0fff), UINT64_C(0xffffffff0780f000)),
+    MVX(0x000001b2, "IA32_PACKAGE_THERM_INTERRUPT", 0x1000003, 0, UINT64_C(0xfffffffffe0000e8)),
+    MVO(0x000001c6, "I7_UNK_0000_01c6", 0x3),
+    MFX(0x000001c8, "MSR_LBR_SELECT", IntelI7LbrSelect, IntelI7LbrSelect, 0, 0, UINT64_C(0xfffffffffffffe00)), /* value=0x0 */
+    MFX(0x000001c9, "MSR_LASTBRANCH_TOS", IntelLastBranchTos, IntelLastBranchTos, 0, 0, UINT64_C(0xfffffffffffffff0)), /* value=0x8 */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, 0, UINT64_C(0xffffffffffff803c)), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0x7fffffff`a061f4c9 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xffffffff`810473c0 */
+    MFX(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp, P6LastIntFromIp, 0, 0, UINT64_C(0x7fff800000000000)), /* value=0x0 */
+    MFX(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp, P6LastIntToIp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFO(0x000001f0, "I7_VLW_CAPABILITY", IntelI7VirtualLegacyWireCap), /* value=0x74 */
+    MFO(0x000001f2, "IA32_SMRR_PHYSBASE", Ia32SmrrPhysBase), /* value=0xdb000006 */
+    MFO(0x000001f3, "IA32_SMRR_PHYSMASK", Ia32SmrrPhysMask), /* value=0xff800800 */
+    MFX(0x000001fc, "I7_MSR_POWER_CTL", IntelI7PowerCtl, IntelI7PowerCtl, 0, 0x20, UINT64_C(0xffffffffffc20000)), /* value=0x14005f */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xc`00000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x4`00000006 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`e0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xfffffff000000ff8)), /* value=0xe0000000 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`e0000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xfffffff000000ff8)), /* value=0xdc000000 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`fc000800 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xfffffff000000ff8)), /* value=0xdb800000 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`ff800800 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x4`1f000000 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`ff000800 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x4`1e800000 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`ff800800 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x4`1e600000 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`ffe00800 */
+    MFX(0x00000210, "IA32_MTRR_PHYS_BASE8", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x8, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000211, "IA32_MTRR_PHYS_MASK8", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x8, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x00000212, "IA32_MTRR_PHYS_BASE9", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x9, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000213, "IA32_MTRR_PHYS_MASK9", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x9, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    RSN(0x00000280, 0x00000281, "IA32_MC0_CTLn", Ia32McNCtl2, Ia32McNCtl2, 0x0, 0, UINT64_C(0xffffffffbfff8000)),
+    MFX(0x00000282, "IA32_MC2_CTL2", Ia32McNCtl2, Ia32McNCtl2, 0x2, 0x40007fff, UINT64_C(0xffffffffbfff8000)), /* value=0x0 */
+    MFX(0x00000283, "IA32_MC3_CTL2", Ia32McNCtl2, Ia32McNCtl2, 0x3, 0, UINT64_C(0xffffffffbfff8000)), /* value=0x40000001 */
+    MFX(0x00000284, "IA32_MC4_CTL2", Ia32McNCtl2, Ia32McNCtl2, 0x4, 0x40007fff, UINT64_C(0xffffffffbfff8000)), /* value=0x0 */
+    RSN(0x00000285, 0x00000288, "IA32_MC5_CTLn", Ia32McNCtl2, Ia32McNCtl2, 0x5, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x000002e0, "I7_SB_NO_EVICT_MODE", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFN(0x000002e6, "I7_IB_UNK_0000_02e6", WriteOnly, IgnoreWrite),
+    MVX(0x000002e7, "I7_IB_UNK_0000_02e7", 0x1, 0x1, UINT64_C(0xfffffffffffffffe)),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    MVO(0x00000305, "I7_SB_UNK_0000_0305", 0),
+    MFX(0x00000309, "IA32_FIXED_CTR0", Ia32FixedCtrN, Ia32FixedCtrN, 0x0, 0, UINT64_C(0xffff000000000000)), /* value=0x46 */
+    MFX(0x0000030a, "IA32_FIXED_CTR1", Ia32FixedCtrN, Ia32FixedCtrN, 0x1, 0x816506, UINT64_C(0xffff000000000000)), /* value=0xffff`d65aa6fb */
+    MFX(0x0000030b, "IA32_FIXED_CTR2", Ia32FixedCtrN, Ia32FixedCtrN, 0x2, 0, UINT64_C(0xffff000000000000)), /* value=0x264 */
+    MFX(0x00000345, "IA32_PERF_CAPABILITIES", Ia32PerfCapabilities, ReadOnly, 0x31c3, 0, 0), /* value=0x31c3 */
+    MFX(0x0000038d, "IA32_FIXED_CTR_CTRL", Ia32FixedCtrCtrl, Ia32FixedCtrCtrl, 0, 0, UINT64_C(0xfffffffffffff000)), /* value=0xb0 */
+    MFX(0x0000038e, "IA32_PERF_GLOBAL_STATUS", Ia32PerfGlobalStatus, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x0000038f, "IA32_PERF_GLOBAL_CTRL", Ia32PerfGlobalCtrl, Ia32PerfGlobalCtrl, 0, 0, UINT64_C(0xfffffff8ffffff00)), /* value=0x7`000000ff */
+    MFX(0x00000390, "IA32_PERF_GLOBAL_OVF_CTRL", Ia32PerfGlobalOvfCtrl, Ia32PerfGlobalOvfCtrl, 0, UINT64_C(0xe0000007000000ff), UINT64_C(0x1ffffff8ffffff00)), /* value=0x0 */
+    MFX(0x00000391, "I7_UNC_PERF_GLOBAL_CTRL", IntelI7UncPerfGlobalCtrl, IntelI7UncPerfGlobalCtrl, 0, 0, UINT64_C(0xffffffff1fffffe0)), /* value=0x2000000f */
+    MFX(0x00000392, "I7_UNC_PERF_GLOBAL_STATUS", IntelI7UncPerfGlobalStatus, IntelI7UncPerfGlobalStatus, 0, 0xf, UINT64_C(0xfffffffffffffff0)), /* value=0x0 */
+    MFX(0x00000393, "I7_UNC_PERF_GLOBAL_OVF_CTRL", IntelI7UncPerfGlobalOvfCtrl, IntelI7UncPerfGlobalOvfCtrl, 0, 0x3, UINT64_C(0xfffffffffffffffc)), /* value=0x0 */
+    MFX(0x00000394, "I7_UNC_PERF_FIXED_CTR_CTRL", IntelI7UncPerfFixedCtrCtrl, IntelI7UncPerfFixedCtrCtrl, 0, 0, UINT64_C(0xffffffffffafffff)), /* value=0x0 */
+    MFX(0x00000395, "I7_UNC_PERF_FIXED_CTR", IntelI7UncPerfFixedCtr, IntelI7UncPerfFixedCtr, 0, 0, UINT64_C(0xffff000000000000)), /* value=0x1950 */
+    MFO(0x00000396, "I7_UNC_CBO_CONFIG", IntelI7UncCBoxConfig), /* value=0x5 */
+    MVX(0x00000397, "I7_IB_UNK_0000_0397", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MFX(0x000003b0, "I7_UNC_ARB_PERF_CTR0", IntelI7UncArbPerfCtrN, IntelI7UncArbPerfCtrN, 0, 0, UINT64_C(0xfffff00000000000)), /* value=0x0 */
+    MFX(0x000003b1, "I7_UNC_ARB_PERF_CTR1", IntelI7UncArbPerfCtrN, IntelI7UncArbPerfCtrN, 0, 0, UINT64_C(0xfffff00000000000)), /* value=0x0 */
+    MFX(0x000003b2, "I7_UNC_ARB_PERF_EVT_SEL0", IntelI7UncArbPerfEvtSelN, IntelI7UncArbPerfEvtSelN, 0, 0, UINT64_C(0xffffffffc0230000)), /* value=0x0 */
+    MFX(0x000003b3, "I7_UNC_ARB_PERF_EVT_SEL1", IntelI7UncArbPerfEvtSelN, IntelI7UncArbPerfEvtSelN, 0, 0, UINT64_C(0xffffffffc0230000)), /* value=0x0 */
+    MFX(0x000003f1, "IA32_PEBS_ENABLE", Ia32PebsEnable, Ia32PebsEnable, 0, 0, UINT64_C(0x7ffffff0fffffff0)), /* value=0x0 */
+    MFX(0x000003f6, "I7_MSR_PEBS_LD_LAT", IntelI7PebsLdLat, IntelI7PebsLdLat, 0, UINT64_C(0xffffffffffff0000), 0), /* value=0xffff */
+    MFX(0x000003f8, "I7_MSR_PKG_C3_RESIDENCY", IntelI7PkgCnResidencyN, ReadOnly, 0x3, 0, UINT64_MAX), /* value=0x7`7827f19a */
+    RSN(0x000003f9, 0x000003fa, "I7_MSR_PKG_Cn_RESIDENCY", IntelI7PkgCnResidencyN, ReadOnly, 0x6, 0, UINT64_MAX),
+    MFX(0x000003fc, "I7_MSR_CORE_C3_RESIDENCY", IntelI7CoreCnResidencyN, ReadOnly, 0x3, 0, UINT64_MAX), /* value=0x1`3e604592 */
+    RSN(0x000003fd, 0x000003fe, "I7_MSR_CORE_Cn_RESIDENCY", IntelI7CoreCnResidencyN, ReadOnly, 0x6, 0, UINT64_MAX),
+    RFN(0x00000400, 0x00000423, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0x00000480, "IA32_VMX_BASIC", Ia32VmxBase, ReadOnly, UINT64_C(0xda040000000010), 0, 0), /* value=0xda0400`00000010 */
+    MFX(0x00000481, "IA32_VMX_PINBASED_CTLS", Ia32VmxPinbasedCtls, ReadOnly, UINT64_C(0x7f00000016), 0, 0), /* value=0x7f`00000016 */
+    MFX(0x00000482, "IA32_VMX_PROCBASED_CTLS", Ia32VmxProcbasedCtls, ReadOnly, UINT64_C(0xfff9fffe0401e172), 0, 0), /* value=0xfff9fffe`0401e172 */
+    MFX(0x00000483, "IA32_VMX_EXIT_CTLS", Ia32VmxExitCtls, ReadOnly, UINT64_C(0x7fffff00036dff), 0, 0), /* value=0x7fffff`00036dff */
+    MFX(0x00000484, "IA32_VMX_ENTRY_CTLS", Ia32VmxEntryCtls, ReadOnly, UINT64_C(0xffff000011ff), 0, 0), /* value=0xffff`000011ff */
+    MFX(0x00000485, "IA32_VMX_MISC", Ia32VmxMisc, ReadOnly, 0x100401e5, 0, 0), /* value=0x100401e5 */
+    MFX(0x00000486, "IA32_VMX_CR0_FIXED0", Ia32VmxCr0Fixed0, ReadOnly, UINT32_C(0x80000021), 0, 0), /* value=0x80000021 */
+    MFX(0x00000487, "IA32_VMX_CR0_FIXED1", Ia32VmxCr0Fixed1, ReadOnly, UINT32_MAX, 0, 0), /* value=0xffffffff */
+    MFX(0x00000488, "IA32_VMX_CR4_FIXED0", Ia32VmxCr4Fixed0, ReadOnly, 0x2000, 0, 0), /* value=0x2000 */
+    MFX(0x00000489, "IA32_VMX_CR4_FIXED1", Ia32VmxCr4Fixed1, ReadOnly, 0x1767ff, 0, 0), /* value=0x1767ff */
+    MFX(0x0000048a, "IA32_VMX_VMCS_ENUM", Ia32VmxVmcsEnum, ReadOnly, 0x2a, 0, 0), /* value=0x2a */
+    MFX(0x0000048b, "IA32_VMX_PROCBASED_CTLS2", Ia32VmxProcBasedCtls2, ReadOnly, UINT64_C(0x8ff00000000), 0, 0), /* value=0x8ff`00000000 */
+    MFX(0x0000048c, "IA32_VMX_EPT_VPID_CAP", Ia32VmxEptVpidCap, ReadOnly, UINT64_C(0xf0106114141), 0, 0), /* value=0xf01`06114141 */
+    MFX(0x0000048d, "IA32_VMX_TRUE_PINBASED_CTLS", Ia32VmxTruePinbasedCtls, ReadOnly, UINT64_C(0x7f00000016), 0, 0), /* value=0x7f`00000016 */
+    MFX(0x0000048e, "IA32_VMX_TRUE_PROCBASED_CTLS", Ia32VmxTrueProcbasedCtls, ReadOnly, UINT64_C(0xfff9fffe04006172), 0, 0), /* value=0xfff9fffe`04006172 */
+    MFX(0x0000048f, "IA32_VMX_TRUE_EXIT_CTLS", Ia32VmxTrueExitCtls, ReadOnly, UINT64_C(0x7fffff00036dfb), 0, 0), /* value=0x7fffff`00036dfb */
+    MFX(0x00000490, "IA32_VMX_TRUE_ENTRY_CTLS", Ia32VmxTrueEntryCtls, ReadOnly, UINT64_C(0xffff000011fb), 0, 0), /* value=0xffff`000011fb */
+    RSN(0x000004c1, 0x000004c8, "IA32_A_PMCn", Ia32PmcN, Ia32PmcN, 0x0, 0, UINT64_C(0xffff000000000000)),
+    MFX(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffff8804`07da1cc0 */
+    MFX(0x00000601, "I7_SB_MSR_VR_CURRENT_CONFIG", IntelI7SandyVrCurrentConfig, IntelI7SandyVrCurrentConfig, 0, UINT32_C(0x80001fff), 0x7fffe000), /* value=0x18141494`80000380 */
+    MVX(0x00000602, "I7_IB_UNK_0000_0602", UINT64_C(0x1814149480000170), UINT32_C(0x80001fff), 0x7fffe000),
+    MFX(0x00000603, "I7_SB_MSR_VR_MISC_CONFIG", IntelI7SandyVrMiscConfig, IntelI7SandyVrMiscConfig, 0, UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)), /* value=0x802c2c2c */
+    MVX(0x00000604, "I7_IB_UNK_0000_0602", UINT32_C(0x80686868), UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)),
+    MFO(0x00000606, "I7_SB_MSR_RAPL_POWER_UNIT", IntelI7SandyRaplPowerUnit), /* value=0xa1003 */
+    MFX(0x0000060a, "I7_SB_MSR_PKGC3_IRTL", IntelI7SandyPkgCnIrtlN, IntelI7SandyPkgCnIrtlN, 0x3, 0, UINT64_C(0xffffffffffff6000)), /* value=0x883b */
+    RSN(0x0000060b, 0x0000060c, "I7_SB_MSR_PKGC6_IRTn", IntelI7SandyPkgCnIrtlN, IntelI7SandyPkgCnIrtlN, 0x6, 0, UINT64_C(0xffffffffffff6000)),
+    MFO(0x0000060d, "I7_SB_MSR_PKG_C2_RESIDENCY", IntelI7SandyPkgC2Residency), /* value=0x76c`bd67b914 */
+    MFX(0x00000610, "I7_SB_MSR_PKG_POWER_LIMIT", IntelI7RaplPkgPowerLimit, IntelI7RaplPkgPowerLimit, 0, UINT64_C(0x80ffffff00ffffff), UINT64_C(0x7f000000ff000000)), /* value=0x80008302`00148268 */
+    MFO(0x00000611, "I7_SB_MSR_PKG_ENERGY_STATUS", IntelI7RaplPkgEnergyStatus), /* value=0x3451b969 */
+    MFO(0x00000614, "I7_SB_MSR_PKG_POWER_INFO", IntelI7RaplPkgPowerInfo), /* value=0xd0000`01e00268 */
+    MFX(0x00000638, "I7_SB_MSR_PP0_POWER_LIMIT", IntelI7RaplPp0PowerLimit, IntelI7RaplPp0PowerLimit, 0, UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)), /* value=0x80000000 */
+    MFO(0x00000639, "I7_SB_MSR_PP0_ENERGY_STATUS", IntelI7RaplPp0EnergyStatus), /* value=0x357de52e */
+    MFX(0x0000063a, "I7_SB_MSR_PP0_POLICY", IntelI7RaplPp0Policy, IntelI7RaplPp0Policy, 0, 0, UINT64_C(0xffffffffffffffe0)), /* value=0x0 */
+    MFX(0x00000640, "I7_HW_MSR_PP0_POWER_LIMIT", IntelI7RaplPp1PowerLimit, IntelI7RaplPp1PowerLimit, 0, UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)), /* value=0x80000000 */
+    MFO(0x00000641, "I7_HW_MSR_PP0_ENERGY_STATUS", IntelI7RaplPp1EnergyStatus), /* value=0x6eeef */
+    MFX(0x00000642, "I7_HW_MSR_PP0_POLICY", IntelI7RaplPp1Policy, IntelI7RaplPp1Policy, 0, 0, UINT64_C(0xffffffffffffffe0)), /* value=0x10 */
+    MFO(0x00000648, "I7_IB_MSR_CONFIG_TDP_NOMINAL", IntelI7IvyConfigTdpNominal), /* value=0x22 */
+    MFO(0x00000649, "I7_IB_MSR_CONFIG_TDP_LEVEL1", IntelI7IvyConfigTdpLevel1), /* value=0x1e00000`00000000 */
+    MFO(0x0000064a, "I7_IB_MSR_CONFIG_TDP_LEVEL2", IntelI7IvyConfigTdpLevel2), /* value=0x1e00000`00000000 */
+    MFO(0x0000064b, "I7_IB_MSR_CONFIG_TDP_CONTROL", IntelI7IvyConfigTdpControl), /* value=0x80000000 */
+    MFX(0x0000064c, "I7_IB_MSR_TURBO_ACTIVATION_RATIO", IntelI7IvyTurboActivationRatio, IntelI7IvyTurboActivationRatio, 0, 0, UINT64_C(0xffffffff7fffff00)), /* value=0x80000000 */
+    RFN(0x00000680, 0x0000068f, "MSR_LASTBRANCH_n_FROM_IP", IntelLastBranchFromN, IntelLastBranchFromN),
+    RFN(0x000006c0, 0x000006cf, "MSR_LASTBRANCH_n_TO_IP", IntelLastBranchFromN, IntelLastBranchFromN),
+    MFX(0x000006e0, "IA32_TSC_DEADLINE", Ia32TscDeadline, Ia32TscDeadline, 0, UINT64_C(0xb280452208b), 0), /* value=0x4293`ef1535a6 */
+    MVX(0x00000700, "I7_IB_UNK_0000_0700", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000701, "I7_IB_UNK_0000_0701", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000702, "I7_IB_UNK_0000_0702", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000703, "I7_IB_UNK_0000_0703", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000704, "I7_IB_UNK_0000_0704", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000705, "I7_IB_UNK_0000_0705", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000706, "I7_IB_UNK_0000_0706", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000707, "I7_IB_UNK_0000_0707", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000708, "I7_IB_UNK_0000_0708", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000709, "I7_IB_UNK_0000_0709", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000710, "I7_IB_UNK_0000_0710", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000711, "I7_IB_UNK_0000_0711", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000712, "I7_IB_UNK_0000_0712", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000713, "I7_IB_UNK_0000_0713", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000714, "I7_IB_UNK_0000_0714", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000715, "I7_IB_UNK_0000_0715", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000716, "I7_IB_UNK_0000_0716", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000717, "I7_IB_UNK_0000_0717", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000718, "I7_IB_UNK_0000_0718", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000719, "I7_IB_UNK_0000_0719", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000720, "I7_IB_UNK_0000_0720", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000721, "I7_IB_UNK_0000_0721", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000722, "I7_IB_UNK_0000_0722", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000723, "I7_IB_UNK_0000_0723", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000724, "I7_IB_UNK_0000_0724", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000725, "I7_IB_UNK_0000_0725", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000726, "I7_IB_UNK_0000_0726", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000727, "I7_IB_UNK_0000_0727", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000728, "I7_IB_UNK_0000_0728", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000729, "I7_IB_UNK_0000_0729", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000730, "I7_IB_UNK_0000_0730", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000731, "I7_IB_UNK_0000_0731", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000732, "I7_IB_UNK_0000_0732", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000733, "I7_IB_UNK_0000_0733", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000734, "I7_IB_UNK_0000_0734", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000735, "I7_IB_UNK_0000_0735", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000736, "I7_IB_UNK_0000_0736", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000737, "I7_IB_UNK_0000_0737", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000738, "I7_IB_UNK_0000_0738", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000739, "I7_IB_UNK_0000_0739", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000740, "I7_IB_UNK_0000_0740", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000741, "I7_IB_UNK_0000_0741", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000742, "I7_IB_UNK_0000_0742", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000743, "I7_IB_UNK_0000_0743", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000744, "I7_IB_UNK_0000_0744", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000745, "I7_IB_UNK_0000_0745", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000746, "I7_IB_UNK_0000_0746", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000747, "I7_IB_UNK_0000_0747", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000748, "I7_IB_UNK_0000_0748", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000749, "I7_IB_UNK_0000_0749", 0, 0, UINT64_C(0xfffff00000000000)),
+    RFN(0x00000800, 0x000008ff, "IA32_X2APIC_n", Ia32X2ApicN, Ia32X2ApicN),
+    MFN(0x00000c80, "IA32_DEBUG_INTERFACE", Ia32DebugInterface, Ia32DebugInterface), /* value=0x0 */
+    MVX(0x00000c81, "I7_IB_UNK_0000_0c81", 0, 0, 0),
+    MVX(0x00000c82, "I7_IB_UNK_0000_0c82", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00000c83, "I7_IB_UNK_0000_0c83", 0, ~(uint64_t)UINT32_MAX, 0),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0x400, UINT64_C(0xfffffffffffff2fe)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xffffffff`8159b620 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xffffffff`8159ce10 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x43700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0x908880 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xffff8804`1e200000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x0 */
+    MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, 0, ~(uint64_t)UINT32_MAX), /* value=0x0 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz.
+ */
+static CPUMDBENTRY const g_Entry_Intel_Core_i5_3570 = 
+{
+    /*.pszName          = */ "Intel Core i5-3570",
+    /*.pszFullName      = */ "Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
+    /*.uFamily          = */ 6,
+    /*.uModel           = */ 58,
+    /*.uStepping        = */ 9,
+    /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_IvyBridge,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 36,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i5_3570),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i5_3570)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
+    /*.DefUnknownCpuId  = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_Intel_Core_i5_3570)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_Intel_Core_i5_3570),
+};
+
+#endif /* !VBOX_DB_Intel_Core_i5_3570 */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h b/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h
new file mode 100644
index 0000000..54dc9cb
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h
@@ -0,0 +1,382 @@
+/* $Id: Intel_Core_i7_3820QM.h $ */
+/** @file
+ * CPU database entry "Intel Core i7-3820QM".
+ * Generated at 2013-12-04T12:54:32Z by VBoxCpuReport v4.3.51r91071 on darwin.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Intel_Core_i7_3820QM
+#define VBOX_CPUDB_Intel_Core_i7_3820QM
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Intel_Core_i7_3820QM[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x000306a9, 0x02100800, 0x7fbae3ff, 0xbfebfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x1c004121, 0x01c0003f, 0x0000003f, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00021120, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000077, 0x00000002, 0x00000009, 0x00000000, 0 },
+    { 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000281, 0x00000000, 0x00000000, 0 },
+    { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000a, 0x00000000, 0x00000000, 0x07300403, 0x00000000, 0x00000000, 0x00000603, 0 },
+    { 0x0000000b, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000100, 0x00000002, 0 },
+    { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000d, 0x00000000, 0x00000000, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x28100800, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20202020, 0x6e492020, 0x286c6574, 0x43202952, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x2865726f, 0x20294d54, 0x332d3769, 0x51303238, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x5043204d, 0x20402055, 0x30372e32, 0x007a4847, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01006040, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003024, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Intel_Core_i7_3820QM[] = 
+{
+    MFX(0x00000000, "IA32_P5_MC_ADDR", Ia32P5McAddr, Ia32P5McAddr, 0, UINT64_C(0xffffffffffffffe0), 0), /* value=0x1f */
+    MFX(0x00000001, "IA32_P5_MC_TYPE", Ia32P5McType, Ia32P5McType, 0, 0, UINT64_MAX), /* value=0x0 */
+    MFX(0x00000006, "IA32_MONITOR_FILTER_LINE_SIZE", Ia32MonitorFilterLineSize, Ia32MonitorFilterLineSize, 0, 0, UINT64_C(0xffffffffffff0000)), /* value=0x40 */
+    MFX(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter, 0, 0, 0),
+    MVO(0x00000017, "IA32_PLATFORM_ID", UINT64_C(0x10000000000000)),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00900), 0, UINT64_C(0xfffffff0000002ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MVX(0x0000002e, "I7_UNK_0000_002e", 0, 0x400, UINT64_C(0xfffffffffffffbff)),
+    MVX(0x00000033, "TEST_CTL", 0, 0, UINT64_C(0xffffffff7fffffff)),
+    MVO(0x00000034, "P6_UNK_0000_0034", 0xe),
+    MVO(0x00000035, "P6_UNK_0000_0035", 0x40008),
+    MVO(0x00000036, "I7_UNK_0000_0036", 0x6c405eec),
+    MFO(0x0000003a, "IA32_FEATURE_CONTROL", Ia32FeatureControl), /* value=0xff07 */
+    MVX(0x0000003e, "I7_UNK_0000_003e", 0, 0, UINT64_C(0xfffffffffffffffe)),
+    MFN(0x00000079, "IA32_BIOS_UPDT_TRIG", WriteOnly, Ia32BiosUpdateTrigger),
+    MVX(0x0000008b, "BBL_CR_D3|BIOS_SIGN", UINT64_C(0x1500000000), 0x1, UINT32_C(0xfffffffe)),
+    MFO(0x0000009b, "IA32_SMM_MONITOR_CTL", Ia32SmmMonitorCtl), /* value=0x0 */
+    MFX(0x000000c1, "IA32_PMC0", Ia32PmcN, Ia32PmcN, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x000000c2, "IA32_PMC1", Ia32PmcN, Ia32PmcN, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x000000c3, "IA32_PMC2", Ia32PmcN, Ia32PmcN, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x000000c4, "IA32_PMC3", Ia32PmcN, Ia32PmcN, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVO(0x000000ce, "P6_UNK_0000_00ce", UINT64_C(0x80c10f0011b00)),
+    MFX(0x000000e2, "MSR_PKG_CST_CONFIG_CONTROL", IntelPkgCStConfigControl, IntelPkgCStConfigControl, 0, 0, UINT64_C(0xffffffffe1fffbf8)), /* value=0x8405 */
+    MFX(0x000000e4, "MSR_PMG_IO_CAPTURE_BASE", IntelPmgIoCaptureBase, IntelPmgIoCaptureBase, 0, 0, UINT64_C(0xfffffffffff80000)), /* value=0x20414 */
+    MFX(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf, 0, 0x47810, 0), /* value=0x6b`5d075e9c */
+    MFX(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf, 0, 0x1121880, 0), /* value=0x55`2bec768b */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0xd0a, 0, 0), /* value=0xd0a */
+    MVX(0x00000102, "I7_IVY_UNK_0000_0102", 0, 0, UINT64_C(0xffffffff7fff8000)),
+    MVX(0x00000103, "I7_IVY_UNK_0000_0103", 0, 0, UINT64_C(0xffffffffffffff00)),
+    MVX(0x00000104, "I7_IVY_UNK_0000_0104", 0, 0, UINT64_C(0xfffffffffffffffe)),
+    MVX(0x00000132, "I7_UNK_0000_0132", UINT64_MAX, 0, 0),
+    MVX(0x00000133, "I7_UNK_0000_0133", UINT64_MAX, 0, 0),
+    MVX(0x00000134, "I7_UNK_0000_0134", UINT64_MAX, 0, 0),
+    MVO(0x0000013c, "TODO_0000_013c", 0x1),
+    MVX(0x00000140, "I7_IVY_UNK_0000_0140", 0, 0, UINT64_C(0xfffffffffffffffe)),
+    MVX(0x00000142, "I7_IVY_UNK_0000_0142", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0xb */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffff80`21af5080 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffff80`214ce720 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0xc09, 0, 0), /* value=0xc09 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, 0, UINT64_C(0xfffffffffffffff8)), /* value=0x0 */
+    RSN(0x00000186, 0x00000189, "IA32_PERFEVTSELn", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0, 0, UINT64_C(0xffffffff00080000)),
+    MVX(0x00000194, "CLOCK_FLEX_MAX", 0x180000, 0x1e00ff, UINT64_C(0xffffffffffe00000)),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, ReadOnly, UINT64_C(0x240700002400), 0, 0), /* value=0x2407`00002400 */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0x2500, 0, 0), /* Might bite. value=0x2500 */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0, 0, UINT64_C(0xffffffffffffffe0)), /* value=0x0 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0x10, 0, UINT64_C(0xfffffffffe0000e8)), /* value=0x10 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, UINT32_C(0x88340000), UINT32_C(0xf87f0fff), UINT64_C(0xffffffff0780f000)), /* value=0x88340000 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, 0x850089, 0x1080, UINT64_C(0xffffffbbff3aef72)), /* value=0x850089 */
+    MFX(0x000001a2, "I7_MSR_TEMPERATURE_TARGET", IntelI7TemperatureTarget, IntelI7TemperatureTarget, 0x691200, 0xffff00, UINT64_C(0xfffffffff00000ff)), /* value=0x691200 */
+    MVX(0x000001a4, "I7_UNK_0000_01a4", 0, 0, UINT64_C(0xfffffffffffff7f0)),
+    RSN(0x000001a6, 0x000001a7, "I7_MSR_OFFCORE_RSP_n", IntelI7MsrOffCoreResponseN, IntelI7MsrOffCoreResponseN, 0, 0, UINT64_C(0xffffffc000007000)), /* XXX: The range ended earlier than expected! */
+    MVX(0x000001a8, "I7_UNK_0000_01a8", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFX(0x000001aa, "MSR_MISC_PWR_MGMT", IntelI7MiscPwrMgmt, IntelI7MiscPwrMgmt, 0, 0, UINT64_C(0xffffffffffbffffe)), /* value=0x400001 */
+    MVX(0x000001ad, "TODO_0000_01ad", 0x23232425, UINT32_MAX, ~(uint64_t)UINT32_MAX),
+    MVX(0x000001b0, "IA32_ENERGY_PERF_BIAS", 0x4, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x000001b1, "IA32_PACKAGE_THERM_STATUS", UINT32_C(0x88300000), UINT32_C(0xf87f0fff), UINT64_C(0xffffffff0780f000)),
+    MVX(0x000001b2, "IA32_PACKAGE_THERM_INTERRUPT", 0, 0, UINT64_C(0xfffffffffe0000e8)),
+    MVO(0x000001c6, "TODO_0000_01c6", 0x3),
+    MVX(0x000001c8, "TODO_0000_01c8", 0, 0, UINT64_C(0xfffffffffffffe00)),
+    MFX(0x000001c9, "MSR_LASTBRANCH_TOS", IntelLastBranchTos, IntelLastBranchTos, 0, 0, UINT64_C(0xfffffffffffffff0)), /* value=0x8 */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, 0, UINT64_C(0xffffffffffff803c)), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0x7fffff7f`a38c2298 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xffffff80`214b24e0 */
+    MFX(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp, P6LastIntFromIp, 0, 0, UINT64_C(0x7fff800000000000)), /* value=0x0 */
+    MFX(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp, P6LastIntToIp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MVO(0x000001f0, "TODO_0000_01f0", 0x74),
+    MVO(0x000001f2, "TODO_0000_01f2", UINT32_C(0x8b000006)),
+    MVO(0x000001f3, "TODO_0000_01f3", UINT32_C(0xff800800)),
+    MVX(0x000001fc, "TODO_0000_01fc", 0x340047, 0x20, UINT64_C(0xffffffffffc20000)),
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0, 0, UINT64_C(0xfffffff000000ff8)), /* value=0xc0000000 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`c0000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xfffffff000000ff8)), /* value=0xa0000000 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`e0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x90000000 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`f0000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x8c000000 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`fc000800 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x8b000000 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`ff000800 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x00000210, "IA32_MTRR_PHYS_BASE8", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x8, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000211, "IA32_MTRR_PHYS_MASK8", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x8, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x00000212, "IA32_MTRR_PHYS_BASE9", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x9, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000213, "IA32_MTRR_PHYS_MASK9", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x9, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MVX(0x00000280, "TODO_0000_0280", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000281, "TODO_0000_0281", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000282, "TODO_0000_0282", 0, 0x40007fff, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000283, "TODO_0000_0283", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000284, "TODO_0000_0284", 0, 0x40007fff, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000285, "TODO_0000_0285", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000286, "TODO_0000_0286", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000287, "TODO_0000_0287", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x00000288, "TODO_0000_0288", 0, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x000002e0, "TODO_0000_02e0", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFN(0x000002e6, "TODO_0000_02e6", WriteOnly, IgnoreWrite),
+    MVX(0x000002e7, "TODO_0000_02e7", 0x1, 0x1, UINT64_C(0xfffffffffffffffe)),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    MVO(0x00000305, "TODO_0000_0305", 0),
+    MVX(0x00000309, "TODO_0000_0309", 0, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x0000030a, "TODO_0000_030a", 0, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x0000030b, "TODO_0000_030b", 0, 0, UINT64_C(0xffff000000000000)),
+    MVO(0x00000345, "TODO_0000_0345", 0x31c3),
+    MVX(0x0000038d, "TODO_0000_038d", 0, 0, UINT64_C(0xfffffffffffff000)),
+    MVO(0x0000038e, "TODO_0000_038e", UINT64_C(0x8000000000000000)),
+    MVX(0x0000038f, "TODO_0000_038f", 0xf, 0, UINT64_C(0xfffffff8fffffff0)),
+    MVX(0x00000390, "TODO_0000_0390", 0, UINT64_C(0xe00000070000000f), UINT64_C(0x1ffffff8fffffff0)),
+    MVX(0x00000391, "TODO_0000_0391", 0, 0, UINT64_C(0xffffffff1fffffe0)),
+    MVX(0x00000392, "TODO_0000_0392", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000393, "TODO_0000_0393", 0, 0x3, UINT64_C(0xfffffffffffffffc)),
+    MVX(0x00000394, "TODO_0000_0394", 0, 0, UINT64_C(0xffffffffffafffff)),
+    MVX(0x00000395, "TODO_0000_0395", 0, 0, UINT64_C(0xffff000000000000)),
+    MVO(0x00000396, "TODO_0000_0396", 0x5),
+    MVX(0x00000397, "TODO_0000_0397", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x000003b0, "TODO_0000_03b0", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x000003b1, "TODO_0000_03b1", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x000003b2, "TODO_0000_03b2", 0, 0, UINT64_C(0xffffffffc0230000)),
+    MVX(0x000003b3, "TODO_0000_03b3", 0, 0, UINT64_C(0xffffffffc0230000)),
+    MVX(0x000003f1, "TODO_0000_03f1", 0, 0, UINT64_C(0x7ffffff0fffffff0)),
+    MVX(0x000003f6, "TODO_0000_03f6", UINT16_MAX, UINT64_C(0xffffffffffff0000), 0),
+    MVO(0x000003f8, "TODO_0000_03f8", 0),
+    MVO(0x000003f9, "TODO_0000_03f9", UINT64_C(0x27495a818)),
+    MVO(0x000003fa, "TODO_0000_03fa", UINT64_C(0x428fa6c6207)),
+    MVO(0x000003fc, "TODO_0000_03fc", 0x389bb693),
+    MVO(0x000003fd, "TODO_0000_03fd", 0x13323393),
+    MVO(0x000003fe, "TODO_0000_03fe", UINT64_C(0x48d7ffc9bd1)),
+    RFN(0x00000400, 0x00000423, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MVO(0x00000480, "TODO_0000_0480", UINT64_C(0xda040000000010)),
+    MVO(0x00000481, "TODO_0000_0481", UINT64_C(0x7f00000016)),
+    MVO(0x00000482, "TODO_0000_0482", UINT64_C(0xfff9fffe0401e172)),
+    MVO(0x00000483, "TODO_0000_0483", UINT64_C(0x7fffff00036dff)),
+    MVO(0x00000484, "TODO_0000_0484", UINT64_C(0xffff000011ff)),
+    MVO(0x00000485, "TODO_0000_0485", 0x100401e5),
+    MVO(0x00000486, "TODO_0000_0486", UINT32_C(0x80000021)),
+    MVO(0x00000487, "TODO_0000_0487", UINT32_MAX),
+    MVO(0x00000488, "TODO_0000_0488", 0x2000),
+    MVO(0x00000489, "TODO_0000_0489", 0x1767ff),
+    MVO(0x0000048a, "TODO_0000_048a", 0x2a),
+    MVO(0x0000048b, "TODO_0000_048b", UINT64_C(0x8ff00000000)),
+    MVO(0x0000048c, "TODO_0000_048c", UINT64_C(0xf0106114141)),
+    MVO(0x0000048d, "TODO_0000_048d", UINT64_C(0x7f00000016)),
+    MVO(0x0000048e, "TODO_0000_048e", UINT64_C(0xfff9fffe04006172)),
+    MVO(0x0000048f, "TODO_0000_048f", UINT64_C(0x7fffff00036dfb)),
+    MVO(0x00000490, "TODO_0000_0490", UINT64_C(0xffff000011fb)),
+    MVX(0x000004c1, "TODO_0000_04c1", 0, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x000004c2, "TODO_0000_04c2", 0, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x000004c3, "TODO_0000_04c3", 0, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x000004c4, "TODO_0000_04c4", 0, 0, UINT64_C(0xffff000000000000)),
+    MFX(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MVX(0x00000601, "TODO_0000_0601", UINT64_C(0x1814149480000380), UINT32_C(0x80001fff), 0x7fffe000),
+    MVX(0x00000602, "TODO_0000_0602", UINT64_C(0x1814149480000170), UINT32_C(0x80001fff), 0x7fffe000),
+    MVX(0x00000603, "TODO_0000_0603", UINT32_C(0x80303030), UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)),
+    MVX(0x00000604, "TODO_0000_0604", UINT32_C(0x80646464), UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)),
+    MVO(0x00000606, "TODO_0000_0606", 0xa1003),
+    MVX(0x0000060a, "TODO_0000_060a", 0x8894, 0, UINT64_C(0xffffffffffff6000)),
+    MVX(0x0000060b, "TODO_0000_060b", 0x88a9, 0, UINT64_C(0xffffffffffff6000)),
+    MVX(0x0000060c, "TODO_0000_060c", 0x88c6, 0, UINT64_C(0xffffffffffff6000)),
+    MVO(0x0000060d, "TODO_0000_060d", UINT64_C(0xd0fd23dd9)),
+    MVX(0x00000610, "TODO_0000_0610", UINT64_C(0x800083e800dd8320), UINT64_C(0x80ffffff00ffffff), UINT64_C(0x7f000000ff000000)),
+    MVO(0x00000611, "TODO_0000_0611", 0x2ed06e3b),
+    MVO(0x00000614, "TODO_0000_0614", 0x1200168),
+    MVX(0x00000638, "TODO_0000_0638", UINT32_C(0x80000000), UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)),
+    MVO(0x00000639, "TODO_0000_0639", 0x106344fd),
+    MVX(0x0000063a, "TODO_0000_063a", 0, 0, UINT64_C(0xffffffffffffffe0)),
+    MVX(0x00000640, "TODO_0000_0640", UINT32_C(0x80000000), UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)),
+    MVO(0x00000641, "TODO_0000_0641", 0xb39e93),
+    MVX(0x00000642, "TODO_0000_0642", 0x10, 0, UINT64_C(0xffffffffffffffe0)),
+    MVO(0x00000648, "TODO_0000_0648", 0x1b),
+    MVO(0x00000649, "TODO_0000_0649", UINT64_C(0x120000000000000)),
+    MVO(0x0000064a, "TODO_0000_064a", UINT64_C(0x120000000000000)),
+    MVO(0x0000064b, "TODO_0000_064b", UINT32_C(0x80000000)),
+    MVX(0x0000064c, "TODO_0000_064c", UINT32_C(0x80000000), UINT32_C(0x800000ff), UINT64_C(0xffffffff7fffff00)),
+    MVX(0x00000680, "TODO_0000_0680", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000681, "TODO_0000_0681", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000682, "TODO_0000_0682", UINT64_C(0x7fffff7fa38c2289), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000683, "TODO_0000_0683", UINT64_C(0x7fffff80214b24cb), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000684, "TODO_0000_0684", UINT64_C(0x7fffff7fa38c2298), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000685, "TODO_0000_0685", UINT64_C(0x7fffff80214b24ee), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000686, "TODO_0000_0686", UINT64_C(0x7fffff7fa38c2289), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000687, "TODO_0000_0687", UINT64_C(0x7fffff80214b24cb), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000688, "TODO_0000_0688", UINT64_C(0x7fffff7fa38c2298), 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x00000689, "TODO_0000_0689", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x0000068a, "TODO_0000_068a", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x0000068b, "TODO_0000_068b", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x0000068c, "TODO_0000_068c", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x0000068d, "TODO_0000_068d", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x0000068e, "TODO_0000_068e", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x0000068f, "TODO_0000_068f", 0, 0, UINT64_C(0x7fff800000000000)),
+    MVX(0x000006c0, "TODO_0000_06c0", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c1, "TODO_0000_06c1", UINT64_C(0xffffff7fa38c227f), 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c2, "TODO_0000_06c2", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c3, "TODO_0000_06c3", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c4, "TODO_0000_06c4", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c5, "TODO_0000_06c5", UINT64_C(0xffffff7fa38c227f), 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c6, "TODO_0000_06c6", UINT64_C(0xffffff80214b24c0), 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c7, "TODO_0000_06c7", UINT64_C(0xffffff7fa38c228f), 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c8, "TODO_0000_06c8", UINT64_C(0xffffff80214b24e0), 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006c9, "TODO_0000_06c9", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006ca, "TODO_0000_06ca", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006cb, "TODO_0000_06cb", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006cc, "TODO_0000_06cc", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006cd, "TODO_0000_06cd", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006ce, "TODO_0000_06ce", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006cf, "TODO_0000_06cf", 0, 0, UINT64_C(0xffff800000000000)),
+    MVX(0x000006e0, "TODO_0000_06e0", UINT64_C(0x535157ca1ca), 0x80000, 0),
+    MVX(0x00000700, "TODO_0000_0700", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000701, "TODO_0000_0701", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000702, "TODO_0000_0702", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000703, "TODO_0000_0703", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000704, "TODO_0000_0704", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000705, "TODO_0000_0705", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000706, "TODO_0000_0706", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000707, "TODO_0000_0707", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000708, "TODO_0000_0708", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000709, "TODO_0000_0709", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000710, "TODO_0000_0710", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000711, "TODO_0000_0711", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000712, "TODO_0000_0712", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000713, "TODO_0000_0713", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000714, "TODO_0000_0714", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000715, "TODO_0000_0715", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000716, "TODO_0000_0716", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000717, "TODO_0000_0717", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000718, "TODO_0000_0718", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000719, "TODO_0000_0719", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000720, "TODO_0000_0720", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000721, "TODO_0000_0721", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000722, "TODO_0000_0722", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000723, "TODO_0000_0723", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000724, "TODO_0000_0724", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000725, "TODO_0000_0725", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000726, "TODO_0000_0726", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000727, "TODO_0000_0727", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000728, "TODO_0000_0728", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000729, "TODO_0000_0729", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000730, "TODO_0000_0730", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000731, "TODO_0000_0731", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000732, "TODO_0000_0732", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000733, "TODO_0000_0733", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000734, "TODO_0000_0734", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000735, "TODO_0000_0735", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000736, "TODO_0000_0736", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000737, "TODO_0000_0737", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000738, "TODO_0000_0738", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000739, "TODO_0000_0739", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000740, "TODO_0000_0740", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000741, "TODO_0000_0741", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000742, "TODO_0000_0742", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000743, "TODO_0000_0743", 0, 0, UINT64_C(0xffffffffe0230000)),
+    MVX(0x00000744, "TODO_0000_0744", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000745, "TODO_0000_0745", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000746, "TODO_0000_0746", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000747, "TODO_0000_0747", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000748, "TODO_0000_0748", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000749, "TODO_0000_0749", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000c80, "TODO_0000_0c80", 0, 0, 0),
+    MVX(0x00000c81, "TODO_0000_0c81", 0, 0, 0),
+    MVX(0x00000c82, "TODO_0000_0c82", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00000c83, "TODO_0000_0c83", 0, ~(uint64_t)UINT32_MAX, 0),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0x400, UINT64_C(0xfffffffffffff2fe)),
+    MFX(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget, 0, 0, 0), /* value=0x1b0008`00000000 */
+    MFX(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffff80`214ce6c0 */
+    MFX(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x4700 */
+    MFX(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffff81`e942f000 */
+    MFX(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x7fff`7ccad1e0 */
+    MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, 0, ~(uint64_t)UINT32_MAX), /* value=0x0 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz.
+ */
+static CPUMDBENTRY const g_Entry_Intel_Core_i7_3820QM = 
+{
+    /*.pszName          = */ "Intel Core i7-3820QM",
+    /*.pszFullName      = */ "Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
+    /*.uFamily          = */ 6,
+    /*.uModel           = */ 58,
+    /*.uStepping        = */ 9,
+    /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_IvyBridge,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 36,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_3820QM),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i7_3820QM)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
+    /*.DefUnknownCpuId  = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.apaMsrRanges[]   = */
+    {
+        NULL_ALONE(g_aMsrRanges_Intel_Core_i7_3820QM),
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+    }
+};
+
+#endif /* !VBOX_DB_Intel_Core_i7_3820QM */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h b/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h
new file mode 100644
index 0000000..597ec14
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h
@@ -0,0 +1,364 @@
+/* $Id: Intel_Core_i7_3960X.h $ */
+/** @file
+ * CPU database entry "Intel Core i7-3960X".
+ * Generated at 2013-12-12T15:29:11Z by VBoxCpuReport v4.3.53r91237 on win.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Intel_Core_i7_3960X
+#define VBOX_CPUDB_Intel_Core_i7_3960X
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Intel_Core_i7_3960X[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x000206d6, 0x02200800, 0x1fbee3bf, 0xbfebfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, UINT32_MAX, 0x3c004121, 0x01c0003f, 0x0000003f, 0x00000000, 0 },
+    { 0x00000004, 0x00000001, UINT32_MAX, 0x3c004122, 0x01c0003f, 0x0000003f, 0x00000000, 0 },
+    { 0x00000004, 0x00000002, UINT32_MAX, 0x3c004143, 0x01c0003f, 0x000001ff, 0x00000000, 0 },
+    { 0x00000004, 0x00000003, UINT32_MAX, 0x3c07c163, 0x04c0003f, 0x00002fff, 0x00000006, 0 },
+    { 0x00000004, 0x00000004, UINT32_MAX, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00021120, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000077, 0x00000002, 0x00000001, 0x00000000, 0 },
+    { 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000009, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000a, 0x00000000, 0x00000000, 0x07300403, 0x00000000, 0x00000000, 0x00000603, 0 },
+    { 0x0000000b, 0x00000000, UINT32_MAX, 0x00000001, 0x00000002, 0x00000100, 0x00000002, 0 },
+    { 0x0000000b, 0x00000001, UINT32_MAX, 0x00000005, 0x0000000c, 0x00000201, 0x00000002, 0 },
+    { 0x0000000b, 0x00000002, UINT32_MAX, 0x00000000, 0x00000000, 0x00000002, 0x00000002, 0 | CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED },
+    { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000d, 0x00000000, UINT32_MAX, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 },
+    { 0x0000000d, 0x00000001, UINT32_MAX, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000d, 0x00000002, UINT32_MAX, 0x00000100, 0x00000240, 0x00000000, 0x00000000, 0 },
+    { 0x0000000d, 0x00000003, UINT32_MAX, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x2c100800, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20202020, 0x49202020, 0x6c65746e, 0x20295228, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x65726f43, 0x294d5428, 0x2d376920, 0x30363933, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x50432058, 0x20402055, 0x30332e33, 0x007a4847, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01006040, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x0000302e, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Intel_Core_i7_3960X[] = 
+{
+    MFX(0x00000000, "IA32_P5_MC_ADDR", Ia32P5McAddr, Ia32P5McAddr, 0, UINT64_C(0xffffffffffffffe0), 0), /* value=0x1f */
+    MFX(0x00000001, "IA32_P5_MC_TYPE", Ia32P5McType, Ia32P5McType, 0, 0, UINT64_MAX), /* value=0x0 */
+    MFX(0x00000006, "IA32_MONITOR_FILTER_LINE_SIZE", Ia32MonitorFilterLineSize, Ia32MonitorFilterLineSize, 0, 0, UINT64_C(0xffffffffffff0000)), /* value=0x40 */
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x177ab4`48466b19 */
+    MVO(0x00000017, "IA32_PLATFORM_ID", UINT64_C(0x8000000000000)),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0, UINT64_C(0xffffc000000002ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MVX(0x0000002e, "I7_UNK_0000_002e", 0, 0x400, UINT64_C(0xfffffffffffffbff)),
+    MVX(0x00000033, "TEST_CTL", 0, 0, UINT64_C(0xffffffff7fffffff)),
+    MVO(0x00000034, "P6_UNK_0000_0034", 0x4cb),
+    MVO(0x00000035, "P6_UNK_0000_0035", 0x6000c),
+    MFO(0x0000003a, "IA32_FEATURE_CONTROL", Ia32FeatureControl), /* value=0x5 */
+    MVX(0x0000003e, "I7_UNK_0000_003e", 0x1, 0, UINT64_C(0xfffffffffffffffe)),
+    MFN(0x00000079, "IA32_BIOS_UPDT_TRIG", WriteOnly, Ia32BiosUpdateTrigger),
+    MVX(0x0000008b, "BBL_CR_D3|BIOS_SIGN", UINT64_C(0x61600000000), 0, UINT32_C(0xfffffffe)),
+    MFO(0x0000009b, "IA32_SMM_MONITOR_CTL", Ia32SmmMonitorCtl), /* value=0x0 */
+    RSN(0x000000c1, 0x000000c4, "IA32_PMCn", Ia32PmcN, Ia32PmcN, 0x0, ~(uint64_t)UINT32_MAX, 0),
+    MFO(0x000000ce, "MSR_PLATFORM_INFO", IntelPlatformInfo100MHz), /* value=0xc00'70012100*/
+    MFX(0x000000e2, "MSR_PKG_CST_CONFIG_CONTROL", IntelPkgCStConfigControl, IntelPkgCStConfigControl, 0, 0, UINT64_C(0xffffffffe1ffffff)), /* value=0x1e008400 */
+    MFX(0x000000e4, "MSR_PMG_IO_CAPTURE_BASE", IntelPmgIoCaptureBase, IntelPmgIoCaptureBase, 0, 0, UINT64_C(0xfffffffffff80000)), /* value=0x20414 */
+    MFN(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf), /* value=0x2be98e4 */
+    MFN(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf), /* value=0x2d84ced */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0xd0a, 0, 0), /* value=0xd0a */
+    MFN(0x00000132, "CPUID1_FEATURE_MASK", IntelCpuId1FeatureMaskEax, IntelCpuId1FeatureMaskEax), /* value=0xffffffff`ffffffff */
+    MFN(0x00000133, "CPUIDD_01_FEATURE_MASK", IntelCpuId1FeatureMaskEcdx, IntelCpuId1FeatureMaskEcdx), /* value=0xffffffff`ffffffff */
+    MFN(0x00000134, "CPUID80000001_FEATURE_MASK", IntelCpuId80000001FeatureMaskEcdx, IntelCpuId80000001FeatureMaskEcdx), /* value=0xffffffff`ffffffff */
+    MFO(0x0000013c, "I7_SB_AES_NI_CTL", IntelI7SandyAesNiCtl), /* value=0x1 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0xc12, 0, 0), /* value=0xc12 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, 0, UINT64_C(0xfffffffffffffff8)), /* value=0x0 */
+    MFX(0x0000017f, "I7_SB_ERROR_CONTROL", IntelI7SandyErrorControl, IntelI7SandyErrorControl, 0, 0xc, UINT64_C(0xffffffffffffffe1)), /* value=0x0 */
+    RSN(0x00000186, 0x00000189, "IA32_PERFEVTSELn", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0x0, 0, UINT64_C(0xffffffff00080000)),
+    MFX(0x00000194, "CLOCK_FLEX_MAX", IntelFlexRatio100MHz, IntelFlexRatio100MHz, 0xf2100, 0xe0000, UINT64_C(0xfffffffffff00000)),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, ReadOnly, UINT64_C(0x288300002400), 0, 0), /* value=0x2883`00002400 */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0x2700, 0, 0), /* Might bite. value=0x2700 */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0, 0, UINT64_C(0xffffffffffffffe0)), /* value=0x0 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0, 0, UINT64_C(0xfffffffffe0000e8)), /* value=0x0 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, UINT32_C(0x88380000), UINT32_C(0xf87f0fff), UINT64_C(0xffffffff0780f000)), /* value=0x88380000 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, 0x850089, 0x1080, UINT64_C(0xffffffbbff3aef72)), /* value=0x850089 */
+    MFX(0x000001a2, "I7_MSR_TEMPERATURE_TARGET", IntelI7TemperatureTarget, IntelI7TemperatureTarget, 0x5b0a00, 0xffff00, UINT64_C(0xfffffffff00000ff)), /* value=0x5b0a00 */
+    MVX(0x000001a4, "I7_UNK_0000_01a4", 0, 0, UINT64_C(0xfffffffffffff7f0)),
+    RSN(0x000001a6, 0x000001a7, "I7_MSR_OFFCORE_RSP_n", IntelI7MsrOffCoreResponseN, IntelI7MsrOffCoreResponseN, 0x0, 0, UINT64_C(0xffffffc000007000)),
+    MVX(0x000001a8, "I7_UNK_0000_01a8", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFX(0x000001aa, "MSR_MISC_PWR_MGMT", IntelI7MiscPwrMgmt, IntelI7MiscPwrMgmt, 0, 0, UINT64_C(0xffffffffffbffffe)), /* value=0x400000 */
+    MFX(0x000001ad, "I7_MSR_TURBO_RATIO_LIMIT", IntelI7TurboRatioLimit, IntelI7TurboRatioLimit, UINT64_C(0x2424242425252727), 0, 0), /* value=0x24242424`25252727 */
+    MVX(0x000001b1, "IA32_PACKAGE_THERM_STATUS", UINT32_C(0x88310000), UINT32_C(0xf87f0fff), UINT64_C(0xffffffff0780f000)),
+    MVX(0x000001b2, "IA32_PACKAGE_THERM_INTERRUPT", 0, 0, UINT64_C(0xfffffffffe0000e8)),
+    MVO(0x000001c6, "I7_UNK_0000_01c6", 0x3),
+    MFX(0x000001c8, "MSR_LBR_SELECT", IntelI7LbrSelect, IntelI7LbrSelect, 0, 0, UINT64_C(0xfffffffffffffe00)), /* value=0x0 */
+    MFX(0x000001c9, "MSR_LASTBRANCH_TOS", IntelLastBranchTos, IntelLastBranchTos, 0, 0, UINT64_C(0xfffffffffffffff0)), /* value=0xc */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, 0, UINT64_C(0xffffffffffff803c)), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0x7ffff880`093814ea */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xfffff880`093a60e0 */
+    MFX(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp, P6LastIntFromIp, 0, 0, UINT64_C(0x7fff800000000000)), /* value=0x0 */
+    MFX(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp, P6LastIntToIp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MVO(0x000001e1, "I7_SB_UNK_0000_01e1", 0x2),
+    MVX(0x000001ef, "I7_SB_UNK_0000_01ef", 0xff, 0, UINT64_MAX),
+    MFO(0x000001f0, "I7_VLW_CAPABILITY", IntelI7VirtualLegacyWireCap), /* value=0x74 */
+    MFO(0x000001f2, "IA32_SMRR_PHYSBASE", Ia32SmrrPhysBase), /* value=0xad800006 */
+    MFO(0x000001f3, "IA32_SMRR_PHYSMASK", Ia32SmrrPhysMask), /* value=0xff800800 */
+    MFX(0x000001f8, "IA32_PLATFORM_DCA_CAP", Ia32PlatformDcaCap, Ia32PlatformDcaCap, 0, 0, UINT64_C(0xfffffffffffffffe)), /* value=0x1 */
+    MFO(0x000001f9, "IA32_CPU_DCA_CAP", Ia32CpuDcaCap), /* value=0x1 */
+    MFX(0x000001fa, "IA32_DCA_0_CAP", Ia32Dca0Cap, Ia32Dca0Cap, 0, 0x40007ff, UINT64_C(0xfffffffffafe1800)), /* value=0x1e489 */
+    MFX(0x000001fc, "I7_MSR_POWER_CTL", IntelI7PowerCtl, IntelI7PowerCtl, 0, 0, UINT64_C(0xffffffff00320020)), /* value=0x2500005b */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffffc000000007ff)), /* value=0x3ffc`00000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x4`00000006 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffffc000000007ff)), /* value=0x3fff`c0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x4`40000006 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffffc000000007ff)), /* value=0x3fff`f0000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffffc00000000ff8)), /* value=0xae000000 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffffc000000007ff)), /* value=0x3fff`fe000800 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffffc00000000ff8)), /* value=0xb0000000 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffffc000000007ff)), /* value=0x3fff`f0000800 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffffc00000000ff8)), /* value=0xc0000000 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffffc000000007ff)), /* value=0x3fff`c0000800 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffffc000000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffffc000000007ff)), /* value=0x0 */
+    MFX(0x00000210, "IA32_MTRR_PHYS_BASE8", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x8, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x0 */
+    MFX(0x00000211, "IA32_MTRR_PHYS_MASK8", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x8, 0, UINT64_C(0xffffc000000007ff)), /* value=0x0 */
+    MFX(0x00000212, "IA32_MTRR_PHYS_BASE9", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x9, 0, UINT64_C(0xffffc00000000ff8)), /* value=0x0 */
+    MFX(0x00000213, "IA32_MTRR_PHYS_MASK9", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x9, 0, UINT64_C(0xffffc000000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    RSN(0x00000280, 0x00000281, "IA32_MC0_CTLn", Ia32McNCtl2, Ia32McNCtl2, 0x0, 0, UINT64_C(0xffffffffbfff8000)),
+    MFX(0x00000282, "IA32_MC2_CTL2", Ia32McNCtl2, Ia32McNCtl2, 0x2, 0x40007fff, UINT64_C(0xffffffffbfff8000)), /* value=0x0 */
+    MFX(0x00000283, "IA32_MC3_CTL2", Ia32McNCtl2, Ia32McNCtl2, 0x3, 0, UINT64_C(0xffffffffbfff8000)), /* value=0x40000001 */
+    MFX(0x00000284, "IA32_MC4_CTL2", Ia32McNCtl2, Ia32McNCtl2, 0x4, 0x40007fff, UINT64_C(0xffffffffbfff8000)), /* value=0x0 */
+    RSN(0x00000285, 0x00000287, "IA32_MC5_CTLn", Ia32McNCtl2, Ia32McNCtl2, 0x5, 0, UINT64_C(0xffffffffbfff8000)),
+    RSN(0x00000288, 0x0000028b, "IA32_MC8_CTLn", Ia32McNCtl2, Ia32McNCtl2, 0x8, 0x1, UINT64_C(0xffffffffbfff8000)),
+    RSN(0x0000028c, 0x00000291, "IA32_MC12_CTLn", Ia32McNCtl2, Ia32McNCtl2, 0xc, 0, UINT64_C(0xffffffffbfff8000)),
+    MVX(0x000002e0, "I7_SB_NO_EVICT_MODE", 0, 0, UINT64_C(0xfffffffffffffffc)),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    MVO(0x00000300, "I7_SB_UNK_0000_0300", UINT32_C(0x8000ff00)),
+    MVO(0x00000305, "I7_SB_UNK_0000_0305", 0),
+    RSN(0x00000309, 0x0000030b, "IA32_FIXED_CTRn", Ia32FixedCtrN, Ia32FixedCtrN, 0x0, 0, UINT64_C(0xffff000000000000)),
+    MFX(0x00000345, "IA32_PERF_CAPABILITIES", Ia32PerfCapabilities, ReadOnly, 0x31c3, 0, 0), /* value=0x31c3 */
+    MFX(0x0000038d, "IA32_FIXED_CTR_CTRL", Ia32FixedCtrCtrl, Ia32FixedCtrCtrl, 0, 0, UINT64_C(0xfffffffffffff000)), /* value=0x0 */
+    MFX(0x0000038e, "IA32_PERF_GLOBAL_STATUS", Ia32PerfGlobalStatus, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x0000038f, "IA32_PERF_GLOBAL_CTRL", Ia32PerfGlobalCtrl, Ia32PerfGlobalCtrl, 0, 0, UINT64_C(0xfffffff8fffffff0)), /* value=0xf */
+    MFX(0x00000390, "IA32_PERF_GLOBAL_OVF_CTRL", Ia32PerfGlobalOvfCtrl, Ia32PerfGlobalOvfCtrl, 0, UINT64_C(0xe00000070000000f), UINT64_C(0x1ffffff8fffffff0)), /* value=0x0 */
+    MFX(0x0000039c, "I7_SB_MSR_PEBS_NUM_ALT", IntelI7SandyPebsNumAlt, IntelI7SandyPebsNumAlt, 0, 0, UINT64_C(0xfffffffffffffffe)), /* value=0x0 */
+    MFX(0x000003f1, "IA32_PEBS_ENABLE", Ia32PebsEnable, Ia32PebsEnable, 0, 0, UINT64_C(0x7ffffff0fffffff0)), /* value=0x0 */
+    MFX(0x000003f6, "I7_MSR_PEBS_LD_LAT", IntelI7PebsLdLat, IntelI7PebsLdLat, 0, UINT64_C(0xffffffffffff0000), 0), /* value=0xffff */
+    MFX(0x000003f8, "I7_MSR_PKG_C3_RESIDENCY", IntelI7PkgCnResidencyN, ReadOnly, 0x3, 0, UINT64_MAX), /* value=0x0 */
+    RSN(0x000003f9, 0x000003fa, "I7_MSR_PKG_Cn_RESIDENCY", IntelI7PkgCnResidencyN, ReadOnly, 0x6, 0, UINT64_MAX),
+    MFX(0x000003fc, "I7_MSR_CORE_C3_RESIDENCY", IntelI7CoreCnResidencyN, ReadOnly, 0x3, 0, UINT64_MAX), /* value=0x3f8f`5718a87c */
+    RSN(0x000003fd, 0x000003fe, "I7_MSR_CORE_Cn_RESIDENCY", IntelI7CoreCnResidencyN, ReadOnly, 0x6, 0, UINT64_MAX),
+    RFN(0x00000400, 0x00000447, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0x00000480, "IA32_VMX_BASIC", Ia32VmxBase, ReadOnly, UINT64_C(0xda040000000010), 0, 0), /* value=0xda0400`00000010 */
+    MFX(0x00000481, "IA32_VMX_PINBASED_CTLS", Ia32VmxPinbasedCtls, ReadOnly, UINT64_C(0x7f00000016), 0, 0), /* value=0x7f`00000016 */
+    MFX(0x00000482, "IA32_VMX_PROCBASED_CTLS", Ia32VmxProcbasedCtls, ReadOnly, UINT64_C(0xfff9fffe0401e172), 0, 0), /* value=0xfff9fffe`0401e172 */
+    MFX(0x00000483, "IA32_VMX_EXIT_CTLS", Ia32VmxExitCtls, ReadOnly, UINT64_C(0x7fffff00036dff), 0, 0), /* value=0x7fffff`00036dff */
+    MFX(0x00000484, "IA32_VMX_ENTRY_CTLS", Ia32VmxEntryCtls, ReadOnly, UINT64_C(0xffff000011ff), 0, 0), /* value=0xffff`000011ff */
+    MFX(0x00000485, "IA32_VMX_MISC", Ia32VmxMisc, ReadOnly, 0x100401e5, 0, 0), /* value=0x100401e5 */
+    MFX(0x00000486, "IA32_VMX_CR0_FIXED0", Ia32VmxCr0Fixed0, ReadOnly, UINT32_C(0x80000021), 0, 0), /* value=0x80000021 */
+    MFX(0x00000487, "IA32_VMX_CR0_FIXED1", Ia32VmxCr0Fixed1, ReadOnly, UINT32_MAX, 0, 0), /* value=0xffffffff */
+    MFX(0x00000488, "IA32_VMX_CR4_FIXED0", Ia32VmxCr4Fixed0, ReadOnly, 0x2000, 0, 0), /* value=0x2000 */
+    MFX(0x00000489, "IA32_VMX_CR4_FIXED1", Ia32VmxCr4Fixed1, ReadOnly, 0x627ff, 0, 0), /* value=0x627ff */
+    MFX(0x0000048a, "IA32_VMX_VMCS_ENUM", Ia32VmxVmcsEnum, ReadOnly, 0x2a, 0, 0), /* value=0x2a */
+    MFX(0x0000048b, "IA32_VMX_PROCBASED_CTLS2", Ia32VmxProcBasedCtls2, ReadOnly, UINT64_C(0x4ff00000000), 0, 0), /* value=0x4ff`00000000 */
+    MFX(0x0000048c, "IA32_VMX_EPT_VPID_CAP", Ia32VmxEptVpidCap, ReadOnly, UINT64_C(0xf0106134141), 0, 0), /* value=0xf01`06134141 */
+    MFX(0x0000048d, "IA32_VMX_TRUE_PINBASED_CTLS", Ia32VmxTruePinbasedCtls, ReadOnly, UINT64_C(0x7f00000016), 0, 0), /* value=0x7f`00000016 */
+    MFX(0x0000048e, "IA32_VMX_TRUE_PROCBASED_CTLS", Ia32VmxTrueProcbasedCtls, ReadOnly, UINT64_C(0xfff9fffe04006172), 0, 0), /* value=0xfff9fffe`04006172 */
+    MFX(0x0000048f, "IA32_VMX_TRUE_EXIT_CTLS", Ia32VmxTrueExitCtls, ReadOnly, UINT64_C(0x7fffff00036dfb), 0, 0), /* value=0x7fffff`00036dfb */
+    MFX(0x00000490, "IA32_VMX_TRUE_ENTRY_CTLS", Ia32VmxTrueEntryCtls, ReadOnly, UINT64_C(0xffff000011fb), 0, 0), /* value=0xffff`000011fb */
+    RSN(0x000004c1, 0x000004c4, "IA32_A_PMCn", Ia32PmcN, Ia32PmcN, 0x0, 0, UINT64_C(0xffff000000000000)),
+    MVO(0x00000502, "I7_SB_UNK_0000_0502", 0),
+    MFX(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000601, "I7_SB_MSR_VR_CURRENT_CONFIG", IntelI7SandyVrCurrentConfig, IntelI7SandyVrCurrentConfig, 0, UINT32_C(0x80001fff), 0x7fffe000), /* value=0x141494`80000640 */
+    MFX(0x00000603, "I7_SB_MSR_VR_MISC_CONFIG", IntelI7SandyVrMiscConfig, IntelI7SandyVrMiscConfig, 0, UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)), /* value=0x80151515 */
+    MFO(0x00000606, "I7_SB_MSR_RAPL_POWER_UNIT", IntelI7SandyRaplPowerUnit), /* value=0xa1003 */
+    MFX(0x0000060a, "I7_SB_MSR_PKGC3_IRTL", IntelI7SandyPkgCnIrtlN, IntelI7SandyPkgCnIrtlN, 0x3, 0, UINT64_C(0xffffffffffff6000)), /* value=0x0 */
+    RSN(0x0000060b, 0x0000060c, "I7_SB_MSR_PKGC6_IRTn", IntelI7SandyPkgCnIrtlN, IntelI7SandyPkgCnIrtlN, 0x6, 0, UINT64_C(0xffffffffffff6000)),
+    MFO(0x0000060d, "I7_SB_MSR_PKG_C2_RESIDENCY", IntelI7SandyPkgC2Residency), /* value=0x0 */
+    MFX(0x00000610, "I7_SB_MSR_PKG_POWER_LIMIT", IntelI7RaplPkgPowerLimit, IntelI7RaplPkgPowerLimit, 0, UINT64_C(0x80ffffff00ffffff), UINT64_C(0x7f000000ff000000)), /* value=0x80068960`005affff */
+    MFO(0x00000611, "I7_SB_MSR_PKG_ENERGY_STATUS", IntelI7RaplPkgEnergyStatus), /* value=0xc120ff02 */
+    MFO(0x00000613, "I7_SB_MSR_PKG_PERF_STATUS", IntelI7RaplPkgPerfStatus), /* value=0x0 */
+    MFO(0x00000614, "I7_SB_MSR_PKG_POWER_INFO", IntelI7RaplPkgPowerInfo), /* value=0x1a80410 */
+    MFX(0x00000618, "I7_SB_MSR_DRAM_POWER_LIMIT", IntelI7RaplDramPowerLimit, IntelI7RaplDramPowerLimit, 0, UINT32_C(0x80feffff), UINT64_C(0xffffffff7f010000)), /* value=0x80000000 */
+    MFO(0x00000619, "I7_SB_MSR_DRAM_ENERGY_STATUS", IntelI7RaplDramEnergyStatus), /* value=0x0 */
+    MFO(0x0000061b, "I7_SB_MSR_DRAM_PERF_STATUS", IntelI7RaplDramPerfStatus), /* value=0x0 */
+    MFO(0x0000061c, "I7_SB_MSR_DRAM_POWER_INFO", IntelI7RaplDramPowerInfo), /* value=0x280258`00780118 */
+    MFX(0x00000638, "I7_SB_MSR_PP0_POWER_LIMIT", IntelI7RaplPp0PowerLimit, IntelI7RaplPp0PowerLimit, 0, UINT32_C(0x80ffffff), UINT64_C(0xffffffff7f000000)), /* value=0x80000000 */
+    MFO(0x00000639, "I7_SB_MSR_PP0_ENERGY_STATUS", IntelI7RaplPp0EnergyStatus), /* value=0x448bc04 */
+    MFX(0x0000063a, "I7_SB_MSR_PP0_POLICY", IntelI7RaplPp0Policy, IntelI7RaplPp0Policy, 0, 0, UINT64_C(0xffffffffffffffe0)), /* value=0x0 */
+    MFO(0x0000063b, "I7_SB_MSR_PP0_PERF_STATUS", IntelI7RaplPp0PerfStatus), /* value=0x0 */
+    RFN(0x00000680, 0x0000068f, "MSR_LASTBRANCH_n_FROM_IP", IntelLastBranchFromN, IntelLastBranchFromN),
+    RFN(0x000006c0, 0x000006cf, "MSR_LASTBRANCH_n_TO_IP", IntelLastBranchFromN, IntelLastBranchFromN),
+    MFI(0x000006e0, "IA32_TSC_DEADLINE", Ia32TscDeadline), /* value=0x0 */
+    MVX(0x00000a00, "I7_SB_UNK_0000_0a00", 0, 0, UINT64_C(0xfffffffffffffec0)),
+    MVX(0x00000a01, "I7_SB_UNK_0000_0a01", 0x178fa000, 0, UINT64_C(0xffffffff00000f80)),
+    MVX(0x00000a02, "I7_SB_UNK_0000_0a02", 0, 0, UINT64_C(0xffffffff20002000)),
+    MVX(0x00000c00, "I7_SB_UNK_0000_0c00", 0, 0, UINT64_C(0xffffffffbfffff00)),
+    MVX(0x00000c01, "I7_SB_UNK_0000_0c01", 0, 0x9229fe7, UINT64_C(0xfffffffff6dd6018)),
+    MVO(0x00000c06, "I7_SB_UNK_0000_0c06", 0x6),
+    MVX(0x00000c08, "I7_SB_UNK_0000_0c08", 0, 0, UINT64_C(0xffffffffffafffff)),
+    MVX(0x00000c09, "I7_SB_UNK_0000_0c09", 0x301a, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x00000c10, "I7_SB_UNK_0000_0c10", 0, 0x20000, UINT64_C(0xffffffffe0210000)),
+    MVX(0x00000c11, "I7_SB_UNK_0000_0c11", 0, 0x20000, UINT64_C(0xffffffffe0210000)),
+    MVX(0x00000c14, "I7_SB_UNK_0000_0c14", 0, 0, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000c15, "I7_SB_UNK_0000_0c15", 0, 0x3, UINT64_C(0xfffffffffffffffc)),
+    MVX(0x00000c16, "I7_SB_UNK_0000_0c16", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000c17, "I7_SB_UNK_0000_0c17", 0, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000c24, "I7_SB_UNK_0000_0c24", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000c30, "I7_SB_UNK_0000_0c30", 0, 0x20000, UINT64_C(0xffffffff20013f00)),
+    MVX(0x00000c31, "I7_SB_UNK_0000_0c31", 0, 0x20000, UINT64_C(0xffffffff20013f00)),
+    MVX(0x00000c32, "I7_SB_UNK_0000_0c32", 0, 0x20000, UINT64_C(0xffffffff20013f00)),
+    MVX(0x00000c33, "I7_SB_UNK_0000_0c33", 0, 0x20000, UINT64_C(0xffffffff20013f00)),
+    MVX(0x00000c34, "I7_SB_UNK_0000_0c34", 0, 0, ~(uint64_t)UINT32_MAX),
+    MVX(0x00000c35, "I7_SB_UNK_0000_0c35", 0, 0x7f, UINT64_C(0xffffffffffffff80)),
+    MVX(0x00000c36, "I7_SB_UNK_0000_0c36", 0x203, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x00000c37, "I7_SB_UNK_0000_0c37", 0x203, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x00000c38, "I7_SB_UNK_0000_0c38", 0x20c, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x00000c39, "I7_SB_UNK_0000_0c39", 0x203, 0, UINT64_C(0xffff000000000000)),
+    MVX(0x00000d04, "I7_SB_UNK_0000_0d04", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000d10, "I7_SB_UNK_0000_0d10", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d11, "I7_SB_UNK_0000_0d11", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d12, "I7_SB_UNK_0000_0d12", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d13, "I7_SB_UNK_0000_0d13", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d14, "I7_SB_UNK_0000_0d14", 0x20, 0, UINT64_C(0xffffffff00000300)),
+    MVX(0x00000d15, "I7_SB_UNK_0000_0d15", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000d16, "I7_SB_UNK_0000_0d16", 0x81c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d17, "I7_SB_UNK_0000_0d17", 0x80c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d18, "I7_SB_UNK_0000_0d18", 0x80c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d19, "I7_SB_UNK_0000_0d19", 0x810, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d24, "I7_SB_UNK_0000_0d24", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000d30, "I7_SB_UNK_0000_0d30", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d31, "I7_SB_UNK_0000_0d31", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d32, "I7_SB_UNK_0000_0d32", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d33, "I7_SB_UNK_0000_0d33", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d34, "I7_SB_UNK_0000_0d34", 0x20, 0, UINT64_C(0xffffffff00000300)),
+    MVX(0x00000d35, "I7_SB_UNK_0000_0d35", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000d36, "I7_SB_UNK_0000_0d36", 0x864, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d37, "I7_SB_UNK_0000_0d37", 0x804, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d38, "I7_SB_UNK_0000_0d38", 0x822, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d39, "I7_SB_UNK_0000_0d39", 0x81c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d44, "I7_SB_UNK_0000_0d44", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000d50, "I7_SB_UNK_0000_0d50", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d51, "I7_SB_UNK_0000_0d51", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d52, "I7_SB_UNK_0000_0d52", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d53, "I7_SB_UNK_0000_0d53", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d54, "I7_SB_UNK_0000_0d54", 0x20, 0, UINT64_C(0xffffffff00000300)),
+    MVX(0x00000d55, "I7_SB_UNK_0000_0d55", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000d56, "I7_SB_UNK_0000_0d56", 0x848, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d57, "I7_SB_UNK_0000_0d57", 0x866, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d58, "I7_SB_UNK_0000_0d58", 0x83c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d59, "I7_SB_UNK_0000_0d59", 0x83c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d64, "I7_SB_UNK_0000_0d64", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000d70, "I7_SB_UNK_0000_0d70", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d71, "I7_SB_UNK_0000_0d71", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d72, "I7_SB_UNK_0000_0d72", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d73, "I7_SB_UNK_0000_0d73", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d74, "I7_SB_UNK_0000_0d74", 0x20, 0, UINT64_C(0xffffffff00000300)),
+    MVX(0x00000d75, "I7_SB_UNK_0000_0d75", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000d76, "I7_SB_UNK_0000_0d76", 0x846, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d77, "I7_SB_UNK_0000_0d77", 0x90c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d78, "I7_SB_UNK_0000_0d78", 0x846, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d79, "I7_SB_UNK_0000_0d79", 0x842, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d84, "I7_SB_UNK_0000_0d84", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000d90, "I7_SB_UNK_0000_0d90", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d91, "I7_SB_UNK_0000_0d91", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d92, "I7_SB_UNK_0000_0d92", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d93, "I7_SB_UNK_0000_0d93", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000d94, "I7_SB_UNK_0000_0d94", 0x20, 0, UINT64_C(0xffffffff00000300)),
+    MVX(0x00000d95, "I7_SB_UNK_0000_0d95", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000d96, "I7_SB_UNK_0000_0d96", 0x8c6, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d97, "I7_SB_UNK_0000_0d97", 0x840, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d98, "I7_SB_UNK_0000_0d98", 0x81a, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000d99, "I7_SB_UNK_0000_0d99", 0x910, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000da4, "I7_SB_UNK_0000_0da4", 0, 0x3, UINT64_C(0xfffffffffffcfefc)),
+    MVX(0x00000db0, "I7_SB_UNK_0000_0db0", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000db1, "I7_SB_UNK_0000_0db1", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000db2, "I7_SB_UNK_0000_0db2", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000db3, "I7_SB_UNK_0000_0db3", 0, 0x30000, UINT64_C(0xffffffff00200000)),
+    MVX(0x00000db4, "I7_SB_UNK_0000_0db4", 0x20, 0, UINT64_C(0xffffffff00000300)),
+    MVX(0x00000db5, "I7_SB_UNK_0000_0db5", 0, 0xf, UINT64_C(0xfffffffffffffff0)),
+    MVX(0x00000db6, "I7_SB_UNK_0000_0db6", 0x80c, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000db7, "I7_SB_UNK_0000_0db7", 0x81e, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000db8, "I7_SB_UNK_0000_0db8", 0x810, 0, UINT64_C(0xfffff00000000000)),
+    MVX(0x00000db9, "I7_SB_UNK_0000_0db9", 0x80a, 0, UINT64_C(0xfffff00000000000)),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0x400, UINT64_C(0xfffffffffffff2fe)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xfffff800`030dac00 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xfffff800`030da940 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x4700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0xfffe0000 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xfffff880`061e6000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x7ff`fffde000 */
+    MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, 0, ~(uint64_t)UINT32_MAX), /* value=0x0 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz.
+ */
+static CPUMDBENTRY const g_Entry_Intel_Core_i7_3960X = 
+{
+    /*.pszName          = */ "Intel Core i7-3960X",
+    /*.pszFullName      = */ "Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
+    /*.uFamily          = */ 6,
+    /*.uModel           = */ 45,
+    /*.uStepping        = */ 6,
+    /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_SandyBridge,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 46,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_3960X),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i7_3960X)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
+    /*.DefUnknownCpuId  = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_Intel_Core_i7_3960X)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_Intel_Core_i7_3960X),
+};
+
+#endif /* !VBOX_DB_Intel_Core_i7_3960X */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h b/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h
new file mode 100644
index 0000000..96fa39c
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h
@@ -0,0 +1,272 @@
+/* $Id: Intel_Pentium_4_3_00GHz.h $ */
+/** @file
+ * CPU database entry "Intel Pentium 4 3.00GHz".
+ * Generated at 2013-12-18T06:37:54Z by VBoxCpuReport v4.3.53r91376 on win.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Intel_Pentium_4_3_00GHz
+#define VBOX_CPUDB_Intel_Pentium_4_3_00GHz
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Intel(R) Pentium(R) 4 CPU 3.00GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Intel_Pentium_4_3_00GHz[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x00000005, 0x756e6547, 0x6c65746e, 0x49656e69, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x00000f43, 0x00020800, 0x0000649d, 0xbfebfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x605b5001, 0x00000000, 0x00000000, 0x007d7040, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, UINT32_MAX, 0x00004121, 0x01c0003f, 0x0000001f, 0x00000000, 0 },
+    { 0x00000004, 0x00000001, UINT32_MAX, 0x00004143, 0x01c0103f, 0x000007ff, 0x00000000, 0 },
+    { 0x00000004, 0x00000002, UINT32_MAX, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x20100800, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20202020, 0x20202020, 0x20202020, 0x6e492020, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x286c6574, 0x50202952, 0x69746e65, 0x52286d75, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x20342029, 0x20555043, 0x30302e33, 0x007a4847, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08006040, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003024, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Intel(R) Pentium(R) 4 CPU 3.00GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Intel_Pentium_4_3_00GHz[] = 
+{
+    MFO(0x00000000, "IA32_P5_MC_ADDR", Ia32P5McAddr), /* value=0xc55df88 */
+    MFO(0x00000001, "IA32_P5_MC_TYPE", Ia32P5McType), /* value=0xbe000300`1008081f */
+    MFX(0x00000006, "IA32_MONITOR_FILTER_LINE_SIZE", Ia32MonitorFilterLineSize, Ia32MonitorFilterLineSize, 0, UINT64_C(0xffffffffffff0000), 0), /* value=0x40 */
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x1ac`2077a134 */
+    MVI(0x00000017, "IA32_PLATFORM_ID", UINT64_C(0x12000000000000)),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0x600, UINT64_C(0xffffff00000000ff)),
+    MFX(0x0000002a, "P4_EBC_HARD_POWERON", IntelP4EbcHardPowerOn, IntelP4EbcHardPowerOn, 0, UINT64_MAX, 0), /* value=0x0 */
+    MFX(0x0000002b, "P4_EBC_SOFT_POWERON", IntelP4EbcSoftPowerOn, IntelP4EbcSoftPowerOn, 0x7e, UINT64_C(0xffffffffffffff80), 0), /* value=0x7e */
+    MFX(0x0000002c, "P4_EBC_FREQUENCY_ID", IntelP4EbcFrequencyId, IntelP4EbcFrequencyId, 0xf12010f, UINT64_MAX, 0), /* value=0xf12010f */
+    MVX(0x00000039, "C2_UNK_0000_0039", 0x1, 0x1f, ~(uint64_t)UINT32_MAX),
+    MFN(0x00000079, "IA32_BIOS_UPDT_TRIG", WriteOnly, IgnoreWrite),
+    MVX(0x00000080, "P4_UNK_0000_0080", 0, ~(uint64_t)UINT32_MAX, UINT32_MAX),
+    MFX(0x0000008b, "IA32_BIOS_SIGN_ID", Ia32BiosSignId, Ia32BiosSignId, 0, UINT32_MAX, 0), /* value=0x5`00000000 */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0x508, 0, 0), /* value=0x508 */
+    MFX(0x00000119, "BBL_CR_CTL", IntelBblCrCtl, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x180204, 0, 0), /* value=0x180204 */
+    MFN(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus), /* value=0x0 */
+    MVX(0x00000180, "MSR_MCG_RAX", 0, 0, UINT64_MAX),
+    MVX(0x00000181, "MSR_MCG_RBX", 0, 0, UINT64_MAX),
+    MVX(0x00000182, "MSR_MCG_RCX", 0, 0, UINT64_MAX),
+    MVX(0x00000183, "MSR_MCG_RDX", 0, 0, UINT64_MAX),
+    MVX(0x00000184, "MSR_MCG_RSI", 0, 0, UINT64_MAX),
+    MVX(0x00000185, "MSR_MCG_RDI", 0, 0, UINT64_MAX),
+    MFX(0x00000186, "MSR_MCG_RBP", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0, 0, UINT64_MAX), /* value=0x0 */
+    MFX(0x00000187, "MSR_MCG_RSP", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0, 0, UINT64_MAX), /* value=0x0 */
+    MVX(0x00000188, "MSR_MCG_RFLAGS", 0, 0, UINT64_MAX),
+    MVX(0x00000189, "MSR_MCG_RIP", 0, 0, UINT64_MAX),
+    MVX(0x0000018a, "MSR_MCG_MISC", 0, 0, UINT64_MAX),
+    MVX(0x0000018b, "MSR_MCG_RESERVED1", 0, 0, UINT64_MAX),
+    MVX(0x0000018c, "MSR_MCG_RESERVED2", 0, 0, UINT64_MAX),
+    MVX(0x0000018d, "MSR_MCG_RESERVED3", 0, 0, UINT64_MAX),
+    MVX(0x0000018e, "MSR_MCG_RESERVED4", 0, 0, UINT64_MAX),
+    MVX(0x0000018f, "MSR_MCG_RESERVED5", 0, 0, UINT64_MAX),
+    MVX(0x00000190, "MSR_MCG_R8", 0, 0, UINT64_MAX),
+    MVX(0x00000191, "MSR_MCG_R9", 0, 0, UINT64_MAX),
+    MVX(0x00000192, "MSR_MCG_R10", 0, 0, UINT64_MAX),
+    MVX(0x00000193, "MSR_MCG_R11", 0, 0, UINT64_MAX),
+    MVX(0x00000194, "MSR_MCG_R12", 0, 0, UINT64_MAX),
+    MVX(0x00000195, "MSR_MCG_R13", 0, 0, UINT64_MAX),
+    MVX(0x00000196, "MSR_MCG_R14", 0, 0, UINT64_MAX),
+    MVX(0x00000197, "MSR_MCG_R15", 0, 0, UINT64_MAX),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, Ia32PerfStatus, UINT64_C(0xf2d00000f2d), UINT64_MAX, 0), /* value=0xf2d`00000f2d */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0xf2d, 0, 0), /* Might bite. value=0xf2d */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0, UINT64_C(0xffffffffffffffe1), 0), /* value=0x0 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0, UINT64_C(0xfffffffffffffffc), 0), /* value=0x0 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, 0, UINT64_C(0xfffffffffffffff5), 0), /* value=0x0 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, ReadOnly, 0xe2d, 0, 0), /* value=0xe2d */
+    MVX(0x0000019e, "P6_UNK_0000_019e", 0, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0x0000019f, "P6_UNK_0000_019f", UINT64_C(0x32050500000101), UINT64_C(0xff000000fff0c0c0), 0),
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, 0x22850089, 0x20800080, UINT64_C(0xfffffffbdc10f800)), /* value=0x22850089 */
+    MVX(0x000001a1, "MSR_PLATFORM_BRV", 0, UINT64_C(0xfffffffffffcc0c0), 0),
+    MFX(0x000001a2, "P4_UNK_0000_01a2", IntelI7TemperatureTarget, ReadOnly, 0x61048, 0, 0), /* value=0x61048 */
+    MFO(0x000001d7, "MSR_LER_FROM_LIP", P6LastIntFromIp), /* value=0x0 */
+    MFO(0x000001d8, "MSR_LER_TO_LIP", P6LastIntToIp), /* value=0x0 */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, 0, UINT64_C(0xffffffffffffff80)), /* value=0x0 */
+    MFX(0x000001da, "MSR_LASTBRANCH_TOS", IntelLastBranchTos, IntelLastBranchTos, 0, UINT64_C(0xfffffffffffffff0), 0), /* value=0x0 */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffffff00000007ff)), /* value=0xf`c0000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x3f600000 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffffff00000007ff)), /* value=0xf`ffe00800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x3f800000 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffffff00000007ff)), /* value=0xf`ff800800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffffff0000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffffff00000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    MVX(0x00000300, "P4_MSR_BPU_COUNTER0", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000301, "P4_MSR_BPU_COUNTER1", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000302, "P4_MSR_BPU_COUNTER2", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000303, "P4_MSR_BPU_COUNTER3", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000304, "P4_MSR_MS_COUNTER0", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000305, "P4_MSR_MS_COUNTER1", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000306, "P4_MSR_MS_COUNTER2", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000307, "P4_MSR_MS_COUNTER3", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000308, "P4_MSR_FLAME_COUNTER0", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000309, "P4_MSR_FLAME_COUNTER1", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x0000030a, "P4_MSR_FLAME_COUNTER2", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x0000030b, "P4_MSR_FLAME_COUNTER3", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x0000030c, "P4_MSR_IQ_COUNTER0", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x0000030d, "P4_MSR_IQ_COUNTER1", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x0000030e, "P4_MSR_IQ_COUNTER2", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x0000030f, "P4_MSR_IQ_COUNTER3", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000310, "P4_MSR_IQ_COUNTER4", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000311, "P4_MSR_IQ_COUNTER5", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00000360, "P4_MSR_BPU_CCCR0", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000361, "P4_MSR_BPU_CCCR1", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000362, "P4_MSR_BPU_CCCR2", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000363, "P4_MSR_BPU_CCCR3", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000364, "P4_MSR_MS_CCCR0", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000365, "P4_MSR_MS_CCCR1", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000366, "P4_MSR_MS_CCCR2", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000367, "P4_MSR_MS_CCCR3", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000368, "P4_MSR_FLAME_CCCR0", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x00000369, "P4_MSR_FLAME_CCCR1", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x0000036a, "P4_MSR_FLAME_CCCR2", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x0000036b, "P4_MSR_FLAME_CCCR3", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x0000036c, "P4_MSR_IQ_CCCR0", 0, UINT64_C(0xffffffff000007ff), 0),
+    MVX(0x0000036d, "P4_MSR_IQ_CCCR1", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x0000036e, "P4_MSR_IQ_CCCR2", 0, UINT64_C(0xffffffff00000fff), 0),
+    MVX(0x0000036f, "P4_MSR_IQ_CCCR3", 0, UINT64_C(0xffffffff000007ff), 0),
+    MVX(0x00000370, "P4_MSR_IQ_CCCR4", 0, UINT64_C(0xffffffff000000ff), 0),
+    MVX(0x00000371, "P4_MSR_IQ_CCCR5", 0, UINT64_C(0xffffffff000000ff), 0),
+    MVX(0x000003a0, "P4_MSR_BSU_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003a1, "P4_MSR_BSU_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003a2, "P4_MSR_FSB_ESCR0", 0, UINT64_C(0xffffffff40000000), UINT32_C(0x80000000)),
+    MVX(0x000003a3, "P4_MSR_FSB_ESCR1", 0, UINT64_C(0xffffffff40000000), UINT32_C(0x80000000)),
+    MVX(0x000003a4, "P4_MSR_FIRM_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003a5, "P4_MSR_FIRM_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003a6, "P4_MSR_FLAME_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003a7, "P4_MSR_FLAME_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003a8, "P4_MSR_DAC_ESCR0", 0, UINT64_C(0xffffffff61fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003a9, "P4_MSR_DAC_ESCR1", 0, UINT64_C(0xffffffff61fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003aa, "P4_MSR_MOB_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003ab, "P4_MSR_MOB_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003ac, "P4_MSR_PMH_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003ad, "P4_MSR_PMH_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003ae, "P4_MSR_SAAT_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003af, "P4_MSR_SAAT_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003b0, "P4_MSR_U2L_ESCR0", 0, UINT64_C(0xffffffff71c001f0), UINT32_C(0x80000000)),
+    MVX(0x000003b1, "P4_MSR_U2L_ESCR1", 0, UINT64_C(0xffffffff71c001f0), UINT32_C(0x80000000)),
+    MVX(0x000003b2, "P4_MSR_BPU_ESCR0", 0, UINT64_C(0xffffffff61fc0000), UINT32_C(0x80000000)),
+    MVX(0x000003b3, "P4_MSR_BPU_ESCR1", 0, UINT64_C(0xffffffff61fc0000), UINT32_C(0x80000000)),
+    MVX(0x000003b4, "P4_MSR_IS_ESCR0", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003b5, "P4_MSR_IS_ESCR1", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003b6, "P4_MSR_ITLB_ESCR0", 0, UINT64_C(0xffffffff0ffff1e0), UINT32_C(0x80000000)),
+    MVX(0x000003b7, "P4_MSR_ITLB_ESCR1", 0, UINT64_C(0xffffffff0ffff1e0), UINT32_C(0x80000000)),
+    MVX(0x000003b8, "P4_MSR_CRU_ESCR0", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003b9, "P4_MSR_CRU_ESCR1", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003ba, "P4_MSR_IQ_ESCR0", 0, UINT64_C(0xffffffff7fffffff), UINT32_C(0x80000000)),
+    MVX(0x000003bb, "P4_MSR_IQ_ESCR1", 0, UINT64_C(0xffffffff7fffffff), UINT32_C(0x80000000)),
+    MVX(0x000003bc, "P4_MSR_RAT_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003bd, "P4_MSR_RAT_ESCR1", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003be, "P4_MSR_SSU_ESCR0", 0, ~(uint64_t)UINT32_MAX, UINT32_C(0x80000000)),
+    MVX(0x000003c0, "P4_MSR_MS_ESCR0", 0, UINT64_C(0xffffffff61ff81e0), UINT32_C(0x80000000)),
+    MVX(0x000003c1, "P4_MSR_MS_ESCR1", 0, UINT64_C(0xffffffff61ff81e0), UINT32_C(0x80000000)),
+    MVX(0x000003c2, "P4_MSR_TBPU_ESCR0", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003c3, "P4_MSR_TBPU_ESCR1", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003c4, "P4_MSR_TC_ESCR0", 0, UINT64_C(0xffffffff61f801f0), UINT32_C(0x80000000)),
+    MVX(0x000003c5, "P4_MSR_TC_ESCR1", 0, UINT64_C(0xffffffff61f801f0), UINT32_C(0x80000000)),
+    MVX(0x000003c8, "P4_MSR_IX_ESCR0", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003c9, "P4_MSR_IX_ESCR0", 0, UINT64_C(0xffffffff71fe01f0), UINT32_C(0x80000000)),
+    MVX(0x000003ca, "P4_MSR_ALF_ESCR0", 0, UINT64_C(0xffffffff700001f0), UINT32_C(0x80000000)),
+    MVX(0x000003cb, "P4_MSR_ALF_ESCR1", 0, UINT64_C(0xffffffff700001f0), UINT32_C(0x80000000)),
+    MVX(0x000003cc, "P4_MSR_CRU_ESCR2", 0, UINT64_C(0xffffffff61f001f0), UINT32_C(0x80000000)),
+    MVX(0x000003cd, "P4_MSR_CRU_ESCR3", 0, UINT64_C(0xffffffff61f001f0), UINT32_C(0x80000000)),
+    MVX(0x000003e0, "P4_MSR_CRU_ESCR4", 0, UINT64_C(0xffffffff71ff01f0), UINT32_C(0x80000000)),
+    MVX(0x000003e1, "P4_MSR_CRU_ESCR5", 0, UINT64_C(0xffffffff71ff01f0), UINT32_C(0x80000000)),
+    MVX(0x000003f0, "P4_MSR_TC_PRECISE_EVENT", 0xfc00, UINT64_C(0xfffffffffffc001f), 0),
+    MFX(0x000003f1, "IA32_PEBS_ENABLE", Ia32PebsEnable, Ia32PebsEnable, 0, UINT64_C(0xfffffffff8000000), 0), /* value=0x0 */
+    MVX(0x000003f2, "P4_MSR_PEBS_MATRIX_VERT", 0, UINT64_C(0xffffffffffffe000), 0),
+    MVX(0x000003f5, "P4_UNK_0000_03f5", 0, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0x000003f6, "P4_UNK_0000_03f6", 0, UINT64_C(0xffffffffffe00000), 0),
+    MVX(0x000003f7, "P4_UNK_0000_03f7", 0, UINT64_C(0xfffe000000000000), 0),
+    MVX(0x000003f8, "P4_UNK_0000_03f8", 0, UINT64_C(0xffffff000000003f), 0),
+    RFN(0x00000400, 0x0000040f, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFN(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea), /* value=0x0 */
+    RFN(0x00000680, 0x0000068f, "MSR_LASTBRANCH_n_FROM_IP", IntelLastBranchFromN, IntelLastBranchFromN),
+    RFN(0x000006c0, 0x000006cf, "MSR_LASTBRANCH_n_TO_IP", IntelLastBranchToN, IntelLastBranchToN),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0x400, UINT64_C(0xfffffffffffff2fe)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xfffff800`654efdc0 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xfffff800`654efb00 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x4700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0xeed1e000 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xfffff880`009bf000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x7f7`eed1c000 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Intel(R) Pentium(R) 4 CPU 3.00GHz.
+ */
+static CPUMDBENTRY const g_Entry_Intel_Pentium_4_3_00GHz = 
+{
+    /*.pszName          = */ "Intel Pentium 4 3.00GHz",
+    /*.pszFullName      = */ "Intel(R) Pentium(R) 4 CPU 3.00GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
+    /*.uFamily          = */ 15,
+    /*.uModel           = */ 4,
+    /*.uStepping        = */ 3,
+    /*.enmMicroarch     = */ kCpumMicroarch_Intel_NB_Prescott2M,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 36,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Pentium_4_3_00GHz),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Pentium_4_3_00GHz)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_LAST_STD_LEAF,
+    /*.DefUnknownCpuId  = */ { 0x00000040, 0x00000040, 0x00000000, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_Intel_Pentium_4_3_00GHz)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_Intel_Pentium_4_3_00GHz),
+};
+
+#endif /* !VBOX_DB_Intel_Pentium_4_3_00GHz */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h b/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h
new file mode 100644
index 0000000..d07c4d3
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h
@@ -0,0 +1,211 @@
+/* $Id: Intel_Pentium_M_processor_2_00GHz.h $ */
+/** @file
+ * CPU database entry "Intel Pentium M processor 2.00GHz".
+ * Generated at 2013-12-09T14:18:00Z by VBoxCpuReport v4.3.51r91027 on win.x86.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz
+#define VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Intel(R) Pentium(R) M processor 2.00GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Intel_Pentium_M_processor_2_00GHz[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x756e6547, 0x6c65746e, 0x49656e69, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x000006d6, 0x00000816, 0x00000180, 0xafe9f9bf, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x02b3b001, 0x000000f0, 0x00000000, 0x2c04307d, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000004, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20202020, 0x20202020, 0x65746e49, 0x2952286c, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x6e655020, 0x6d756974, 0x20295228, 0x7270204d, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x7365636f, 0x20726f73, 0x30302e32, 0x007a4847, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Intel(R) Pentium(R) M processor 2.00GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Intel_Pentium_M_processor_2_00GHz[] = 
+{
+    MFI(0x00000000, "IA32_P5_MC_ADDR", Ia32P5McAddr), /* value=0x0 */
+    MFI(0x00000001, "IA32_P5_MC_TYPE", Ia32P5McType), /* value=0x0 */
+    MFX(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x22`4d44782e */
+    MVO(0x00000017, "IA32_PLATFORM_ID", UINT64_C(0x140000d0248a28)),
+    MVX(0x00000018, "P6_UNK_0000_0018", 0, 0, 0),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00100), UINT64_C(0xffffffff00000600), 0xff),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, IntelEblCrPowerOn, 0x45080000, UINT64_C(0xfffffffffff7ff7e), 0), /* value=0x45080000 */
+    MVX(0x0000002f, "P6_UNK_0000_002f", 0, UINT64_C(0xfffffffffffffff5), 0),
+    MVX(0x00000032, "P6_UNK_0000_0032", 0, UINT64_C(0xfffffffffffe0000), 0),
+    MVX(0x00000033, "TEST_CTL", 0, UINT64_C(0xffffffff40000000), 0),
+    MVX(0x00000034, "P6_UNK_0000_0034", 0x77ff, ~(uint64_t)UINT32_MAX, UINT32_C(0xfff80000)),
+    MVO(0x00000035, "P6_UNK_0000_0035", 0x300008),
+    MVX(0x0000003b, "P6_UNK_0000_003b", 0, UINT64_C(0xafffffffe), UINT64_C(0xfffffff500000001)),
+    MVO(0x0000003f, "P6_UNK_0000_003f", 0x4),
+    RFN(0x00000040, 0x00000047, "MSR_LASTBRANCH_n", IntelLastBranchFromToN, ReadOnly),
+    MVX(0x0000004a, "P6_UNK_0000_004a", 0, 0, 0), /* value=0x0 */
+    MVX(0x0000004b, "P6_UNK_0000_004b", 0, 0, 0), /* value=0x0 */
+    MVX(0x0000004c, "P6_UNK_0000_004c", 0, 0, 0), /* value=0x0 */
+    MVX(0x0000004d, "P6_UNK_0000_004d", 0, 0, 0), /* value=0xeb1cffbf`8918200a */
+    MVX(0x0000004e, "P6_UNK_0000_004e", 0, 0, 0), /* value=0x8204c60a`e8009512 */
+    MVX(0x0000004f, "P6_UNK_0000_004f", 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVI(0x00000050, "P6_UNK_0000_0050", 0), /* Villain? value=0x0 */
+    MVI(0x00000051, "P6_UNK_0000_0051", 0), /* Villain? value=0x0 */
+    MVI(0x00000052, "P6_UNK_0000_0052", 0), /* Villain? value=0x0 */
+    MVI(0x00000053, "P6_UNK_0000_0053", 0), /* Villain? value=0x0 */
+    MVI(0x00000054, "P6_UNK_0000_0054", 0), /* Villain? value=0x0 */
+    MVX(0x0000006c, "P6_UNK_0000_006c", 0, UINT64_C(0xffffffff00000082), 0),
+    MVX(0x0000006d, "P6_UNK_0000_006d", 0, UINT64_C(0xffffffff00000082), 0),
+    MVX(0x0000006e, "P6_UNK_0000_006e", 0, UINT64_C(0xffffffff00000082), 0),
+    MVO(0x0000006f, "P6_UNK_0000_006f", 0xadb),
+    MFN(0x00000079, "IA32_BIOS_UPDT_TRIG", WriteOnly, Ia32BiosUpdateTrigger),
+    MVX(0x00000088, "BBL_CR_D0", 0, 0, 0), /* value=0xfcaeffff`d779fd3e */
+    MVX(0x00000089, "BBL_CR_D1", 0, 0, 0), /* value=0xefffbcb7`ff77fbef */
+    MVX(0x0000008a, "BBL_CR_D2", 0, 0, 0), /* value=0xdfff3f2f`fb367d9f */
+    MVX(0x0000008b, "BBL_CR_D3|BIOS_SIGN", UINT64_C(0x1800000000), 0, 0),
+    MVX(0x0000008c, "P6_UNK_0000_008c", 0, 0, 0), /* value=0xeffff3ff`ef39bfff */
+    MVX(0x0000008d, "P6_UNK_0000_008d", 0, 0, 0), /* value=0xf773adfb`ef3ff3fc */
+    MVX(0x0000008e, "P6_UNK_0000_008e", 0, 0, 0), /* value=0xfeb7f6ff`ebbffeff */
+    MVX(0x0000008f, "P6_UNK_0000_008f", 0, 0, 0), /* value=0xd6ffb7af`ffad9e7e */
+    MVX(0x00000090, "P6_UNK_0000_0090", 0, UINT64_C(0xfffffffffffffffa), 0), /* value=0x9ebdb4b5 */
+    MVX(0x000000ae, "P6_UNK_0000_00ae", UINT64_C(0x1000000000007efc), 0, 0),
+    MFX(0x000000c1, "IA32_PMC0", Ia32PmcN, Ia32PmcN, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x000000c2, "IA32_PMC1", Ia32PmcN, Ia32PmcN, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVI(0x000000c7, "P6_UNK_0000_00c7", UINT64_C(0x5a000000ac000000)),
+    MVO(0x000000cd, "P6_UNK_0000_00cd", 0),
+    MVO(0x000000ce, "P6_UNK_0000_00ce", UINT64_C(0x2812140000000000)),
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0x508, 0, 0), /* value=0x508 */
+    MVX(0x00000116, "BBL_CR_ADDR", UINT32_C(0xfe7efff0), UINT64_C(0xffffffff0000000f), 0),
+    MVX(0x00000118, "BBL_CR_DECC", UINT64_C(0xc0000000c1ae9fda), UINT64_C(0xfffffff00000000), 0),
+    MFX(0x00000119, "BBL_CR_CTL", IntelBblCrCtl, IntelBblCrCtl, 0x8, UINT64_C(0xffffffffc00001ff), 0), /* value=0x8 */
+    MVI(0x0000011b, "P6_UNK_0000_011b", 0),
+    MFX(0x0000011e, "BBL_CR_CTL3", IntelBblCrCtl3, IntelBblCrCtl3, 0x34272b, UINT64_C(0xfffffffffffbfc1f), 0), /* value=0x34272b */
+    MVI(0x00000131, "P6_UNK_0000_0131", 0),
+    MVX(0x0000014e, "P6_UNK_0000_014e", 0xd31f40, UINT64_C(0xfffffffff000008f), 0),
+    MVI(0x0000014f, "P6_UNK_0000_014f", 0xd31f40),
+    MVX(0x00000150, "P6_UNK_0000_0150", 0, UINT64_C(0xffffffffdfffe07f), 0x20000000),
+    MVX(0x00000151, "P6_UNK_0000_0151", 0x3c531fc6, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x00000154, "P6_UNK_0000_0154", 0),
+    MVX(0x0000015b, "P6_UNK_0000_015b", 0, ~(uint64_t)UINT32_MAX, 0),
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x8 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0xf78af000 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x804de6f0 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x5, 0, 0), /* value=0x5 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RSN(0x00000186, 0x00000187, "IA32_PERFEVTSELn", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0x0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00000194, "CLOCK_FLEX_MAX", 0, UINT64_C(0xfffffffffffee0c0), 0),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, ReadOnly, UINT64_C(0x612142806000612), 0, 0), /* value=0x6121428`06000612 */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0x612, 0, 0), /* Might bite. value=0x612 */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0x2, UINT64_C(0xffffffffffffffe1), 0), /* value=0x2 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0, UINT64_C(0xfffffffffffffffc), 0), /* value=0x0 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, 0, UINT64_C(0xfffffffffffffffd), 0), /* value=0x0 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, Ia32Therm2Ctl, 0x10612, UINT64_C(0xfffffffffffee0c0), 0), /* value=0x10612 */
+    MVX(0x0000019e, "P6_UNK_0000_019e", 0, UINT64_C(0xffffffffffff0000), 0),
+    MVI(0x0000019f, "P6_UNK_0000_019f", 0),
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, 0x111088, UINT64_C(0xffffffff001ffb77), 0), /* value=0x111088 */
+    MVX(0x000001a1, "P6_UNK_0000_01a1", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x000001aa, "P6_PIC_SENS_CFG", 0x3, UINT64_C(0xfffffffffffffffc), 0),
+    MVX(0x000001ae, "P6_UNK_0000_01ae", 0, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x000001af, "P6_UNK_0000_01af", 0x3ff, UINT64_C(0xfffffffffffffc00), 0),
+    MVO(0x000001c9, "TODO_0000_01c9", 0x8000000),
+    MVX(0x000001d3, "P6_UNK_0000_01d3", 0x8000, UINT64_C(0xffffffffffff7fff), 0),
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, UINT64_C(0xffffffffffffc200), 0), /* value=0x1 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0xaad05fa1 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xaad06480 */
+    MFO(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp), /* value=0x7dba1245 */
+    MFO(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp), /* value=0x806f5d54 */
+    MVO(0x000001e0, "MSR_ROB_CR_BKUPTMPDR6", 0xff0),
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`c0000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x40000006 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`e0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x5ff80000 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`fff80800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`00000000 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`00000000 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`00000000 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`00000000 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, UINT64_C(0xf00000000), UINT64_C(0xfffffff000000fff)), /* value=0xf`00000000 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RFN(0x00000400, 0x00000413, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVX(0x00001000, "P6_DEBUG_REGISTER_0", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001001, "P6_DEBUG_REGISTER_1", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001002, "P6_DEBUG_REGISTER_2", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001003, "P6_DEBUG_REGISTER_3", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001004, "P6_DEBUG_REGISTER_4", UINT32_C(0xffff0ff0), ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001005, "P6_DEBUG_REGISTER_5", 0x400, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x00001006, "P6_DEBUG_REGISTER_6", UINT32_C(0xffff0ff0)), /* Villain? */
+    MVI(0x00001007, "P6_DEBUG_REGISTER_7", 0x400), /* Villain? */
+    MVO(0x0000103f, "P6_UNK_0000_103f", 0x4),
+    MVO(0x000010cd, "P6_UNK_0000_10cd", 0),
+    MFW(0x00002000, "P6_CR0", IntelP6CrN, IntelP6CrN, UINT64_C(0xffffffff00000010)), /* value=0x8001003b */
+    MFX(0x00002002, "P6_CR2", IntelP6CrN, IntelP6CrN, 0x2, ~(uint64_t)UINT32_MAX, 0), /* value=0xc30000 */
+    MFX(0x00002003, "P6_CR3", IntelP6CrN, IntelP6CrN, 0x3, ~(uint64_t)UINT32_MAX, 0), /* value=0x29765000 */
+    MFX(0x00002004, "P6_CR4", IntelP6CrN, IntelP6CrN, 0x4, ~(uint64_t)UINT32_MAX, 0), /* value=0x6d9 */
+    MVO(0x0000203f, "P6_UNK_0000_203f", 0x4),
+    MVO(0x000020cd, "P6_UNK_0000_20cd", 0),
+    MVO(0x0000303f, "P6_UNK_0000_303f", 0x4),
+    MVO(0x000030cd, "P6_UNK_0000_30cd", 0),
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Intel(R) Pentium(R) M processor 2.00GHz.
+ */
+static CPUMDBENTRY const g_Entry_Intel_Pentium_M_processor_2_00GHz = 
+{
+    /*.pszName          = */ "Intel Pentium M processor 2.00GHz",
+    /*.pszFullName      = */ "Intel(R) Pentium(R) M processor 2.00GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
+    /*.uFamily          = */ 6,
+    /*.uModel           = */ 13,
+    /*.uStepping        = */ 6,
+    /*.enmMicroarch     = */ kCpumMicroarch_Intel_P6_M_Dothan,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 32,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Pentium_M_processor_2_00GHz),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Pentium_M_processor_2_00GHz)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_LAST_STD_LEAF,
+    /*.DefUnknownCpuId  = */ { 0x02b3b001, 0x000000f0, 0x00000000, 0x2c04307d },
+    /*.fMsrMask         = */ UINT32_C(0x3fff),
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_Intel_Pentium_M_processor_2_00GHz)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_Intel_Pentium_M_processor_2_00GHz),
+};
+
+#endif /* !VBOX_DB_Intel_Pentium_M_processor_2_00GHz */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h b/src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h
new file mode 100644
index 0000000..e307e65
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h
@@ -0,0 +1,240 @@
+/* $Id: Intel_Xeon_X5482_3_20GHz.h $ */
+/** @file
+ * CPU database entry "Intel Xeon X5482 3.20GHz".
+ * Generated at 2013-12-16T12:10:52Z by VBoxCpuReport v4.3.53r91299 on darwin.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz
+#define VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Intel_Xeon_X5482_3_20GHz[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x00010676, 0x04040800, 0x000ce3bd, 0xbfebfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x05b0b101, 0x005657f0, 0x00000000, 0x2cb4304e, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x0c000121, 0x01c0003f, 0x0000003f, 0x00000001, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00002220, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000001, 0x00000000, 0 },
+    { 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000008, 0x00000000, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000a, 0x00000000, 0x00000000, 0x07280202, 0x00000000, 0x00000000, 0x00000503, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x20100800, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x65746e49, 0x2952286c, 0x6f655820, 0x2952286e, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x55504320, 0x20202020, 0x20202020, 0x58202020, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x32383435, 0x20402020, 0x30322e33, 0x007a4847, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x18008040, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003026, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Intel_Xeon_X5482_3_20GHz[] = 
+{
+    MFO(0x00000000, "IA32_P5_MC_ADDR", Ia32P5McAddr), /* value=0x610010 */
+    MFX(0x00000001, "IA32_P5_MC_TYPE", Ia32P5McType, Ia32P5McType, 0, 0, UINT64_MAX), /* value=0x0 */
+    MFX(0x00000006, "IA32_MONITOR_FILTER_LINE_SIZE", Ia32MonitorFilterLineSize, Ia32MonitorFilterLineSize, 0, 0, UINT64_C(0xffffffffffff0000)), /* value=0x40 */
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x1358`d28c2c60 */
+    MVO(0x00000017, "IA32_PLATFORM_ID", UINT64_C(0x18000088e40822)),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0, UINT64_C(0xffffffc0000006ff)),
+    MVX(0x00000021, "C2_UNK_0000_0021", 0, 0, UINT64_C(0xffffffffffffffc0)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, IntelEblCrPowerOn, UINT32_C(0xc2383400), UINT64_C(0xffffffffdff7df00), 0), /* value=0xc2383400 */
+    MVX(0x00000032, "P6_UNK_0000_0032", 0, UINT64_C(0xffffffff01fe0000), 0),
+    MVX(0x00000033, "TEST_CTL", 0, UINT64_C(0xffffffff7fffffff), 0),
+    MVO(0x00000039, "C2_UNK_0000_0039", 0x7),
+    MFO(0x0000003a, "IA32_FEATURE_CONTROL", Ia32FeatureControl), /* value=0x5 */
+    MVO(0x0000003f, "P6_UNK_0000_003f", 0),
+    RFN(0x00000040, 0x00000043, "MSR_LASTBRANCH_n_FROM_IP", IntelLastBranchToN, IntelLastBranchToN),
+    RFN(0x00000060, 0x00000063, "MSR_LASTBRANCH_n_TO_IP", IntelLastBranchFromN, IntelLastBranchFromN),
+    MFN(0x00000079, "IA32_BIOS_UPDT_TRIG", WriteOnly, IgnoreWrite),
+    MVX(0x0000008b, "BBL_CR_D3|BIOS_SIGN", UINT64_C(0x60b00000000), UINT32_MAX, 0),
+    MFO(0x0000009b, "IA32_SMM_MONITOR_CTL", Ia32SmmMonitorCtl), /* value=0x0 */
+    MFX(0x000000a8, "C2_EMTTM_CR_TABLES_0", IntelCore2EmttmCrTablesN, IntelCore2EmttmCrTablesN, 0x612, UINT64_C(0xffffffffffff8000), 0), /* value=0x612 */
+    MFX(0x000000a9, "C2_EMTTM_CR_TABLES_1", IntelCore2EmttmCrTablesN, IntelCore2EmttmCrTablesN, 0x612, UINT64_C(0xffffffffffff8000), 0), /* value=0x612 */
+    MFX(0x000000aa, "C2_EMTTM_CR_TABLES_2", IntelCore2EmttmCrTablesN, IntelCore2EmttmCrTablesN, 0x612, UINT64_C(0xffffffffffff8000), 0), /* value=0x612 */
+    MFX(0x000000ab, "C2_EMTTM_CR_TABLES_3", IntelCore2EmttmCrTablesN, IntelCore2EmttmCrTablesN, 0x612, UINT64_C(0xffffffffffff8000), 0), /* value=0x612 */
+    MFX(0x000000ac, "C2_EMTTM_CR_TABLES_4", IntelCore2EmttmCrTablesN, IntelCore2EmttmCrTablesN, 0x612, UINT64_C(0xffffffffffff8000), 0), /* value=0x612 */
+    MFX(0x000000ad, "C2_EMTTM_CR_TABLES_5", IntelCore2EmttmCrTablesN, IntelCore2EmttmCrTablesN, 0x612, ~(uint64_t)UINT32_MAX, 0), /* value=0x612 */
+    RSN(0x000000c1, 0x000000c2, "IA32_PMCn", Ia32PmcN, Ia32PmcN, 0x0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x000000c7, "P6_UNK_0000_00c7", UINT64_C(0x2300000052000000)),
+    MVO(0x000000cd, "P6_UNK_0000_00cd", 0x806),
+    MVO(0x000000ce, "P6_UNK_0000_00ce", UINT64_C(0x1208227f7f0710)),
+    MVO(0x000000cf, "C2_UNK_0000_00cf", 0),
+    MVO(0x000000e0, "C2_UNK_0000_00e0", 0x18820f0),
+    MVO(0x000000e1, "C2_UNK_0000_00e1", UINT32_C(0xf0f00000)),
+    MFX(0x000000e2, "MSR_PKG_CST_CONFIG_CONTROL", IntelPkgCStConfigControl, IntelPkgCStConfigControl, 0, 0x404000, UINT64_C(0xfffffffffc001000)), /* value=0x202a01 */
+    MFX(0x000000e3, "C2_SMM_CST_MISC_INFO", IntelCore2SmmCStMiscInfo, IntelCore2SmmCStMiscInfo, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x000000e4, "MSR_PMG_IO_CAPTURE_BASE", IntelPmgIoCaptureBase, IntelPmgIoCaptureBase, 0, 0, UINT64_C(0xffffffffff800000)), /* value=0x0 */
+    MVO(0x000000e5, "C2_UNK_0000_00e5", UINT32_C(0xd00208c8)),
+    MFN(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf), /* value=0x40`a0a41c60 */
+    MFN(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf), /* value=0x3a`cc470b98 */
+    MFX(0x000000ee, "C1_EXT_CONFIG", IntelCore1ExtConfig, IntelCore1ExtConfig, 0, UINT64_C(0xffffffffefc5ffff), 0), /* value=0x4000000`877d4b01 */
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0xd08, 0, 0), /* value=0xd08 */
+    MVX(0x00000116, "BBL_CR_ADDR", 0x3fc0, UINT64_C(0xffffff000000001f), 0),
+    MVX(0x00000118, "BBL_CR_DECC", 0xa7f99, UINT64_C(0xfffffffffff00000), 0),
+    MFN(0x0000011a, "BBL_CR_TRIG", WriteOnly, IgnoreWrite),
+    MVI(0x0000011b, "P6_UNK_0000_011b", 0),
+    MVX(0x0000011c, "C2_UNK_0000_011c", UINT32_C(0xe003b94d), UINT64_C(0xffffffff07c00000), 0),
+    MFX(0x0000011e, "BBL_CR_CTL3", IntelBblCrCtl3, IntelBblCrCtl3, UINT32_C(0xbe702111), UINT64_C(0xfffffffffef3fe9f), 0), /* value=0xbe702111 */
+    MVX(0x0000014e, "P6_UNK_0000_014e", 0x70375245, UINT64_C(0xffffffff00000080), 0),
+    MVI(0x0000014f, "P6_UNK_0000_014f", UINT32_C(0xffffba7f)),
+    MVX(0x00000151, "P6_UNK_0000_0151", 0x6b929082, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x0000015e, "C2_UNK_0000_015e", 0x6, 0, UINT64_C(0xfffffffffffffff0)),
+    MFX(0x0000015f, "C1_DTS_CAL_CTRL", IntelCore1DtsCalControl, IntelCore1DtsCalControl, 0, UINT64_C(0xffffffffffc0ffff), 0), /* value=0x822 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0xb */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffff82`0dce9190 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffff80`0d2ce720 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x806, 0, 0), /* value=0x806 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RSN(0x00000186, 0x00000187, "IA32_PERFEVTSELn", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0x0, 0, UINT64_C(0xffffffff00200000)),
+    MVO(0x00000193, "C2_UNK_0000_0193", 0),
+    MVX(0x00000194, "CLOCK_FLEX_MAX", 0x14822, UINT64_C(0xfffffffffffea0c0), 0),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, ReadOnly, UINT64_C(0x822082206300622), 0, 0), /* value=0x8220822`06300622 */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0x822, 0, 0), /* Might bite. value=0x822 */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0x2, 0, UINT64_C(0xffffffffffffffe1)), /* value=0x2 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0x10, 0, UINT64_C(0xffffffffff0000e0)), /* value=0x10 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, UINT32_C(0x883c0000), UINT32_C(0xf87f017f), UINT64_C(0xffffffff0780fc00)), /* value=0x883c0000 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, ReadOnly, 0x612, 0, 0), /* value=0x612 */
+    MVX(0x0000019e, "P6_UNK_0000_019e", 0x2120000, UINT64_C(0xffffffffffff0000), 0),
+    MVI(0x0000019f, "P6_UNK_0000_019f", 0),
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, UINT64_C(0x4066a52489), UINT64_C(0x52600099f6), UINT64_C(0xffffff0019004000)), /* value=0x40`66a52489 */
+    MVX(0x000001a1, "P6_UNK_0000_01a1", 0, UINT64_C(0xffff000000000000), 0),
+    MFX(0x000001a2, "I7_MSR_TEMPERATURE_TARGET", IntelI7TemperatureTarget, ReadOnly, 0x1400, 0, 0), /* value=0x1400 */
+    MVX(0x000001aa, "P6_PIC_SENS_CFG", UINT32_C(0xfe7f042f), UINT64_C(0xffffffff7faf00af), 0),
+    MVX(0x000001bf, "C2_UNK_0000_01bf", 0x404, UINT64_C(0xffffffffffff0000), 0),
+    MFX(0x000001c9, "MSR_LASTBRANCH_TOS", IntelLastBranchTos, IntelLastBranchTos, 0, UINT64_C(0xfffffffffffffffe), 0), /* value=0x0 */
+    MVX(0x000001d3, "P6_UNK_0000_01d3", 0x8000, UINT64_C(0xffffffffffff7fff), 0),
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, 0, UINT64_C(0xffffffffffffa03c)), /* value=0x1 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0xffffff7f`8f47ca6b */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xffffff80`0d2b24c0 */
+    MFX(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp, P6LastIntFromIp, 0, 0x1, UINT64_C(0xffff800000000000)), /* value=0xffffff80`0d2ba20f */
+    MFX(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp, P6LastIntToIp, 0, 0x10, UINT64_C(0xffff800000000000)), /* value=0xffffff80`0d2ba200 */
+    MVO(0x000001e0, "MSR_ROB_CR_BKUPTMPDR6", 0xff0),
+    MFX(0x000001f8, "IA32_PLATFORM_DCA_CAP", Ia32PlatformDcaCap, Ia32PlatformDcaCap, 0, UINT64_C(0xfffffffffffffffe), 0), /* value=0x0 */
+    MFO(0x000001f9, "IA32_CPU_DCA_CAP", Ia32CpuDcaCap), /* value=0x1 */
+    MFX(0x000001fa, "IA32_DCA_0_CAP", Ia32Dca0Cap, Ia32Dca0Cap, 0, UINT64_C(0xfffffffffefe17ff), 0), /* value=0xc01e489 */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x80000000 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x3f`80000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x7fc00000 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x3f`ffc00800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x6 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x30`00000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x0 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x0 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x0 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffffffc000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffffffc0000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RSN(0x00000309, 0x0000030b, "IA32_FIXED_CTRn", Ia32FixedCtrN, Ia32FixedCtrN, 0x0, 0, UINT64_C(0xffffff0000000000)),
+    MFX(0x00000345, "IA32_PERF_CAPABILITIES", Ia32PerfCapabilities, ReadOnly, 0x10c2, 0, 0), /* value=0x10c2 */
+    MFX(0x0000038d, "IA32_FIXED_CTR_CTRL", Ia32FixedCtrCtrl, Ia32FixedCtrCtrl, 0, 0, UINT64_C(0xfffffffffffff444)), /* value=0x0 */
+    MFX(0x0000038e, "IA32_PERF_GLOBAL_STATUS", Ia32PerfGlobalStatus, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFN(0x0000038f, "IA32_PERF_GLOBAL_CTRL", Ia32PerfGlobalCtrl, Ia32PerfGlobalCtrl), /* value=0xffffffff`ffffffff */
+    MFO(0x00000390, "IA32_PERF_GLOBAL_OVF_CTRL", Ia32PerfGlobalOvfCtrl), /* value=0xffffffff`ffffffff */
+    MFX(0x000003f1, "IA32_PEBS_ENABLE", Ia32PebsEnable, Ia32PebsEnable, 0, UINT64_C(0xfffffffffffffffe), 0), /* value=0x0 */
+    RFN(0x00000400, 0x00000417, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFN(0x00000478, "CPUID1_FEATURE_MASK", IntelCpuId1FeatureMaskEcdx, IntelCpuId1FeatureMaskEcdx), /* value=0xffffffff`ffffffff */
+    MFX(0x00000480, "IA32_VMX_BASIC", Ia32VmxBase, ReadOnly, UINT64_C(0x5a08000000000d), 0, 0), /* value=0x5a0800`0000000d */
+    MFX(0x00000481, "IA32_VMX_PINBASED_CTLS", Ia32VmxPinbasedCtls, ReadOnly, UINT64_C(0x3f00000016), 0, 0), /* value=0x3f`00000016 */
+    MFX(0x00000482, "IA32_VMX_PROCBASED_CTLS", Ia32VmxProcbasedCtls, ReadOnly, UINT64_C(0xf7f9fffe0401e172), 0, 0), /* value=0xf7f9fffe`0401e172 */
+    MFX(0x00000483, "IA32_VMX_EXIT_CTLS", Ia32VmxExitCtls, ReadOnly, UINT64_C(0x3ffff00036dff), 0, 0), /* value=0x3ffff`00036dff */
+    MFX(0x00000484, "IA32_VMX_ENTRY_CTLS", Ia32VmxEntryCtls, ReadOnly, UINT64_C(0x3fff000011ff), 0, 0), /* value=0x3fff`000011ff */
+    MFX(0x00000485, "IA32_VMX_MISC", Ia32VmxMisc, ReadOnly, 0x403c0, 0, 0), /* value=0x403c0 */
+    MFX(0x00000486, "IA32_VMX_CR0_FIXED0", Ia32VmxCr0Fixed0, ReadOnly, UINT32_C(0x80000021), 0, 0), /* value=0x80000021 */
+    MFX(0x00000487, "IA32_VMX_CR0_FIXED1", Ia32VmxCr0Fixed1, ReadOnly, UINT32_MAX, 0, 0), /* value=0xffffffff */
+    MFX(0x00000488, "IA32_VMX_CR4_FIXED0", Ia32VmxCr4Fixed0, ReadOnly, 0x2000, 0, 0), /* value=0x2000 */
+    MFX(0x00000489, "IA32_VMX_CR4_FIXED1", Ia32VmxCr4Fixed1, ReadOnly, 0x27ff, 0, 0), /* value=0x27ff */
+    MFX(0x0000048a, "IA32_VMX_VMCS_ENUM", Ia32VmxVmcsEnum, ReadOnly, 0x2c, 0, 0), /* value=0x2c */
+    MFX(0x0000048b, "IA32_VMX_PROCBASED_CTLS2", Ia32VmxProcBasedCtls2, ReadOnly, UINT64_C(0x4100000000), 0, 0), /* value=0x41`00000000 */
+    MVX(0x000004f8, "C2_UNK_0000_04f8", 0, 0, 0),
+    MVX(0x000004f9, "C2_UNK_0000_04f9", 0, 0, 0),
+    MVX(0x000004fa, "C2_UNK_0000_04fa", 0, 0, 0),
+    MVX(0x000004fb, "C2_UNK_0000_04fb", 0, 0, 0),
+    MVX(0x000004fc, "C2_UNK_0000_04fc", 0, 0, 0),
+    MVX(0x000004fd, "C2_UNK_0000_04fd", 0, 0, 0),
+    MVX(0x000004fe, "C2_UNK_0000_04fe", 0, 0, 0),
+    MVX(0x000004ff, "C2_UNK_0000_04ff", 0, 0, 0),
+    MVX(0x00000590, "C2_UNK_0000_0590", 0, 0, 0),
+    MVX(0x00000591, "C2_UNK_0000_0591", 0, ~(uint64_t)UINT32_MAX, 0),
+    MFX(0x000005a0, "C2_PECI_CTL", IntelCore2PeciControl, IntelCore2PeciControl, 0, UINT64_C(0xfffffffffffffffe), 0), /* value=0x1 */
+    MVI(0x000005a1, "C2_UNK_0000_05a1", 0x1),
+    MFX(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0x400, UINT64_C(0xfffffffffffff2fe)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x1b0008`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xffffff80`0d2ce6c0 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0x0 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x4700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0x0 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xffffff82`0dcfd000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x7fff`7c7511e0 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz.
+ */
+static CPUMDBENTRY const g_Entry_Intel_Xeon_X5482_3_20GHz = 
+{
+    /*.pszName          = */ "Intel Xeon X5482 3.20GHz",
+    /*.pszFullName      = */ "Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
+    /*.uFamily          = */ 6,
+    /*.uModel           = */ 23,
+    /*.uStepping        = */ 6,
+    /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core2_Penryn,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 38,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Xeon_X5482_3_20GHz),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Xeon_X5482_3_20GHz)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_LAST_STD_LEAF,
+    /*.DefUnknownCpuId  = */ { 0x07280202, 0x00000000, 0x00000000, 0x00000503 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_Intel_Xeon_X5482_3_20GHz)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_Intel_Xeon_X5482_3_20GHz),
+};
+
+#endif /* !VBOX_DB_Intel_Xeon_X5482_3_20GHz */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/Makefile.kup b/src/VBox/VMM/VMMR3/cpus/Makefile.kup
new file mode 100644
index 0000000..e69de29
diff --git a/src/VBox/VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h b/src/VBox/VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h
new file mode 100644
index 0000000..c9a27fd
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h
@@ -0,0 +1,265 @@
+/* $Id: Quad_Core_AMD_Opteron_2384.h $ */
+/** @file
+ * CPU database entry "Quad-Core AMD Opteron 2384".
+ * Generated at 2013-12-09T21:56:56Z by VBoxCpuReport v4.3.51r91133 on win.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384
+#define VBOX_CPUDB_Quad_Core_AMD_Opteron_2384
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for Quad-Core AMD Opteron(tm) Processor 2384.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_Quad_Core_AMD_Opteron_2384[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x00000005, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x00100f42, 0x06040800, 0x00802009, 0x178bfbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00000000, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x8000001b, 0x68747541, 0x444d4163, 0x69746e65, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00100f42, 0x00000d4f, 0x000037ff, 0xefd3fbff, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x64617551, 0x726f432d, 0x4d412065, 0x704f2044, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x6f726574, 0x6d74286e, 0x72502029, 0x7365636f, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x20726f73, 0x34383332, 0x00000000, 0x00000000, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0xff30ff10, 0xff30ff20, 0x40020140, 0x40020140, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x20800000, 0x42004200, 0x02008140, 0x0030b140, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000001f9, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003030, 0x00000000, 0x00002003, 0x00000000, 0 },
+    { 0x80000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000a, 0x00000000, 0x00000000, 0x00000001, 0x00000040, 0x00000000, 0x0000000f, 0 },
+    { 0x8000000b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000010, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000011, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000013, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000014, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000015, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000016, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000017, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000018, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000019, 0x00000000, 0x00000000, 0xf0300000, 0x60100000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001a, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x8000001b, 0x00000000, 0x00000000, 0x0000001f, 0x00000000, 0x00000000, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for Quad-Core AMD Opteron(tm) Processor 2384.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Quad_Core_AMD_Opteron_2384[] = 
+{
+    MAL(0x00000000, "IA32_P5_MC_ADDR", 0x00000402),
+    MAL(0x00000001, "IA32_P5_MC_TYPE", 0x00000401),
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0xbe`410ca9b6 */
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0, UINT64_C(0xffff0000000006ff)),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MVO(0x0000008b, "BBL_CR_D3|BIOS_SIGN", 0x1000086),
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0x508, 0, 0), /* value=0x508 */
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0x106, 0, 0), /* value=0x106 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, UINT64_C(0xfffffffffffffff8), 0), /* value=0x0 */
+    MFX(0x0000017b, "IA32_MCG_CTL", Ia32McgCtl, Ia32McgCtl, 0, UINT64_C(0xffffffffffffffc0), 0), /* value=0x3f */
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, UINT64_C(0xffffffffffffff80), 0x40), /* value=0x0 */
+    MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP", P6LastBranchFromIp), /* value=0xfffff800`0245dd94 */
+    MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP", P6LastBranchToIp), /* value=0xfffff800`0245e910 */
+    MFO(0x000001dd, "P6_LAST_INT_FROM_IP", P6LastIntFromIp), /* value=0x753d3416 */
+    MFO(0x000001de, "P6_LAST_INT_TO_IP", P6LastIntToIp), /* value=0x753ea130 */
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xffff000000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`80000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xffff000000000ff8)), /* value=0x80000006 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`c0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xffff000000000ff8)), /* value=0xc0000006 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xffff0000000007ff)), /* value=0xffff`f8000800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xffff000000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RFN(0x00000400, 0x00000417, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0x4d01, 0xfe, UINT64_C(0xffffffffffff8200)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xfffff800`0245dd00 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xfffff800`0245da80 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x14700 */
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0xfffe0000 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xfffffa60`01b8a000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x7ff`fffde000 */
+    MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RSN(0xc0000408, 0xc000040a, "AMD_10H_MC4_MISCn", AmdFam10hMc4MiscN, AmdFam10hMc4MiscN, 0, UINT64_C(0xff00f000ffffffff), 0),
+    RVI(0xc000040b, 0xc000040f, "AMD_10H_MC4_MISCn", 0),
+    RSN(0xc0010000, 0xc0010003, "AMD_K8_PERF_CTL_n", AmdK8PerfCtlN, AmdK8PerfCtlN, 0x0, UINT64_C(0xfffffcf000200000), 0),
+    RSN(0xc0010004, 0xc0010007, "AMD_K8_PERF_CTR_n", AmdK8PerfCtrN, AmdK8PerfCtrN, 0x0, UINT64_C(0xffff000000000000), 0),
+    MFX(0xc0010010, "AMD_K8_SYS_CFG", AmdK8SysCfg, AmdK8SysCfg, 0x760600, UINT64_C(0xffffffffff80f8ff), 0), /* value=0x760600 */
+    MFX(0xc0010015, "AMD_K8_HW_CFG", AmdK8HwCr, AmdK8HwCr, 0x1000030, UINT64_C(0xffffffff00000020), 0), /* value=0x1000030 */
+    MFW(0xc0010016, "AMD_K8_IORR_BASE_0", AmdK8IorrBaseN, AmdK8IorrBaseN, UINT64_C(0xffff000000000fe7)), /* value=0x1`b8210000 */
+    MFW(0xc0010017, "AMD_K8_IORR_MASK_0", AmdK8IorrMaskN, AmdK8IorrMaskN, UINT64_C(0xffff0000000007ff)), /* value=0x0 */
+    MFX(0xc0010018, "AMD_K8_IORR_BASE_1", AmdK8IorrBaseN, AmdK8IorrBaseN, 0x1, UINT64_C(0xffff000000000fe7), 0), /* value=0x0 */
+    MFX(0xc0010019, "AMD_K8_IORR_MASK_1", AmdK8IorrMaskN, AmdK8IorrMaskN, 0x1, UINT64_C(0xffff0000000007ff), 0), /* value=0x0 */
+    MFW(0xc001001a, "AMD_K8_TOP_MEM", AmdK8TopOfMemN, AmdK8TopOfMemN, UINT64_C(0xffff0000007fffff)), /* value=0xc8000000 */
+    MFX(0xc001001d, "AMD_K8_TOP_MEM2", AmdK8TopOfMemN, AmdK8TopOfMemN, 0x1, UINT64_C(0xffff0000007fffff), 0), /* value=0x2`38000000 */
+    MFN(0xc001001f, "AMD_K8_NB_CFG1", AmdK8NbCfg1, AmdK8NbCfg1), /* value=0x400000`00000008 */
+    MFN(0xc0010020, "AMD_K8_PATCH_LOADER", WriteOnly, AmdK8PatchLoader),
+    MFX(0xc0010022, "AMD_K8_MC_XCPT_REDIR", AmdK8McXcptRedir, AmdK8McXcptRedir, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RFN(0xc0010030, 0xc0010035, "AMD_K8_CPU_NAME_n", AmdK8CpuNameN, AmdK8CpuNameN),
+    MFX(0xc001003e, "AMD_K8_HTC", AmdK8HwThermalCtrl, AmdK8HwThermalCtrl, 0x327f0004, UINT64_C(0xffffffffc0008838), 0), /* value=0x327f0004 */
+    MFX(0xc001003f, "AMD_K8_STC", AmdK8SwThermalCtrl, AmdK8SwThermalCtrl, 0, UINT64_C(0xffffffffc00088c0), 0), /* value=0x30000000 */
+    MVO(0xc0010043, "AMD_K8_THERMTRIP_STATUS", 0x1830),
+    MFX(0xc0010044, "AMD_K8_MC_CTL_MASK_0", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x0, UINT64_C(0xffffffffffffff00), 0), /* value=0x80 */
+    MFX(0xc0010045, "AMD_K8_MC_CTL_MASK_1", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x1, ~(uint64_t)UINT32_MAX, 0), /* value=0x80 */
+    MFX(0xc0010046, "AMD_K8_MC_CTL_MASK_2", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x2, UINT64_C(0xfffffffffffff000), 0), /* value=0x200 */
+    MFX(0xc0010047, "AMD_K8_MC_CTL_MASK_3", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x3, UINT64_C(0xfffffffffffffffc), 0), /* value=0x0 */
+    MFX(0xc0010048, "AMD_K8_MC_CTL_MASK_4", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x4, UINT64_C(0xffffffffc0000000), 0), /* value=0x780400 */
+    MFX(0xc0010049, "AMD_K8_MC_CTL_MASK_5", AmdK8McCtlMaskN, AmdK8McCtlMaskN, 0x5, UINT64_C(0xfffffffffffffffe), 0), /* value=0x0 */
+    RFN(0xc0010050, 0xc0010053, "AMD_K8_SMI_ON_IO_TRAP_n", AmdK8SmiOnIoTrapN, AmdK8SmiOnIoTrapN),
+    MFX(0xc0010054, "AMD_K8_SMI_ON_IO_TRAP_CTL_STS", AmdK8SmiOnIoTrapCtlSts, AmdK8SmiOnIoTrapCtlSts, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010055, "AMD_K8_INT_PENDING_MSG", AmdK8IntPendingMessage, AmdK8IntPendingMessage, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010056, "AMD_K8_SMI_TRIGGER_IO_CYCLE", AmdK8SmiTriggerIoCycle, AmdK8SmiTriggerIoCycle, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x200242e */
+    MVX(0xc0010057, "AMD_10H_UNK_c001_0057", 0, 0, 0),
+    MFX(0xc0010058, "AMD_10H_MMIO_CFG_BASE_ADDR", AmdFam10hMmioCfgBaseAddr, AmdFam10hMmioCfgBaseAddr, 0, UINT64_C(0xffff0000000fffc0), 0), /* value=0xe0000021 */
+    MFX(0xc0010059, "AMD_10H_TRAP_CTL?", AmdFam10hTrapCtlMaybe, AmdFam10hTrapCtlMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVX(0xc001005a, "AMD_10H_UNK_c001_005a", 0, 0, 0),
+    MVX(0xc001005b, "AMD_10H_UNK_c001_005b", 0, 0, 0),
+    MVX(0xc001005c, "AMD_10H_UNK_c001_005c", 0, 0, 0),
+    MVX(0xc001005d, "AMD_10H_UNK_c001_005d", 0, 0, 0),
+    MVO(0xc0010060, "AMD_K8_BIST_RESULT", 0),
+    MFX(0xc0010061, "AMD_10H_P_ST_CUR_LIM", AmdFam10hPStateCurLimit, ReadOnly, 0x30, 0, 0), /* value=0x30 */
+    MFX(0xc0010062, "AMD_10H_P_ST_CTL", AmdFam10hPStateControl, AmdFam10hPStateControl, 0x1, 0, UINT64_C(0xfffffffffffffff8)), /* value=0x1 */
+    MFX(0xc0010063, "AMD_10H_P_ST_STS", AmdFam10hPStateStatus, ReadOnly, 0x1, 0, 0), /* value=0x1 */
+    MFX(0xc0010064, "AMD_10H_P_ST_0", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x800001e13000300b), 0, 0), /* value=0x800001e1`3000300b */
+    MFX(0xc0010065, "AMD_10H_P_ST_1", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x800001c840004004), 0, 0), /* value=0x800001c8`40004004 */
+    MFX(0xc0010066, "AMD_10H_P_ST_2", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x800001b64000404e), 0, 0), /* value=0x800001b6`4000404e */
+    MFX(0xc0010067, "AMD_10H_P_ST_3", AmdFam10hPStateN, AmdFam10hPStateN, UINT64_C(0x8000019d40004040), 0, 0), /* value=0x8000019d`40004040 */
+    MFX(0xc0010068, "AMD_10H_P_ST_4", AmdFam10hPStateN, AmdFam10hPStateN, 0, 0, 0), /* value=0x0 */
+    MFX(0xc0010070, "AMD_10H_COFVID_CTL", AmdFam10hCofVidControl, AmdFam10hCofVidControl, 0x40014004, UINT64_C(0xffffffff01b80000), 0), /* value=0x40014004 */
+    MFX(0xc0010071, "AMD_10H_COFVID_STS", AmdFam10hCofVidStatus, AmdFam10hCofVidStatus, UINT64_C(0x38b600c340014004), UINT64_MAX, 0), /* value=0x38b600c3`40014004 */
+    MFX(0xc0010074, "AMD_10H_CPU_WD_TMR_CFG", AmdFam10hCpuWatchdogTimer, AmdFam10hCpuWatchdogTimer, 0, UINT64_C(0xffffffffffffff80), 0), /* value=0x0 */
+    MFX(0xc0010111, "AMD_K8_SMM_BASE", AmdK8SmmBase, AmdK8SmmBase, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x98e00 */
+    MFX(0xc0010112, "AMD_K8_SMM_ADDR", AmdK8SmmAddr, AmdK8SmmAddr, 0, UINT64_C(0xffff00000001ffff), 0), /* value=0x0 */
+    MFX(0xc0010113, "AMD_K8_SMM_MASK", AmdK8SmmMask, AmdK8SmmMask, 0, UINT64_C(0xffff0000000188c0), 0), /* value=0x1 */
+    MFX(0xc0010114, "AMD_K8_VM_CR", AmdK8VmCr, AmdK8VmCr, 0, ~(uint64_t)UINT32_MAX, UINT32_C(0xffffffe0)), /* value=0x8 */
+    MFX(0xc0010115, "AMD_K8_IGNNE", AmdK8IgnNe, AmdK8IgnNe, 0, ~(uint64_t)UINT32_MAX, UINT32_C(0xfffffffe)), /* value=0x0 */
+    MFX(0xc0010117, "AMD_K8_VM_HSAVE_PA", AmdK8VmHSavePa, AmdK8VmHSavePa, 0, 0, UINT64_C(0xffff000000000fff)), /* value=0x0 */
+    MFN(0xc0010118, "AMD_10H_VM_LOCK_KEY", AmdFam10hVmLockKey, AmdFam10hVmLockKey), /* value=0x0 */
+    MFN(0xc0010119, "AMD_10H_SSM_LOCK_KEY", AmdFam10hSmmLockKey, AmdFam10hSmmLockKey), /* value=0x0 */
+    MFX(0xc001011a, "AMD_10H_LOCAL_SMI_STS", AmdFam10hLocalSmiStatus, AmdFam10hLocalSmiStatus, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc0010140, "AMD_10H_OSVW_ID_LEN", AmdFam10hOsVisWrkIdLength, AmdFam10hOsVisWrkIdLength, 0x1, 0, 0), /* value=0x1 */
+    MFN(0xc0010141, "AMD_10H_OSVW_STS", AmdFam10hOsVisWrkStatus, AmdFam10hOsVisWrkStatus), /* value=0x0 */
+    MFX(0xc0011000, "AMD_K7_MCODE_CTL", AmdK7MicrocodeCtl, AmdK7MicrocodeCtl, 0, ~(uint64_t)UINT32_MAX, 0x204), /* value=0x0 */
+    MFX(0xc0011001, "AMD_K7_APIC_CLUSTER_ID", AmdK7ClusterIdMaybe, AmdK7ClusterIdMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFN(0xc0011004, "AMD_K8_CPUID_CTL_STD01", AmdK8CpuIdCtlStd01hEdcx, AmdK8CpuIdCtlStd01hEdcx), /* value=0x802009`178bfbff */
+    MFN(0xc0011005, "AMD_K8_CPUID_CTL_EXT01", AmdK8CpuIdCtlExt01hEdcx, AmdK8CpuIdCtlExt01hEdcx), /* value=0x37ff`efd3fbff */
+    MFX(0xc0011006, "AMD_K7_DEBUG_STS?", AmdK7DebugStatusMaybe, AmdK7DebugStatusMaybe, 0, UINT64_C(0xffffffff00000080), 0), /* value=0x0 */
+    MFN(0xc0011007, "AMD_K7_BH_TRACE_BASE?", AmdK7BHTraceBaseMaybe, AmdK7BHTraceBaseMaybe), /* value=0x0 */
+    MFN(0xc0011008, "AMD_K7_BH_TRACE_PTR?", AmdK7BHTracePtrMaybe, AmdK7BHTracePtrMaybe), /* value=0x0 */
+    MFN(0xc0011009, "AMD_K7_BH_TRACE_LIM?", AmdK7BHTraceLimitMaybe, AmdK7BHTraceLimitMaybe), /* value=0x0 */
+    MFX(0xc001100a, "AMD_K7_HDT_CFG?", AmdK7HardwareDebugToolCfgMaybe, AmdK7HardwareDebugToolCfgMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0xc001100b, "AMD_K7_FAST_FLUSH_COUNT?", AmdK7FastFlushCountMaybe, AmdK7FastFlushCountMaybe, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x7c0 */
+    MFX(0xc001100c, "AMD_K7_NODE_ID", AmdK7NodeId, AmdK7NodeId, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MVX(0xc001100d, "AMD_K8_LOGICAL_CPUS_NUM?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001100e, "AMD_K8_WRMSR_BP?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001100f, "AMD_K8_WRMSR_BP_MASK?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc0011010, "AMD_K8_BH_TRACE_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0xc0011011, "AMD_K8_BH_TRACE_USRD?", 0), /* value=0x0 */
+    MVI(0xc0011012, "AMD_K7_UNK_c001_1012", UINT32_MAX),
+    MVI(0xc0011013, "AMD_K7_UNK_c001_1013", UINT64_MAX),
+    MVX(0xc0011014, "AMD_K8_XCPT_BP_RIP?", 0, 0, 0),
+    MVX(0xc0011015, "AMD_K8_XCPT_BP_RIP_MASK?", 0, 0, 0),
+    MVX(0xc0011016, "AMD_K8_COND_HDT_VAL?", 0, 0, 0),
+    MVX(0xc0011017, "AMD_K8_COND_HDT_VAL_MASK?", 0, 0, 0),
+    MVX(0xc0011018, "AMD_K8_XCPT_BP_CTL?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0xc001101d, "AMD_K8_NB_BIST?", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0xc001101e, "AMD_K8_THERMTRIP_2?", 0x1830), /* Villain? */
+    MVX(0xc001101f, "AMD_K8_NB_CFG?", UINT64_C(0x40000000000008), 0, 0),
+    MFX(0xc0011020, "AMD_K7_LS_CFG", AmdK7LoadStoreCfg, AmdK7LoadStoreCfg, 0, UINT64_C(0xfffe012000000000), 0), /* value=0x10`00001000 */
+    MFW(0xc0011021, "AMD_K7_IC_CFG", AmdK7InstrCacheCfg, AmdK7InstrCacheCfg, ~(uint64_t)UINT32_MAX), /* value=0x0 */
+    MFX(0xc0011022, "AMD_K7_DC_CFG", AmdK7DataCacheCfg, AmdK7DataCacheCfg, 0, UINT64_C(0xffc0000000000000), 0), /* value=0x1c94`49000000 */
+    MFN(0xc0011023, "AMD_K7_BU_CFG", AmdK7BusUnitCfg, AmdK7BusUnitCfg), /* Villain? value=0x10200020 */
+    MFX(0xc0011024, "AMD_K7_DEBUG_CTL_2?", AmdK7DebugCtl2Maybe, AmdK7DebugCtl2Maybe, 0, UINT64_C(0xffffffffffffff00), 0), /* value=0x0 */
+    MFN(0xc0011025, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMatchMaybe, AmdK7Dr0DataMatchMaybe), /* value=0x0 */
+    MFN(0xc0011026, "AMD_K7_DR0_DATA_MATCH?", AmdK7Dr0DataMaskMaybe, AmdK7Dr0DataMaskMaybe), /* value=0x0 */
+    MFX(0xc0011027, "AMD_K7_DR0_ADDR_MASK", AmdK7DrXAddrMaskN, AmdK7DrXAddrMaskN, 0x0, UINT64_C(0xfffffffffffff000), 0), /* value=0x0 */
+    MVX(0xc0011028, "AMD_10H_UNK_c001_1028", 0, UINT64_C(0xfffffffffffffff8), 0),
+    MVX(0xc0011029, "AMD_10H_UNK_c001_1029", 0, ~(uint64_t)UINT32_MAX, 0),
+    MFX(0xc001102a, "AMD_10H_BU_CFG2", AmdFam10hBusUnitCfg2, AmdFam10hBusUnitCfg2, 0, UINT64_C(0xfff00000c0000000), 0), /* value=0x40040`050000c0 */
+    MFX(0xc0011030, "AMD_10H_IBS_FETCH_CTL", AmdFam10hIbsFetchCtl, AmdFam10hIbsFetchCtl, 0, UINT64_C(0xfdfcffff00000000), 0), /* value=0x0 */
+    MFI(0xc0011031, "AMD_10H_IBS_FETCH_LIN_ADDR", AmdFam10hIbsFetchLinAddr), /* value=0xffffff1f`6ffffec0 */
+    MFI(0xc0011032, "AMD_10H_IBS_FETCH_PHYS_ADDR", AmdFam10hIbsFetchPhysAddr), /* value=0xffffbecf`eff1fec0 */
+    MFX(0xc0011033, "AMD_10H_IBS_OP_EXEC_CTL", AmdFam10hIbsOpExecCtl, AmdFam10hIbsOpExecCtl, 0, UINT64_C(0xfffffffffff00000), 0), /* value=0x0 */
+    MFN(0xc0011034, "AMD_10H_IBS_OP_RIP", AmdFam10hIbsOpRip, AmdFam10hIbsOpRip), /* value=0xffffcf06`409f2d93 */
+    MFI(0xc0011035, "AMD_10H_IBS_OP_DATA", AmdFam10hIbsOpData), /* value=0x3b`7701fe63 */
+    MFX(0xc0011036, "AMD_10H_IBS_OP_DATA2", AmdFam10hIbsOpData2, AmdFam10hIbsOpData2, 0, UINT64_C(0xffffffffffffffc8), 0), /* value=0x0 */
+    MFI(0xc0011037, "AMD_10H_IBS_OP_DATA3", AmdFam10hIbsOpData3), /* value=0x0 */
+    MFX(0xc0011038, "AMD_10H_IBS_DC_LIN_ADDR", AmdFam10hIbsDcLinAddr, AmdFam10hIbsDcLinAddr, 0, UINT64_C(0x7fffffffffff), 0), /* value=0x0 */
+    MFI(0xc0011039, "AMD_10H_IBS_DC_PHYS_ADDR", AmdFam10hIbsDcPhysAddr), /* value=0x0 */
+    MFO(0xc001103a, "AMD_10H_IBS_CTL", AmdFam10hIbsCtl), /* value=0x100 */
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for Quad-Core AMD Opteron(tm) Processor 2384.
+ */
+static CPUMDBENTRY const g_Entry_Quad_Core_AMD_Opteron_2384 = 
+{
+    /*.pszName          = */ "Quad-Core AMD Opteron 2384",
+    /*.pszFullName      = */ "Quad-Core AMD Opteron(tm) Processor 2384",
+    /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
+    /*.uFamily          = */ 16,
+    /*.uModel           = */ 4,
+    /*.uStepping        = */ 2,
+    /*.enmMicroarch     = */ kCpumMicroarch_AMD_K10,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 48,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Quad_Core_AMD_Opteron_2384),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Quad_Core_AMD_Opteron_2384)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_DEFAULTS,
+    /*.DefUnknownCpuId  = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_Quad_Core_AMD_Opteron_2384)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_Quad_Core_AMD_Opteron_2384),
+};
+
+#endif /* !VBOX_DB_Quad_Core_AMD_Opteron_2384 */
+
diff --git a/src/VBox/VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h b/src/VBox/VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h
new file mode 100644
index 0000000..8ea4e5c
--- /dev/null
+++ b/src/VBox/VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h
@@ -0,0 +1,399 @@
+/* $Id: VIA_QuadCore_L4700_1_2_GHz.h $ */
+/** @file
+ * CPU database entry "VIA QuadCore L4700 1.2+ GHz".
+ * Generated at 2013-12-20T14:40:07Z by VBoxCpuReport v4.3.53r91411 on linux.amd64.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz
+#define VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * CPUID leaves for VIA QuadCore L4700 @ 1.2+ GHz.
+ */
+static CPUMCPUIDLEAF const g_aCpuIdLeaves_VIA_QuadCore_L4700_1_2_GHz[] = 
+{
+    { 0x00000000, 0x00000000, 0x00000000, 0x0000000a, 0x746e6543, 0x736c7561, 0x48727561, 0 },
+    { 0x00000001, 0x00000000, 0x00000000, 0x000006fd, 0x06080800, 0x008863a9, 0xbfc9fbff, 0 },
+    { 0x00000002, 0x00000000, 0x00000000, 0x02b3b001, 0x00000000, 0x00000000, 0x2c04307d, 0 },
+    { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000004, 0x00000000, 0x00000000, 0x1c000021, 0x03c0003f, 0x0000003f, 0x00000000, 0 },
+    { 0x00000005, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000003, 0x00022220, 0 },
+    { 0x00000006, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x0000000a, 0x00000000, 0x00000000, 0x06280202, 0x00000000, 0x00000000, 0x00000503, 0 },
+    { 0x80000000, 0x00000000, 0x00000000, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x20100800, 0 },
+    { 0x80000002, 0x00000000, 0x00000000, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0 },
+    { 0x80000003, 0x00000000, 0x00000000, 0x49562020, 0x75512041, 0x6f436461, 0x4c206572, 0 },
+    { 0x80000004, 0x00000000, 0x00000000, 0x30303734, 0x31204020, 0x202b322e, 0x007a4847, 0 },
+    { 0x80000005, 0x00000000, 0x00000000, 0x00000000, 0x08800880, 0x40100140, 0x40100140, 0 },
+    { 0x80000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04008140, 0x00000000, 0 },
+    { 0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0x80000008, 0x00000000, 0x00000000, 0x00003024, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0xc0000000, 0x00000000, 0x00000000, 0xc0000004, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0xc0000001, 0x00000000, 0x00000000, 0x000006fd, 0x00000000, 0x00000000, 0x1ec03dcc, 0 },
+    { 0xc0000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0xc0000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 },
+    { 0xc0000004, 0x00000000, 0x00000000, 0x000fffb7, 0x08000955, 0x08530954, 0x00000000, 0 },
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+#ifndef CPUM_DB_STANDALONE
+/**
+ * MSR ranges for VIA QuadCore L4700 @ 1.2+ GHz.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_VIA_QuadCore_L4700_1_2_GHz[] = 
+{
+    RVI(0x00000000, 0x00000005, "ZERO_0000_0000_THRU_0000_0005", 0),
+    MFX(0x00000006, "IA32_MONITOR_FILTER_LINE_SIZE", Ia32MonitorFilterLineSize, Ia32MonitorFilterLineSize, 0, UINT64_C(0xffffffffffff0000), 0), /* value=0x40 */
+    RVI(0x00000007, 0x0000000f, "ZERO_0000_0007_THRU_0000_000f", 0),
+    MFN(0x00000010, "IA32_TIME_STAMP_COUNTER", Ia32TimestampCounter, Ia32TimestampCounter), /* value=0x965`912e15ac */
+    RVI(0x00000011, 0x0000001a, "ZERO_0000_0011_THRU_0000_001a", 0),
+    MFX(0x0000001b, "IA32_APIC_BASE", Ia32ApicBase, Ia32ApicBase, UINT32_C(0xfee00800), 0x600, UINT64_C(0xfffffff0000000ff)),
+    RVI(0x0000001c, 0x00000029, "ZERO_0000_001c_THRU_0000_0029", 0),
+    MFX(0x0000002a, "EBL_CR_POWERON", IntelEblCrPowerOn, IntelEblCrPowerOn, 0x2580000, UINT64_MAX, 0), /* value=0x2580000 */
+    RVI(0x0000002b, 0x00000039, "ZERO_0000_002b_THRU_0000_0039", 0),
+    MFO(0x0000003a, "IA32_FEATURE_CONTROL", Ia32FeatureControl), /* value=0x5 */
+    RVI(0x0000003b, 0x00000078, "ZERO_0000_003b_THRU_0000_0078", 0),
+    RVI(0x0000007a, 0x0000008a, "ZERO_0000_007a_THRU_0000_008a", 0),
+    MFN(0x0000008b, "BBL_CR_D3|BIOS_SIGN", Ia32BiosSignId, Ia32BiosSignId), /* value=0xc`00000000 */
+    RVI(0x0000008c, 0x0000009a, "ZERO_0000_008c_THRU_0000_009a", 0),
+    MFO(0x0000009b, "IA32_SMM_MONITOR_CTL", Ia32SmmMonitorCtl), /* value=0x0 */
+    RVI(0x0000009c, 0x000000c0, "ZERO_0000_009c_THRU_0000_00c0", 0),
+    RSN(0x000000c1, 0x000000c3, "IA32_PMCn", Ia32PmcN, Ia32PmcN, 0x0, UINT64_C(0xffffff0000000000), 0), /* XXX: The range ended earlier than expected! */
+    RVI(0x000000c4, 0x000000cc, "ZERO_0000_00c4_THRU_0000_00cc", 0),
+    MVO(0x000000cd, "P6_UNK_0000_00cd", 0),
+    RVI(0x000000ce, 0x000000e1, "ZERO_0000_00ce_THRU_0000_00e1", 0),
+    MFI(0x000000e2, "MSR_PKG_CST_CONFIG_CONTROL", IntelPkgCStConfigControl), /* value=0x6a204 */
+    MFX(0x000000e3, "C2_SMM_CST_MISC_INFO", IntelCore2SmmCStMiscInfo, IntelCore2SmmCStMiscInfo, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    MFX(0x000000e4, "MSR_PMG_IO_CAPTURE_BASE", IntelPmgIoCaptureBase, IntelPmgIoCaptureBase, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x0 */
+    RVI(0x000000e5, 0x000000e6, "ZERO_0000_00e5_THRU_0000_00e6", 0),
+    MFN(0x000000e7, "IA32_MPERF", Ia32MPerf, Ia32MPerf), /* value=0x2f4 */
+    MFN(0x000000e8, "IA32_APERF", Ia32APerf, Ia32APerf), /* value=0x2f2 */
+    RVI(0x000000e9, 0x000000fd, "ZERO_0000_00e9_THRU_0000_00fd", 0),
+    MFX(0x000000fe, "IA32_MTRRCAP", Ia32MtrrCap, ReadOnly, 0xd08, 0, 0), /* value=0xd08 */
+    RVI(0x000000ff, 0x0000011d, "ZERO_0000_00ff_THRU_0000_011d", 0),
+    MFX(0x0000011e, "BBL_CR_CTL3", IntelBblCrCtl3, IntelBblCrCtl3, 0, UINT64_MAX, 0), /* value=0x0 */
+    RVI(0x0000011f, 0x00000173, "ZERO_0000_011f_THRU_0000_0173", 0),
+    MFX(0x00000174, "IA32_SYSENTER_CS", Ia32SysEnterCs, Ia32SysEnterCs, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x10 */
+    MFX(0x00000175, "IA32_SYSENTER_ESP", Ia32SysEnterEsp, Ia32SysEnterEsp, 0, 0, UINT64_C(0xffff800000000000)), /* value=0x0 */
+    MFX(0x00000176, "IA32_SYSENTER_EIP", Ia32SysEnterEip, Ia32SysEnterEip, 0, 0, UINT64_C(0xffff800000000000)), /* value=0xffffffff`8166bfa0 */
+    RVI(0x00000177, 0x00000178, "ZERO_0000_0177_THRU_0000_0178", 0),
+    MFX(0x00000179, "IA32_MCG_CAP", Ia32McgCap, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFX(0x0000017a, "IA32_MCG_STATUS", Ia32McgStatus, Ia32McgStatus, 0, UINT64_C(0xfffffffffffffff8), 0), /* value=0x0 */
+    RVI(0x0000017b, 0x00000185, "ZERO_0000_017b_THRU_0000_0185", 0),
+    RSN(0x00000186, 0x00000188, "IA32_PERFEVTSELn", Ia32PerfEvtSelN, Ia32PerfEvtSelN, 0x0, UINT64_C(0xfffffffff8280000), 0), /* XXX: The range ended earlier than expected! */
+    RVI(0x00000189, 0x00000197, "ZERO_0000_0189_THRU_0000_0197", 0),
+    MFX(0x00000198, "IA32_PERF_STATUS", Ia32PerfStatus, Ia32PerfStatus, UINT64_C(0x853095408000955), UINT64_MAX, 0), /* value=0x8530954`08000955 */
+    MFX(0x00000199, "IA32_PERF_CTL", Ia32PerfCtl, Ia32PerfCtl, 0x954, 0, 0), /* Might bite. value=0x954 */
+    MFX(0x0000019a, "IA32_CLOCK_MODULATION", Ia32ClockModulation, Ia32ClockModulation, 0x2, UINT64_C(0xffffffffffffffe1), 0), /* value=0x2 */
+    MFX(0x0000019b, "IA32_THERM_INTERRUPT", Ia32ThermInterrupt, Ia32ThermInterrupt, 0, UINT64_C(0xffffffffff0000e0), 0), /* value=0x0 */
+    MFX(0x0000019c, "IA32_THERM_STATUS", Ia32ThermStatus, Ia32ThermStatus, 0x8320000, UINT64_MAX, 0), /* value=0x8320000 */
+    MFX(0x0000019d, "IA32_THERM2_CTL", Ia32Therm2Ctl, ReadOnly, 0x853, 0, 0), /* value=0x853 */
+    RVI(0x0000019e, 0x0000019f, "ZERO_0000_019e_THRU_0000_019f", 0),
+    MFX(0x000001a0, "IA32_MISC_ENABLE", Ia32MiscEnable, Ia32MiscEnable, 0x173c89, UINT64_C(0xffffffb87939c176), 0), /* value=0x173c89 */
+    RVI(0x000001a1, 0x000001d8, "ZERO_0000_01a1_THRU_0000_01d8", 0),
+    MFX(0x000001d9, "IA32_DEBUGCTL", Ia32DebugCtl, Ia32DebugCtl, 0, 0, UINT64_C(0xffffffffffffe03c)), /* value=0x1 */
+    RVI(0x000001da, 0x000001f1, "ZERO_0000_01da_THRU_0000_01f1", 0),
+    MFO(0x000001f2, "IA32_SMRR_PHYSBASE", Ia32SmrrPhysBase), /* value=0x0 */
+    MFO(0x000001f3, "IA32_SMRR_PHYSMASK", Ia32SmrrPhysMask), /* value=0x0 */
+    RVI(0x000001f4, 0x000001ff, "ZERO_0000_01f4_THRU_0000_01ff", 0),
+    MFX(0x00000200, "IA32_MTRR_PHYS_BASE0", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x0, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x6 */
+    MFX(0x00000201, "IA32_MTRR_PHYS_MASK0", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x0, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`80000800 */
+    MFX(0x00000202, "IA32_MTRR_PHYS_BASE1", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x1, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x70000000 */
+    MFX(0x00000203, "IA32_MTRR_PHYS_MASK1", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x1, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`f0000800 */
+    MFX(0x00000204, "IA32_MTRR_PHYS_BASE2", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x2, 0, UINT64_C(0xfffffff000000ff8)), /* value=0xd0000001 */
+    MFX(0x00000205, "IA32_MTRR_PHYS_MASK2", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x2, 0, UINT64_C(0xfffffff0000007ff)), /* value=0xf`ff800800 */
+    MFX(0x00000206, "IA32_MTRR_PHYS_BASE3", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x3, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000207, "IA32_MTRR_PHYS_MASK3", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x3, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x00000208, "IA32_MTRR_PHYS_BASE4", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x4, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x00000209, "IA32_MTRR_PHYS_MASK4", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x4, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x0000020a, "IA32_MTRR_PHYS_BASE5", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x5, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020b, "IA32_MTRR_PHYS_MASK5", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x5, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x0000020c, "IA32_MTRR_PHYS_BASE6", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x6, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020d, "IA32_MTRR_PHYS_MASK6", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x6, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    MFX(0x0000020e, "IA32_MTRR_PHYS_BASE7", Ia32MtrrPhysBaseN, Ia32MtrrPhysBaseN, 0x7, 0, UINT64_C(0xfffffff000000ff8)), /* value=0x0 */
+    MFX(0x0000020f, "IA32_MTRR_PHYS_MASK7", Ia32MtrrPhysMaskN, Ia32MtrrPhysMaskN, 0x7, 0, UINT64_C(0xfffffff0000007ff)), /* value=0x0 */
+    RVI(0x00000210, 0x0000024f, "ZERO_0000_0210_THRU_0000_024f", 0),
+    MFS(0x00000250, "IA32_MTRR_FIX64K_00000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix64K_00000),
+    RVI(0x00000251, 0x00000257, "ZERO_0000_0251_THRU_0000_0257", 0),
+    MFS(0x00000258, "IA32_MTRR_FIX16K_80000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_80000),
+    MFS(0x00000259, "IA32_MTRR_FIX16K_A0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix16K_A0000),
+    RVI(0x0000025a, 0x00000267, "ZERO_0000_025a_THRU_0000_0267", 0),
+    MFS(0x00000268, "IA32_MTRR_FIX4K_C0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C0000),
+    MFS(0x00000269, "IA32_MTRR_FIX4K_C8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_C8000),
+    MFS(0x0000026a, "IA32_MTRR_FIX4K_D0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D0000),
+    MFS(0x0000026b, "IA32_MTRR_FIX4K_D8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_D8000),
+    MFS(0x0000026c, "IA32_MTRR_FIX4K_E0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E0000),
+    MFS(0x0000026d, "IA32_MTRR_FIX4K_E8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_E8000),
+    MFS(0x0000026e, "IA32_MTRR_FIX4K_F0000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F0000),
+    MFS(0x0000026f, "IA32_MTRR_FIX4K_F8000", Ia32MtrrFixed, Ia32MtrrFixed, GuestMsrs.msr.MtrrFix4K_F8000),
+    RVI(0x00000270, 0x00000276, "ZERO_0000_0270_THRU_0000_0276", 0),
+    MFS(0x00000277, "IA32_PAT", Ia32Pat, Ia32Pat, Guest.msrPAT),
+    RVI(0x00000278, 0x000002fe, "ZERO_0000_0278_THRU_0000_02fe", 0),
+    MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, UINT64_C(0xfffffffffffff3f8)),
+    RVI(0x00000300, 0x00000308, "ZERO_0000_0300_THRU_0000_0308", 0),
+    RSN(0x00000309, 0x0000030a, "IA32_FIXED_CTRn", Ia32FixedCtrN, Ia32FixedCtrN, 0x0, UINT64_C(0xffffff0000000000), 0),
+    MFX(0x0000030b, "IA32_FIXED_CTR2", Ia32FixedCtrN, Ia32FixedCtrN, 0x2, UINT64_C(0xfffff8020a068061), 0), /* value=0x2d4 */
+    RVI(0x0000030c, 0x0000038c, "ZERO_0000_030c_THRU_0000_038c", 0),
+    MFX(0x0000038d, "IA32_FIXED_CTR_CTRL", Ia32FixedCtrCtrl, Ia32FixedCtrCtrl, 0, UINT64_C(0xfffffffffffff444), 0), /* value=0x0 */
+    MFX(0x0000038e, "IA32_PERF_GLOBAL_STATUS", Ia32PerfGlobalStatus, ReadOnly, 0, 0, 0), /* value=0x0 */
+    MFN(0x0000038f, "IA32_PERF_GLOBAL_CTRL", Ia32PerfGlobalCtrl, Ia32PerfGlobalCtrl), /* value=0xffffffff`ffffffff */
+    RVI(0x00000390, 0x0000047f, "ZERO_0000_0390_THRU_0000_047f", 0),
+    MFX(0x00000480, "IA32_VMX_BASIC", Ia32VmxBase, ReadOnly, UINT64_C(0x1a040000000007), 0, 0), /* value=0x1a0400`00000007 */
+    MFX(0x00000481, "IA32_VMX_PINBASED_CTLS", Ia32VmxPinbasedCtls, ReadOnly, UINT64_C(0x3f00000016), 0, 0), /* value=0x3f`00000016 */
+    MFX(0x00000482, "IA32_VMX_PROCBASED_CTLS", Ia32VmxProcbasedCtls, ReadOnly, UINT64_C(0x77f9fffe0401e172), 0, 0), /* value=0x77f9fffe`0401e172 */
+    MFX(0x00000483, "IA32_VMX_EXIT_CTLS", Ia32VmxExitCtls, ReadOnly, UINT64_C(0x3efff00036dff), 0, 0), /* value=0x3efff`00036dff */
+    MFX(0x00000484, "IA32_VMX_ENTRY_CTLS", Ia32VmxEntryCtls, ReadOnly, UINT64_C(0x1fff000011ff), 0, 0), /* value=0x1fff`000011ff */
+    MFX(0x00000485, "IA32_VMX_MISC", Ia32VmxMisc, ReadOnly, 0x403c0, 0, 0), /* value=0x403c0 */
+    MFX(0x00000486, "IA32_VMX_CR0_FIXED0", Ia32VmxCr0Fixed0, ReadOnly, UINT32_C(0x80000021), 0, 0), /* value=0x80000021 */
+    MFX(0x00000487, "IA32_VMX_CR0_FIXED1", Ia32VmxCr0Fixed1, ReadOnly, UINT32_MAX, 0, 0), /* value=0xffffffff */
+    MFX(0x00000488, "IA32_VMX_CR4_FIXED0", Ia32VmxCr4Fixed0, ReadOnly, 0x2000, 0, 0), /* value=0x2000 */
+    MFX(0x00000489, "IA32_VMX_CR4_FIXED1", Ia32VmxCr4Fixed1, ReadOnly, 0x27ff, 0, 0), /* value=0x27ff */
+    MFX(0x0000048a, "IA32_VMX_VMCS_ENUM", Ia32VmxVmcsEnum, ReadOnly, 0x2c, 0, 0), /* value=0x2c */
+    RVI(0x0000048b, 0x000005ff, "ZERO_0000_048b_THRU_0000_05ff", 0),
+    MFN(0x00000600, "IA32_DS_AREA", Ia32DsArea, Ia32DsArea), /* value=0x0 */
+    RVI(0x00000601, 0x00001106, "ZERO_0000_0601_THRU_0000_1106", 0),
+    MVI(0x00001107, "VIA_UNK_0000_1107", 0x2),
+    RVI(0x00001108, 0x0000110e, "ZERO_0000_1108_THRU_0000_110e", 0),
+    MVI(0x0000110f, "VIA_UNK_0000_110f", 0x2),
+    RVI(0x00001110, 0x00001152, "ZERO_0000_1110_THRU_0000_1152", 0),
+    MVO(0x00001153, "VIA_UNK_0000_1153", 0),
+    RVI(0x00001154, 0x000011ff, "ZERO_0000_1154_THRU_0000_11ff", 0),
+    MVX(0x00001200, "VIA_UNK_0000_1200", UINT64_C(0x8863a9bfc9fbff), 0x40000, 0),
+    MVX(0x00001201, "VIA_UNK_0000_1201", UINT64_C(0x120100800), UINT64_C(0xfffffff000000000), 0),
+    MVX(0x00001202, "VIA_UNK_0000_1202", 0x3dcc, UINT64_C(0xffffffffffffc233), 0),
+    MVX(0x00001203, "VIA_UNK_0000_1203", 0x18, 0, 0),
+    MVX(0x00001204, "VIA_UNK_0000_1204", UINT64_C(0x6fd00000424), 0, 0),
+    MVX(0x00001205, "VIA_UNK_0000_1205", UINT64_C(0x9890000000001), 0, 0),
+    MVX(0x00001206, "VIA_ALT_VENDOR_EBX", 0, 0, 0),
+    MVX(0x00001207, "VIA_ALT_VENDOR_ECDX", 0, 0, 0),
+    MVX(0x00001208, "VIA_UNK_0000_1208", 0, 0, 0),
+    MVX(0x00001209, "VIA_UNK_0000_1209", 0, 0, 0),
+    MVX(0x0000120a, "VIA_UNK_0000_120a", 0, 0, 0),
+    MVX(0x0000120b, "VIA_UNK_0000_120b", 0, 0, 0),
+    MVX(0x0000120c, "VIA_UNK_0000_120c", 0, 0, 0),
+    MVX(0x0000120d, "VIA_UNK_0000_120d", 0, 0, 0),
+    MVI(0x0000120e, "VIA_UNK_0000_120e", UINT64_C(0x820007b100002080)), /* Villain? */
+    MVX(0x0000120f, "VIA_UNK_0000_120f", UINT64_C(0x200000001a000000), 0x18000000, 0),
+    MVI(0x00001210, "ZERO_0000_1210", 0),
+    MVX(0x00001211, "VIA_UNK_0000_1211", 0, 0, 0),
+    MVX(0x00001212, "VIA_UNK_0000_1212", 0, 0, 0),
+    MVX(0x00001213, "VIA_UNK_0000_1213", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVO(0x00001214, "VIA_UNK_0000_1214", UINT64_C(0x5dd89e10ffffffff)),
+    RVI(0x00001215, 0x0000121f, "ZERO_0000_1215_THRU_0000_121f", 0),
+    MVO(0x00001220, "VIA_UNK_0000_1220", 0),
+    MVO(0x00001221, "VIA_UNK_0000_1221", 0x4dd2e713),
+    RVI(0x00001222, 0x0000122f, "ZERO_0000_1222_THRU_0000_122f", 0),
+    MVX(0x00001230, "VIA_UNK_0000_1230", UINT64_C(0x5dd89e10ffffffff), UINT32_C(0xfffffd68), 0),
+    MVX(0x00001231, "VIA_UNK_0000_1231", UINT64_C(0x7f9110bdc740), 0x200, 0),
+    MVO(0x00001232, "VIA_UNK_0000_1232", UINT64_C(0x2603448430479888)),
+    MVI(0x00001233, "VIA_UNK_0000_1233", UINT64_C(0xb39acda158793c27)), /* Villain? */
+    MVX(0x00001234, "VIA_UNK_0000_1234", 0, 0, 0),
+    MVX(0x00001235, "VIA_UNK_0000_1235", 0, 0, 0),
+    MVX(0x00001236, "VIA_UNK_0000_1236", UINT64_C(0x5dd89e10ffffffff), UINT32_C(0xfffffd68), 0),
+    MVX(0x00001237, "VIA_UNK_0000_1237", UINT32_C(0xffc00026), UINT64_C(0xffffffff06000001), 0),
+    MVO(0x00001238, "VIA_UNK_0000_1238", 0x2),
+    MVI(0x00001239, "VIA_UNK_0000_1239", 0), /* Villain? */
+    RVI(0x0000123a, 0x0000123f, "ZERO_0000_123a_THRU_0000_123f", 0),
+    MVO(0x00001240, "VIA_UNK_0000_1240", 0),
+    MVO(0x00001241, "VIA_UNK_0000_1241", UINT64_C(0x5dd89e10ffffffff)),
+    MVI(0x00001242, "ZERO_0000_1242", 0),
+    MVX(0x00001243, "VIA_UNK_0000_1243", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x00001244, "ZERO_0000_1244", 0),
+    MVX(0x00001245, "VIA_UNK_0000_1245", UINT64_C(0x3020400000000064), UINT64_C(0xf000000000000000), 0),
+    MVX(0x00001246, "VIA_UNK_0000_1246", UINT64_C(0x10000000000), 0, 0),
+    MVX(0x00001247, "VIA_UNK_0000_1247", 0, 0, 0),
+    MVX(0x00001248, "VIA_UNK_0000_1248", 0, 0, 0),
+    MVI(0x00001249, "VIA_UNK_0000_1249", 0), /* Villain? */
+    MVI(0x0000124a, "VIA_UNK_0000_124a", 0), /* Villain? */
+    RVI(0x0000124b, 0x00001300, "ZERO_0000_124b_THRU_0000_1300", 0),
+    MVX(0x00001301, "VIA_UNK_0000_1301", 0, 0, 0),
+    MVX(0x00001302, "VIA_UNK_0000_1302", 0, 0, 0),
+    MVX(0x00001303, "VIA_UNK_0000_1303", 0, 0, 0),
+    MVX(0x00001304, "VIA_UNK_0000_1304", 0, 0, 0),
+    MVX(0x00001305, "VIA_UNK_0000_1305", 0, 0, 0),
+    MVX(0x00001306, "VIA_UNK_0000_1306", 0, 0, 0),
+    MVX(0x00001307, "VIA_UNK_0000_1307", 0, UINT64_C(0xffffff0000000000), 0),
+    MVX(0x00001308, "VIA_UNK_0000_1308", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001309, "VIA_UNK_0000_1309", 0, ~(uint64_t)UINT32_MAX, 0),
+    RVI(0x0000130a, 0x0000130c, "ZERO_0000_130a_THRU_0000_130c", 0),
+    MVX(0x0000130d, "VIA_UNK_0000_130d", 0, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0x0000130e, "VIA_UNK_0000_130e", UINT64_MAX, 0, 0),
+    RVI(0x0000130f, 0x00001311, "ZERO_0000_130f_THRU_0000_1311", 0),
+    MVX(0x00001312, "VIA_UNK_0000_1312", 0, 0, 0),
+    RVI(0x00001313, 0x00001314, "ZERO_0000_1313_THRU_0000_1314", 0),
+    MVX(0x00001315, "VIA_UNK_0000_1315", 0, 0, 0),
+    MVI(0x00001316, "ZERO_0000_1316", 0),
+    MVX(0x00001317, "VIA_UNK_0000_1317", 0, 0, 0),
+    MVX(0x00001318, "VIA_UNK_0000_1318", 0, 0, 0),
+    MVI(0x00001319, "ZERO_0000_1319", 0),
+    MVX(0x0000131a, "VIA_UNK_0000_131a", 0, 0, 0),
+    MVX(0x0000131b, "VIA_UNK_0000_131b", 0x3c20954, 0, 0),
+    RVI(0x0000131c, 0x00001401, "ZERO_0000_131c_THRU_0000_1401", 0),
+    MVO(0x00001402, "VIA_UNK_0000_1402", 0x148c48),
+    MVX(0x00001403, "VIA_UNK_0000_1403", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x00001404, "VIA_UNK_0000_1404", 0), /* Villain? */
+    MVI(0x00001405, "VIA_UNK_0000_1405", UINT32_C(0x80fffffc)), /* Villain? */
+    MVX(0x00001406, "VIA_UNK_0000_1406", UINT32_C(0xc842c800), ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001407, "VIA_UNK_0000_1407", UINT32_C(0x880400c0), ~(uint64_t)UINT32_MAX, 0),
+    RVI(0x00001408, 0x0000140f, "ZERO_0000_1408_THRU_0000_140f", 0),
+    MVX(0x00001410, "VIA_UNK_0000_1410", 0xfa0, UINT64_C(0xfffffffffff00000), 0),
+    MVX(0x00001411, "VIA_UNK_0000_1411", 0xa5a, UINT64_C(0xfffffffffff00000), 0),
+    MVI(0x00001412, "VIA_UNK_0000_1412", 0x4090),
+    MVI(0x00001413, "VIA_UNK_0000_1413", 0), /* Villain? */
+    MVX(0x00001414, "VIA_UNK_0000_1414", 0x5a, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x00001415, "VIA_UNK_0000_1415", 0x5a, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x00001416, "VIA_UNK_0000_1416", 0x6e, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x00001417, "VIA_UNK_0000_1417", 0x32, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x00001418, "VIA_UNK_0000_1418", 0xa, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x00001419, "VIA_UNK_0000_1419", 0x14, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000141a, "VIA_UNK_0000_141a", 0x28, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000141b, "VIA_UNK_0000_141b", 0x3c, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000141c, "VIA_UNK_0000_141c", 0x69, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000141d, "VIA_UNK_0000_141d", 0x69, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000141e, "VIA_UNK_0000_141e", 0x69, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000141f, "VIA_UNK_0000_141f", 0x32, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x00001420, "VIA_UNK_0000_1420", 0x3, UINT64_C(0xffffffffffffc000), 0),
+    MVX(0x00001421, "VIA_UNK_0000_1421", 0x1f8, UINT64_C(0xfffffffffffc0000), 0),
+    MVX(0x00001422, "VIA_UNK_0000_1422", 0x1f4, UINT64_C(0xfffffffffffc0000), 0),
+    MVI(0x00001423, "VIA_UNK_0000_1423", 0xfffb7),
+    MVI(0x00001424, "VIA_UNK_0000_1424", 0x5b6),
+    MVI(0x00001425, "VIA_UNK_0000_1425", 0x65508),
+    MVI(0x00001426, "VIA_UNK_0000_1426", 0x843b),
+    MVX(0x00001427, "VIA_UNK_0000_1427", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001428, "VIA_UNK_0000_1428", 0x1ffffff, ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001429, "VIA_UNK_0000_1429", 0, UINT64_C(0xfffffffffff00000), 0),
+    MVI(0x0000142a, "VIA_UNK_0000_142a", 0x1c85d),
+    MVO(0x0000142b, "VIA_UNK_0000_142b", 0xf7e),
+    MVI(0x0000142c, "VIA_UNK_0000_142c", 0x20080), /* Villain? */
+    MVI(0x0000142d, "ZERO_0000_142d", 0),
+    MVI(0x0000142e, "VIA_UNK_0000_142e", 0x8000000), /* Villain? */
+    MVX(0x0000142f, "VIA_UNK_0000_142f", UINT64_C(0xffe57bea2ff3fdff), 0, 0),
+    RVI(0x00001430, 0x00001433, "ZERO_0000_1430_THRU_0000_1433", 0),
+    MVX(0x00001434, "VIA_UNK_0000_1434", 0x853f0e0, UINT64_C(0xffffffff7e7b0000), 0),
+    MVI(0x00001435, "VIA_UNK_0000_1435", 0x8000838), /* Villain? */
+    MVI(0x00001436, "VIA_UNK_0000_1436", 0x200004f), /* Villain? */
+    MVX(0x00001437, "VIA_UNK_0000_1437", 0, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x00001438, "VIA_UNK_0000_1438", 0x7004801c), /* Villain? */
+    MVI(0x00001439, "ZERO_0000_1439", 0),
+    MVX(0x0000143a, "VIA_UNK_0000_143a", 0x20000, ~(uint64_t)UINT32_MAX, 0),
+    MVI(0x0000143b, "ZERO_0000_143b", 0),
+    MVX(0x0000143c, "VIA_UNK_0000_143c", 0, UINT64_C(0xfffffffffffffe00), 0),
+    MVX(0x0000143d, "VIA_UNK_0000_143d", 0, UINT64_C(0xfffffffffffffe00), 0),
+    RVI(0x0000143e, 0x0000143f, "ZERO_0000_143e_THRU_0000_143f", 0),
+    MVX(0x00001440, "VIA_UNK_0000_1440", UINT32_C(0x80e00954), ~(uint64_t)UINT32_MAX, 0),
+    MVX(0x00001441, "VIA_UNK_0000_1441", 0xf00954, UINT64_C(0xffffffff00ff7f7f), 0),
+    MVX(0x00001442, "VIA_UNK_0000_1442", 0xf00954, UINT64_C(0xffffffff00ff7f7f), 0),
+    RVI(0x00001443, 0x00001448, "ZERO_0000_1443_THRU_0000_1448", 0),
+    MVI(0x00001449, "VIA_UNK_0000_1449", UINT64_C(0xfffff7e247)),
+    RVI(0x0000144a, 0x0000144f, "ZERO_0000_144a_THRU_0000_144f", 0),
+    MVX(0x00001450, "VIA_UNK_0000_1450", 0, UINT64_C(0xffffffffffffe000), 0),
+    MVX(0x00001451, "VIA_UNK_0000_1451", 0, UINT64_C(0xffffffffff000000), 0),
+    MVX(0x00001452, "VIA_UNK_0000_1452", 0, UINT64_C(0xffffffffff000000), 0),
+    MVI(0x00001453, "VIA_UNK_0000_1453", 0x3fffffff),
+    RVI(0x00001454, 0x0000145f, "ZERO_0000_1454_THRU_0000_145f", 0),
+    MVX(0x00001460, "VIA_UNK_0000_1460", 0, UINT64_C(0xffffffffffffffc0), 0),
+    MVX(0x00001461, "VIA_UNK_0000_1461", 0x7b, UINT64_C(0xffffffffffffff00), 0),
+    MVX(0x00001462, "VIA_UNK_0000_1462", 0x76, UINT64_C(0xffffffffffffff00), 0),
+    MVI(0x00001463, "VIA_UNK_0000_1463", 0x4a),
+    MVI(0x00001464, "ZERO_0000_1464", 0),
+    MVI(0x00001465, "VIA_UNK_0000_1465", 0xc6),
+    MVI(0x00001466, "VIA_UNK_0000_1466", UINT64_C(0x800000053)),
+    RVI(0x00001467, 0x0000146f, "ZERO_0000_1467_THRU_0000_146f", 0),
+    MVX(0x00001470, "VIA_UNK_0000_1470", UINT64_C(0x5dd89e10ffffffff), UINT32_C(0xfffffd68), 0),
+    MVI(0x00001471, "VIA_UNK_0000_1471", 0x2a000000),
+    RVI(0x00001472, 0x0000147f, "ZERO_0000_1472_THRU_0000_147f", 0),
+    MVI(0x00001480, "VIA_UNK_0000_1480", 0x3907),
+    MVI(0x00001481, "VIA_UNK_0000_1481", 0x12c0),
+    MVI(0x00001482, "VIA_UNK_0000_1482", 0x320),
+    MVI(0x00001483, "VIA_UNK_0000_1483", 0x3),
+    MVI(0x00001484, "VIA_UNK_0000_1484", 0x1647),
+    MVI(0x00001485, "VIA_UNK_0000_1485", 0x3b7),
+    MVI(0x00001486, "VIA_UNK_0000_1486", 0x443),
+    RVI(0x00001487, 0x0000148f, "ZERO_0000_1487_THRU_0000_148f", 0),
+    MVX(0x00001490, "VIA_UNK_0000_1490", 0xf5, UINT64_C(0xffffffffffffc000), 0),
+    MVX(0x00001491, "VIA_UNK_0000_1491", 0x200, UINT64_C(0xffffffffff000000), 0),
+    MVX(0x00001492, "VIA_UNK_0000_1492", 0, UINT64_C(0xffffffffff000000), 0),
+    MVX(0x00001493, "VIA_UNK_0000_1493", 0x4, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0x00001494, "VIA_UNK_0000_1494", 0x100, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0x00001495, "VIA_UNK_0000_1495", 0x100, UINT64_C(0xffffffffff000000), 0),
+    MVX(0x00001496, "VIA_UNK_0000_1496", 0x8, UINT64_C(0xffffffffffff0000), 0),
+    MVX(0x00001497, "VIA_UNK_0000_1497", 0, UINT64_C(0xffffffffff000000), 0),
+    MVX(0x00001498, "VIA_UNK_0000_1498", 0xffffff, UINT64_C(0xfffffffffffffe3c), 0),
+    MVI(0x00001499, "VIA_UNK_0000_1499", 0x2c5),
+    MVI(0x0000149a, "VIA_UNK_0000_149a", 0x1c1),
+    MVI(0x0000149b, "VIA_UNK_0000_149b", 0x2c5a),
+    MVI(0x0000149c, "VIA_UNK_0000_149c", 0x1c8f),
+    RVI(0x0000149d, 0x0000149e, "ZERO_0000_149d_THRU_0000_149e", 0),
+    MVI(0x0000149f, "VIA_UNK_0000_149f", 0x1c9),
+    RVI(0x000014a0, 0x00001522, "ZERO_0000_14a0_THRU_0000_1522", 0),
+    MFN(0x00001523, "VIA_UNK_0000_1523", WriteOnly, IgnoreWrite),
+    RVI(0x00001524, 0x00003179, "ZERO_0000_1524_THRU_0000_3179", 0),
+    MVO(0x0000317a, "VIA_UNK_0000_317a", UINT64_C(0x139f29749595b8)),
+    MVO(0x0000317b, "VIA_UNK_0000_317b", UINT64_C(0x5dd89e10ffffffff)),
+    MVI(0x0000317c, "ZERO_0000_317c", 0),
+    MFN(0x0000317d, "VIA_UNK_0000_317d", WriteOnly, IgnoreWrite),
+    MFN(0x0000317e, "VIA_UNK_0000_317e", WriteOnly, IgnoreWrite),
+    MVI(0x0000317f, "VIA_UNK_0000_317f", 0), /* Villain? */
+    RVI(0x00003180, 0x00003fff, "ZERO_0000_3180_THRU_0000_3fff", 0),
+    RVI(0x40000000, 0x40003fff, "ZERO_4000_0000_THRU_4000_3fff", 0),
+    RVI(0x80000000, 0x80000197, "ZERO_8000_0000_THRU_8000_0197", 0),
+    RVI(0x80000199, 0x80003fff, "ZERO_8000_0199_THRU_8000_3fff", 0),
+    RVI(0xc0000000, 0xc000007f, "ZERO_c000_0000_THRU_c000_007f", 0),
+    MFX(0xc0000080, "AMD64_EFER", Amd64Efer, Amd64Efer, 0xd01, 0x400, UINT64_C(0xffffffffffffd2fe)),
+    MFN(0xc0000081, "AMD64_STAR", Amd64SyscallTarget, Amd64SyscallTarget), /* value=0x230010`00000000 */
+    MFN(0xc0000082, "AMD64_STAR64", Amd64LongSyscallTarget, Amd64LongSyscallTarget), /* value=0xffffffff`81669af0 */
+    MFN(0xc0000083, "AMD64_STARCOMPAT", Amd64CompSyscallTarget, Amd64CompSyscallTarget), /* value=0xffffffff`8166c1d0 */
+    MFX(0xc0000084, "AMD64_SYSCALL_FLAG_MASK", Amd64SyscallFlagMask, Amd64SyscallFlagMask, 0, ~(uint64_t)UINT32_MAX, 0), /* value=0x3700 */
+    RVI(0xc0000085, 0xc00000ff, "ZERO_c000_0085_THRU_c000_00ff", 0),
+    MFN(0xc0000100, "AMD64_FS_BASE", Amd64FsBase, Amd64FsBase), /* value=0x7f91`10bdc740 */
+    MFN(0xc0000101, "AMD64_GS_BASE", Amd64GsBase, Amd64GsBase), /* value=0xffff8800`6fd80000 */
+    MFN(0xc0000102, "AMD64_KERNEL_GS_BASE", Amd64KernelGsBase, Amd64KernelGsBase), /* value=0x0 */
+    RVI(0xc0000104, 0xc0003fff, "ZERO_c000_0104_THRU_c000_3fff", 0),
+};
+#endif /* !CPUM_DB_STANDALONE */
+
+
+/**
+ * Database entry for VIA QuadCore L4700 @ 1.2+ GHz.
+ */
+static CPUMDBENTRY const g_Entry_VIA_QuadCore_L4700_1_2_GHz = 
+{
+    /*.pszName          = */ "VIA QuadCore L4700 1.2+ GHz",
+    /*.pszFullName      = */ "VIA QuadCore L4700 @ 1.2+ GHz",
+    /*.enmVendor        = */ CPUMCPUVENDOR_VIA,
+    /*.uFamily          = */ 6,
+    /*.uModel           = */ 15,
+    /*.uStepping        = */ 13,
+    /*.enmMicroarch     = */ kCpumMicroarch_VIA_Isaiah,
+    /*.fFlags           = */ 0,
+    /*.cMaxPhysAddrWidth= */ 36,
+    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_VIA_QuadCore_L4700_1_2_GHz),
+    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_VIA_QuadCore_L4700_1_2_GHz)),
+    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_DEFAULTS,
+    /*.DefUnknownCpuId  = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    /*.fMsrMask         = */ UINT32_MAX,
+    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_VIA_QuadCore_L4700_1_2_GHz)),
+    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_VIA_QuadCore_L4700_1_2_GHz),
+};
+
+#endif /* !VBOX_DB_VIA_QuadCore_L4700_1_2_GHz */
+
diff --git a/src/VBox/VMM/VMMRC/SELMRC.cpp b/src/VBox/VMM/VMMRC/SELMRC.cpp
index 7bc28e7..65367f3 100644
--- a/src/VBox/VMM/VMMRC/SELMRC.cpp
+++ b/src/VBox/VMM/VMMRC/SELMRC.cpp
@@ -148,7 +148,8 @@ static VBOXSTRICTRC selmRCSyncGDTEntry(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegF
                     Log(("GDT write to selector in %s register %04X (now stale)\n", g_aszSRegNms[iSReg], paSReg[iSReg].Sel));
                     paSReg[iSReg].fFlags |= CPUMSELREG_FLAGS_STALE;
                     VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3); /* paranoia */
-                    rcStrict = VINF_EM_RESCHEDULE_REM;
+                    /* rcStrict = VINF_EM_RESCHEDULE_REM; - bad idea if we're in a patch. */
+                    rcStrict = VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT;
                 }
                 else if (paSReg[iSReg].fFlags & CPUMSELREG_FLAGS_STALE)
                 {
@@ -287,6 +288,9 @@ VMMRCDECL(int) selmRCGuestGDTWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTX
 
                 if (rc2 == VINF_SUCCESS || rc2 == VINF_EM_RESCHEDULE_REM)
                 {
+                    /* VINF_EM_RESCHEDULE_REM - bad idea if we're in a patch. */
+                    if (rc2 == VINF_EM_RESCHEDULE_REM)
+                        rc = VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT;
                     STAM_COUNTER_INC(&pVM->selm.s.StatRCWriteGuestGDTHandled);
                     return rc;
                 }
diff --git a/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp b/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
index 9e0224e..3587db6 100644
--- a/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
+++ b/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
@@ -1451,3 +1451,19 @@ DECLCALLBACK(int) trpmRCTrapInGeneric(PVM pVM, PCPUMCTXCORE pRegFrame, uintptr_t
     return VERR_TRPM_IPE_3;
 }
 
+
+/**
+ * Generic hyper trap handler that sets the EIP to @a uUser.
+ *
+ * @returns VBox status code.  (Anything but VINF_SUCCESS will cause guru.)
+ * @param   pVM         Pointer to the cross context VM structure.
+ * @param   pRegFrame   Pointer to the register frame (within VM)
+ * @param   uUser       The user arg, which should be the new EIP address.
+ */
+extern "C" DECLCALLBACK(int) TRPMRCTrapHyperHandlerSetEIP(PVM pVM, PCPUMCTXCORE pRegFrame, uintptr_t uUser)
+{
+    AssertReturn(MMHyperIsInsideArea(pVM, uUser), VERR_TRPM_IPE_3);
+    pRegFrame->eip = uUser;
+    return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/VMM/VMMRC/VMMRC.cpp b/src/VBox/VMM/VMMRC/VMMRC.cpp
index 24a8f2c..06e2003 100644
--- a/src/VBox/VMM/VMMRC/VMMRC.cpp
+++ b/src/VBox/VMM/VMMRC/VMMRC.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -47,6 +47,8 @@ extern "C" DECLIMPORT(RTLOGGERRC)   g_RelLogger;
 static int vmmGCTest(PVM pVM, unsigned uOperation, unsigned uArg);
 static DECLCALLBACK(int) vmmGCTestTmpPFHandler(PVM pVM, PCPUMCTXCORE pRegFrame);
 static DECLCALLBACK(int) vmmGCTestTmpPFHandlerCorruptFS(PVM pVM, PCPUMCTXCORE pRegFrame);
+DECLASM(bool)   vmmRCSafeMsrRead(uint32_t uMsr, uint64_t *pu64Value);
+DECLASM(bool)   vmmRCSafeMsrWrite(uint32_t uMsr, uint64_t u64Value);
 
 
 
@@ -343,6 +345,82 @@ static int vmmGCTest(PVM pVM, unsigned uOperation, unsigned uArg)
 }
 
 
+
+/**
+ * Reads a range of MSRs.
+ *
+ * This is called directly via VMMR3CallRC.
+ *
+ * @returns VBox status code.
+ * @param   pVM             The VM handle.
+ * @param   uMsr            The MSR to start at.
+ * @param   cMsrs           The number of MSRs to read.
+ * @param   paResults       Where to store the results.  This must be large
+ *                          enough to hold at least @a cMsrs result values.
+ */
+extern "C" VMMRCDECL(int)
+VMMRCTestReadMsrs(PVM pVM, uint32_t uMsr, uint32_t cMsrs, PVMMTESTMSRENTRY paResults)
+{
+    AssertReturn(cMsrs <= 16384, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(paResults, VERR_INVALID_POINTER);
+    ASMIntEnable(); /* Run with interrupts enabled, so we can query more MSRs in one block. */
+
+    for (uint32_t i = 0; i < cMsrs; i++, uMsr++)
+    {
+        if (vmmRCSafeMsrRead(uMsr, &paResults[i].uValue))
+            paResults[i].uMsr = uMsr;
+        else
+            paResults[i].uMsr = UINT64_MAX;
+    }
+
+    ASMIntDisable();
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Tries to write the given value to an MSR, returns the effect and restors the
+ * original value.
+ *
+ * This is called directly via VMMR3CallRC.
+ *
+ * @returns VBox status code.
+ * @param   pVM             The VM handle.
+ * @param   uMsr            The MSR to start at.
+ * @param   u32ValueLow     The low part of the value to write.
+ * @param   u32ValueHi      The high part of the value to write.
+ * @param   puValueBefore   The value before writing.
+ * @param   puValueAfter    The value read back after writing.
+ */
+extern "C" VMMRCDECL(int)
+VMMRCTestTestWriteMsr(PVM pVM, uint32_t uMsr, uint32_t u32ValueLow, uint32_t u32ValueHi,
+                      uint64_t *puValueBefore, uint64_t *puValueAfter)
+{
+    AssertPtrReturn(puValueBefore, VERR_INVALID_POINTER);
+    AssertPtrReturn(puValueAfter, VERR_INVALID_POINTER);
+    ASMIntDisable();
+
+    int      rc           = VINF_SUCCESS;
+    uint64_t uValueBefore = UINT64_MAX;
+    uint64_t uValueAfter  = UINT64_MAX;
+    if (vmmRCSafeMsrRead(uMsr, &uValueBefore))
+    {
+        if (!vmmRCSafeMsrWrite(uMsr, RT_MAKE_U64(u32ValueLow, u32ValueHi)))
+            rc = VERR_WRITE_PROTECT;
+        if (!vmmRCSafeMsrRead(uMsr, &uValueAfter) && RT_SUCCESS(rc))
+            rc = VERR_READ_ERROR;
+        vmmRCSafeMsrWrite(uMsr, uValueBefore);
+    }
+    else
+        rc = VERR_ACCESS_DENIED;
+
+    *puValueBefore = uValueBefore;
+    *puValueAfter  = uValueAfter;
+    return rc;
+}
+
+
+
 /**
  * Temporary \#PF trap handler for the \#PF test case.
  *
diff --git a/src/VBox/VMM/VMMRC/VMMRCA.asm b/src/VBox/VMM/VMMRC/VMMRCA.asm
index 106e08e..ad523a4 100644
--- a/src/VBox/VMM/VMMRC/VMMRCA.asm
+++ b/src/VBox/VMM/VMMRC/VMMRCA.asm
@@ -23,6 +23,7 @@
 %include "VBox/sup.mac"
 %include "VBox/vmm/vm.mac"
 %include "VMMInternal.mac"
+%include "VMMRC.mac"
 
 
 ;*******************************************************************************
@@ -56,6 +57,7 @@ extern IMPNAME(g_Logger)
 extern IMPNAME(g_RelLogger)
 extern NAME(RTLogLogger)
 extern NAME(vmmRCProbeFireHelper)
+extern NAME(TRPMRCTrapHyperHandlerSetEIP)
 
 
 BEGINCODE
@@ -222,6 +224,89 @@ ENDPROC vmmGCTestTrap0e
 
 
 ;;
+; Safely reads an MSR.
+; @returns  boolean
+; @param    uMsr        The MSR to red.
+; @param    pu64Value   Where to return the value on success.
+;
+GLOBALNAME vmmRCSafeMsrRead
+    push    ebp
+    mov     ebp, esp
+    pushf
+    cli
+    push    esi
+    push    edi
+    push    ebx
+    push    ebp
+
+    mov     ecx, [ebp + 8]              ; The MSR to read.
+    mov     eax, 0deadbeefh
+    mov     edx, 0deadbeefh
+
+TRPM_GP_HANDLER NAME(TRPMRCTrapHyperHandlerSetEIP), .trapped
+    rdmsr
+
+    mov     ecx, [ebp + 0ch]            ; Where to store the result.
+    mov     [ecx], eax
+    mov     [ecx + 4], edx
+
+    mov     eax, 1
+.return:
+    pop     ebp
+    pop     ebx
+    pop     edi
+    pop     esi
+    popf
+    leave
+    ret
+
+.trapped:
+    mov     eax, 0
+    jmp     .return
+ENDPROC vmmRCSafeMsrRead
+
+
+;;
+; Safely writes an MSR.
+; @returns  boolean
+; @param    uMsr        The MSR to red.
+; @param    u64Value    The value to write.
+;
+GLOBALNAME vmmRCSafeMsrWrite
+    push    ebp
+    mov     ebp, esp
+    pushf
+    cli
+    push    esi
+    push    edi
+    push    ebx
+    push    ebp
+
+    mov     ecx, [ebp + 8]              ; The MSR to write to.
+    mov     eax, [ebp + 12]             ; The value to write.
+    mov     edx, [ebp + 16]
+
+TRPM_GP_HANDLER NAME(TRPMRCTrapHyperHandlerSetEIP), .trapped
+    wrmsr
+
+    mov     eax, 1
+.return:
+    pop     ebp
+    pop     ebx
+    pop     edi
+    pop     esi
+    popf
+    leave
+    ret
+
+.trapped:
+    mov     eax, 0
+    jmp     .return
+ENDPROC vmmRCSafeMsrWrite
+
+
+
+;;
 ; The raw-mode context equivalent of SUPTracerFireProbe.
 ;
 ; See also SUPLibTracerA.asm.
diff --git a/src/VBox/VMM/VMMRZ/VMMRZ.cpp b/src/VBox/VMM/VMMRZ/VMMRZ.cpp
index 95a7321..e78f41f 100644
--- a/src/VBox/VMM/VMMRZ/VMMRZ.cpp
+++ b/src/VBox/VMM/VMMRZ/VMMRZ.cpp
@@ -25,6 +25,7 @@
 #include <VBox/err.h>
 
 #include <iprt/assert.h>
+#include <iprt/asm-amd64-x86.h>
 #include <iprt/string.h>
 
 
@@ -127,8 +128,12 @@ VMMRZDECL(int) VMMRZCallRing3NoCpu(PVM pVM, VMMCALLRING3 enmOperation, uint64_t
 VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu)
 {
     VMCPU_ASSERT_EMT(pVCpu);
+#if defined(LOG_ENABLED) && defined(IN_RING0)
+    RTCCUINTREG fFlags = ASMIntDisableFlags(); /* preemption consistency. */
+#endif
+
     Assert(pVCpu->vmm.s.cCallRing3Disabled < 16);
-    if (++pVCpu->vmm.s.cCallRing3Disabled == 1)
+    if (ASMAtomicIncU32(&pVCpu->vmm.s.cCallRing3Disabled) == 1) /** @todo replace with unordered variant (ASMAtomicUoIncU32). */
     {
         /** @todo it might make more sense to just disable logging here, then we
          * won't flush away important bits... but that goes both ways really. */
@@ -141,6 +146,10 @@ VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu)
 # endif
 #endif
     }
+
+#if defined(LOG_ENABLED) && defined(IN_RING0)
+    ASMSetFlags(fFlags);
+#endif
 }
 
 
@@ -153,8 +162,12 @@ VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu)
 VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPU pVCpu)
 {
     VMCPU_ASSERT_EMT(pVCpu);
+#if defined(LOG_ENABLED) && defined(IN_RING0)
+    RTCCUINTREG fFlags = ASMIntDisableFlags(); /* preemption consistency. */
+#endif
+
     Assert(pVCpu->vmm.s.cCallRing3Disabled > 0);
-    if (--pVCpu->vmm.s.cCallRing3Disabled == 0)
+    if (ASMAtomicDecU32(&pVCpu->vmm.s.cCallRing3Disabled) == 0) /** @todo replace with unordered variant (ASMAtomicUoDecU32). */
     {
 #ifdef IN_RC
         pVCpu->pVMRC->vmm.s.fRCLoggerFlushingDisabled = false;
@@ -165,6 +178,10 @@ VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPU pVCpu)
 # endif
 #endif
     }
+
+#if defined(LOG_ENABLED) && defined(IN_RING0)
+    ASMSetFlags(fFlags);
+#endif
 }
 
 
diff --git a/src/VBox/VMM/include/CPUMInternal.h b/src/VBox/VMM/include/CPUMInternal.h
index c20c94e..d9f5f6c 100644
--- a/src/VBox/VMM/include/CPUMInternal.h
+++ b/src/VBox/VMM/include/CPUMInternal.h
@@ -21,6 +21,7 @@
 #ifndef VBOX_FOR_DTRACE_LIB
 # include <VBox/cdefs.h>
 # include <VBox/types.h>
+# include <VBox/vmm/stam.h>
 # include <iprt/x86.h>
 #else
 # pragma D depends_on library x86.d
@@ -110,6 +111,670 @@
 
 
 /**
+ * MSR read functions.
+ */
+typedef enum CPUMMSRRDFN
+{
+    /** Invalid zero value. */
+    kCpumMsrRdFn_Invalid = 0,
+    /** Return the CPUMMSRRANGE::uValue. */
+    kCpumMsrRdFn_FixedValue,
+    /** Alias to the MSR range starting at the MSR given by
+     * CPUMMSRRANGE::uValue.  Must be used in pair with
+     * kCpumMsrWrFn_MsrAlias. */
+    kCpumMsrRdFn_MsrAlias,
+    /** Write only register, GP all read attempts. */
+    kCpumMsrRdFn_WriteOnly,
+
+    kCpumMsrRdFn_Ia32P5McAddr,
+    kCpumMsrRdFn_Ia32P5McType,
+    kCpumMsrRdFn_Ia32TimestampCounter,
+    kCpumMsrRdFn_Ia32ApicBase,
+    kCpumMsrRdFn_Ia32FeatureControl,
+    kCpumMsrRdFn_Ia32BiosSignId,            /**< Range value returned. */
+    kCpumMsrRdFn_Ia32SmmMonitorCtl,
+    kCpumMsrRdFn_Ia32PmcN,
+    kCpumMsrRdFn_Ia32MonitorFilterLineSize,
+    kCpumMsrRdFn_Ia32MPerf,
+    kCpumMsrRdFn_Ia32APerf,
+    kCpumMsrRdFn_Ia32MtrrCap,               /**< Takes real CPU value for reference.  */
+    kCpumMsrRdFn_Ia32MtrrPhysBaseN,         /**< Takes register number. */
+    kCpumMsrRdFn_Ia32MtrrPhysMaskN,         /**< Takes register number. */
+    kCpumMsrRdFn_Ia32MtrrFixed,             /**< Takes CPUMCPU offset. */
+    kCpumMsrRdFn_Ia32MtrrDefType,
+    kCpumMsrRdFn_Ia32Pat,
+    kCpumMsrRdFn_Ia32SysEnterCs,
+    kCpumMsrRdFn_Ia32SysEnterEsp,
+    kCpumMsrRdFn_Ia32SysEnterEip,
+    kCpumMsrRdFn_Ia32McgCap,
+    kCpumMsrRdFn_Ia32McgStatus,
+    kCpumMsrRdFn_Ia32McgCtl,
+    kCpumMsrRdFn_Ia32DebugCtl,
+    kCpumMsrRdFn_Ia32SmrrPhysBase,
+    kCpumMsrRdFn_Ia32SmrrPhysMask,
+    kCpumMsrRdFn_Ia32PlatformDcaCap,
+    kCpumMsrRdFn_Ia32CpuDcaCap,
+    kCpumMsrRdFn_Ia32Dca0Cap,
+    kCpumMsrRdFn_Ia32PerfEvtSelN,           /**< Range value indicates the register number. */
+    kCpumMsrRdFn_Ia32PerfStatus,            /**< Range value returned. */
+    kCpumMsrRdFn_Ia32PerfCtl,               /**< Range value returned. */
+    kCpumMsrRdFn_Ia32FixedCtrN,             /**< Takes register number of start of range. */
+    kCpumMsrRdFn_Ia32PerfCapabilities,      /**< Takes reference value. */
+    kCpumMsrRdFn_Ia32FixedCtrCtrl,
+    kCpumMsrRdFn_Ia32PerfGlobalStatus,      /**< Takes reference value. */
+    kCpumMsrRdFn_Ia32PerfGlobalCtrl,
+    kCpumMsrRdFn_Ia32PerfGlobalOvfCtrl,
+    kCpumMsrRdFn_Ia32PebsEnable,
+    kCpumMsrRdFn_Ia32ClockModulation,       /**< Range value returned. */
+    kCpumMsrRdFn_Ia32ThermInterrupt,        /**< Range value returned. */
+    kCpumMsrRdFn_Ia32ThermStatus,           /**< Range value returned. */
+    kCpumMsrRdFn_Ia32Therm2Ctl,             /**< Range value returned. */
+    kCpumMsrRdFn_Ia32MiscEnable,            /**< Range value returned. */
+    kCpumMsrRdFn_Ia32McCtlStatusAddrMiscN,  /**< Takes bank number. */
+    kCpumMsrRdFn_Ia32McNCtl2,               /**< Takes register number of start of range. */
+    kCpumMsrRdFn_Ia32DsArea,
+    kCpumMsrRdFn_Ia32TscDeadline,
+    kCpumMsrRdFn_Ia32X2ApicN,
+    kCpumMsrRdFn_Ia32DebugInterface,
+    kCpumMsrRdFn_Ia32VmxBase,               /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxPinbasedCtls,       /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxProcbasedCtls,      /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxExitCtls,           /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxEntryCtls,          /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxMisc,               /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxCr0Fixed0,          /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxCr0Fixed1,          /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxCr4Fixed0,          /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxCr4Fixed1,          /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxVmcsEnum,           /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxProcBasedCtls2,     /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxEptVpidCap,         /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxTruePinbasedCtls,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxTrueProcbasedCtls,  /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxTrueExitCtls,       /**< Takes real value as reference. */
+    kCpumMsrRdFn_Ia32VmxTrueEntryCtls,      /**< Takes real value as reference. */
+
+    kCpumMsrRdFn_Amd64Efer,
+    kCpumMsrRdFn_Amd64SyscallTarget,
+    kCpumMsrRdFn_Amd64LongSyscallTarget,
+    kCpumMsrRdFn_Amd64CompSyscallTarget,
+    kCpumMsrRdFn_Amd64SyscallFlagMask,
+    kCpumMsrRdFn_Amd64FsBase,
+    kCpumMsrRdFn_Amd64GsBase,
+    kCpumMsrRdFn_Amd64KernelGsBase,
+    kCpumMsrRdFn_Amd64TscAux,
+
+    kCpumMsrRdFn_IntelEblCrPowerOn,
+    kCpumMsrRdFn_IntelP4EbcHardPowerOn,
+    kCpumMsrRdFn_IntelP4EbcSoftPowerOn,
+    kCpumMsrRdFn_IntelP4EbcFrequencyId,
+    kCpumMsrRdFn_IntelPlatformInfo100MHz,
+    kCpumMsrRdFn_IntelPlatformInfo133MHz,
+    kCpumMsrRdFn_IntelFlexRatio100MHz,      /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelFlexRatio133MHz,      /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelPkgCStConfigControl,
+    kCpumMsrRdFn_IntelPmgIoCaptureBase,
+    kCpumMsrRdFn_IntelLastBranchFromToN,
+    kCpumMsrRdFn_IntelLastBranchFromN,
+    kCpumMsrRdFn_IntelLastBranchToN,
+    kCpumMsrRdFn_IntelLastBranchTos,
+    kCpumMsrRdFn_IntelBblCrCtl,
+    kCpumMsrRdFn_IntelBblCrCtl3,
+    kCpumMsrRdFn_IntelI7TemperatureTarget,  /**< Range value returned. */
+    kCpumMsrRdFn_IntelI7MsrOffCoreResponseN,/**< Takes register number. */
+    kCpumMsrRdFn_IntelI7MiscPwrMgmt,
+    kCpumMsrRdFn_IntelP6CrN,
+    kCpumMsrRdFn_IntelCpuId1FeatureMaskEcdx,
+    kCpumMsrRdFn_IntelCpuId1FeatureMaskEax,
+    kCpumMsrRdFn_IntelCpuId80000001FeatureMaskEcdx,
+    kCpumMsrRdFn_IntelI7SandyAesNiCtl,
+    kCpumMsrRdFn_IntelI7TurboRatioLimit,    /**< Returns range value. */
+    kCpumMsrRdFn_IntelI7LbrSelect,
+    kCpumMsrRdFn_IntelI7SandyErrorControl,
+    kCpumMsrRdFn_IntelI7VirtualLegacyWireCap,/**< Returns range value. */
+    kCpumMsrRdFn_IntelI7PowerCtl,
+    kCpumMsrRdFn_IntelI7SandyPebsNumAlt,
+    kCpumMsrRdFn_IntelI7PebsLdLat,
+    kCpumMsrRdFn_IntelI7PkgCnResidencyN,     /**< Takes C-state number. */
+    kCpumMsrRdFn_IntelI7CoreCnResidencyN,    /**< Takes C-state number. */
+    kCpumMsrRdFn_IntelI7SandyVrCurrentConfig,/**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7SandyVrMiscConfig,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7SandyRaplPowerUnit,  /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7SandyPkgCnIrtlN,     /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7SandyPkgC2Residency, /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPkgPowerLimit,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPkgEnergyStatus, /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPkgPerfStatus,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPkgPowerInfo,    /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplDramPowerLimit,  /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplDramEnergyStatus,/**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplDramPerfStatus,  /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplDramPowerInfo,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp0PowerLimit,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp0EnergyStatus, /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp0Policy,       /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp0PerfStatus,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp1PowerLimit,   /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp1EnergyStatus, /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7RaplPp1Policy,       /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7IvyConfigTdpNominal, /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7IvyConfigTdpLevel1,  /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7IvyConfigTdpLevel2,  /**< Takes real value as reference. */
+    kCpumMsrRdFn_IntelI7IvyConfigTdpControl,
+    kCpumMsrRdFn_IntelI7IvyTurboActivationRatio,
+    kCpumMsrRdFn_IntelI7UncPerfGlobalCtrl,
+    kCpumMsrRdFn_IntelI7UncPerfGlobalStatus,
+    kCpumMsrRdFn_IntelI7UncPerfGlobalOvfCtrl,
+    kCpumMsrRdFn_IntelI7UncPerfFixedCtrCtrl,
+    kCpumMsrRdFn_IntelI7UncPerfFixedCtr,
+    kCpumMsrRdFn_IntelI7UncCBoxConfig,
+    kCpumMsrRdFn_IntelI7UncArbPerfCtrN,
+    kCpumMsrRdFn_IntelI7UncArbPerfEvtSelN,
+    kCpumMsrRdFn_IntelCore2EmttmCrTablesN,  /**< Range value returned. */
+    kCpumMsrRdFn_IntelCore2SmmCStMiscInfo,
+    kCpumMsrRdFn_IntelCore1ExtConfig,
+    kCpumMsrRdFn_IntelCore1DtsCalControl,
+    kCpumMsrRdFn_IntelCore2PeciControl,
+
+    kCpumMsrRdFn_P6LastBranchFromIp,
+    kCpumMsrRdFn_P6LastBranchToIp,
+    kCpumMsrRdFn_P6LastIntFromIp,
+    kCpumMsrRdFn_P6LastIntToIp,
+
+    kCpumMsrRdFn_AmdFam15hTscRate,
+    kCpumMsrRdFn_AmdFam15hLwpCfg,
+    kCpumMsrRdFn_AmdFam15hLwpCbAddr,
+    kCpumMsrRdFn_AmdFam10hMc4MiscN,
+    kCpumMsrRdFn_AmdK8PerfCtlN,
+    kCpumMsrRdFn_AmdK8PerfCtrN,
+    kCpumMsrRdFn_AmdK8SysCfg,               /**< Range value returned. */
+    kCpumMsrRdFn_AmdK8HwCr,
+    kCpumMsrRdFn_AmdK8IorrBaseN,
+    kCpumMsrRdFn_AmdK8IorrMaskN,
+    kCpumMsrRdFn_AmdK8TopOfMemN,
+    kCpumMsrRdFn_AmdK8NbCfg1,
+    kCpumMsrRdFn_AmdK8McXcptRedir,
+    kCpumMsrRdFn_AmdK8CpuNameN,
+    kCpumMsrRdFn_AmdK8HwThermalCtrl,        /**< Range value returned. */
+    kCpumMsrRdFn_AmdK8SwThermalCtrl,
+    kCpumMsrRdFn_AmdK8FidVidControl,        /**< Range value returned. */
+    kCpumMsrRdFn_AmdK8FidVidStatus,         /**< Range value returned. */
+    kCpumMsrRdFn_AmdK8McCtlMaskN,
+    kCpumMsrRdFn_AmdK8SmiOnIoTrapN,
+    kCpumMsrRdFn_AmdK8SmiOnIoTrapCtlSts,
+    kCpumMsrRdFn_AmdK8IntPendingMessage,
+    kCpumMsrRdFn_AmdK8SmiTriggerIoCycle,
+    kCpumMsrRdFn_AmdFam10hMmioCfgBaseAddr,
+    kCpumMsrRdFn_AmdFam10hTrapCtlMaybe,
+    kCpumMsrRdFn_AmdFam10hPStateCurLimit,   /**< Returns range value. */
+    kCpumMsrRdFn_AmdFam10hPStateControl,    /**< Returns range value. */
+    kCpumMsrRdFn_AmdFam10hPStateStatus,     /**< Returns range value. */
+    kCpumMsrRdFn_AmdFam10hPStateN,          /**< Returns range value. This isn't an register index! */
+    kCpumMsrRdFn_AmdFam10hCofVidControl,    /**< Returns range value. */
+    kCpumMsrRdFn_AmdFam10hCofVidStatus,     /**< Returns range value. */
+    kCpumMsrRdFn_AmdFam10hCStateIoBaseAddr,
+    kCpumMsrRdFn_AmdFam10hCpuWatchdogTimer,
+    kCpumMsrRdFn_AmdK8SmmBase,
+    kCpumMsrRdFn_AmdK8SmmAddr,
+    kCpumMsrRdFn_AmdK8SmmMask,
+    kCpumMsrRdFn_AmdK8VmCr,
+    kCpumMsrRdFn_AmdK8IgnNe,
+    kCpumMsrRdFn_AmdK8SmmCtl,
+    kCpumMsrRdFn_AmdK8VmHSavePa,
+    kCpumMsrRdFn_AmdFam10hVmLockKey,
+    kCpumMsrRdFn_AmdFam10hSmmLockKey,
+    kCpumMsrRdFn_AmdFam10hLocalSmiStatus,
+    kCpumMsrRdFn_AmdFam10hOsVisWrkIdLength,
+    kCpumMsrRdFn_AmdFam10hOsVisWrkStatus,
+    kCpumMsrRdFn_AmdFam16hL2IPerfCtlN,
+    kCpumMsrRdFn_AmdFam16hL2IPerfCtrN,
+    kCpumMsrRdFn_AmdFam15hNorthbridgePerfCtlN,
+    kCpumMsrRdFn_AmdFam15hNorthbridgePerfCtrN,
+    kCpumMsrRdFn_AmdK7MicrocodeCtl,         /**< Returns range value. */
+    kCpumMsrRdFn_AmdK7ClusterIdMaybe,       /**< Returns range value. */
+    kCpumMsrRdFn_AmdK8CpuIdCtlStd07hEbax,
+    kCpumMsrRdFn_AmdK8CpuIdCtlStd06hEcx,
+    kCpumMsrRdFn_AmdK8CpuIdCtlStd01hEdcx,
+    kCpumMsrRdFn_AmdK8CpuIdCtlExt01hEdcx,
+    kCpumMsrRdFn_AmdK8PatchLevel,           /**< Returns range value. */
+    kCpumMsrRdFn_AmdK7DebugStatusMaybe,
+    kCpumMsrRdFn_AmdK7BHTraceBaseMaybe,
+    kCpumMsrRdFn_AmdK7BHTracePtrMaybe,
+    kCpumMsrRdFn_AmdK7BHTraceLimitMaybe,
+    kCpumMsrRdFn_AmdK7HardwareDebugToolCfgMaybe,
+    kCpumMsrRdFn_AmdK7FastFlushCountMaybe,
+    kCpumMsrRdFn_AmdK7NodeId,
+    kCpumMsrRdFn_AmdK7DrXAddrMaskN,      /**< Takes register index. */
+    kCpumMsrRdFn_AmdK7Dr0DataMatchMaybe,
+    kCpumMsrRdFn_AmdK7Dr0DataMaskMaybe,
+    kCpumMsrRdFn_AmdK7LoadStoreCfg,
+    kCpumMsrRdFn_AmdK7InstrCacheCfg,
+    kCpumMsrRdFn_AmdK7DataCacheCfg,
+    kCpumMsrRdFn_AmdK7BusUnitCfg,
+    kCpumMsrRdFn_AmdK7DebugCtl2Maybe,
+    kCpumMsrRdFn_AmdFam15hFpuCfg,
+    kCpumMsrRdFn_AmdFam15hDecoderCfg,
+    kCpumMsrRdFn_AmdFam10hBusUnitCfg2,
+    kCpumMsrRdFn_AmdFam15hCombUnitCfg,
+    kCpumMsrRdFn_AmdFam15hCombUnitCfg2,
+    kCpumMsrRdFn_AmdFam15hCombUnitCfg3,
+    kCpumMsrRdFn_AmdFam15hExecUnitCfg,
+    kCpumMsrRdFn_AmdFam15hLoadStoreCfg2,
+    kCpumMsrRdFn_AmdFam10hIbsFetchCtl,
+    kCpumMsrRdFn_AmdFam10hIbsFetchLinAddr,
+    kCpumMsrRdFn_AmdFam10hIbsFetchPhysAddr,
+    kCpumMsrRdFn_AmdFam10hIbsOpExecCtl,
+    kCpumMsrRdFn_AmdFam10hIbsOpRip,
+    kCpumMsrRdFn_AmdFam10hIbsOpData,
+    kCpumMsrRdFn_AmdFam10hIbsOpData2,
+    kCpumMsrRdFn_AmdFam10hIbsOpData3,
+    kCpumMsrRdFn_AmdFam10hIbsDcLinAddr,
+    kCpumMsrRdFn_AmdFam10hIbsDcPhysAddr,
+    kCpumMsrRdFn_AmdFam10hIbsCtl,
+    kCpumMsrRdFn_AmdFam14hIbsBrTarget,
+
+    /** End of valid MSR read function indexes. */
+    kCpumMsrRdFn_End
+} CPUMMSRRDFN;
+
+/**
+ * MSR write functions.
+ */
+typedef enum CPUMMSRWRFN
+{
+    /** Invalid zero value. */
+    kCpumMsrWrFn_Invalid = 0,
+    /** Writes are ignored, the fWrGpMask is observed though. */
+    kCpumMsrWrFn_IgnoreWrite,
+    /** Writes cause GP(0) to be raised, the fWrGpMask should be UINT64_MAX. */
+    kCpumMsrWrFn_ReadOnly,
+    /** Alias to the MSR range starting at the MSR given by
+     * CPUMMSRRANGE::uValue.  Must be used in pair with
+     * kCpumMsrRdFn_MsrAlias. */
+    kCpumMsrWrFn_MsrAlias,
+
+    kCpumMsrWrFn_Ia32P5McAddr,
+    kCpumMsrWrFn_Ia32P5McType,
+    kCpumMsrWrFn_Ia32TimestampCounter,
+    kCpumMsrWrFn_Ia32ApicBase,
+    kCpumMsrWrFn_Ia32FeatureControl,
+    kCpumMsrWrFn_Ia32BiosSignId,
+    kCpumMsrWrFn_Ia32BiosUpdateTrigger,
+    kCpumMsrWrFn_Ia32SmmMonitorCtl,
+    kCpumMsrWrFn_Ia32PmcN,
+    kCpumMsrWrFn_Ia32MonitorFilterLineSize,
+    kCpumMsrWrFn_Ia32MPerf,
+    kCpumMsrWrFn_Ia32APerf,
+    kCpumMsrWrFn_Ia32MtrrPhysBaseN,         /**< Takes register number. */
+    kCpumMsrWrFn_Ia32MtrrPhysMaskN,         /**< Takes register number. */
+    kCpumMsrWrFn_Ia32MtrrFixed,             /**< Takes CPUMCPU offset. */
+    kCpumMsrWrFn_Ia32MtrrDefType,
+    kCpumMsrWrFn_Ia32Pat,
+    kCpumMsrWrFn_Ia32SysEnterCs,
+    kCpumMsrWrFn_Ia32SysEnterEsp,
+    kCpumMsrWrFn_Ia32SysEnterEip,
+    kCpumMsrWrFn_Ia32McgStatus,
+    kCpumMsrWrFn_Ia32McgCtl,
+    kCpumMsrWrFn_Ia32DebugCtl,
+    kCpumMsrWrFn_Ia32SmrrPhysBase,
+    kCpumMsrWrFn_Ia32SmrrPhysMask,
+    kCpumMsrWrFn_Ia32PlatformDcaCap,
+    kCpumMsrWrFn_Ia32Dca0Cap,
+    kCpumMsrWrFn_Ia32PerfEvtSelN,           /**< Range value indicates the register number. */
+    kCpumMsrWrFn_Ia32PerfStatus,
+    kCpumMsrWrFn_Ia32PerfCtl,
+    kCpumMsrWrFn_Ia32FixedCtrN,             /**< Takes register number of start of range. */
+    kCpumMsrWrFn_Ia32PerfCapabilities,
+    kCpumMsrWrFn_Ia32FixedCtrCtrl,
+    kCpumMsrWrFn_Ia32PerfGlobalStatus,
+    kCpumMsrWrFn_Ia32PerfGlobalCtrl,
+    kCpumMsrWrFn_Ia32PerfGlobalOvfCtrl,
+    kCpumMsrWrFn_Ia32PebsEnable,
+    kCpumMsrWrFn_Ia32ClockModulation,
+    kCpumMsrWrFn_Ia32ThermInterrupt,
+    kCpumMsrWrFn_Ia32ThermStatus,
+    kCpumMsrWrFn_Ia32Therm2Ctl,
+    kCpumMsrWrFn_Ia32MiscEnable,
+    kCpumMsrWrFn_Ia32McCtlStatusAddrMiscN,  /**< Takes bank number. */
+    kCpumMsrWrFn_Ia32McNCtl2,               /**< Takes register number of start of range. */
+    kCpumMsrWrFn_Ia32DsArea,
+    kCpumMsrWrFn_Ia32TscDeadline,
+    kCpumMsrWrFn_Ia32X2ApicN,
+    kCpumMsrWrFn_Ia32DebugInterface,
+
+    kCpumMsrWrFn_Amd64Efer,
+    kCpumMsrWrFn_Amd64SyscallTarget,
+    kCpumMsrWrFn_Amd64LongSyscallTarget,
+    kCpumMsrWrFn_Amd64CompSyscallTarget,
+    kCpumMsrWrFn_Amd64SyscallFlagMask,
+    kCpumMsrWrFn_Amd64FsBase,
+    kCpumMsrWrFn_Amd64GsBase,
+    kCpumMsrWrFn_Amd64KernelGsBase,
+    kCpumMsrWrFn_Amd64TscAux,
+    kCpumMsrWrFn_IntelEblCrPowerOn,
+    kCpumMsrWrFn_IntelP4EbcHardPowerOn,
+    kCpumMsrWrFn_IntelP4EbcSoftPowerOn,
+    kCpumMsrWrFn_IntelP4EbcFrequencyId,
+    kCpumMsrWrFn_IntelFlexRatio100MHz,
+    kCpumMsrWrFn_IntelFlexRatio133MHz,
+    kCpumMsrWrFn_IntelPkgCStConfigControl,
+    kCpumMsrWrFn_IntelPmgIoCaptureBase,
+    kCpumMsrWrFn_IntelLastBranchFromToN,
+    kCpumMsrWrFn_IntelLastBranchFromN,
+    kCpumMsrWrFn_IntelLastBranchToN,
+    kCpumMsrWrFn_IntelLastBranchTos,
+    kCpumMsrWrFn_IntelBblCrCtl,
+    kCpumMsrWrFn_IntelBblCrCtl3,
+    kCpumMsrWrFn_IntelI7TemperatureTarget,
+    kCpumMsrWrFn_IntelI7MsrOffCoreResponseN, /**< Takes register number. */
+    kCpumMsrWrFn_IntelI7MiscPwrMgmt,
+    kCpumMsrWrFn_IntelP6CrN,
+    kCpumMsrWrFn_IntelCpuId1FeatureMaskEcdx,
+    kCpumMsrWrFn_IntelCpuId1FeatureMaskEax,
+    kCpumMsrWrFn_IntelCpuId80000001FeatureMaskEcdx,
+    kCpumMsrWrFn_IntelI7SandyAesNiCtl,
+    kCpumMsrWrFn_IntelI7TurboRatioLimit,
+    kCpumMsrWrFn_IntelI7LbrSelect,
+    kCpumMsrWrFn_IntelI7SandyErrorControl,
+    kCpumMsrWrFn_IntelI7PowerCtl,
+    kCpumMsrWrFn_IntelI7SandyPebsNumAlt,
+    kCpumMsrWrFn_IntelI7PebsLdLat,
+    kCpumMsrWrFn_IntelI7SandyVrCurrentConfig,
+    kCpumMsrWrFn_IntelI7SandyVrMiscConfig,
+    kCpumMsrWrFn_IntelI7SandyPkgCnIrtlN,
+    kCpumMsrWrFn_IntelI7RaplPkgPowerLimit,
+    kCpumMsrWrFn_IntelI7RaplDramPowerLimit,
+    kCpumMsrWrFn_IntelI7RaplPp0PowerLimit,
+    kCpumMsrWrFn_IntelI7RaplPp0Policy,
+    kCpumMsrWrFn_IntelI7RaplPp1PowerLimit,
+    kCpumMsrWrFn_IntelI7RaplPp1Policy,
+    kCpumMsrWrFn_IntelI7IvyConfigTdpControl,
+    kCpumMsrWrFn_IntelI7IvyTurboActivationRatio,
+    kCpumMsrWrFn_IntelI7UncPerfGlobalCtrl,
+    kCpumMsrWrFn_IntelI7UncPerfGlobalStatus,
+    kCpumMsrWrFn_IntelI7UncPerfGlobalOvfCtrl,
+    kCpumMsrWrFn_IntelI7UncPerfFixedCtrCtrl,
+    kCpumMsrWrFn_IntelI7UncPerfFixedCtr,
+    kCpumMsrWrFn_IntelI7UncArbPerfCtrN,
+    kCpumMsrWrFn_IntelI7UncArbPerfEvtSelN,
+    kCpumMsrWrFn_IntelCore2EmttmCrTablesN,
+    kCpumMsrWrFn_IntelCore2SmmCStMiscInfo,
+    kCpumMsrWrFn_IntelCore1ExtConfig,
+    kCpumMsrWrFn_IntelCore1DtsCalControl,
+    kCpumMsrWrFn_IntelCore2PeciControl,
+
+    kCpumMsrWrFn_P6LastIntFromIp,
+    kCpumMsrWrFn_P6LastIntToIp,
+
+    kCpumMsrWrFn_AmdFam15hTscRate,
+    kCpumMsrWrFn_AmdFam15hLwpCfg,
+    kCpumMsrWrFn_AmdFam15hLwpCbAddr,
+    kCpumMsrWrFn_AmdFam10hMc4MiscN,
+    kCpumMsrWrFn_AmdK8PerfCtlN,
+    kCpumMsrWrFn_AmdK8PerfCtrN,
+    kCpumMsrWrFn_AmdK8SysCfg,
+    kCpumMsrWrFn_AmdK8HwCr,
+    kCpumMsrWrFn_AmdK8IorrBaseN,
+    kCpumMsrWrFn_AmdK8IorrMaskN,
+    kCpumMsrWrFn_AmdK8TopOfMemN,
+    kCpumMsrWrFn_AmdK8NbCfg1,
+    kCpumMsrWrFn_AmdK8McXcptRedir,
+    kCpumMsrWrFn_AmdK8CpuNameN,
+    kCpumMsrWrFn_AmdK8HwThermalCtrl,
+    kCpumMsrWrFn_AmdK8SwThermalCtrl,
+    kCpumMsrWrFn_AmdK8FidVidControl,
+    kCpumMsrWrFn_AmdK8McCtlMaskN,
+    kCpumMsrWrFn_AmdK8SmiOnIoTrapN,
+    kCpumMsrWrFn_AmdK8SmiOnIoTrapCtlSts,
+    kCpumMsrWrFn_AmdK8IntPendingMessage,
+    kCpumMsrWrFn_AmdK8SmiTriggerIoCycle,
+    kCpumMsrWrFn_AmdFam10hMmioCfgBaseAddr,
+    kCpumMsrWrFn_AmdFam10hTrapCtlMaybe,
+    kCpumMsrWrFn_AmdFam10hPStateControl,
+    kCpumMsrWrFn_AmdFam10hPStateStatus,
+    kCpumMsrWrFn_AmdFam10hPStateN,
+    kCpumMsrWrFn_AmdFam10hCofVidControl,
+    kCpumMsrWrFn_AmdFam10hCofVidStatus,
+    kCpumMsrWrFn_AmdFam10hCStateIoBaseAddr,
+    kCpumMsrWrFn_AmdFam10hCpuWatchdogTimer,
+    kCpumMsrWrFn_AmdK8SmmBase,
+    kCpumMsrWrFn_AmdK8SmmAddr,
+    kCpumMsrWrFn_AmdK8SmmMask,
+    kCpumMsrWrFn_AmdK8VmCr,
+    kCpumMsrWrFn_AmdK8IgnNe,
+    kCpumMsrWrFn_AmdK8SmmCtl,
+    kCpumMsrWrFn_AmdK8VmHSavePa,
+    kCpumMsrWrFn_AmdFam10hVmLockKey,
+    kCpumMsrWrFn_AmdFam10hSmmLockKey,
+    kCpumMsrWrFn_AmdFam10hLocalSmiStatus,
+    kCpumMsrWrFn_AmdFam10hOsVisWrkIdLength,
+    kCpumMsrWrFn_AmdFam10hOsVisWrkStatus,
+    kCpumMsrWrFn_AmdFam16hL2IPerfCtlN,
+    kCpumMsrWrFn_AmdFam16hL2IPerfCtrN,
+    kCpumMsrWrFn_AmdFam15hNorthbridgePerfCtlN,
+    kCpumMsrWrFn_AmdFam15hNorthbridgePerfCtrN,
+    kCpumMsrWrFn_AmdK7MicrocodeCtl,
+    kCpumMsrWrFn_AmdK7ClusterIdMaybe,
+    kCpumMsrWrFn_AmdK8CpuIdCtlStd07hEbax,
+    kCpumMsrWrFn_AmdK8CpuIdCtlStd06hEcx,
+    kCpumMsrWrFn_AmdK8CpuIdCtlStd01hEdcx,
+    kCpumMsrWrFn_AmdK8CpuIdCtlExt01hEdcx,
+    kCpumMsrWrFn_AmdK8PatchLoader,
+    kCpumMsrWrFn_AmdK7DebugStatusMaybe,
+    kCpumMsrWrFn_AmdK7BHTraceBaseMaybe,
+    kCpumMsrWrFn_AmdK7BHTracePtrMaybe,
+    kCpumMsrWrFn_AmdK7BHTraceLimitMaybe,
+    kCpumMsrWrFn_AmdK7HardwareDebugToolCfgMaybe,
+    kCpumMsrWrFn_AmdK7FastFlushCountMaybe,
+    kCpumMsrWrFn_AmdK7NodeId,
+    kCpumMsrWrFn_AmdK7DrXAddrMaskN,      /**< Takes register index. */
+    kCpumMsrWrFn_AmdK7Dr0DataMatchMaybe,
+    kCpumMsrWrFn_AmdK7Dr0DataMaskMaybe,
+    kCpumMsrWrFn_AmdK7LoadStoreCfg,
+    kCpumMsrWrFn_AmdK7InstrCacheCfg,
+    kCpumMsrWrFn_AmdK7DataCacheCfg,
+    kCpumMsrWrFn_AmdK7BusUnitCfg,
+    kCpumMsrWrFn_AmdK7DebugCtl2Maybe,
+    kCpumMsrWrFn_AmdFam15hFpuCfg,
+    kCpumMsrWrFn_AmdFam15hDecoderCfg,
+    kCpumMsrWrFn_AmdFam10hBusUnitCfg2,
+    kCpumMsrWrFn_AmdFam15hCombUnitCfg,
+    kCpumMsrWrFn_AmdFam15hCombUnitCfg2,
+    kCpumMsrWrFn_AmdFam15hCombUnitCfg3,
+    kCpumMsrWrFn_AmdFam15hExecUnitCfg,
+    kCpumMsrWrFn_AmdFam15hLoadStoreCfg2,
+    kCpumMsrWrFn_AmdFam10hIbsFetchCtl,
+    kCpumMsrWrFn_AmdFam10hIbsFetchLinAddr,
+    kCpumMsrWrFn_AmdFam10hIbsFetchPhysAddr,
+    kCpumMsrWrFn_AmdFam10hIbsOpExecCtl,
+    kCpumMsrWrFn_AmdFam10hIbsOpRip,
+    kCpumMsrWrFn_AmdFam10hIbsOpData,
+    kCpumMsrWrFn_AmdFam10hIbsOpData2,
+    kCpumMsrWrFn_AmdFam10hIbsOpData3,
+    kCpumMsrWrFn_AmdFam10hIbsDcLinAddr,
+    kCpumMsrWrFn_AmdFam10hIbsDcPhysAddr,
+    kCpumMsrWrFn_AmdFam10hIbsCtl,
+    kCpumMsrWrFn_AmdFam14hIbsBrTarget,
+
+    /** End of valid MSR write function indexes. */
+    kCpumMsrWrFn_End
+} CPUMMSRWRFN;
+
+/**
+ * MSR range.
+ */
+typedef struct CPUMMSRRANGE
+{
+    /** The first MSR. [0] */
+    uint32_t    uFirst;
+    /** The last MSR. [4] */
+    uint32_t    uLast;
+    /** The read function (CPUMMSRRDFN). [8] */
+    uint16_t    enmRdFn;
+    /** The write function (CPUMMSRWRFN). [10] */
+    uint16_t    enmWrFn;
+    /** The offset of the 64-bit MSR value relative to the start of CPUMCPU.
+     * UINT16_MAX if not used by the read and write functions.  [12] */
+    uint16_t    offCpumCpu;
+    /** Reserved for future hacks. [14] */
+    uint16_t    fReserved;
+    /** The init/read value. [16]
+     * When enmRdFn is kCpumMsrRdFn_INIT_VALUE, this is the value returned on RDMSR.
+     * offCpumCpu must be UINT16_MAX in that case, otherwise it must be a valid
+     * offset into CPUM. */
+    uint64_t    uValue;
+    /** The bits to ignore when writing. [24]   */
+    uint64_t    fWrIgnMask;
+    /** The bits that will cause a GP(0) when writing. [32]
+     * This is always checked prior to calling the write function.  Using
+     * UINT64_MAX effectively marks the MSR as read-only. */
+    uint64_t    fWrGpMask;
+    /** The register name, if applicable. [40] */
+    char        szName[56];
+
+#ifdef VBOX_WITH_STATISTICS
+    /** The number of reads. */
+    STAMCOUNTER cReads;
+    /** The number of writes. */
+    STAMCOUNTER cWrites;
+    /** The number of times ignored bits were written. */
+    STAMCOUNTER cIgnoredBits;
+    /** The number of GPs generated. */
+    STAMCOUNTER cGps;
+#endif
+} CPUMMSRRANGE;
+#ifdef VBOX_WITH_STATISTICS
+AssertCompileSize(CPUMMSRRANGE, 128);
+#else
+AssertCompileSize(CPUMMSRRANGE, 96);
+#endif
+/** Pointer to an MSR range. */
+typedef CPUMMSRRANGE *PCPUMMSRRANGE;
+/** Pointer to a const MSR range. */
+typedef CPUMMSRRANGE const *PCCPUMMSRRANGE;
+
+
+
+
+/**
+ * CPU features and quirks.
+ * This is mostly exploded CPUID info.
+ */
+typedef struct CPUMFEATURES
+{
+    /** The CPU vendor (CPUMCPUVENDOR). */
+    uint8_t         enmCpuVendor;
+    /** The CPU family. */
+    uint8_t         uFamily;
+    /** The CPU model. */
+    uint8_t         uModel;
+    /** The CPU stepping. */
+    uint8_t         uStepping;
+    /** The microarchitecture. */
+    CPUMMICROARCH   enmMicroarch;
+    /** The maximum physical address with of the CPU. */
+    uint8_t         cMaxPhysAddrWidth;
+    /** Alignment padding.  */
+    uint8_t         abPadding[3];
+
+    /** Supports MSRs.  */
+    uint32_t        fMsr : 1;
+    /** Supports the page size extension (4/2 MB pages). */
+    uint32_t        fPse : 1;
+    /** Supports 36-bit page size extension (4 MB pages can map memory above
+     *  4GB). */
+    uint32_t        fPse36 : 1;
+    /** Supports physical address extension (PAE).  */
+    uint32_t        fPae : 1;
+    /** Page attribute table (PAT) support (page level cache control). */
+    uint32_t        fPat : 1;
+    /** Supports the FXSAVE and FXRSTOR instructions. */
+    uint32_t        fFxSaveRstor : 1;
+    /** Intel SYSENTER/SYSEXIT support */
+    uint32_t        fSysEnter : 1;
+    /** First generation APIC. */
+    uint32_t        fApic : 1;
+    /** Second generation APIC. */
+    uint32_t        fX2Apic : 1;
+    /** Hypervisor present. */
+    uint32_t        fHypervisorPresent : 1;
+    /** MWAIT & MONITOR instructions supported. */
+    uint32_t        fMonitorMWait : 1;
+
+    /** AMD64: Supports long mode.  */
+    uint32_t        fLongMode : 1;
+    /** AMD64: SYSCALL/SYSRET support. */
+    uint32_t        fSysCall : 1;
+    /** AMD64: No-execute page table bit. */
+    uint32_t        fNoExecute : 1;
+    /** AMD64: Supports LAHF & SAHF instructions in 64-bit mode. */
+    uint32_t        fLahfSahf : 1;
+    /** AMD64: Supports RDTSCP. */
+    uint32_t        fRdTscP : 1;
+
+    /** Indicates that FPU instruction and data pointers may leak.
+     * This generally applies to recent AMD CPUs, where the FPU IP and DP pointer
+     * is only saved and restored if an exception is pending.   */
+    uint32_t        fLeakyFxSR : 1;
+
+    /** Alignment padding.  */
+    uint32_t        fPadding : 9;
+
+    uint64_t        auPadding[2];
+} CPUMFEATURES;
+AssertCompileSize(CPUMFEATURES, 32);
+/** Pointer to a CPU feature structure. */
+typedef CPUMFEATURES *PCPUMFEATURES;
+/** Pointer to a const CPU feature structure. */
+typedef CPUMFEATURES const *PCCPUMFEATURES;
+
+
+/**
+ * CPU info
+ */
+typedef struct CPUMINFO
+{
+    /** The number of MSR ranges (CPUMMSRRANGE) in the array pointed to below. */
+    uint32_t                    cMsrRanges;
+    /** Mask applied to ECX before looking up the MSR for a RDMSR/WRMSR
+     * instruction.  Older hardware has been observed to ignore higher bits. */
+    uint32_t                    fMsrMask;
+
+    /** The number of CPUID leaves (CPUMCPUIDLEAF) in the array pointed to below. */
+    uint32_t                    cCpuIdLeaves;
+    /** The index of the first extended CPUID leaf in the array.
+     *  Set to cCpuIdLeaves if none present. */
+    uint32_t                    iFirstExtCpuIdLeaf;
+    /** How to handle unknown CPUID leaves. */
+    CPUMUKNOWNCPUID             enmUnknownCpuIdMethod;
+    /** For use with CPUMUKNOWNCPUID_DEFAULTS. */
+    CPUMCPUID                   DefCpuId;
+
+    /** Alignment padding.  */
+    uint32_t                    uPadding;
+
+    /** Pointer to the MSR ranges (ring-0 pointer). */
+    R0PTRTYPE(PCPUMMSRRANGE)    paMsrRangesR0;
+    /** Pointer to the CPUID leaves (ring-0 pointer). */
+    R0PTRTYPE(PCPUMCPUIDLEAF)   paCpuIdLeavesR0;
+
+    /** Pointer to the MSR ranges (ring-3 pointer). */
+    R3PTRTYPE(PCPUMMSRRANGE)    paMsrRangesR3;
+    /** Pointer to the CPUID leaves (ring-3 pointer). */
+    R3PTRTYPE(PCPUMCPUIDLEAF)   paCpuIdLeavesR3;
+
+    /** Pointer to the MSR ranges (raw-mode context pointer). */
+    RCPTRTYPE(PCPUMMSRRANGE)    paMsrRangesRC;
+    /** Pointer to the CPUID leaves (raw-mode context pointer). */
+    RCPTRTYPE(PCPUMCPUIDLEAF)   paCpuIdLeavesRC;
+} CPUMINFO;
+/** Pointer to a CPU info structure. */
+typedef CPUMINFO *PCPUMINFO;
+/** Pointer to a const CPU info structure. */
+typedef CPUMINFO const *CPCPUMINFO;
+
+
+/**
  * The saved host CPU state.
  *
  * @remark  The special VBOX_WITH_HYBRID_32BIT_KERNEL checks here are for the 10.4.x series
@@ -309,11 +974,6 @@ typedef struct CPUM
         uint32_t            ecx;
     } CPUFeaturesExt;
 
-    /** Host CPU manufacturer. */
-    CPUMCPUVENDOR           enmHostCpuVendor;
-    /** Guest CPU manufacturer. */
-    CPUMCPUVENDOR           enmGuestCpuVendor;
-
     /** CR4 mask */
     struct
     {
@@ -321,14 +981,12 @@ typedef struct CPUM
         uint32_t            OrMask;
     } CR4;
 
-    /** Synthetic CPU type? */
-    bool                    fSyntheticCpu;
     /** The (more) portable CPUID level.  */
     uint8_t                 u8PortableCpuIdLevel;
     /** Indicates that a state restore is pending.
      * This is used to verify load order dependencies (PGM). */
     bool                    fPendingRestore;
-    uint8_t                 abPadding[HC_ARCH_BITS == 64 ? 5 : 1];
+    uint8_t                 abPadding[HC_ARCH_BITS == 64 ? 6 : 2];
 
     /** The standard set of CpuId leaves. */
     CPUMCPUID               aGuestCpuIdStd[6];
@@ -344,6 +1002,24 @@ typedef struct CPUM
 #if HC_ARCH_BITS == 32
     uint8_t                 abPadding2[4];
 #endif
+
+    /** Guest CPU info. */
+    CPUMINFO                GuestInfo;
+    /** Guest CPU feature information. */
+    CPUMFEATURES            GuestFeatures;
+    /** Host CPU feature information. */
+    CPUMFEATURES            HostFeatures;
+
+    /** @name MSR statistics.
+     * @{ */
+    STAMCOUNTER             cMsrWrites;
+    STAMCOUNTER             cMsrWritesToIgnoredBits;
+    STAMCOUNTER             cMsrWritesRaiseGp;
+    STAMCOUNTER             cMsrWritesUnknown;
+    STAMCOUNTER             cMsrReads;
+    STAMCOUNTER             cMsrReadsRaiseGp;
+    STAMCOUNTER             cMsrReadsUnknown;
+    /** @} */
 } CPUM;
 /** Pointer to the CPUM instance data residing in the shared VM structure. */
 typedef CPUM *PCPUM;
@@ -429,8 +1105,22 @@ typedef CPUMCPU *PCPUMCPU;
 #ifndef VBOX_FOR_DTRACE_LIB
 RT_C_DECLS_BEGIN
 
+PCPUMCPUIDLEAF      cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf);
+
 #ifdef IN_RING3
 int                 cpumR3DbgInit(PVM pVM);
+PCPUMCPUIDLEAF      cpumR3CpuIdGetLeaf(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf);
+bool                cpumR3CpuIdGetLeafLegacy(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf,
+                                             PCPUMCPUID pLeagcy);
+int                 cpumR3CpuIdInsert(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves, PCPUMCPUIDLEAF pNewLeaf);
+void                cpumR3CpuIdRemoveRange(PCPUMCPUIDLEAF paLeaves, uint32_t *pcLeaves, uint32_t uFirst, uint32_t uLast);
+int                 cpumR3CpuIdExplodeFeatures(PCCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, PCPUMFEATURES pFeatures);
+int                 cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo);
+int                 cpumR3MsrRangesInsert(PCPUMMSRRANGE *ppaMsrRanges, uint32_t *pcMsrRanges, PCCPUMMSRRANGE pNewRange);
+int                 cpumR3MsrApplyFudge(PVM pVM);
+int                 cpumR3MsrRegStats(PVM pVM);
+int                 cpumR3MsrStrictInitChecks(void);
+PCPUMMSRRANGE       cpumLookupMsrRange(PVM pVM, uint32_t idMsr);
 #endif
 
 #ifdef IN_RC
diff --git a/src/VBox/VMM/include/CPUMInternal.mac b/src/VBox/VMM/include/CPUMInternal.mac
index c3ee43a..4e18b4e 100644
--- a/src/VBox/VMM/include/CPUMInternal.mac
+++ b/src/VBox/VMM/include/CPUMInternal.mac
@@ -66,20 +66,16 @@ struc CPUM
     .CPUFeaturesExt.edx   resd    1
     .CPUFeaturesExt.ecx   resd    1
 
-    .enmHostCpuVendor     resd    1
-    .enmGuestCpuVendor    resd    1
-
     ; CR4 masks
     .CR4.AndMask          resd    1
     .CR4.OrMask           resd    1
     ; entered rawmode?
-    .fSyntheticCpu        resb    1
     .u8PortableCpuIdLevel resb    1
     .fPendingRestore      resb    1
 %if RTHCPTR_CB == 8
-    .abPadding            resb    5
+    .abPadding            resb    6
 %else
-    .abPadding            resb    1
+    .abPadding            resb    2
 %endif
 
     ; CPUID leafs
@@ -92,6 +88,18 @@ struc CPUM
 %if HC_ARCH_BITS == 32
     .abPadding2           resb    4
 %endif
+
+    .GuestInfo            resb    RTHCPTR_CB*4 + RTRCPTR_CB*2 + 4*10
+    .GuestFeatures        resb    32
+    .HostFeatures         resb    32
+
+    .cMsrWrites                 resq  1
+    .cMsrWritesToIgnoredBits    resq  1
+    .cMsrWritesRaiseGp          resq  1
+    .cMsrWritesUnknown          resq  1
+    .cMsrReads                  resq  1
+    .cMsrReadsRaiseGp           resq  1
+    .cMsrReadsUnknown           resq  1
 endstruc
 
 struc CPUMCPU
diff --git a/src/VBox/VMM/include/SELMInline.h b/src/VBox/VMM/include/SELMInline.h
index c0600c7..a122294 100644
--- a/src/VBox/VMM/include/SELMInline.h
+++ b/src/VBox/VMM/include/SELMInline.h
@@ -252,7 +252,7 @@ DECLINLINE(bool) selmIsSRegStale32(PCCPUMSELREG pSReg, PCX86DESC pShwDesc, uint3
 
     if (pSReg->u64Base != X86DESC_BASE(pShwDesc))
     {
-        Log(("selmIsSRegStale32: base changed (%#llx -> %#llx)\n", pSReg->u64Base, X86DESC_BASE(pShwDesc)));
+        Log(("selmIsSRegStale32: base changed (%#llx -> %#x)\n", pSReg->u64Base, X86DESC_BASE(pShwDesc)));
         return true;
     }
 
diff --git a/src/VBox/VMM/include/VMMInternal.h b/src/VBox/VMM/include/VMMInternal.h
index 081d317..fa3f253 100644
--- a/src/VBox/VMM/include/VMMInternal.h
+++ b/src/VBox/VMM/include/VMMInternal.h
@@ -525,6 +525,23 @@ typedef enum VMMGCOPERATION
 } VMMGCOPERATION;
 
 
+
+/**
+ * MSR test result entry.
+ */
+typedef struct VMMTESTMSRENTRY
+{
+    /** The MSR number, including padding.
+     * Set to UINT64_MAX if invalid MSR. */
+    uint64_t    uMsr;
+    /** The register value. */
+    uint64_t    uValue;
+} VMMTESTMSRENTRY;
+/** Pointer to an MSR test result entry. */
+typedef VMMTESTMSRENTRY *PVMMTESTMSRENTRY;
+
+
+
 RT_C_DECLS_BEGIN
 
 int  vmmInitFormatTypes(void);
diff --git a/src/VBox/VMM/testcase/tstVMM.cpp b/src/VBox/VMM/testcase/tstVMM.cpp
index 5ee7dd9..2e77560 100644
--- a/src/VBox/VMM/testcase/tstVMM.cpp
+++ b/src/VBox/VMM/testcase/tstVMM.cpp
@@ -54,7 +54,8 @@ static uint32_t g_cCpus = 1;
 /*******************************************************************************
 *   Internal Functions                                                         *
 *******************************************************************************/
-VMMR3DECL(int) VMMDoTest(PVM pVM); /* Linked into VMM, see ../VMMTests.cpp. */
+VMMR3DECL(int) VMMDoTest(PVM pVM);    /* Linked into VMM, see ../VMMTests.cpp. */
+VMMR3DECL(int) VMMDoBruteForceMsrs(PVM pVM); /* Ditto. */
 
 
 /** Dummy timer callback. */
@@ -209,7 +210,7 @@ int main(int argc, char **argv)
     };
     enum
     {
-        kTstVMMTest_VMM,  kTstVMMTest_TM
+        kTstVMMTest_VMM,  kTstVMMTest_TM, kTstVMMTest_MSRs
     } enmTestOpt = kTstVMMTest_VMM;
 
     int ch;
@@ -229,6 +230,8 @@ int main(int argc, char **argv)
                     enmTestOpt = kTstVMMTest_VMM;
                 else if (!strcmp("tm", ValueUnion.psz))
                     enmTestOpt = kTstVMMTest_TM;
+                else if (!strcmp("msr", ValueUnion.psz) || !strcmp("msrs", ValueUnion.psz))
+                    enmTestOpt = kTstVMMTest_MSRs;
                 else
                 {
                     RTPrintf("tstVMM: unknown test: '%s'\n", ValueUnion.psz);
@@ -237,11 +240,11 @@ int main(int argc, char **argv)
                 break;
 
             case 'h':
-                RTPrintf("usage: tstVMM [--cpus|-c cpus] [--test <vmm|tm>]\n");
+                RTPrintf("usage: tstVMM [--cpus|-c cpus] [--test <vmm|tm|msr>]\n");
                 return 1;
 
             case 'V':
-                RTPrintf("$Revision: 86910 $\n");
+                RTPrintf("$Revision: 91444 $\n");
                 return 0;
 
             default:
@@ -273,6 +276,7 @@ int main(int argc, char **argv)
                 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM);
                 if (RT_FAILURE(rc))
                     RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
+                STAMR3Dump(pUVM, "*");
                 break;
             }
 
@@ -289,11 +293,24 @@ int main(int argc, char **argv)
                 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)tstTMWorker, 2, pVM, hTest);
                 if (RT_FAILURE(rc))
                     RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
+                STAMR3Dump(pUVM, "*");
                 break;
             }
-        }
 
-        STAMR3Dump(pUVM, "*");
+            case kTstVMMTest_MSRs:
+            {
+                RTTestSub(hTest, "MSRs");
+                if (g_cCpus == 1)
+                {
+                    rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoBruteForceMsrs, 1, pVM);
+                    if (RT_FAILURE(rc))
+                        RTTestFailed(hTest, "VMMDoBruteForceMsrs failed: rc=%Rrc\n", rc);
+                }
+                else
+                    RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
+                break;
+            }
+        }
 
         /*
          * Cleanup.
diff --git a/src/VBox/VMM/testcase/tstVMStruct.h b/src/VBox/VMM/testcase/tstVMStruct.h
index 0217156..902b0fd 100644
--- a/src/VBox/VMM/testcase/tstVMStruct.h
+++ b/src/VBox/VMM/testcase/tstVMStruct.h
@@ -31,11 +31,8 @@
     GEN_CHECK_OFF(CPUM, CPUFeatures);
     GEN_CHECK_OFF(CPUM, CPUFeaturesExt);
     GEN_CHECK_OFF(CPUM, CPUFeaturesExt);
-    GEN_CHECK_OFF(CPUM, enmHostCpuVendor);
-    GEN_CHECK_OFF(CPUM, enmGuestCpuVendor);
     GEN_CHECK_OFF(CPUM, CR4);
 #ifndef VBOX_FOR_DTRACE_LIB
-    GEN_CHECK_OFF(CPUM, fSyntheticCpu);
     GEN_CHECK_OFF(CPUM, u8PortableCpuIdLevel);
     GEN_CHECK_OFF(CPUM, fPendingRestore);
 #endif
diff --git a/src/VBox/VMM/Preload/Makefile.kmk b/src/VBox/VMM/tools/Makefile.kmk
similarity index 66%
rename from src/VBox/VMM/Preload/Makefile.kmk
rename to src/VBox/VMM/tools/Makefile.kmk
index 4051c76..107208d 100644
--- a/src/VBox/VMM/Preload/Makefile.kmk
+++ b/src/VBox/VMM/tools/Makefile.kmk
@@ -1,11 +1,11 @@
 
 # $Id: Makefile.kmk $
 ## @file
-# Sub-Makefile for the headless frontend.
+# Sub-Makefile for VMM tools.
 #
 
 #
-# Copyright (C) 2006-2012 Oracle Corporation
+# Copyright (C) 2006-2013 Oracle Corporation
 #
 # This file is part of VirtualBox Open Source Edition (OSE), as
 # available from http://www.virtualbox.org. This file is free software;
@@ -50,5 +50,24 @@ ifdef VBOX_WITH_HARDENING
 endif
 
 
+#
+# CPU report program (CPUM DB).
+#
+#PROGRAMS += VBoxCpuReport - not on 4.3, supdrv interface currently missing.
+VBoxCpuReport_TEMPLATE := VBoxR3Static
+VBoxCpuReport_DEFS      = IN_VMM_R3
+VBoxCpuReport_INCS      = ../include
+VBoxCpuReport_SOURCES   = \
+	VBoxCpuReport.cpp \
+       ../VMMR3/CPUMR3CpuId.cpp
+VBoxCpuReport_LIBS      = \
+	$(PATH_STAGE_LIB)/SUPR3Static$(VBOX_SUFF_LIB) \
+       $(VBOX_LIB_RUNTIME_STATIC)
+VBoxCpuReport_LIBS.solaris = kstat contract
+
+VBoxCpuReport_LDFLAGS.darwin = \
+	-framework IOKit -framework CoreFoundation -framework CoreServices
+
+
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/VBox/VMM/tools/VBoxCpuReport.cpp b/src/VBox/VMM/tools/VBoxCpuReport.cpp
new file mode 100644
index 0000000..b1b70cd
--- /dev/null
+++ b/src/VBox/VMM/tools/VBoxCpuReport.cpp
@@ -0,0 +1,4687 @@
+/* $Id: VBoxCpuReport.cpp $ */
+/** @file
+ * VBoxCpuReport - Produces the basis for a CPU DB entry.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/buildconfig.h>
+#include <iprt/ctype.h>
+#include <iprt/file.h>
+#include <iprt/getopt.h>
+#include <iprt/initterm.h>
+#include <iprt/message.h>
+#include <iprt/mem.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/stream.h>
+#include <iprt/symlink.h>
+#include <iprt/thread.h>
+#include <iprt/time.h>
+
+#include <VBox/err.h>
+#include <VBox/vmm/cpum.h>
+#include <VBox/sup.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** Write only register. */
+#define VBCPUREPMSR_F_WRITE_ONLY      RT_BIT(0)
+
+typedef struct VBCPUREPMSR
+{
+    /** The first MSR register number. */
+    uint32_t        uMsr;
+    /** Flags (MSRREPORT_F_XXX). */
+    uint32_t        fFlags;
+    /** The value we read, unless write-only.  */
+    uint64_t        uValue;
+} VBCPUREPMSR;
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The CPU vendor.  Used by the MSR code. */
+static CPUMCPUVENDOR    g_enmVendor = CPUMCPUVENDOR_INVALID;
+/** The CPU microarchitecture.  Used by the MSR code. */
+static CPUMMICROARCH    g_enmMicroarch = kCpumMicroarch_Invalid;
+/** Set if g_enmMicroarch indicates an Intel NetBurst CPU. */
+static bool             g_fIntelNetBurst = false;
+/** The alternative report stream. */
+static PRTSTREAM        g_pReportOut;
+/** The alternative debug stream. */
+static PRTSTREAM        g_pDebugOut;
+
+
+static void vbCpuRepDebug(const char *pszMsg, ...)
+{
+    va_list va;
+
+    /* Always print a copy of the report to standard error. */
+    va_start(va, pszMsg);
+    RTStrmPrintfV(g_pStdErr, pszMsg, va);
+    va_end(va);
+    RTStrmFlush(g_pStdErr);
+
+    /* Alternatively, also print to a log file. */
+    if (g_pDebugOut)
+    {
+        va_start(va, pszMsg);
+        RTStrmPrintfV(g_pDebugOut, pszMsg, va);
+        va_end(va);
+        RTStrmFlush(g_pDebugOut);
+    }
+
+    /* Give the output device a chance to write / display it. */
+    RTThreadSleep(1);
+}
+
+
+static void vbCpuRepPrintf(const char *pszMsg, ...)
+{
+    va_list va;
+
+    /* Output to report file, if requested. */
+    if (g_pReportOut)
+    {
+        va_start(va, pszMsg);
+        RTStrmPrintfV(g_pReportOut, pszMsg, va);
+        va_end(va);
+        RTStrmFlush(g_pReportOut);
+    }
+
+    /* Always print a copy of the report to standard out. */
+    va_start(va, pszMsg);
+    RTStrmPrintfV(g_pStdOut, pszMsg, va);
+    va_end(va);
+    RTStrmFlush(g_pStdOut);
+}
+
+
+
+static int vbCpuRepMsrsAddOne(VBCPUREPMSR **ppaMsrs, uint32_t *pcMsrs,
+                              uint32_t uMsr, uint64_t uValue, uint32_t fFlags)
+{
+    /*
+     * Grow the array?
+     */
+    uint32_t cMsrs = *pcMsrs;
+    if ((cMsrs % 64) == 0)
+    {
+        void *pvNew = RTMemRealloc(*ppaMsrs, (cMsrs + 64) * sizeof(**ppaMsrs));
+        if (!pvNew)
+        {
+            RTMemFree(*ppaMsrs);
+            *ppaMsrs = NULL;
+            *pcMsrs  = 0;
+            return VERR_NO_MEMORY;
+        }
+        *ppaMsrs = (VBCPUREPMSR *)pvNew;
+    }
+
+    /*
+     * Add it.
+     */
+    VBCPUREPMSR *pEntry = *ppaMsrs + cMsrs;
+    pEntry->uMsr   = uMsr;
+    pEntry->fFlags = fFlags;
+    pEntry->uValue = uValue;
+    *pcMsrs = cMsrs + 1;
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Returns the max physical address width as a number of bits.
+ *
+ * @returns Bit count.
+ */
+static uint8_t vbCpuRepGetPhysAddrWidth(void)
+{
+    uint8_t  cMaxWidth;
+    uint32_t cMaxExt = ASMCpuId_EAX(0x80000000);
+    if (!ASMHasCpuId())
+        cMaxWidth = 32;
+    else if (ASMIsValidExtRange(cMaxExt)&& cMaxExt >= 0x80000008)
+        cMaxWidth = ASMCpuId_EAX(0x80000008) & 0xff;
+    else if (   ASMIsValidStdRange(ASMCpuId_EAX(0))
+             && (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PSE36))
+        cMaxWidth = 36;
+    else
+        cMaxWidth = 32;
+    return cMaxWidth;
+}
+
+
+static bool vbCpuRepSupportsPae(void)
+{
+    return ASMHasCpuId()
+        && ASMIsValidStdRange(ASMCpuId_EAX(0))
+        && (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PAE);
+}
+
+
+static bool vbCpuRepSupportsLongMode(void)
+{
+    return ASMHasCpuId()
+        && ASMIsValidExtRange(ASMCpuId_EAX(0x80000000))
+        && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
+}
+
+
+static bool vbCpuRepSupportsNX(void)
+{
+    return ASMHasCpuId()
+        && ASMIsValidExtRange(ASMCpuId_EAX(0x80000000))
+        && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_NX);
+}
+
+
+static bool vbCpuRepSupportsX2Apic(void)
+{
+    return ASMHasCpuId()
+        && ASMIsValidStdRange(ASMCpuId_EAX(0))
+        && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_X2APIC);
+}
+
+
+
+static bool msrProberWrite(uint32_t uMsr, uint64_t uValue)
+{
+    bool fGp;
+    int rc = SUPR3MsrProberWrite(uMsr, NIL_RTCPUID, uValue, &fGp);
+    AssertRC(rc);
+    return RT_SUCCESS(rc) && !fGp;
+}
+
+
+static bool msrProberRead(uint32_t uMsr, uint64_t *puValue)
+{
+    *puValue = 0;
+    bool fGp;
+    int rc = SUPR3MsrProberRead(uMsr, NIL_RTCPUID, puValue, &fGp);
+    AssertRC(rc);
+    return RT_SUCCESS(rc) && !fGp;
+}
+
+
+/** Tries to modify the register by writing the original value to it. */
+static bool msrProberModifyNoChange(uint32_t uMsr)
+{
+    SUPMSRPROBERMODIFYRESULT Result;
+    int rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, UINT64_MAX, 0, &Result);
+    return RT_SUCCESS(rc)
+        && !Result.fBeforeGp
+        && !Result.fModifyGp
+        && !Result.fAfterGp
+        && !Result.fRestoreGp;
+}
+
+
+/** Tries to modify the register by writing zero to it. */
+static bool msrProberModifyZero(uint32_t uMsr)
+{
+    SUPMSRPROBERMODIFYRESULT Result;
+    int rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, 0, 0, &Result);
+    return RT_SUCCESS(rc)
+        && !Result.fBeforeGp
+        && !Result.fModifyGp
+        && !Result.fAfterGp
+        && !Result.fRestoreGp;
+}
+
+
+/**
+ * Tries to modify each bit in the MSR and see if we can make it change.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR.
+ * @param   pfIgnMask           The ignore mask to update.
+ * @param   pfGpMask            The GP mask to update.
+ * @param   fSkipMask           Mask of bits to skip.
+ */
+static int msrProberModifyBitChanges(uint32_t uMsr, uint64_t *pfIgnMask, uint64_t *pfGpMask, uint64_t fSkipMask)
+{
+    for (unsigned iBit = 0; iBit < 64; iBit++)
+    {
+        uint64_t fBitMask = RT_BIT_64(iBit);
+        if (fBitMask & fSkipMask)
+            continue;
+
+        /* Set it. */
+        SUPMSRPROBERMODIFYRESULT ResultSet;
+        int rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, fBitMask, &ResultSet);
+        if (RT_FAILURE(rc))
+            return RTMsgErrorRc(rc, "SUPR3MsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, fBitMask, rc);
+
+        /* Clear it. */
+        SUPMSRPROBERMODIFYRESULT ResultClear;
+        rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, 0, &ResultClear);
+        if (RT_FAILURE(rc))
+            return RTMsgErrorRc(rc, "SUPR3MsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, 0, rc);
+
+        if (ResultSet.fModifyGp || ResultClear.fModifyGp)
+            *pfGpMask |= fBitMask;
+        else if (   (   ((ResultSet.uBefore   ^ ResultSet.uAfter)   & fBitMask) == 0
+                     && !ResultSet.fBeforeGp
+                     && !ResultSet.fAfterGp)
+                 && (   ((ResultClear.uBefore ^ ResultClear.uAfter) & fBitMask) == 0
+                     && !ResultClear.fBeforeGp
+                     && !ResultClear.fAfterGp) )
+            *pfIgnMask |= fBitMask;
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Tries to modify one bit.
+ *
+ * @retval  -2 on API error.
+ * @retval  -1 on \#GP.
+ * @retval  0 if ignored.
+ * @retval  1 if it changed.
+ *
+ * @param   uMsr                The MSR.
+ * @param   iBit                The bit to try modify.
+ */
+static int msrProberModifyBit(uint32_t uMsr, unsigned iBit)
+{
+    uint64_t fBitMask = RT_BIT_64(iBit);
+
+    /* Set it. */
+    SUPMSRPROBERMODIFYRESULT ResultSet;
+    int rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, fBitMask, &ResultSet);
+    if (RT_FAILURE(rc))
+        return RTMsgErrorRc(-2, "SUPR3MsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, fBitMask, rc);
+
+    /* Clear it. */
+    SUPMSRPROBERMODIFYRESULT ResultClear;
+    rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, 0, &ResultClear);
+    if (RT_FAILURE(rc))
+        return RTMsgErrorRc(-2, "SUPR3MsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, 0, rc);
+
+    if (ResultSet.fModifyGp || ResultClear.fModifyGp)
+        return -1;
+
+    if (   (   ((ResultSet.uBefore   ^ ResultSet.uAfter)   & fBitMask) != 0
+            && !ResultSet.fBeforeGp
+            && !ResultSet.fAfterGp)
+        || (   ((ResultClear.uBefore ^ ResultClear.uAfter) & fBitMask) != 0
+            && !ResultClear.fBeforeGp
+            && !ResultClear.fAfterGp) )
+        return 1;
+
+    return 0;
+}
+
+
+/**
+ * Tries to do a simple AND+OR change and see if we \#GP or not.
+ *
+ * @retval  @c true if successfully modified.
+ * @retval  @c false if \#GP or other error.
+ *
+ * @param   uMsr                The MSR.
+ * @param   fAndMask            The AND mask.
+ * @param   fOrMask             The OR mask.
+ */
+static bool msrProberModifySimpleGp(uint32_t uMsr, uint64_t fAndMask, uint64_t fOrMask)
+{
+    SUPMSRPROBERMODIFYRESULT Result;
+    int rc = SUPR3MsrProberModify(uMsr, NIL_RTCPUID, fAndMask, fOrMask, &Result);
+    if (RT_FAILURE(rc))
+    {
+        RTMsgError("SUPR3MsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, fAndMask, fOrMask, rc);
+        return false;
+    }
+    return !Result.fBeforeGp
+        && !Result.fModifyGp
+        && !Result.fAfterGp
+        && !Result.fRestoreGp;
+}
+
+
+
+
+/**
+ * Combination of the basic tests.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR.
+ * @param   fSkipMask           Mask of bits to skip.
+ * @param   pfReadOnly          Where to return read-only status.
+ * @param   pfIgnMask           Where to return the write ignore mask.  Need not
+ *                              be initialized.
+ * @param   pfGpMask            Where to return the write GP mask.  Need not
+ *                              be initialized.
+ */
+static int msrProberModifyBasicTests(uint32_t uMsr, uint64_t fSkipMask, bool *pfReadOnly, uint64_t *pfIgnMask, uint64_t *pfGpMask)
+{
+    if (msrProberModifyNoChange(uMsr))
+    {
+        *pfReadOnly = false;
+        *pfIgnMask  = 0;
+        *pfGpMask  = 0;
+        return msrProberModifyBitChanges(uMsr, pfIgnMask, pfGpMask, fSkipMask);
+    }
+
+    *pfReadOnly = true;
+    *pfIgnMask  = 0;
+    *pfGpMask   = UINT64_MAX;
+    return VINF_SUCCESS;
+}
+
+
+
+/**
+ * Determines for the MSR AND mask.
+ *
+ * Older CPUs doesn't necessiarly implement all bits of the MSR register number.
+ * So, we have to approximate how many are used so we don't get an overly large
+ * and confusing set of MSRs when probing.
+ *
+ * @returns The mask.
+ */
+static uint32_t determineMsrAndMask(void)
+{
+#define VBCPUREP_MASK_TEST_MSRS     7
+    static uint32_t const s_aMsrs[VBCPUREP_MASK_TEST_MSRS] =
+    {
+        /* Try a bunch of mostly read only registers: */
+        MSR_P5_MC_TYPE, MSR_IA32_PLATFORM_ID, MSR_IA32_MTRR_CAP, MSR_IA32_MCG_CAP, MSR_IA32_CR_PAT,
+        /* Then some which aren't supposed to be present on any CPU: */
+        0x00000015, 0x00000019,
+    };
+
+    /* Get the base values. */
+    uint64_t auBaseValues[VBCPUREP_MASK_TEST_MSRS];
+    for (unsigned i = 0; i < RT_ELEMENTS(s_aMsrs); i++)
+    {
+        if (!msrProberRead(s_aMsrs[i], &auBaseValues[i]))
+            auBaseValues[i] = UINT64_MAX;
+        //vbCpuRepDebug("Base: %#x -> %#llx\n", s_aMsrs[i], auBaseValues[i]);
+    }
+
+    /* Do the probing. */
+    unsigned iBit;
+    for (iBit = 31; iBit > 8; iBit--)
+    {
+        uint64_t fMsrOrMask = RT_BIT_64(iBit);
+        for (unsigned iTest = 0; iTest <= 64 && fMsrOrMask < UINT32_MAX; iTest++)
+        {
+            for (unsigned i = 0; i < RT_ELEMENTS(s_aMsrs); i++)
+            {
+                uint64_t uValue;
+                if (!msrProberRead(s_aMsrs[i] | fMsrOrMask, &uValue))
+                    uValue = UINT64_MAX;
+                if (uValue != auBaseValues[i])
+                {
+                    uint32_t fMsrMask = iBit >= 31 ? UINT32_MAX : RT_BIT_32(iBit + 1) - 1;
+                    vbCpuRepDebug("MSR AND mask: quit on iBit=%u uMsr=%#x (%#x) %llx != %llx => fMsrMask=%#x\n",
+                                  iBit, s_aMsrs[i] | (uint32_t)fMsrOrMask, s_aMsrs[i], uValue, auBaseValues[i], fMsrMask);
+                    return fMsrMask;
+                }
+            }
+
+            /* Advance. */
+            if (iBit <= 6)
+                fMsrOrMask += RT_BIT_64(iBit);
+            else if (iBit <= 11)
+                fMsrOrMask += RT_BIT_64(iBit) * 33;
+            else if (iBit <= 16)
+                fMsrOrMask += RT_BIT_64(iBit) * 1025;
+            else if (iBit <= 22)
+                fMsrOrMask += RT_BIT_64(iBit) * 65537;
+            else
+                fMsrOrMask += RT_BIT_64(iBit) * 262145;
+        }
+    }
+
+    uint32_t fMsrMask = RT_BIT_32(iBit + 1) - 1;
+    vbCpuRepDebug("MSR AND mask: less that %u bits that matters?!? => fMsrMask=%#x\n", iBit + 1, fMsrMask);
+    return fMsrMask;
+}
+
+
+static int findMsrs(VBCPUREPMSR **ppaMsrs, uint32_t *pcMsrs, uint32_t fMsrMask)
+{
+    /*
+     * Gather them.
+     */
+    static struct { uint32_t uFirst, cMsrs; } const s_aRanges[] =
+    {
+        { 0x00000000, 0x00042000 },
+        { 0x10000000, 0x00001000 },
+        { 0x20000000, 0x00001000 },
+        { 0x40000000, 0x00012000 },
+        { 0x80000000, 0x00012000 },
+        { 0xc0000000, 0x00022000 }, /* Had some trouble here on solaris with the tstVMM setup. */
+    };
+
+    *pcMsrs  = 0;
+    *ppaMsrs = NULL;
+
+    for (unsigned i = 0; i < RT_ELEMENTS(s_aRanges); i++)
+    {
+        uint32_t uMsr  = s_aRanges[i].uFirst;
+        if ((uMsr & fMsrMask) != uMsr)
+            continue;
+        uint32_t cLeft = s_aRanges[i].cMsrs;
+        while (cLeft-- > 0 && (uMsr & fMsrMask) == uMsr)
+        {
+            if ((uMsr & 0xfff) == 0)
+            {
+                vbCpuRepDebug("testing %#x...\n", uMsr);
+                RTThreadSleep(22);
+            }
+#if 0
+            else if (uMsr >= 0x00003170 && uMsr <= 0xc0000090)
+            {
+                vbCpuRepDebug("testing %#x...\n", uMsr);
+                RTThreadSleep(250);
+            }
+#endif
+            /* Skip 0xc0011012..13 as it seems to be bad for our health (Phenom II X6 1100T). */
+            if ((uMsr >= 0xc0011012 && uMsr <= 0xc0011013) && g_enmVendor == CPUMCPUVENDOR_AMD)
+                vbCpuRepDebug("Skipping %#x\n", uMsr);
+            else
+            {
+                /* Read probing normally does it. */
+                uint64_t uValue = 0;
+                bool     fGp    = true;
+                int rc = SUPR3MsrProberRead(uMsr, NIL_RTCPUID, &uValue, &fGp);
+                if (RT_FAILURE(rc))
+                {
+                    RTMemFree(*ppaMsrs);
+                    *ppaMsrs = NULL;
+                    return RTMsgErrorRc(rc, "SUPR3MsrProberRead failed on %#x: %Rrc\n", uMsr, rc);
+                }
+
+                uint32_t fFlags;
+                if (!fGp)
+                    fFlags = 0;
+                /* VIA HACK - writing to 0x0000317e on a quad core make the core unresponsive. */
+                else if (uMsr == 0x0000317e && g_enmVendor == CPUMCPUVENDOR_VIA)
+                {
+                    uValue = 0;
+                    fFlags = VBCPUREPMSR_F_WRITE_ONLY;
+                    fGp    = *pcMsrs == 0
+                          || (*ppaMsrs)[*pcMsrs - 1].uMsr != 0x0000317d
+                          || (*ppaMsrs)[*pcMsrs - 1].fFlags != VBCPUREPMSR_F_WRITE_ONLY;
+                }
+                else
+                {
+                    /* Is it a write only register? */
+#if 0
+                    if (uMsr >= 0x00003170 && uMsr <= 0xc0000090)
+                    {
+                        vbCpuRepDebug("test writing %#x...\n", uMsr);
+                        RTThreadSleep(250);
+                    }
+#endif
+                    fGp = true;
+                    rc = SUPR3MsrProberWrite(uMsr, NIL_RTCPUID, 0, &fGp);
+                    if (RT_FAILURE(rc))
+                    {
+                        RTMemFree(*ppaMsrs);
+                        *ppaMsrs = NULL;
+                        return RTMsgErrorRc(rc, "SUPR3MsrProberWrite failed on %#x: %Rrc\n", uMsr, rc);
+                    }
+                    uValue = 0;
+                    fFlags = VBCPUREPMSR_F_WRITE_ONLY;
+
+                    /*
+                     * Tweaks.  On Intel CPUs we've got trouble detecting
+                     * IA32_BIOS_UPDT_TRIG (0x00000079), so we have to add it manually here.
+                     * Ditto on AMD with PATCH_LOADER (0xc0010020).
+                     */
+                    if (   uMsr == 0x00000079
+                        && fGp
+                        && g_enmMicroarch >= kCpumMicroarch_Intel_P6_Core_Atom_First
+                        && g_enmMicroarch <= kCpumMicroarch_Intel_End)
+                        fGp = false;
+                    if (   uMsr == 0xc0010020
+                        && fGp
+                        && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First
+                        && g_enmMicroarch <= kCpumMicroarch_AMD_End)
+                        fGp = false;
+                }
+
+                if (!fGp)
+                {
+                    /* Add it. */
+                    rc = vbCpuRepMsrsAddOne(ppaMsrs, pcMsrs, uMsr, uValue, fFlags);
+                    if (RT_FAILURE(rc))
+                        return RTMsgErrorRc(rc, "Out of memory (uMsr=%#x).\n", uMsr);
+                    if (   g_enmVendor != CPUMCPUVENDOR_VIA
+                        || uValue
+                        || fFlags)
+                        vbCpuRepDebug("%#010x: uValue=%#llx fFlags=%#x\n", uMsr, uValue, fFlags);
+                }
+            }
+
+            uMsr++;
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Get the name of the specified MSR, if we know it and can handle it.
+ *
+ * Do _NOT_ add any new names here without ALSO at the SAME TIME making sure it
+ * is handled correctly by the PROBING CODE and REPORTED correctly!!
+ *
+ * @returns Pointer to name if handled, NULL if not yet explored.
+ * @param   uMsr                The MSR in question.
+ */
+static const char *getMsrNameHandled(uint32_t uMsr)
+{
+    /** @todo figure out where NCU_EVENT_CORE_MASK might be... */
+    switch (uMsr)
+    {
+        case 0x00000000: return "IA32_P5_MC_ADDR";
+        case 0x00000001: return "IA32_P5_MC_TYPE";
+        case 0x00000006:
+            if (g_enmMicroarch >= kCpumMicroarch_Intel_First && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_First)
+                return NULL; /* TR4 / cache tag on Pentium, but that's for later. */
+            return "IA32_MONITOR_FILTER_LINE_SIZE";
+        //case 0x0000000e: return "P?_TR12"; /* K6-III docs */
+        case 0x00000010: return "IA32_TIME_STAMP_COUNTER";
+        case 0x00000017: return "IA32_PLATFORM_ID";
+        case 0x00000018: return "P6_UNK_0000_0018"; /* P6_M_Dothan. */
+        case 0x0000001b: return "IA32_APIC_BASE";
+        case 0x00000021: return "C2_UNK_0000_0021"; /* Core2_Penryn */
+        case 0x0000002a: return g_fIntelNetBurst ? "P4_EBC_HARD_POWERON" : "EBL_CR_POWERON";
+        case 0x0000002b: return g_fIntelNetBurst ? "P4_EBC_SOFT_POWERON" : NULL;
+        case 0x0000002c: return g_fIntelNetBurst ? "P4_EBC_FREQUENCY_ID" : NULL;
+        case 0x0000002e: return "I7_UNK_0000_002e"; /* SandyBridge, IvyBridge. */
+        case 0x0000002f: return "P6_UNK_0000_002f"; /* P6_M_Dothan. */
+        case 0x00000032: return "P6_UNK_0000_0032"; /* P6_M_Dothan. */
+        case 0x00000033: return "TEST_CTL";
+        case 0x00000034: return "P6_UNK_0000_0034"; /* P6_M_Dothan. */
+        case 0x00000035: return "P6_UNK_0000_0035"; /* P6_M_Dothan. */
+        case 0x00000036: return "I7_UNK_0000_0036"; /* SandyBridge, IvyBridge. */
+        case 0x00000039: return "C2_UNK_0000_0039"; /* Core2_Penryn */
+        case 0x0000003a: return "IA32_FEATURE_CONTROL";
+        case 0x0000003b: return "P6_UNK_0000_003b"; /* P6_M_Dothan. */
+        case 0x0000003e: return "I7_UNK_0000_003e"; /* SandyBridge, IvyBridge. */
+        case 0x0000003f: return "P6_UNK_0000_003f"; /* P6_M_Dothan. */
+        case 0x00000040: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_0_FROM_IP" : "MSR_LASTBRANCH_0";
+        case 0x00000041: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_1_FROM_IP" : "MSR_LASTBRANCH_1";
+        case 0x00000042: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_2_FROM_IP" : "MSR_LASTBRANCH_2";
+        case 0x00000043: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_3_FROM_IP" : "MSR_LASTBRANCH_3";
+        case 0x00000044: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_4_FROM_IP" : "MSR_LASTBRANCH_4";
+        case 0x00000045: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_5_FROM_IP" : "MSR_LASTBRANCH_5";
+        case 0x00000046: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_6_FROM_IP" : "MSR_LASTBRANCH_6";
+        case 0x00000047: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_7_FROM_IP" : "MSR_LASTBRANCH_7";
+        case 0x00000048: return "MSR_LASTBRANCH_8"; /*??*/
+        case 0x00000049: return "MSR_LASTBRANCH_9"; /*??*/
+        case 0x0000004a: return "P6_UNK_0000_004a"; /* P6_M_Dothan. */
+        case 0x0000004b: return "P6_UNK_0000_004b"; /* P6_M_Dothan. */
+        case 0x0000004c: return "P6_UNK_0000_004c"; /* P6_M_Dothan. */
+        case 0x0000004d: return "P6_UNK_0000_004d"; /* P6_M_Dothan. */
+        case 0x0000004e: return "P6_UNK_0000_004e"; /* P6_M_Dothan. */
+        case 0x0000004f: return "P6_UNK_0000_004f"; /* P6_M_Dothan. */
+        case 0x00000050: return "P6_UNK_0000_0050"; /* P6_M_Dothan. */
+        case 0x00000051: return "P6_UNK_0000_0051"; /* P6_M_Dothan. */
+        case 0x00000052: return "P6_UNK_0000_0052"; /* P6_M_Dothan. */
+        case 0x00000053: return "P6_UNK_0000_0053"; /* P6_M_Dothan. */
+        case 0x00000054: return "P6_UNK_0000_0054"; /* P6_M_Dothan. */
+        case 0x00000060: return "MSR_LASTBRANCH_0_TO_IP"; /* Core2_Penryn */
+        case 0x00000061: return "MSR_LASTBRANCH_1_TO_IP"; /* Core2_Penryn */
+        case 0x00000062: return "MSR_LASTBRANCH_2_TO_IP"; /* Core2_Penryn */
+        case 0x00000063: return "MSR_LASTBRANCH_3_TO_IP"; /* Core2_Penryn */
+        case 0x00000064: return "MSR_LASTBRANCH_4_TO_IP"; /* Atom? */
+        case 0x00000065: return "MSR_LASTBRANCH_5_TO_IP";
+        case 0x00000066: return "MSR_LASTBRANCH_6_TO_IP";
+        case 0x00000067: return "MSR_LASTBRANCH_7_TO_IP";
+        case 0x0000006c: return "P6_UNK_0000_006c"; /* P6_M_Dothan. */
+        case 0x0000006d: return "P6_UNK_0000_006d"; /* P6_M_Dothan. */
+        case 0x0000006e: return "P6_UNK_0000_006e"; /* P6_M_Dothan. */
+        case 0x0000006f: return "P6_UNK_0000_006f"; /* P6_M_Dothan. */
+        case 0x00000079: return "IA32_BIOS_UPDT_TRIG";
+        case 0x00000080: return "P4_UNK_0000_0080";
+        case 0x00000088: return "BBL_CR_D0";
+        case 0x00000089: return "BBL_CR_D1";
+        case 0x0000008a: return "BBL_CR_D2";
+        case 0x0000008b: return g_enmVendor == CPUMCPUVENDOR_AMD ? "AMD_K8_PATCH_LEVEL"
+                              : g_fIntelNetBurst ? "IA32_BIOS_SIGN_ID" : "BBL_CR_D3|BIOS_SIGN";
+        case 0x0000008c: return "P6_UNK_0000_008c"; /* P6_M_Dothan. */
+        case 0x0000008d: return "P6_UNK_0000_008d"; /* P6_M_Dothan. */
+        case 0x0000008e: return "P6_UNK_0000_008e"; /* P6_M_Dothan. */
+        case 0x0000008f: return "P6_UNK_0000_008f"; /* P6_M_Dothan. */
+        case 0x00000090: return "P6_UNK_0000_0090"; /* P6_M_Dothan. */
+        case 0x0000009b: return "IA32_SMM_MONITOR_CTL";
+        case 0x000000a8: return "C2_EMTTM_CR_TABLES_0";
+        case 0x000000a9: return "C2_EMTTM_CR_TABLES_1";
+        case 0x000000aa: return "C2_EMTTM_CR_TABLES_2";
+        case 0x000000ab: return "C2_EMTTM_CR_TABLES_3";
+        case 0x000000ac: return "C2_EMTTM_CR_TABLES_4";
+        case 0x000000ad: return "C2_EMTTM_CR_TABLES_5";
+        case 0x000000ae: return "P6_UNK_0000_00ae"; /* P6_M_Dothan. */
+        case 0x000000c1: return "IA32_PMC0";
+        case 0x000000c2: return "IA32_PMC1";
+        case 0x000000c3: return "IA32_PMC2";
+        case 0x000000c4: return "IA32_PMC3";
+        /* PMC4+ first seen on SandyBridge. The earlier cut off is just to be
+           on the safe side as we must avoid P6_M_Dothan and possibly others. */
+        case 0x000000c5: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC4" : NULL;
+        case 0x000000c6: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC5" : NULL;
+        case 0x000000c7: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC6" : "P6_UNK_0000_00c7"; /* P6_M_Dothan. */
+        case 0x000000c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC7" : NULL;
+        case 0x000000cd: return "P6_UNK_0000_00cd"; /* P6_M_Dothan. */
+        case 0x000000ce: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PLATFORM_INFO" : "P6_UNK_0000_00ce"; /* P6_M_Dothan. */
+        case 0x000000cf: return "C2_UNK_0000_00cf"; /* Core2_Penryn. */
+        case 0x000000e0: return "C2_UNK_0000_00e0"; /* Core2_Penryn. */
+        case 0x000000e1: return "C2_UNK_0000_00e1"; /* Core2_Penryn. */
+        case 0x000000e2: return "MSR_PKG_CST_CONFIG_CONTROL";
+        case 0x000000e3: return "C2_SMM_CST_MISC_INFO"; /* Core2_Penryn. */
+        case 0x000000e4: return "MSR_PMG_IO_CAPTURE_BASE";
+        case 0x000000e5: return "C2_UNK_0000_00e5"; /* Core2_Penryn. */
+        case 0x000000e7: return "IA32_MPERF";
+        case 0x000000e8: return "IA32_APERF";
+        case 0x000000ee: return "C1_EXT_CONFIG"; /* Core2_Penryn. msrtool lists it for Core1 as well. */
+        case 0x000000fe: return "IA32_MTRRCAP";
+        case 0x00000102: return "I7_IB_UNK_0000_0102"; /* IvyBridge. */
+        case 0x00000103: return "I7_IB_UNK_0000_0103"; /* IvyBridge. */
+        case 0x00000104: return "I7_IB_UNK_0000_0104"; /* IvyBridge. */
+        case 0x00000116: return "BBL_CR_ADDR";
+        case 0x00000118: return "BBL_CR_DECC";
+        case 0x00000119: return "BBL_CR_CTL";
+        case 0x0000011a: return "BBL_CR_TRIG";
+        case 0x0000011b: return "P6_UNK_0000_011b"; /* P6_M_Dothan. */
+        case 0x0000011c: return "C2_UNK_0000_011c"; /* Core2_Penryn. */
+        case 0x0000011e: return "BBL_CR_CTL3";
+        case 0x00000130: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
+                             || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
+                              ? "CPUID1_FEATURE_MASK" : NULL;
+        case 0x00000131: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
+                             || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
+                              ? "CPUID80000001_FEATURE_MASK" : "P6_UNK_0000_0131" /* P6_M_Dothan. */;
+        case 0x00000132: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                              ? "CPUID1_FEATURE_MASK" : NULL;
+        case 0x00000133: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                              ? "CPUIDD_01_FEATURE_MASK" : NULL;
+        case 0x00000134: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                              ? "CPUID80000001_FEATURE_MASK" : NULL;
+        case 0x0000013c: return "I7_SB_AES_NI_CTL"; /* SandyBridge. Bit 0 is lock bit, bit 1 disables AES-NI. */
+        case 0x00000140: return "I7_IB_UNK_0000_0140"; /* IvyBridge. */
+        case 0x00000142: return "I7_IB_UNK_0000_0142"; /* IvyBridge. */
+        case 0x0000014e: return "P6_UNK_0000_014e"; /* P6_M_Dothan. */
+        case 0x0000014f: return "P6_UNK_0000_014f"; /* P6_M_Dothan. */
+        case 0x00000150: return "P6_UNK_0000_0150"; /* P6_M_Dothan. */
+        case 0x00000151: return "P6_UNK_0000_0151"; /* P6_M_Dothan. */
+        case 0x00000154: return "P6_UNK_0000_0154"; /* P6_M_Dothan. */
+        case 0x0000015b: return "P6_UNK_0000_015b"; /* P6_M_Dothan. */
+        case 0x0000015e: return "C2_UNK_0000_015e"; /* Core2_Penryn. */
+        case 0x0000015f: return "C1_DTS_CAL_CTRL"; /* Core2_Penryn. msrtool only docs this for core1! */
+        case 0x00000174: return "IA32_SYSENTER_CS";
+        case 0x00000175: return "IA32_SYSENTER_ESP";
+        case 0x00000176: return "IA32_SYSENTER_EIP";
+        case 0x00000179: return "IA32_MCG_CAP";
+        case 0x0000017a: return "IA32_MCG_STATUS";
+        case 0x0000017b: return "IA32_MCG_CTL";
+        case 0x0000017f: return "I7_SB_ERROR_CONTROL"; /* SandyBridge. */
+        case 0x00000180: return g_fIntelNetBurst ? "MSR_MCG_RAX"       : NULL;
+        case 0x00000181: return g_fIntelNetBurst ? "MSR_MCG_RBX"       : NULL;
+        case 0x00000182: return g_fIntelNetBurst ? "MSR_MCG_RCX"       : NULL;
+        case 0x00000183: return g_fIntelNetBurst ? "MSR_MCG_RDX"       : NULL;
+        case 0x00000184: return g_fIntelNetBurst ? "MSR_MCG_RSI"       : NULL;
+        case 0x00000185: return g_fIntelNetBurst ? "MSR_MCG_RDI"       : NULL;
+        case 0x00000186: return g_fIntelNetBurst ? "MSR_MCG_RBP"       : "IA32_PERFEVTSEL0";
+        case 0x00000187: return g_fIntelNetBurst ? "MSR_MCG_RSP"       : "IA32_PERFEVTSEL1";
+        case 0x00000188: return g_fIntelNetBurst ? "MSR_MCG_RFLAGS"    : "IA32_PERFEVTSEL2";
+        case 0x00000189: return g_fIntelNetBurst ? "MSR_MCG_RIP"       : "IA32_PERFEVTSEL3";
+        case 0x0000018a: return g_fIntelNetBurst ? "MSR_MCG_MISC"      : "IA32_PERFEVTSEL4";
+        case 0x0000018b: return g_fIntelNetBurst ? "MSR_MCG_RESERVED1" : "IA32_PERFEVTSEL5";
+        case 0x0000018c: return g_fIntelNetBurst ? "MSR_MCG_RESERVED2" : "IA32_PERFEVTSEL6";
+        case 0x0000018d: return g_fIntelNetBurst ? "MSR_MCG_RESERVED3" : "IA32_PERFEVTSEL7";
+        case 0x0000018e: return g_fIntelNetBurst ? "MSR_MCG_RESERVED4" : "IA32_PERFEVTSEL8";
+        case 0x0000018f: return g_fIntelNetBurst ? "MSR_MCG_RESERVED5" : "IA32_PERFEVTSEL9";
+        case 0x00000190: return g_fIntelNetBurst ? "MSR_MCG_R8"        : NULL;
+        case 0x00000191: return g_fIntelNetBurst ? "MSR_MCG_R9"        : NULL;
+        case 0x00000192: return g_fIntelNetBurst ? "MSR_MCG_R10"       : NULL;
+        case 0x00000193: return g_fIntelNetBurst ? "MSR_MCG_R11"       : "C2_UNK_0000_0193";
+        case 0x00000194: return g_fIntelNetBurst ? "MSR_MCG_R12"       : "CLOCK_FLEX_MAX";
+        case 0x00000195: return g_fIntelNetBurst ? "MSR_MCG_R13"       : NULL;
+        case 0x00000196: return g_fIntelNetBurst ? "MSR_MCG_R14"       : NULL;
+        case 0x00000197: return g_fIntelNetBurst ? "MSR_MCG_R15"       : NULL;
+        case 0x00000198: return "IA32_PERF_STATUS";
+        case 0x00000199: return "IA32_PERF_CTL";
+        case 0x0000019a: return "IA32_CLOCK_MODULATION";
+        case 0x0000019b: return "IA32_THERM_INTERRUPT";
+        case 0x0000019c: return "IA32_THERM_STATUS";
+        case 0x0000019d: return "IA32_THERM2_CTL";
+        case 0x0000019e: return "P6_UNK_0000_019e"; /* P6_M_Dothan. */
+        case 0x0000019f: return "P6_UNK_0000_019f"; /* P6_M_Dothan. */
+        case 0x000001a0: return "IA32_MISC_ENABLE";
+        case 0x000001a1: return g_fIntelNetBurst ? "MSR_PLATFORM_BRV" : "P6_UNK_0000_01a1" /* P6_M_Dothan. */;
+        case 0x000001a2: return g_fIntelNetBurst ? "P4_UNK_0000_01a2" : "I7_MSR_TEMPERATURE_TARGET" /* SandyBridge, IvyBridge. */;
+        case 0x000001a4: return "I7_UNK_0000_01a4"; /* SandyBridge, IvyBridge. */
+        case 0x000001a6: return "I7_MSR_OFFCORE_RSP_0";
+        case 0x000001a7: return "I7_MSR_OFFCORE_RSP_1";
+        case 0x000001a8: return "I7_UNK_0000_01a8"; /* SandyBridge, IvyBridge. */
+        case 0x000001aa: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "MSR_MISC_PWR_MGMT" : "P6_PIC_SENS_CFG" /* Pentium M. */;
+        case 0x000001ad: return "I7_MSR_TURBO_RATIO_LIMIT"; /* SandyBridge+, Silvermount+ */
+        case 0x000001ae: return "P6_UNK_0000_01ae"; /* P6_M_Dothan. */
+        case 0x000001af: return "P6_UNK_0000_01af"; /* P6_M_Dothan. */
+        case 0x000001b0: return "IA32_ENERGY_PERF_BIAS";
+        case 0x000001b1: return "IA32_PACKAGE_THERM_STATUS";
+        case 0x000001b2: return "IA32_PACKAGE_THERM_INTERRUPT";
+        case 0x000001bf: return "C2_UNK_0000_01bf"; /* Core2_Penryn. */
+        case 0x000001c6: return "I7_UNK_0000_01c6"; /* SandyBridge*/
+        case 0x000001c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Nehalem ? "MSR_LBR_SELECT" : NULL;
+        case 0x000001c9: return    g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
+                                && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_End
+                              ? "MSR_LASTBRANCH_TOS" : NULL /* Pentium M Dothan seems to have something else here. */;
+        case 0x000001d3: return "P6_UNK_0000_01d3"; /* P6_M_Dothan. */
+        case 0x000001d7: return g_fIntelNetBurst ? "MSR_LER_FROM_LIP" : NULL;
+        case 0x000001d8: return g_fIntelNetBurst ? "MSR_LER_TO_LIP"   : NULL;
+        case 0x000001d9: return "IA32_DEBUGCTL";
+        case 0x000001da: return g_fIntelNetBurst ? "MSR_LASTBRANCH_TOS" : NULL;
+        case 0x000001db: return g_fIntelNetBurst ? "P6_LASTBRANCH_0" : "P6_LAST_BRANCH_FROM_IP"; /* Not exclusive to P6, also AMD. */
+        case 0x000001dc: return g_fIntelNetBurst ? "P6_LASTBRANCH_1" : "P6_LAST_BRANCH_TO_IP";
+        case 0x000001dd: return g_fIntelNetBurst ? "P6_LASTBRANCH_2" : "P6_LAST_INT_FROM_IP";
+        case 0x000001de: return g_fIntelNetBurst ? "P6_LASTBRANCH_3" : "P6_LAST_INT_TO_IP";
+        case 0x000001e0: return "MSR_ROB_CR_BKUPTMPDR6";
+        case 0x000001e1: return "I7_SB_UNK_0000_01e1";
+        case 0x000001ef: return "I7_SB_UNK_0000_01ef";
+        case 0x000001f0: return "I7_VLW_CAPABILITY"; /* SandyBridge.  Bit 1 is A20M and was implemented incorrectly (AAJ49). */
+        case 0x000001f2: return "IA32_SMRR_PHYSBASE";
+        case 0x000001f3: return "IA32_SMRR_PHYSMASK";
+        case 0x000001f8: return "IA32_PLATFORM_DCA_CAP";
+        case 0x000001f9: return "IA32_CPU_DCA_CAP";
+        case 0x000001fa: return "IA32_DCA_0_CAP";
+        case 0x000001fc: return "I7_MSR_POWER_CTL";
+
+        case 0x00000200: return "IA32_MTRR_PHYS_BASE0";
+        case 0x00000202: return "IA32_MTRR_PHYS_BASE1";
+        case 0x00000204: return "IA32_MTRR_PHYS_BASE2";
+        case 0x00000206: return "IA32_MTRR_PHYS_BASE3";
+        case 0x00000208: return "IA32_MTRR_PHYS_BASE4";
+        case 0x0000020a: return "IA32_MTRR_PHYS_BASE5";
+        case 0x0000020c: return "IA32_MTRR_PHYS_BASE6";
+        case 0x0000020e: return "IA32_MTRR_PHYS_BASE7";
+        case 0x00000210: return "IA32_MTRR_PHYS_BASE8";
+        case 0x00000212: return "IA32_MTRR_PHYS_BASE9";
+        case 0x00000214: return "IA32_MTRR_PHYS_BASE10";
+        case 0x00000216: return "IA32_MTRR_PHYS_BASE11";
+        case 0x00000218: return "IA32_MTRR_PHYS_BASE12";
+        case 0x0000021a: return "IA32_MTRR_PHYS_BASE13";
+        case 0x0000021c: return "IA32_MTRR_PHYS_BASE14";
+        case 0x0000021e: return "IA32_MTRR_PHYS_BASE15";
+
+        case 0x00000201: return "IA32_MTRR_PHYS_MASK0";
+        case 0x00000203: return "IA32_MTRR_PHYS_MASK1";
+        case 0x00000205: return "IA32_MTRR_PHYS_MASK2";
+        case 0x00000207: return "IA32_MTRR_PHYS_MASK3";
+        case 0x00000209: return "IA32_MTRR_PHYS_MASK4";
+        case 0x0000020b: return "IA32_MTRR_PHYS_MASK5";
+        case 0x0000020d: return "IA32_MTRR_PHYS_MASK6";
+        case 0x0000020f: return "IA32_MTRR_PHYS_MASK7";
+        case 0x00000211: return "IA32_MTRR_PHYS_MASK8";
+        case 0x00000213: return "IA32_MTRR_PHYS_MASK9";
+        case 0x00000215: return "IA32_MTRR_PHYS_MASK10";
+        case 0x00000217: return "IA32_MTRR_PHYS_MASK11";
+        case 0x00000219: return "IA32_MTRR_PHYS_MASK12";
+        case 0x0000021b: return "IA32_MTRR_PHYS_MASK13";
+        case 0x0000021d: return "IA32_MTRR_PHYS_MASK14";
+        case 0x0000021f: return "IA32_MTRR_PHYS_MASK15";
+
+        case 0x00000250: return "IA32_MTRR_FIX64K_00000";
+        case 0x00000258: return "IA32_MTRR_FIX16K_80000";
+        case 0x00000259: return "IA32_MTRR_FIX16K_A0000";
+        case 0x00000268: return "IA32_MTRR_FIX4K_C0000";
+        case 0x00000269: return "IA32_MTRR_FIX4K_C8000";
+        case 0x0000026a: return "IA32_MTRR_FIX4K_D0000";
+        case 0x0000026b: return "IA32_MTRR_FIX4K_D8000";
+        case 0x0000026c: return "IA32_MTRR_FIX4K_E0000";
+        case 0x0000026d: return "IA32_MTRR_FIX4K_E8000";
+        case 0x0000026e: return "IA32_MTRR_FIX4K_F0000";
+        case 0x0000026f: return "IA32_MTRR_FIX4K_F8000";
+        case 0x00000277: return "IA32_PAT";
+        case 0x00000280: return "IA32_MC0_CTL2";
+        case 0x00000281: return "IA32_MC1_CTL2";
+        case 0x00000282: return "IA32_MC2_CTL2";
+        case 0x00000283: return "IA32_MC3_CTL2";
+        case 0x00000284: return "IA32_MC4_CTL2";
+        case 0x00000285: return "IA32_MC5_CTL2";
+        case 0x00000286: return "IA32_MC6_CTL2";
+        case 0x00000287: return "IA32_MC7_CTL2";
+        case 0x00000288: return "IA32_MC8_CTL2";
+        case 0x00000289: return "IA32_MC9_CTL2";
+        case 0x0000028a: return "IA32_MC10_CTL2";
+        case 0x0000028b: return "IA32_MC11_CTL2";
+        case 0x0000028c: return "IA32_MC12_CTL2";
+        case 0x0000028d: return "IA32_MC13_CTL2";
+        case 0x0000028e: return "IA32_MC14_CTL2";
+        case 0x0000028f: return "IA32_MC15_CTL2";
+        case 0x00000290: return "IA32_MC16_CTL2";
+        case 0x00000291: return "IA32_MC17_CTL2";
+        case 0x00000292: return "IA32_MC18_CTL2";
+        case 0x00000293: return "IA32_MC19_CTL2";
+        case 0x00000294: return "IA32_MC20_CTL2";
+        case 0x00000295: return "IA32_MC21_CTL2";
+        //case 0x00000296: return "IA32_MC22_CTL2";
+        //case 0x00000297: return "IA32_MC23_CTL2";
+        //case 0x00000298: return "IA32_MC24_CTL2";
+        //case 0x00000299: return "IA32_MC25_CTL2";
+        //case 0x0000029a: return "IA32_MC26_CTL2";
+        //case 0x0000029b: return "IA32_MC27_CTL2";
+        //case 0x0000029c: return "IA32_MC28_CTL2";
+        //case 0x0000029d: return "IA32_MC29_CTL2";
+        //case 0x0000029e: return "IA32_MC30_CTL2";
+        //case 0x0000029f: return "IA32_MC31_CTL2";
+        case 0x000002e0: return "I7_SB_NO_EVICT_MODE"; /* (Bits 1 & 0 are said to have something to do with no-evict cache mode used during early boot.) */
+        case 0x000002e6: return "I7_IB_UNK_0000_02e6"; /* IvyBridge */
+        case 0x000002e7: return "I7_IB_UNK_0000_02e7"; /* IvyBridge */
+        case 0x000002ff: return "IA32_MTRR_DEF_TYPE";
+        case 0x00000300: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER0"   : "I7_SB_UNK_0000_0300" /* SandyBridge */;
+        case 0x00000301: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER1"   : NULL;
+        case 0x00000302: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER2"   : NULL;
+        case 0x00000303: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER3"   : NULL;
+        case 0x00000304: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER0"    : NULL;
+        case 0x00000305: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER1"    : "I7_SB_UNK_0000_0305" /* SandyBridge, IvyBridge */;
+        case 0x00000306: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER2"    : NULL;
+        case 0x00000307: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER3"    : NULL;
+        case 0x00000308: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER0" : NULL;
+        case 0x00000309: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER1" : "IA32_FIXED_CTR0";
+        case 0x0000030a: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER2" : "IA32_FIXED_CTR1";
+        case 0x0000030b: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER3" : "IA32_FIXED_CTR2";
+        case 0x0000030c: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER0" : NULL;
+        case 0x0000030d: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER1" : NULL;
+        case 0x0000030e: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER2" : NULL;
+        case 0x0000030f: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER3" : NULL;
+        case 0x00000310: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER4" : NULL;
+        case 0x00000311: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER5" : NULL;
+        case 0x00000345: return "IA32_PERF_CAPABILITIES";
+        case 0x00000360: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR0"   : NULL;
+        case 0x00000361: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR1"   : NULL;
+        case 0x00000362: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR2"   : NULL;
+        case 0x00000363: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR3"   : NULL;
+        case 0x00000364: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR0"    : NULL;
+        case 0x00000365: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR1"    : NULL;
+        case 0x00000366: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR2"    : NULL;
+        case 0x00000367: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR3"    : NULL;
+        case 0x00000368: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR0" : NULL;
+        case 0x00000369: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR1" : NULL;
+        case 0x0000036a: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR2" : NULL;
+        case 0x0000036b: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR3" : NULL;
+        case 0x0000036c: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR0"    : NULL;
+        case 0x0000036d: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR1"    : NULL;
+        case 0x0000036e: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR2"    : NULL;
+        case 0x0000036f: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR3"    : NULL;
+        case 0x00000370: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR4"    : NULL;
+        case 0x00000371: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR5"    : NULL;
+        case 0x0000038d: return "IA32_FIXED_CTR_CTRL";
+        case 0x0000038e: return "IA32_PERF_GLOBAL_STATUS";
+        case 0x0000038f: return "IA32_PERF_GLOBAL_CTRL";
+        case 0x00000390: return "IA32_PERF_GLOBAL_OVF_CTRL";
+        case 0x00000391: return "I7_UNC_PERF_GLOBAL_CTRL";             /* S,H,X */
+        case 0x00000392: return "I7_UNC_PERF_GLOBAL_STATUS";           /* S,H,X */
+        case 0x00000393: return "I7_UNC_PERF_GLOBAL_OVF_CTRL";         /* X. ASSUMING this is the same on sandybridge and later. */
+        case 0x00000394: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PERF_FIXED_CTR"  /* X */    : "I7_UNC_PERF_FIXED_CTR_CTRL"; /* >= S,H */
+        case 0x00000395: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PERF_FIXED_CTR_CTRL" /* X*/ : "I7_UNC_PERF_FIXED_CTR";      /* >= S,H */
+        case 0x00000396: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_ADDR_OPCODE_MATCH" /* X */  : "I7_UNC_CBO_CONFIG";          /* >= S,H */
+        case 0x00000397: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_IvyBridge   ? NULL                                : "I7_IB_UNK_0000_0397";
+        case 0x0000039c: return "I7_SB_MSR_PEBS_NUM_ALT";
+        case 0x000003a0: return g_fIntelNetBurst ? "P4_MSR_BSU_ESCR0"   : NULL;
+        case 0x000003a1: return g_fIntelNetBurst ? "P4_MSR_BSU_ESCR1"   : NULL;
+        case 0x000003a2: return g_fIntelNetBurst ? "P4_MSR_FSB_ESCR0"   : NULL;
+        case 0x000003a3: return g_fIntelNetBurst ? "P4_MSR_FSB_ESCR1"   : NULL;
+        case 0x000003a4: return g_fIntelNetBurst ? "P4_MSR_FIRM_ESCR0"  : NULL;
+        case 0x000003a5: return g_fIntelNetBurst ? "P4_MSR_FIRM_ESCR1"  : NULL;
+        case 0x000003a6: return g_fIntelNetBurst ? "P4_MSR_FLAME_ESCR0" : NULL;
+        case 0x000003a7: return g_fIntelNetBurst ? "P4_MSR_FLAME_ESCR1" : NULL;
+        case 0x000003a8: return g_fIntelNetBurst ? "P4_MSR_DAC_ESCR0"   : NULL;
+        case 0x000003a9: return g_fIntelNetBurst ? "P4_MSR_DAC_ESCR1"   : NULL;
+        case 0x000003aa: return g_fIntelNetBurst ? "P4_MSR_MOB_ESCR0"   : NULL;
+        case 0x000003ab: return g_fIntelNetBurst ? "P4_MSR_MOB_ESCR1"   : NULL;
+        case 0x000003ac: return g_fIntelNetBurst ? "P4_MSR_PMH_ESCR0"   : NULL;
+        case 0x000003ad: return g_fIntelNetBurst ? "P4_MSR_PMH_ESCR1"   : NULL;
+        case 0x000003ae: return g_fIntelNetBurst ? "P4_MSR_SAAT_ESCR0"  : NULL;
+        case 0x000003af: return g_fIntelNetBurst ? "P4_MSR_SAAT_ESCR1"  : NULL;
+        case 0x000003b0: return g_fIntelNetBurst ? "P4_MSR_U2L_ESCR0" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC0" /* X */               : "I7_UNC_ARB_PERF_CTR0";       /* >= S,H */
+        case 0x000003b1: return g_fIntelNetBurst ? "P4_MSR_U2L_ESCR1" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC1" /* X */               : "I7_UNC_ARB_PERF_CTR1";       /* >= S,H */
+        case 0x000003b2: return g_fIntelNetBurst ? "P4_MSR_BPU_ESCR0" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC2" /* X */               : "I7_UNC_ARB_PERF_EVT_SEL0";   /* >= S,H */
+        case 0x000003b3: return g_fIntelNetBurst ? "P4_MSR_BPU_ESCR1" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC3" /* X */               : "I7_UNC_ARB_PERF_EVT_SEL1";   /* >= S,H */
+        case 0x000003b4: return g_fIntelNetBurst ? "P4_MSR_IS_ESCR0"    : "I7_UNC_PMC4";
+        case 0x000003b5: return g_fIntelNetBurst ? "P4_MSR_IS_ESCR1"    : "I7_UNC_PMC5";
+        case 0x000003b6: return g_fIntelNetBurst ? "P4_MSR_ITLB_ESCR0"  : "I7_UNC_PMC6";
+        case 0x000003b7: return g_fIntelNetBurst ? "P4_MSR_ITLB_ESCR1"  : "I7_UNC_PMC7";
+        case 0x000003b8: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR0"   : NULL;
+        case 0x000003b9: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR1"   : NULL;
+        case 0x000003ba: return g_fIntelNetBurst ? "P4_MSR_IQ_ESCR0"    : NULL;
+        case 0x000003bb: return g_fIntelNetBurst ? "P4_MSR_IQ_ESCR1"    : NULL;
+        case 0x000003bc: return g_fIntelNetBurst ? "P4_MSR_RAT_ESCR0"   : NULL;
+        case 0x000003bd: return g_fIntelNetBurst ? "P4_MSR_RAT_ESCR1"   : NULL;
+        case 0x000003be: return g_fIntelNetBurst ? "P4_MSR_SSU_ESCR0"   : NULL;
+        case 0x000003c0: return g_fIntelNetBurst ? "P4_MSR_MS_ESCR0"    : "I7_UNC_PERF_EVT_SEL0";
+        case 0x000003c1: return g_fIntelNetBurst ? "P4_MSR_MS_ESCR1"    : "I7_UNC_PERF_EVT_SEL1";
+        case 0x000003c2: return g_fIntelNetBurst ? "P4_MSR_TBPU_ESCR0"  : "I7_UNC_PERF_EVT_SEL2";
+        case 0x000003c3: return g_fIntelNetBurst ? "P4_MSR_TBPU_ESCR1"  : "I7_UNC_PERF_EVT_SEL3";
+        case 0x000003c4: return g_fIntelNetBurst ? "P4_MSR_TC_ESCR0"    : "I7_UNC_PERF_EVT_SEL4";
+        case 0x000003c5: return g_fIntelNetBurst ? "P4_MSR_TC_ESCR1"    : "I7_UNC_PERF_EVT_SEL5";
+        case 0x000003c6: return g_fIntelNetBurst ? NULL                 : "I7_UNC_PERF_EVT_SEL6";
+        case 0x000003c7: return g_fIntelNetBurst ? NULL                 : "I7_UNC_PERF_EVT_SEL7";
+        case 0x000003c8: return g_fIntelNetBurst ? "P4_MSR_IX_ESCR0"    : NULL;
+        case 0x000003c9: return g_fIntelNetBurst ? "P4_MSR_IX_ESCR0"    : NULL;
+        case 0x000003ca: return g_fIntelNetBurst ? "P4_MSR_ALF_ESCR0"   : NULL;
+        case 0x000003cb: return g_fIntelNetBurst ? "P4_MSR_ALF_ESCR1"   : NULL;
+        case 0x000003cc: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR2"   : NULL;
+        case 0x000003cd: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR3"   : NULL;
+        case 0x000003e0: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR4"   : NULL;
+        case 0x000003e1: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR5"   : NULL;
+        case 0x000003f0: return g_fIntelNetBurst ? "P4_MSR_TC_PRECISE_EVENT" : NULL;
+        case 0x000003f1: return "IA32_PEBS_ENABLE";
+        case 0x000003f2: return g_fIntelNetBurst ? "P4_MSR_PEBS_MATRIX_VERT" : "IA32_PEBS_ENABLE";
+        case 0x000003f3: return g_fIntelNetBurst ? "P4_UNK_0000_03f3" : NULL;
+        case 0x000003f4: return g_fIntelNetBurst ? "P4_UNK_0000_03f4" : NULL;
+        case 0x000003f5: return g_fIntelNetBurst ? "P4_UNK_0000_03f5" : NULL;
+        case 0x000003f6: return g_fIntelNetBurst ? "P4_UNK_0000_03f6" : "I7_MSR_PEBS_LD_LAT";
+        case 0x000003f7: return g_fIntelNetBurst ? "P4_UNK_0000_03f7" : "I7_MSR_PEBS_LD_LAT";
+        case 0x000003f8: return g_fIntelNetBurst ? "P4_UNK_0000_03f8" : "I7_MSR_PKG_C3_RESIDENCY";
+        case 0x000003f9: return "I7_MSR_PKG_C6_RESIDENCY";
+        case 0x000003fa: return "I7_MSR_PKG_C7_RESIDENCY";
+        case 0x000003fc: return "I7_MSR_CORE_C3_RESIDENCY";
+        case 0x000003fd: return "I7_MSR_CORE_C6_RESIDENCY";
+        case 0x000003fe: return "I7_MSR_CORE_C7_RESIDENCY";
+        case 0x00000478: return g_enmMicroarch == kCpumMicroarch_Intel_Core2_Penryn ? "CPUID1_FEATURE_MASK" : NULL;
+        case 0x00000480: return "IA32_VMX_BASIC";
+        case 0x00000481: return "IA32_VMX_PINBASED_CTLS";
+        case 0x00000482: return "IA32_VMX_PROCBASED_CTLS";
+        case 0x00000483: return "IA32_VMX_EXIT_CTLS";
+        case 0x00000484: return "IA32_VMX_ENTRY_CTLS";
+        case 0x00000485: return "IA32_VMX_MISC";
+        case 0x00000486: return "IA32_VMX_CR0_FIXED0";
+        case 0x00000487: return "IA32_VMX_CR0_FIXED1";
+        case 0x00000488: return "IA32_VMX_CR4_FIXED0";
+        case 0x00000489: return "IA32_VMX_CR4_FIXED1";
+        case 0x0000048a: return "IA32_VMX_VMCS_ENUM";
+        case 0x0000048b: return "IA32_VMX_PROCBASED_CTLS2";
+        case 0x0000048c: return "IA32_VMX_EPT_VPID_CAP";
+        case 0x0000048d: return "IA32_VMX_TRUE_PINBASED_CTLS";
+        case 0x0000048e: return "IA32_VMX_TRUE_PROCBASED_CTLS";
+        case 0x0000048f: return "IA32_VMX_TRUE_EXIT_CTLS";
+        case 0x00000490: return "IA32_VMX_TRUE_ENTRY_CTLS";
+        case 0x000004c1: return "IA32_A_PMC0";
+        case 0x000004c2: return "IA32_A_PMC1";
+        case 0x000004c3: return "IA32_A_PMC2";
+        case 0x000004c4: return "IA32_A_PMC3";
+        case 0x000004c5: return "IA32_A_PMC4";
+        case 0x000004c6: return "IA32_A_PMC5";
+        case 0x000004c7: return "IA32_A_PMC6";
+        case 0x000004c8: return "IA32_A_PMC7";
+        case 0x000004f8: return "C2_UNK_0000_04f8"; /* Core2_Penryn. */
+        case 0x000004f9: return "C2_UNK_0000_04f9"; /* Core2_Penryn. */
+        case 0x000004fa: return "C2_UNK_0000_04fa"; /* Core2_Penryn. */
+        case 0x000004fb: return "C2_UNK_0000_04fb"; /* Core2_Penryn. */
+        case 0x000004fc: return "C2_UNK_0000_04fc"; /* Core2_Penryn. */
+        case 0x000004fd: return "C2_UNK_0000_04fd"; /* Core2_Penryn. */
+        case 0x000004fe: return "C2_UNK_0000_04fe"; /* Core2_Penryn. */
+        case 0x000004ff: return "C2_UNK_0000_04ff"; /* Core2_Penryn. */
+        case 0x00000502: return "I7_SB_UNK_0000_0502";
+        case 0x00000590: return "C2_UNK_0000_0590"; /* Core2_Penryn. */
+        case 0x00000591: return "C2_UNK_0000_0591"; /* Core2_Penryn. */
+        case 0x000005a0: return "C2_PECI_CTL"; /* Core2_Penryn. */
+        case 0x000005a1: return "C2_UNK_0000_05a1"; /* Core2_Penryn. */
+        case 0x00000600: return "IA32_DS_AREA";
+        case 0x00000601: return "I7_SB_MSR_VR_CURRENT_CONFIG"; /* SandyBridge, IvyBridge. */
+        case 0x00000602: return "I7_IB_UNK_0000_0602";
+        case 0x00000603: return "I7_SB_MSR_VR_MISC_CONFIG"; /* SandyBridge, IvyBridge. */
+        case 0x00000604: return "I7_IB_UNK_0000_0602";
+        case 0x00000606: return "I7_SB_MSR_RAPL_POWER_UNIT"; /* SandyBridge, IvyBridge. */
+        case 0x0000060a: return "I7_SB_MSR_PKGC3_IRTL"; /* SandyBridge, IvyBridge. */
+        case 0x0000060b: return "I7_SB_MSR_PKGC6_IRTL"; /* SandyBridge, IvyBridge. */
+        case 0x0000060c: return "I7_SB_MSR_PKGC7_IRTL"; /* SandyBridge, IvyBridge. */
+        case 0x0000060d: return "I7_SB_MSR_PKG_C2_RESIDENCY"; /* SandyBridge, IvyBridge. */
+        case 0x00000610: return "I7_SB_MSR_PKG_POWER_LIMIT";
+        case 0x00000611: return "I7_SB_MSR_PKG_ENERGY_STATUS";
+        case 0x00000613: return "I7_SB_MSR_PKG_PERF_STATUS";
+        case 0x00000614: return "I7_SB_MSR_PKG_POWER_INFO";
+        case 0x00000618: return "I7_SB_MSR_DRAM_POWER_LIMIT";
+        case 0x00000619: return "I7_SB_MSR_DRAM_ENERGY_STATUS";
+        case 0x0000061b: return "I7_SB_MSR_DRAM_PERF_STATUS";
+        case 0x0000061c: return "I7_SB_MSR_DRAM_POWER_INFO";
+        case 0x00000638: return "I7_SB_MSR_PP0_POWER_LIMIT";
+        case 0x00000639: return "I7_SB_MSR_PP0_ENERGY_STATUS";
+        case 0x0000063a: return "I7_SB_MSR_PP0_POLICY";
+        case 0x0000063b: return "I7_SB_MSR_PP0_PERF_STATUS";
+        case 0x00000640: return "I7_HW_MSR_PP0_POWER_LIMIT";
+        case 0x00000641: return "I7_HW_MSR_PP0_ENERGY_STATUS";
+        case 0x00000642: return "I7_HW_MSR_PP0_POLICY";
+        case 0x00000648: return "I7_IB_MSR_CONFIG_TDP_NOMINAL";
+        case 0x00000649: return "I7_IB_MSR_CONFIG_TDP_LEVEL1";
+        case 0x0000064a: return "I7_IB_MSR_CONFIG_TDP_LEVEL2";
+        case 0x0000064b: return "I7_IB_MSR_CONFIG_TDP_CONTROL";
+        case 0x0000064c: return "I7_IB_MSR_TURBO_ACTIVATION_RATIO";
+        case 0x00000680: return "MSR_LASTBRANCH_0_FROM_IP";
+        case 0x00000681: return "MSR_LASTBRANCH_1_FROM_IP";
+        case 0x00000682: return "MSR_LASTBRANCH_2_FROM_IP";
+        case 0x00000683: return "MSR_LASTBRANCH_3_FROM_IP";
+        case 0x00000684: return "MSR_LASTBRANCH_4_FROM_IP";
+        case 0x00000685: return "MSR_LASTBRANCH_5_FROM_IP";
+        case 0x00000686: return "MSR_LASTBRANCH_6_FROM_IP";
+        case 0x00000687: return "MSR_LASTBRANCH_7_FROM_IP";
+        case 0x00000688: return "MSR_LASTBRANCH_8_FROM_IP";
+        case 0x00000689: return "MSR_LASTBRANCH_9_FROM_IP";
+        case 0x0000068a: return "MSR_LASTBRANCH_10_FROM_IP";
+        case 0x0000068b: return "MSR_LASTBRANCH_11_FROM_IP";
+        case 0x0000068c: return "MSR_LASTBRANCH_12_FROM_IP";
+        case 0x0000068d: return "MSR_LASTBRANCH_13_FROM_IP";
+        case 0x0000068e: return "MSR_LASTBRANCH_14_FROM_IP";
+        case 0x0000068f: return "MSR_LASTBRANCH_15_FROM_IP";
+        case 0x000006c0: return "MSR_LASTBRANCH_0_TO_IP";
+        case 0x000006c1: return "MSR_LASTBRANCH_1_TO_IP";
+        case 0x000006c2: return "MSR_LASTBRANCH_2_TO_IP";
+        case 0x000006c3: return "MSR_LASTBRANCH_3_TO_IP";
+        case 0x000006c4: return "MSR_LASTBRANCH_4_TO_IP";
+        case 0x000006c5: return "MSR_LASTBRANCH_5_TO_IP";
+        case 0x000006c6: return "MSR_LASTBRANCH_6_TO_IP";
+        case 0x000006c7: return "MSR_LASTBRANCH_7_TO_IP";
+        case 0x000006c8: return "MSR_LASTBRANCH_8_TO_IP";
+        case 0x000006c9: return "MSR_LASTBRANCH_9_TO_IP";
+        case 0x000006ca: return "MSR_LASTBRANCH_10_TO_IP";
+        case 0x000006cb: return "MSR_LASTBRANCH_11_TO_IP";
+        case 0x000006cc: return "MSR_LASTBRANCH_12_TO_IP";
+        case 0x000006cd: return "MSR_LASTBRANCH_13_TO_IP";
+        case 0x000006ce: return "MSR_LASTBRANCH_14_TO_IP";
+        case 0x000006cf: return "MSR_LASTBRANCH_15_TO_IP";
+        case 0x000006e0: return "IA32_TSC_DEADLINE";
+
+        case 0x00000c80: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "IA32_DEBUG_INTERFACE" : NULL; /* Mentioned in an intel dataskit called 4th-gen-core-family-desktop-vol-1-datasheet.pdf. */
+        case 0x00000c81: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c81"  : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
+        case 0x00000c82: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c82"  : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
+        case 0x00000c83: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c83"  : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
+
+        /* 0x1000..0x1004 seems to have been used by IBM 386 and 486 clones too. */
+        case 0x00001000: return "P6_DEBUG_REGISTER_0";
+        case 0x00001001: return "P6_DEBUG_REGISTER_1";
+        case 0x00001002: return "P6_DEBUG_REGISTER_2";
+        case 0x00001003: return "P6_DEBUG_REGISTER_3";
+        case 0x00001004: return "P6_DEBUG_REGISTER_4";
+        case 0x00001005: return "P6_DEBUG_REGISTER_5";
+        case 0x00001006: return "P6_DEBUG_REGISTER_6";
+        case 0x00001007: return "P6_DEBUG_REGISTER_7";
+        case 0x0000103f: return "P6_UNK_0000_103f"; /* P6_M_Dothan. */
+        case 0x000010cd: return "P6_UNK_0000_10cd"; /* P6_M_Dothan. */
+
+        case 0x00001107: return "VIA_UNK_0000_1107";
+        case 0x0000110f: return "VIA_UNK_0000_110f";
+        case 0x00001153: return "VIA_UNK_0000_1153";
+        case 0x00001200: return "VIA_UNK_0000_1200";
+        case 0x00001201: return "VIA_UNK_0000_1201";
+        case 0x00001202: return "VIA_UNK_0000_1202";
+        case 0x00001203: return "VIA_UNK_0000_1203";
+        case 0x00001204: return "VIA_UNK_0000_1204";
+        case 0x00001205: return "VIA_UNK_0000_1205";
+        case 0x00001206: return "VIA_ALT_VENDOR_EBX";
+        case 0x00001207: return "VIA_ALT_VENDOR_ECDX";
+        case 0x00001208: return "VIA_UNK_0000_1208";
+        case 0x00001209: return "VIA_UNK_0000_1209";
+        case 0x0000120a: return "VIA_UNK_0000_120a";
+        case 0x0000120b: return "VIA_UNK_0000_120b";
+        case 0x0000120c: return "VIA_UNK_0000_120c";
+        case 0x0000120d: return "VIA_UNK_0000_120d";
+        case 0x0000120e: return "VIA_UNK_0000_120e";
+        case 0x0000120f: return "VIA_UNK_0000_120f";
+        case 0x00001210: return "VIA_UNK_0000_1210";
+        case 0x00001211: return "VIA_UNK_0000_1211";
+        case 0x00001212: return "VIA_UNK_0000_1212";
+        case 0x00001213: return "VIA_UNK_0000_1213";
+        case 0x00001214: return "VIA_UNK_0000_1214";
+        case 0x00001220: return "VIA_UNK_0000_1220";
+        case 0x00001221: return "VIA_UNK_0000_1221";
+        case 0x00001230: return "VIA_UNK_0000_1230";
+        case 0x00001231: return "VIA_UNK_0000_1231";
+        case 0x00001232: return "VIA_UNK_0000_1232";
+        case 0x00001233: return "VIA_UNK_0000_1233";
+        case 0x00001234: return "VIA_UNK_0000_1234";
+        case 0x00001235: return "VIA_UNK_0000_1235";
+        case 0x00001236: return "VIA_UNK_0000_1236";
+        case 0x00001237: return "VIA_UNK_0000_1237";
+        case 0x00001238: return "VIA_UNK_0000_1238";
+        case 0x00001239: return "VIA_UNK_0000_1239";
+        case 0x00001240: return "VIA_UNK_0000_1240";
+        case 0x00001241: return "VIA_UNK_0000_1241";
+        case 0x00001243: return "VIA_UNK_0000_1243";
+        case 0x00001245: return "VIA_UNK_0000_1245";
+        case 0x00001246: return "VIA_UNK_0000_1246";
+        case 0x00001247: return "VIA_UNK_0000_1247";
+        case 0x00001248: return "VIA_UNK_0000_1248";
+        case 0x00001249: return "VIA_UNK_0000_1249";
+        case 0x0000124a: return "VIA_UNK_0000_124a";
+
+        case 0x00001301: return "VIA_UNK_0000_1301";
+        case 0x00001302: return "VIA_UNK_0000_1302";
+        case 0x00001303: return "VIA_UNK_0000_1303";
+        case 0x00001304: return "VIA_UNK_0000_1304";
+        case 0x00001305: return "VIA_UNK_0000_1305";
+        case 0x00001306: return "VIA_UNK_0000_1306";
+        case 0x00001307: return "VIA_UNK_0000_1307";
+        case 0x00001308: return "VIA_UNK_0000_1308";
+        case 0x00001309: return "VIA_UNK_0000_1309";
+        case 0x0000130d: return "VIA_UNK_0000_130d";
+        case 0x0000130e: return "VIA_UNK_0000_130e";
+        case 0x00001312: return "VIA_UNK_0000_1312";
+        case 0x00001315: return "VIA_UNK_0000_1315";
+        case 0x00001317: return "VIA_UNK_0000_1317";
+        case 0x00001318: return "VIA_UNK_0000_1318";
+        case 0x0000131a: return "VIA_UNK_0000_131a";
+        case 0x0000131b: return "VIA_UNK_0000_131b";
+        case 0x00001402: return "VIA_UNK_0000_1402";
+        case 0x00001403: return "VIA_UNK_0000_1403";
+        case 0x00001404: return "VIA_UNK_0000_1404";
+        case 0x00001405: return "VIA_UNK_0000_1405";
+        case 0x00001406: return "VIA_UNK_0000_1406";
+        case 0x00001407: return "VIA_UNK_0000_1407";
+        case 0x00001410: return "VIA_UNK_0000_1410";
+        case 0x00001411: return "VIA_UNK_0000_1411";
+        case 0x00001412: return "VIA_UNK_0000_1412";
+        case 0x00001413: return "VIA_UNK_0000_1413";
+        case 0x00001414: return "VIA_UNK_0000_1414";
+        case 0x00001415: return "VIA_UNK_0000_1415";
+        case 0x00001416: return "VIA_UNK_0000_1416";
+        case 0x00001417: return "VIA_UNK_0000_1417";
+        case 0x00001418: return "VIA_UNK_0000_1418";
+        case 0x00001419: return "VIA_UNK_0000_1419";
+        case 0x0000141a: return "VIA_UNK_0000_141a";
+        case 0x0000141b: return "VIA_UNK_0000_141b";
+        case 0x0000141c: return "VIA_UNK_0000_141c";
+        case 0x0000141d: return "VIA_UNK_0000_141d";
+        case 0x0000141e: return "VIA_UNK_0000_141e";
+        case 0x0000141f: return "VIA_UNK_0000_141f";
+        case 0x00001420: return "VIA_UNK_0000_1420";
+        case 0x00001421: return "VIA_UNK_0000_1421";
+        case 0x00001422: return "VIA_UNK_0000_1422";
+        case 0x00001423: return "VIA_UNK_0000_1423";
+        case 0x00001424: return "VIA_UNK_0000_1424";
+        case 0x00001425: return "VIA_UNK_0000_1425";
+        case 0x00001426: return "VIA_UNK_0000_1426";
+        case 0x00001427: return "VIA_UNK_0000_1427";
+        case 0x00001428: return "VIA_UNK_0000_1428";
+        case 0x00001429: return "VIA_UNK_0000_1429";
+        case 0x0000142a: return "VIA_UNK_0000_142a";
+        case 0x0000142b: return "VIA_UNK_0000_142b";
+        case 0x0000142c: return "VIA_UNK_0000_142c";
+        case 0x0000142d: return "VIA_UNK_0000_142d";
+        case 0x0000142e: return "VIA_UNK_0000_142e";
+        case 0x0000142f: return "VIA_UNK_0000_142f";
+        case 0x00001434: return "VIA_UNK_0000_1434";
+        case 0x00001435: return "VIA_UNK_0000_1435";
+        case 0x00001436: return "VIA_UNK_0000_1436";
+        case 0x00001437: return "VIA_UNK_0000_1437";
+        case 0x00001438: return "VIA_UNK_0000_1438";
+        case 0x0000143a: return "VIA_UNK_0000_143a";
+        case 0x0000143c: return "VIA_UNK_0000_143c";
+        case 0x0000143d: return "VIA_UNK_0000_143d";
+        case 0x00001440: return "VIA_UNK_0000_1440";
+        case 0x00001441: return "VIA_UNK_0000_1441";
+        case 0x00001442: return "VIA_UNK_0000_1442";
+        case 0x00001449: return "VIA_UNK_0000_1449";
+        case 0x00001450: return "VIA_UNK_0000_1450";
+        case 0x00001451: return "VIA_UNK_0000_1451";
+        case 0x00001452: return "VIA_UNK_0000_1452";
+        case 0x00001453: return "VIA_UNK_0000_1453";
+        case 0x00001460: return "VIA_UNK_0000_1460";
+        case 0x00001461: return "VIA_UNK_0000_1461";
+        case 0x00001462: return "VIA_UNK_0000_1462";
+        case 0x00001463: return "VIA_UNK_0000_1463";
+        case 0x00001465: return "VIA_UNK_0000_1465";
+        case 0x00001466: return "VIA_UNK_0000_1466";
+        case 0x00001470: return "VIA_UNK_0000_1470";
+        case 0x00001471: return "VIA_UNK_0000_1471";
+        case 0x00001480: return "VIA_UNK_0000_1480";
+        case 0x00001481: return "VIA_UNK_0000_1481";
+        case 0x00001482: return "VIA_UNK_0000_1482";
+        case 0x00001483: return "VIA_UNK_0000_1483";
+        case 0x00001484: return "VIA_UNK_0000_1484";
+        case 0x00001485: return "VIA_UNK_0000_1485";
+        case 0x00001486: return "VIA_UNK_0000_1486";
+        case 0x00001490: return "VIA_UNK_0000_1490";
+        case 0x00001491: return "VIA_UNK_0000_1491";
+        case 0x00001492: return "VIA_UNK_0000_1492";
+        case 0x00001493: return "VIA_UNK_0000_1493";
+        case 0x00001494: return "VIA_UNK_0000_1494";
+        case 0x00001495: return "VIA_UNK_0000_1495";
+        case 0x00001496: return "VIA_UNK_0000_1496";
+        case 0x00001497: return "VIA_UNK_0000_1497";
+        case 0x00001498: return "VIA_UNK_0000_1498";
+        case 0x00001499: return "VIA_UNK_0000_1499";
+        case 0x0000149a: return "VIA_UNK_0000_149a";
+        case 0x0000149b: return "VIA_UNK_0000_149b";
+        case 0x0000149c: return "VIA_UNK_0000_149c";
+        case 0x0000149f: return "VIA_UNK_0000_149f";
+        case 0x00001523: return "VIA_UNK_0000_1523";
+
+        case 0x00002000: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR0" : NULL;
+        case 0x00002002: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR2" : NULL;
+        case 0x00002003: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR3" : NULL;
+        case 0x00002004: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR4" : NULL;
+        case 0x0000203f: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_203f" /* P6_M_Dothan. */ : NULL;
+        case 0x000020cd: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_20cd" /* P6_M_Dothan. */ : NULL;
+        case 0x0000303f: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_303f" /* P6_M_Dothan. */ : NULL;
+        case 0x000030cd: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_30cd" /* P6_M_Dothan. */ : NULL;
+
+        case 0x0000317a: return "VIA_UNK_0000_317a";
+        case 0x0000317b: return "VIA_UNK_0000_317b";
+        case 0x0000317d: return "VIA_UNK_0000_317d";
+        case 0x0000317e: return "VIA_UNK_0000_317e";
+        case 0x0000317f: return "VIA_UNK_0000_317f";
+        case 0x80000198: return "VIA_UNK_8000_0198";
+
+        case 0xc0000080: return "AMD64_EFER";
+        case 0xc0000081: return "AMD64_STAR";
+        case 0xc0000082: return "AMD64_STAR64";
+        case 0xc0000083: return "AMD64_STARCOMPAT";
+        case 0xc0000084: return "AMD64_SYSCALL_FLAG_MASK";
+        case 0xc0000100: return "AMD64_FS_BASE";
+        case 0xc0000101: return "AMD64_GS_BASE";
+        case 0xc0000102: return "AMD64_KERNEL_GS_BASE";
+        case 0xc0000103: return "AMD64_TSC_AUX";
+        case 0xc0000104: return "AMD_15H_TSC_RATE";
+        case 0xc0000105: return "AMD_15H_LWP_CFG";      /* Only Family 15h? */
+        case 0xc0000106: return "AMD_15H_LWP_CBADDR";   /* Only Family 15h? */
+        case 0xc0000408: return "AMD_10H_MC4_MISC1";
+        case 0xc0000409: return "AMD_10H_MC4_MISC2";
+        case 0xc000040a: return "AMD_10H_MC4_MISC3";
+        case 0xc000040b: return "AMD_10H_MC4_MISC4";
+        case 0xc000040c: return "AMD_10H_MC4_MISC5";
+        case 0xc000040d: return "AMD_10H_MC4_MISC6";
+        case 0xc000040e: return "AMD_10H_MC4_MISC7";
+        case 0xc000040f: return "AMD_10H_MC4_MISC8";
+        case 0xc0010000: return "AMD_K8_PERF_CTL_0";
+        case 0xc0010001: return "AMD_K8_PERF_CTL_1";
+        case 0xc0010002: return "AMD_K8_PERF_CTL_2";
+        case 0xc0010003: return "AMD_K8_PERF_CTL_3";
+        case 0xc0010004: return "AMD_K8_PERF_CTR_0";
+        case 0xc0010005: return "AMD_K8_PERF_CTR_1";
+        case 0xc0010006: return "AMD_K8_PERF_CTR_2";
+        case 0xc0010007: return "AMD_K8_PERF_CTR_3";
+        case 0xc0010010: return "AMD_K8_SYS_CFG";
+        case 0xc0010015: return "AMD_K8_HW_CFG";
+        case 0xc0010016: return "AMD_K8_IORR_BASE_0";
+        case 0xc0010017: return "AMD_K8_IORR_MASK_0";
+        case 0xc0010018: return "AMD_K8_IORR_BASE_1";
+        case 0xc0010019: return "AMD_K8_IORR_MASK_1";
+        case 0xc001001a: return "AMD_K8_TOP_MEM";
+        case 0xc001001d: return "AMD_K8_TOP_MEM2";
+        case 0xc001001e: return "AMD_K8_MANID";
+        case 0xc001001f: return "AMD_K8_NB_CFG1";
+        case 0xc0010020: return "AMD_K8_PATCH_LOADER";
+        case 0xc0010021: return "AMD_K8_UNK_c001_0021";
+        case 0xc0010022: return "AMD_K8_MC_XCPT_REDIR";
+        case 0xc0010028: return "AMD_K8_UNK_c001_0028";
+        case 0xc0010029: return "AMD_K8_UNK_c001_0029";
+        case 0xc001002a: return "AMD_K8_UNK_c001_002a";
+        case 0xc001002b: return "AMD_K8_UNK_c001_002b";
+        case 0xc001002c: return "AMD_K8_UNK_c001_002c";
+        case 0xc001002d: return "AMD_K8_UNK_c001_002d";
+        case 0xc0010030: return "AMD_K8_CPU_NAME_0";
+        case 0xc0010031: return "AMD_K8_CPU_NAME_1";
+        case 0xc0010032: return "AMD_K8_CPU_NAME_2";
+        case 0xc0010033: return "AMD_K8_CPU_NAME_3";
+        case 0xc0010034: return "AMD_K8_CPU_NAME_4";
+        case 0xc0010035: return "AMD_K8_CPU_NAME_5";
+        case 0xc001003e: return "AMD_K8_HTC";
+        case 0xc001003f: return "AMD_K8_STC";
+        case 0xc0010041: return "AMD_K8_FIDVID_CTL";
+        case 0xc0010042: return "AMD_K8_FIDVID_STATUS";
+        case 0xc0010043: return "AMD_K8_THERMTRIP_STATUS"; /* BDKG says it was removed in K8 revision C.*/
+        case 0xc0010044: return "AMD_K8_MC_CTL_MASK_0";
+        case 0xc0010045: return "AMD_K8_MC_CTL_MASK_1";
+        case 0xc0010046: return "AMD_K8_MC_CTL_MASK_2";
+        case 0xc0010047: return "AMD_K8_MC_CTL_MASK_3";
+        case 0xc0010048: return "AMD_K8_MC_CTL_MASK_4";
+        case 0xc0010049: return "AMD_K8_MC_CTL_MASK_5";
+        case 0xc001004a: return "AMD_K8_MC_CTL_MASK_6";
+        //case 0xc001004b: return "AMD_K8_MC_CTL_MASK_7";
+        case 0xc0010050: return "AMD_K8_SMI_ON_IO_TRAP_0";
+        case 0xc0010051: return "AMD_K8_SMI_ON_IO_TRAP_1";
+        case 0xc0010052: return "AMD_K8_SMI_ON_IO_TRAP_2";
+        case 0xc0010053: return "AMD_K8_SMI_ON_IO_TRAP_3";
+        case 0xc0010054: return "AMD_K8_SMI_ON_IO_TRAP_CTL_STS";
+        case 0xc0010055: return "AMD_K8_INT_PENDING_MSG";
+        case 0xc0010056: return "AMD_K8_SMI_TRIGGER_IO_CYCLE";
+        case 0xc0010057: return "AMD_10H_UNK_c001_0057";
+        case 0xc0010058: return "AMD_10H_MMIO_CFG_BASE_ADDR";
+        case 0xc0010059: return "AMD_10H_TRAP_CTL?"; /* Undocumented, only one google hit. */
+        case 0xc001005a: return "AMD_10H_UNK_c001_005a";
+        case 0xc001005b: return "AMD_10H_UNK_c001_005b";
+        case 0xc001005c: return "AMD_10H_UNK_c001_005c";
+        case 0xc001005d: return "AMD_10H_UNK_c001_005d";
+        case 0xc0010060: return "AMD_K8_BIST_RESULT";   /* BDKG says it as introduced with revision F. */
+        case 0xc0010061: return "AMD_10H_P_ST_CUR_LIM";
+        case 0xc0010062: return "AMD_10H_P_ST_CTL";
+        case 0xc0010063: return "AMD_10H_P_ST_STS";
+        case 0xc0010064: return "AMD_10H_P_ST_0";
+        case 0xc0010065: return "AMD_10H_P_ST_1";
+        case 0xc0010066: return "AMD_10H_P_ST_2";
+        case 0xc0010067: return "AMD_10H_P_ST_3";
+        case 0xc0010068: return "AMD_10H_P_ST_4";
+        case 0xc0010069: return "AMD_10H_P_ST_5";
+        case 0xc001006a: return "AMD_10H_P_ST_6";
+        case 0xc001006b: return "AMD_10H_P_ST_7";
+        case 0xc0010070: return "AMD_10H_COFVID_CTL";
+        case 0xc0010071: return "AMD_10H_COFVID_STS";
+        case 0xc0010073: return "AMD_10H_C_ST_IO_BASE_ADDR";
+        case 0xc0010074: return "AMD_10H_CPU_WD_TMR_CFG";
+        // case 0xc0010075: return "AMD_15H_APML_TDP_LIM";
+        // case 0xc0010077: return "AMD_15H_CPU_PWR_IN_TDP";
+        // case 0xc0010078: return "AMD_15H_PWR_AVG_PERIOD";
+        // case 0xc0010079: return "AMD_15H_DRAM_CTR_CMD_THR";
+        // case 0xc0010080: return "AMD_16H_FSFM_ACT_CNT_0";
+        // case 0xc0010081: return "AMD_16H_FSFM_REF_CNT_0";
+        case 0xc0010111: return "AMD_K8_SMM_BASE";
+        case 0xc0010112: return "AMD_K8_SMM_ADDR";
+        case 0xc0010113: return "AMD_K8_SMM_MASK";
+        case 0xc0010114: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_K8_VM_CR"          : "AMD_K8_UNK_c001_0114";
+        case 0xc0010115: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_K8_IGNNE"          : "AMD_K8_UNK_c001_0115";
+        case 0xc0010116: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_K8_SMM_CTL"        : "AMD_K8_UNK_c001_0116";
+        case 0xc0010117: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_K8_VM_HSAVE_PA"    : "AMD_K8_UNK_c001_0117";
+        case 0xc0010118: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_10H_VM_LOCK_KEY"   : "AMD_K8_UNK_c001_0118";
+        case 0xc0010119: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_10H_SSM_LOCK_KEY"  : "AMD_K8_UNK_c001_0119";
+        case 0xc001011a: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_10H_LOCAL_SMI_STS" : "AMD_K8_UNK_c001_011a";
+        case 0xc001011b: return "AMD_K8_UNK_c001_011b";
+        case 0xc001011c: return "AMD_K8_UNK_c001_011c";
+        case 0xc0010140: return "AMD_10H_OSVW_ID_LEN";
+        case 0xc0010141: return "AMD_10H_OSVW_STS";
+        case 0xc0010200: return "AMD_K8_PERF_CTL_0";
+        case 0xc0010202: return "AMD_K8_PERF_CTL_1";
+        case 0xc0010204: return "AMD_K8_PERF_CTL_2";
+        case 0xc0010206: return "AMD_K8_PERF_CTL_3";
+        case 0xc0010208: return "AMD_K8_PERF_CTL_4";
+        case 0xc001020a: return "AMD_K8_PERF_CTL_5";
+        //case 0xc001020c: return "AMD_K8_PERF_CTL_6";
+        //case 0xc001020e: return "AMD_K8_PERF_CTL_7";
+        case 0xc0010201: return "AMD_K8_PERF_CTR_0";
+        case 0xc0010203: return "AMD_K8_PERF_CTR_1";
+        case 0xc0010205: return "AMD_K8_PERF_CTR_2";
+        case 0xc0010207: return "AMD_K8_PERF_CTR_3";
+        case 0xc0010209: return "AMD_K8_PERF_CTR_4";
+        case 0xc001020b: return "AMD_K8_PERF_CTR_5";
+        //case 0xc001020d: return "AMD_K8_PERF_CTR_6";
+        //case 0xc001020f: return "AMD_K8_PERF_CTR_7";
+        case 0xc0010230: return "AMD_16H_L2I_PERF_CTL_0";
+        case 0xc0010232: return "AMD_16H_L2I_PERF_CTL_1";
+        case 0xc0010234: return "AMD_16H_L2I_PERF_CTL_2";
+        case 0xc0010236: return "AMD_16H_L2I_PERF_CTL_3";
+        //case 0xc0010238: return "AMD_16H_L2I_PERF_CTL_4";
+        //case 0xc001023a: return "AMD_16H_L2I_PERF_CTL_5";
+        //case 0xc001030c: return "AMD_16H_L2I_PERF_CTL_6";
+        //case 0xc001023e: return "AMD_16H_L2I_PERF_CTL_7";
+        case 0xc0010231: return "AMD_16H_L2I_PERF_CTR_0";
+        case 0xc0010233: return "AMD_16H_L2I_PERF_CTR_1";
+        case 0xc0010235: return "AMD_16H_L2I_PERF_CTR_2";
+        case 0xc0010237: return "AMD_16H_L2I_PERF_CTR_3";
+        //case 0xc0010239: return "AMD_16H_L2I_PERF_CTR_4";
+        //case 0xc001023b: return "AMD_16H_L2I_PERF_CTR_5";
+        //case 0xc001023d: return "AMD_16H_L2I_PERF_CTR_6";
+        //case 0xc001023f: return "AMD_16H_L2I_PERF_CTR_7";
+        case 0xc0010240: return "AMD_15H_NB_PERF_CTL_0";
+        case 0xc0010242: return "AMD_15H_NB_PERF_CTL_1";
+        case 0xc0010244: return "AMD_15H_NB_PERF_CTL_2";
+        case 0xc0010246: return "AMD_15H_NB_PERF_CTL_3";
+        //case 0xc0010248: return "AMD_15H_NB_PERF_CTL_4";
+        //case 0xc001024a: return "AMD_15H_NB_PERF_CTL_5";
+        //case 0xc001024c: return "AMD_15H_NB_PERF_CTL_6";
+        //case 0xc001024e: return "AMD_15H_NB_PERF_CTL_7";
+        case 0xc0010241: return "AMD_15H_NB_PERF_CTR_0";
+        case 0xc0010243: return "AMD_15H_NB_PERF_CTR_1";
+        case 0xc0010245: return "AMD_15H_NB_PERF_CTR_2";
+        case 0xc0010247: return "AMD_15H_NB_PERF_CTR_3";
+        //case 0xc0010249: return "AMD_15H_NB_PERF_CTR_4";
+        //case 0xc001024b: return "AMD_15H_NB_PERF_CTR_5";
+        //case 0xc001024d: return "AMD_15H_NB_PERF_CTR_6";
+        //case 0xc001024f: return "AMD_15H_NB_PERF_CTR_7";
+        case 0xc0011000: return "AMD_K7_MCODE_CTL";
+        case 0xc0011001: return "AMD_K7_APIC_CLUSTER_ID"; /* Mentioned in BKDG (r3.00) for fam16h when describing EBL_CR_POWERON. */
+        case 0xc0011002: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD07" : NULL;
+        case 0xc0011003: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD06" : NULL;
+        case 0xc0011004: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD01" : NULL;
+        case 0xc0011005: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_EXT01" : NULL;
+        case 0xc0011006: return "AMD_K7_DEBUG_STS?";
+        case 0xc0011007: return "AMD_K7_BH_TRACE_BASE?";
+        case 0xc0011008: return "AMD_K7_BH_TRACE_PTR?";
+        case 0xc0011009: return "AMD_K7_BH_TRACE_LIM?";
+        case 0xc001100a: return "AMD_K7_HDT_CFG?";
+        case 0xc001100b: return "AMD_K7_FAST_FLUSH_COUNT?";
+        case 0xc001100c: return "AMD_K7_NODE_ID";
+        case 0xc001100d: return "AMD_K8_LOGICAL_CPUS_NUM?";
+        case 0xc001100e: return "AMD_K8_WRMSR_BP?";
+        case 0xc001100f: return "AMD_K8_WRMSR_BP_MASK?";
+        case 0xc0011010: return "AMD_K8_BH_TRACE_CTL?";
+        case 0xc0011011: return "AMD_K8_BH_TRACE_USRD?";
+        case 0xc0011012: return "AMD_K7_UNK_c001_1012";
+        case 0xc0011013: return "AMD_K7_UNK_c001_1013";
+        case 0xc0011014: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_RIP?" : "AMD_K7_MOBIL_DEBUG?";
+        case 0xc0011015: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_RIP_MASK?" : NULL;
+        case 0xc0011016: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_COND_HDT_VAL?" : NULL;
+        case 0xc0011017: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_COND_HDT_VAL_MASK?" : NULL;
+        case 0xc0011018: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_CTL?" : NULL;
+        case 0xc0011019: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR1_ADDR_MASK" : NULL;
+        case 0xc001101a: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR2_ADDR_MASK" : NULL;
+        case 0xc001101b: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR3_ADDR_MASK" : NULL;
+        case 0xc001101d: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_NB_BIST?" : NULL;
+        case 0xc001101e: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_THERMTRIP_2?" : NULL;
+        case 0xc001101f: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_NB_CFG?" : NULL;
+        case 0xc0011020: return "AMD_K7_LS_CFG";
+        case 0xc0011021: return "AMD_K7_IC_CFG";
+        case 0xc0011022: return "AMD_K7_DC_CFG";
+        case 0xc0011023: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_CU_CFG" : "AMD_K7_BU_CFG";
+        case 0xc0011024: return "AMD_K7_DEBUG_CTL_2?";
+        case 0xc0011025: return "AMD_K7_DR0_DATA_MATCH?";
+        case 0xc0011026: return "AMD_K7_DR0_DATA_MATCH?";
+        case 0xc0011027: return "AMD_K7_DR0_ADDR_MASK";
+        case 0xc0011028: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AMD_15H_FP_CFG"
+                              : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)   ? "AMD_10H_UNK_c001_1028"
+                              : NULL;
+        case 0xc0011029: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AMD_15H_DC_CFG"
+                              : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)   ? "AMD_10H_UNK_c001_1029"
+                              : NULL;
+        case 0xc001102a: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_CU_CFG2"
+                              : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) || g_enmMicroarch > kCpumMicroarch_AMD_15h_End
+                              ? "AMD_10H_BU_CFG2" /* 10h & 16h */ : NULL;
+        case 0xc001102b: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_CU_CFG3" : NULL;
+        case 0xc001102c: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_EX_CFG" : NULL;
+        case 0xc001102d: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_LS_CFG2" : NULL;
+        case 0xc0011030: return "AMD_10H_IBS_FETCH_CTL";
+        case 0xc0011031: return "AMD_10H_IBS_FETCH_LIN_ADDR";
+        case 0xc0011032: return "AMD_10H_IBS_FETCH_PHYS_ADDR";
+        case 0xc0011033: return "AMD_10H_IBS_OP_EXEC_CTL";
+        case 0xc0011034: return "AMD_10H_IBS_OP_RIP";
+        case 0xc0011035: return "AMD_10H_IBS_OP_DATA";
+        case 0xc0011036: return "AMD_10H_IBS_OP_DATA2";
+        case 0xc0011037: return "AMD_10H_IBS_OP_DATA3";
+        case 0xc0011038: return "AMD_10H_IBS_DC_LIN_ADDR";
+        case 0xc0011039: return "AMD_10H_IBS_DC_PHYS_ADDR";
+        case 0xc001103a: return "AMD_10H_IBS_CTL";
+        case 0xc001103b: return "AMD_14H_IBS_BR_TARGET";
+
+        case 0xc0011040: return "AMD_15H_UNK_c001_1040";
+        case 0xc0011041: return "AMD_15H_UNK_c001_1041";
+        case 0xc0011042: return "AMD_15H_UNK_c001_1042";
+        case 0xc0011043: return "AMD_15H_UNK_c001_1043";
+        case 0xc0011044: return "AMD_15H_UNK_c001_1044";
+        case 0xc0011045: return "AMD_15H_UNK_c001_1045";
+        case 0xc0011046: return "AMD_15H_UNK_c001_1046";
+        case 0xc0011047: return "AMD_15H_UNK_c001_1047";
+        case 0xc0011048: return "AMD_15H_UNK_c001_1048";
+        case 0xc0011049: return "AMD_15H_UNK_c001_1049";
+        case 0xc001104a: return "AMD_15H_UNK_c001_104a";
+        case 0xc001104b: return "AMD_15H_UNK_c001_104b";
+        case 0xc001104c: return "AMD_15H_UNK_c001_104c";
+        case 0xc001104d: return "AMD_15H_UNK_c001_104d";
+        case 0xc001104e: return "AMD_15H_UNK_c001_104e";
+        case 0xc001104f: return "AMD_15H_UNK_c001_104f";
+        case 0xc0011050: return "AMD_15H_UNK_c001_1050";
+        case 0xc0011051: return "AMD_15H_UNK_c001_1051";
+        case 0xc0011052: return "AMD_15H_UNK_c001_1052";
+        case 0xc0011053: return "AMD_15H_UNK_c001_1053";
+        case 0xc0011054: return "AMD_15H_UNK_c001_1054";
+        case 0xc0011055: return "AMD_15H_UNK_c001_1055";
+        case 0xc0011056: return "AMD_15H_UNK_c001_1056";
+        case 0xc0011057: return "AMD_15H_UNK_c001_1057";
+        case 0xc0011058: return "AMD_15H_UNK_c001_1058";
+        case 0xc0011059: return "AMD_15H_UNK_c001_1059";
+        case 0xc001105a: return "AMD_15H_UNK_c001_105a";
+        case 0xc001105b: return "AMD_15H_UNK_c001_105b";
+        case 0xc001105c: return "AMD_15H_UNK_c001_105c";
+        case 0xc001105d: return "AMD_15H_UNK_c001_105d";
+        case 0xc001105e: return "AMD_15H_UNK_c001_105e";
+        case 0xc001105f: return "AMD_15H_UNK_c001_105f";
+        case 0xc0011060: return "AMD_15H_UNK_c001_1060";
+        case 0xc0011061: return "AMD_15H_UNK_c001_1061";
+        case 0xc0011062: return "AMD_15H_UNK_c001_1062";
+        case 0xc0011063: return "AMD_15H_UNK_c001_1063";
+        case 0xc0011064: return "AMD_15H_UNK_c001_1064";
+        case 0xc0011065: return "AMD_15H_UNK_c001_1065";
+        case 0xc0011066: return "AMD_15H_UNK_c001_1066";
+        case 0xc0011067: return "AMD_15H_UNK_c001_1067";
+        case 0xc0011068: return "AMD_15H_UNK_c001_1068";
+        case 0xc0011069: return "AMD_15H_UNK_c001_1069";
+        case 0xc001106a: return "AMD_15H_UNK_c001_106a";
+        case 0xc001106b: return "AMD_15H_UNK_c001_106b";
+        case 0xc001106c: return "AMD_15H_UNK_c001_106c";
+        case 0xc001106d: return "AMD_15H_UNK_c001_106d";
+        case 0xc001106e: return "AMD_15H_UNK_c001_106e";
+        case 0xc001106f: return "AMD_15H_UNK_c001_106f";
+        case 0xc0011070: return "AMD_15H_UNK_c001_1070"; /* coreboot defines this, but with a numerical name. */
+        case 0xc0011071: return "AMD_15H_UNK_c001_1071";
+        case 0xc0011072: return "AMD_15H_UNK_c001_1072";
+        case 0xc0011073: return "AMD_15H_UNK_c001_1073";
+        case 0xc0011080: return "AMD_15H_UNK_c001_1080";
+    }
+
+    /*
+     * Bunch of unknown sandy bridge registers.  They might seem like the
+     * nehalem based xeon stuff, but the layout doesn't match.  I bet it's the
+     * same kind of registes though (i.e. uncore (UNC)).
+     *
+     * Kudos to Intel for keeping these a secret!  Many thanks guys!!
+     */
+    if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_SandyBridge)
+        switch (uMsr)
+        {
+            case 0x00000a00: return "I7_SB_UNK_0000_0a00"; case 0x00000a01: return "I7_SB_UNK_0000_0a01";
+            case 0x00000a02: return "I7_SB_UNK_0000_0a02";
+            case 0x00000c00: return "I7_SB_UNK_0000_0c00"; case 0x00000c01: return "I7_SB_UNK_0000_0c01";
+            case 0x00000c06: return "I7_SB_UNK_0000_0c06"; case 0x00000c08: return "I7_SB_UNK_0000_0c08";
+            case 0x00000c09: return "I7_SB_UNK_0000_0c09"; case 0x00000c10: return "I7_SB_UNK_0000_0c10";
+            case 0x00000c11: return "I7_SB_UNK_0000_0c11"; case 0x00000c14: return "I7_SB_UNK_0000_0c14";
+            case 0x00000c15: return "I7_SB_UNK_0000_0c15"; case 0x00000c16: return "I7_SB_UNK_0000_0c16";
+            case 0x00000c17: return "I7_SB_UNK_0000_0c17"; case 0x00000c24: return "I7_SB_UNK_0000_0c24";
+            case 0x00000c30: return "I7_SB_UNK_0000_0c30"; case 0x00000c31: return "I7_SB_UNK_0000_0c31";
+            case 0x00000c32: return "I7_SB_UNK_0000_0c32"; case 0x00000c33: return "I7_SB_UNK_0000_0c33";
+            case 0x00000c34: return "I7_SB_UNK_0000_0c34"; case 0x00000c35: return "I7_SB_UNK_0000_0c35";
+            case 0x00000c36: return "I7_SB_UNK_0000_0c36"; case 0x00000c37: return "I7_SB_UNK_0000_0c37";
+            case 0x00000c38: return "I7_SB_UNK_0000_0c38"; case 0x00000c39: return "I7_SB_UNK_0000_0c39";
+            case 0x00000d04: return "I7_SB_UNK_0000_0d04";
+            case 0x00000d10: return "I7_SB_UNK_0000_0d10"; case 0x00000d11: return "I7_SB_UNK_0000_0d11";
+            case 0x00000d12: return "I7_SB_UNK_0000_0d12"; case 0x00000d13: return "I7_SB_UNK_0000_0d13";
+            case 0x00000d14: return "I7_SB_UNK_0000_0d14"; case 0x00000d15: return "I7_SB_UNK_0000_0d15";
+            case 0x00000d16: return "I7_SB_UNK_0000_0d16"; case 0x00000d17: return "I7_SB_UNK_0000_0d17";
+            case 0x00000d18: return "I7_SB_UNK_0000_0d18"; case 0x00000d19: return "I7_SB_UNK_0000_0d19";
+            case 0x00000d24: return "I7_SB_UNK_0000_0d24";
+            case 0x00000d30: return "I7_SB_UNK_0000_0d30"; case 0x00000d31: return "I7_SB_UNK_0000_0d31";
+            case 0x00000d32: return "I7_SB_UNK_0000_0d32"; case 0x00000d33: return "I7_SB_UNK_0000_0d33";
+            case 0x00000d34: return "I7_SB_UNK_0000_0d34"; case 0x00000d35: return "I7_SB_UNK_0000_0d35";
+            case 0x00000d36: return "I7_SB_UNK_0000_0d36"; case 0x00000d37: return "I7_SB_UNK_0000_0d37";
+            case 0x00000d38: return "I7_SB_UNK_0000_0d38"; case 0x00000d39: return "I7_SB_UNK_0000_0d39";
+            case 0x00000d44: return "I7_SB_UNK_0000_0d44";
+            case 0x00000d50: return "I7_SB_UNK_0000_0d50"; case 0x00000d51: return "I7_SB_UNK_0000_0d51";
+            case 0x00000d52: return "I7_SB_UNK_0000_0d52"; case 0x00000d53: return "I7_SB_UNK_0000_0d53";
+            case 0x00000d54: return "I7_SB_UNK_0000_0d54"; case 0x00000d55: return "I7_SB_UNK_0000_0d55";
+            case 0x00000d56: return "I7_SB_UNK_0000_0d56"; case 0x00000d57: return "I7_SB_UNK_0000_0d57";
+            case 0x00000d58: return "I7_SB_UNK_0000_0d58"; case 0x00000d59: return "I7_SB_UNK_0000_0d59";
+            case 0x00000d64: return "I7_SB_UNK_0000_0d64";
+            case 0x00000d70: return "I7_SB_UNK_0000_0d70"; case 0x00000d71: return "I7_SB_UNK_0000_0d71";
+            case 0x00000d72: return "I7_SB_UNK_0000_0d72"; case 0x00000d73: return "I7_SB_UNK_0000_0d73";
+            case 0x00000d74: return "I7_SB_UNK_0000_0d74"; case 0x00000d75: return "I7_SB_UNK_0000_0d75";
+            case 0x00000d76: return "I7_SB_UNK_0000_0d76"; case 0x00000d77: return "I7_SB_UNK_0000_0d77";
+            case 0x00000d78: return "I7_SB_UNK_0000_0d78"; case 0x00000d79: return "I7_SB_UNK_0000_0d79";
+            case 0x00000d84: return "I7_SB_UNK_0000_0d84";
+            case 0x00000d90: return "I7_SB_UNK_0000_0d90"; case 0x00000d91: return "I7_SB_UNK_0000_0d91";
+            case 0x00000d92: return "I7_SB_UNK_0000_0d92"; case 0x00000d93: return "I7_SB_UNK_0000_0d93";
+            case 0x00000d94: return "I7_SB_UNK_0000_0d94"; case 0x00000d95: return "I7_SB_UNK_0000_0d95";
+            case 0x00000d96: return "I7_SB_UNK_0000_0d96"; case 0x00000d97: return "I7_SB_UNK_0000_0d97";
+            case 0x00000d98: return "I7_SB_UNK_0000_0d98"; case 0x00000d99: return "I7_SB_UNK_0000_0d99";
+            case 0x00000da4: return "I7_SB_UNK_0000_0da4";
+            case 0x00000db0: return "I7_SB_UNK_0000_0db0"; case 0x00000db1: return "I7_SB_UNK_0000_0db1";
+            case 0x00000db2: return "I7_SB_UNK_0000_0db2"; case 0x00000db3: return "I7_SB_UNK_0000_0db3";
+            case 0x00000db4: return "I7_SB_UNK_0000_0db4"; case 0x00000db5: return "I7_SB_UNK_0000_0db5";
+            case 0x00000db6: return "I7_SB_UNK_0000_0db6"; case 0x00000db7: return "I7_SB_UNK_0000_0db7";
+            case 0x00000db8: return "I7_SB_UNK_0000_0db8"; case 0x00000db9: return "I7_SB_UNK_0000_0db9";
+        }
+
+    /*
+     * Ditto for ivy bridge (observed on the i5-3570).  There are some haswell
+     * and sandybridge related docs on registers in this ares, but either
+     * things are different for ivy or they're very incomplete.  Again, kudos
+     * to intel!
+     */
+    if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_IvyBridge)
+        switch (uMsr)
+        {
+            case 0x00000700: return "I7_IB_UNK_0000_0700"; case 0x00000701: return "I7_IB_UNK_0000_0701";
+            case 0x00000702: return "I7_IB_UNK_0000_0702"; case 0x00000703: return "I7_IB_UNK_0000_0703";
+            case 0x00000704: return "I7_IB_UNK_0000_0704"; case 0x00000705: return "I7_IB_UNK_0000_0705";
+            case 0x00000706: return "I7_IB_UNK_0000_0706"; case 0x00000707: return "I7_IB_UNK_0000_0707";
+            case 0x00000708: return "I7_IB_UNK_0000_0708"; case 0x00000709: return "I7_IB_UNK_0000_0709";
+            case 0x00000710: return "I7_IB_UNK_0000_0710"; case 0x00000711: return "I7_IB_UNK_0000_0711";
+            case 0x00000712: return "I7_IB_UNK_0000_0712"; case 0x00000713: return "I7_IB_UNK_0000_0713";
+            case 0x00000714: return "I7_IB_UNK_0000_0714"; case 0x00000715: return "I7_IB_UNK_0000_0715";
+            case 0x00000716: return "I7_IB_UNK_0000_0716"; case 0x00000717: return "I7_IB_UNK_0000_0717";
+            case 0x00000718: return "I7_IB_UNK_0000_0718"; case 0x00000719: return "I7_IB_UNK_0000_0719";
+            case 0x00000720: return "I7_IB_UNK_0000_0720"; case 0x00000721: return "I7_IB_UNK_0000_0721";
+            case 0x00000722: return "I7_IB_UNK_0000_0722"; case 0x00000723: return "I7_IB_UNK_0000_0723";
+            case 0x00000724: return "I7_IB_UNK_0000_0724"; case 0x00000725: return "I7_IB_UNK_0000_0725";
+            case 0x00000726: return "I7_IB_UNK_0000_0726"; case 0x00000727: return "I7_IB_UNK_0000_0727";
+            case 0x00000728: return "I7_IB_UNK_0000_0728"; case 0x00000729: return "I7_IB_UNK_0000_0729";
+            case 0x00000730: return "I7_IB_UNK_0000_0730"; case 0x00000731: return "I7_IB_UNK_0000_0731";
+            case 0x00000732: return "I7_IB_UNK_0000_0732"; case 0x00000733: return "I7_IB_UNK_0000_0733";
+            case 0x00000734: return "I7_IB_UNK_0000_0734"; case 0x00000735: return "I7_IB_UNK_0000_0735";
+            case 0x00000736: return "I7_IB_UNK_0000_0736"; case 0x00000737: return "I7_IB_UNK_0000_0737";
+            case 0x00000738: return "I7_IB_UNK_0000_0738"; case 0x00000739: return "I7_IB_UNK_0000_0739";
+            case 0x00000740: return "I7_IB_UNK_0000_0740"; case 0x00000741: return "I7_IB_UNK_0000_0741";
+            case 0x00000742: return "I7_IB_UNK_0000_0742"; case 0x00000743: return "I7_IB_UNK_0000_0743";
+            case 0x00000744: return "I7_IB_UNK_0000_0744"; case 0x00000745: return "I7_IB_UNK_0000_0745";
+            case 0x00000746: return "I7_IB_UNK_0000_0746"; case 0x00000747: return "I7_IB_UNK_0000_0747";
+            case 0x00000748: return "I7_IB_UNK_0000_0748"; case 0x00000749: return "I7_IB_UNK_0000_0749";
+
+        }
+    return NULL;
+}
+
+
+/**
+ * Gets the name of an MSR.
+ *
+ * This may return a static buffer, so the content should only be considered
+ * valid until the next time this function is called!.
+ *
+ * @returns MSR name.
+ * @param   uMsr                The MSR in question.
+ */
+static const char *getMsrName(uint32_t uMsr)
+{
+    const char *pszReadOnly = getMsrNameHandled(uMsr);
+    if (pszReadOnly)
+        return pszReadOnly;
+
+    /*
+     * This MSR needs looking into, return a TODO_XXXX_XXXX name.
+     */
+    static char s_szBuf[32];
+    RTStrPrintf(s_szBuf, sizeof(s_szBuf), "TODO_%04x_%04x", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
+    return s_szBuf;
+}
+
+
+
+/**
+ * Gets the name of an MSR range.
+ *
+ * This may return a static buffer, so the content should only be considered
+ * valid until the next time this function is called!.
+ *
+ * @returns MSR name.
+ * @param   uMsr                The first MSR in the range.
+ */
+static const char *getMsrRangeName(uint32_t uMsr)
+{
+    switch (uMsr)
+    {
+        case 0x00000040:
+            return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_n_FROM_IP" : "MSR_LASTBRANCH_n";
+        case 0x00000060:
+            if (g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah)
+                return "MSR_LASTBRANCH_n_TO_IP";
+            break;
+
+        case 0x000003f8:
+        case 0x000003f9:
+        case 0x000003fa:
+            return "I7_MSR_PKG_Cn_RESIDENCY";
+        case 0x000003fc:
+        case 0x000003fd:
+        case 0x000003fe:
+            return "I7_MSR_CORE_Cn_RESIDENCY";
+
+        case 0x00000400:
+            return "IA32_MCi_CTL_STATUS_ADDR_MISC";
+
+        case 0x00000680:
+            return "MSR_LASTBRANCH_n_FROM_IP";
+        case 0x000006c0:
+            return "MSR_LASTBRANCH_n_TO_IP";
+
+        case 0x00000800: case 0x00000801: case 0x00000802: case 0x00000803:
+        case 0x00000804: case 0x00000805: case 0x00000806: case 0x00000807:
+        case 0x00000808: case 0x00000809: case 0x0000080a: case 0x0000080b:
+        case 0x0000080c: case 0x0000080d: case 0x0000080e: case 0x0000080f:
+            return "IA32_X2APIC_n";
+    }
+
+    static char s_szBuf[96];
+    const char *pszReadOnly = getMsrNameHandled(uMsr);
+    if (pszReadOnly)
+    {
+        /*
+         * Replace the last char with 'n'.
+         */
+        RTStrCopy(s_szBuf, sizeof(s_szBuf), pszReadOnly);
+        size_t off = strlen(s_szBuf);
+        if (off > 0)
+            off--;
+        if (off + 1 < sizeof(s_szBuf))
+        {
+            s_szBuf[off] = 'n';
+            s_szBuf[off + 1] = '\0';
+        }
+    }
+    else
+    {
+        /*
+         * This MSR needs looking into, return a TODO_XXXX_XXXX_n name.
+         */
+        RTStrPrintf(s_szBuf, sizeof(s_szBuf), "TODO_%04x_%04x_n", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
+    }
+    return s_szBuf;
+}
+
+
+/**
+ * Returns the function name for MSRs that have one or two.
+ *
+ * @returns Function name if applicable, NULL if not.
+ * @param   uMsr            The MSR in question.
+ * @param   pfTakesValue    Whether this MSR function takes a value or not.
+ *                          Optional.
+ */
+static const char *getMsrFnName(uint32_t uMsr, bool *pfTakesValue)
+{
+    bool fTmp;
+    if (!pfTakesValue)
+        pfTakesValue = &fTmp;
+
+    *pfTakesValue = false;
+
+    switch (uMsr)
+    {
+        case 0x00000000: return "Ia32P5McAddr";
+        case 0x00000001: return "Ia32P5McType";
+        case 0x00000006:
+            if (g_enmMicroarch >= kCpumMicroarch_Intel_First && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_First)
+                return NULL; /* TR4 / cache tag on Pentium, but that's for later. */
+            return "Ia32MonitorFilterLineSize";
+        case 0x00000010: return "Ia32TimestampCounter";
+        case 0x0000001b: return "Ia32ApicBase";
+        case 0x0000002a: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcHardPowerOn" : "IntelEblCrPowerOn";
+        case 0x0000002b: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcSoftPowerOn" : NULL;
+        case 0x0000002c: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcFrequencyId" : NULL;
+        //case 0x00000033: return "IntelTestCtl";
+        case 0x0000003a: return "Ia32FeatureControl";
+
+        case 0x00000040:
+        case 0x00000041:
+        case 0x00000042:
+        case 0x00000043:
+        case 0x00000044:
+        case 0x00000045:
+        case 0x00000046:
+        case 0x00000047:
+            return "IntelLastBranchFromToN";
+
+        case 0x0000008b: return g_enmVendor == CPUMCPUVENDOR_AMD ? "AmdK8PatchLevel" : "Ia32BiosSignId";
+        case 0x0000009b: return "Ia32SmmMonitorCtl";
+
+        case 0x000000a8:
+        case 0x000000a9:
+        case 0x000000aa:
+        case 0x000000ab:
+        case 0x000000ac:
+        case 0x000000ad:
+            *pfTakesValue = true;
+            return "IntelCore2EmttmCrTablesN";
+
+        case 0x000000c1:
+        case 0x000000c2:
+        case 0x000000c3:
+        case 0x000000c4:
+            return "Ia32PmcN";
+        case 0x000000c5:
+        case 0x000000c6:
+        case 0x000000c7:
+        case 0x000000c8:
+            if (g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First)
+                return "Ia32PmcN";
+            return NULL;
+
+        case 0x000000ce: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch)
+                              ? (g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                                 ? "IntelPlatformInfo100MHz" : "IntelPlatformInfo133MHz")
+                              : NULL;
+
+        case 0x000000e2: return "IntelPkgCStConfigControl";
+        case 0x000000e3: return "IntelCore2SmmCStMiscInfo";
+        case 0x000000e4: return "IntelPmgIoCaptureBase";
+        case 0x000000e7: return "Ia32MPerf";
+        case 0x000000e8: return "Ia32APerf";
+        case 0x000000ee: return "IntelCore1ExtConfig";
+        case 0x000000fe: *pfTakesValue = true; return "Ia32MtrrCap";
+        case 0x00000119: *pfTakesValue = true; return "IntelBblCrCtl";
+        case 0x0000011e: *pfTakesValue = true; return "IntelBblCrCtl3";
+
+        case 0x00000130: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
+                             || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
+                              ? "IntelCpuId1FeatureMaskEcdx" : NULL;
+        case 0x00000131: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
+                             || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
+                              ? "IntelCpuId80000001FeatureMaskEcdx" : NULL;
+        case 0x00000132: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                              ? "IntelCpuId1FeatureMaskEax" : NULL;
+        case 0x00000133: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                              ? "IntelCpuId1FeatureMaskEcdx" : NULL;
+        case 0x00000134: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                              ? "IntelCpuId80000001FeatureMaskEcdx" : NULL;
+        case 0x0000013c: return "IntelI7SandyAesNiCtl";
+        case 0x0000015f: return "IntelCore1DtsCalControl";
+        case 0x00000174: return "Ia32SysEnterCs";
+        case 0x00000175: return "Ia32SysEnterEsp";
+        case 0x00000176: return "Ia32SysEnterEip";
+        case 0x00000179: *pfTakesValue = true; return "Ia32McgCap";
+        case 0x0000017a: return "Ia32McgStatus";
+        case 0x0000017b: return "Ia32McgCtl";
+        case 0x0000017f: return "IntelI7SandyErrorControl"; /* SandyBridge. */
+        case 0x00000186: return "Ia32PerfEvtSelN";
+        case 0x00000187: return "Ia32PerfEvtSelN";
+        case 0x00000193: return /*g_fIntelNetBurst ? NULL :*/ NULL /* Core2_Penryn. */;
+        case 0x00000194:
+            if (g_fIntelNetBurst)
+                break;
+            *pfTakesValue = true;
+            return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) && g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
+                 ? "IntelFlexRatio100MHz" : "IntelFlexRatio133MHz";
+        case 0x00000198: *pfTakesValue = true; return "Ia32PerfStatus";
+        case 0x00000199: *pfTakesValue = true; return "Ia32PerfCtl";
+        case 0x0000019a: *pfTakesValue = true; return "Ia32ClockModulation";
+        case 0x0000019b: *pfTakesValue = true; return "Ia32ThermInterrupt";
+        case 0x0000019c: *pfTakesValue = true; return "Ia32ThermStatus";
+        case 0x0000019d: *pfTakesValue = true; return "Ia32Therm2Ctl";
+        case 0x000001a0: *pfTakesValue = true; return "Ia32MiscEnable";
+        case 0x000001a2: *pfTakesValue = true; return "IntelI7TemperatureTarget";
+        case 0x000001a6: return "IntelI7MsrOffCoreResponseN";
+        case 0x000001a7: return "IntelI7MsrOffCoreResponseN";
+        case 0x000001aa: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "IntelI7MiscPwrMgmt" : NULL /*"P6PicSensCfg"*/;
+        case 0x000001ad: *pfTakesValue = true; return "IntelI7TurboRatioLimit"; /* SandyBridge+, Silvermount+ */
+        case 0x000001c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Nehalem ? "IntelI7LbrSelect" : NULL;
+        case 0x000001c9: return    g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
+                                && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_End
+                              ? "IntelLastBranchTos" : NULL /* Pentium M Dothan seems to have something else here. */;
+        case 0x000001d7: return g_fIntelNetBurst ? "P6LastIntFromIp" : NULL;
+        case 0x000001d8: return g_fIntelNetBurst ? "P6LastIntToIp"   : NULL;
+        case 0x000001d9: return "Ia32DebugCtl";
+        case 0x000001da: return g_fIntelNetBurst ? "IntelLastBranchTos" : NULL;
+        case 0x000001db: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastBranchFromIp";
+        case 0x000001dc: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastBranchToIp";
+        case 0x000001dd: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastIntFromIp";
+        case 0x000001de: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastIntToIp";
+        case 0x000001f0: return "IntelI7VirtualLegacyWireCap"; /* SandyBridge. */
+        case 0x000001f2: return "Ia32SmrrPhysBase";
+        case 0x000001f3: return "Ia32SmrrPhysMask";
+        case 0x000001f8: return "Ia32PlatformDcaCap";
+        case 0x000001f9: return "Ia32CpuDcaCap";
+        case 0x000001fa: return "Ia32Dca0Cap";
+        case 0x000001fc: return "IntelI7PowerCtl";
+
+        case 0x00000200: case 0x00000202: case 0x00000204: case 0x00000206:
+        case 0x00000208: case 0x0000020a: case 0x0000020c: case 0x0000020e:
+        case 0x00000210: case 0x00000212: case 0x00000214: case 0x00000216:
+        case 0x00000218: case 0x0000021a: case 0x0000021c: case 0x0000021e:
+            return "Ia32MtrrPhysBaseN";
+        case 0x00000201: case 0x00000203: case 0x00000205: case 0x00000207:
+        case 0x00000209: case 0x0000020b: case 0x0000020d: case 0x0000020f:
+        case 0x00000211: case 0x00000213: case 0x00000215: case 0x00000217:
+        case 0x00000219: case 0x0000021b: case 0x0000021d: case 0x0000021f:
+            return "Ia32MtrrPhysMaskN";
+        case 0x00000250:
+        case 0x00000258: case 0x00000259:
+        case 0x00000268: case 0x00000269: case 0x0000026a: case 0x0000026b:
+        case 0x0000026c: case 0x0000026d: case 0x0000026e: case 0x0000026f:
+            return "Ia32MtrrFixed";
+        case 0x00000277: *pfTakesValue = true; return "Ia32Pat";
+
+        case 0x00000280: case 0x00000281:  case 0x00000282: case 0x00000283:
+        case 0x00000284: case 0x00000285:  case 0x00000286: case 0x00000287:
+        case 0x00000288: case 0x00000289:  case 0x0000028a: case 0x0000028b:
+        case 0x0000028c: case 0x0000028d:  case 0x0000028e: case 0x0000028f:
+        case 0x00000290: case 0x00000291:  case 0x00000292: case 0x00000293:
+        case 0x00000294: case 0x00000295:  //case 0x00000296: case 0x00000297:
+        //case 0x00000298: case 0x00000299:  case 0x0000029a: case 0x0000029b:
+        //case 0x0000029c: case 0x0000029d:  case 0x0000029e: case 0x0000029f:
+            return "Ia32McNCtl2";
+
+        case 0x000002ff: return "Ia32MtrrDefType";
+        //case 0x00000305: return g_fIntelNetBurst ? TODO : NULL;
+        case 0x00000309: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
+        case 0x0000030a: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
+        case 0x0000030b: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
+        case 0x00000345: *pfTakesValue = true; return "Ia32PerfCapabilities";
+        /* Note! Lots of P4 MSR 0x00000360..0x00000371. */
+        case 0x0000038d: return "Ia32FixedCtrCtrl";
+        case 0x0000038e: *pfTakesValue = true; return "Ia32PerfGlobalStatus";
+        case 0x0000038f: return "Ia32PerfGlobalCtrl";
+        case 0x00000390: return "Ia32PerfGlobalOvfCtrl";
+        case 0x00000391: return "IntelI7UncPerfGlobalCtrl";             /* S,H,X */
+        case 0x00000392: return "IntelI7UncPerfGlobalStatus";           /* S,H,X */
+        case 0x00000393: return "IntelI7UncPerfGlobalOvfCtrl";          /* X. ASSUMING this is the same on sandybridge and later. */
+        case 0x00000394: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPerfFixedCtr"  /* X */   : "IntelI7UncPerfFixedCtrCtrl"; /* >= S,H */
+        case 0x00000395: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPerfFixedCtrCtrl" /* X*/ : "IntelI7UncPerfFixedCtr";     /* >= S,H */
+        case 0x00000396: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncAddrOpcodeMatch" /* X */ : "IntelI7UncCBoxConfig";       /* >= S,H */
+        case 0x0000039c: return "IntelI7SandyPebsNumAlt";
+         /* Note! Lots of P4 MSR 0x000003a0..0x000003e1. */
+        case 0x000003b0: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfCtrN";      /* >= S,H */
+        case 0x000003b1: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfCtrN";      /* >= S,H */
+        case 0x000003b2: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfEvtSelN";   /* >= S,H */
+        case 0x000003b3: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfEvtSelN";   /* >= S,H */
+        case 0x000003b4: case 0x000003b5: case 0x000003b6: case 0x000003b7:
+            return g_fIntelNetBurst ? NULL : "IntelI7UncPmcN";
+        case 0x000003c0: case 0x000003c1: case 0x000003c2: case 0x000003c3:
+        case 0x000003c4: case 0x000003c5: case 0x000003c6: case 0x000003c7:
+            return g_fIntelNetBurst ? NULL : "IntelI7UncPerfEvtSelN";
+        case 0x000003f1: return "Ia32PebsEnable";
+        case 0x000003f6: return g_fIntelNetBurst ? NULL /*??*/ : "IntelI7PebsLdLat";
+        case 0x000003f8: return g_fIntelNetBurst ? NULL : "IntelI7PkgCnResidencyN";
+        case 0x000003f9: return "IntelI7PkgCnResidencyN";
+        case 0x000003fa: return "IntelI7PkgCnResidencyN";
+        case 0x000003fc: return "IntelI7CoreCnResidencyN";
+        case 0x000003fd: return "IntelI7CoreCnResidencyN";
+        case 0x000003fe: return "IntelI7CoreCnResidencyN";
+
+        case 0x00000478: return g_enmMicroarch == kCpumMicroarch_Intel_Core2_Penryn ? "IntelCpuId1FeatureMaskEcdx" : NULL;
+        case 0x00000480: *pfTakesValue = true; return "Ia32VmxBase";
+        case 0x00000481: *pfTakesValue = true; return "Ia32VmxPinbasedCtls";
+        case 0x00000482: *pfTakesValue = true; return "Ia32VmxProcbasedCtls";
+        case 0x00000483: *pfTakesValue = true; return "Ia32VmxExitCtls";
+        case 0x00000484: *pfTakesValue = true; return "Ia32VmxEntryCtls";
+        case 0x00000485: *pfTakesValue = true; return "Ia32VmxMisc";
+        case 0x00000486: *pfTakesValue = true; return "Ia32VmxCr0Fixed0";
+        case 0x00000487: *pfTakesValue = true; return "Ia32VmxCr0Fixed1";
+        case 0x00000488: *pfTakesValue = true; return "Ia32VmxCr4Fixed0";
+        case 0x00000489: *pfTakesValue = true; return "Ia32VmxCr4Fixed1";
+        case 0x0000048a: *pfTakesValue = true; return "Ia32VmxVmcsEnum";
+        case 0x0000048b: *pfTakesValue = true; return "Ia32VmxProcBasedCtls2";
+        case 0x0000048c: *pfTakesValue = true; return "Ia32VmxEptVpidCap";
+        case 0x0000048d: *pfTakesValue = true; return "Ia32VmxTruePinbasedCtls";
+        case 0x0000048e: *pfTakesValue = true; return "Ia32VmxTrueProcbasedCtls";
+        case 0x0000048f: *pfTakesValue = true; return "Ia32VmxTrueExitCtls";
+        case 0x00000490: *pfTakesValue = true; return "Ia32VmxTrueEntryCtls";
+
+        case 0x000004c1:
+        case 0x000004c2:
+        case 0x000004c3:
+        case 0x000004c4:
+        case 0x000004c5:
+        case 0x000004c6:
+        case 0x000004c7:
+        case 0x000004c8:
+            return "Ia32PmcN";
+
+        case 0x000005a0: return "IntelCore2PeciControl"; /* Core2_Penryn. */
+
+        case 0x00000600: return "Ia32DsArea";
+        case 0x00000601: return "IntelI7SandyVrCurrentConfig";
+        case 0x00000603: return "IntelI7SandyVrMiscConfig";
+        case 0x00000606: return "IntelI7SandyRaplPowerUnit";
+        case 0x0000060a: return "IntelI7SandyPkgCnIrtlN";
+        case 0x0000060b: return "IntelI7SandyPkgCnIrtlN";
+        case 0x0000060c: return "IntelI7SandyPkgCnIrtlN";
+        case 0x0000060d: return "IntelI7SandyPkgC2Residency";
+
+        case 0x00000610: return "IntelI7RaplPkgPowerLimit";
+        case 0x00000611: return "IntelI7RaplPkgEnergyStatus";
+        case 0x00000613: return "IntelI7RaplPkgPerfStatus";
+        case 0x00000614: return "IntelI7RaplPkgPowerInfo";
+        case 0x00000618: return "IntelI7RaplDramPowerLimit";
+        case 0x00000619: return "IntelI7RaplDramEnergyStatus";
+        case 0x0000061b: return "IntelI7RaplDramPerfStatus";
+        case 0x0000061c: return "IntelI7RaplDramPowerInfo";
+        case 0x00000638: return "IntelI7RaplPp0PowerLimit";
+        case 0x00000639: return "IntelI7RaplPp0EnergyStatus";
+        case 0x0000063a: return "IntelI7RaplPp0Policy";
+        case 0x0000063b: return "IntelI7RaplPp0PerfStatus";
+        case 0x00000640: return "IntelI7RaplPp1PowerLimit";
+        case 0x00000641: return "IntelI7RaplPp1EnergyStatus";
+        case 0x00000642: return "IntelI7RaplPp1Policy";
+        case 0x00000648: return "IntelI7IvyConfigTdpNominal";
+        case 0x00000649: return "IntelI7IvyConfigTdpLevel1";
+        case 0x0000064a: return "IntelI7IvyConfigTdpLevel2";
+        case 0x0000064b: return "IntelI7IvyConfigTdpControl";
+        case 0x0000064c: return "IntelI7IvyTurboActivationRatio";
+
+        case 0x00000680: case 0x00000681: case 0x00000682: case 0x00000683:
+        case 0x00000684: case 0x00000685: case 0x00000686: case 0x00000687:
+        case 0x00000688: case 0x00000689: case 0x0000068a: case 0x0000068b:
+        case 0x0000068c: case 0x0000068d: case 0x0000068e: case 0x0000068f:
+        //case 0x00000690: case 0x00000691: case 0x00000692: case 0x00000693:
+        //case 0x00000694: case 0x00000695: case 0x00000696: case 0x00000697:
+        //case 0x00000698: case 0x00000699: case 0x0000069a: case 0x0000069b:
+        //case 0x0000069c: case 0x0000069d: case 0x0000069e: case 0x0000069f:
+            return "IntelLastBranchFromN";
+        case 0x000006c0: case 0x000006c1: case 0x000006c2: case 0x000006c3:
+        case 0x000006c4: case 0x000006c5: case 0x000006c6: case 0x000006c7:
+        case 0x000006c8: case 0x000006c9: case 0x000006ca: case 0x000006cb:
+        case 0x000006cc: case 0x000006cd: case 0x000006ce: case 0x000006cf:
+        //case 0x000006d0: case 0x000006d1: case 0x000006d2: case 0x000006d3:
+        //case 0x000006d4: case 0x000006d5: case 0x000006d6: case 0x000006d7:
+        //case 0x000006d8: case 0x000006d9: case 0x000006da: case 0x000006db:
+        //case 0x000006dc: case 0x000006dd: case 0x000006de: case 0x000006df:
+            return "IntelLastBranchToN";
+        case 0x000006e0: return "Ia32TscDeadline"; /** @todo detect this correctly! */
+
+        case 0x00000c80: return g_enmMicroarch > kCpumMicroarch_Intel_Core7_Nehalem ? "Ia32DebugInterface" : NULL;
+
+        case 0xc0000080: return "Amd64Efer";
+        case 0xc0000081: return "Amd64SyscallTarget";
+        case 0xc0000082: return "Amd64LongSyscallTarget";
+        case 0xc0000083: return "Amd64CompSyscallTarget";
+        case 0xc0000084: return "Amd64SyscallFlagMask";
+        case 0xc0000100: return "Amd64FsBase";
+        case 0xc0000101: return "Amd64GsBase";
+        case 0xc0000102: return "Amd64KernelGsBase";
+        case 0xc0000103: return "Amd64TscAux";
+        case 0xc0000104: return "AmdFam15hTscRate";
+        case 0xc0000105: return "AmdFam15hLwpCfg";
+        case 0xc0000106: return "AmdFam15hLwpCbAddr";
+        case 0xc0000408: return "AmdFam10hMc4MiscN";
+        case 0xc0000409: return "AmdFam10hMc4MiscN";
+        case 0xc000040a: return "AmdFam10hMc4MiscN";
+        case 0xc000040b: return "AmdFam10hMc4MiscN";
+        case 0xc000040c: return "AmdFam10hMc4MiscN";
+        case 0xc000040d: return "AmdFam10hMc4MiscN";
+        case 0xc000040e: return "AmdFam10hMc4MiscN";
+        case 0xc000040f: return "AmdFam10hMc4MiscN";
+        case 0xc0010000: return "AmdK8PerfCtlN";
+        case 0xc0010001: return "AmdK8PerfCtlN";
+        case 0xc0010002: return "AmdK8PerfCtlN";
+        case 0xc0010003: return "AmdK8PerfCtlN";
+        case 0xc0010004: return "AmdK8PerfCtrN";
+        case 0xc0010005: return "AmdK8PerfCtrN";
+        case 0xc0010006: return "AmdK8PerfCtrN";
+        case 0xc0010007: return "AmdK8PerfCtrN";
+        case 0xc0010010: *pfTakesValue = true; return "AmdK8SysCfg";
+        case 0xc0010015: return "AmdK8HwCr";
+        case 0xc0010016: case 0xc0010018: return "AmdK8IorrBaseN";
+        case 0xc0010017: case 0xc0010019: return "AmdK8IorrMaskN";
+        case 0xc001001a: case 0xc001001d: return "AmdK8TopOfMemN";
+        case 0xc001001f: return "AmdK8NbCfg1";
+        case 0xc0010020: return "AmdK8PatchLoader";
+        case 0xc0010022: return "AmdK8McXcptRedir";
+        case 0xc0010030: case 0xc0010031: case 0xc0010032:
+        case 0xc0010033: case 0xc0010034: case 0xc0010035:
+            return "AmdK8CpuNameN";
+        case 0xc001003e: *pfTakesValue = true; return "AmdK8HwThermalCtrl";
+        case 0xc001003f: return "AmdK8SwThermalCtrl";
+        case 0xc0010041: *pfTakesValue = true; return "AmdK8FidVidControl";
+        case 0xc0010042: *pfTakesValue = true; return "AmdK8FidVidStatus";
+        case 0xc0010044: case 0xc0010045: case 0xc0010046: case 0xc0010047:
+        case 0xc0010048: case 0xc0010049: case 0xc001004a: //case 0xc001004b:
+            return "AmdK8McCtlMaskN";
+        case 0xc0010050: case 0xc0010051: case 0xc0010052: case 0xc0010053:
+            return "AmdK8SmiOnIoTrapN";
+        case 0xc0010054: return "AmdK8SmiOnIoTrapCtlSts";
+        case 0xc0010055: return "AmdK8IntPendingMessage";
+        case 0xc0010056: return "AmdK8SmiTriggerIoCycle";
+        case 0xc0010058: return "AmdFam10hMmioCfgBaseAddr";
+        case 0xc0010059: return "AmdFam10hTrapCtlMaybe";
+        case 0xc0010061: *pfTakesValue = true; return "AmdFam10hPStateCurLimit";
+        case 0xc0010062: *pfTakesValue = true; return "AmdFam10hPStateControl";
+        case 0xc0010063: *pfTakesValue = true; return "AmdFam10hPStateStatus";
+        case 0xc0010064: case 0xc0010065: case 0xc0010066: case 0xc0010067:
+        case 0xc0010068: case 0xc0010069: case 0xc001006a: case 0xc001006b:
+            *pfTakesValue = true; return "AmdFam10hPStateN";
+        case 0xc0010070: *pfTakesValue = true; return "AmdFam10hCofVidControl";
+        case 0xc0010071: *pfTakesValue = true; return "AmdFam10hCofVidStatus";
+        case 0xc0010073: return "AmdFam10hCStateIoBaseAddr";
+        case 0xc0010074: return "AmdFam10hCpuWatchdogTimer";
+        // case 0xc0010075: return "AmdFam15hApmlTdpLimit";
+        // case 0xc0010077: return "AmdFam15hCpuPowerInTdp";
+        // case 0xc0010078: return "AmdFam15hPowerAveragingPeriod";
+        // case 0xc0010079: return "AmdFam15hDramCtrlCmdThrottle";
+        // case 0xc0010080: return "AmdFam16hFreqSensFeedbackMonActCnt0";
+        // case 0xc0010081: return "AmdFam16hFreqSensFeedbackMonRefCnt0";
+        case 0xc0010111: return "AmdK8SmmBase";     /** @todo probably misdetected ign/gp due to locking */
+        case 0xc0010112: return "AmdK8SmmAddr";     /** @todo probably misdetected ign/gp due to locking */
+        case 0xc0010113: return "AmdK8SmmMask";     /** @todo probably misdetected ign/gp due to locking */
+        case 0xc0010114: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdK8VmCr" : NULL;        /** @todo probably misdetected due to locking */
+        case 0xc0010115: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdK8IgnNe" : NULL;
+        case 0xc0010116: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdK8SmmCtl" : NULL;
+        case 0xc0010117: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdK8VmHSavePa" : NULL;   /** @todo probably misdetected due to locking */
+        case 0xc0010118: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdFam10hVmLockKey" : NULL;
+        case 0xc0010119: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdFam10hSmmLockKey" : NULL; /* Not documented by BKDG, found in netbsd patch. */
+        case 0xc001011a: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdFam10hLocalSmiStatus" : NULL;
+        case 0xc0010140: *pfTakesValue = true; return "AmdFam10hOsVisWrkIdLength";
+        case 0xc0010141: *pfTakesValue = true; return "AmdFam10hOsVisWrkStatus";
+        case 0xc0010200: case 0xc0010202: case 0xc0010204: case 0xc0010206:
+        case 0xc0010208: case 0xc001020a: //case 0xc001020c: case 0xc001020e:
+            return "AmdK8PerfCtlN";
+        case 0xc0010201: case 0xc0010203: case 0xc0010205: case 0xc0010207:
+        case 0xc0010209: case 0xc001020b: //case 0xc001020d: case 0xc001020f:
+            return "AmdK8PerfCtrN";
+        case 0xc0010230: case 0xc0010232: case 0xc0010234: case 0xc0010236:
+        //case 0xc0010238: case 0xc001023a: case 0xc001030c: case 0xc001023e:
+            return "AmdFam16hL2IPerfCtlN";
+        case 0xc0010231: case 0xc0010233: case 0xc0010235: case 0xc0010237:
+        //case 0xc0010239: case 0xc001023b: case 0xc001023d: case 0xc001023f:
+            return "AmdFam16hL2IPerfCtrN";
+        case 0xc0010240: case 0xc0010242: case 0xc0010244: case 0xc0010246:
+        //case 0xc0010248: case 0xc001024a: case 0xc001024c: case 0xc001024e:
+            return "AmdFam15hNorthbridgePerfCtlN";
+        case 0xc0010241: case 0xc0010243: case 0xc0010245: case 0xc0010247:
+        //case 0xc0010249: case 0xc001024b: case 0xc001024d: case 0xc001024f:
+            return "AmdFam15hNorthbridgePerfCtrN";
+        case 0xc0011000: *pfTakesValue = true; return "AmdK7MicrocodeCtl";
+        case 0xc0011001: *pfTakesValue = true; return "AmdK7ClusterIdMaybe";
+        case 0xc0011002: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd07hEbax" : NULL;
+        case 0xc0011003: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd06hEcx"  : NULL;
+        case 0xc0011004: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd01hEdcx" : NULL;
+        case 0xc0011005: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlExt01hEdcx" : NULL;
+        case 0xc0011006: return "AmdK7DebugStatusMaybe";
+        case 0xc0011007: return "AmdK7BHTraceBaseMaybe";
+        case 0xc0011008: return "AmdK7BHTracePtrMaybe";
+        case 0xc0011009: return "AmdK7BHTraceLimitMaybe";
+        case 0xc001100a: return "AmdK7HardwareDebugToolCfgMaybe";
+        case 0xc001100b: return "AmdK7FastFlushCountMaybe";
+        case 0xc001100c: return "AmdK7NodeId"; /** @todo dunno if this was there is K7 already. Kinda doubt it. */
+        case 0xc0011019: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
+        case 0xc001101a: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
+        case 0xc001101b: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
+        case 0xc0011020: return "AmdK7LoadStoreCfg";
+        case 0xc0011021: return "AmdK7InstrCacheCfg";
+        case 0xc0011022: return "AmdK7DataCacheCfg";
+        case 0xc0011023: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hCombUnitCfg" : "AmdK7BusUnitCfg";
+        case 0xc0011024: return "AmdK7DebugCtl2Maybe";
+        case 0xc0011025: return "AmdK7Dr0DataMatchMaybe";
+        case 0xc0011026: return "AmdK7Dr0DataMaskMaybe";
+        case 0xc0011027: return "AmdK7DrXAddrMaskN";
+        case 0xc0011028: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AmdFam15hFpuCfg" : NULL;
+        case 0xc0011029: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AmdFam15hDecoderCfg" : NULL;
+        case 0xc001102a: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hCombUnitCfg2"
+                              : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) || g_enmMicroarch > kCpumMicroarch_AMD_15h_End
+                              ? "AmdFam10hBusUnitCfg2" /* 10h & 16h */ : NULL;
+        case 0xc001102b: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hCombUnitCfg3" : NULL;
+        case 0xc001102c: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hExecUnitCfg" : NULL;
+        case 0xc001102d: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hLoadStoreCfg2" : NULL;
+        case 0xc0011030: return "AmdFam10hIbsFetchCtl";
+        case 0xc0011031: return "AmdFam10hIbsFetchLinAddr";
+        case 0xc0011032: return "AmdFam10hIbsFetchPhysAddr";
+        case 0xc0011033: return "AmdFam10hIbsOpExecCtl";
+        case 0xc0011034: return "AmdFam10hIbsOpRip";
+        case 0xc0011035: return "AmdFam10hIbsOpData";
+        case 0xc0011036: return "AmdFam10hIbsOpData2";
+        case 0xc0011037: return "AmdFam10hIbsOpData3";
+        case 0xc0011038: return "AmdFam10hIbsDcLinAddr";
+        case 0xc0011039: return "AmdFam10hIbsDcPhysAddr";
+        case 0xc001103a: return "AmdFam10hIbsCtl";
+        case 0xc001103b: return "AmdFam14hIbsBrTarget";
+    }
+    return NULL;
+}
+
+
+/**
+ * Names CPUMCPU variables that MSRs corresponds to.
+ *
+ * @returns The variable name @a uMsr corresponds to, NULL if no variable.
+ * @param   uMsr                The MSR in question.
+ */
+static const char *getMsrCpumCpuVarName(uint32_t uMsr)
+{
+    switch (uMsr)
+    {
+        case 0x00000250: return "GuestMsrs.msr.MtrrFix64K_00000";
+        case 0x00000258: return "GuestMsrs.msr.MtrrFix16K_80000";
+        case 0x00000259: return "GuestMsrs.msr.MtrrFix16K_A0000";
+        case 0x00000268: return "GuestMsrs.msr.MtrrFix4K_C0000";
+        case 0x00000269: return "GuestMsrs.msr.MtrrFix4K_C8000";
+        case 0x0000026a: return "GuestMsrs.msr.MtrrFix4K_D0000";
+        case 0x0000026b: return "GuestMsrs.msr.MtrrFix4K_D8000";
+        case 0x0000026c: return "GuestMsrs.msr.MtrrFix4K_E0000";
+        case 0x0000026d: return "GuestMsrs.msr.MtrrFix4K_E8000";
+        case 0x0000026e: return "GuestMsrs.msr.MtrrFix4K_F0000";
+        case 0x0000026f: return "GuestMsrs.msr.MtrrFix4K_F8000";
+        case 0x00000277: return "Guest.msrPAT";
+        case 0x000002ff: return "GuestMsrs.msr.MtrrDefType";
+    }
+    return NULL;
+}
+
+
+/**
+ * Checks whether the MSR should read as zero for some reason.
+ *
+ * @returns true if the register should read as zero, false if not.
+ * @param   uMsr                The MSR.
+ */
+static bool doesMsrReadAsZero(uint32_t uMsr)
+{
+    switch (uMsr)
+    {
+        case 0x00000088: return true; // "BBL_CR_D0" - RAZ until understood/needed.
+        case 0x00000089: return true; // "BBL_CR_D1" - RAZ until understood/needed.
+        case 0x0000008a: return true; // "BBL_CR_D2" - RAZ until understood/needed.
+
+        /* Non-zero, but unknown register. */
+        case 0x0000004a:
+        case 0x0000004b:
+        case 0x0000004c:
+        case 0x0000004d:
+        case 0x0000004e:
+        case 0x0000004f:
+        case 0x00000050:
+        case 0x00000051:
+        case 0x00000052:
+        case 0x00000053:
+        case 0x00000054:
+        case 0x0000008c:
+        case 0x0000008d:
+        case 0x0000008e:
+        case 0x0000008f:
+        case 0x00000090:
+        case 0xc0011011:
+            return true;
+    }
+
+    return false;
+}
+
+
+/**
+ * Gets the skip mask for the given MSR.
+ *
+ * @returns Skip mask (0 means skipping nothing).
+ * @param   uMsr                The MSR.
+ */
+static uint64_t getGenericSkipMask(uint32_t uMsr)
+{
+    switch (uMsr)
+    {
+        case 0x0000013c: return 3; /* AES-NI lock bit ++. */
+
+        case 0x000001f2: return UINT64_C(0xfffff00f); /* Ia32SmrrPhysBase - Only writable in SMM. */
+        case 0x000001f3: return UINT64_C(0xfffff800); /* Ia32SmrrPhysMask - Only writable in SMM. */
+
+        /* these two have lock bits. */
+        case 0x0000064b: return UINT64_C(0x80000003);
+        case 0x0000064c: return UINT64_C(0x800000ff);
+
+        case 0xc0010015: return 1; /* SmmLock bit */
+
+        /* SmmLock effect: */
+        case 0xc0010111: return UINT32_MAX;
+        case 0xc0010112: return UINT64_C(0xfffe0000) | ((RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(uint64_t)UINT32_MAX);
+        case 0xc0010113: return UINT64_C(0xfffe773f) | ((RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(uint64_t)UINT32_MAX);
+        case 0xc0010116: return 0x1f;
+
+        case 0xc0010114: return RT_BIT_64(3) /* SVM lock */ | RT_BIT_64(4) /* SvmeDisable */;
+
+        /* Canonical */
+        case 0xc0011034:
+        case 0xc0011038:
+        case 0xc001103b:
+            return UINT64_C(0xffff800000000000);
+
+        case 0x00000060: case 0x00000061: case 0x00000062: case 0x00000063:
+        case 0x00000064: case 0x00000065: case 0x00000066: case 0x00000067:
+        case 0x00000040: case 0x00000041: case 0x00000042: case 0x00000043:
+        case 0x00000044: case 0x00000045: case 0x00000046: case 0x00000047:
+        case 0x00000600:
+            if (g_enmMicroarch >= kCpumMicroarch_Intel_Core2_First)
+                return UINT64_C(0xffff800000000000);
+            break;
+
+
+        /* Write only bits. */
+        case 0xc0010041: return RT_BIT_64(16); /* FIDVID_CTL.InitFidVid */
+
+        /* Time counters - fudge them to avoid incorrect ignore masks. */
+        case 0x00000010:
+        case 0x000000e7:
+        case 0x000000e8:
+            return RT_BIT_32(29) - 1;
+    }
+    return 0;
+}
+
+
+
+
+/** queryMsrWriteBadness return values. */
+typedef enum
+{
+    /** . */
+    VBCPUREPBADNESS_MOSTLY_HARMLESS = 0,
+    /** Not a problem if accessed with care. */
+    VBCPUREPBADNESS_MIGHT_BITE,
+    /** Worse than a bad james bond villain. */
+    VBCPUREPBADNESS_BOND_VILLAIN
+} VBCPUREPBADNESS;
+
+
+/**
+ * Backlisting and graylisting of MSRs which may cause tripple faults.
+ *
+ * @returns Badness factor.
+ * @param   uMsr                The MSR in question.
+ */
+static VBCPUREPBADNESS queryMsrWriteBadness(uint32_t uMsr)
+{
+    /** @todo Having trouble in the 0xc0010247,0xc0011006,?? region on Bulldozer. */
+    /** @todo Having trouble in the 0xc001100f,0xc001100d,?? region on Opteron
+     *        2384. */
+
+    switch (uMsr)
+    {
+        case 0x00000050:
+        case 0x00000051:
+        case 0x00000052:
+        case 0x00000053:
+        case 0x00000054:
+
+        case 0x00001006:
+        case 0x00001007:
+            return VBCPUREPBADNESS_BOND_VILLAIN;
+
+        case 0x0000120e:
+        case 0x00001233:
+        case 0x00001239:
+        case 0x00001249:
+        case 0x0000124a:
+        case 0x00001404:
+        case 0x00001405:
+        case 0x00001413:
+        case 0x0000142c: /* Caused rip to be set to 297 or some such weirdness... */
+        case 0x0000142e:
+        case 0x00001435:
+        case 0x00001436:
+        case 0x00001438:
+        case 0x0000317f:
+            if (g_enmVendor == CPUMCPUVENDOR_VIA)
+                return VBCPUREPBADNESS_BOND_VILLAIN;
+            break;
+
+        case 0xc0010010:
+        case 0xc0010016:
+        case 0xc0010017:
+        case 0xc0010018:
+        case 0xc0010019:
+        case 0xc001001a:
+        case 0xc001001d:
+        case 0xc0010064: /* P-state fequency, voltage, ++. */
+        case 0xc0010065: /* P-state fequency, voltage, ++. */
+        case 0xc0010066: /* P-state fequency, voltage, ++. */
+        case 0xc0010067: /* P-state fequency, voltage, ++. */
+        case 0xc0010068: /* P-state fequency, voltage, ++. */
+        case 0xc0010069: /* P-state fequency, voltage, ++. */
+        case 0xc001006a: /* P-state fequency, voltage, ++. */
+        case 0xc001006b: /* P-state fequency, voltage, ++. */
+        case 0xc0010070: /* COFVID Control. */
+        case 0xc001101e:
+        case 0xc0011021: /* IC_CFG (instruction cache configuration) */
+        case 0xc0011023: /* CU_CFG (combined unit configuration) */
+        case 0xc001102c: /* EX_CFG (execution unit configuration) */
+            return VBCPUREPBADNESS_BOND_VILLAIN;
+
+        case 0xc0011012:
+            if (CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch))
+                return VBCPUREPBADNESS_MIGHT_BITE;
+            break;
+
+        case 0x000001a0: /* IA32_MISC_ENABLE */
+        case 0x00000199: /* IA32_PERF_CTL */
+            return VBCPUREPBADNESS_MIGHT_BITE;
+        case 0x00002000: /* P6_CR0. */
+        case 0x00002003: /* P6_CR3. */
+        case 0x00002004: /* P6_CR4. */
+            if (g_enmVendor == CPUMCPUVENDOR_INTEL)
+                return VBCPUREPBADNESS_MIGHT_BITE;
+            break;
+        case 0xc0000080: /* MSR_K6_EFER */
+            return VBCPUREPBADNESS_MIGHT_BITE;
+    }
+    return VBCPUREPBADNESS_MOSTLY_HARMLESS;
+}
+
+
+/**
+ * Checks if this might be a VIA dummy register.
+ *
+ * @returns true if it's a dummy, false if it isn't.
+ * @param   uMsr                The MSR.
+ * @param   uValue              The value.
+ * @param   fFlags              The flags.
+ */
+static bool isMsrViaDummy(uint32_t uMsr, uint64_t uValue, uint32_t fFlags)
+{
+    if (g_enmVendor != CPUMCPUVENDOR_VIA)
+        return false;
+
+    if (uValue)
+        return false;
+
+    if (fFlags)
+        return false;
+
+    switch (uMsr)
+    {
+        case 0x00000010:
+        case 0x0000001b:
+        case 0x000000c1:
+        case 0x000000c2:
+        case 0x0000011e:
+        case 0x00000186:
+        case 0x00000187:
+        //case 0x00000200 ... (mtrrs will be detected)
+            return false;
+
+        case 0xc0000080:
+        case 0xc0000081:
+        case 0xc0000082:
+        case 0xc0000083:
+            if (vbCpuRepSupportsLongMode())
+                return false;
+            break;
+    }
+
+    if (uMsr >= 0x00001200 && uMsr <= 0x00003fff && queryMsrWriteBadness(uMsr) != VBCPUREPBADNESS_MOSTLY_HARMLESS)
+        return false;
+
+    if (   !msrProberModifyNoChange(uMsr)
+        && !msrProberModifyZero(uMsr))
+        return false;
+
+    uint64_t fIgnMask  = 0;
+    uint64_t fGpMask   = 0;
+    int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, 0);
+    if (RT_FAILURE(rc))
+        return false;
+
+    if (fIgnMask != UINT64_MAX)
+        return false;
+    if (fGpMask != 0)
+        return false;
+
+    return true;
+}
+
+
+
+
+/**
+ * Prints a 64-bit value in the best way.
+ *
+ * @param   uValue              The value.
+ */
+static void printMsrValueU64(uint64_t uValue)
+{
+    if (uValue == 0)
+        vbCpuRepPrintf(", 0");
+    else if (uValue == UINT16_MAX)
+        vbCpuRepPrintf(", UINT16_MAX");
+    else if (uValue == UINT32_MAX)
+        vbCpuRepPrintf(", UINT32_MAX");
+    else if (uValue == UINT64_MAX)
+        vbCpuRepPrintf(", UINT64_MAX");
+    else if (uValue == UINT64_C(0xffffffff00000000))
+        vbCpuRepPrintf(", ~(uint64_t)UINT32_MAX");
+    else if (uValue <= (UINT32_MAX >> 1))
+        vbCpuRepPrintf(", %#llx", uValue);
+    else if (uValue <= UINT32_MAX)
+        vbCpuRepPrintf(", UINT32_C(%#llx)", uValue);
+    else
+        vbCpuRepPrintf(", UINT64_C(%#llx)", uValue);
+}
+
+
+/**
+ * Prints the newline after an MSR line has been printed.
+ *
+ * This is used as a hook to slow down the output and make sure the remote
+ * terminal or/and output file has received the last update before we go and
+ * crash probing the next MSR.
+ */
+static void printMsrNewLine(void)
+{
+    vbCpuRepPrintf("\n");
+#if 1
+    RTThreadSleep(8);
+#endif
+}
+
+static int printMsrWriteOnly(uint32_t uMsr, const char *pszWrFnName, const char *pszAnnotation)
+{
+    if (!pszWrFnName)
+        pszWrFnName = "IgnoreWrite";
+    vbCpuRepPrintf(pszAnnotation
+                   ? "    MFN(%#010x, \"%s\", WriteOnly, %s), /* %s */"
+                   : "    MFN(%#010x, \"%s\", WriteOnly, %s),",
+                   uMsr, getMsrName(uMsr), pszWrFnName, pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrValueReadOnly(uint32_t uMsr, uint64_t uValue, const char *pszAnnotation)
+{
+    vbCpuRepPrintf("    MVO(%#010x, \"%s\"", uMsr, getMsrName(uMsr));
+    printMsrValueU64(uValue);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+
+static int printMsrValueIgnoreWritesNamed(uint32_t uMsr, uint64_t uValue, const char *pszName, const char *pszAnnotation)
+{
+    vbCpuRepPrintf("    MVI(%#010x, \"%s\"", uMsr, pszName);
+    printMsrValueU64(uValue);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrValueIgnoreWrites(uint32_t uMsr, uint64_t uValue, const char *pszAnnotation)
+{
+    return printMsrValueIgnoreWritesNamed(uMsr, uValue, getMsrName(uMsr), pszAnnotation);
+}
+
+
+static int printMsrValueExtended(uint32_t uMsr, uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask,
+                                  const char *pszAnnotation)
+{
+    vbCpuRepPrintf("    MVX(%#010x, \"%s\"", uMsr, getMsrName(uMsr));
+    printMsrValueU64(uValue);
+    printMsrValueU64(fIgnMask);
+    printMsrValueU64(fGpMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrRangeValueReadOnly(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszAnnotation)
+{
+    vbCpuRepPrintf("    RVO(%#010x, %#010x, \"%s\"", uMsr, uLast, getMsrRangeName(uMsr));
+    printMsrValueU64(uValue);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrRangeValueIgnoreWritesNamed(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszName, const char *pszAnnotation)
+{
+    vbCpuRepPrintf("    RVI(%#010x, %#010x, \"%s\"", uMsr, uLast, pszName);
+    printMsrValueU64(uValue);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrRangeValueIgnoreWrites(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszAnnotation)
+{
+    return printMsrRangeValueIgnoreWritesNamed(uMsr, uLast, uValue, getMsrRangeName(uMsr), pszAnnotation);
+}
+
+
+static int printMsrFunction(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    MFN(%#010x, \"%s\", %s, %s),", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionReadOnly(uint32_t uMsr, const char *pszRdFnName, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    vbCpuRepPrintf("    MFO(%#010x, \"%s\", %s),", uMsr, getMsrName(uMsr), pszRdFnName);
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionIgnoreWrites(uint32_t uMsr, const char *pszRdFnName, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    vbCpuRepPrintf("    MFI(%#010x, \"%s\", %s),", uMsr, getMsrName(uMsr), pszRdFnName);
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionIgnoreMask(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
+                                      uint64_t fIgnMask, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    MFW(%#010x, \"%s\", %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
+    printMsrValueU64(fIgnMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionExtended(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, uint64_t uValue,
+                                    uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    MFX(%#010x, \"%s\", %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
+    printMsrValueU64(uValue);
+    printMsrValueU64(fIgnMask);
+    printMsrValueU64(fGpMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionExtendedIdxVal(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, uint64_t uValue,
+                                          uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    MFX(%#010x, \"%s\", %s, %s, %#x", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, uValue);
+    printMsrValueU64(fIgnMask);
+    printMsrValueU64(fGpMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionCpumCpu(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
+                                   const char *pszCpumCpuStorage, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    if (!pszCpumCpuStorage)
+        pszCpumCpuStorage = getMsrCpumCpuVarName(uMsr);
+    if (!pszCpumCpuStorage)
+        return RTMsgErrorRc(VERR_NOT_FOUND, "Missing CPUMCPU member for %#s (%#x)\n", getMsrName(uMsr), uMsr);
+    vbCpuRepPrintf("    MFS(%#010x, \"%s\", %s, %s, %s),", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, pszCpumCpuStorage);
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrFunctionCpumCpuEx(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
+                                     const char *pszCpumCpuStorage, uint64_t fIgnMask, uint64_t fGpMask,
+                                     const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    if (!pszCpumCpuStorage)
+        pszCpumCpuStorage = getMsrCpumCpuVarName(uMsr);
+    if (!pszCpumCpuStorage)
+        return RTMsgErrorRc(VERR_NOT_FOUND, "Missing CPUMCPU member for %#s (%#x)\n", getMsrName(uMsr), uMsr);
+    vbCpuRepPrintf("    MFZ(%#010x, \"%s\", %s, %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, pszCpumCpuStorage);
+    printMsrValueU64(fIgnMask);
+    printMsrValueU64(fGpMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrRangeFunction(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
+                                 const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    RFN(%#010x, %#010x, \"%s\", %s, %s),", uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName);
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrRangeFunctionEx(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
+                                   uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    RSN(%#010x, %#010x, \"%s\", %s, %s", uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName);
+    printMsrValueU64(uValue);
+    printMsrValueU64(fIgnMask);
+    printMsrValueU64(fGpMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrRangeFunctionExIdxVal(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
+                                         uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
+{
+    if (!pszRdFnName)
+        pszRdFnName = getMsrFnName(uMsr, NULL);
+    if (!pszWrFnName)
+        pszWrFnName = pszRdFnName;
+    vbCpuRepPrintf("    RSN(%#010x, %#010x, \"%s\", %s, %s, %#x",
+                   uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName, uValue);
+    printMsrValueU64(fIgnMask);
+    printMsrValueU64(fGpMask);
+    vbCpuRepPrintf("),");
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+static int printMsrAlias(uint32_t uMsr, uint32_t uTarget, const char *pszAnnotation)
+{
+    vbCpuRepPrintf("    MAL(%#010x, \"%s\", %#010x),", uMsr, getMsrName(uMsr), uTarget);
+    if (pszAnnotation)
+        vbCpuRepPrintf(" /* %s */", pszAnnotation);
+    printMsrNewLine();
+    return VINF_SUCCESS;
+}
+
+
+
+static const char *annotateValue(uint64_t uValue)
+{
+    static char s_szBuf[40];
+    if (uValue <= UINT32_MAX)
+        RTStrPrintf(s_szBuf, sizeof(s_szBuf), "value=%#llx", uValue);
+    else
+        RTStrPrintf(s_szBuf, sizeof(s_szBuf), "value=%#x`%08x", RT_HI_U32(uValue), RT_LO_U32(uValue));
+    return s_szBuf;
+}
+
+
+static const char *annotateValueExtra(const char *pszExtra, uint64_t uValue)
+{
+    static char s_szBuf[40];
+    if (uValue <= UINT32_MAX)
+        RTStrPrintf(s_szBuf, sizeof(s_szBuf), "%s value=%#llx", pszExtra, uValue);
+    else
+        RTStrPrintf(s_szBuf, sizeof(s_szBuf), "%s value=%#x`%08x", pszExtra, RT_HI_U32(uValue), RT_LO_U32(uValue));
+    return s_szBuf;
+}
+
+
+static const char *annotateIfMissingBits(uint64_t uValue, uint64_t fBits)
+{
+    static char s_szBuf[80];
+    if ((uValue & fBits) == fBits)
+        return annotateValue(uValue);
+    RTStrPrintf(s_szBuf, sizeof(s_szBuf), "XXX: Unexpected value %#llx - wanted bits %#llx to be set.", uValue, fBits);
+    return s_szBuf;
+}
+
+
+static int reportMsr_Generic(uint32_t uMsr, uint32_t fFlags, uint64_t uValue)
+{
+    int         rc;
+    bool        fTakesValue = false;
+    const char *pszFnName   = getMsrFnName(uMsr, &fTakesValue);
+
+    if (fFlags & VBCPUREPMSR_F_WRITE_ONLY)
+        rc = printMsrWriteOnly(uMsr, pszFnName, NULL);
+    else
+    {
+        bool    fReadAsZero = doesMsrReadAsZero(uMsr);
+        fTakesValue = fTakesValue && !fReadAsZero;
+
+
+        switch (queryMsrWriteBadness(uMsr))
+        {
+            /* This is what we're here for... */
+            case VBCPUREPBADNESS_MOSTLY_HARMLESS:
+            {
+                if (   msrProberModifyNoChange(uMsr)
+                    || msrProberModifyZero(uMsr))
+                {
+                    uint64_t fSkipMask = getGenericSkipMask(uMsr);
+                    uint64_t fIgnMask  = 0;
+                    uint64_t fGpMask   = 0;
+                    rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
+                    if (RT_FAILURE(rc))
+                        return rc;
+
+                    if (pszFnName)
+                    {
+                        if (fGpMask == 0 && fIgnMask == UINT64_MAX && !fTakesValue)
+                            rc = printMsrFunctionIgnoreWrites(uMsr, pszFnName, annotateValue(uValue));
+                        else if (fGpMask == 0 && fIgnMask == 0 && (!fTakesValue || uValue == 0))
+                            rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValue(uValue));
+                        else
+                            rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, fTakesValue ? uValue : 0,
+                                                          fIgnMask, fGpMask, annotateValue(uValue));
+                    }
+                    else if (fGpMask == 0 && fIgnMask == UINT64_MAX)
+                        rc = printMsrValueIgnoreWrites(uMsr, fReadAsZero ? 0 : uValue, fReadAsZero ? annotateValue(uValue) : NULL);
+                    else
+                        rc = printMsrValueExtended(uMsr, fReadAsZero ? 0 : uValue, fIgnMask, fGpMask,
+                                                   fReadAsZero ? annotateValue(uValue) : NULL);
+                }
+                /* Most likely read-only. */
+                else if (pszFnName && !fTakesValue)
+                    rc = printMsrFunctionReadOnly(uMsr, pszFnName, annotateValue(uValue));
+                else if (pszFnName)
+                    rc = printMsrFunctionExtended(uMsr, pszFnName, "ReadOnly", uValue, 0, 0, annotateValue(uValue));
+                else if (fReadAsZero)
+                    rc = printMsrValueReadOnly(uMsr, 0, annotateValue(uValue));
+                else
+                    rc = printMsrValueReadOnly(uMsr, uValue, NULL);
+                break;
+            }
+
+            /* These should have special handling, so just do a simple
+               write back same value check to see if it's writable. */
+            case VBCPUREPBADNESS_MIGHT_BITE:
+                if (msrProberModifyNoChange(uMsr))
+                {
+                    if (pszFnName && !fTakesValue)
+                        rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValueExtra("Might bite.", uValue));
+                    else if (pszFnName)
+                        rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, uValue, 0, 0,
+                                                      annotateValueExtra("Might bite.", uValue));
+                    else if (fReadAsZero)
+                        rc = printMsrValueIgnoreWrites(uMsr, 0, annotateValueExtra("Might bite.", uValue));
+                    else
+                        rc = printMsrValueIgnoreWrites(uMsr, uValue, "Might bite.");
+                }
+                else if (pszFnName && !fTakesValue)
+                    rc = printMsrFunctionReadOnly(uMsr, pszFnName, annotateValueExtra("Might bite.", uValue));
+                else if (pszFnName)
+                    rc = printMsrFunctionExtended(uMsr, pszFnName, "ReadOnly", uValue, 0, UINT64_MAX,
+                                                  annotateValueExtra("Might bite.", uValue));
+                else if (fReadAsZero)
+                    rc = printMsrValueReadOnly(uMsr, 0, annotateValueExtra("Might bite.", uValue));
+                else
+                    rc = printMsrValueReadOnly(uMsr, uValue, "Might bite.");
+                break;
+
+
+            /* Don't try anything with these guys. */
+            case VBCPUREPBADNESS_BOND_VILLAIN:
+            default:
+                if (pszFnName && !fTakesValue)
+                    rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValueExtra("Villain?", uValue));
+                else if (pszFnName)
+                    rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, uValue, 0, 0,
+                                                  annotateValueExtra("Villain?", uValue));
+                else if (fReadAsZero)
+                    rc = printMsrValueIgnoreWrites(uMsr, 0, annotateValueExtra("Villain?", uValue));
+                else
+                    rc = printMsrValueIgnoreWrites(uMsr, uValue, "Villain?");
+                break;
+        }
+    }
+
+    return rc;
+}
+
+
+static int reportMsr_GenRangeFunctionEx(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, const char *pszRdWrFnName,
+                                        uint32_t uMsrBase, bool fEarlyEndOk, bool fNoIgnMask, uint64_t fSkipMask, uint32_t *pidxLoop)
+{
+    uint32_t uMsr   = paMsrs[0].uMsr;
+    uint32_t iRange = uMsr - uMsrBase;
+    Assert(cMax > iRange);
+    cMax -= iRange;
+
+    /* Resolve default function name. */
+    if (!pszRdWrFnName)
+    {
+        pszRdWrFnName = getMsrFnName(uMsr, NULL);
+        if (!pszRdWrFnName)
+            return RTMsgErrorRc(VERR_INVALID_PARAMETER, "uMsr=%#x no function name\n", uMsr);
+    }
+
+    /* Figure the possible register count. */
+    if (cMax > cMsrs)
+        cMax = cMsrs;
+    uint32_t cRegs = 1;
+    while (   cRegs < cMax
+           && paMsrs[cRegs].uMsr == uMsr + cRegs)
+        cRegs++;
+
+    /* Probe the first register and check that the others exhibit
+       the same characteristics. */
+    bool     fReadOnly0;
+    uint64_t fIgnMask0, fGpMask0;
+    int rc = msrProberModifyBasicTests(uMsr, fSkipMask, &fReadOnly0, &fIgnMask0, &fGpMask0);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    const char *pszAnnotation = NULL;
+    for (uint32_t i = 1; i < cRegs; i++)
+    {
+        bool     fReadOnlyN;
+        uint64_t fIgnMaskN, fGpMaskN;
+        rc = msrProberModifyBasicTests(paMsrs[i].uMsr, fSkipMask, &fReadOnlyN, &fIgnMaskN, &fGpMaskN);
+        if (RT_FAILURE(rc))
+            return rc;
+        if (   fReadOnlyN != fReadOnly0
+            || (fIgnMaskN != fIgnMask0 && !fNoIgnMask)
+            || fGpMaskN   != fGpMask0)
+        {
+            if (!fEarlyEndOk && !isMsrViaDummy(uMsr, paMsrs[i].uValue, paMsrs[i].fFlags))
+            {
+                vbCpuRepDebug("MSR %s (%#x) range ended unexpectedly early on %#x: ro=%d ign=%#llx/%#llx gp=%#llx/%#llx [N/0]\n",
+                              getMsrNameHandled(uMsr), uMsr, paMsrs[i].uMsr,
+                              fReadOnlyN, fReadOnly0, fIgnMaskN, fIgnMask0, fGpMaskN, fGpMask0);
+                pszAnnotation = "XXX: The range ended earlier than expected!";
+            }
+            cRegs = i;
+            break;
+        }
+    }
+
+    /*
+     * Report the range (or single MSR as it might be).
+     */
+    *pidxLoop += cRegs - 1;
+
+    if (fNoIgnMask)
+        fIgnMask0 = 0;
+    bool fSimple = fIgnMask0 == 0
+                && (fGpMask0 == 0 || (fGpMask0 == UINT64_MAX && fReadOnly0))
+                && iRange == 0;
+    if (cRegs == 1)
+        return printMsrFunctionExtendedIdxVal(uMsr, pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName,
+                                              iRange, fIgnMask0, fGpMask0,
+                                              pszAnnotation ? pszAnnotation : annotateValue(paMsrs[0].uValue));
+    if (fSimple)
+        return printMsrRangeFunction(uMsr, uMsr + cRegs - 1,
+                                     pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName, pszAnnotation);
+
+    return printMsrRangeFunctionExIdxVal(uMsr, uMsr + cRegs - 1, pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName,
+                                         iRange /*uValue*/, fIgnMask0, fGpMask0, pszAnnotation);
+}
+
+
+static int reportMsr_GenRangeFunction(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, const char *pszRdWrFnName,
+                                      uint32_t *pidxLoop)
+{
+    return reportMsr_GenRangeFunctionEx(paMsrs, cMsrs, cMax, pszRdWrFnName, paMsrs[0].uMsr, false /*fEarlyEndOk*/, false /*fNoIgnMask*/,
+                                        getGenericSkipMask(paMsrs[0].uMsr), pidxLoop);
+}
+
+
+/**
+ * Generic report for an MSR implemented by functions, extended version.
+ *
+ * @returns VBox status code.
+ * @param   uMsr            The MSR.
+ * @param   pszRdWrFnName   The read/write function name, optional.
+ * @param   uValue          The MSR range value.
+ * @param   fSkipMask       Mask of bits to skip.
+ * @param   fNoGpMask       Mask of bits to remove from the GP mask after
+ *                          probing
+ * @param   pszAnnotate     Annotation.
+ */
+static int reportMsr_GenFunctionEx(uint32_t uMsr, const char *pszRdWrFnName, uint32_t uValue,
+                                   uint64_t fSkipMask, uint64_t fNoGpMask, const char *pszAnnotate)
+{
+    /* Resolve default function name. */
+    if (!pszRdWrFnName)
+    {
+        pszRdWrFnName = getMsrFnName(uMsr, NULL);
+        if (!pszRdWrFnName)
+            return RTMsgErrorRc(VERR_INVALID_PARAMETER, "uMsr=%#x no function name\n", uMsr);
+    }
+
+    /* Probe the register and report. */
+    uint64_t fIgnMask = 0;
+    uint64_t fGpMask  = 0;
+    int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
+    if (RT_SUCCESS(rc))
+    {
+        fGpMask &= ~fNoGpMask;
+
+        if (fGpMask == UINT64_MAX && uValue == 0 && !msrProberModifyZero(uMsr))
+            rc = printMsrFunctionReadOnly(uMsr, pszRdWrFnName, pszAnnotate);
+        else if (fIgnMask == UINT64_MAX && fGpMask == 0 && uValue == 0)
+            rc = printMsrFunctionIgnoreWrites(uMsr, pszRdWrFnName, pszAnnotate);
+        else if (fIgnMask != 0 && fGpMask == 0 && uValue == 0)
+            rc = printMsrFunctionIgnoreMask(uMsr, pszRdWrFnName, NULL, fIgnMask, pszAnnotate);
+        else if (fIgnMask == 0 && fGpMask == 0 && uValue == 0)
+            rc = printMsrFunction(uMsr, pszRdWrFnName, NULL, pszAnnotate);
+        else
+            rc = printMsrFunctionExtended(uMsr, pszRdWrFnName, NULL, uValue, fIgnMask, fGpMask, pszAnnotate);
+    }
+    return rc;
+}
+
+
+/**
+ * Reports a VIA dummy range.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MSR entry in the range.
+ */
+static int reportMsr_ViaDummyRange(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    /* Figure how many. */
+    uint32_t uMsr  = paMsrs[0].uMsr;
+    uint32_t cRegs = 1;
+    while (   cRegs < cMsrs
+           && paMsrs[cRegs].uMsr == uMsr + cRegs
+           && isMsrViaDummy(paMsrs[cRegs].uMsr, paMsrs[cRegs].uValue, paMsrs[cRegs].fFlags))
+    {
+        cRegs++;
+        if (!(cRegs % 0x80))
+            vbCpuRepDebug("VIA dummy detection %#llx..%#llx (%#x regs)...\n", uMsr, uMsr + cRegs - 1, cRegs);
+    }
+
+    /* Advance. */
+    *pidxLoop += cRegs - 1;
+
+    /* Report it/them. */
+    char szName[80];
+    if (cRegs == 1)
+    {
+        RTStrPrintf(szName, sizeof(szName), "ZERO_%04x_%04x", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
+        return printMsrValueIgnoreWritesNamed(uMsr, 0, szName, NULL);
+    }
+
+    uint32_t uMsrLast = uMsr +  cRegs - 1;
+    RTStrPrintf(szName, sizeof(szName), "ZERO_%04x_%04x_THRU_%04x_%04x",
+                RT_HI_U16(uMsr), RT_LO_U16(uMsr), RT_HI_U16(uMsrLast), RT_LO_U16(uMsrLast));
+    return printMsrRangeValueIgnoreWritesNamed(uMsr, uMsrLast, 0, szName, NULL);
+}
+
+
+/**
+ * Special function for reporting the IA32_APIC_BASE register, as it seems to be
+ * causing trouble on newer systems.
+ *
+ * @returns
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The value.
+ */
+static int reportMsr_Ia32ApicBase(uint32_t uMsr, uint64_t uValue)
+{
+    /* Trouble with the generic treatment of both the "APIC Global Enable" and
+       "Enable x2APIC mode" bits on an i7-3820QM running OS X 10.8.5.  */
+    uint64_t fSkipMask = RT_BIT_64(11);
+    if (vbCpuRepSupportsX2Apic())
+        fSkipMask |= RT_BIT_64(10);
+    return reportMsr_GenFunctionEx(uMsr, "Ia32ApicBase", uValue, fSkipMask, 0, NULL);
+}
+
+
+/**
+ * Special function for reporting the IA32_MISC_ENABLE register, as it seems to
+ * be causing trouble on newer systems.
+ *
+ * @returns
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The value.
+ */
+static int reportMsr_Ia32MiscEnable(uint32_t uMsr, uint64_t uValue)
+{
+    uint64_t fSkipMask = 0;
+
+    if (   (   g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Broadwell
+            && g_enmMicroarch <= kCpumMicroarch_Intel_Core7_End)
+        || (   g_enmMicroarch >= kCpumMicroarch_Intel_Atom_Airmount
+            && g_enmMicroarch <= kCpumMicroarch_Intel_Atom_End)
+       )
+    {
+        vbCpuRepPrintf("WARNING: IA32_MISC_ENABLE probing needs hacking on this CPU!\n");
+        RTThreadSleep(128);
+    }
+
+    /* The no execute related flag is deadly if clear.  */
+    if (   !(uValue & MSR_IA32_MISC_ENABLE_XD_DISABLE)
+        && (   g_enmMicroarch <  kCpumMicroarch_Intel_First
+            || g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
+            || vbCpuRepSupportsNX() ) )
+        fSkipMask |= MSR_IA32_MISC_ENABLE_XD_DISABLE;
+
+    uint64_t fIgnMask = 0;
+    uint64_t fGpMask  = 0;
+    int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
+    if (RT_SUCCESS(rc))
+        rc = printMsrFunctionExtended(uMsr, "Ia32MiscEnable", "Ia32MiscEnable", uValue,
+                                      fIgnMask, fGpMask, annotateValue(uValue));
+    return rc;
+}
+
+
+/**
+ * Verifies that MTRR type field works correctly in the given MSR.
+ *
+ * @returns VBox status code (failure if bad MSR behavior).
+ * @param   uMsr                The MSR.
+ * @param   iBit                The first bit of the type field (8-bit wide).
+ * @param   cExpected           The number of types expected - PAT=8, MTRR=7.
+ */
+static int msrVerifyMtrrTypeGPs(uint32_t uMsr, uint32_t iBit, uint32_t cExpected)
+{
+    uint32_t uEndTypes = 0;
+    while (uEndTypes < 255)
+    {
+        bool fGp = !msrProberModifySimpleGp(uMsr, ~(UINT64_C(0xff) << iBit), (uint64_t)uEndTypes << iBit);
+        if (!fGp && (uEndTypes == 2 || uEndTypes == 3))
+            return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR types %u does not cause a GP as it should. (msr %#x)\n",
+                                uEndTypes, uMsr);
+        if (fGp && uEndTypes != 2 && uEndTypes != 3)
+            break;
+        uEndTypes++;
+    }
+    if (uEndTypes != cExpected)
+        return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR types detected to be %#x (msr %#x). Expected %#x.\n",
+                            uEndTypes, uMsr, cExpected);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals with the variable MTRR MSRs.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first variable MTRR MSR (200h).
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MTRR MSR entry.
+ */
+static int reportMsr_Ia32MtrrPhysBaseMaskN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    uint32_t uMsr = paMsrs[0].uMsr;
+
+    /* Count them. */
+    uint32_t cRegs = 1;
+    while (   cRegs < cMsrs
+           && paMsrs[cRegs].uMsr == uMsr + cRegs
+           && !isMsrViaDummy(paMsrs[cRegs].uMsr, paMsrs[cRegs].uValue, paMsrs[cRegs].fFlags) )
+        cRegs++;
+    if (cRegs & 1)
+        return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR variable MSR range is odd: cRegs=%#x\n", cRegs);
+    if (cRegs > 0x20)
+        return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR variable MSR range is too large: cRegs=%#x\n", cRegs);
+
+    /* Find a disabled register that we can play around with. */
+    uint32_t iGuineaPig;
+    for (iGuineaPig = 0; iGuineaPig < cRegs; iGuineaPig += 2)
+        if (!(paMsrs[iGuineaPig + 1].uValue & RT_BIT_32(11)))
+            break;
+    if (iGuineaPig >= cRegs)
+        iGuineaPig = cRegs - 2;
+    vbCpuRepDebug("iGuineaPig=%#x -> %#x\n", iGuineaPig, uMsr + iGuineaPig);
+
+    /* Probe the base.  */
+    uint64_t fIgnBase = 0;
+    uint64_t fGpBase  = 0;
+    int rc = msrProberModifyBitChanges(uMsr + iGuineaPig, &fIgnBase, &fGpBase, 0);
+    if (RT_FAILURE(rc))
+        return rc;
+    rc = msrVerifyMtrrTypeGPs(uMsr + iGuineaPig, 0, 7);
+    if (RT_FAILURE(rc))
+        return rc;
+    vbCpuRepDebug("fIgnBase=%#llx fGpBase=%#llx\n", fIgnBase, fGpBase);
+
+    /* Probing the mask is relatively straight forward. */
+    uint64_t fIgnMask = 0;
+    uint64_t fGpMask  = 0;
+    rc = msrProberModifyBitChanges(uMsr + iGuineaPig + 1, &fIgnMask, &fGpMask, 0);
+    if (RT_FAILURE(rc))
+        return rc;
+    vbCpuRepDebug("fIgnMask=%#llx fGpMask=%#llx\n", fIgnMask, fGpMask);
+
+    /* Validate that the whole range subscribes to the apprimately same GP rules. */
+    for (uint32_t i = 0; i < cRegs; i += 2)
+    {
+        uint64_t fSkipBase = ~fGpBase;
+        uint64_t fSkipMask = ~fGpMask;
+        if (!(paMsrs[i + 1].uValue & RT_BIT_32(11)))
+            fSkipBase = fSkipMask = 0;
+        fSkipBase |= 0x7;           /* Always skip the type. */
+        fSkipMask |= RT_BIT_32(11); /* Always skip the enable bit. */
+
+        vbCpuRepDebug("i=%#x fSkipBase=%#llx fSkipMask=%#llx\n", i, fSkipBase, fSkipMask);
+
+        if (!(paMsrs[i + 1].uValue & RT_BIT_32(11)))
+        {
+            rc = msrVerifyMtrrTypeGPs(uMsr + iGuineaPig, 0, 7);
+            if (RT_FAILURE(rc))
+                return rc;
+        }
+
+        uint64_t fIgnBaseN = 0;
+        uint64_t fGpBaseN  = 0;
+        rc = msrProberModifyBitChanges(uMsr + i, &fIgnBaseN, &fGpBaseN, fSkipBase);
+        if (RT_FAILURE(rc))
+            return rc;
+
+        if (   fIgnBaseN != (fIgnBase & ~fSkipBase)
+            || fGpBaseN  != (fGpBase  & ~fSkipBase) )
+            return RTMsgErrorRc(VERR_INVALID_PARAMETER,
+                                "MTRR PHYS BASE register %#x behaves differently from %#x: ign=%#llx/%#llx gp=%#llx/%#llx (fSkipBase=%#llx)\n",
+                                uMsr + i, uMsr + iGuineaPig,
+                                fIgnBaseN, fIgnBase & ~fSkipBase, fGpBaseN, fGpBase & ~fSkipBase, fSkipBase);
+
+        uint64_t fIgnMaskN = 0;
+        uint64_t fGpMaskN  = 0;
+        rc = msrProberModifyBitChanges(uMsr + i + 1, &fIgnMaskN, &fGpMaskN, fSkipMask);
+        if (RT_FAILURE(rc))
+            return rc;
+        if (   fIgnMaskN != (fIgnMask & ~fSkipMask)
+            || fGpMaskN  != (fGpMask  & ~fSkipMask) )
+            return RTMsgErrorRc(VERR_INVALID_PARAMETER,
+                                "MTRR PHYS MASK register %#x behaves differently from %#x: ign=%#llx/%#llx gp=%#llx/%#llx (fSkipMask=%#llx)\n",
+                                uMsr + i + 1, uMsr + iGuineaPig + 1,
+                                fIgnMaskN, fIgnMask & ~fSkipMask, fGpMaskN, fGpMask & ~fSkipMask, fSkipMask);
+    }
+
+    /* Print the whole range. */
+    fGpBase &= ~(uint64_t)0x7; /* Valid type bits, see msrVerifyMtrrTypeGPs(). */
+    for (uint32_t i = 0; i < cRegs; i += 2)
+    {
+        printMsrFunctionExtendedIdxVal(uMsr + i,     "Ia32MtrrPhysBaseN", NULL, i / 2, fIgnBase, fGpBase,
+                                       annotateValue(paMsrs[i].uValue));
+        printMsrFunctionExtendedIdxVal(uMsr + i + 1, "Ia32MtrrPhysMaskN", NULL, i / 2, fIgnMask, fGpMask,
+                                       annotateValue(paMsrs[i + 1].uValue));
+    }
+
+    *pidxLoop += cRegs - 1;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals with fixed MTRR and PAT MSRs, checking the 8 memory type fields.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR.
+ */
+static int reportMsr_Ia32MtrrFixedOrPat(uint32_t uMsr)
+{
+    /* Had a spot of trouble on an old macbook pro with core2 duo T9900 (penryn)
+       running 64-bit win81pe. Not giving PAT such a scrutiny fixes it. */
+    if (   uMsr != 0x00000277
+        || g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First)
+    {
+        /* Every 8 bytes is a type, check the type ranges one by one. */
+        for (uint32_t iBit = 0; iBit < 64; iBit += 8)
+        {
+            int rc = msrVerifyMtrrTypeGPs(uMsr, iBit, 7 + (uMsr == 0x00000277));
+            if (RT_FAILURE(rc))
+                return rc;
+        }
+    }
+
+    return printMsrFunctionCpumCpu(uMsr, NULL, NULL, NULL, NULL);
+}
+
+
+/**
+ * Deals with IA32_MTRR_DEF_TYPE.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR.
+ */
+static int reportMsr_Ia32MtrrDefType(uint32_t uMsr)
+{
+    int rc = msrVerifyMtrrTypeGPs(uMsr, 0, 7);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    uint64_t fGpMask  = 0;
+    uint64_t fIgnMask = 0;
+    rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, 0x7);
+    if (RT_FAILURE(rc))
+        return rc;
+    Assert(!(fGpMask & 7)); Assert(!(fIgnMask & 7));
+
+    return printMsrFunctionCpumCpuEx(uMsr, NULL, NULL, NULL, fIgnMask, fGpMask, NULL);
+}
+
+
+/**
+ * Deals with the Machine Check (MC) MSRs in the 400h+ area.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MC MSR (400h).
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MC MSR entry.
+ */
+static int reportMsr_Ia32McCtlStatusAddrMiscN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    uint32_t uMsr = paMsrs[0].uMsr;
+
+    /* Count them. */
+    uint32_t cRegs = 1;
+    uint32_t cDetectedRegs = 1;
+    while (   cDetectedRegs < cMsrs
+           && (   paMsrs[cDetectedRegs].uMsr == uMsr + cRegs
+               || (cRegs & 3) == 2 /* ADDR may or may not be there, depends on STATUS and CPU. */
+               || (cRegs & 3) == 3 /* MISC may or may not be there, depends on STATUS and CPU. */)
+           && cRegs < 0x7f )
+    {
+        if (paMsrs[cDetectedRegs].uMsr == uMsr + cRegs)
+            cDetectedRegs++;
+        cRegs++;
+    }
+    if (cRegs & 3)
+        return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MC MSR range is odd: cRegs=%#x\n", cRegs);
+
+    /* Just report them.  We don't bother probing here as the CTL format
+       and such seems to be a lot of work to test correctly and changes between
+       cpu generations.  */
+    *pidxLoop += cDetectedRegs - 1;
+    return printMsrRangeFunction(uMsr, uMsr + cRegs - 1, "Ia32McCtlStatusAddrMiscN", NULL, NULL);
+}
+
+
+
+/**
+ * Deals with the X2APIC msrs.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first X2APIC MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last X2APIC MSR entry.
+ */
+static int reportMsr_GenX2Apic(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    /* Advance. */
+    uint32_t cRegs = 1;
+    while (   cRegs < cMsrs
+           && paMsrs[cRegs].uMsr <= 0x8ff)
+        cRegs++;
+    *pidxLoop += cRegs - 1;
+
+    /* Just emit an X2APIC range. */
+    return printMsrRangeFunction(0x800, 0x8ff, "Ia32X2ApicN", NULL, NULL);
+}
+
+
+/**
+ * Deals carefully with the EFER register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_Amd64Efer(uint32_t uMsr, uint64_t uValue)
+{
+    uint64_t fSkipMask = 0;
+    if (vbCpuRepSupportsLongMode())
+        fSkipMask |= MSR_K6_EFER_LME;
+    if (   (uValue & MSR_K6_EFER_NXE)
+        || vbCpuRepSupportsNX())
+        fSkipMask |= MSR_K6_EFER_NXE;
+
+    /* NetBurst prescott 2MB (model 4) hung or triple faulted here.  The extra
+       sleep or something seemed to help for some screwed up reason. */
+    if (g_fIntelNetBurst)
+    {
+        // This doesn't matter:
+        //fSkipMask |= MSR_K6_EFER_SCE;
+        //if (vbCpuRepSupportsLongMode())
+        //    fSkipMask |= MSR_K6_EFER_LMA;
+        //vbCpuRepDebug("EFER - netburst workaround - ignore SCE & LMA (fSkipMask=%#llx)\n", fSkipMask);
+
+        vbCpuRepDebug("EFER - netburst sleep fudge - fSkipMask=%#llx\n", fSkipMask);
+        RTThreadSleep(1000);
+    }
+
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, MSR_K6_EFER_LMA, NULL);
+}
+
+
+/**
+ * Deals with the MC4_MISCn (n >= 1) range and the following reserved MSRs.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MSR entry in the range.
+ */
+static int reportMsr_AmdFam10hMc4MiscN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    /* Count registers. */
+    uint32_t cRegs = 1;
+    while (   cRegs < cMsrs
+           && cRegs < 8
+           && paMsrs[cRegs].uMsr == paMsrs[0].uMsr + cRegs)
+        cRegs++;
+
+    /* Probe & report used MSRs. */
+    uint64_t fIgnMask = 0;
+    uint64_t fGpMask  = 0;
+    uint32_t cUsed    = 0;
+    while (cUsed < cRegs)
+    {
+        uint64_t fIgnMaskN = 0;
+        uint64_t fGpMaskN  = 0;
+        int rc = msrProberModifyBitChanges(paMsrs[cUsed].uMsr, &fIgnMaskN, &fGpMaskN, 0);
+        if (RT_FAILURE(rc))
+            return rc;
+        if (fIgnMaskN == UINT64_MAX || fGpMaskN == UINT64_MAX)
+            break;
+        if (cUsed == 0)
+        {
+            fIgnMask = fIgnMaskN;
+            fGpMask  = fGpMaskN;
+        }
+        else if (   fIgnMaskN != fIgnMask
+                 || fGpMaskN  != fGpMask)
+            return RTMsgErrorRc(VERR_NOT_EQUAL, "AmdFam16hMc4MiscN mismatch: fIgn=%#llx/%#llx fGp=%#llx/%#llx uMsr=%#x\n",
+                                fIgnMaskN, fIgnMask, fGpMaskN, fGpMask, paMsrs[cUsed].uMsr);
+        cUsed++;
+    }
+    if (cUsed > 0)
+        printMsrRangeFunctionEx(paMsrs[0].uMsr, paMsrs[cUsed - 1].uMsr, "AmdFam10hMc4MiscN", NULL, 0, fIgnMask, fGpMask, NULL);
+
+    /* Probe & report reserved MSRs. */
+    uint32_t cReserved = 0;
+    while (cUsed + cReserved < cRegs)
+    {
+        fIgnMask = fGpMask = 0;
+        int rc = msrProberModifyBitChanges(paMsrs[cUsed + cReserved].uMsr, &fIgnMask, &fGpMask, 0);
+        if (RT_FAILURE(rc))
+            return rc;
+        if ((fIgnMask != UINT64_MAX && fGpMask != UINT64_MAX) || paMsrs[cUsed + cReserved].uValue)
+            return RTMsgErrorRc(VERR_NOT_EQUAL,
+                                "Unexpected reserved AmdFam16hMc4MiscN: fIgn=%#llx fGp=%#llx uMsr=%#x uValue=%#llx\n",
+                                fIgnMask, fGpMask, paMsrs[cUsed + cReserved].uMsr, paMsrs[cUsed + cReserved].uValue);
+        cReserved++;
+    }
+    if (cReserved > 0 && fIgnMask == UINT64_MAX)
+        printMsrRangeValueIgnoreWrites(paMsrs[cUsed].uMsr, paMsrs[cUsed + cReserved - 1].uMsr, 0, NULL);
+    else if (cReserved > 0 && fGpMask == UINT64_MAX)
+        printMsrRangeValueReadOnly(paMsrs[cUsed].uMsr, paMsrs[cUsed + cReserved - 1].uMsr, 0, NULL);
+
+    *pidxLoop += cRegs - 1;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals with the AMD PERF_CTL range.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MSR entry in the range.
+ */
+static int reportMsr_AmdK8PerfCtlN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    uint32_t uMsr = paMsrs[0].uMsr;
+    Assert(uMsr == 0xc0010000);
+
+    /* Family 15h (bulldozer +) aliases these registers sparsely onto c001020x. */
+    if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
+    {
+        for (uint32_t i = 0; i < 4; i++)
+            printMsrAlias(uMsr + i, 0xc0010200 + i * 2, NULL);
+        *pidxLoop += 3;
+    }
+    else
+        return reportMsr_GenRangeFunction(paMsrs, cMsrs, 4, "AmdK8PerfCtlN", pidxLoop);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals with the AMD PERF_CTR range.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MSR entry in the range.
+ */
+static int reportMsr_AmdK8PerfCtrN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    uint32_t uMsr = paMsrs[0].uMsr;
+    Assert(uMsr == 0xc0010004);
+
+    /* Family 15h (bulldozer +) aliases these registers sparsely onto c001020x. */
+    if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
+    {
+        for (uint32_t i = 0; i < 4; i++)
+            printMsrAlias(uMsr + i, 0xc0010201 + i * 2, NULL);
+        *pidxLoop += 3;
+    }
+    else
+        return reportMsr_GenRangeFunction(paMsrs, cMsrs, 4, "AmdK8PerfCtrN", pidxLoop);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals carefully with the SYS_CFG register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdK8SysCfg(uint32_t uMsr, uint64_t uValue)
+{
+    uint64_t fSkipMask = 0;
+
+    /* Bit 21 (MtrrTom2En) is marked reserved in family 0fh, while in family
+       10h BKDG this changes (as does the document style).  Testing this bit
+       causes bulldozer running win64 to restart, thus this special treatment. */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K10)
+        fSkipMask |= RT_BIT(21);
+
+    /* Turns out there are more killer bits here, at least on Opteron 2384.
+       Skipping all known bits. */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_65nm /* Not sure when introduced - harmless? */)
+        fSkipMask |= RT_BIT(22); /* Tom2ForceMemTypeWB */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+        fSkipMask |= RT_BIT(21); /* MtrrTom2En */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+        fSkipMask |= RT_BIT(20); /* MtrrVarDramEn*/
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+        fSkipMask |= RT_BIT(19); /* MtrrFixDramModEn */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+        fSkipMask |= RT_BIT(18); /* MtrrFixDramEn */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+        fSkipMask |= RT_BIT(17); /* SysUcLockEn */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+        fSkipMask |= RT_BIT(16); /* ChgToDirtyDis */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First && g_enmMicroarch < kCpumMicroarch_AMD_15h_First)
+        fSkipMask |= RT_BIT(10); /* SetDirtyEnO */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First && g_enmMicroarch < kCpumMicroarch_AMD_15h_First)
+        fSkipMask |= RT_BIT(9);  /* SetDirtyEnS */
+    if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
+        || CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
+        fSkipMask |= RT_BIT(8);  /* SetDirtyEnE */
+    if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
+        || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
+        fSkipMask |= RT_BIT(7)   /* SysVicLimit */
+                  |  RT_BIT(6)   /* SysVicLimit */
+                  |  RT_BIT(5)   /* SysVicLimit */
+                  |  RT_BIT(4)   /* SysAckLimit */
+                  |  RT_BIT(3)   /* SysAckLimit */
+                  |  RT_BIT(2)   /* SysAckLimit */
+                  |  RT_BIT(1)   /* SysAckLimit */
+                  |  RT_BIT(0)   /* SysAckLimit */;
+
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals carefully with the HWCR register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdK8HwCr(uint32_t uMsr, uint64_t uValue)
+{
+    uint64_t fSkipMask = 0;
+
+    /* Trouble on Opteron 2384, skip some of the known bits. */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_K10 && !CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch))
+        fSkipMask |= /*RT_BIT(10)*/ 0  /* MonMwaitUserEn */
+                  |  RT_BIT(9);  /* MonMwaitDis */
+    fSkipMask |= RT_BIT(8);      /* #IGNNE port emulation */
+    if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
+        || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
+        fSkipMask |= RT_BIT(7)   /* DisLock */
+                  |  RT_BIT(6);  /* FFDis (TLB flush filter) */
+    fSkipMask |= RT_BIT(4);      /* INVD to WBINVD */
+    fSkipMask |= RT_BIT(3);      /* TLBCACHEDIS */
+    if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
+        || CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
+        || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
+        fSkipMask |= RT_BIT(1);  /* SLOWFENCE */
+    fSkipMask |= RT_BIT(0);      /* SMMLOCK */
+
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals carefully with a IORRBasei register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdK8IorrBaseN(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = RT_BIT(4) | RT_BIT(3);
+    fSkipMask |= (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & X86_PAGE_4K_BASE_MASK;
+    return reportMsr_GenFunctionEx(uMsr, NULL, (uMsr - 0xc0010016) / 2, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals carefully with a IORRMaski register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdK8IorrMaskN(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = RT_BIT(11);
+    fSkipMask |= (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & X86_PAGE_4K_BASE_MASK;
+    return reportMsr_GenFunctionEx(uMsr, NULL, (uMsr - 0xc0010017) / 2, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals carefully with a IORRMaski register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdK8TopMemN(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(RT_BIT_64(23) - 1);
+    return reportMsr_GenFunctionEx(uMsr, NULL, uMsr == 0xc001001d, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals with the AMD P-state config range.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MSR entry in the range.
+ */
+static int reportMsr_AmdFam10hPStateN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
+{
+    uint32_t uMsr = paMsrs[0].uMsr;
+    AssertRelease(uMsr == 0xc0010064);
+
+    /* Count them. */
+    uint32_t cRegs = 1;
+    while (   cRegs < 8
+           && cRegs < cMsrs
+           && paMsrs[cRegs].uMsr == uMsr + cRegs)
+        cRegs++;
+
+    /* Figure out which bits we should skip when probing.  This is based on
+       specs and may need adjusting for real life when handy. */
+    uint64_t fSkipMask = RT_BIT_64(63);             /* PstateEn */
+    fSkipMask |= RT_BIT_64(41) | RT_BIT_64(40);     /* IddDiv */
+    fSkipMask |= UINT64_C(0x000000ff00000000);      /* IddValue */
+    if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
+        fSkipMask |= UINT32_C(0xfe000000);          /* NbVid - Northbridge VID */
+    if (   CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
+        || CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
+        fSkipMask |= RT_BIT_32(22);                 /* NbDid or NbPstate. */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver) /* ?? - listed in 10-1Fh model BDKG as well asFam16h */
+        fSkipMask |= RT_BIT_32(16);                 /* CpuVid[7] */
+    fSkipMask |= UINT32_C(0x0000fe00);              /* CpuVid[6:0] */
+    fSkipMask |= UINT32_C(0x000001c0);              /* CpuDid */
+    fSkipMask |= UINT32_C(0x0000003f);              /* CpuFid */
+
+    /* Probe and report them one by one since we're passing values instead of
+       register indexes to the functions. */
+    for (uint32_t i = 0; i < cRegs; i++)
+    {
+        uint64_t fIgnMask = 0;
+        uint64_t fGpMask = 0;
+        int rc = msrProberModifyBitChanges(uMsr + i, &fIgnMask, &fGpMask, fSkipMask);
+        if (RT_FAILURE(rc))
+            return rc;
+        printMsrFunctionExtended(uMsr + i, "AmdFam10hPStateN", NULL, paMsrs[i].uValue, fIgnMask, fGpMask,
+                                 annotateValue(paMsrs[i].uValue));
+    }
+
+    /* Advance. */
+    *pidxLoop += cRegs - 1;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals carefully with a COFVID control register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdFam10hCofVidControl(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = 0;
+    if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
+        fSkipMask |= UINT32_C(0xfe000000);          /* NbVid - Northbridge VID */
+    else if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_First) /* Listed in preliminary Fam16h BDKG. */
+        fSkipMask |= UINT32_C(0xff000000);          /* NbVid - Northbridge VID - includes bit 24 for Fam15h and Fam16h. Odd... */
+    if (   CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
+        || g_enmMicroarch >= kCpumMicroarch_AMD_15h_First) /* Listed in preliminary Fam16h BDKG. */
+        fSkipMask |= RT_BIT_32(22);                 /* NbDid or NbPstate. */
+    if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver) /* ?? - listed in 10-1Fh model BDKG as well asFam16h */
+        fSkipMask |= RT_BIT_32(20);                 /* CpuVid[7] */
+    fSkipMask |= UINT32_C(0x00070000);              /* PstatId */
+    fSkipMask |= UINT32_C(0x0000fe00);              /* CpuVid[6:0] */
+    fSkipMask |= UINT32_C(0x000001c0);              /* CpuDid */
+    fSkipMask |= UINT32_C(0x0000003f);              /* CpuFid */
+
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals with the AMD [|L2I_|NB_]PERF_CT[LR] mixed ranges.
+ *
+ * Mixed here refers to the control and counter being in mixed in pairs as
+ * opposed to them being two separate parallel arrays like in the 0xc0010000
+ * area.
+ *
+ * @returns VBox status code.
+ * @param   paMsrs              Pointer to the first MSR.
+ * @param   cMsrs               The number of MSRs in the array @a paMsr.
+ * @param   cMax                The max number of MSRs (not counters).
+ * @param   pidxLoop            Index variable that should be advanced to the
+ *                              last MSR entry in the range.
+ */
+static int reportMsr_AmdGenPerfMixedRange(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, uint32_t *pidxLoop)
+{
+    uint32_t uMsr = paMsrs[0].uMsr;
+
+    /* Count them. */
+    uint32_t cRegs = 1;
+    while (   cRegs < cMax
+           && cRegs < cMsrs
+           && paMsrs[cRegs].uMsr == uMsr + cRegs)
+        cRegs++;
+    if (cRegs & 1)
+        return RTMsgErrorRc(VERR_INVALID_PARAMETER, "PERF range at %#x is odd: cRegs=%#x\n", uMsr, cRegs);
+
+    /* Report them as individual entries, using default names and such. */
+    for (uint32_t i = 0; i < cRegs; i++)
+    {
+        uint64_t fIgnMask = 0;
+        uint64_t fGpMask  = 0;
+        int rc = msrProberModifyBitChanges(uMsr + i, &fIgnMask, &fGpMask, 0);
+        if (RT_FAILURE(rc))
+            return rc;
+        printMsrFunctionExtendedIdxVal(uMsr + i, NULL, NULL, i / 2, fIgnMask, fGpMask, annotateValue(paMsrs[i].uValue));
+    }
+
+    /* Advance. */
+    *pidxLoop += cRegs - 1;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Deals carefully with a LS_CFG register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdK7InstrCacheCfg(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = RT_BIT_64(9) /* DIS_SPEC_TLB_RLD */;
+    if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
+        fSkipMask |= RT_BIT_64(14); /* DIS_IND */
+    if (CPUMMICROARCH_IS_AMD_FAM_16H(g_enmMicroarch))
+        fSkipMask |= RT_BIT_64(26); /* DIS_WIDEREAD_PWR_SAVE */
+    if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
+    {
+        fSkipMask |= 0x1e;          /* DisIcWayFilter */
+        fSkipMask |= RT_BIT_64(39); /* DisLoopPredictor */
+        fSkipMask |= RT_BIT_64(27); /* Unknown killer bit, possibly applicable to other microarchs. */
+        fSkipMask |= RT_BIT_64(28); /* Unknown killer bit, possibly applicable to other microarchs. */
+    }
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals carefully with a CU_CFG register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdFam15hCombUnitCfg(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = RT_BIT_64(23) /* L2WayLock  */
+                       | RT_BIT_64(22) /* L2FirstLockWay */
+                       | RT_BIT_64(21) /* L2FirstLockWay */
+                       | RT_BIT_64(20) /* L2FirstLockWay */
+                       | RT_BIT_64(19) /* L2FirstLockWay */
+                       | RT_BIT_64(10) /* DcacheAggressivePriority */;
+    fSkipMask |= RT_BIT_64(46) | RT_BIT_64(45); /* Killer field. Seen bit 46 set, 45 clear. Messing with either means reboot/BSOD. */
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+/**
+ * Deals carefully with a EX_CFG register.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR number.
+ * @param   uValue              The current value.
+ */
+static int reportMsr_AmdFam15hExecUnitCfg(uint32_t uMsr, uint64_t uValue)
+{
+    /* Skip know bits here, as harm seems to come from messing with them. */
+    uint64_t fSkipMask = RT_BIT_64(54) /* LateSbzResync  */;
+    fSkipMask |= RT_BIT_64(35); /* Undocumented killer bit. */
+    return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
+}
+
+
+
+static int produceMsrReport(VBCPUREPMSR *paMsrs, uint32_t cMsrs)
+{
+    vbCpuRepDebug("produceMsrReport\n");
+    RTThreadSleep(500);
+
+    for (uint32_t i = 0; i < cMsrs; i++)
+    {
+        uint32_t    uMsr       = paMsrs[i].uMsr;
+        uint32_t    fFlags     = paMsrs[i].fFlags;
+        uint64_t    uValue     = paMsrs[i].uValue;
+        int         rc;
+#if 0
+        if (uMsr < 0x00003170)
+            continue;
+        if (uMsr >= 0x00003170)
+        {
+            vbCpuRepDebug("produceMsrReport: uMsr=%#x (%s)...\n", uMsr, getMsrNameHandled(uMsr));
+            RTThreadSleep(1000);
+        }
+#endif
+        /*
+         * Deal with write only regs first to avoid having to avoid them all the time.
+         */
+        if (fFlags & VBCPUREPMSR_F_WRITE_ONLY)
+        {
+            if (uMsr == 0x00000079)
+                rc = printMsrWriteOnly(uMsr, NULL, NULL);
+            else
+                rc = reportMsr_Generic(uMsr, fFlags, uValue);
+        }
+        /*
+         * VIA implement MSRs in a interesting way, so we have to select what we
+         * want to handle there to avoid making the code below unreadable.
+         */
+        else if (isMsrViaDummy(uMsr, uValue, fFlags))
+            rc = reportMsr_ViaDummyRange(&paMsrs[i], cMsrs - i, &i);
+        /*
+         * This shall be sorted by uMsr as much as possible.
+         */
+        else if (uMsr == 0x00000000 && g_enmVendor == CPUMCPUVENDOR_AMD && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+            rc = printMsrAlias(uMsr, 0x00000402, NULL);
+        else if (uMsr == 0x00000001 && g_enmVendor == CPUMCPUVENDOR_AMD && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
+            rc = printMsrAlias(uMsr, 0x00000401, NULL); /** @todo not 101% correct on Fam15h and later, 0xc0010015[McstatusWrEn] effect differs. */
+        else if (uMsr == 0x0000001b)
+            rc = reportMsr_Ia32ApicBase(uMsr, uValue);
+        else if (uMsr == 0x00000040 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_M_Dothan)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchFromToN", &i);
+        else if (uMsr == 0x00000040)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchToN", uMsr, false,
+                                              true, getGenericSkipMask(uMsr), &i);
+        else if (uMsr == 0x00000060 && g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchFromN", uMsr, false,
+                                              true, getGenericSkipMask(uMsr), &i);
+        else if (uMsr == 0x000000c1)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i,
+                                            g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? 8 : 4 /*cMax*/,
+                                            NULL, &i);
+        else if (uMsr == 0x00000186 && !g_fIntelNetBurst)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "Ia32PerfEvtSelN", &i);
+        else if (uMsr == 0x000001a0)
+            rc = reportMsr_Ia32MiscEnable(uMsr, uValue);
+        else if (uMsr >= 0x000001a6 && uMsr <= 0x000001a7)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 2 /*cMax*/, "IntelI7MsrOffCoreResponseN", &i);
+        else if (uMsr == 0x000001db && g_fIntelNetBurst)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 4 /*cMax*/, "IntelLastBranchFromToN", &i);
+        else if (uMsr == 0x00000200)
+            rc = reportMsr_Ia32MtrrPhysBaseMaskN(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr >= 0x00000250 && uMsr <= 0x00000279)
+            rc = reportMsr_Ia32MtrrFixedOrPat(uMsr);
+        else if (uMsr >= 0x00000280 && uMsr <= 0x00000295)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 22 /*cMax*/, NULL, 0x00000280, true /*fEarlyEndOk*/, false, 0, &i);
+        else if (uMsr == 0x000002ff)
+            rc = reportMsr_Ia32MtrrDefType(uMsr);
+        else if (uMsr >= 0x00000309 && uMsr <= 0x0000030b && !g_fIntelNetBurst)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 3 /*cMax*/, NULL, 0x00000309, true /*fEarlyEndOk*/, false, 0, &i);
+        else if ((uMsr == 0x000003f8 || uMsr == 0x000003fc || uMsr == 0x0000060a) && !g_fIntelNetBurst)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 4, NULL, uMsr - 3, true, false, 0, &i);
+        else if ((uMsr == 0x000003f9 || uMsr == 0x000003fd || uMsr == 0x0000060b) && !g_fIntelNetBurst)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8, NULL, uMsr - 6, true, false, 0, &i);
+        else if ((uMsr == 0x000003fa || uMsr == 0x000003fe || uMsr == 0x0000060c) && !g_fIntelNetBurst)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8, NULL, uMsr - 7, true, false, 0, &i);
+        else if (uMsr >= 0x00000400 && uMsr <= 0x00000477)
+            rc = reportMsr_Ia32McCtlStatusAddrMiscN(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr == 0x000004c1)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8, NULL, &i);
+        else if (uMsr == 0x00000680 || uMsr == 0x000006c0)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 16, NULL, uMsr, false, false,
+                                              g_fIntelNetBurst
+                                              ? UINT64_C(0xffffffffffffff00) /* kludge */
+                                              : UINT64_C(0xffff800000000000), &i);
+        else if (uMsr >= 0x00000800 && uMsr <= 0x000008ff)
+            rc = reportMsr_GenX2Apic(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr == 0x00002000 && g_enmVendor == CPUMCPUVENDOR_INTEL)
+            rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 0, X86_CR0_PE | X86_CR0_PG, 0,
+                                         annotateIfMissingBits(uValue, X86_CR0_PE | X86_CR0_PE | X86_CR0_ET));
+        else if (uMsr == 0x00002002 && g_enmVendor == CPUMCPUVENDOR_INTEL)
+            rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 2, 0, 0, annotateValue(uValue));
+        else if (uMsr == 0x00002003 && g_enmVendor == CPUMCPUVENDOR_INTEL)
+        {
+            uint64_t fCr3Mask = (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & (X86_CR3_PAE_PAGE_MASK | X86_CR3_AMD64_PAGE_MASK);
+            if (!vbCpuRepSupportsPae())
+                fCr3Mask &= X86_CR3_PAGE_MASK | X86_CR3_AMD64_PAGE_MASK;
+            rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 3, fCr3Mask, 0, annotateValue(uValue));
+        }
+        else if (uMsr == 0x00002004 && g_enmVendor == CPUMCPUVENDOR_INTEL)
+            rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 4,
+                                         X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE | X86_CR4_SMXE, 0,
+                                         annotateValue(uValue));
+        else if (uMsr == 0xc0000080)
+            rc = reportMsr_Amd64Efer(uMsr, uValue);
+        else if (uMsr == 0xc0000082 || uMsr == 0xc0000083 || uMsr == 0xc0000100 || uMsr == 0xc0000101 || uMsr == 0xc0000102)
+            rc = reportMsr_GenFunctionEx(uMsr, NULL, 0, UINT64_C(0xffff800000000000), 0, annotateValue(uValue)); /* Canoncial address hack. */
+        else if (uMsr >= 0xc0000408 && uMsr <= 0xc000040f)
+            rc = reportMsr_AmdFam10hMc4MiscN(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr == 0xc0010000 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8PerfCtlN(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr == 0xc0010004 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8PerfCtrN(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr == 0xc0010010 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8SysCfg(uMsr, uValue);
+        else if (uMsr == 0xc0010015 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8HwCr(uMsr, uValue);
+        else if ((uMsr == 0xc0010016 || uMsr == 0xc0010018) && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8IorrBaseN(uMsr, uValue);
+        else if ((uMsr == 0xc0010017 || uMsr == 0xc0010019) && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8IorrMaskN(uMsr, uValue);
+        else if ((uMsr == 0xc001001a || uMsr == 0xc001001d) && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK8TopMemN(uMsr, uValue);
+        else if (uMsr == 0xc0010030 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 6, "AmdK8CpuNameN", &i);
+        else if (uMsr >= 0xc0010044 && uMsr <= 0xc001004a && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 7, "AmdK8McCtlMaskN", 0xc0010044, true /*fEarlyEndOk*/, false, 0, &i);
+        else if (uMsr == 0xc0010050 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 4, "AmdK8SmiOnIoTrapN", &i);
+        else if (uMsr == 0xc0010064 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdFam10hPStateN(&paMsrs[i], cMsrs - i, &i);
+        else if (uMsr == 0xc0010070 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdFam10hCofVidControl(uMsr, uValue);
+        else if ((uMsr == 0xc0010118 || uMsr == 0xc0010119) && getMsrFnName(uMsr, NULL) && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = printMsrFunction(uMsr, NULL, NULL, annotateValue(uValue)); /* RAZ, write key. */
+        else if (uMsr == 0xc0010200 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 12, &i);
+        else if (uMsr == 0xc0010230 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 8, &i);
+        else if (uMsr == 0xc0010240 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 8, &i);
+        else if (uMsr == 0xc0011019 && g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 3, "AmdK7DrXAddrMaskN", 0xc0011019 - 1,
+                                              false /*fEarlyEndOk*/, false /*fNoIgnMask*/, 0, &i);
+        else if (uMsr == 0xc0011021 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_AmdK7InstrCacheCfg(uMsr, uValue);
+        else if (uMsr == 0xc0011023 && CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
+            rc = reportMsr_AmdFam15hCombUnitCfg(uMsr, uValue);
+        else if (uMsr == 0xc0011027 && g_enmVendor == CPUMCPUVENDOR_AMD)
+            rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 1, "AmdK7DrXAddrMaskN", 0xc0011027,
+                                              false /*fEarlyEndOk*/, false /*fNoIgnMask*/, 0, &i);
+        else if (uMsr == 0xc001102c && CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
+            rc = reportMsr_AmdFam15hExecUnitCfg(uMsr, uValue);
+        /* generic handling. */
+        else
+            rc = reportMsr_Generic(uMsr, fFlags, uValue);
+
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Custom MSR hacking & probing.
+ *
+ * Called when the '-d' option is given.
+ *
+ * @returns VBox status code.
+ */
+static int hackingMsrs(void)
+{
+#if 0
+    vbCpuRepDebug("\nhackingMsrs:\n"); RTStrmFlush(g_pDebugOut); RTThreadSleep(2000);
+
+    uint32_t uMsr = 0xc0000081;
+    vbCpuRepDebug("%#x: msrProberModifyNoChange -> %RTbool\n", uMsr, msrProberModifyNoChange(uMsr));
+    RTThreadSleep(3000);
+
+    vbCpuRepDebug("%#x: msrProberModifyBit 30 -> %d\n", uMsr, msrProberModifyBit(uMsr, 30));
+    RTThreadSleep(3000);
+
+    vbCpuRepDebug("%#x: msrProberModifyZero -> %RTbool\n", uMsr, msrProberModifyZero(uMsr));
+    RTThreadSleep(3000);
+
+    for (uint32_t i = 0; i < 63; i++)
+    {
+        vbCpuRepDebug("%#x: bit=%02u -> %d\n", msrProberModifyBit(uMsr, i));
+        RTThreadSleep(500);
+    }
+#else
+
+    uint32_t uMsr = 0xc0000080;
+    uint64_t uValue = 0;
+    msrProberRead(uMsr, &uValue);
+    /* Try for a triple fault... */
+    msrProberWrite(uMsr, uValue ^ MSR_K6_EFER_LME);
+    msrProberRead(uMsr, &uValue);
+    msrProberWrite(uMsr, uValue ^ MSR_K6_EFER_NXE);
+#endif
+    return VINF_SUCCESS;
+}
+
+
+static int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc,
+                     char *pszMsrMask, size_t cbMsrMask)
+{
+    /* Initialize the mask. */
+    if (pszMsrMask && cbMsrMask)
+        RTStrCopy(pszMsrMask, cbMsrMask, "UINT32_MAX /** @todo */");
+
+    /*
+     * Are MSRs supported by the CPU?
+     */
+    if (   !ASMIsValidStdRange(ASMCpuId_EAX(0))
+        || !(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_MSR) )
+    {
+        vbCpuRepDebug("Skipping MSR probing, CPUID indicates there isn't any MSR support.\n");
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Initialize the support library and check if we can read MSRs.
+     */
+    int rc = SUPR3Init(NULL);
+    if (RT_FAILURE(rc))
+    {
+        vbCpuRepDebug("warning: Unable to initialize the support library (%Rrc), skipping MSR detection.\n", rc);
+        return VINF_SUCCESS;
+    }
+    uint64_t uValue;
+    bool     fGp;
+    rc = SUPR3MsrProberRead(MSR_IA32_TSC, NIL_RTCPUID, &uValue, &fGp);
+    if (RT_FAILURE(rc))
+    {
+        vbCpuRepDebug("warning: MSR probing not supported by the support driver (%Rrc), skipping MSR detection.\n", rc);
+        return VINF_SUCCESS;
+    }
+    vbCpuRepDebug("MSR_IA32_TSC: %#llx fGp=%RTbool\n", uValue, fGp);
+    rc = SUPR3MsrProberRead(0xdeadface, NIL_RTCPUID, &uValue, &fGp);
+    vbCpuRepDebug("0xdeadface: %#llx fGp=%RTbool rc=%Rrc\n", uValue, fGp, rc);
+
+    /*
+     * Initialize globals we use.
+     */
+    uint32_t uEax, uEbx, uEcx, uEdx;
+    ASMCpuIdExSlow(0, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+    if (!ASMIsValidStdRange(uEax))
+        return RTMsgErrorRc(VERR_NOT_SUPPORTED, "Invalid std CPUID range: %#x\n", uEax);
+    g_enmVendor = CPUMR3CpuIdDetectVendorEx(uEax, uEbx, uEcx, uEdx);
+
+    ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+    g_enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(g_enmVendor,
+                                                     ASMGetCpuFamily(uEax),
+                                                     ASMGetCpuModel(uEax, g_enmVendor == CPUMCPUVENDOR_INTEL),
+                                                     ASMGetCpuStepping(uEax));
+    g_fIntelNetBurst = CPUMMICROARCH_IS_INTEL_NETBURST(g_enmMicroarch);
+
+    /*
+     * Do the probing.
+     */
+    if (fHacking)
+        rc = hackingMsrs();
+    else
+    {
+        /* Determine the MSR mask. */
+        uint32_t fMsrMask = determineMsrAndMask();
+        if (fMsrMask == UINT32_MAX)
+            RTStrCopy(pszMsrMask, cbMsrMask, "UINT32_MAX");
+        else
+            RTStrPrintf(pszMsrMask, cbMsrMask, "UINT32_C(%#x)", fMsrMask);
+
+        /* Detect MSR. */
+        VBCPUREPMSR    *paMsrs;
+        uint32_t        cMsrs;
+        rc = findMsrs(&paMsrs, &cMsrs, fMsrMask);
+        if (RT_FAILURE(rc))
+            return rc;
+
+        /* Probe the MSRs and spit out the database table. */
+        vbCpuRepPrintf("\n"
+                       "#ifndef CPUM_DB_STANDALONE\n"
+                       "/**\n"
+                       " * MSR ranges for %s.\n"
+                       " */\n"
+                       "static CPUMMSRRANGE const g_aMsrRanges_%s[] = \n{\n",
+                       pszCpuDesc,
+                       pszNameC);
+        rc = produceMsrReport(paMsrs, cMsrs);
+        vbCpuRepPrintf("};\n"
+                       "#endif /* !CPUM_DB_STANDALONE */\n"
+                       "\n"
+                       );
+
+        RTMemFree(paMsrs);
+        paMsrs = NULL;
+    }
+    return rc;
+}
+
+
+static int produceCpuIdArray(const char *pszNameC, const char *pszCpuDesc)
+{
+    /*
+     * Collect the data.
+     */
+    PCPUMCPUIDLEAF  paLeaves;
+    uint32_t        cLeaves;
+    int rc = CPUMR3CpuIdCollectLeaves(&paLeaves, &cLeaves);
+    if (RT_FAILURE(rc))
+        return RTMsgErrorRc(rc, "CPUMR3CollectCpuIdInfo failed: %Rrc\n", rc);
+
+    /*
+     * Dump the array.
+     */
+    vbCpuRepPrintf("\n"
+                   "#ifndef CPUM_DB_STANDALONE\n"
+                   "/**\n"
+                   " * CPUID leaves for %s.\n"
+                   " */\n"
+                   "static CPUMCPUIDLEAF const g_aCpuIdLeaves_%s[] = \n{\n",
+                   pszCpuDesc,
+                   pszNameC);
+    for (uint32_t i = 0; i < cLeaves; i++)
+    {
+        vbCpuRepPrintf("    { %#010x, %#010x, ", paLeaves[i].uLeaf, paLeaves[i].uSubLeaf);
+        if (paLeaves[i].fSubLeafMask == UINT32_MAX)
+            vbCpuRepPrintf("UINT32_MAX, ");
+        else
+            vbCpuRepPrintf("%#010x, ", paLeaves[i].fSubLeafMask);
+        vbCpuRepPrintf("%#010x, %#010x, %#010x, %#010x, ",
+                     paLeaves[i].uEax, paLeaves[i].uEbx, paLeaves[i].uEcx, paLeaves[i].uEdx);
+        if (paLeaves[i].fFlags == 0)
+            vbCpuRepPrintf("0 },\n");
+        else
+        {
+            vbCpuRepPrintf("0");
+            uint32_t fFlags = paLeaves[i].fFlags;
+            if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED)
+            {
+                vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED");
+                fFlags &= ~CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED;
+            }
+            if (fFlags)
+            {
+                RTMemFree(paLeaves);
+                return RTMsgErrorRc(rc, "Unknown CPUID flags %#x\n", fFlags);
+            }
+            vbCpuRepPrintf(" },\n");
+        }
+    }
+    vbCpuRepPrintf("};\n"
+                   "#endif /* !CPUM_DB_STANDALONE */\n"
+                   "\n");
+    RTMemFree(paLeaves);
+    return VINF_SUCCESS;
+}
+
+
+static const char *cpuVendorToString(CPUMCPUVENDOR enmCpuVendor)
+{
+    switch (enmCpuVendor)
+    {
+        case CPUMCPUVENDOR_INTEL:       return "Intel";
+        case CPUMCPUVENDOR_AMD:         return "AMD";
+        case CPUMCPUVENDOR_VIA:         return "VIA";
+        case CPUMCPUVENDOR_CYRIX:       return "Cyrix";
+        case CPUMCPUVENDOR_INVALID:
+        case CPUMCPUVENDOR_UNKNOWN:
+        case CPUMCPUVENDOR_32BIT_HACK:
+            break;
+    }
+    return "invalid-cpu-vendor";
+}
+
+
+static int produceCpuReport(void)
+{
+    /*
+     * Figure the cpu vendor.
+     */
+    if (!ASMHasCpuId())
+        return RTMsgErrorRc(VERR_NOT_SUPPORTED, "No CPUID support.\n");
+    uint32_t uEax, uEbx, uEcx, uEdx;
+    ASMCpuIdExSlow(0, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+    if (!ASMIsValidStdRange(uEax))
+        return RTMsgErrorRc(VERR_NOT_SUPPORTED, "Invalid std CPUID range: %#x\n", uEax);
+
+    CPUMCPUVENDOR enmVendor = CPUMR3CpuIdDetectVendorEx(uEax, uEbx, uEcx, uEdx);
+    if (enmVendor == CPUMCPUVENDOR_UNKNOWN)
+        return RTMsgErrorRc(VERR_NOT_IMPLEMENTED, "Unknown CPU vendor: %.4s%.4s%.4s\n", &uEbx, &uEdx, &uEcx);
+    vbCpuRepDebug("CPU Vendor: %s - %.4s%.4s%.4s\n", CPUMR3CpuVendorName(enmVendor), &uEbx, &uEdx, &uEcx);
+
+    /*
+     * Determine the micro arch.
+     */
+    ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+    CPUMMICROARCH enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(enmVendor,
+                                                                 ASMGetCpuFamily(uEax),
+                                                                 ASMGetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
+                                                                 ASMGetCpuStepping(uEax));
+
+    /*
+     * Generate a name.
+     */
+    char  szName[16*3+1];
+    char  szNameC[16*3+1];
+    char  szNameRaw[16*3+1];
+    char *pszName    = szName;
+    char *pszCpuDesc = (char *)"";
+
+    ASMCpuIdExSlow(0x80000000, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+    if (ASMIsValidExtRange(uEax) && uEax >= UINT32_C(0x80000004))
+    {
+        /* Get the raw name and strip leading spaces. */
+        ASMCpuIdExSlow(0x80000002, 0, 0, 0, &szNameRaw[0 +  0], &szNameRaw[4 +  0], &szNameRaw[8 +  0], &szNameRaw[12 +  0]);
+        ASMCpuIdExSlow(0x80000003, 0, 0, 0, &szNameRaw[0 + 16], &szNameRaw[4 + 16], &szNameRaw[8 + 16], &szNameRaw[12 + 16]);
+        ASMCpuIdExSlow(0x80000004, 0, 0, 0, &szNameRaw[0 + 32], &szNameRaw[4 + 32], &szNameRaw[8 + 32], &szNameRaw[12 + 32]);
+        szNameRaw[48] = '\0';
+        pszCpuDesc = RTStrStrip(szNameRaw);
+        vbCpuRepDebug("Name2: %s\n", pszCpuDesc);
+
+        /* Reduce the name. */
+        pszName = strcpy(szName, pszCpuDesc);
+
+        static const char * const s_apszSuffixes[] =
+        {
+            "CPU @",
+        };
+        for (uint32_t i = 0; i < RT_ELEMENTS(s_apszSuffixes); i++)
+        {
+            char *pszHit = strstr(pszName, s_apszSuffixes[i]);
+            if (pszHit)
+                RT_BZERO(pszHit, strlen(pszHit));
+        }
+
+        static const char * const s_apszWords[] =
+        {
+            "(TM)", "(tm)", "(R)", "(r)", "Processor", "CPU", "@",
+        };
+        for (uint32_t i = 0; i < RT_ELEMENTS(s_apszWords); i++)
+        {
+            const char *pszWord = s_apszWords[i];
+            size_t      cchWord = strlen(pszWord);
+            char       *pszHit;
+            while ((pszHit = strstr(pszName, pszWord)) != NULL)
+                memmove(pszHit, pszHit + cchWord, strlen(pszHit + cchWord) + 1);
+        }
+
+        RTStrStripR(pszName);
+        for (char *psz = pszName; *psz; psz++)
+            if (RT_C_IS_BLANK(*psz))
+            {
+                size_t cchBlanks = 1;
+                while (RT_C_IS_BLANK(psz[cchBlanks]))
+                    cchBlanks++;
+                *psz = ' ';
+                if (cchBlanks > 1)
+                    memmove(psz + 1, psz + cchBlanks, strlen(psz + cchBlanks) + 1);
+            }
+        pszName = RTStrStripL(pszName);
+        vbCpuRepDebug("Name: %s\n", pszName);
+
+        /* Make it C/C++ acceptable. */
+        strcpy(szNameC, pszName);
+        unsigned offDst = 0;
+        for (unsigned offSrc = 0; ; offSrc++)
+        {
+            char ch = szNameC[offSrc];
+            if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != '\0')
+                ch = '_';
+            if (ch == '_' && offDst > 0 && szNameC[offDst - 1] == '_')
+                offDst--;
+            szNameC[offDst++] = ch;
+            if (!ch)
+                break;
+        }
+        while (offDst > 1 && szNameC[offDst - 1] == '_')
+            szNameC[--offDst] = '\0';
+
+        vbCpuRepDebug("NameC: %s\n", szNameC);
+    }
+    else
+    {
+        ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+        RTStrPrintf(szNameC, sizeof(szNameC), "%s_%u_%u_%u", cpuVendorToString(enmVendor), ASMGetCpuFamily(uEax),
+                    ASMGetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL), ASMGetCpuStepping(uEax));
+        pszCpuDesc = pszName = szNameC;
+        vbCpuRepDebug("Name/NameC: %s\n", szNameC);
+    }
+
+    /*
+     * Print a file header, if we're not outputting to stdout (assumption being
+     * that stdout is used while hacking the reporter and too much output is
+     * unwanted).
+     */
+    if (g_pReportOut)
+    {
+        RTTIMESPEC Now;
+        char       szNow[64];
+        RTTimeSpecToString(RTTimeNow(&Now), szNow, sizeof(szNow));
+        char *pchDot = strchr(szNow, '.');
+        if (pchDot)
+            strcpy(pchDot, "Z");
+
+        vbCpuRepPrintf("/* $" "Id" "$ */\n"
+                       "/** @file\n"
+                       " * CPU database entry \"%s\".\n"
+                       " * Generated at %s by VBoxCpuReport v%sr%s on %s.%s.\n"
+                       " */\n"
+                       "\n"
+                       "/*\n"
+                       " * Copyright (C) 2013 Oracle Corporation\n"
+                       " *\n"
+                       " * This file is part of VirtualBox Open Source Edition (OSE), as\n"
+                       " * available from http://www.virtualbox.org. This file is free software;\n"
+                       " * you can redistribute it and/or modify it under the terms of the GNU\n"
+                       " * General Public License (GPL) as published by the Free Software\n"
+                       " * Foundation, in version 2 as it comes in the \"COPYING\" file of the\n"
+                       " * VirtualBox OSE distribution. VirtualBox OSE is distributed in the\n"
+                       " * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.\n"
+                       " */\n"
+                       "\n"
+                       "#ifndef VBOX_CPUDB_%s\n"
+                       "#define VBOX_CPUDB_%s\n"
+                       "\n",
+                       pszName,
+                       szNow, RTBldCfgVersion(), RTBldCfgRevisionStr(), RTBldCfgTarget(), RTBldCfgTargetArch(),
+                       szNameC, szNameC);
+    }
+
+    /*
+     * Extract CPUID based data.
+     */
+    int rc = produceCpuIdArray(szNameC, pszCpuDesc);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    CPUMUKNOWNCPUID enmUnknownMethod;
+    CPUMCPUID       DefUnknown;
+    rc = CPUMR3CpuIdDetectUnknownLeafMethod(&enmUnknownMethod, &DefUnknown);
+    if (RT_FAILURE(rc))
+        return RTMsgErrorRc(rc, "CPUMR3DetectCpuIdUnknownMethod failed: %Rrc\n", rc);
+    vbCpuRepDebug("enmUnknownMethod=%s\n", CPUMR3CpuIdUnknownLeafMethodName(enmUnknownMethod));
+
+    /*
+     * Do the MSRs, if we can.
+     */
+    char szMsrMask[64];
+    probeMsrs(false /*fHacking*/, szNameC, pszCpuDesc, szMsrMask, sizeof(szMsrMask));
+
+    /*
+     * Emit the CPUMDBENTRY record.
+     */
+    ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
+    vbCpuRepPrintf("\n"
+                   "/**\n"
+                   " * Database entry for %s.\n"
+                   " */\n"
+                   "static CPUMDBENTRY const g_Entry_%s = \n"
+                   "{\n"
+                   "    /*.pszName          = */ \"%s\",\n"
+                   "    /*.pszFullName      = */ \"%s\",\n"
+                   "    /*.enmVendor        = */ CPUMCPUVENDOR_%s,\n"
+                   "    /*.uFamily          = */ %u,\n"
+                   "    /*.uModel           = */ %u,\n"
+                   "    /*.uStepping        = */ %u,\n"
+                   "    /*.enmMicroarch     = */ kCpumMicroarch_%s,\n"
+                   "    /*.fFlags           = */ 0,\n"
+                   "    /*.cMaxPhysAddrWidth= */ %u,\n"
+                   "    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_%s),\n"
+                   "    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_%s)),\n"
+                   "    /*.enmUnknownCpuId  = */ CPUMUKNOWNCPUID_%s,\n"
+                   "    /*.DefUnknownCpuId  = */ { %#010x, %#010x, %#010x, %#010x },\n"
+                   "    /*.fMsrMask         = */ %s,\n"
+                   "    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_%s)),\n"
+                   "    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_%s),\n"
+                   "};\n"
+                   "\n"
+                   "#endif /* !VBOX_DB_%s */\n"
+                   "\n",
+                   pszCpuDesc,
+                   szNameC,
+                   pszName,
+                   pszCpuDesc,
+                   CPUMR3CpuVendorName(enmVendor),
+                   ASMGetCpuFamily(uEax),
+                   ASMGetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
+                   ASMGetCpuStepping(uEax),
+                   CPUMR3MicroarchName(enmMicroarch),
+                   vbCpuRepGetPhysAddrWidth(),
+                   szNameC,
+                   szNameC,
+                   CPUMR3CpuIdUnknownLeafMethodName(enmUnknownMethod),
+                   DefUnknown.eax,
+                   DefUnknown.ebx,
+                   DefUnknown.ecx,
+                   DefUnknown.edx,
+                   szMsrMask,
+                   szNameC,
+                   szNameC,
+                   szNameC
+                   );
+
+    return VINF_SUCCESS;
+}
+
+
+int main(int argc, char **argv)
+{
+    int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
+    if (RT_FAILURE(rc))
+        return RTMsgInitFailure(rc);
+
+    /*
+     * Argument parsing?
+     */
+    static const RTGETOPTDEF s_aOptions[] =
+    {
+        { "--msrs-only", 'm', RTGETOPT_REQ_NOTHING },
+        { "--msrs-dev",  'd', RTGETOPT_REQ_NOTHING },
+        { "--output",    'o', RTGETOPT_REQ_STRING  },
+        { "--log",       'l', RTGETOPT_REQ_STRING  },
+    };
+    RTGETOPTSTATE State;
+    RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
+
+    enum
+    {
+        kCpuReportOp_Normal,
+        kCpuReportOp_MsrsOnly,
+        kCpuReportOp_MsrsHacking
+    } enmOp = kCpuReportOp_Normal;
+    g_pReportOut = NULL;
+    g_pDebugOut  = NULL;
+    const char *pszOutput   = NULL;
+    const char *pszDebugOut = NULL;
+
+    int iOpt;
+    RTGETOPTUNION ValueUnion;
+    while ((iOpt = RTGetOpt(&State, &ValueUnion)) != 0)
+    {
+        switch (iOpt)
+        {
+            case 'm':
+                enmOp = kCpuReportOp_MsrsOnly;
+                break;
+
+            case 'd':
+                enmOp = kCpuReportOp_MsrsHacking;
+                break;
+
+            case 'o':
+                pszOutput = ValueUnion.psz;
+                break;
+
+            case 'l':
+                pszDebugOut = ValueUnion.psz;
+                break;
+
+            case 'h':
+                RTPrintf("Usage: VBoxCpuReport [-m|--msrs-only] [-d|--msrs-dev] [-h|--help] [-V|--version] [-o filename.h] [-l debug.log]\n");
+                RTPrintf("Internal tool for gathering information to the VMM CPU database.\n");
+                return RTEXITCODE_SUCCESS;
+            case 'V':
+                RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
+                return RTEXITCODE_SUCCESS;
+            default:
+                return RTGetOptPrintError(iOpt, &ValueUnion);
+        }
+    }
+
+    /*
+     * Open the alternative debug log stream.
+     */
+    if (pszDebugOut)
+    {
+        if (RTFileExists(pszDebugOut) && !RTSymlinkExists(pszDebugOut))
+        {
+            char szOld[RTPATH_MAX];
+            rc = RTStrCopy(szOld, sizeof(szOld), pszDebugOut);
+            if (RT_SUCCESS(rc))
+                rc = RTStrCat(szOld, sizeof(szOld), ".old");
+            if (RT_SUCCESS(rc))
+                RTFileRename(pszDebugOut, szOld, RTFILEMOVE_FLAGS_REPLACE);
+        }
+        rc = RTStrmOpen(pszDebugOut, "w", &g_pDebugOut);
+        if (RT_FAILURE(rc))
+        {
+            RTMsgError("Error opening '%s': %Rrc", pszDebugOut, rc);
+            g_pDebugOut = NULL;
+        }
+    }
+
+    /*
+     * Do the requested job.
+     */
+    rc = VERR_INTERNAL_ERROR;
+    switch (enmOp)
+    {
+        case kCpuReportOp_Normal:
+            /* switch output file. */
+            if (pszOutput)
+            {
+                if (RTFileExists(pszOutput) && !RTSymlinkExists(pszOutput))
+                {
+                    char szOld[RTPATH_MAX];
+                    rc = RTStrCopy(szOld, sizeof(szOld), pszOutput);
+                    if (RT_SUCCESS(rc))
+                        rc = RTStrCat(szOld, sizeof(szOld), ".old");
+                    if (RT_SUCCESS(rc))
+                        RTFileRename(pszOutput, szOld, RTFILEMOVE_FLAGS_REPLACE);
+                }
+                rc = RTStrmOpen(pszOutput, "w", &g_pReportOut);
+                if (RT_FAILURE(rc))
+                {
+                    RTMsgError("Error opening '%s': %Rrc", pszOutput, rc);
+                    break;
+                }
+            }
+            rc = produceCpuReport();
+            break;
+        case kCpuReportOp_MsrsOnly:
+        case kCpuReportOp_MsrsHacking:
+            rc = probeMsrs(enmOp == kCpuReportOp_MsrsHacking, NULL, NULL, NULL, 0);
+            break;
+    }
+
+    /*
+     * Close the output files.
+     */
+    if (g_pReportOut)
+    {
+        RTStrmClose(g_pReportOut);
+        g_pReportOut = NULL;
+    }
+
+    if (g_pDebugOut)
+    {
+        RTStrmClose(g_pDebugOut);
+        g_pDebugOut = NULL;
+    }
+
+    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
+}
+
diff --git a/src/VBox/VMM/Preload/VBoxVMMPreload.cpp b/src/VBox/VMM/tools/VBoxVMMPreload.cpp
similarity index 100%
rename from src/VBox/VMM/Preload/VBoxVMMPreload.cpp
rename to src/VBox/VMM/tools/VBoxVMMPreload.cpp
diff --git a/src/VBox/VMM/Preload/VBoxVMMPreloadHardened.cpp b/src/VBox/VMM/tools/VBoxVMMPreloadHardened.cpp
similarity index 100%
rename from src/VBox/VMM/Preload/VBoxVMMPreloadHardened.cpp
rename to src/VBox/VMM/tools/VBoxVMMPreloadHardened.cpp
diff --git a/src/apps/adpctl/VBoxNetAdpCtl.cpp b/src/apps/adpctl/VBoxNetAdpCtl.cpp
index b3c3969..2e46d36 100644
--- a/src/apps/adpctl/VBoxNetAdpCtl.cpp
+++ b/src/apps/adpctl/VBoxNetAdpCtl.cpp
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include <sys/wait.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <fcntl.h>
 #ifdef RT_OS_LINUX
 # include <net/if.h>
@@ -61,8 +62,9 @@ typedef struct VBoxNetAdpReq
 } VBOXNETADPREQ;
 typedef VBOXNETADPREQ *PVBOXNETADPREQ;
 
-
-#define VBOXADPCTL_IFCONFIG_PATH "/sbin/ifconfig"
+#define VBOXADPCTL_IFCONFIG_PATH1 "/sbin/ifconfig"
+#define VBOXADPCTL_IFCONFIG_PATH2 "/bin/ifconfig"
+static char *g_pszIfConfig;
 
 #if defined(RT_OS_LINUX)
 # define VBOXADPCTL_DEL_CMD "del"
@@ -82,6 +84,16 @@ static void showUsage(void)
     fprintf(stderr, "     | VBoxNetAdpCtl <adapter> remove\n");
 }
 
+static void setPathIfConfig(void)
+{
+    struct stat s;
+    if (   !stat(VBOXADPCTL_IFCONFIG_PATH1, &s)
+        && S_ISREG(s.st_mode))
+        g_pszIfConfig = (char*)VBOXADPCTL_IFCONFIG_PATH1;
+    else
+        g_pszIfConfig = (char*)VBOXADPCTL_IFCONFIG_PATH2;
+}
+
 static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
                            const char *pcszArg2 = NULL,
                            const char *pcszArg3 = NULL,
@@ -90,7 +102,7 @@ static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
 {
     const char * const argv[] =
     {
-        VBOXADPCTL_IFCONFIG_PATH,
+        g_pszIfConfig,
         pcszAdapterName,
         pcszArg1, /* [address family] */
         pcszArg2, /* address */
@@ -109,7 +121,7 @@ static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
             rc = EXIT_FAILURE;
             break;
         case 0: /* Child process. */
-            if (execve(VBOXADPCTL_IFCONFIG_PATH, (char * const*)argv, envp) == -1)
+            if (execve(argv[0], (char * const*)argv, envp) == -1)
                 rc = EXIT_FAILURE;
             break;
         default: /* Parent process. */
@@ -129,7 +141,7 @@ static bool removeAddresses(char *pszAdapterName)
     char aszAddresses[MAX_ADDRESSES][MAX_ADDRLEN];
     int rc;
     int fds[2];
-    char * const argv[] = { (char*)VBOXADPCTL_IFCONFIG_PATH, pszAdapterName, NULL };
+    char * const argv[] = { g_pszIfConfig, pszAdapterName, NULL };
     char * const envp[] = { (char*)"LC_ALL=C", NULL };
 
     memset(aszAddresses, 0, sizeof(aszAddresses));
@@ -149,7 +161,7 @@ static bool removeAddresses(char *pszAdapterName)
         close(STDOUT_FILENO);
         rc = dup2(fds[1], STDOUT_FILENO);
         if (rc >= 0)
-            execve(VBOXADPCTL_IFCONFIG_PATH, argv, envp);
+            execve(argv[0], argv, envp);
         return false;
     }
 
@@ -250,6 +262,8 @@ int main(int argc, char *argv[])
     bool fRemove = false;
     VBOXNETADPREQ Req;
 
+    setPathIfConfig();
+
     switch (argc)
     {
         case 5:
diff --git a/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp b/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp
index 9905a15..19436f1 100644
--- a/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp
+++ b/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp
@@ -1006,7 +1006,7 @@ FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
                                                      aVariant.val.u8;
         if (aParamInfo.IsRetval() && !aIsArrayElement) {
           *aParam = env->NewObject(shortClass, shortInitMID, value);
-        } else if ((aParamInfo.IsOut() || aIsArrayElement) && aParam) {
+        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
           env->SetShortArrayRegion((jshortArray) *aParam, aIndex, 1, &value);
         }
       }
@@ -1753,8 +1753,9 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
     }
 
     jobject* javaElement;
+    jobject element = nsnull;
     if (!paramInfo.IsRetval()) {
-      jobject element = env->GetObjectArrayElement(aParams, i);
+      element = env->GetObjectArrayElement(aParams, i);
       javaElement = &element;
     } else {
       javaElement = &result;

-- 
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