Index: /trunk/include/VBox/vmm/dbgf.h
===================================================================
--- /trunk/include/VBox/vmm/dbgf.h	(revision 35489)
+++ /trunk/include/VBox/vmm/dbgf.h	(revision 35490)
@@ -1355,4 +1355,27 @@
 } DBGFREGDESC;
 
+/** @name Macros for constructing DBGFREGDESC arrays.
+ * @{ */
+#define DBGFREGDESC_RW(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RO(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RW_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RO_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RW_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
+#define DBGFREGDESC_RO_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
+#define DBGFREGDESC_RW_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define DBGFREGDESC_RO_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+    { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define DBGFREGDESC_TERMINATOR() \
+    { NULL, DBGFREG_END, DBGFREGVALTYPE_INVALID, 0, 0, NULL, NULL, NULL, NULL }
+/** @} */
+
+
 /** @name DBGFREG_FLAGS_XXX
  * @{ */
@@ -1360,7 +1383,4 @@
 #define DBGFREG_FLAGS_READ_ONLY         RT_BIT_32(0)
 /** @} */
-
-
-
 
 /**
@@ -1400,4 +1420,7 @@
 
 VMMR3DECL(const char *) DBGFR3RegCpuName(PVM pVM, DBGFREG enmReg, DBGFREGVALTYPE enmType);
+
+VMMR3_INT_DECL(int) DBGFR3RegRegisterCpu(PVM pVM, PVMCPU pVCpu, PCDBGFREGDESC paRegisters);
+VMMR3DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns, const char *pszPrefix, uint32_t iInstance);
 
 /**
Index: /trunk/include/iprt/uint128.h
===================================================================
--- /trunk/include/iprt/uint128.h	(revision 35489)
+++ /trunk/include/iprt/uint128.h	(revision 35490)
@@ -269,4 +269,28 @@
 
 /**
+ * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made
+ * up of the first N bits, assigning the result to the the 128-bit value.
+ *
+ * @returns pValueResult.
+ * @param   pValueResult    The value and result.
+ * @param   cBits           The number of bits to AND (counting from the first
+ *                          bit).
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits)
+{
+    if (cBits <= 64)
+    {
+        if (cBits != 64)
+            pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
+        pValueResult->s.Hi = 0;
+    }
+    else if (cBits < 128)
+        pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
+/** @todo #if ARCH_BITS >= 64 */
+    return pValueResult;
+}
+
+
+/**
  * Performs a bitwise OR of two 128-bit unsigned integer values and assigned
  * the result to the first one.
Index: /trunk/src/VBox/Debugger/DBGCOps.cpp
===================================================================
--- /trunk/src/VBox/Debugger/DBGCOps.cpp	(revision 35489)
+++ /trunk/src/VBox/Debugger/DBGCOps.cpp	(revision 35490)
@@ -494,7 +494,47 @@
      * Get the register.
      */
-    /// @todo DBGFR3RegByName();
-    return VERR_NOT_IMPLEMENTED;
-
+    DBGFREGVALTYPE  enmType;
+    DBGFREGVAL      Value;
+    int rc = DBGFR3RegNmQuery(pDbgc->pVM, pDbgc->idCpu, pArg->u.pszString, &Value, &enmType);
+    if (RT_SUCCESS(rc))
+    {
+        rc = VERR_INTERNAL_ERROR_5;
+        switch (enmType)
+        {
+            case DBGFREGVALTYPE_U8:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u8);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_U16:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u16);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_U32:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u32);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_U64:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u64);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_U128:
+                DBGCVAR_INIT_NUMBER(pResult, Value.u128.s.Lo);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_LRD:
+                DBGCVAR_INIT_NUMBER(pResult, (uint64_t)Value.lrd);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_DTR:
+                DBGCVAR_INIT_NUMBER(pResult, Value.dtr.u64Base);
+                return VINF_SUCCESS;
+
+            case DBGFREGVALTYPE_INVALID:
+            case DBGFREGVALTYPE_END:
+            case DBGFREGVALTYPE_32BIT_HACK:
+                break;
+        }
+    }
+    return rc;
 }
 
Index: /trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp
===================================================================
--- /trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp	(revision 35489)
+++ /trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp	(revision 35490)
@@ -206,4 +206,9 @@
     return VERR_INTERNAL_ERROR;
 }
+VMMR3DECL(int) DBGFR3RegNmQuery(    PVM pVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType)
+{
+    return VERR_INTERNAL_ERROR;
+}
+
 VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PVM pVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr)
 {
Index: /trunk/src/VBox/VMM/VMMR3/CPUM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 35489)
+++ /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 35490)
@@ -220,5 +220,5 @@
 
     /*
-     * Register info handlers.
+     * Register info handlers and registers with the debugger facility.
      */
     DBGFR3InfoRegisterInternal(pVM, "cpum",             "Displays the all the cpu states.",         &cpumR3InfoAll);
@@ -228,4 +228,8 @@
     DBGFR3InfoRegisterInternal(pVM, "cpuid",            "Displays the guest cpuid leaves.",         &cpumR3CpuIdInfo);
     DBGFR3InfoRegisterInternal(pVM, "cpumguestinstr",   "Displays the current guest instruction.",  &cpumR3InfoGuestInstr);
+
+    rc = cpumR3DbgInit(pVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     /*
Index: /trunk/src/VBox/VMM/VMMR3/CPUMDbg.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUMDbg.cpp	(revision 35489)
+++ /trunk/src/VBox/VMM/VMMR3/CPUMDbg.cpp	(revision 35490)
@@ -23,4 +23,5 @@
 #include <VBox/vmm/cpum.h>
 #include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/pdmapi.h>
 #include "CPUMInternal.h"
 #include <VBox/vmm/vm.h>
@@ -29,7 +30,7 @@
 #include <VBox/log.h>
 #include <iprt/thread.h>
-
-
-#if 0
+#include <iprt/uint128.h>
+
+
 /**
  * @interface_method_impl{DBGFREGDESC, pfnGet}
@@ -88,9 +89,10 @@
 
         case DBGFREGVALTYPE_U128:
-            ((PRTUINT128U)pv)->s.Hi &= ~pfMask->u128.s.Hi;
-            ((PRTUINT128U)pv)->s.Lo &= ~pfMask->u128.s.Lo;
-            ((PRTUINT128U)pv)->s.Hi |= pValue->u128.s.Hi & pfMask->u128.s.Hi;
-            ((PRTUINT128U)pv)->s.Lo |= pValue->u128.s.Lo & pfMask->u128.s.Lo;
+        {
+            RTUINT128U Val;
+            RTUInt128AssignAnd((PRTUINT128U)pv, RTUInt128AssignBitwiseNot(RTUInt128Assign(&Val, &pfMask->u128)));
+            RTUInt128AssignOr((PRTUINT128U)pv, RTUInt128AssignAnd(RTUInt128Assign(&Val, &pValue->u128), &pfMask->u128));
             return VINF_SUCCESS;
+        }
 
         default:
@@ -110,68 +112,309 @@
 
 
-static DECLCALLBACK(int) cpumR3RegGet_crX(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_crX(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    uint64_t u64Value;
+    int rc = CPUMGetGuestCRx(pVCpu, pDesc->offRegister, &u64Value);
+    AssertRCReturn(rc, rc);
+    switch (pDesc->enmType)
+    {
+        case DBGFREGVALTYPE_U64:    pValue->u64 = u64Value; break;
+        case DBGFREGVALTYPE_U32:    pValue->u32 = (uint32_t)u64Value; break;
+        default:
+            AssertFailedReturn(VERR_INTERNAL_ERROR_4);
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_crX(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+    int         rc;
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    /*
+     * Calculate the new value.
+     */
+    uint64_t u64Value;
+    uint64_t fMask;
+    uint64_t fMaskMax;
+    switch (pDesc->enmType)
+    {
+        case DBGFREGVALTYPE_U64:
+            u64Value = pValue->u64;
+            fMask    = pfMask->u64;
+            fMaskMax = UINT64_MAX;
+            break;
+        case DBGFREGVALTYPE_U32:
+            u64Value = pValue->u32;
+            fMask    = pfMask->u32;
+            fMaskMax = UINT32_MAX;
+            break;
+        default:                    AssertFailedReturn(VERR_INTERNAL_ERROR_4);
+    }
+    if (fMask != fMaskMax)
+    {
+        uint64_t u64FullValue;
+        rc = CPUMGetGuestCRx(pVCpu, pDesc->offRegister, &u64FullValue);
+        if (RT_FAILURE(rc))
+            return rc;
+        u64Value = (u64FullValue & ~fMask)
+                 | (u64Value     &  fMask);
+    }
+
+    /*
+     * Perform the assignment.
+     */
+    switch (pDesc->offRegister)
+    {
+        case 0: rc = CPUMSetGuestCR0(pVCpu, u64Value); break;
+        case 2: rc = CPUMSetGuestCR2(pVCpu, u64Value); break;
+        case 3: rc = CPUMSetGuestCR3(pVCpu, u64Value); break;
+        case 4: rc = CPUMSetGuestCR4(pVCpu, u64Value); break;
+        case 8: rc = PDMApicSetTPR(pVCpu, (uint8_t)(u64Value << 4)); break;
+        default:
+            AssertFailedReturn(VERR_INTERNAL_ERROR_2);
+    }
+    return rc;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_drX(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    uint64_t u64Value;
+    int rc = CPUMGetGuestDRx(pVCpu, pDesc->offRegister, &u64Value);
+    AssertRCReturn(rc, rc);
+    switch (pDesc->enmType)
+    {
+        case DBGFREGVALTYPE_U64:    pValue->u64 = u64Value; break;
+        case DBGFREGVALTYPE_U32:    pValue->u32 = (uint32_t)u64Value; break;
+        default:
+            AssertFailedReturn(VERR_INTERNAL_ERROR_4);
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_drX(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+    int         rc;
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    /*
+     * Calculate the new value.
+     */
+    uint64_t u64Value;
+    uint64_t fMask;
+    uint64_t fMaskMax;
+    switch (pDesc->enmType)
+    {
+        case DBGFREGVALTYPE_U64:
+            u64Value = pValue->u64;
+            fMask    = pfMask->u64;
+            fMaskMax = UINT64_MAX;
+            break;
+        case DBGFREGVALTYPE_U32:
+            u64Value = pValue->u32;
+            fMask    = pfMask->u32;
+            fMaskMax = UINT32_MAX;
+            break;
+        default:                    AssertFailedReturn(VERR_INTERNAL_ERROR_4);
+    }
+    if (fMask != fMaskMax)
+    {
+        uint64_t u64FullValue;
+        rc = CPUMGetGuestDRx(pVCpu, pDesc->offRegister, &u64FullValue);
+        if (RT_FAILURE(rc))
+            return rc;
+        u64Value = (u64FullValue & ~fMask)
+                 | (u64Value     &  fMask);
+    }
+
+    /*
+     * Perform the assignment.
+     */
+    return CPUMSetGuestDRx(pVCpu, pDesc->offRegister, u64Value);
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_msr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+    uint64_t u64Value;
+    int rc = CPUMQueryGuestMsr(pVCpu, pDesc->offRegister, &u64Value);
+    if (RT_SUCCESS(rc))
+    {
+        switch (pDesc->enmType)
+        {
+            case DBGFREGVALTYPE_U64:    pValue->u64 = u64Value; break;
+            case DBGFREGVALTYPE_U32:    pValue->u32 = (uint32_t)u64Value; break;
+            case DBGFREGVALTYPE_U16:    pValue->u16 = (uint16_t)u64Value; break;
+            default:
+                AssertFailedReturn(VERR_INTERNAL_ERROR_4);
+        }
+    }
+    /** @todo what to do about errors? */
+    return rc;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_msr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+    int         rc;
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    /*
+     * Calculate the new value.
+     */
+    uint64_t u64Value;
+    uint64_t fMask;
+    uint64_t fMaskMax;
+    switch (pDesc->enmType)
+    {
+        case DBGFREGVALTYPE_U64:
+            u64Value = pValue->u64;
+            fMask    = pfMask->u64;
+            fMaskMax = UINT64_MAX;
+            break;
+        case DBGFREGVALTYPE_U32:
+            u64Value = pValue->u32;
+            fMask    = pfMask->u32;
+            fMaskMax = UINT32_MAX;
+            break;
+        case DBGFREGVALTYPE_U16:
+            u64Value = pValue->u16;
+            fMask    = pfMask->u16;
+            fMaskMax = UINT16_MAX;
+            break;
+        default:                    AssertFailedReturn(VERR_INTERNAL_ERROR_4);
+    }
+    if (fMask != fMaskMax)
+    {
+        uint64_t u64FullValue;
+        rc = CPUMQueryGuestMsr(pVCpu, pDesc->offRegister, &u64FullValue);
+        if (RT_FAILURE(rc))
+            return rc;
+        u64Value = (u64FullValue & ~fMask)
+                 | (u64Value     &  fMask);
+    }
+
+    /*
+     * Perform the assignment.
+     */
+    return CPUMSetGuestMsr(pVCpu, pDesc->offRegister, u64Value);
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_gdtr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+    Assert(pDesc->enmType == DBGFREGVALTYPE_DTR);
+
+    pValue->dtr.u32Limit  = pVCpu->cpum.s.Guest.gdtr.cbGdt;
+    pValue->dtr.u64Base   = pVCpu->cpum.s.Guest.gdtr.pGdt;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_gdtr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static DECLCALLBACK(int) cpumR3RegSet_crX(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_idtr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+    PVMCPU      pVCpu   = (PVMCPU)pvUser;
+    void const *pv      = (uint8_t const *)&pVCpu->cpum.s.Guest + pDesc->offRegister;
+
+    VMCPU_ASSERT_EMT(pVCpu);
+    Assert(pDesc->enmType == DBGFREGVALTYPE_DTR);
+
+    pValue->dtr.u32Limit  = pVCpu->cpum.s.Guest.idtr.cbIdt;
+    pValue->dtr.u64Base   = pVCpu->cpum.s.Guest.idtr.pIdt;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_idtr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static DECLCALLBACK(int) cpumR3RegGet_drX(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_ftw(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static DECLCALLBACK(int) cpumR3RegSet_drX(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegSet_ftw(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static DECLCALLBACK(int) cpumR3RegGet_msr(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegSet_msr(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegGet_gdtr(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegSet_gdtr(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegGet_idtr(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegSet_idtr(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegGet_ftw(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static DECLCALLBACK(int) cpumR3RegSet_ftw(PVMCPU pVCpu, PCDBGFREGDESC pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-/**
- * @interface_method_impl{DBGFREGDESC, pfnGet}
- */
-static DECLCALLBACK(int) cpumR3RegGet_stN(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+/**
+ * @interface_method_impl{DBGFREGDESC, pfnGet}
+ */
+static DECLCALLBACK(int) cpumR3RegGet_stN(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
 {
     return VERR_NOT_IMPLEMENTED;
@@ -220,5 +463,5 @@
 static DBGFREGALIAS const g_aCpumRegAliases_fpuip[] =
 {
-    { "fpuip", DBGFREGVALTYPE_U16  },
+    { "fpuip16", DBGFREGVALTYPE_U16  },
     { NULL, DBGFREGVALTYPE_INVALID }
 };
@@ -226,5 +469,5 @@
 static DBGFREGALIAS const g_aCpumRegAliases_fpudp[] =
 {
-    { "fpudp", DBGFREGVALTYPE_U16  },
+    { "fpudp16", DBGFREGVALTYPE_U16  },
     { NULL, DBGFREGVALTYPE_INVALID }
 };
@@ -497,9 +740,17 @@
 static DBGFREGDESC const g_aCpumRegDescs[] =
 {
+#define CPUMREGDESC_RW_AS(a_szName, a_RegSuff, a_TypeSuff, a_CpumCtxMemb, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+    { a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            RT_OFFSETOF(CPUMCTX, a_CpumCtxMemb), a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define CPUMREGDESC_RO_AS(a_szName, a_RegSuff, a_TypeSuff, a_CpumCtxMemb, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+    { a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, RT_OFFSETOF(CPUMCTX, a_CpumCtxMemb), a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define CPUMREGDESC_EX_AS(a_szName, a_RegSuff, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+    { a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/,            a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+
 #define CPUMREGDESC_REG(UName, LName) \
-    { #LName, DBGFREG_##UName, DBGFREGVALTYPE_U64, 0, RT_OFFSETOF(CPUMCTX, LName), cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_##LName, NULL }
+    CPUMREGDESC_RW_AS(#LName,           UName,          U64, LName,                 cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_##LName,  NULL)
     CPUMREGDESC_REG(RAX, rax),
     CPUMREGDESC_REG(RCX, rcx),
     CPUMREGDESC_REG(RDX, rdx),
+    CPUMREGDESC_REG(RBX, rbx),
     CPUMREGDESC_REG(RSP, rsp),
     CPUMREGDESC_REG(RBP, rbp),
@@ -515,8 +766,8 @@
     CPUMREGDESC_REG(R15, r15),
 #define CPUMREGDESC_SEG(UName, LName) \
-    { #LName,         DBGFREG_##UName,        DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, LName),               cpumR3RegGet_Generic, cpumR3RegSet_seg,     NULL, NULL },  \
-    { #LName "_attr", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, 0, RT_OFFSETOF(CPUMCTX, LName##Hid.Attr.u),   cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_seg }, \
-    { #LName "_base", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U64, 0, RT_OFFSETOF(CPUMCTX, LName##Hid.u64Base),  cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL }, \
-    { #LName "_lim",  DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, 0, RT_OFFSETOF(CPUMCTX, LName##Hid.u32Limit), cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL }
+    CPUMREGDESC_RW_AS(#LName,           UName,          U16, LName,                 cpumR3RegGet_Generic, cpumR3RegSet_seg,     NULL,                       NULL                ), \
+    CPUMREGDESC_RW_AS(#LName "_attr",   UName##_ATTR,   U32, LName##Hid.Attr.u,     cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_seg), \
+    CPUMREGDESC_RW_AS(#LName "_base",   UName##_BASE,   U64, LName##Hid.u64Base,    cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       NULL                ), \
+    CPUMREGDESC_RW_AS(#LName "_lim",    UName##_LIMIT,  U32, LName##Hid.u32Limit,   cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       NULL                )
     CPUMREGDESC_SEG(CS, cs),
     CPUMREGDESC_SEG(DS, ds),
@@ -526,17 +777,17 @@
     CPUMREGDESC_SEG(SS, ss),
     CPUMREGDESC_REG(RIP, rip),
-    { "rflags",     DBGFREG_RFLAGS,     DBGFREGVALTYPE_U64, 0, RT_OFFSETOF(CPUMCTX, rflags),         cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_rflags, g_aCpumRegFields_rflags },
-    { "fcw",        DBGFREG_FCW,        DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, fpu.FCW),        cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_fcw },
-    { "fsw",        DBGFREG_FSW,        DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, fpu.FSW),        cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_fsw },
-    { "ftw",        DBGFREG_FTW,        DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, fpu.FTW),        cpumR3RegGet_ftw,     cpumR3RegSet_ftw,     NULL, g_aCpumRegFields_ftw },
-    { "fop",        DBGFREG_FOP,        DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, fpu.FOP),        cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
-    { "fpuip",      DBGFREG_FPUIP,      DBGFREGVALTYPE_U32, 0, RT_OFFSETOF(CPUMCTX, fpu.FPUIP),      cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpuip, NULL },
-    { "fpucs",      DBGFREG_FPUCS,      DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, fpu.CS),         cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
-    { "fpudp",      DBGFREG_FPUDP,      DBGFREGVALTYPE_U32, 0, RT_OFFSETOF(CPUMCTX, fpu.FPUDP),      cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpudp, NULL },
-    { "fpuds",      DBGFREG_FPUDS,      DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, fpu.DS),         cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
-    { "mxcsr",      DBGFREG_MXCSR,      DBGFREGVALTYPE_U32, 0, RT_OFFSETOF(CPUMCTX, fpu.MXCSR),      cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mxcsr },
-    { "mxcsr_mask", DBGFREG_MXCSR_MASK, DBGFREGVALTYPE_U32, 0, RT_OFFSETOF(CPUMCTX, fpu.MXCSR_MASK), cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mxcsr },
+    CPUMREGDESC_RW_AS("rflags",         RFLAGS,         U64, rflags,                cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_rflags,   g_aCpumRegFields_rflags ),
+    CPUMREGDESC_RW_AS("fcw",            FCW,            U16, fpu.FCW,               cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_fcw    ),
+    CPUMREGDESC_RW_AS("fsw",            FSW,            U16, fpu.FSW,               cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_fsw    ),
+    CPUMREGDESC_RW_AS("ftw",            FTW,            U16, fpu.FTW,               cpumR3RegGet_ftw,     cpumR3RegSet_ftw,     NULL,                       g_aCpumRegFields_ftw    ),
+    CPUMREGDESC_RW_AS("fop",            FOP,            U16, fpu.FOP,               cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("fpuip",          FPUIP,          U32, fpu.FPUIP,             cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpuip,    NULL                    ),
+    CPUMREGDESC_RW_AS("fpucs",          FPUCS,          U16, fpu.CS,                cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("fpudp",          FPUDP,          U32, fpu.FPUDP,             cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpudp,    NULL                    ),
+    CPUMREGDESC_RW_AS("fpuds",          FPUDS,          U16, fpu.DS,                cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("mxcsr",          MXCSR,          U32, fpu.MXCSR,             cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_mxcsr  ),
+    CPUMREGDESC_RW_AS("mxcsr_mask",     MXCSR_MASK,     U32, fpu.MXCSR_MASK,        cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_mxcsr  ),
 #define CPUMREGDESC_ST(n) \
-    { "st" #n,      DBGFREG_ST##n,      DBGFREGVALTYPE_LRD, 0, ~(size_t)0, cpumR3RegGet_stN, cpumR3RegSet_stN, NULL, g_aCpumRegFields_stN }
+    CPUMREGDESC_RW_AS("st" #n,          ST##n,          LRD, fpu.aRegs[n],          cpumR3RegGet_stN,     cpumR3RegSet_stN,     NULL,                       g_aCpumRegFields_stN    )
     CPUMREGDESC_ST(0),
     CPUMREGDESC_ST(1),
@@ -548,5 +799,5 @@
     CPUMREGDESC_ST(7),
 #define CPUMREGDESC_MM(n) \
-    { "mm" #n,      DBGFREG_MM##n,      DBGFREGVALTYPE_U64, 0, RT_OFFSETOF(CPUMCTX, fpu.aRegs[n].mmx), cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mmN }
+    CPUMREGDESC_RW_AS("mm" #n,          MM##n,          U64, fpu.aRegs[n].mmx,      cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_mmN    )
     CPUMREGDESC_MM(0),
     CPUMREGDESC_MM(1),
@@ -558,5 +809,5 @@
     CPUMREGDESC_MM(7),
 #define CPUMREGDESC_XMM(n) \
-    { "xmm" #n,     DBGFREG_XMM##n,     DBGFREGVALTYPE_U128, 0, RT_OFFSETOF(CPUMCTX, fpu.aXMM[n].xmm), cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_xmmN }
+    CPUMREGDESC_RW_AS("xmm" #n,         XMM##n,         U128, fpu.aXMM[n].xmm,      cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,                       g_aCpumRegFields_xmmN   )
     CPUMREGDESC_XMM(0),
     CPUMREGDESC_XMM(1),
@@ -575,42 +826,46 @@
     CPUMREGDESC_XMM(14),
     CPUMREGDESC_XMM(15),
-    { "gdtr_base",  DBGFREG_GDTR_BASE,      DBGFREGVALTYPE_U64, 0, RT_OFFSETOF(CPUMCTX, gdtr.pGdt),  cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
-    { "gdtr_limit", DBGFREG_GDTR_LIMIT,     DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, gdtr.cbGdt), cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
-    { "idtr_base",  DBGFREG_IDTR_BASE,      DBGFREGVALTYPE_U64, 0, RT_OFFSETOF(CPUMCTX, idtr.pIdt),  cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
-    { "idtr_limit", DBGFREG_IDTR_LIMIT,     DBGFREGVALTYPE_U16, 0, RT_OFFSETOF(CPUMCTX, idtr.cbIdt), cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL },
+    CPUMREGDESC_RW_AS("gdtr_base",      GDTR_BASE,      U64, gdtr.pGdt,          cpumR3RegGet_Generic,    cpumR3RegSet_Generic, NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("gdtr_limit",     GDTR_LIMIT,     U16, gdtr.cbGdt,         cpumR3RegGet_Generic,    cpumR3RegSet_Generic, NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("idtr_base",      IDTR_BASE,      U64, idtr.pIdt,          cpumR3RegGet_Generic,    cpumR3RegSet_Generic, NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("idtr_limit",     IDTR_LIMIT,     U16, idtr.cbIdt,         cpumR3RegGet_Generic,    cpumR3RegSet_Generic, NULL,                       NULL                    ),
     CPUMREGDESC_SEG(LDTR, ldtr),
     CPUMREGDESC_SEG(TR, tr),
-    { "cr0",        DBGFREG_CR0,       DBGFREGVALTYPE_U32, 0, 0, cpumR3RegGet_crX, cpumR3RegSet_crX, g_aCpumRegAliases_cr0, g_aCpumRegFields_cr0 },
-    { "cr2",        DBGFREG_CR2,       DBGFREGVALTYPE_U64, 0, 2, cpumR3RegGet_crX, cpumR3RegSet_crX, NULL, NULL },
-    { "cr3",        DBGFREG_CR3,       DBGFREGVALTYPE_U64, 0, 3, cpumR3RegGet_crX, cpumR3RegSet_crX, NULL, g_aCpumRegFields_cr3 },
-    { "cr4",        DBGFREG_CR4,       DBGFREGVALTYPE_U32, 0, 4, cpumR3RegGet_crX, cpumR3RegSet_crX, NULL, g_aCpumRegFields_cr4 },
-    { "cr8",        DBGFREG_CR8,       DBGFREGVALTYPE_U32, 0, 8, cpumR3RegGet_crX, cpumR3RegSet_crX, NULL, NULL },
-    { "dr0",        DBGFREG_DR0,       DBGFREGVALTYPE_U64, 0, 0, cpumR3RegGet_drX, cpumR3RegSet_drX, NULL, NULL },
-    { "dr1",        DBGFREG_DR1,       DBGFREGVALTYPE_U64, 0, 1, cpumR3RegGet_drX, cpumR3RegSet_drX, NULL, NULL },
-    { "dr2",        DBGFREG_DR2,       DBGFREGVALTYPE_U64, 0, 2, cpumR3RegGet_drX, cpumR3RegSet_drX, NULL, NULL },
-    { "dr3",        DBGFREG_DR3,       DBGFREGVALTYPE_U64, 0, 3, cpumR3RegGet_drX, cpumR3RegSet_drX, NULL, NULL },
-    { "dr6",        DBGFREG_DR6,       DBGFREGVALTYPE_U32, 0, 6, cpumR3RegGet_drX, cpumR3RegSet_drX, NULL, g_aCpumRegFields_dr6 },
-    { "dr7",        DBGFREG_DR7,       DBGFREGVALTYPE_U32, 0, 7, cpumR3RegGet_drX, cpumR3RegSet_drX, NULL, g_aCpumRegFields_dr7 },
-    { "apic_base",    DBGFREG_MSR_IA32_APICBASE,      DBGFREGVALTYPE_U32, 0, MSR_IA32_APICBASE,      cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_apic_base },
-    { "pat",          DBGFREG_MSR_IA32_CR_PAT,        DBGFREGVALTYPE_U64, 0, MSR_IA32_CR_PAT,        cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_cr_pat },
-    { "perf_status",  DBGFREG_MSR_IA32_PERF_STATUS,   DBGFREGVALTYPE_U64, 0, MSR_IA32_PERF_STATUS,   cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_perf_status },
-    { "sysenter_cs",  DBGFREG_MSR_IA32_SYSENTER_CS,   DBGFREGVALTYPE_U16, 0, MSR_IA32_SYSENTER_CS,   cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "sysenter_eip", DBGFREG_MSR_IA32_SYSENTER_EIP,  DBGFREGVALTYPE_U32, 0, MSR_IA32_SYSENTER_EIP,  cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "sysenter_esp", DBGFREG_MSR_IA32_SYSENTER_ESP,  DBGFREGVALTYPE_U32, 0, MSR_IA32_SYSENTER_ESP,  cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "tsc",          DBGFREG_MSR_IA32_TSC,           DBGFREGVALTYPE_U32, 0, MSR_IA32_TSC,           cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "efer",         DBGFREG_MSR_K6_EFER,            DBGFREGVALTYPE_U32, 0, MSR_K6_EFER,            cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_efer },
-    { "star",         DBGFREG_MSR_K6_STAR,            DBGFREGVALTYPE_U64, 0, MSR_K6_STAR,            cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_star },
-    { "cstar",        DBGFREG_MSR_K8_CSTAR,           DBGFREGVALTYPE_U64, 0, MSR_K8_CSTAR,           cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_cstar },
-    { "msr_fs_base",  DBGFREG_MSR_K8_FS_BASE,         DBGFREGVALTYPE_U64, 0, MSR_K8_FS_BASE,         cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "msr_gs_base",  DBGFREG_MSR_K8_GS_BASE,         DBGFREGVALTYPE_U64, 0, MSR_K8_GS_BASE,         cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "krnl_gs_base", DBGFREG_MSR_K8_KERNEL_GS_BASE,  DBGFREGVALTYPE_U64, 0, MSR_K8_KERNEL_GS_BASE,  cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "lstar",        DBGFREG_MSR_K8_LSTAR,           DBGFREGVALTYPE_U64, 0, MSR_K8_LSTAR,           cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, g_aCpumRegFields_lstar },
-    { "tsc_aux",      DBGFREG_MSR_K8_TSC_AUX,         DBGFREGVALTYPE_U64, 0, MSR_K8_TSC_AUX,         cpumR3RegGet_msr, cpumR3RegSet_msr, NULL, NULL },
-    { "ah",           DBGFREG_AH,       DBGFREGVALTYPE_U8,  0, RT_OFFSETOF(CPUMCTX, rax) + 1,  NULL, NULL, NULL, NULL },
-    { "ch",           DBGFREG_CH,       DBGFREGVALTYPE_U8,  0, RT_OFFSETOF(CPUMCTX, rcx) + 1,  NULL, NULL, NULL, NULL },
-    { "dh",           DBGFREG_DH,       DBGFREGVALTYPE_U8,  0, RT_OFFSETOF(CPUMCTX, rdx) + 1,  NULL, NULL, NULL, NULL },
-    { "bh",           DBGFREG_BH,       DBGFREGVALTYPE_U8,  0, RT_OFFSETOF(CPUMCTX, rbx) + 1,  NULL, NULL, NULL, NULL },
-    { "gdtr",         DBGFREG_GDTR,     DBGFREGVALTYPE_DTR, 0, ~(size_t)0, cpumR3RegGet_gdtr, cpumR3RegSet_gdtr, NULL, NULL },
-    { "idtr",         DBGFREG_IDTR,     DBGFREGVALTYPE_DTR, 0, ~(size_t)0, cpumR3RegGet_idtr, cpumR3RegSet_idtr, NULL, NULL },
+    CPUMREGDESC_EX_AS("cr0",            CR0,            U32, 0,                  cpumR3RegGet_crX,        cpumR3RegSet_crX,     g_aCpumRegAliases_cr0,      g_aCpumRegFields_cr0    ),
+    CPUMREGDESC_EX_AS("cr2",            CR2,            U64, 2,                  cpumR3RegGet_crX,        cpumR3RegSet_crX,     NULL,                       NULL                    ),
+    CPUMREGDESC_EX_AS("cr3",            CR3,            U64, 3,                  cpumR3RegGet_crX,        cpumR3RegSet_crX,     NULL,                       g_aCpumRegFields_cr3    ),
+    CPUMREGDESC_EX_AS("cr4",            CR4,            U32, 4,                  cpumR3RegGet_crX,        cpumR3RegSet_crX,     NULL,                       g_aCpumRegFields_cr4    ),
+    CPUMREGDESC_EX_AS("cr8",            CR8,            U32, 8,                  cpumR3RegGet_crX,        cpumR3RegSet_crX,     NULL,                       NULL                    ),
+    CPUMREGDESC_EX_AS("dr0",            DR0,            U64, 0,                  cpumR3RegGet_drX,        cpumR3RegSet_drX,     NULL,                       NULL                    ),
+    CPUMREGDESC_EX_AS("dr1",            DR1,            U64, 1,                  cpumR3RegGet_drX,        cpumR3RegSet_drX,     NULL,                       NULL                    ),
+    CPUMREGDESC_EX_AS("dr2",            DR2,            U64, 2,                  cpumR3RegGet_drX,        cpumR3RegSet_drX,     NULL,                       NULL                    ),
+    CPUMREGDESC_EX_AS("dr3",            DR3,            U64, 3,                  cpumR3RegGet_drX,        cpumR3RegSet_drX,     NULL,                       NULL                    ),
+    CPUMREGDESC_EX_AS("dr6",            DR6,            U32, 6,                  cpumR3RegGet_drX,        cpumR3RegSet_drX,     NULL,                       g_aCpumRegFields_dr6    ),
+    CPUMREGDESC_EX_AS("dr7",            DR7,            U32, 7,                  cpumR3RegGet_drX,        cpumR3RegSet_drX,     NULL,                       g_aCpumRegFields_dr7    ),
+#define CPUMREGDESC_MSR(a_szName, UName, a_TypeSuff, a_paSubFields) \
+    CPUMREGDESC_EX_AS(a_szName,         MSR_##UName,    a_TypeSuff, MSR_##UName, cpumR3RegGet_msr,        cpumR3RegSet_msr,     NULL,                       a_paSubFields           )
+    CPUMREGDESC_MSR("apic_base",     IA32_APICBASE,     U32, g_aCpumRegFields_apic_base  ),
+    CPUMREGDESC_MSR("pat",           IA32_CR_PAT,       U64, g_aCpumRegFields_cr_pat     ),
+    CPUMREGDESC_MSR("perf_status",   IA32_PERF_STATUS,  U64, g_aCpumRegFields_perf_status),
+    CPUMREGDESC_MSR("sysenter_cs",   IA32_SYSENTER_CS,  U16, NULL                        ),
+    CPUMREGDESC_MSR("sysenter_eip",  IA32_SYSENTER_EIP, U32, NULL                        ),
+    CPUMREGDESC_MSR("sysenter_esp",  IA32_SYSENTER_ESP, U32, NULL                        ),
+    CPUMREGDESC_MSR("tsc",           IA32_TSC,          U32, NULL                        ),
+    CPUMREGDESC_MSR("efer",          K6_EFER,           U32, g_aCpumRegFields_efer       ),
+    CPUMREGDESC_MSR("star",          K6_STAR,           U64, g_aCpumRegFields_star       ),
+    CPUMREGDESC_MSR("cstar",         K8_CSTAR,          U64, g_aCpumRegFields_cstar      ),
+    CPUMREGDESC_MSR("msr_fs_base",   K8_FS_BASE,        U64, NULL                        ),
+    CPUMREGDESC_MSR("msr_gs_base",   K8_GS_BASE,        U64, NULL                        ),
+    CPUMREGDESC_MSR("krnl_gs_base",  K8_KERNEL_GS_BASE, U64, NULL                        ),
+    CPUMREGDESC_MSR("lstar",         K8_LSTAR,          U64, g_aCpumRegFields_lstar      ),
+    CPUMREGDESC_MSR("sf_mask",       K8_SF_MASK,        U64, NULL                        ),
+    CPUMREGDESC_MSR("tsc_aux",       K8_TSC_AUX,        U64, NULL                        ),
+    CPUMREGDESC_EX_AS("ah",             AH,             U8,  RT_OFFSETOF(CPUMCTX, rax) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,               NULL                    ),
+    CPUMREGDESC_EX_AS("ch",             CH,             U8,  RT_OFFSETOF(CPUMCTX, rcx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,               NULL                    ),
+    CPUMREGDESC_EX_AS("dh",             DH,             U8,  RT_OFFSETOF(CPUMCTX, rdx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,               NULL                    ),
+    CPUMREGDESC_EX_AS("bh",             BH,             U8,  RT_OFFSETOF(CPUMCTX, rbx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL,               NULL                    ),
+    CPUMREGDESC_RW_AS("gdtr",           GDTR,           DTR, gdtr,              cpumR3RegGet_gdtr,        cpumR3RegSet_gdtr,    NULL,                       NULL                    ),
+    CPUMREGDESC_RW_AS("idtr",           IDTR,           DTR, idtr,              cpumR3RegGet_idtr,        cpumR3RegSet_idtr,    NULL,                       NULL                    ),
+    DBGFREGDESC_TERMINATOR()
 #undef CPUMREGDESC_REG
 #undef CPUMREGDESC_SEG
@@ -618,5 +873,25 @@
 #undef CPUMREGDESC_MM
 #undef CPUMREGDESC_XMM
-};
-
-#endif
+#undef CPUMREGDESC_MSR
+};
+
+
+/**
+ * Initializes the debugger related sides of the CPUM component.
+ *
+ * Called by CPUMR3Init.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 The VM handle.
+ */
+int cpumR3DbgInit(PVM pVM)
+{
+    for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
+    {
+        int rc = DBGFR3RegRegisterCpu(pVM, &pVM->aCpus[iCpu], g_aCpumRegDescs);
+        AssertLogRelRCReturn(rc, rc);
+    }
+
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp	(revision 35489)
+++ /trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp	(revision 35490)
@@ -30,4 +30,5 @@
 #include <iprt/ctype.h>
 #include <iprt/string.h>
+#include <iprt/uint128.h>
 
 
@@ -156,5 +157,11 @@
 int dbgfR3RegInit(PVM pVM)
 {
-    return RTSemRWCreate(&pVM->dbgf.s.hRegDbLock);
+    int rc = VINF_SUCCESS;
+    if (!pVM->dbgf.s.fRegDbInitialized)
+    {
+        rc = RTSemRWCreate(&pVM->dbgf.s.hRegDbLock);
+        pVM->dbgf.s.fRegDbInitialized = RT_SUCCESS(rc);
+    }
+    return rc;
 }
 
@@ -169,4 +176,5 @@
     RTSemRWDestroy(pVM->dbgf.s.hRegDbLock);
     pVM->dbgf.s.hRegDbLock = NIL_RTSEMRW;
+    pVM->dbgf.s.fRegDbInitialized = false;
 }
 
@@ -179,6 +187,7 @@
  * @returns true if valid, false if not.
  * @param   pszName             The register name to validate.
- */
-static bool dbgfR3RegIsNameValid(const char *pszName)
+ * @param   chDot               Set to '.' if accepted, otherwise 0.
+ */
+static bool dbgfR3RegIsNameValid(const char *pszName, char chDot)
 {
     const char *psz = pszName;
@@ -189,5 +198,6 @@
         if (   !RT_C_IS_LOWER(ch)
             && !RT_C_IS_DIGIT(ch)
-            && ch != '_')
+            && ch != '_'
+            && ch != chDot)
             return false;
     if (psz - pszName > DBGF_REG_MAX_NAME)
@@ -215,5 +225,5 @@
      */
     /* The name components. */
-    AssertMsgReturn(dbgfR3RegIsNameValid(pszPrefix), ("%s\n", pszPrefix), VERR_INVALID_NAME);
+    AssertMsgReturn(dbgfR3RegIsNameValid(pszPrefix, 0), ("%s\n", pszPrefix), VERR_INVALID_NAME);
     const char  *psz             = RTStrEnd(pszPrefix, RTSTR_MAX);
     bool const   fNeedUnderscore = RT_C_IS_DIGIT(psz[-1]);
@@ -228,5 +238,5 @@
     for (iDesc = 0; paRegisters[iDesc].pszName != NULL; iDesc++)
     {
-        AssertMsgReturn(dbgfR3RegIsNameValid(paRegisters[iDesc].pszName), ("%s (#%u)\n", paRegisters[iDesc].pszName, iDesc), VERR_INVALID_NAME);
+        AssertMsgReturn(dbgfR3RegIsNameValid(paRegisters[iDesc].pszName, 0), ("%s (#%u)\n", paRegisters[iDesc].pszName, iDesc), VERR_INVALID_NAME);
 
         if (enmType == DBGFREGSETTYPE_CPU)
@@ -238,5 +248,5 @@
         AssertReturn(   paRegisters[iDesc].enmType > DBGFREGVALTYPE_INVALID
                      && paRegisters[iDesc].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
-        AssertMsgReturn(paRegisters[iDesc].fFlags & ~DBGFREG_FLAGS_READ_ONLY,
+        AssertMsgReturn(!(paRegisters[iDesc].fFlags & ~DBGFREG_FLAGS_READ_ONLY),
                         ("%#x (#%u)\n", paRegisters[iDesc].fFlags, iDesc),
                         VERR_INVALID_PARAMETER);
@@ -251,5 +261,5 @@
             for (; paAliases[iAlias].pszName; iAlias++)
             {
-                AssertMsgReturn(dbgfR3RegIsNameValid(paAliases[iAlias].pszName), ("%s (%s)\n", paAliases[iAlias].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
+                AssertMsgReturn(dbgfR3RegIsNameValid(paAliases[iAlias].pszName, 0), ("%s (%s)\n", paAliases[iAlias].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
                 AssertReturn(   paAliases[iAlias].enmType > DBGFREGVALTYPE_INVALID
                              && paAliases[iAlias].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
@@ -264,5 +274,5 @@
             for (; paSubFields[iSubField].pszName; iSubField++)
             {
-                AssertMsgReturn(dbgfR3RegIsNameValid(paSubFields[iSubField].pszName), ("%s (%s)\n", paSubFields[iSubField].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
+                AssertMsgReturn(dbgfR3RegIsNameValid(paSubFields[iSubField].pszName, '.'), ("%s (%s)\n", paSubFields[iSubField].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
                 AssertReturn(paSubFields[iSubField].iFirstBit + paSubFields[iSubField].cBits <= 128, VERR_INVALID_PARAMETER);
                 AssertReturn(paSubFields[iSubField].cBits + paSubFields[iSubField].cShift <= 128, VERR_INVALID_PARAMETER);
@@ -323,6 +333,6 @@
         while (RT_SUCCESS(rc))
         {
-            size_t cchReg = strlen(paRegisters[iDesc].pszName);
-            memcpy(pszReg, paRegisters[iDesc].pszName, cchReg + 1);
+            size_t cchReg = strlen(pszRegName);
+            memcpy(pszReg, pszRegName, cchReg + 1);
             pLookupRec->Core.pszString = MMR3HeapStrDup(pVM, MM_TAG_DBGF_REG, szName);
             if (!pLookupRec->Core.pszString)
@@ -332,4 +342,5 @@
             pLookupRec->pAlias    = pCurAlias;
             pLookupRec->pSubField = NULL;
+            pLookupRec++;
 
             PCDBGFREGSUBFIELD paSubFields = paRegisters[iDesc].paSubFields;
@@ -348,4 +359,5 @@
                     pLookupRec->pAlias    = pCurAlias;
                     pLookupRec->pSubField = &paSubFields[iSubField];
+                    pLookupRec++;
                 }
             }
@@ -353,10 +365,12 @@
             /* next */
             pCurAlias = pNextAlias++;
-            if (   !pCurAlias
-                || !pCurAlias->pszName)
+            if (!pCurAlias)
                 break;
             pszRegName = pCurAlias->pszName;
+            if (!pszRegName)
+                break;
         }
     }
+    Assert(pLookupRec == &pRegSet->paLookupRecs[pRegSet->cLookupRecs]);
 
     if (RT_SUCCESS(rc))
@@ -406,10 +420,18 @@
  *
  * @returns VBox status code.
+ * @param   pVM             The VM handle.
  * @param   pVCpu           The virtual CPU handle.
  * @param   paRegisters     The register descriptors.
  */
-VMMR3_INT_DECL(int) DBGFR3RegRegisterDevice(PVMCPU pVCpu, PCDBGFREGDESC paRegisters)
-{
-    return dbgfR3RegRegisterCommon(pVCpu->pVMR3, paRegisters, DBGFREGSETTYPE_CPU, pVCpu, "cpu", pVCpu->idCpu);
+VMMR3_INT_DECL(int) DBGFR3RegRegisterCpu(PVM pVM, PVMCPU pVCpu, PCDBGFREGDESC paRegisters)
+{
+    if (!pVM->dbgf.s.fRegDbInitialized)
+    {
+        int rc = dbgfR3RegInit(pVM);
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+
+    return dbgfR3RegRegisterCommon(pVM, paRegisters, DBGFREGSETTYPE_CPU, pVCpu, "cpu", pVCpu->idCpu);
 }
 
@@ -1065,75 +1087,4 @@
 
 /**
- * Performs a left shift on a RTUINT128U value.
- *
- * @returns pVal.
- * @param   pVal                The value to shift (input/output).
- * @param   cBits               The number of bits to shift it.  Negative
- *                              numbers are treated as right shifts.
- */
-static PRTUINT128U dbgfR3RegU128_ShiftLeft(PRTUINT128U pVal, int cBits)
-{
-    RTUINT128U const InVal = *pVal;
-
-    if (cBits >= 0)
-    {
-        if (cBits >= 128)
-            pVal->s.Lo  = pVal->s.Hi = 0;
-        else if (cBits >= 64)
-        {
-            pVal->s.Lo  = 0;
-            pVal->s.Hi  = InVal.s.Lo << (cBits - 64);
-        }
-        else
-        {
-            pVal->s.Hi  = InVal.s.Hi << cBits;
-            pVal->s.Hi |= InVal.s.Lo >> (64 - cBits);
-            pVal->s.Lo  = InVal.s.Lo << cBits;
-        }
-    }
-    else
-    {
-        /* (right shift) */
-        cBits = -cBits;
-        if (cBits >= 128)
-            pVal->s.Lo  = pVal->s.Hi = 0;
-        else if (cBits >= 64)
-        {
-            pVal->s.Hi  = 0;
-            pVal->s.Lo  = InVal.s.Hi >> (cBits - 64);
-        }
-        else
-        {
-            pVal->s.Lo  = InVal.s.Lo >> cBits;
-            pVal->s.Lo |= InVal.s.Hi << (64 - cBits);
-            pVal->s.Hi  = InVal.s.Hi >> cBits;
-        }
-    }
-    return pVal;
-}
-
-
-/**
- * ANDs the RTUINT128U value against a bitmask made up of the first @a cBits
- * bits.
- *
- * @returns pVal.
- * @param   pVal                The value to shift (input/output).
- * @param   cBits               The number of bits in the AND mask.
- */
-static PRTUINT128U dbgfR3RegU128_AndNFirstBits(PRTUINT128U pVal, unsigned cBits)
-{
-    if (cBits <= 64)
-    {
-        pVal->s.Hi  = 0;
-        pVal->s.Lo &= RT_BIT_64(cBits) - 1;
-    }
-    else if (cBits < 128)
-        pVal->s.Hi &= RT_BIT_64(cBits - 64) - 1;
-    return pVal;
-}
-
-
-/**
  * On CPU worker for the register queries, used by dbgfR3RegNmQueryWorker.
  *
@@ -1177,8 +1128,8 @@
                 if (RT_SUCCESS(rc))
                 {
-                    dbgfR3RegU128_ShiftLeft(&pValue->u128, -pSubField->iFirstBit);
-                    dbgfR3RegU128_AndNFirstBits(&pValue->u128, pSubField->cBits);
+                    RTUInt128AssignShiftLeft(&pValue->u128, -pSubField->iFirstBit);
+                    RTUInt128AssignAndNFirstBits(&pValue->u128, pSubField->cBits);
                     if (pSubField->cShift)
-                        dbgfR3RegU128_ShiftLeft(&pValue->u128, pSubField->cShift);
+                        RTUInt128AssignShiftLeft(&pValue->u128, pSubField->cShift);
                 }
             }
Index: /trunk/src/VBox/VMM/include/CPUMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 35489)
+++ /trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 35490)
@@ -404,21 +404,25 @@
 RT_C_DECLS_BEGIN
 
-DECLASM(int)      cpumHandleLazyFPUAsm(PCPUMCPU pCPUM);
+#ifdef IN_RING3
+int                 cpumR3DbgInit(PVM pVM);
+#endif
+
+DECLASM(int)        cpumHandleLazyFPUAsm(PCPUMCPU pCPUM);
 
 #ifdef IN_RING0
-DECLASM(int)      cpumR0SaveHostRestoreGuestFPUState(PCPUMCPU pCPUM);
-DECLASM(int)      cpumR0SaveGuestRestoreHostFPUState(PCPUMCPU pCPUM);
-DECLASM(int)      cpumR0SaveHostFPUState(PCPUMCPU pCPUM);
-DECLASM(int)      cpumR0RestoreHostFPUState(PCPUMCPU pCPUM);
-DECLASM(void)     cpumR0LoadFPU(PCPUMCTX pCtx);
-DECLASM(void)     cpumR0SaveFPU(PCPUMCTX pCtx);
-DECLASM(void)     cpumR0LoadXMM(PCPUMCTX pCtx);
-DECLASM(void)     cpumR0SaveXMM(PCPUMCTX pCtx);
-DECLASM(void)     cpumR0SetFCW(uint16_t u16FCW);
-DECLASM(uint16_t) cpumR0GetFCW(void);
-DECLASM(void)     cpumR0SetMXCSR(uint32_t u32MXCSR);
-DECLASM(uint32_t) cpumR0GetMXCSR(void);
-DECLASM(void)     cpumR0LoadDRx(uint64_t const *pa4Regs);
-DECLASM(void)     cpumR0SaveDRx(uint64_t *pa4Regs);
+DECLASM(int)        cpumR0SaveHostRestoreGuestFPUState(PCPUMCPU pCPUM);
+DECLASM(int)        cpumR0SaveGuestRestoreHostFPUState(PCPUMCPU pCPUM);
+DECLASM(int)        cpumR0SaveHostFPUState(PCPUMCPU pCPUM);
+DECLASM(int)        cpumR0RestoreHostFPUState(PCPUMCPU pCPUM);
+DECLASM(void)       cpumR0LoadFPU(PCPUMCTX pCtx);
+DECLASM(void)       cpumR0SaveFPU(PCPUMCTX pCtx);
+DECLASM(void)       cpumR0LoadXMM(PCPUMCTX pCtx);
+DECLASM(void)       cpumR0SaveXMM(PCPUMCTX pCtx);
+DECLASM(void)       cpumR0SetFCW(uint16_t u16FCW);
+DECLASM(uint16_t)   cpumR0GetFCW(void);
+DECLASM(void)       cpumR0SetMXCSR(uint32_t u32MXCSR);
+DECLASM(uint32_t)   cpumR0GetMXCSR(void);
+DECLASM(void)       cpumR0LoadDRx(uint64_t const *pa4Regs);
+DECLASM(void)       cpumR0SaveDRx(uint64_t *pa4Regs);
 #endif
 
Index: /trunk/src/VBox/VMM/include/DBGFInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/DBGFInternal.h	(revision 35489)
+++ /trunk/src/VBox/VMM/include/DBGFInternal.h	(revision 35490)
@@ -271,5 +271,5 @@
     bool volatile               afAsAliasPopuplated[DBGF_AS_COUNT];
     /** Alignment padding. */
-    bool                        afAlignment[2];
+    bool                        afAlignment1[2];
 
     /** The register database lock. */
@@ -281,6 +281,8 @@
     /** The number of registers (aliases and sub-fields not counted). */
     uint32_t                    cRegs;
+    /** For early initialization by . */
+    bool volatile               fRegDbInitialized;
     /** Alignment padding. */
-    uint32_t                    Alignment2;
+    bool                        afAlignment2[3];
 
     /** The current Guest OS digger. */
