VirtualBox

Changeset 35410 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Jan 5, 2011 5:21:11 PM (14 years ago)
Author:
vboxsync
Message:

DBGFReg revamp #2.

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/CPUMDbg.cpp

    r35404 r35410  
    11/* $Id$ */
    22/** @file
    3  * DBGF - Debugger Facility, Register Methods.
     3 * CPUM - CPU Monitor / Manager, Debugger & Debugging APIs.
    44 */
    55
     
    2929
    3030
    31 /*******************************************************************************
    32 *   Defined Constants And Macros                                               *
    33 *******************************************************************************/
    34 /** @name Register and value sizes used by dbgfR3RegQueryWorker and
    35  *        dbgfR3RegSetWorker.
    36  * @{ */
    37 #define R_SZ_8          RT_BIT(0)
    38 #define R_SZ_16         RT_BIT(1)
    39 #define R_SZ_32         RT_BIT(2)
    40 #define R_SZ_64         RT_BIT(3)
    41 #define R_SZ_64_16      RT_BIT(4)
    42 #define R_SZ_80         RT_BIT(5)
    43 #define R_SZ_128        RT_BIT(6)
    44 #define R_SZ_8_TO_64    (R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64)
    45 #define R_SZ_16_TO_64   (R_SZ_16 | R_SZ_32 | R_SZ_64)
    46 #define R_SZ_32_OR_64   (R_SZ_32 | R_SZ_64)
    47 /** @}  */
    48 
    49 
    50 /*******************************************************************************
    51 *   Structures and Typedefs                                                    *
    52 *******************************************************************************/
    53 /**
    54  * Register sub-field descriptor.
    55  */
    56 typedef struct DBGFREGSUBFIELD
    57 {
    58     /** The name of the sub-field.  NULL is used to terminate the array. */
    59     const char     *pszName;
    60     /** The index of the first bit. */
    61     uint8_t         iFirstBit;
    62     /** The number of bits. */
    63     uint8_t         cBits;
    64     /** The shift count. */
    65     int8_t          cShift;
    66     /** @todo getter/setter callbacks? */
    67 } DBGFREGSUBFIELD;
    68 /** Pointer to a const register sub-field descriptor. */
    69 typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD;
    70 
    71 /**
    72  * Register alias descriptor.
    73  */
    74 typedef struct DBGFREGALIAS
    75 {
    76     /** The alias name.  NULL is used to terminate the array. */
    77     const char     *pszName;
    78     /** Set to a valid type if the alias has a different type. */
    79     DBGFREGVALTYPE  enmType;
    80 } DBGFREGALIAS;
    81 /** Pointer to a const register alias descriptor. */
    82 typedef DBGFREGALIAS const *PCDBGFREGALIAS;
    83 
    84 /**
    85  * Register descriptor.
    86  */
    87 typedef struct DBGFREGDESC
    88 {
    89     /** The normal register name. */
    90     const char             *pszName;
    91     /** The register identifier (same as the table index). */
    92     DBGFREG                 enmReg;
    93     /** The default register type. */
    94     DBGFREGVALTYPE          enmType;
    95     /** The offset info the CPUMCTX structure. ~(size_t)0 if not applicable. */
    96     size_t                  offCtx;
    97     /** Getter (optional). */
    98     DECLCALLBACKMEMBER(int, pfnGet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    99     /** Setter (optional). */
    100     DECLCALLBACKMEMBER(int, pfnSet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    101     /** Aliases (optional). */
    102     PCDBGFREGALIAS          paAliases;
    103     /** Sub fields (optional). */
    104     PCDBGFREGSUBFIELD       paSubFields;
    105 } DBGFREGDESC;
    106 /** Pointer to a const register descriptor. */
    107 typedef DBGFREGDESC const *PCDBGFREGDESC;
    108 
    109 
    110 /*******************************************************************************
    111 *   Internal Functions                                                         *
    112 *******************************************************************************/
    113 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    114 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    115 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    116 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    117 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    118 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    119 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    120 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    121 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    122 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    123 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    124 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    125 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    126 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    127 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    128 
    129 
    130 /*******************************************************************************
    131 *   Global Variables                                                           *
    132 *******************************************************************************/
     31static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     32{
     33    return VERR_NOT_IMPLEMENTED;
     34}
     35
     36static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     37{
     38    return VERR_NOT_IMPLEMENTED;
     39}
     40
     41static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     42{
     43    return VERR_NOT_IMPLEMENTED;
     44}
     45
     46static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     47{
     48    return VERR_NOT_IMPLEMENTED;
     49}
     50
     51static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     52{
     53    return VERR_NOT_IMPLEMENTED;
     54}
     55
     56static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     57{
     58    return VERR_NOT_IMPLEMENTED;
     59}
     60
     61static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     62{
     63    return VERR_NOT_IMPLEMENTED;
     64}
     65
     66static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     67{
     68    return VERR_NOT_IMPLEMENTED;
     69}
     70
     71static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     72{
     73    return VERR_NOT_IMPLEMENTED;
     74}
     75
     76static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     77{
     78    return VERR_NOT_IMPLEMENTED;
     79}
     80
     81static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     82{
     83    return VERR_NOT_IMPLEMENTED;
     84}
     85
     86static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     87{
     88    return VERR_NOT_IMPLEMENTED;
     89}
     90
     91static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     92{
     93    return VERR_NOT_IMPLEMENTED;
     94}
     95
     96static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
     97{
     98    return VERR_NOT_IMPLEMENTED;
     99}
     100
     101static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
     102{
     103    return VERR_NOT_IMPLEMENTED;
     104}
     105
     106
     107
    133108/*
    134109 * Set up aliases.
     
    564539};
    565540
    566 
    567 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    568 {
    569     return VERR_NOT_IMPLEMENTED;
    570 }
    571 
    572 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    573 {
    574     return VERR_NOT_IMPLEMENTED;
    575 }
    576 
    577 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    578 {
    579     return VERR_NOT_IMPLEMENTED;
    580 }
    581 
    582 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    583 {
    584     return VERR_NOT_IMPLEMENTED;
    585 }
    586 
    587 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    588 {
    589     return VERR_NOT_IMPLEMENTED;
    590 }
    591 
    592 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    593 {
    594     return VERR_NOT_IMPLEMENTED;
    595 }
    596 
    597 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    598 {
    599     return VERR_NOT_IMPLEMENTED;
    600 }
    601 
    602 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    603 {
    604     return VERR_NOT_IMPLEMENTED;
    605 }
    606 
    607 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    608 {
    609     return VERR_NOT_IMPLEMENTED;
    610 }
    611 
    612 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    613 {
    614     return VERR_NOT_IMPLEMENTED;
    615 }
    616 
    617 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    618 {
    619     return VERR_NOT_IMPLEMENTED;
    620 }
    621 
    622 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    623 {
    624     return VERR_NOT_IMPLEMENTED;
    625 }
    626 
    627 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    628 {
    629     return VERR_NOT_IMPLEMENTED;
    630 }
    631 
    632 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    633 {
    634     return VERR_NOT_IMPLEMENTED;
    635 }
    636 
    637 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    638 {
    639     return VERR_NOT_IMPLEMENTED;
    640 }
    641 
    642 
    643 
    644 /**
    645  * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryWorker.
    646  *
    647  * @retval  VINF_SUCCESS
    648  * @retval  VERR_DBGF_INVALID_REGISTER
    649  *
    650  * @param   pVCpu               The current CPU.
    651  * @param   pu64                Where to store the register value.
    652  * @param   pfRegSizes          Where to store the register sizes.
    653  * @param   idMsr               The MSR to get.
    654  */
    655 static uint64_t dbgfR3RegGetMsr(PVMCPU pVCpu, uint64_t *pu64, uint32_t *pfRegSizes, uint32_t idMsr)
    656 {
    657     *pfRegSizes = R_SZ_64;
    658     int rc = CPUMQueryGuestMsr(pVCpu, idMsr, pu64);
    659     if (RT_FAILURE(rc))
    660     {
    661         AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));
    662         *pu64 = 0;
    663     }
    664     return VINF_SUCCESS;
    665 }
    666 
    667 /**
    668  * Worker for DBGFR3RegQueryU8, DBGFR3RegQueryU16, DBGFR3RegQueryU32 and
    669  * DBGFR3RegQueryU64.
    670  *
    671  * @param   pVM                 The VM handle.
    672  * @param   idCpu               The target CPU ID.
    673  * @param   enmReg              The register that's being queried.
    674  * @param   pu64                Where to store the register value.
    675  * @param   pfRegSizes          Where to store the register sizes.
    676  */
    677 static DECLCALLBACK(int) dbgfR3RegQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64, uint32_t *pfRegSizes)
    678 {
    679 /** @todo rewrite this to use the register descriptors. */
    680     PVMCPU    pVCpu = &pVM->aCpus[idCpu];
    681     PCCPUMCTX pCtx  = CPUMQueryGuestCtxPtr(pVCpu);
    682     switch (enmReg)
    683     {
    684         case DBGFREG_RAX:       *pu64 = pCtx->rax;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    685         case DBGFREG_RCX:       *pu64 = pCtx->rcx;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    686         case DBGFREG_RDX:       *pu64 = pCtx->rdx;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    687         case DBGFREG_RBX:       *pu64 = pCtx->rbx;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    688         case DBGFREG_RSP:       *pu64 = pCtx->rsp;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    689         case DBGFREG_RBP:       *pu64 = pCtx->rbp;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    690         case DBGFREG_RSI:       *pu64 = pCtx->rsi;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    691         case DBGFREG_RDI:       *pu64 = pCtx->rdi;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    692         case DBGFREG_R8:        *pu64 = pCtx->r8;   *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    693         case DBGFREG_R9:        *pu64 = pCtx->r9;   *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    694         case DBGFREG_R10:       *pu64 = pCtx->r10;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    695         case DBGFREG_R11:       *pu64 = pCtx->r11;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    696         case DBGFREG_R12:       *pu64 = pCtx->r12;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    697         case DBGFREG_R13:       *pu64 = pCtx->r13;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    698         case DBGFREG_R14:       *pu64 = pCtx->r14;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    699         case DBGFREG_R15:       *pu64 = pCtx->r15;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    700 
    701         case DBGFREG_CS:        *pu64 = pCtx->cs;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    702         case DBGFREG_DS:        *pu64 = pCtx->ds;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    703         case DBGFREG_ES:        *pu64 = pCtx->es;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    704         case DBGFREG_FS:        *pu64 = pCtx->fs;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    705         case DBGFREG_GS:        *pu64 = pCtx->gs;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    706         case DBGFREG_SS:        *pu64 = pCtx->ss;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    707 
    708         case DBGFREG_CS_ATTR:   *pu64 = pCtx->csHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    709         case DBGFREG_DS_ATTR:   *pu64 = pCtx->dsHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    710         case DBGFREG_ES_ATTR:   *pu64 = pCtx->esHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    711         case DBGFREG_FS_ATTR:   *pu64 = pCtx->fsHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    712         case DBGFREG_GS_ATTR:   *pu64 = pCtx->gsHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    713         case DBGFREG_SS_ATTR:   *pu64 = pCtx->ssHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    714 
    715         case DBGFREG_CS_BASE:   *pu64 = pCtx->csHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    716         case DBGFREG_DS_BASE:   *pu64 = pCtx->dsHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    717         case DBGFREG_ES_BASE:   *pu64 = pCtx->esHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    718         case DBGFREG_FS_BASE:   *pu64 = pCtx->fsHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    719         case DBGFREG_GS_BASE:   *pu64 = pCtx->gsHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    720         case DBGFREG_SS_BASE:   *pu64 = pCtx->ssHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    721 
    722         case DBGFREG_CS_LIMIT:  *pu64 = pCtx->csHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    723         case DBGFREG_DS_LIMIT:  *pu64 = pCtx->dsHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    724         case DBGFREG_ES_LIMIT:  *pu64 = pCtx->esHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    725         case DBGFREG_FS_LIMIT:  *pu64 = pCtx->fsHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    726         case DBGFREG_GS_LIMIT:  *pu64 = pCtx->gsHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    727         case DBGFREG_SS_LIMIT:  *pu64 = pCtx->ssHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    728 
    729         case DBGFREG_RIP:       *pu64 = pCtx->rip;      *pfRegSizes = R_SZ_16_TO_64;    return VINF_SUCCESS;
    730         case DBGFREG_FLAGS:     *pu64 = pCtx->rflags.u; *pfRegSizes = R_SZ_16_TO_64;    return VINF_SUCCESS;
    731 
    732         /** @todo check fxsave/fsave format? */
    733         case DBGFREG_FCW:       *pu64 = pCtx->fpu.FCW;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    734         case DBGFREG_FSW:       *pu64 = pCtx->fpu.FSW;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    735         case DBGFREG_FTW:       *pu64 = pCtx->fpu.FTW;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    736         case DBGFREG_FOP:       *pu64 = pCtx->fpu.FOP;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    737         case DBGFREG_FPUIP:     *pu64 = pCtx->fpu.FPUIP;    *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    738         case DBGFREG_FPUCS:     *pu64 = pCtx->fpu.CS;       *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    739         case DBGFREG_FPUDP:     *pu64 = pCtx->fpu.FPUDP;    *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    740         case DBGFREG_FPUDS:     *pu64 = pCtx->fpu.DS;       *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    741         case DBGFREG_MXCSR:     *pu64 = pCtx->fpu.MXCSR;    *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    742         case DBGFREG_MXCSR_MASK:*pu64 = pCtx->fpu.MXCSR_MASK; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    743 
    744         case DBGFREG_ST0:
    745         case DBGFREG_ST1:
    746         case DBGFREG_ST2:
    747         case DBGFREG_ST3:
    748         case DBGFREG_ST4:
    749         case DBGFREG_ST5:
    750         case DBGFREG_ST6:
    751         case DBGFREG_ST7:
    752         {
    753             /** @todo check tags and fxsave/fsave format. */
    754             unsigned iReg = (pCtx->fpu.FSW >> 11) & 7;
    755             iReg += enmReg - DBGFREG_ST0;
    756             iReg &= 7;
    757 
    758             *pu64 = pCtx->fpu.aRegs[iReg].au64[0];
    759             *pfRegSizes = R_SZ_80;
    760             return VINF_SUCCESS;
    761         }
    762 
    763         case DBGFREG_MM0:
    764         case DBGFREG_MM1:
    765         case DBGFREG_MM2:
    766         case DBGFREG_MM3:
    767         case DBGFREG_MM4:
    768         case DBGFREG_MM5:
    769         case DBGFREG_MM6:
    770         case DBGFREG_MM7:
    771             *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_MM0].mmx;
    772             *pfRegSizes = R_SZ_64;
    773             return VINF_SUCCESS;
    774 
    775         case DBGFREG_XMM0:
    776         case DBGFREG_XMM1:
    777         case DBGFREG_XMM2:
    778         case DBGFREG_XMM3:
    779         case DBGFREG_XMM4:
    780         case DBGFREG_XMM5:
    781         case DBGFREG_XMM6:
    782         case DBGFREG_XMM7:
    783         case DBGFREG_XMM8:
    784         case DBGFREG_XMM9:
    785         case DBGFREG_XMM10:
    786         case DBGFREG_XMM11:
    787         case DBGFREG_XMM12:
    788         case DBGFREG_XMM13:
    789         case DBGFREG_XMM14:
    790         case DBGFREG_XMM15:
    791             *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_XMM0].au64[0];
    792             *pfRegSizes = R_SZ_128;
    793             return VINF_SUCCESS;
    794 
    795         case DBGFREG_GDTR_BASE:     *pu64 = pCtx->gdtr.pGdt;        *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    796         case DBGFREG_GDTR_LIMIT:    *pu64 = pCtx->gdtr.cbGdt;       *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    797         case DBGFREG_IDTR_BASE:     *pu64 = pCtx->idtr.pIdt;        *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    798         case DBGFREG_IDTR_LIMIT:    *pu64 = pCtx->idtr.cbIdt;       *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    799         case DBGFREG_LDTR:          *pu64 = pCtx->ldtr;             *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    800         case DBGFREG_LDTR_ATTR:     *pu64 = pCtx->ldtrHid.Attr.u;   *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    801         case DBGFREG_LDTR_BASE:     *pu64 = pCtx->ldtrHid.u64Base;  *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    802         case DBGFREG_LDTR_LIMIT:    *pu64 = pCtx->ldtrHid.u32Limit; *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    803         case DBGFREG_TR:            *pu64 = pCtx->tr;               *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    804         case DBGFREG_TR_ATTR:       *pu64 = pCtx->trHid.Attr.u;     *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    805         case DBGFREG_TR_BASE:       *pu64 = pCtx->trHid.u64Base;    *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    806         case DBGFREG_TR_LIMIT:      *pu64 = pCtx->trHid.u32Limit;   *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    807 
    808         case DBGFREG_CR0:           *pu64 = CPUMGetGuestCR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    809         case DBGFREG_CR2:           *pu64 = CPUMGetGuestCR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    810         case DBGFREG_CR3:           *pu64 = CPUMGetGuestCR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    811         case DBGFREG_CR4:           *pu64 = CPUMGetGuestCR4(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    812         case DBGFREG_CR8:           *pu64 = CPUMGetGuestCR8(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    813 
    814         case DBGFREG_DR0:           *pu64 = CPUMGetGuestDR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    815         case DBGFREG_DR1:           *pu64 = CPUMGetGuestDR1(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    816         case DBGFREG_DR2:           *pu64 = CPUMGetGuestDR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    817         case DBGFREG_DR3:           *pu64 = CPUMGetGuestDR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    818         case DBGFREG_DR6:           *pu64 = CPUMGetGuestDR6(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    819         case DBGFREG_DR7:           *pu64 = CPUMGetGuestDR7(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    820 
    821         case DBGFREG_MSR_IA32_APICBASE:     return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_APICBASE);
    822         case DBGFREG_MSR_IA32_CR_PAT:       return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_CR_PAT);
    823         case DBGFREG_MSR_IA32_PERF_STATUS:  return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_PERF_STATUS);
    824         case DBGFREG_MSR_IA32_SYSENTER_CS:  return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_CS);
    825         case DBGFREG_MSR_IA32_SYSENTER_EIP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_EIP);
    826         case DBGFREG_MSR_IA32_SYSENTER_ESP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_ESP);
    827         case DBGFREG_MSR_IA32_TSC:          return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_TSC);
    828         case DBGFREG_MSR_K6_EFER:           return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_EFER);
    829         case DBGFREG_MSR_K6_STAR:           return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_STAR);
    830         case DBGFREG_MSR_K8_CSTAR:          return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_CSTAR);
    831         case DBGFREG_MSR_K8_FS_BASE:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_FS_BASE);
    832         case DBGFREG_MSR_K8_GS_BASE:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_GS_BASE);
    833         case DBGFREG_MSR_K8_KERNEL_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_KERNEL_GS_BASE);
    834         case DBGFREG_MSR_K8_LSTAR:          return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_LSTAR);
    835         case DBGFREG_MSR_K8_SF_MASK:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_SF_MASK);
    836         case DBGFREG_MSR_K8_TSC_AUX:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_TSC_AUX);
    837 
    838         case DBGFREG_AH:        *pu64 = RT_BYTE2(pCtx->ax); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    839         case DBGFREG_CH:        *pu64 = RT_BYTE2(pCtx->cx); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    840         case DBGFREG_DH:        *pu64 = RT_BYTE2(pCtx->dx); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    841         case DBGFREG_BH:        *pu64 = RT_BYTE2(pCtx->bx); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    842         case DBGFREG_GDTR:      *pu64 = pCtx->gdtr.pGdt;    *pfRegSizes = R_SZ_64_16;   return VINF_SUCCESS;
    843         case DBGFREG_IDTR:      *pu64 = pCtx->idtr.pIdt;    *pfRegSizes = R_SZ_64_16;   return VINF_SUCCESS;
    844 
    845         case DBGFREG_END:
    846         case DBGFREG_32BIT_HACK:
    847             /* no default! We want GCC warnings. */
    848             break;
    849     }
    850 
    851     AssertMsgFailed(("%d (%#x)\n", enmReg, enmReg));
    852     return VERR_DBGF_INVALID_REGISTER;
    853 }
    854 
    855 
    856 /**
    857  * Queries a 8-bit register value.
    858  *
    859  * @retval  VINF_SUCCESS
    860  * @retval  VERR_INVALID_VM_HANDLE
    861  * @retval  VERR_INVALID_CPU_ID
    862  * @retval  VERR_DBGF_INVALID_REGISTER
    863  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    864  *
    865  * @param   pVM                 The VM handle.
    866  * @param   idCpu               The target CPU ID.
    867  * @param   enmReg              The register that's being queried.
    868  * @param   pu8                 Where to store the register value.
    869  */
    870 VMMR3DECL(int) DBGFR3RegQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8)
    871 {
    872     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    873     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    874 
    875     uint64_t u64Value;
    876     uint32_t fRegSizes;
    877     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    878     if (RT_SUCCESS(rc))
    879     {
    880         *pu8 = (uint8_t)u64Value;
    881         if (R_SZ_8 & fRegSizes)
    882             rc = VINF_SUCCESS;
    883         else
    884             rc = VINF_DBGF_TRUNCATED_REGISTER;
    885     }
    886     else
    887         *pu8 = 0;
    888     return rc;
    889 }
    890 
    891 
    892 /**
    893  * Queries a 16-bit register value.
    894  *
    895  * @retval  VINF_SUCCESS
    896  * @retval  VERR_INVALID_VM_HANDLE
    897  * @retval  VERR_INVALID_CPU_ID
    898  * @retval  VERR_DBGF_INVALID_REGISTER
    899  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    900  * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    901  *
    902  * @param   pVM                 The VM handle.
    903  * @param   idCpu               The target CPU ID.
    904  * @param   enmReg              The register that's being queried.
    905  * @param   pu16                Where to store the register value.
    906  */
    907 VMMR3DECL(int) DBGFR3RegQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16)
    908 {
    909     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    910     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    911 
    912     uint64_t u64Value;
    913     uint32_t fRegSizes;
    914     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    915     if (RT_SUCCESS(rc))
    916     {
    917         *pu16 = (uint16_t)u64Value;
    918         if (R_SZ_16 & fRegSizes)
    919             rc = VINF_SUCCESS;
    920         else if (~(R_SZ_8 | R_SZ_16) & fRegSizes)
    921             rc = VINF_DBGF_TRUNCATED_REGISTER;
    922         else
    923             rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
    924     }
    925     else
    926         *pu16 = 0;
    927     return rc;
    928 }
    929 
    930 
    931 /**
    932  * Queries a 32-bit register value.
    933  *
    934  * @retval  VINF_SUCCESS
    935  * @retval  VERR_INVALID_VM_HANDLE
    936  * @retval  VERR_INVALID_CPU_ID
    937  * @retval  VERR_DBGF_INVALID_REGISTER
    938  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    939  * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    940  *
    941  * @param   pVM                 The VM handle.
    942  * @param   idCpu               The target CPU ID.
    943  * @param   enmReg              The register that's being queried.
    944  * @param   pu32                Where to store the register value.
    945  */
    946 VMMR3DECL(int) DBGFR3RegQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32)
    947 {
    948     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    949     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    950 
    951     uint64_t u64Value;
    952     uint32_t fRegSizes;
    953     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    954     if (RT_SUCCESS(rc))
    955     {
    956         *pu32 = (uint32_t)u64Value;
    957         if (R_SZ_32 & fRegSizes)
    958             rc = VINF_SUCCESS;
    959         else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32) & fRegSizes)
    960             rc = VINF_DBGF_TRUNCATED_REGISTER;
    961         else
    962             rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
    963     }
    964     else
    965         *pu32 = 0;
    966     return rc;
    967 }
    968 
    969 
    970 /**
    971  * Queries a 64-bit register value.
    972  *
    973  * @retval  VINF_SUCCESS
    974  * @retval  VERR_INVALID_VM_HANDLE
    975  * @retval  VERR_INVALID_CPU_ID
    976  * @retval  VERR_DBGF_INVALID_REGISTER
    977  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    978  * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    979  *
    980  * @param   pVM                 The VM handle.
    981  * @param   idCpu               The target CPU ID.
    982  * @param   enmReg              The register that's being queried.
    983  * @param   pu64                Where to store the register value.
    984  */
    985 VMMR3DECL(int) DBGFR3RegQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64)
    986 {
    987     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    988     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    989 
    990     uint64_t u64Value;
    991     uint32_t fRegSizes;
    992     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    993     if (RT_SUCCESS(rc))
    994     {
    995         *pu64 = u64Value;
    996         if (R_SZ_64 & fRegSizes)
    997             rc = VINF_SUCCESS;
    998         else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) & fRegSizes)
    999             rc = VINF_DBGF_TRUNCATED_REGISTER;
    1000         else
    1001             rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
    1002     }
    1003     else
    1004         *pu64 = 0;
    1005     return rc;
    1006 }
    1007 
    1008 
    1009 /**
    1010  * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryBatchWorker.
    1011  *
    1012  * @retval  VINF_SUCCESS
    1013  * @retval  VERR_DBGF_INVALID_REGISTER
    1014  *
    1015  * @param   pVCpu               The current CPU.
    1016  * @param   pReg                The where to store the register value and
    1017  *                              size.
    1018  * @param   idMsr               The MSR to get.
    1019  */
    1020 static void dbgfR3RegGetMsrBatch(PVMCPU pVCpu, PDBGFREGENTRY pReg, uint32_t idMsr)
    1021 {
    1022     pReg->enmType = DBGFREGVALTYPE_U64;
    1023     int rc = CPUMQueryGuestMsr(pVCpu, idMsr, &pReg->Val.u64);
    1024     if (RT_FAILURE(rc))
    1025     {
    1026         AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));
    1027         pReg->Val.u64 = 0;
    1028     }
    1029 }
    1030 
    1031 
    1032 static DECLCALLBACK(int) dbgfR3RegQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
    1033 {
    1034     PVMCPU    pVCpu = &pVM->aCpus[idCpu];
    1035     PCCPUMCTX pCtx  = CPUMQueryGuestCtxPtr(pVCpu);
    1036 
    1037     PDBGFREGENTRY pReg = paRegs - 1;
    1038     while (cRegs-- > 0)
    1039     {
    1040         pReg++;
    1041         pReg->Val.au64[0] = 0;
    1042         pReg->Val.au64[1] = 0;
    1043 
    1044         DBGFREG const enmReg = pReg->enmReg;
    1045         AssertMsgReturn(enmReg >= 0 && enmReg <= DBGFREG_END, ("%d (%#x)\n", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);
    1046         if (enmReg != DBGFREG_END)
    1047         {
    1048             PCDBGFREGDESC pDesc = &g_aDbgfRegDescs[enmReg];
    1049             if (!pDesc->pfnGet)
    1050             {
    1051                 PCRTUINT128U pu = (PCRTUINT128U)((uintptr_t)pCtx + pDesc->offCtx);
    1052                 pReg->enmType = pDesc->enmType;
    1053                 switch (pDesc->enmType)
    1054                 {
    1055                     case DBGFREGVALTYPE_U8:     pReg->Val.u8   = pu->au8[0];   break;
    1056                     case DBGFREGVALTYPE_U16:    pReg->Val.u16  = pu->au16[0];  break;
    1057                     case DBGFREGVALTYPE_U32:    pReg->Val.u32  = pu->au32[0];  break;
    1058                     case DBGFREGVALTYPE_U64:    pReg->Val.u64  = pu->au64[0];  break;
    1059                     case DBGFREGVALTYPE_U128:
    1060                         pReg->Val.au64[0] = pu->au64[0];
    1061                         pReg->Val.au64[1] = pu->au64[1];
    1062                         break;
    1063                     case DBGFREGVALTYPE_LRD:
    1064                         pReg->Val.au64[0] = pu->au64[0];
    1065                         pReg->Val.au16[5] = pu->au16[5];
    1066                         break;
    1067                     default:
    1068                         AssertMsgFailedReturn(("%s %d\n", pDesc->pszName, pDesc->enmType), VERR_INTERNAL_ERROR_3);
    1069                 }
    1070             }
    1071             else
    1072             {
    1073                 int rc = pDesc->pfnGet(pVCpu, pDesc, pCtx, &pReg->Val.u);
    1074                 if (RT_FAILURE(rc))
    1075                     return rc;
    1076             }
    1077         }
    1078     }
    1079 
    1080     return VINF_SUCCESS;
    1081 }
    1082 
    1083 
    1084 /**
    1085  * Query a batch of registers.
    1086  *
    1087  * @retval  VINF_SUCCESS
    1088  * @retval  VERR_INVALID_VM_HANDLE
    1089  * @retval  VERR_INVALID_CPU_ID
    1090  * @retval  VERR_DBGF_INVALID_REGISTER
    1091  *
    1092  * @param   pVM                 The VM handle.
    1093  * @param   idCpu               The target CPU ID.
    1094  * @param   paRegs              Pointer to an array of @a cRegs elements.  On
    1095  *                              input the enmReg members indicates which
    1096  *                              registers to query.  On successful return the
    1097  *                              other members are set.  DBGFREG_END can be used
    1098  *                              as a filler.
    1099  * @param   cRegs               The number of entries in @a paRegs.
    1100  */
    1101 VMMR3DECL(int) DBGFR3RegQueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
    1102 {
    1103     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    1104     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    1105     if (!cRegs)
    1106         return VINF_SUCCESS;
    1107     AssertReturn(cRegs < _1M, VERR_OUT_OF_RANGE);
    1108     AssertPtrReturn(paRegs, VERR_INVALID_POINTER);
    1109     size_t iReg = cRegs;
    1110     while (iReg-- > 0)
    1111     {
    1112         DBGFREG enmReg = paRegs[iReg].enmReg;
    1113         AssertMsgReturn(enmReg < DBGFREG_END && enmReg >= DBGFREG_AL, ("%d (%#x)", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);
    1114     }
    1115 
    1116     return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
    1117 }
    1118 
    1119 
    1120 /**
    1121  * Query a all registers for a Virtual CPU.
    1122  *
    1123  * @retval  VINF_SUCCESS
    1124  * @retval  VERR_INVALID_VM_HANDLE
    1125  * @retval  VERR_INVALID_CPU_ID
    1126  *
    1127  * @param   pVM                 The VM handle.
    1128  * @param   idCpu               The target CPU ID.
    1129  * @param   paRegs              Pointer to an array of @a cRegs elements.
    1130  *                              These will be filled with the CPU register
    1131  *                              values. Overflowing entries will be set to
    1132  *                              DBGFREG_END.  The returned registers can be
    1133  *                              accessed by using the DBGFREG values as index.
    1134  * @param   cRegs               The number of entries in @a paRegs.  The
    1135  *                              recommended value is DBGFREG_ALL_COUNT.
    1136  */
    1137 VMMR3DECL(int) DBGFR3RegQueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
    1138 {
    1139     /*
    1140      * Validate input.
    1141      */
    1142     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    1143     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    1144     if (!cRegs)
    1145         return VINF_SUCCESS;
    1146     AssertReturn(cRegs < _1M, VERR_OUT_OF_RANGE);
    1147     AssertPtrReturn(paRegs, VERR_INVALID_POINTER);
    1148 
    1149     /*
    1150      * Convert it into a batch query (lazy bird).
    1151      */
    1152     unsigned iReg = 0;
    1153     while (iReg < cRegs && iReg < DBGFREG_ALL_COUNT)
    1154     {
    1155         paRegs[iReg].enmReg = (DBGFREG)iReg;
    1156         iReg++;
    1157     }
    1158     while (iReg < cRegs)
    1159         paRegs[iReg++].enmReg = DBGFREG_END;
    1160 
    1161     return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
    1162 }
    1163 
    1164 
    1165 
    1166 /**
    1167  * Gets the name of a register.
    1168  *
    1169  * @returns Pointer to read-only register name (lower case).  NULL if the
    1170  *          parameters are invalid.
    1171  * @param   enmReg              The register identifier.
    1172  * @param   enmType             The register type.  This is for sort out
    1173  *                              aliases.  Pass DBGFREGVALTYPE_INVALID to get
    1174  *                              the standard name.
    1175  */
    1176 VMMR3DECL(const char *) DBGFR3RegName(DBGFREG enmReg, DBGFREGVALTYPE enmType)
    1177 {
    1178     AssertReturn(enmReg >= DBGFREG_AL && enmReg < DBGFREG_END, NULL);
    1179     AssertReturn(enmType >= DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, NULL);
    1180 
    1181     PCDBGFREGDESC   pDesc  = &g_aDbgfRegDescs[enmReg];
    1182     PCDBGFREGALIAS  pAlias = pDesc->paAliases;
    1183     if (   pAlias
    1184         && pDesc->enmType != enmType
    1185         && enmType != DBGFREGVALTYPE_INVALID)
    1186     {
    1187         while (pAlias->pszName)
    1188         {
    1189             if (pAlias->enmType == enmType)
    1190                 return pAlias->pszName;
    1191             pAlias++;
    1192         }
    1193     }
    1194 
    1195     return pDesc->pszName;
    1196 }
    1197 
  • trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp

    r35351 r35410  
    2323#include <VBox/vmm/dbgf.h>
    2424#include "DBGFInternal.h"
     25#include <VBox/vmm/mm.h>
    2526#include <VBox/vmm/vm.h>
    2627#include <VBox/param.h>
    2728#include <VBox/err.h>
    2829#include <VBox/log.h>
     30#include <iprt/ctype.h>
     31#include <iprt/string.h>
    2932
    3033
     
    3235*   Defined Constants And Macros                                               *
    3336*******************************************************************************/
    34 /** @name Register and value sizes used by dbgfR3RegQueryWorker and
    35  *        dbgfR3RegSetWorker.
    36  * @{ */
    37 #define R_SZ_8          RT_BIT(0)
    38 #define R_SZ_16         RT_BIT(1)
    39 #define R_SZ_32         RT_BIT(2)
    40 #define R_SZ_64         RT_BIT(3)
    41 #define R_SZ_64_16      RT_BIT(4)
    42 #define R_SZ_80         RT_BIT(5)
    43 #define R_SZ_128        RT_BIT(6)
    44 #define R_SZ_8_TO_64    (R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64)
    45 #define R_SZ_16_TO_64   (R_SZ_16 | R_SZ_32 | R_SZ_64)
    46 #define R_SZ_32_OR_64   (R_SZ_32 | R_SZ_64)
    47 /** @}  */
     37/** Locks the register database for writing. */
     38#define DBGF_REG_DB_LOCK_WRITE(pVM) \
     39    do { \
     40        int rcSem = RTSemRWRequestWrite((pVM)->dbgf.s.hRegDbLock, RT_INDEFINITE_WAIT); \
     41        AssertRC(rcSem); \
     42    } while (0)
     43
     44/** Unlocks the register database after writing. */
     45#define DBGF_REG_DB_UNLOCK_WRITE(pVM) \
     46    do { \
     47        int rcSem = RTSemRWReleaseWrite((pVM)->dbgf.s.hRegDbLock); \
     48        AssertRC(rcSem); \
     49    } while (0)
     50
     51/** Locks the register database for reading. */
     52#define DBGF_REG_DB_LOCK_READ(pVM) \
     53    do { \
     54        int rcSem = RTSemRWRequestRead((pVM)->dbgf.s.hRegDbLock, RT_INDEFINITE_WAIT); \
     55        AssertRC(rcSem); \
     56    } while (0)
     57
     58/** Unlocks the register database after reading. */
     59#define DBGF_REG_DB_UNLOCK_READ(pVM) \
     60    do { \
     61        int rcSem = RTSemRWReleaseRead((pVM)->dbgf.s.hRegDbLock); \
     62        AssertRC(rcSem); \
     63    } while (0)
     64
    4865
    4966
     
    5269*******************************************************************************/
    5370/**
    54  * Register sub-field descriptor.
    55  */
    56 typedef struct DBGFREGSUBFIELD
    57 {
    58     /** The name of the sub-field.  NULL is used to terminate the array. */
    59     const char     *pszName;
    60     /** The index of the first bit. */
    61     uint8_t         iFirstBit;
    62     /** The number of bits. */
    63     uint8_t         cBits;
    64     /** The shift count. */
    65     int8_t          cShift;
    66     /** @todo getter/setter callbacks? */
    67 } DBGFREGSUBFIELD;
    68 /** Pointer to a const register sub-field descriptor. */
    69 typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD;
    70 
    71 /**
    72  * Register alias descriptor.
    73  */
    74 typedef struct DBGFREGALIAS
    75 {
    76     /** The alias name.  NULL is used to terminate the array. */
    77     const char     *pszName;
    78     /** Set to a valid type if the alias has a different type. */
    79     DBGFREGVALTYPE  enmType;
    80 } DBGFREGALIAS;
    81 /** Pointer to a const register alias descriptor. */
    82 typedef DBGFREGALIAS const *PCDBGFREGALIAS;
    83 
    84 /**
    85  * Register descriptor.
    86  */
    87 typedef struct DBGFREGDESC
    88 {
    89     /** The normal register name. */
    90     const char             *pszName;
    91     /** The register identifier (same as the table index). */
    92     DBGFREG                 enmReg;
    93     /** The default register type. */
    94     DBGFREGVALTYPE          enmType;
    95     /** The offset info the CPUMCTX structure. ~(size_t)0 if not applicable. */
    96     size_t                  offCtx;
    97     /** Getter (optional). */
    98     DECLCALLBACKMEMBER(int, pfnGet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    99     /** Setter (optional). */
    100     DECLCALLBACKMEMBER(int, pfnSet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    101     /** Aliases (optional). */
    102     PCDBGFREGALIAS          paAliases;
    103     /** Sub fields (optional). */
    104     PCDBGFREGSUBFIELD       paSubFields;
    105 } DBGFREGDESC;
    106 /** Pointer to a const register descriptor. */
    107 typedef DBGFREGDESC const *PCDBGFREGDESC;
    108 
    109 
    110 /*******************************************************************************
    111 *   Internal Functions                                                         *
    112 *******************************************************************************/
    113 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    114 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    115 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    116 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    117 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    118 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    119 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    120 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    121 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    122 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    123 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    124 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    125 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    126 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
    127 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
    128 
    129 
    130 /*******************************************************************************
    131 *   Global Variables                                                           *
    132 *******************************************************************************/
    133 /*
    134  * Set up aliases.
    135  */
    136 #define DBGFREGALIAS_STD(Name, psz32, psz16, psz8)  \
    137     static DBGFREGALIAS const g_aDbgfRegAliases_##Name[] = \
    138     { \
    139         { psz32, DBGFREGVALTYPE_U32    }, \
    140         { psz16, DBGFREGVALTYPE_U16    }, \
    141         { psz8,  DBGFREGVALTYPE_U8     }, \
    142         { NULL, DBGFREGVALTYPE_INVALID } \
     71 * Register set registration record type.
     72 */
     73typedef enum DBGFREGSETTYPE
     74{
     75    /** Invalid zero value. */
     76    DBGFREGSETTYPE_INVALID = 0,
     77    /** CPU record. */
     78    DBGFREGSETTYPE_CPU,
     79    /** Device record. */
     80    DBGFREGSETTYPE_DEVICE,
     81    /** End of valid record types. */
     82    DBGFREGSETTYPE_END
     83} DBGFREGSETTYPE;
     84
     85
     86/**
     87 * Register set registration record.
     88 */
     89typedef struct DBGFREGSET
     90{
     91    /** String space core. */
     92    RTSTRSPACECORE          Core;
     93    /** The registration record type. */
     94    DBGFREGSETTYPE       enmType;
     95    /** The user argument for the callbacks. */
     96    union
     97    {
     98        /** The CPU view. */
     99        PVMCPU              pVCpu;
     100        /** The device view. */
     101        PPDMDEVINS          pDevIns;
     102        /** The general view. */
     103        void               *pv;
     104    } uUserArg;
     105
     106    /** The register descriptors. */
     107    PCDBGFREGDESC           paDescs;
     108    /** The number of register descriptors. */
     109    size_t                  cDescs;
     110
     111    /** The register name prefix. */
     112    char                    szPrefix[32];
     113} DBGFREGSET;
     114/** Pointer to a register registration record. */
     115typedef DBGFREGSET *PDBGFREGSET;
     116
     117
     118/**
     119 * Validates a register name.
     120 *
     121 * This is used for prefixes, aliases and field names.
     122 *
     123 * @returns true if valid, false if not.
     124 * @param   pszName             The register name to validate.
     125 */
     126static bool dbgfR3RegIsNameValid(const char *pszName)
     127{
     128    if (!RT_C_IS_ALPHA(*pszName))
     129        return false;
     130    char ch;
     131    while ((ch = *++pszName))
     132        if (   !RT_C_IS_LOWER(ch)
     133            && !RT_C_IS_DIGIT(ch)
     134            && ch != '_')
     135            return false;
     136    return true;
     137}
     138
     139
     140/**
     141 * Common worker for registering a register set.
     142 *
     143 * @returns VBox status code.
     144 * @param   pVM                 The VM handle.
     145 * @param   paRegisters         The register descriptors.
     146 * @param   enmType             The set type.
     147 * @param   pvUserArg           The user argument for the callbacks.
     148 * @param   pszPrefix           The name prefix.
     149 * @param   iInstance           The instance number to be appended to @a
     150 *                              pszPrefix when creating the set name.
     151 */
     152static int dbgfR3RegRegisterCommon(PVM pVM, PCDBGFREGDESC paRegisters, DBGFREGSETTYPE enmType, void *pvUserArg, const char *pszPrefix, uint32_t iInstance)
     153{
     154    /*
     155     * Validate input.
     156     */
     157    /* The name components. */
     158    AssertMsgReturn(dbgfR3RegIsNameValid(pszPrefix), ("%s\n", pszPrefix), VERR_INVALID_NAME);
     159    const char  *psz             = RTStrEnd(pszPrefix, RTSTR_MAX);
     160    bool const   fNeedUnderscore = RT_C_IS_DIGIT(psz[-1]);
     161    size_t const cchPrefix       = psz - pszPrefix + fNeedUnderscore;
     162    AssertMsgReturn(cchPrefix < RT_SIZEOFMEMB(DBGFREGSET, szPrefix) - 4 - 1, ("%s\n", pszPrefix), VERR_INVALID_NAME);
     163
     164    AssertMsgReturn(iInstance <= 9999, ("%d\n", iInstance), VERR_INVALID_NAME);
     165
     166    /* The descriptors. */
     167    uint32_t iDesc;
     168    for (iDesc = 0; paRegisters[iDesc].pszName != NULL; iDesc++)
     169    {
     170        AssertMsgReturn(dbgfR3RegIsNameValid(paRegisters[iDesc].pszName), ("%s (#%u)\n", paRegisters[iDesc].pszName, iDesc), VERR_INVALID_NAME);
     171
     172        if (enmType == DBGFREGSETTYPE_CPU)
     173            AssertMsgReturn((unsigned)paRegisters[iDesc].enmReg == iDesc && iDesc < (unsigned)DBGFREG_END,
     174                            ("%d iDesc=%d\n", paRegisters[iDesc].enmReg, iDesc),
     175                            VERR_INVALID_PARAMETER);
     176        else
     177            AssertReturn(paRegisters[iDesc].enmReg == DBGFREG_END, VERR_INVALID_PARAMETER);
     178        AssertReturn(   paRegisters[iDesc].enmType > DBGFREGVALTYPE_INVALID
     179                     && paRegisters[iDesc].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
     180        AssertMsgReturn(paRegisters[iDesc].fFlags & ~DBGFREG_FLAGS_READ_ONLY,
     181                        ("%#x (#%u)\n", paRegisters[iDesc].fFlags, iDesc),
     182                        VERR_INVALID_PARAMETER);
     183        AssertPtrReturn(paRegisters[iDesc].pfnGet, VERR_INVALID_PARAMETER);
     184        AssertPtrReturn(paRegisters[iDesc].pfnSet, VERR_INVALID_PARAMETER);
     185
     186        PCDBGFREGALIAS paAliases = paRegisters[iDesc].paAliases;
     187        if (paAliases)
     188        {
     189            AssertPtrReturn(paAliases, VERR_INVALID_PARAMETER);
     190            for (uint32_t j = 0; paAliases[j].pszName; j++)
     191            {
     192                AssertMsgReturn(dbgfR3RegIsNameValid(paAliases[j].pszName), ("%s (%s)\n", paAliases[j].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
     193                AssertReturn(   paAliases[j].enmType > DBGFREGVALTYPE_INVALID
     194                             && paAliases[j].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
     195            }
     196        }
     197
     198        PCDBGFREGSUBFIELD paSubFields = paRegisters[iDesc].paSubFields;
     199        if (paSubFields)
     200        {
     201            AssertPtrReturn(paSubFields, VERR_INVALID_PARAMETER);
     202            for (uint32_t j = 0; paSubFields[j].pszName; j++)
     203            {
     204                AssertMsgReturn(dbgfR3RegIsNameValid(paSubFields[j].pszName), ("%s (%s)\n", paSubFields[j].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
     205                AssertReturn(paSubFields[j].iFirstBit + paSubFields[j].cBits <= 128, VERR_INVALID_PARAMETER);
     206                AssertReturn(paSubFields[j].cBits + paSubFields[j].cShift <= 128, VERR_INVALID_PARAMETER);
     207                AssertPtrNullReturn(paSubFields[j].pfnGet, VERR_INVALID_POINTER);
     208                AssertPtrNullReturn(paSubFields[j].pfnSet, VERR_INVALID_POINTER);
     209            }
     210        }
    143211    }
    144 DBGFREGALIAS_STD(rax,  "eax",   "ax",   "al");
    145 DBGFREGALIAS_STD(rcx,  "ecx",   "cx",   "cl");
    146 DBGFREGALIAS_STD(rdx,  "edx",   "dx",   "dl");
    147 DBGFREGALIAS_STD(rbx,  "ebx",   "bx",   "bl");
    148 DBGFREGALIAS_STD(rsp,  "esp",   "sp",   NULL);
    149 DBGFREGALIAS_STD(rbp,  "ebp",   "bp",   NULL);
    150 DBGFREGALIAS_STD(rsi,  "esi",   "si",  "sil");
    151 DBGFREGALIAS_STD(rdi,  "edi",   "di",  "dil");
    152 DBGFREGALIAS_STD(r8,   "r8d",  "r8w",  "r8b");
    153 DBGFREGALIAS_STD(r9,   "r9d",  "r9w",  "r9b");
    154 DBGFREGALIAS_STD(r10, "r10d", "r10w", "r10b");
    155 DBGFREGALIAS_STD(r11, "r11d", "r11w", "r11b");
    156 DBGFREGALIAS_STD(r12, "r12d", "r12w", "r12b");
    157 DBGFREGALIAS_STD(r13, "r13d", "r13w", "r13b");
    158 DBGFREGALIAS_STD(r14, "r14d", "r14w", "r14b");
    159 DBGFREGALIAS_STD(r15, "r15d", "r15w", "r15b");
    160 DBGFREGALIAS_STD(rip, "eip",   "ip",    NULL);
    161 DBGFREGALIAS_STD(rflags, "eflags", "flags", NULL);
    162 #undef DBGFREGALIAS_STD
    163 
    164 static DBGFREGALIAS const g_aDbgfRegAliases_fpuip[] =
    165 {
    166     { "fpuip", DBGFREGVALTYPE_U16  },
    167     { NULL, DBGFREGVALTYPE_INVALID }
    168 };
    169 
    170 static DBGFREGALIAS const g_aDbgfRegAliases_fpudp[] =
    171 {
    172     { "fpudp", DBGFREGVALTYPE_U16  },
    173     { NULL, DBGFREGVALTYPE_INVALID }
    174 };
    175 
    176 static DBGFREGALIAS const g_aDbgfRegAliases_cr0[] =
    177 {
    178     { "msw", DBGFREGVALTYPE_U16  },
    179     { NULL, DBGFREGVALTYPE_INVALID }
    180 };
    181 
    182 /*
    183  * Sub fields.
    184  */
    185 /** Sub-fields for the (hidden) segment attribute register. */
    186 static DBGFREGSUBFIELD const g_aDbgfRegFields_seg[] =
    187 {
    188     { "type",   0,   4,  0 },
    189     { "s",      4,   1,  0 },
    190     { "dpl",    5,   2,  0 },
    191     { "p",      7,   1,  0 },
    192     { "avl",   12,   1,  0 },
    193     { "l",     13,   1,  0 },
    194     { "d",     14,   1,  0 },
    195     { "g",     15,   1,  0 },
    196     { NULL,     0,   0,  0 }
    197 };
    198 
    199 /** Sub-fields for the flags register. */
    200 static DBGFREGSUBFIELD const g_aDbgfRegFields_rflags[] =
    201 {
    202     { "cf",     0,   1,  0 },
    203     { "pf",     2,   1,  0 },
    204     { "af",     4,   1,  0 },
    205     { "zf",     6,   1,  0 },
    206     { "sf",     7,   1,  0 },
    207     { "tf",     8,   1,  0 },
    208     { "if",     9,   1,  0 },
    209     { "df",    10,   1,  0 },
    210     { "of",    11,   1,  0 },
    211     { "iopl",  12,   2,  0 },
    212     { "nt",    14,   1,  0 },
    213     { "rf",    16,   1,  0 },
    214     { "vm",    17,   1,  0 },
    215     { "ac",    18,   1,  0 },
    216     { "vif",   19,   1,  0 },
    217     { "vip",   20,   1,  0 },
    218     { "id",    21,   1,  0 },
    219     { NULL,     0,   0,  0 }
    220 };
    221 
    222 /** Sub-fields for the FPU control word register. */
    223 static DBGFREGSUBFIELD const g_aDbgfRegFields_fcw[] =
    224 {
    225     { "im",     1,   1,  0 },
    226     { "dm",     2,   1,  0 },
    227     { "zm",     3,   1,  0 },
    228     { "om",     4,   1,  0 },
    229     { "um",     5,   1,  0 },
    230     { "pm",     6,   1,  0 },
    231     { "pc",     8,   2,  0 },
    232     { "rc",    10,   2,  0 },
    233     { "x",     12,   1,  0 },
    234     { NULL,     0,   0,  0 }
    235 };
    236 
    237 /** Sub-fields for the FPU status word register. */
    238 static DBGFREGSUBFIELD const g_aDbgfRegFields_fsw[] =
    239 {
    240     { "ie",     0,   1,  0 },
    241     { "de",     1,   1,  0 },
    242     { "ze",     2,   1,  0 },
    243     { "oe",     3,   1,  0 },
    244     { "ue",     4,   1,  0 },
    245     { "pe",     5,   1,  0 },
    246     { "se",     6,   1,  0 },
    247     { "es",     7,   1,  0 },
    248     { "c0",     8,   1,  0 },
    249     { "c1",     9,   1,  0 },
    250     { "c2",    10,   1,  0 },
    251     { "top",   11,   3,  0 },
    252     { "c3",    14,   1,  0 },
    253     { "b",     15,   1,  0 },
    254     { NULL,     0,   0,  0 }
    255 };
    256 
    257 /** Sub-fields for the FPU tag word register. */
    258 static DBGFREGSUBFIELD const g_aDbgfRegFields_ftw[] =
    259 {
    260     { "tag0",   0,   2,  0 },
    261     { "tag1",   2,   2,  0 },
    262     { "tag2",   4,   2,  0 },
    263     { "tag3",   6,   2,  0 },
    264     { "tag4",   8,   2,  0 },
    265     { "tag5",  10,   2,  0 },
    266     { "tag6",  12,   2,  0 },
    267     { "tag7",  14,   2,  0 },
    268     { NULL,     0,   0,  0 }
    269 };
    270 
    271 /** Sub-fields for the Multimedia Extensions Control and Status Register. */
    272 static DBGFREGSUBFIELD const g_aDbgfRegFields_mxcsr[] =
    273 {
    274     { "ie",     0,   1,  0 },
    275     { "de",     1,   1,  0 },
    276     { "ze",     2,   1,  0 },
    277     { "oe",     3,   1,  0 },
    278     { "ue",     4,   1,  0 },
    279     { "pe",     5,   1,  0 },
    280     { "daz",    6,   1,  0 },
    281     { "im",     7,   1,  0 },
    282     { "dm",     8,   1,  0 },
    283     { "zm",     9,   1,  0 },
    284     { "om",    10,   1,  0 },
    285     { "um",    11,   1,  0 },
    286     { "pm",    12,   1,  0 },
    287     { "rc",    13,   2,  0 },
    288     { "fz",    14,   1,  0 },
    289     { NULL,     0,   0,  0 }
    290 };
    291 
    292 /** Sub-fields for the FPU tag word register. */
    293 static DBGFREGSUBFIELD const g_aDbgfRegFields_stN[] =
    294 {
    295     { "man",    0,  64,  0 },
    296     { "exp",   64,  15,  0 },
    297     { "sig",   79,   1,  0 },
    298     { NULL,     0,   0,  0 }
    299 };
    300 
    301 /** Sub-fields for the MMX registers. */
    302 static DBGFREGSUBFIELD const g_aDbgfRegFields_mmN[] =
    303 {
    304     { "dw0",    0,  32,  0 },
    305     { "dw1",   32,  32,  0 },
    306     { "w0",     0,  16,  0 },
    307     { "w1",    16,  16,  0 },
    308     { "w2",    32,  16,  0 },
    309     { "w3",    48,  16,  0 },
    310     { "b0",     0,   8,  0 },
    311     { "b1",     8,   8,  0 },
    312     { "b2",    16,   8,  0 },
    313     { "b3",    24,   8,  0 },
    314     { "b4",    32,   8,  0 },
    315     { "b5",    40,   8,  0 },
    316     { "b6",    48,   8,  0 },
    317     { "b7",    56,   8,  0 },
    318     { NULL,     0,   0,  0 }
    319 };
    320 
    321 /** Sub-fields for the XMM registers. */
    322 static DBGFREGSUBFIELD const g_aDbgfRegFields_xmmN[] =
    323 {
    324     { "r0",      0,     32,  0 },
    325     { "r0.man",  0+ 0,  23,  0 },
    326     { "r0.exp",  0+23,   8,  0 },
    327     { "r0.sig",  0+31,   1,  0 },
    328     { "r1",     32,     32,  0 },
    329     { "r1.man", 32+ 0,  23,  0 },
    330     { "r1.exp", 32+23,   8,  0 },
    331     { "r1.sig", 32+31,   1,  0 },
    332     { "r2",     64,     32,  0 },
    333     { "r2.man", 64+ 0,  23,  0 },
    334     { "r2.exp", 64+23,   8,  0 },
    335     { "r2.sig", 64+31,   1,  0 },
    336     { "r3",     96,     32,  0 },
    337     { "r3.man", 96+ 0,  23,  0 },
    338     { "r3.exp", 96+23,   8,  0 },
    339     { "r3.sig", 96+31,   1,  0 },
    340     { NULL,      0,      0,  0 }
    341 };
    342 
    343 /** Sub-fields for the CR0 register. */
    344 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr0[] =
    345 {
    346     /** @todo  */
    347     { NULL,      0,      0,  0 }
    348 };
    349 
    350 /** Sub-fields for the CR3 register. */
    351 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr3[] =
    352 {
    353     /** @todo  */
    354     { NULL,      0,      0,  0 }
    355 };
    356 
    357 /** Sub-fields for the CR4 register. */
    358 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr4[] =
    359 {
    360     /** @todo  */
    361     { NULL,      0,      0,  0 }
    362 };
    363 
    364 /** Sub-fields for the DR6 register. */
    365 static DBGFREGSUBFIELD const g_aDbgfRegFields_dr6[] =
    366 {
    367     /** @todo  */
    368     { NULL,      0,      0,  0 }
    369 };
    370 
    371 /** Sub-fields for the DR7 register. */
    372 static DBGFREGSUBFIELD const g_aDbgfRegFields_dr7[] =
    373 {
    374     /** @todo  */
    375     { NULL,      0,      0,  0 }
    376 };
    377 
    378 /** Sub-fields for the CR_PAT MSR. */
    379 static DBGFREGSUBFIELD const g_aDbgfRegFields_apic_base[] =
    380 {
    381     { "bsp",     8,      1,  0 },
    382     { "ge",      9,      1,  0 },
    383     { "base",    12,    20, 12 },
    384     { NULL,      0,      0,  0 }
    385 };
    386 
    387 /** Sub-fields for the CR_PAT MSR. */
    388 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr_pat[] =
    389 {
    390     /** @todo  */
    391     { NULL,      0,      0,  0 }
    392 };
    393 
    394 /** Sub-fields for the PERF_STATUS MSR. */
    395 static DBGFREGSUBFIELD const g_aDbgfRegFields_perf_status[] =
    396 {
    397     /** @todo  */
    398     { NULL,      0,      0,  0 }
    399 };
    400 
    401 /** Sub-fields for the EFER MSR. */
    402 static DBGFREGSUBFIELD const g_aDbgfRegFields_efer[] =
    403 {
    404     /** @todo  */
    405     { NULL,      0,      0,  0 }
    406 };
    407 
    408 /** Sub-fields for the STAR MSR. */
    409 static DBGFREGSUBFIELD const g_aDbgfRegFields_star[] =
    410 {
    411     /** @todo  */
    412     { NULL,      0,      0,  0 }
    413 };
    414 
    415 /** Sub-fields for the CSTAR MSR. */
    416 static DBGFREGSUBFIELD const g_aDbgfRegFields_cstar[] =
    417 {
    418     /** @todo  */
    419     { NULL,      0,      0,  0 }
    420 };
    421 
    422 /** Sub-fields for the LSTAR MSR. */
    423 static DBGFREGSUBFIELD const g_aDbgfRegFields_lstar[] =
    424 {
    425     /** @todo  */
    426     { NULL,      0,      0,  0 }
    427 };
    428 
    429 /** Sub-fields for the SF_MASK MSR. */
    430 static DBGFREGSUBFIELD const g_aDbgfRegFields_sf_mask[] =
    431 {
    432     /** @todo  */
    433     { NULL,      0,      0,  0 }
    434 };
    435 
    436 
    437 
    438 /**
    439  * The register descriptors.
    440  */
    441 static DBGFREGDESC const g_aDbgfRegDescs[] =
    442 {
    443 #define DBGFREGDESC_REG(UName, LName) \
    444     { #LName, DBGFREG_##UName, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, LName), NULL, NULL, g_aDbgfRegAliases_##LName, NULL }
    445     DBGFREGDESC_REG(RAX, rax),
    446     DBGFREGDESC_REG(RCX, rcx),
    447     DBGFREGDESC_REG(RDX, rdx),
    448     DBGFREGDESC_REG(RSP, rsp),
    449     DBGFREGDESC_REG(RBP, rbp),
    450     DBGFREGDESC_REG(RSI, rsi),
    451     DBGFREGDESC_REG(RDI, rdi),
    452     DBGFREGDESC_REG(R8,   r8),
    453     DBGFREGDESC_REG(R9,   r9),
    454     DBGFREGDESC_REG(R10, r10),
    455     DBGFREGDESC_REG(R11, r11),
    456     DBGFREGDESC_REG(R12, r12),
    457     DBGFREGDESC_REG(R13, r13),
    458     DBGFREGDESC_REG(R14, r14),
    459     DBGFREGDESC_REG(R15, r15),
    460 #define DBGFREGDESC_SEG(UName, LName) \
    461     { #LName,         DBGFREG_##UName,        DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, LName),               NULL, dbgfR3RegSet_seg, NULL, NULL },  \
    462     { #LName "_attr", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, LName##Hid.Attr.u),   NULL, NULL, NULL, g_aDbgfRegFields_seg }, \
    463     { #LName "_base", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, LName##Hid.u64Base),  NULL, NULL, NULL, NULL }, \
    464     { #LName "_lim",  DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, LName##Hid.u32Limit), NULL, NULL, NULL, NULL }
    465     DBGFREGDESC_SEG(CS, cs),
    466     DBGFREGDESC_SEG(DS, ds),
    467     DBGFREGDESC_SEG(ES, es),
    468     DBGFREGDESC_SEG(FS, fs),
    469     DBGFREGDESC_SEG(GS, gs),
    470     DBGFREGDESC_SEG(SS, ss),
    471     DBGFREGDESC_REG(RIP, rip),
    472     { "rflags",     DBGFREG_RFLAGS,     DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, rflags),           NULL, NULL, g_aDbgfRegAliases_rflags, g_aDbgfRegFields_rflags },
    473     { "fcw",        DBGFREG_FCW,        DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FCW),          NULL, NULL, NULL, g_aDbgfRegFields_fcw },
    474     { "fsw",        DBGFREG_FSW,        DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FSW),          NULL, NULL, NULL, g_aDbgfRegFields_fsw },
    475     { "ftw",        DBGFREG_FTW,        DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FTW), dbgfR3RegGet_ftw, dbgfR3RegSet_ftw, NULL, g_aDbgfRegFields_ftw },
    476     { "fop",        DBGFREG_FOP,        DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FOP),          NULL, NULL, NULL, NULL },
    477     { "fpuip",      DBGFREG_FPUIP,      DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.FPUIP),        NULL, NULL, g_aDbgfRegAliases_fpuip, NULL },
    478     { "fpucs",      DBGFREG_FPUCS,      DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.CS),           NULL, NULL, NULL, NULL },
    479     { "fpudp",      DBGFREG_FPUDP,      DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.FPUDP),        NULL, NULL, g_aDbgfRegAliases_fpudp, NULL },
    480     { "fpuds",      DBGFREG_FPUDS,      DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.DS),           NULL, NULL, NULL, NULL },
    481     { "mxcsr",      DBGFREG_MXCSR,      DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.MXCSR),        NULL, NULL, NULL, g_aDbgfRegFields_mxcsr },
    482     { "mxcsr_mask", DBGFREG_MXCSR_MASK, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.MXCSR_MASK),   NULL, NULL, NULL, g_aDbgfRegFields_mxcsr },
    483 #define DBGFREGDESC_ST(n) \
    484     { "st" #n,      DBGFREG_ST##n,      DBGFREGVALTYPE_80, ~(size_t)0, dbgfR3RegGet_stN, dbgfR3RegSet_stN, NULL, g_aDbgfRegFields_stN }
    485     DBGFREGDESC_ST(0),
    486     DBGFREGDESC_ST(1),
    487     DBGFREGDESC_ST(2),
    488     DBGFREGDESC_ST(3),
    489     DBGFREGDESC_ST(4),
    490     DBGFREGDESC_ST(5),
    491     DBGFREGDESC_ST(6),
    492     DBGFREGDESC_ST(7),
    493 #define DBGFREGDESC_MM(n) \
    494     { "mm" #n,      DBGFREG_MM##n,      DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, fpu.aRegs[n].mmx), NULL, NULL, NULL, g_aDbgfRegFields_mmN }
    495     DBGFREGDESC_MM(0),
    496     DBGFREGDESC_MM(1),
    497     DBGFREGDESC_MM(2),
    498     DBGFREGDESC_MM(3),
    499     DBGFREGDESC_MM(4),
    500     DBGFREGDESC_MM(5),
    501     DBGFREGDESC_MM(6),
    502     DBGFREGDESC_MM(7),
    503 #define DBGFREGDESC_XMM(n) \
    504     { "xmm" #n,     DBGFREG_XMM##n,     DBGFREGVALTYPE_U128, RT_OFFSETOF(CPUMCTX, fpu.aXMM[n].xmm), NULL, NULL, NULL, g_aDbgfRegFields_xmmN }
    505     DBGFREGDESC_XMM(0),
    506     DBGFREGDESC_XMM(1),
    507     DBGFREGDESC_XMM(2),
    508     DBGFREGDESC_XMM(3),
    509     DBGFREGDESC_XMM(4),
    510     DBGFREGDESC_XMM(5),
    511     DBGFREGDESC_XMM(6),
    512     DBGFREGDESC_XMM(7),
    513     DBGFREGDESC_XMM(8),
    514     DBGFREGDESC_XMM(9),
    515     DBGFREGDESC_XMM(10),
    516     DBGFREGDESC_XMM(11),
    517     DBGFREGDESC_XMM(12),
    518     DBGFREGDESC_XMM(13),
    519     DBGFREGDESC_XMM(14),
    520     DBGFREGDESC_XMM(15),
    521     { "gdtr_base",  DBGFREG_GDTR_BASE,      DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, gdtr.pGdt),           NULL, NULL, NULL, NULL },
    522     { "gdtr_limit", DBGFREG_GDTR_LIMIT,     DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, gdtr.cbGdt),          NULL, NULL, NULL, NULL },
    523     { "idtr_base",  DBGFREG_IDTR_BASE,      DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, idtr.pIdt),           NULL, NULL, NULL, NULL },
    524     { "idtr_limit", DBGFREG_IDTR_LIMIT,     DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, idtr.cbIdt),          NULL, NULL, NULL, NULL },
    525     DBGFREGDESC_SEG(LDTR, ldtr),
    526     DBGFREGDESC_SEG(TR, tr),
    527     { "cr0",        DBGFREG_CR0,       DBGFREGVALTYPE_U32, 0, dbgfR3RegGet_crX, dbgfR3RegSet_crX, g_aDbgfRegAliases_cr0, g_aDbgfRegFields_cr0 },
    528     { "cr2",        DBGFREG_CR2,       DBGFREGVALTYPE_U64, 2, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, NULL },
    529     { "cr3",        DBGFREG_CR3,       DBGFREGVALTYPE_U64, 3, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, g_aDbgfRegFields_cr3 },
    530     { "cr4",        DBGFREG_CR4,       DBGFREGVALTYPE_U32, 4, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, g_aDbgfRegFields_cr4 },
    531     { "cr8",        DBGFREG_CR8,       DBGFREGVALTYPE_U32, 8, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, NULL },
    532     { "dr0",        DBGFREG_DR0,       DBGFREGVALTYPE_U64, 0, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
    533     { "dr1",        DBGFREG_DR1,       DBGFREGVALTYPE_U64, 1, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
    534     { "dr2",        DBGFREG_DR2,       DBGFREGVALTYPE_U64, 2, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
    535     { "dr3",        DBGFREG_DR3,       DBGFREGVALTYPE_U64, 3, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
    536     { "dr6",        DBGFREG_DR6,       DBGFREGVALTYPE_U32, 6, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, g_aDbgfRegFields_dr6 },
    537     { "dr7",        DBGFREG_DR7,       DBGFREGVALTYPE_U32, 7, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, g_aDbgfRegFields_dr7 },
    538     { "apic_base",    DBGFREG_MSR_IA32_APICBASE,      DBGFREGVALTYPE_U32, MSR_IA32_APICBASE,      dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_apic_base },
    539     { "pat",          DBGFREG_MSR_IA32_CR_PAT,        DBGFREGVALTYPE_U64, MSR_IA32_CR_PAT,        dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_cr_pat },
    540     { "perf_status",  DBGFREG_MSR_IA32_PERF_STATUS,   DBGFREGVALTYPE_U64, MSR_IA32_PERF_STATUS,   dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_perf_status },
    541     { "sysenter_cs",  DBGFREG_MSR_IA32_SYSENTER_CS,   DBGFREGVALTYPE_U16, MSR_IA32_SYSENTER_CS,   dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    542     { "sysenter_eip", DBGFREG_MSR_IA32_SYSENTER_EIP,  DBGFREGVALTYPE_U32, MSR_IA32_SYSENTER_EIP,  dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    543     { "sysenter_esp", DBGFREG_MSR_IA32_SYSENTER_ESP,  DBGFREGVALTYPE_U32, MSR_IA32_SYSENTER_ESP,  dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    544     { "tsc",          DBGFREG_MSR_IA32_TSC,           DBGFREGVALTYPE_U32, MSR_IA32_TSC,           dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    545     { "efer",         DBGFREG_MSR_K6_EFER,            DBGFREGVALTYPE_U32, MSR_K6_EFER,            dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_efer },
    546     { "star",         DBGFREG_MSR_K6_STAR,            DBGFREGVALTYPE_U64, MSR_K6_STAR,            dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_star },
    547     { "cstar",        DBGFREG_MSR_K8_CSTAR,           DBGFREGVALTYPE_U64, MSR_K8_CSTAR,           dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_cstar },
    548     { "msr_fs_base",  DBGFREG_MSR_K8_FS_BASE,         DBGFREGVALTYPE_U64, MSR_K8_FS_BASE,         dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    549     { "msr_gs_base",  DBGFREG_MSR_K8_GS_BASE,         DBGFREGVALTYPE_U64, MSR_K8_GS_BASE,         dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    550     { "krnl_gs_base", DBGFREG_MSR_K8_KERNEL_GS_BASE,  DBGFREGVALTYPE_U64, MSR_K8_KERNEL_GS_BASE,  dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    551     { "lstar",        DBGFREG_MSR_K8_LSTAR,           DBGFREGVALTYPE_U64, MSR_K8_LSTAR,           dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_lstar },
    552     { "tsc_aux",      DBGFREG_MSR_K8_TSC_AUX,         DBGFREGVALTYPE_U64, MSR_K8_TSC_AUX,         dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
    553     { "ah",           DBGFREG_AH,       DBGFREGVALTYPE_U8,  RT_OFFSETOF(CPUMCTX, rax) + 1,  NULL, NULL, NULL, NULL },
    554     { "ch",           DBGFREG_CH,       DBGFREGVALTYPE_U8,  RT_OFFSETOF(CPUMCTX, rcx) + 1,  NULL, NULL, NULL, NULL },
    555     { "dh",           DBGFREG_DH,       DBGFREGVALTYPE_U8,  RT_OFFSETOF(CPUMCTX, rdx) + 1,  NULL, NULL, NULL, NULL },
    556     { "bh",           DBGFREG_BH,       DBGFREGVALTYPE_U8,  RT_OFFSETOF(CPUMCTX, rbx) + 1,  NULL, NULL, NULL, NULL },
    557     { "gdtr",         DBGFREG_GDTR,     DBGFREGVALTYPE_DTR, ~(size_t)0, dbgfR3RegGet_gdtr, dbgfR3RegSet_gdtr, NULL, NULL },
    558     { "idtr",         DBGFREG_IDTR,     DBGFREGVALTYPE_DTR, ~(size_t)0, dbgfR3RegGet_idtr, dbgfR3RegSet_idtr, NULL, NULL },
    559 #undef DBGFREGDESC_REG
    560 #undef DBGFREGDESC_SEG
    561 #undef DBGFREGDESC_ST
    562 #undef DBGFREGDESC_MM
    563 #undef DBGFREGDESC_XMM
    564 };
    565 
    566 
    567 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    568 {
    569     return VERR_NOT_IMPLEMENTED;
    570 }
    571 
    572 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    573 {
    574     return VERR_NOT_IMPLEMENTED;
    575 }
    576 
    577 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    578 {
    579     return VERR_NOT_IMPLEMENTED;
    580 }
    581 
    582 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    583 {
    584     return VERR_NOT_IMPLEMENTED;
    585 }
    586 
    587 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    588 {
    589     return VERR_NOT_IMPLEMENTED;
    590 }
    591 
    592 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    593 {
    594     return VERR_NOT_IMPLEMENTED;
    595 }
    596 
    597 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    598 {
    599     return VERR_NOT_IMPLEMENTED;
    600 }
    601 
    602 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    603 {
    604     return VERR_NOT_IMPLEMENTED;
    605 }
    606 
    607 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    608 {
    609     return VERR_NOT_IMPLEMENTED;
    610 }
    611 
    612 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    613 {
    614     return VERR_NOT_IMPLEMENTED;
    615 }
    616 
    617 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    618 {
    619     return VERR_NOT_IMPLEMENTED;
    620 }
    621 
    622 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    623 {
    624     return VERR_NOT_IMPLEMENTED;
    625 }
    626 
    627 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    628 {
    629     return VERR_NOT_IMPLEMENTED;
    630 }
    631 
    632 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
    633 {
    634     return VERR_NOT_IMPLEMENTED;
    635 }
    636 
    637 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
    638 {
    639     return VERR_NOT_IMPLEMENTED;
    640 }
    641 
    642 
    643 
    644 /**
    645  * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryWorker.
     212
     213    /*
     214     * Allocate a new record.
     215     */
     216    PDBGFREGSET pRegRec = (PDBGFREGSET)MMR3HeapAlloc(pVM, MM_TAG_DBGF_REG, RT_OFFSETOF(DBGFREGSET, szPrefix[cchPrefix + 4 + 1]));
     217    if (!pRegRec)
     218        return VERR_NO_MEMORY;
     219
     220    pRegRec->Core.pszString = pRegRec->szPrefix;
     221    pRegRec->enmType        = enmType;
     222    pRegRec->uUserArg.pv    = pvUserArg;
     223    pRegRec->paDescs        = paRegisters;
     224    pRegRec->cDescs         = iDesc;
     225    if (fNeedUnderscore)
     226        RTStrPrintf(pRegRec->szPrefix, cchPrefix + 4 + 1, "%s_%u", pszPrefix, iInstance);
     227    else
     228        RTStrPrintf(pRegRec->szPrefix, cchPrefix + 4 + 1, "%s%u", pszPrefix, iInstance);
     229
     230    DBGF_REG_DB_LOCK_WRITE(pVM);
     231    bool fInserted = RTStrSpaceInsert(&pVM->dbgf.s.RegSetSpace, &pRegRec->Core);
     232    DBGF_REG_DB_UNLOCK_WRITE(pVM);
     233    if (fInserted)
     234        return VINF_SUCCESS;
     235
     236    MMR3HeapFree(pRegRec);
     237    return VERR_DUPLICATE;
     238}
     239
     240
     241/**
     242 * Registers a set of registers for a CPU.
     243 *
     244 * @returns VBox status code.
     245 * @param   pVCpu           The virtual CPU handle.
     246 * @param   paRegisters     The register descriptors.
     247 */
     248VMMR3_INT_DECL(int) DBGFR3RegRegisterDevice(PVMCPU pVCpu, PCDBGFREGDESC paRegisters)
     249{
     250    return dbgfR3RegRegisterCommon(pVCpu->pVMR3, paRegisters, DBGFREGSETTYPE_CPU, pVCpu, "cpu", pVCpu->idCpu);
     251}
     252
     253
     254/**
     255 * Registers a set of registers for a device.
     256 *
     257 * @returns VBox status code.
     258 * @param   enmReg              The register identifier.
     259 * @param   enmType             The register type.  This is for sort out
     260 *                              aliases.  Pass DBGFREGVALTYPE_INVALID to get
     261 *                              the standard name.
     262 */
     263VMMR3DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns, const char *pszPrefix, uint32_t iInstance)
     264{
     265    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     266    AssertPtrReturn(paRegisters, VERR_INVALID_POINTER);
     267    AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
     268    AssertPtrReturn(pszPrefix, VERR_INVALID_POINTER);
     269
     270    return dbgfR3RegRegisterCommon(pVM, paRegisters, DBGFREGSETTYPE_DEVICE, pDevIns, pszPrefix, iInstance);
     271}
     272
     273
     274/**
     275 * Clears the register value variable.
     276 *
     277 * @param   pValue              The variable to clear.
     278 */
     279DECLINLINE(void) dbgfR3RegValClear(PDBGFREGVAL pValue)
     280{
     281    pValue->au64[0] = 0;
     282    pValue->au64[1] = 0;
     283}
     284
     285
     286/**
     287 * Performs a cast between register value types.
    646288 *
    647289 * @retval  VINF_SUCCESS
     290 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     291 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     292 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     293 *
     294 * @param   pValue              The value to cast (input + output).
     295 * @param   enmFromType         The input value.
     296 * @param   enmToType           The desired output value.
     297 */
     298static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGFREGVALTYPE enmToType)
     299{
     300    DBGFREGVAL const InVal = *pValue;
     301    dbgfR3RegValClear(pValue);
     302
     303    switch (enmFromType)
     304    {
     305        case DBGFREGVALTYPE_U8:
     306            switch (enmToType)
     307            {
     308                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u8; return VINF_SUCCESS;
     309                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     310                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     311                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     312                case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     313                case DBGFREGVALTYPE_80:                                   return VERR_DBGF_UNSUPPORTED_CAST;
     314                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     315                case DBGFREGVALTYPE_DTR:                                  return VERR_DBGF_UNSUPPORTED_CAST;
     316
     317                case DBGFREGVALTYPE_32BIT_HACK:
     318                case DBGFREGVALTYPE_END:
     319                case DBGFREGVALTYPE_INVALID:
     320                    break;
     321            }
     322            break;
     323
     324        case DBGFREGVALTYPE_U16:
     325            switch (enmToType)
     326            {
     327                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u16;  return VINF_DBGF_TRUNCATED_REGISTER;
     328                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u16;  return VINF_SUCCESS;
     329                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     330                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     331                case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     332                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
     333                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     334                case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
     335
     336                case DBGFREGVALTYPE_32BIT_HACK:
     337                case DBGFREGVALTYPE_END:
     338                case DBGFREGVALTYPE_INVALID:
     339                    break;
     340            }
     341            break;
     342
     343        case DBGFREGVALTYPE_U32:
     344            switch (enmToType)
     345            {
     346                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u32;  return VINF_DBGF_TRUNCATED_REGISTER;
     347                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u32;  return VINF_DBGF_TRUNCATED_REGISTER;
     348                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u32;  return VINF_SUCCESS;
     349                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     350                case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     351                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
     352                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     353                case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
     354
     355                case DBGFREGVALTYPE_32BIT_HACK:
     356                case DBGFREGVALTYPE_END:
     357                case DBGFREGVALTYPE_INVALID:
     358                    break;
     359            }
     360            break;
     361
     362        case DBGFREGVALTYPE_U64:
     363            switch (enmToType)
     364            {
     365                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
     366                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
     367                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
     368                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u64;  return VINF_SUCCESS;
     369                case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
     370                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
     371                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u64;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
     372                case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
     373
     374                case DBGFREGVALTYPE_32BIT_HACK:
     375                case DBGFREGVALTYPE_END:
     376                case DBGFREGVALTYPE_INVALID:
     377                    break;
     378            }
     379            break;
     380
     381        case DBGFREGVALTYPE_U128:
     382            switch (enmToType)
     383            {
     384                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
     385                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
     386                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
     387                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
     388                case DBGFREGVALTYPE_U128:   pValue->u128      = InVal.u128;       return VINF_SUCCESS;
     389                case DBGFREGVALTYPE_80:                                           return VERR_DBGF_UNSUPPORTED_CAST;
     390                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u64;        return VINF_DBGF_TRUNCATED_REGISTER;
     391                case DBGFREGVALTYPE_DTR:                                          return VERR_DBGF_UNSUPPORTED_CAST;
     392
     393                case DBGFREGVALTYPE_32BIT_HACK:
     394                case DBGFREGVALTYPE_END:
     395                case DBGFREGVALTYPE_INVALID:
     396                    break;
     397            }
     398            break;
     399
     400        case DBGFREGVALTYPE_80:
     401            return VERR_DBGF_UNSUPPORTED_CAST;
     402
     403        case DBGFREGVALTYPE_LRD:
     404            switch (enmToType)
     405            {
     406                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.lrd;  return VINF_DBGF_TRUNCATED_REGISTER;
     407                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.lrd;  return VINF_DBGF_TRUNCATED_REGISTER;
     408                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.lrd;  return VINF_DBGF_TRUNCATED_REGISTER;
     409                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.lrd;  return VINF_DBGF_TRUNCATED_REGISTER;
     410                case DBGFREGVALTYPE_U128:
     411                    pValue->u128.s.Lo = (uint64_t)InVal.lrd;
     412                    pValue->u128.s.Hi = InVal.lrd / _4G / _4G;
     413                    return VINF_DBGF_TRUNCATED_REGISTER;
     414                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
     415                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.lrd;  return VINF_SUCCESS;
     416                case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
     417
     418                case DBGFREGVALTYPE_32BIT_HACK:
     419                case DBGFREGVALTYPE_END:
     420                case DBGFREGVALTYPE_INVALID:
     421                    break;
     422            }
     423            break;
     424
     425        case DBGFREGVALTYPE_DTR:
     426            switch (enmToType)
     427            {
     428                case DBGFREGVALTYPE_U8:     pValue->u8        = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
     429                case DBGFREGVALTYPE_U16:    pValue->u16       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
     430                case DBGFREGVALTYPE_U32:    pValue->u32       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
     431                case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
     432                case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
     433                case DBGFREGVALTYPE_80:                                             return VERR_DBGF_UNSUPPORTED_CAST;
     434                case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
     435                case DBGFREGVALTYPE_DTR:    pValue->dtr       = InVal.dtr;          return VINF_SUCCESS;
     436
     437                case DBGFREGVALTYPE_32BIT_HACK:
     438                case DBGFREGVALTYPE_END:
     439                case DBGFREGVALTYPE_INVALID:
     440                    break;
     441            }
     442            break;
     443
     444        case DBGFREGVALTYPE_INVALID:
     445        case DBGFREGVALTYPE_END:
     446        case DBGFREGVALTYPE_32BIT_HACK:
     447            break;
     448    }
     449
     450    AssertMsgFailed(("%d / %d\n", enmFromType, enmToType));
     451    return VERR_DBGF_UNSUPPORTED_CAST;
     452}
     453
     454
     455/**
     456 * Worker for the CPU register queries.
     457 *
     458 * @returns VBox status code.
     459 * @retval  VINF_SUCCESS
     460 * @retval  VERR_INVALID_VM_HANDLE
     461 * @retval  VERR_INVALID_CPU_ID
    648462 * @retval  VERR_DBGF_INVALID_REGISTER
    649  *
    650  * @param   pVCpu               The current CPU.
    651  * @param   pu64                Where to store the register value.
    652  * @param   pfRegSizes          Where to store the register sizes.
    653  * @param   idMsr               The MSR to get.
    654  */
    655 static uint64_t dbgfR3RegGetMsr(PVMCPU pVCpu, uint64_t *pu64, uint32_t *pfRegSizes, uint32_t idMsr)
    656 {
    657     *pfRegSizes = R_SZ_64;
    658     int rc = CPUMQueryGuestMsr(pVCpu, idMsr, pu64);
    659     if (RT_FAILURE(rc))
     463 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     464 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     465 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     466 *
     467 * @param   pVM                 The VM handle.
     468 * @param   idCpu               The virtual CPU ID.
     469 * @param   enmReg              The register to query.
     470 * @param   enmType             The desired return type.
     471 * @param   puValue             Where to return the register value.
     472 */
     473static DECLCALLBACK(int) dbgfR3RegCpuQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, DBGFREGVALTYPE enmType, PDBGFREGVAL puValue)
     474{
     475    int rc = VINF_SUCCESS;
     476    DBGF_REG_DB_LOCK_READ(pVM);
     477
     478    /*
     479     * Look up the register set of the CPU.
     480     */
     481    /** @todo optimize this by adding a cpu register set array to DBGF. */
     482    char szSetName[16];
     483    RTStrPrintf(szSetName, sizeof(szSetName), "cpu%u", idCpu);
     484    PDBGFREGSET pSet = (PDBGFREGSET)RTStrSpaceGet(&pVM->dbgf.s.RegSetSpace, szSetName);
     485    if (RT_LIKELY(pSet))
    660486    {
    661         AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));
    662         *pu64 = 0;
     487        /*
     488         * Look up the register and get the register value.
     489         */
     490        if (RT_LIKELY(pSet->cDescs > (size_t)enmReg))
     491        {
     492            PCDBGFREGDESC pDesc = &pSet->paDescs[enmReg];
     493
     494            puValue->au64[0] = puValue->au64[1] = 0;
     495            rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, puValue);
     496            if (RT_SUCCESS(rc))
     497            {
     498                /*
     499                 * Do the cast if the desired return type doesn't match what
     500                 * the getter returned.
     501                 */
     502                if (pDesc->enmType == enmType)
     503                    rc = VINF_SUCCESS;
     504                else
     505                    rc = dbgfR3RegValCast(puValue, pDesc->enmType, enmType);
     506            }
     507        }
     508        else
     509            rc = VERR_DBGF_INVALID_REGISTER;
    663510    }
    664     return VINF_SUCCESS;
    665 }
    666 
    667 /**
    668  * Worker for DBGFR3RegQueryU8, DBGFR3RegQueryU16, DBGFR3RegQueryU32 and
    669  * DBGFR3RegQueryU64.
     511    else
     512        rc = VERR_INVALID_CPU_ID;
     513
     514    DBGF_REG_DB_UNLOCK_READ(pVM);
     515    return rc;
     516}
     517
     518
     519/**
     520 * Queries a 8-bit CPU register value.
     521 *
     522 * @retval  VINF_SUCCESS
     523 * @retval  VERR_INVALID_VM_HANDLE
     524 * @retval  VERR_INVALID_CPU_ID
     525 * @retval  VERR_DBGF_INVALID_REGISTER
     526 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     527 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     528 *
     529 * @param   pVM                 The VM handle.
     530 * @param   idCpu               The target CPU ID.
     531 * @param   enmReg              The register that's being queried.
     532 * @param   pu8                 Where to store the register value.
     533 */
     534VMMR3DECL(int) DBGFR3RegCpuQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8)
     535{
     536    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     537    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
     538
     539    DBGFREGVAL Value;
     540    int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U8, &Value);
     541    if (RT_SUCCESS(rc))
     542        *pu8 = Value.u8;
     543    else
     544        *pu8 = 0;
     545
     546    return rc;
     547}
     548
     549
     550/**
     551 * Queries a 16-bit CPU register value.
     552 *
     553 * @retval  VINF_SUCCESS
     554 * @retval  VERR_INVALID_VM_HANDLE
     555 * @retval  VERR_INVALID_CPU_ID
     556 * @retval  VERR_DBGF_INVALID_REGISTER
     557 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     558 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     559 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     560 *
     561 * @param   pVM                 The VM handle.
     562 * @param   idCpu               The target CPU ID.
     563 * @param   enmReg              The register that's being queried.
     564 * @param   pu16                Where to store the register value.
     565 */
     566VMMR3DECL(int) DBGFR3RegCpuQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16)
     567{
     568    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     569    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
     570
     571    DBGFREGVAL Value;
     572    int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U16, &Value);
     573    if (RT_SUCCESS(rc))
     574        *pu16 = Value.u16;
     575    else
     576        *pu16 = 0;
     577
     578    return rc;
     579}
     580
     581
     582/**
     583 * Queries a 32-bit CPU register value.
     584 *
     585 * @retval  VINF_SUCCESS
     586 * @retval  VERR_INVALID_VM_HANDLE
     587 * @retval  VERR_INVALID_CPU_ID
     588 * @retval  VERR_DBGF_INVALID_REGISTER
     589 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     590 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     591 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     592 *
     593 * @param   pVM                 The VM handle.
     594 * @param   idCpu               The target CPU ID.
     595 * @param   enmReg              The register that's being queried.
     596 * @param   pu32                Where to store the register value.
     597 */
     598VMMR3DECL(int) DBGFR3RegCpuQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32)
     599{
     600    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     601    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
     602
     603    DBGFREGVAL Value;
     604    int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U32, &Value);
     605    if (RT_SUCCESS(rc))
     606        *pu32 = Value.u32;
     607    else
     608        *pu32 = 0;
     609
     610    return rc;
     611}
     612
     613
     614/**
     615 * Queries a 64-bit CPU register value.
     616 *
     617 * @retval  VINF_SUCCESS
     618 * @retval  VERR_INVALID_VM_HANDLE
     619 * @retval  VERR_INVALID_CPU_ID
     620 * @retval  VERR_DBGF_INVALID_REGISTER
     621 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     622 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     623 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    670624 *
    671625 * @param   pVM                 The VM handle.
     
    673627 * @param   enmReg              The register that's being queried.
    674628 * @param   pu64                Where to store the register value.
    675  * @param   pfRegSizes          Where to store the register sizes.
    676  */
    677 static DECLCALLBACK(int) dbgfR3RegQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64, uint32_t *pfRegSizes)
    678 {
    679 /** @todo rewrite this to use the register descriptors. */
    680     PVMCPU    pVCpu = &pVM->aCpus[idCpu];
    681     PCCPUMCTX pCtx  = CPUMQueryGuestCtxPtr(pVCpu);
    682     switch (enmReg)
    683     {
    684         case DBGFREG_RAX:       *pu64 = pCtx->rax;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    685         case DBGFREG_RCX:       *pu64 = pCtx->rcx;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    686         case DBGFREG_RDX:       *pu64 = pCtx->rdx;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    687         case DBGFREG_RBX:       *pu64 = pCtx->rbx;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    688         case DBGFREG_RSP:       *pu64 = pCtx->rsp;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    689         case DBGFREG_RBP:       *pu64 = pCtx->rbp;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    690         case DBGFREG_RSI:       *pu64 = pCtx->rsi;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    691         case DBGFREG_RDI:       *pu64 = pCtx->rdi;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    692         case DBGFREG_R8:        *pu64 = pCtx->r8;   *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    693         case DBGFREG_R9:        *pu64 = pCtx->r9;   *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    694         case DBGFREG_R10:       *pu64 = pCtx->r10;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    695         case DBGFREG_R11:       *pu64 = pCtx->r11;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    696         case DBGFREG_R12:       *pu64 = pCtx->r12;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    697         case DBGFREG_R13:       *pu64 = pCtx->r13;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    698         case DBGFREG_R14:       *pu64 = pCtx->r14;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    699         case DBGFREG_R15:       *pu64 = pCtx->r15;  *pfRegSizes = R_SZ_8_TO_64;         return VINF_SUCCESS;
    700 
    701         case DBGFREG_CS:        *pu64 = pCtx->cs;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    702         case DBGFREG_DS:        *pu64 = pCtx->ds;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    703         case DBGFREG_ES:        *pu64 = pCtx->es;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    704         case DBGFREG_FS:        *pu64 = pCtx->fs;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    705         case DBGFREG_GS:        *pu64 = pCtx->gs;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    706         case DBGFREG_SS:        *pu64 = pCtx->ss;   *pfRegSizes = R_SZ_16;              return VINF_SUCCESS;
    707 
    708         case DBGFREG_CS_ATTR:   *pu64 = pCtx->csHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    709         case DBGFREG_DS_ATTR:   *pu64 = pCtx->dsHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    710         case DBGFREG_ES_ATTR:   *pu64 = pCtx->esHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    711         case DBGFREG_FS_ATTR:   *pu64 = pCtx->fsHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    712         case DBGFREG_GS_ATTR:   *pu64 = pCtx->gsHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    713         case DBGFREG_SS_ATTR:   *pu64 = pCtx->ssHid.Attr.u;  *pfRegSizes = R_SZ_32;     return VINF_SUCCESS;
    714 
    715         case DBGFREG_CS_BASE:   *pu64 = pCtx->csHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    716         case DBGFREG_DS_BASE:   *pu64 = pCtx->dsHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    717         case DBGFREG_ES_BASE:   *pu64 = pCtx->esHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    718         case DBGFREG_FS_BASE:   *pu64 = pCtx->fsHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    719         case DBGFREG_GS_BASE:   *pu64 = pCtx->gsHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    720         case DBGFREG_SS_BASE:   *pu64 = pCtx->ssHid.u64Base; *pfRegSizes = R_SZ_64;     return VINF_SUCCESS;
    721 
    722         case DBGFREG_CS_LIMIT:  *pu64 = pCtx->csHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    723         case DBGFREG_DS_LIMIT:  *pu64 = pCtx->dsHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    724         case DBGFREG_ES_LIMIT:  *pu64 = pCtx->esHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    725         case DBGFREG_FS_LIMIT:  *pu64 = pCtx->fsHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    726         case DBGFREG_GS_LIMIT:  *pu64 = pCtx->gsHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    727         case DBGFREG_SS_LIMIT:  *pu64 = pCtx->ssHid.u32Limit; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    728 
    729         case DBGFREG_RIP:       *pu64 = pCtx->rip;      *pfRegSizes = R_SZ_16_TO_64;    return VINF_SUCCESS;
    730         case DBGFREG_FLAGS:     *pu64 = pCtx->rflags.u; *pfRegSizes = R_SZ_16_TO_64;    return VINF_SUCCESS;
    731 
    732         /** @todo check fxsave/fsave format? */
    733         case DBGFREG_FCW:       *pu64 = pCtx->fpu.FCW;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    734         case DBGFREG_FSW:       *pu64 = pCtx->fpu.FSW;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    735         case DBGFREG_FTW:       *pu64 = pCtx->fpu.FTW;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    736         case DBGFREG_FOP:       *pu64 = pCtx->fpu.FOP;      *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    737         case DBGFREG_FPUIP:     *pu64 = pCtx->fpu.FPUIP;    *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    738         case DBGFREG_FPUCS:     *pu64 = pCtx->fpu.CS;       *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    739         case DBGFREG_FPUDP:     *pu64 = pCtx->fpu.FPUDP;    *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    740         case DBGFREG_FPUDS:     *pu64 = pCtx->fpu.DS;       *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    741         case DBGFREG_MXCSR:     *pu64 = pCtx->fpu.MXCSR;    *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    742         case DBGFREG_MXCSR_MASK:*pu64 = pCtx->fpu.MXCSR_MASK; *pfRegSizes = R_SZ_32;    return VINF_SUCCESS;
    743 
    744         case DBGFREG_ST0:
    745         case DBGFREG_ST1:
    746         case DBGFREG_ST2:
    747         case DBGFREG_ST3:
    748         case DBGFREG_ST4:
    749         case DBGFREG_ST5:
    750         case DBGFREG_ST6:
    751         case DBGFREG_ST7:
    752         {
    753             /** @todo check tags and fxsave/fsave format. */
    754             unsigned iReg = (pCtx->fpu.FSW >> 11) & 7;
    755             iReg += enmReg - DBGFREG_ST0;
    756             iReg &= 7;
    757 
    758             *pu64 = pCtx->fpu.aRegs[iReg].au64[0];
    759             *pfRegSizes = R_SZ_80;
    760             return VINF_SUCCESS;
    761         }
    762 
    763         case DBGFREG_MM0:
    764         case DBGFREG_MM1:
    765         case DBGFREG_MM2:
    766         case DBGFREG_MM3:
    767         case DBGFREG_MM4:
    768         case DBGFREG_MM5:
    769         case DBGFREG_MM6:
    770         case DBGFREG_MM7:
    771             *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_MM0].mmx;
    772             *pfRegSizes = R_SZ_64;
    773             return VINF_SUCCESS;
    774 
    775         case DBGFREG_XMM0:
    776         case DBGFREG_XMM1:
    777         case DBGFREG_XMM2:
    778         case DBGFREG_XMM3:
    779         case DBGFREG_XMM4:
    780         case DBGFREG_XMM5:
    781         case DBGFREG_XMM6:
    782         case DBGFREG_XMM7:
    783         case DBGFREG_XMM8:
    784         case DBGFREG_XMM9:
    785         case DBGFREG_XMM10:
    786         case DBGFREG_XMM11:
    787         case DBGFREG_XMM12:
    788         case DBGFREG_XMM13:
    789         case DBGFREG_XMM14:
    790         case DBGFREG_XMM15:
    791             *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_XMM0].au64[0];
    792             *pfRegSizes = R_SZ_128;
    793             return VINF_SUCCESS;
    794 
    795         case DBGFREG_GDTR_BASE:     *pu64 = pCtx->gdtr.pGdt;        *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    796         case DBGFREG_GDTR_LIMIT:    *pu64 = pCtx->gdtr.cbGdt;       *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    797         case DBGFREG_IDTR_BASE:     *pu64 = pCtx->idtr.pIdt;        *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    798         case DBGFREG_IDTR_LIMIT:    *pu64 = pCtx->idtr.cbIdt;       *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    799         case DBGFREG_LDTR:          *pu64 = pCtx->ldtr;             *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    800         case DBGFREG_LDTR_ATTR:     *pu64 = pCtx->ldtrHid.Attr.u;   *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    801         case DBGFREG_LDTR_BASE:     *pu64 = pCtx->ldtrHid.u64Base;  *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    802         case DBGFREG_LDTR_LIMIT:    *pu64 = pCtx->ldtrHid.u32Limit; *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    803         case DBGFREG_TR:            *pu64 = pCtx->tr;               *pfRegSizes = R_SZ_16;      return VINF_SUCCESS;
    804         case DBGFREG_TR_ATTR:       *pu64 = pCtx->trHid.Attr.u;     *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    805         case DBGFREG_TR_BASE:       *pu64 = pCtx->trHid.u64Base;    *pfRegSizes = R_SZ_64;      return VINF_SUCCESS;
    806         case DBGFREG_TR_LIMIT:      *pu64 = pCtx->trHid.u32Limit;   *pfRegSizes = R_SZ_32;      return VINF_SUCCESS;
    807 
    808         case DBGFREG_CR0:           *pu64 = CPUMGetGuestCR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    809         case DBGFREG_CR2:           *pu64 = CPUMGetGuestCR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    810         case DBGFREG_CR3:           *pu64 = CPUMGetGuestCR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    811         case DBGFREG_CR4:           *pu64 = CPUMGetGuestCR4(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    812         case DBGFREG_CR8:           *pu64 = CPUMGetGuestCR8(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    813 
    814         case DBGFREG_DR0:           *pu64 = CPUMGetGuestDR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    815         case DBGFREG_DR1:           *pu64 = CPUMGetGuestDR1(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    816         case DBGFREG_DR2:           *pu64 = CPUMGetGuestDR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    817         case DBGFREG_DR3:           *pu64 = CPUMGetGuestDR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    818         case DBGFREG_DR6:           *pu64 = CPUMGetGuestDR6(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    819         case DBGFREG_DR7:           *pu64 = CPUMGetGuestDR7(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
    820 
    821         case DBGFREG_MSR_IA32_APICBASE:     return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_APICBASE);
    822         case DBGFREG_MSR_IA32_CR_PAT:       return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_CR_PAT);
    823         case DBGFREG_MSR_IA32_PERF_STATUS:  return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_PERF_STATUS);
    824         case DBGFREG_MSR_IA32_SYSENTER_CS:  return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_CS);
    825         case DBGFREG_MSR_IA32_SYSENTER_EIP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_EIP);
    826         case DBGFREG_MSR_IA32_SYSENTER_ESP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_ESP);
    827         case DBGFREG_MSR_IA32_TSC:          return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_TSC);
    828         case DBGFREG_MSR_K6_EFER:           return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_EFER);
    829         case DBGFREG_MSR_K6_STAR:           return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_STAR);
    830         case DBGFREG_MSR_K8_CSTAR:          return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_CSTAR);
    831         case DBGFREG_MSR_K8_FS_BASE:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_FS_BASE);
    832         case DBGFREG_MSR_K8_GS_BASE:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_GS_BASE);
    833         case DBGFREG_MSR_K8_KERNEL_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_KERNEL_GS_BASE);
    834         case DBGFREG_MSR_K8_LSTAR:          return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_LSTAR);
    835         case DBGFREG_MSR_K8_SF_MASK:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_SF_MASK);
    836         case DBGFREG_MSR_K8_TSC_AUX:        return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_TSC_AUX);
    837 
    838         case DBGFREG_AH:        *pu64 = RT_BYTE2(pCtx->ax); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    839         case DBGFREG_CH:        *pu64 = RT_BYTE2(pCtx->cx); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    840         case DBGFREG_DH:        *pu64 = RT_BYTE2(pCtx->dx); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    841         case DBGFREG_BH:        *pu64 = RT_BYTE2(pCtx->bx); *pfRegSizes = R_SZ_8;       return VINF_SUCCESS;
    842         case DBGFREG_GDTR:      *pu64 = pCtx->gdtr.pGdt;    *pfRegSizes = R_SZ_64_16;   return VINF_SUCCESS;
    843         case DBGFREG_IDTR:      *pu64 = pCtx->idtr.pIdt;    *pfRegSizes = R_SZ_64_16;   return VINF_SUCCESS;
    844 
    845         case DBGFREG_END:
    846         case DBGFREG_32BIT_HACK:
    847             /* no default! We want GCC warnings. */
    848             break;
    849     }
    850 
    851     AssertMsgFailed(("%d (%#x)\n", enmReg, enmReg));
    852     return VERR_DBGF_INVALID_REGISTER;
    853 }
    854 
    855 
    856 /**
    857  * Queries a 8-bit register value.
    858  *
    859  * @retval  VINF_SUCCESS
    860  * @retval  VERR_INVALID_VM_HANDLE
    861  * @retval  VERR_INVALID_CPU_ID
    862  * @retval  VERR_DBGF_INVALID_REGISTER
    863  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    864  *
    865  * @param   pVM                 The VM handle.
    866  * @param   idCpu               The target CPU ID.
    867  * @param   enmReg              The register that's being queried.
    868  * @param   pu8                 Where to store the register value.
    869  */
    870 VMMR3DECL(int) DBGFR3RegQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8)
     629 */
     630VMMR3DECL(int) DBGFR3RegCpuQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64)
    871631{
    872632    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    873633    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    874634
    875     uint64_t u64Value;
    876     uint32_t fRegSizes;
    877     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
     635    DBGFREGVAL Value;
     636    int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U64, &Value);
    878637    if (RT_SUCCESS(rc))
    879     {
    880         *pu8 = (uint8_t)u64Value;
    881         if (R_SZ_8 & fRegSizes)
    882             rc = VINF_SUCCESS;
    883         else
    884             rc = VINF_DBGF_TRUNCATED_REGISTER;
    885     }
    886     else
    887         *pu8 = 0;
    888     return rc;
    889 }
    890 
    891 
    892 /**
    893  * Queries a 16-bit register value.
    894  *
    895  * @retval  VINF_SUCCESS
    896  * @retval  VERR_INVALID_VM_HANDLE
    897  * @retval  VERR_INVALID_CPU_ID
    898  * @retval  VERR_DBGF_INVALID_REGISTER
    899  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    900  * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    901  *
    902  * @param   pVM                 The VM handle.
    903  * @param   idCpu               The target CPU ID.
    904  * @param   enmReg              The register that's being queried.
    905  * @param   pu16                Where to store the register value.
    906  */
    907 VMMR3DECL(int) DBGFR3RegQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16)
    908 {
    909     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    910     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    911 
    912     uint64_t u64Value;
    913     uint32_t fRegSizes;
    914     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    915     if (RT_SUCCESS(rc))
    916     {
    917         *pu16 = (uint16_t)u64Value;
    918         if (R_SZ_16 & fRegSizes)
    919             rc = VINF_SUCCESS;
    920         else if (~(R_SZ_8 | R_SZ_16) & fRegSizes)
    921             rc = VINF_DBGF_TRUNCATED_REGISTER;
    922         else
    923             rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
    924     }
    925     else
    926         *pu16 = 0;
    927     return rc;
    928 }
    929 
    930 
    931 /**
    932  * Queries a 32-bit register value.
    933  *
    934  * @retval  VINF_SUCCESS
    935  * @retval  VERR_INVALID_VM_HANDLE
    936  * @retval  VERR_INVALID_CPU_ID
    937  * @retval  VERR_DBGF_INVALID_REGISTER
    938  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    939  * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    940  *
    941  * @param   pVM                 The VM handle.
    942  * @param   idCpu               The target CPU ID.
    943  * @param   enmReg              The register that's being queried.
    944  * @param   pu32                Where to store the register value.
    945  */
    946 VMMR3DECL(int) DBGFR3RegQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32)
    947 {
    948     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    949     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    950 
    951     uint64_t u64Value;
    952     uint32_t fRegSizes;
    953     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    954     if (RT_SUCCESS(rc))
    955     {
    956         *pu32 = (uint32_t)u64Value;
    957         if (R_SZ_32 & fRegSizes)
    958             rc = VINF_SUCCESS;
    959         else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32) & fRegSizes)
    960             rc = VINF_DBGF_TRUNCATED_REGISTER;
    961         else
    962             rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
    963     }
    964     else
    965         *pu32 = 0;
    966     return rc;
    967 }
    968 
    969 
    970 /**
    971  * Queries a 64-bit register value.
    972  *
    973  * @retval  VINF_SUCCESS
    974  * @retval  VERR_INVALID_VM_HANDLE
    975  * @retval  VERR_INVALID_CPU_ID
    976  * @retval  VERR_DBGF_INVALID_REGISTER
    977  * @retval  VINF_DBGF_TRUNCATED_REGISTER
    978  * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
    979  *
    980  * @param   pVM                 The VM handle.
    981  * @param   idCpu               The target CPU ID.
    982  * @param   enmReg              The register that's being queried.
    983  * @param   pu64                Where to store the register value.
    984  */
    985 VMMR3DECL(int) DBGFR3RegQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64)
    986 {
    987     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    988     AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    989 
    990     uint64_t u64Value;
    991     uint32_t fRegSizes;
    992     int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
    993     if (RT_SUCCESS(rc))
    994     {
    995         *pu64 = u64Value;
    996         if (R_SZ_64 & fRegSizes)
    997             rc = VINF_SUCCESS;
    998         else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) & fRegSizes)
    999             rc = VINF_DBGF_TRUNCATED_REGISTER;
    1000         else
    1001             rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
    1002     }
     638        *pu64 = Value.u64;
    1003639    else
    1004640        *pu64 = 0;
     641
    1005642    return rc;
    1006643}
     
    1008645
    1009646/**
    1010  * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryBatchWorker.
     647 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegCpuQueryBatchWorker.
    1011648 *
    1012649 * @retval  VINF_SUCCESS
     
    1030667
    1031668
    1032 static DECLCALLBACK(int) dbgfR3RegQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
    1033 {
     669static DECLCALLBACK(int) dbgfR3RegCpuQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
     670{
     671#if 0
    1034672    PVMCPU    pVCpu = &pVM->aCpus[idCpu];
    1035673    PCCPUMCTX pCtx  = CPUMQueryGuestCtxPtr(pVCpu);
     
    1077715        }
    1078716    }
    1079 
    1080717    return VINF_SUCCESS;
     718#else
     719    return VERR_NOT_IMPLEMENTED;
     720#endif
    1081721}
    1082722
     
    1099739 * @param   cRegs               The number of entries in @a paRegs.
    1100740 */
    1101 VMMR3DECL(int) DBGFR3RegQueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
     741VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
    1102742{
    1103743    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     
    1114754    }
    1115755
    1116     return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
     756    return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
    1117757}
    1118758
     
    1135775 *                              recommended value is DBGFREG_ALL_COUNT.
    1136776 */
    1137 VMMR3DECL(int) DBGFR3RegQueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
     777VMMR3DECL(int) DBGFR3RegCpuQueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
    1138778{
    1139779    /*
     
    1159799        paRegs[iReg++].enmReg = DBGFREG_END;
    1160800
    1161     return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
     801    return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
    1162802}
    1163803
     
    1174814 *                              the standard name.
    1175815 */
    1176 VMMR3DECL(const char *) DBGFR3RegName(DBGFREG enmReg, DBGFREGVALTYPE enmType)
     816VMMR3DECL(const char *) DBGFR3RegCpuName(DBGFREG enmReg, DBGFREGVALTYPE enmType)
    1177817{
    1178818    AssertReturn(enmReg >= DBGFREG_AL && enmReg < DBGFREG_END, NULL);
    1179819    AssertReturn(enmType >= DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, NULL);
    1180820
     821#if 0 /** @todo need the optimization */
    1181822    PCDBGFREGDESC   pDesc  = &g_aDbgfRegDescs[enmReg];
    1182823    PCDBGFREGALIAS  pAlias = pDesc->paAliases;
     
    1194835
    1195836    return pDesc->pszName;
    1196 }
    1197 
     837#else
     838    return NULL;
     839#endif
     840}
     841
     842/** @todo Implementing missing APIs. */
  • trunk/src/VBox/VMM/VMMR3/VBoxVMMDeps.cpp

    r35346 r35410  
    4545    (PFNRT)DBGFR3CoreWrite,
    4646    (PFNRT)DBGFR3MemScan,
    47     (PFNRT)DBGFR3RegQueryU8,
     47    (PFNRT)DBGFR3RegCpuQueryU8,
    4848    (PFNRT)EMInterpretInstruction,
    4949    (PFNRT)IOMIOPortRead,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette