Index: /trunk/include/VBox/vmm/hm_vmx.h
===================================================================
--- /trunk/include/VBox/vmm/hm_vmx.h	(revision 74692)
+++ /trunk/include/VBox/vmm/hm_vmx.h	(revision 74693)
@@ -2504,4 +2504,6 @@
 #define VMXINSTRID_IO_OUT                                       (0x16 | VMXINSTRID_VALID)
 #define VMXINSTRID_IO_OUTS                                      (0x17 | VMXINSTRID_VALID)
+#define VMXINSTRID_MOV_TO_DRX                                   (0x18 | VMXINSTRID_VALID)
+#define VMXINSTRID_MOV_FROM_DRX                                 (0x19 | VMXINSTRID_VALID)
 /** @} */
 
@@ -2612,5 +2614,20 @@
 /** 8-11: General purpose register number. */
 #define VMX_EXIT_QUAL_DRX_GENREG(a)                             (((a) >> 8) & 0xf)
-/** Rest: reserved. */
+
+/** Bit fields for Exit qualification due to Mov DRx. */
+#define VMX_BF_EXIT_QUAL_DRX_REGISTER_SHIFT                     0
+#define VMX_BF_EXIT_QUAL_DRX_REGISTER_MASK                      UINT64_C(0x0000000000000007)
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_1_SHIFT                       3
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_1_MASK                        UINT64_C(0x0000000000000008)
+#define VMX_BF_EXIT_QUAL_DRX_DIRECTION_SHIFT                    4
+#define VMX_BF_EXIT_QUAL_DRX_DIRECTION_MASK                     UINT64_C(0x0000000000000010)
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_5_7_SHIFT                     5
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_5_7_MASK                      UINT64_C(0x00000000000000e0)
+#define VMX_BF_EXIT_QUAL_DRX_GENREG_SHIFT                       8
+#define VMX_BF_EXIT_QUAL_DRX_GENREG_MASK                        UINT64_C(0x0000000000000f00)
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_12_63_SHIFT                   12
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_12_63_MASK                    UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_DRX_, UINT64_C(0), UINT64_MAX,
+                            (REGISTER, RSVD_1, DIRECTION, RSVD_5_7, GENREG, RSVD_12_63));
 /** @} */
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 74692)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 74693)
@@ -5282,4 +5282,5 @@
 {
     IEM_SVM_CHECK_READ_CR0_INTERCEPT(pVCpu, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+    /** @todo NSTVMX: SMSW CR0 masking. */
 
     switch (enmEffOpSize)
@@ -5901,8 +5902,23 @@
 IEM_CIMPL_DEF_2(iemCImpl_mov_Rd_Dd, uint8_t, iGReg, uint8_t, iDrReg)
 {
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+    /*
+     * Check nested-guest VMX intercept.
+     * Unlike most other intercepts, the Mov DRx intercept takes preceedence
+     * over CPL and CR4.DE and even DR4/DR5 checks.
+     *
+     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
+     */
+    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
+    {
+        VBOXSTRICTRC rcStrict = iemVmxVmexitInstrMovDrX(pVCpu, VMXINSTRID_MOV_FROM_DRX, iDrReg, iGReg, cbInstr);
+        if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
+            return rcStrict;
+    }
+#endif
+
     /*
      * Check preconditions.
      */
-
     /* Raise GPs. */
     if (pVCpu->iem.s.uCpl != 0)
@@ -5994,4 +6010,20 @@
 IEM_CIMPL_DEF_2(iemCImpl_mov_Dd_Rd, uint8_t, iDrReg, uint8_t, iGReg)
 {
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+    /*
+     * Check nested-guest VMX intercept.
+     * Unlike most other intercepts, the Mov DRx intercept takes preceedence
+     * over CPL and CR4.DE and even DR4/DR5 checks.
+     *
+     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
+     */
+    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
+    {
+        VBOXSTRICTRC rcStrict = iemVmxVmexitInstrMovDrX(pVCpu, VMXINSTRID_MOV_TO_DRX, iDrReg, iGReg, cbInstr);
+        if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
+            return rcStrict;
+    }
+#endif
+
     /*
      * Check preconditions.
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74692)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74693)
@@ -3292,4 +3292,44 @@
 
 /**
+ * VMX VM-exit handler for VM-exits due to 'Mov DRx,GReg' (DRx write) and 'Mov
+ * GReg,DRx' (DRx read).
+ *
+ * @returns VBox strict status code.
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   uInstrid    The instruction identity (VMXINSTRID_MOV_TO_DRX or
+ *                      VMXINSTRID_MOV_FROM_DRX).
+ * @param   iDrReg      The debug register being accessed.
+ * @param   iGReg       The general register to/from which the DRx value is being
+ *                      store/loaded.
+ * @param   cbInstr     The instruction length in bytes.
+ */
+IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMovDrX(PVMCPU pVCpu, VMXINSTRID uInstrId, uint8_t iDrReg, uint8_t iGReg,
+                                                uint8_t cbInstr)
+{
+    Assert(iDrReg <= 7);
+    Assert(uInstrId == VMXINSTRID_MOV_TO_DRX || uInstrId == VMXINSTRID_MOV_FROM_DRX);
+
+    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    Assert(pVmcs);
+
+    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT)
+    {
+        uint32_t const uDirection = uInstrId == VMXINSTRID_MOV_TO_DRX ? VMX_EXIT_QUAL_DRX_DIRECTION_WRITE
+                                                                      : VMX_EXIT_QUAL_DRX_DIRECTION_READ;
+        VMXVEXITINFO ExitInfo;
+        RT_ZERO(ExitInfo);
+        ExitInfo.uReason = VMX_EXIT_MOV_DRX;
+        ExitInfo.cbInstr = cbInstr;
+        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_DRX_REGISTER,  iDrReg)
+                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_DRX_DIRECTION, uDirection)
+                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_DRX_GENREG,    iGReg);
+        return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
+    }
+
+    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
+}
+
+
+/**
  * VMX VM-exit handler for VM-exits due to I/O instructions (IN and OUT).
  *
@@ -3355,17 +3395,47 @@
     if (fIntercept)
     {
-        uint32_t const uDirection = uInstrId == VMXINSTRID_IO_INS ? VMX_EXIT_QUAL_IO_DIRECTION_IN
-                                                                  : VMX_EXIT_QUAL_IO_DIRECTION_OUT;
+        /*
+         * Figure out the guest-linear address and the direction bit (INS/OUTS).
+         */
+        /** @todo r=ramshankar: Is there something in IEM that already does this? */
+        static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
+        uint8_t const  iSegReg       = ExitInstrInfo.StrIo.iSegReg;
+        uint8_t const  uAddrSize     = ExitInstrInfo.StrIo.u3AddrSize;
+        uint64_t const uAddrSizeMask = s_auAddrSizeMasks[uAddrSize];
+
+        uint32_t uDirection;
+        uint64_t uGuestLinearAddr;
+        if (uInstrId == VMXINSTRID_IO_INS)
+        {
+            uDirection = VMX_EXIT_QUAL_IO_DIRECTION_IN;
+            uGuestLinearAddr = pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base + (pVCpu->cpum.GstCtx.rdi & uAddrSizeMask);
+        }
+        else
+        {
+            uDirection = VMX_EXIT_QUAL_IO_DIRECTION_OUT;
+            uGuestLinearAddr = pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base + (pVCpu->cpum.GstCtx.rsi & uAddrSizeMask);
+        }
+
+        /*
+         * If the segment is ununsable, the guest-linear address in undefined.
+         * We shall clear it for consistency.
+         *
+         * See Intel spec. 27.2.1 "Basic VM-Exit Information".
+         */
+        if (pVCpu->cpum.GstCtx.aSRegs[iSegReg].Attr.n.u1Unusable)
+            uGuestLinearAddr = 0;
+
         VMXVEXITINFO ExitInfo;
         RT_ZERO(ExitInfo);
-        ExitInfo.uReason   = VMX_EXIT_IO_INSTR;
-        ExitInfo.cbInstr   = cbInstr;
-        ExitInfo.InstrInfo = ExitInstrInfo;
-        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_WIDTH,     cbAccess - 1)
-                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_DIRECTION, uDirection)
-                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_IS_STRING, 1)
-                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_IS_REP,    fRep)
-                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_ENCODING,  0)     /* DX (not immediate). */
-                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_PORT,      u16Port);
+        ExitInfo.uReason            = VMX_EXIT_IO_INSTR;
+        ExitInfo.cbInstr            = cbInstr;
+        ExitInfo.InstrInfo          = ExitInstrInfo;
+        ExitInfo.u64GuestLinearAddr = uGuestLinearAddr;
+        ExitInfo.u64Qual            = RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_WIDTH,     cbAccess - 1)
+                                    | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_DIRECTION, uDirection)
+                                    | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_IS_STRING, 1)
+                                    | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_IS_REP,    fRep)
+                                    | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_ENCODING,  VMX_EXIT_QUAL_IO_ENCODING_DX)
+                                    | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_PORT,      u16Port);
         return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
     }
