VirtualBox

Changeset 57989 in vbox


Ignore:
Timestamp:
Oct 1, 2015 4:44:12 PM (9 years ago)
Author:
vboxsync
Message:

Added support for GIM Hyper-V hypercalls and guest debugging.

Location:
trunk
Files:
1 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r57213 r57989  
    26712671/** Hypercall cannot be enabled/performed due to access/permissions/CPL. */
    26722672#define VERR_GIM_HYPERCALL_ACCESS_DENIED            (-6311)
     2673/** Failed to read to a memory region while performing a hypercall. */
     2674#define VERR_GIM_HYPERCALL_MEMORY_READ_FAILED       (-6312)
     2675/** Failed to write to a memory region while performing a hypercall. */
     2676#define VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED      (-6313)
     2677/** Generic hypercall operation failure. */
     2678#define VERR_GIM_HYPERCALL_FAILED                   (-6314)
     2679/** No debug connection configured. */
     2680#define VERR_GIM_NO_DEBUG_CONNECTION                (-6315)
     2681/** Return to ring-3 to perform the hypercall there. */
     2682#define VINF_GIM_R3_HYPERCALL                       6316
    26732683/** @} */
    26742684
  • trunk/include/VBox/log.h

    r57809 r57989  
    228228    /** TUN network transport driver group */
    229229    LOG_GROUP_DRV_TUN,
     230    /** UDP socket stream driver group. */
     231    LOG_GROUP_DRV_UDP,
    230232    /** UDP tunnet network transport driver group. */
    231233    LOG_GROUP_DRV_UDPTUNNEL,
     
    885887    "DRV_TRANSPORT_ASYNC", \
    886888    "DRV_TUN",      \
     889    "DRV_UDP", \
    887890    "DRV_UDPTUNNEL", \
    888891    "DRV_USBPROXY", \
  • trunk/include/VBox/vmm/gim.h

    r55129 r57989  
    3232
    3333#include <VBox/vmm/cpum.h>
     34#include <VBox/vmm/pdmifs.h>
    3435
    3536/** The value used to specify that VirtualBox must use the newest
     
    164165VMMR3_INT_DECL(int)         GIMR3Term(PVM pVM);
    165166VMMR3_INT_DECL(void)        GIMR3Reset(PVM pVM);
    166 VMMR3DECL(void)             GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns);
     167VMMR3DECL(void)             GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevInsR3, PPDMISTREAM pDebugStreamR3);
    167168VMMR3DECL(PGIMMMIO2REGION)  GIMR3GetMmio2Regions(PVM pVM, uint32_t *pcRegions);
    168169/** @} */
  • trunk/include/VBox/vmm/vm.h

    r57492 r57989  
    225225        struct GIMCPU s;
    226226#endif
    227         uint8_t             padding[64];      /* multiple of 64 */
     227        uint8_t             padding[64];        /* multiple of 64 */
    228228    } gim;
    229229
     
    11191119        struct SSM  s;
    11201120#endif
    1121         uint8_t     padding[128];        /* multiple of 64 */
     1121        uint8_t     padding[128];       /* multiple of 64 */
    11221122    } ssm;
    11231123
     
    11281128        struct FTM  s;
    11291129#endif
    1130         uint8_t     padding[512];        /* multiple of 64 */
     1130        uint8_t     padding[512];       /* multiple of 64 */
    11311131    } ftm;
    11321132
     
    11451145        struct GIM s;
    11461146#endif
    1147         uint8_t     padding[320];        /* multiple of 64 */
     1147        uint8_t     padding[320+64];    /* multiple of 64 */
    11481148    } gim;
    11491149
     
    11701170
    11711171    /** Padding for aligning the cpu array on a page boundary. */
    1172     uint8_t         abAlignment2[30];
     1172    uint8_t         abAlignment2[4062];
    11731173
    11741174    /* ---- end small stuff ---- */
  • trunk/src/VBox/Devices/GIMDev/GIMDev.cpp

    r57358 r57989  
    2626
    2727#include "VBoxDD.h"
     28#include <iprt/uuid.h>
     29
     30#define GIMDEV_DEBUG_LUN                998
    2831
    2932/**
     
    4043    /** Alignment. */
    4144    RTRCPTR                         Alignment0;
     45
     46    /** LUN\#998: The debug interface. */
     47    PDMIBASE                        IDbgBase;
     48    /** LUN\#998: The stream port interface. */
     49    PDMISTREAM                      IDbgStreamPort;
     50    /** Pointer to the attached base debug driver. */
     51    R3PTRTYPE(PPDMIBASE)            pDbgDrvBase;
     52    /** Pointer to the attached debug stream driver. */
     53    R3PTRTYPE(PPDMISTREAM)          pDbgDrvStream;
    4254} GIMDEV;
    4355/** Pointer to the GIM device state. */
    4456typedef GIMDEV *PGIMDEV;
    45 
     57AssertCompileMemberAlignment(GIMDEV, IDbgBase, 8);
    4658
    4759#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    4860
    4961#ifdef IN_RING3
     62
     63
     64/* -=-=-=-=-=-=-=-=- PDMIBASE on LUN#GIMDEV_DEBUG_LUN -=-=-=-=-=-=-=-=- */
     65
     66/**
     67 * @interface_method_impl{PDMIBASE, pfnQueryInterface}
     68 */
     69static DECLCALLBACK(void *) gimdevR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
     70{
     71    PGIMDEV pThis = RT_FROM_MEMBER(pInterface, GIMDEV, IDbgBase);
     72    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IDbgBase);
     73    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IDbgStreamPort);
     74    return NULL;
     75}
     76
     77
    5078/**
    5179 * @interface_method_impl{PDMDEVREG,pfnConstruct}
     
    6593
    6694    /*
     95     * Attach the stream driver for the debug connection.
     96     */
     97    pThis->IDbgBase.pfnQueryInterface = gimdevR3QueryInterface;
     98    int rc = PDMDevHlpDriverAttach(pDevIns, GIMDEV_DEBUG_LUN, &pThis->IDbgBase, &pThis->pDbgDrvBase, "GIM Debug Port");
     99    if (RT_SUCCESS(rc))
     100    {
     101        pThis->pDbgDrvStream = PDMIBASE_QUERY_INTERFACE(pThis->pDbgDrvBase, PDMISTREAM);
     102        if (pThis->pDbgDrvStream)
     103            LogRel(("GIMDev: LUN#%u: Debug port configured\n", GIMDEV_DEBUG_LUN));
     104        else
     105            LogRel(("GIMDev: LUN#%u: No unit\n", GIMDEV_DEBUG_LUN));
     106    }
     107    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     108    {
     109        pThis->pDbgDrvBase   = NULL;
     110        pThis->pDbgDrvStream = NULL;
     111        LogRel(("GIMDev: LUN#%u: No debug port configured\n", GIMDEV_DEBUG_LUN));
     112    }
     113    else
     114    {
     115        AssertLogRelMsgFailed(("GIMDev: LUN#%u: Failed to attach to driver on debug port. rc=%Rrc\n", GIMDEV_DEBUG_LUN, rc));
     116        /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
     117        return rc;
     118    }
     119
     120    /*
    67121     * Register ourselves with the GIM VMM component.
    68122     */
    69123    PVM pVM = PDMDevHlpGetVM(pDevIns);
    70     GIMR3GimDeviceRegister(pVM, pDevIns);
     124    GIMR3GimDeviceRegister(pVM, pDevIns, pThis->pDbgDrvStream);
    71125
    72126    /*
     
    85139        {
    86140            Assert(!pCur->fRegistered);
    87             int rc = PDMDevHlpMMIO2Register(pDevIns, pCur->iRegion, pCur->cbRegion, 0 /* fFlags */, &pCur->pvPageR3,
     141            rc = PDMDevHlpMMIO2Register(pDevIns, pCur->iRegion, pCur->cbRegion, 0 /* fFlags */, &pCur->pvPageR3,
    88142                                            pCur->szDescription);
    89143            if (RT_FAILURE(rc))
     
    126180    return VINF_SUCCESS;
    127181}
     182
    128183
    129184/**
  • trunk/src/VBox/Devices/Makefile.kmk

    r57809 r57989  
    153153        PC/DevPcArch.cpp \
    154154        GIMDev/GIMDev.cpp \
     155        GIMDev/DrvUDP.cpp \
    155156        VMMDev/VMMDev.cpp \
    156157        $(if $(VBOX_WITH_HGCM),VMMDev/VMMDevHGCM.cpp,) \
  • trunk/src/VBox/Devices/build/VBoxDD.cpp

    r57809 r57989  
    339339    if (RT_FAILURE(rc))
    340340        return rc;
     341    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvUDP);
     342    if (RT_FAILURE(rc))
     343        return rc;
    341344    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvRawFile);
    342345    if (RT_FAILURE(rc))
  • trunk/src/VBox/Devices/build/VBoxDD.h

    r57809 r57989  
    146146extern const PDMDRVREG g_DrvNamedPipe;
    147147extern const PDMDRVREG g_DrvTCP;
     148extern const PDMDRVREG g_DrvUDP;
    148149extern const PDMDRVREG g_DrvRawFile;
    149150extern const PDMDRVREG g_DrvHostParallel;
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r57979 r57989  
    14101410            InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    14111411            //InsertConfigNode(pInst,    "Config", &pCfg);
     1412
     1413            InsertConfigNode(pInst,     "LUN#998", &pLunL0);
     1414            InsertConfigString(pLunL0,  "Driver", "UDP");
     1415            InsertConfigNode(pLunL0,    "Config", &pLunL1);
     1416            InsertConfigString(pLunL1,  "ServerAddress", "127.0.0.1");
     1417            InsertConfigInteger(pLunL1, "ServerPort", 51000);
    14121418        }
    14131419
  • trunk/src/VBox/VMM/VMMAll/GIMAll.cpp

    r57358 r57989  
    8888 * @param   pVCpu       Pointer to the VMCPU.
    8989 * @param   pCtx        Pointer to the guest-CPU context.
     90 *
     91 * @remarks Guest RIP may or may not have been incremented at this point.
    9092 */
    9193VMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
     
    162164            return gimKvmShouldTrapXcptUD(pVCpu);
    163165
     166        case GIMPROVIDERID_HYPERV:
     167            return gimHvShouldTrapXcptUD(pVCpu);
     168
    164169        default:
    165170            return false;
     
    185190        case GIMPROVIDERID_KVM:
    186191            return gimKvmXcptUD(pVCpu, pCtx, pDis);
     192
     193        case GIMPROVIDERID_HYPERV:
     194            return gimHvXcptUD(pVCpu, pCtx, pDis);
    187195
    188196        default:
  • trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp

    r57851 r57989  
    2424#include "GIMInternal.h"
    2525
     26#include <iprt/asm-amd64-x86.h>
     27#ifdef IN_RING3
     28# include <iprt/mem.h>
     29#endif
     30
    2631#include <VBox/err.h>
     32#include <VBox/vmm/em.h>
    2733#include <VBox/vmm/hm.h>
    2834#include <VBox/vmm/tm.h>
     
    3238#include <VBox/vmm/pdmapi.h>
    3339
    34 #include <iprt/asm-amd64-x86.h>
    35 
    36 
    37 /**
    38  * Handles the Hyper-V hypercall.
     40
     41#ifdef IN_RING3
     42/**
     43 * Helper for reading and validating slow hypercall input/output parameters.
     44 *
     45 * A 'slow' hypercall is one that passes parameters pointers through guest
     46 * memory as opposed to a 'fast' hypercall which passes parameters through guest
     47 * general-purpose registers.
     48 *
     49 * @returns VBox status code.
     50 * @param   pVM               Pointer to the VM.
     51 * @param   pCtx              Pointer to the guest-CPU context.
     52 * @param   fIs64BitMode      Whether the guest is currently in 64-bit mode or not.
     53 * @param   pGCPhysIn         Where to store the guest-physical address of the
     54 *                            hypercall input page. Optional, can be NULL.
     55 * @param   pGCPhysOut        Where to store the guest-physical address of the
     56 *                            hypercall output page. Optional, can be NULL.
     57 * @param   prcHv             Where to store the Hyper-V status code. Only valid
     58 *                            to the caller when this function returns
     59 *                            VINF_SUCCESS.
     60 */
     61static int gimHvReadSlowHypercallParams(PVM pVM, PCPUMCTX pCtx, bool fIs64BitMode, PRTGCPHYS pGCPhysIn, PRTGCPHYS pGCPhysOut,
     62                                        int *prcHv)
     63{
     64    int rc = VINF_SUCCESS;
     65    RTGCPHYS GCPhysIn  = fIs64BitMode ? pCtx->rdx : (pCtx->rbx << 32) | pCtx->ecx;
     66    RTGCPHYS GCPhysOut = fIs64BitMode ? pCtx->r8  : (pCtx->rdi << 32) | pCtx->esi;
     67    if (pGCPhysIn)
     68        *pGCPhysIn = GCPhysIn;
     69    if (pGCPhysOut)
     70        *pGCPhysOut = GCPhysOut;
     71    if (   RT_ALIGN_64(GCPhysIn,  8) == GCPhysIn
     72        && RT_ALIGN_64(GCPhysOut, 8) == GCPhysOut)
     73    {
     74        if (   PGMPhysIsGCPhysNormal(pVM, GCPhysIn)
     75            && PGMPhysIsGCPhysNormal(pVM, GCPhysOut))
     76        {
     77            PGIMHV pHv = &pVM->gim.s.u.Hv;
     78            rc = PGMPhysSimpleReadGCPhys(pVM, pHv->pbHypercallIn, GCPhysIn, GIM_HV_PAGE_SIZE);
     79            if (RT_SUCCESS(rc))
     80            {
     81                rc = PGMPhysSimpleReadGCPhys(pVM, pHv->pbHypercallOut, GCPhysOut, GIM_HV_PAGE_SIZE);
     82                if (RT_SUCCESS(rc))
     83                {
     84                    *prcHv = GIM_HV_STATUS_SUCCESS;
     85                    return VINF_SUCCESS;
     86                }
     87                Log(("GIM: HyperV: gimHvReadSlowHypercallParams reading GCPhysOut=%#RGp failed. rc=%Rrc\n", GCPhysOut, rc));
     88                rc = VERR_GIM_HYPERCALL_MEMORY_READ_FAILED;
     89            }
     90            else
     91            {
     92                Log(("GIM: HyperV: gimHvReadSlowHypercallParams reading GCPhysIn=%#RGp failed. rc=%Rrc\n", GCPhysIn,rc));
     93                rc = VERR_GIM_HYPERCALL_MEMORY_READ_FAILED;
     94            }
     95        }
     96        else
     97            *prcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     98    }
     99    else
     100        *prcHv = GIM_HV_STATUS_INVALID_ALIGNMENT;
     101    return rc;
     102}
     103#endif
     104
     105
     106/**
     107 * Handles all Hyper-V hypercalls.
    39108 *
    40109 * @returns VBox status code.
    41110 * @param   pVCpu           Pointer to the VMCPU.
    42111 * @param   pCtx            Pointer to the guest-CPU context.
     112 *
     113 * @thread  EMT.
     114 * @remarks Guest RIP may or may not have been incremented at this point.
    43115 */
    44116VMM_INT_DECL(int) gimHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
    45117{
    46     NOREF(pCtx);
     118#ifndef IN_RING3
     119    return VINF_GIM_R3_HYPERCALL;
     120#else
    47121    PVM pVM = pVCpu->CTX_SUFF(pVM);
     122
     123    /*
     124     * Verify that hypercalls are enabled.
     125     */
    48126    if (!MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVM->gim.s.u.Hv.u64HypercallMsr))
    49127        return VERR_GIM_HYPERCALLS_NOT_ENABLED;
    50128
    51     /** @todo Handle hypercalls. Fail for now */
    52     return VERR_GIM_IPE_3;
     129    /*
     130     * Verify guest is in ring-0 protected mode.
     131     */
     132    uint32_t uCpl = CPUMGetGuestCPL(pVCpu);
     133    if (   uCpl
     134        || CPUMIsGuestInRealModeEx(pCtx))
     135    {
     136        return VERR_GIM_HYPERCALL_ACCESS_DENIED;
     137    }
     138
     139    /*
     140     * Get the hypercall operation code and modes.
     141     */
     142    const bool       fIs64BitMode     = CPUMIsGuestIn64BitCodeEx(pCtx);
     143    const uint64_t   uHyperIn         = fIs64BitMode ? pCtx->rcx : (pCtx->rdx << 32) | pCtx->eax;
     144    const uint16_t   uHyperOp         = GIM_HV_HYPERCALL_IN_CALL_CODE(uHyperIn);
     145    const bool       fHyperFast       = GIM_HV_HYPERCALL_IN_IS_FAST(uHyperIn);
     146    const uint16_t   cHyperReps       = GIM_HV_HYPERCALL_IN_REP_COUNT(uHyperIn);
     147    const uint16_t   idxHyperRepStart = GIM_HV_HYPERCALL_IN_REP_START_IDX(uHyperIn);
     148    uint64_t         cHyperRepsDone   = 0;
     149
     150    int rc     = VINF_SUCCESS;
     151    int rcHv   = GIM_HV_STATUS_OPERATION_DENIED;
     152    PGIMHV pHv = &pVM->gim.s.u.Hv;
     153
     154    /*
     155     * Validate common hypercall input parameters.
     156     */
     157    if (   !GIM_HV_HYPERCALL_IN_RSVD_1(uHyperIn)
     158        && !GIM_HV_HYPERCALL_IN_RSVD_2(uHyperIn)
     159        && !GIM_HV_HYPERCALL_IN_RSVD_3(uHyperIn))
     160    {
     161        /*
     162         * Perform the hypercall.
     163         */
     164        switch (uHyperOp)
     165        {
     166            case GIM_HV_HYPERCALL_OP_RETREIVE_DEBUG_DATA:   /* Non-rep, memory IO. */
     167            {
     168                if (pHv->uPartFlags & GIM_HV_PART_FLAGS_DEBUGGING)
     169                {
     170                    RTGCPHYS GCPhysOut;
     171                    rc = gimHvReadSlowHypercallParams(pVM, pCtx, fIs64BitMode, NULL /*pGCPhysIn*/, &GCPhysOut, &rcHv);
     172                    if (   RT_SUCCESS(rc)
     173                        && rcHv == GIM_HV_STATUS_SUCCESS)
     174                    {
     175                        rc = gimR3HvHypercallRetrieveDebugData(pVM, GCPhysOut, &rcHv);
     176                        if (RT_FAILURE(rc))
     177                            LogRelMax(10, ("GIM: HyperV: gimR3HvHypercallRetrieveDebugData failed. rc=%Rrc\n", rc));
     178                    }
     179                }
     180                else
     181                    rcHv = GIM_HV_STATUS_ACCESS_DENIED;
     182                break;
     183            }
     184
     185            case GIM_HV_HYPERCALL_OP_POST_DEBUG_DATA:   /* Non-rep, memory IO. */
     186            {
     187                if (pHv->uPartFlags & GIM_HV_PART_FLAGS_DEBUGGING)
     188                {
     189                    RTGCPHYS GCPhysOut;
     190                    rc = gimHvReadSlowHypercallParams(pVM, pCtx, fIs64BitMode, NULL /*pGCPhysIn*/, &GCPhysOut, &rcHv);
     191                    if (   RT_SUCCESS(rc)
     192                        && rcHv == GIM_HV_STATUS_SUCCESS)
     193                    {
     194                        rc = gimR3HvHypercallPostDebugData(pVM, GCPhysOut, &rcHv);
     195                        if (RT_FAILURE(rc))
     196                            LogRelMax(10, ("GIM: HyperV: gimR3HvHypercallPostDebugData failed. rc=%Rrc\n", rc));
     197                    }
     198                }
     199                else
     200                    rcHv = GIM_HV_STATUS_ACCESS_DENIED;
     201                break;
     202            }
     203
     204            case GIM_HV_HYPERCALL_OP_RESET_DEBUG_SESSION:   /* Non-rep, fast (register IO). */
     205            {
     206                if (pHv->uPartFlags & GIM_HV_PART_FLAGS_DEBUGGING)
     207                {
     208                    uint32_t fFlags = 0;
     209                    if (!fHyperFast)
     210                    {
     211                        rc = gimHvReadSlowHypercallParams(pVM, pCtx, fIs64BitMode, NULL /*pGCPhysIn*/, NULL /*pGCPhysOut*/,
     212                                                            &rcHv);
     213                        if (   RT_SUCCESS(rc)
     214                            && rcHv == GIM_HV_STATUS_SUCCESS)
     215                        {
     216                            PGIMHVDEBUGRESETIN pIn = (PGIMHVDEBUGRESETIN)pHv->pbHypercallIn;
     217                            fFlags = pIn->fFlags;
     218                        }
     219                    }
     220                    else
     221                    {
     222                        rcHv = GIM_HV_STATUS_SUCCESS;
     223                        fFlags = fIs64BitMode ? pCtx->rdx : pCtx->ebx;
     224                    }
     225
     226                    /*
     227                     * Since we don't really maintain our own buffers for the debug
     228                     * communication channel, we don't have anything to flush.
     229                     */
     230                    if (rcHv == GIM_HV_STATUS_SUCCESS)
     231                    {
     232                        if (!fFlags)
     233                            rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     234                    }
     235                }
     236                else
     237                    rcHv = GIM_HV_STATUS_ACCESS_DENIED;
     238                break;
     239            }
     240
     241            default:
     242                rcHv = GIM_HV_STATUS_INVALID_HYPERCALL_CODE;
     243                break;
     244        }
     245    }
     246    else
     247        rcHv = GIM_HV_STATUS_INVALID_HYPERCALL_INPUT;
     248
     249    /*
     250     * Update the guest with results of the hypercall.
     251     */
     252    if (RT_SUCCESS(rc))
     253    {
     254        if (fIs64BitMode)
     255            pCtx->rax = (cHyperRepsDone << 32) | rcHv;
     256        else
     257        {
     258            pCtx->edx = cHyperRepsDone;
     259            pCtx->eax = rcHv;
     260        }
     261    }
     262
     263    return rc;
     264#endif
    53265}
    54266
     
    122334 * @param   pRange      The range this MSR belongs to.
    123335 * @param   puValue     Where to store the MSR value read.
     336 *
     337 * @thread  EMT.
    124338 */
    125339VMM_INT_DECL(VBOXSTRICTRC) gimHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
     
    195409        case MSR_GIM_HV_CRASH_P4: *puValue = pHv->uCrashP4;   return VINF_SUCCESS;
    196410
     411        case MSR_GIM_HV_DEBUG_OPTIONS_MSR:
     412        {
     413            if (pHv->fIsVendorMsHv)
     414            {
     415                *puValue = GIM_HV_DEBUG_OPTIONS_MSR_ENABLE;
     416                return VINF_SUCCESS;
     417            }
     418            return VERR_CPUM_RAISE_GP_0;
     419        }
     420
    197421        default:
    198422        {
     
    201425            if (s_cTimes++ < 20)
    202426                LogRel(("GIM: HyperV: Unknown/invalid RdMsr (%#x) -> #GP(0)\n", idMsr));
     427#else
     428            return VINF_CPUM_R3_MSR_READ;
    203429#endif
    204430            LogFunc(("Unknown/invalid RdMsr (%#RX32) -> #GP(0)\n", idMsr));
     
    222448 * @param   pRange      The range this MSR belongs to.
    223449 * @param   uRawValue   The raw value with the ignored bits not masked.
     450 *
     451 * @thread  EMT.
    224452 */
    225453VMM_INT_DECL(VBOXSTRICTRC) gimHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue)
     
    253481                gimR3HvDisableHypercallPage(pVM);
    254482                pHv->u64HypercallMsr &= ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT;
     483                LogRel(("GIM: HyperV: Hypercalls disabled via Guest OS ID Msr\n"));
    255484            }
    256485            else
     
    286515            return VINF_CPUM_R3_MSR_WRITE;
    287516#else  /* IN_RING3 */
     517# if 0
    288518            /*
    289519             * For now ignore writes to the hypercall MSR (i.e. keeps it disabled).
     
    292522             */
    293523            return VINF_SUCCESS;
    294 # if 0
     524# else
    295525            /* First, update all but the hypercall enable bit. */
    296526            pHv->u64HypercallMsr = (uRawValue & ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT);
     
    399629            return VERR_CPUM_RAISE_GP_0;
    400630
     631        case MSR_GIM_HV_DEBUG_OPTIONS_MSR:
     632        {
     633            if (pHv->fIsVendorMsHv)
     634                return VINF_SUCCESS;
     635            return VERR_CPUM_RAISE_GP_0;
     636        }
     637
    401638        default:
    402639        {
     
    406643                LogRel(("GIM: HyperV: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr,
    407644                        uRawValue & UINT64_C(0xffffffff00000000), uRawValue & UINT64_C(0xffffffff)));
     645#else
     646            return VINF_CPUM_R3_MSR_WRITE;
    408647#endif
    409648            LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue));
     
    415654}
    416655
     656
     657/**
     658 * Whether we need to trap #UD exceptions in the guest.
     659 *
     660 * We only need to trap #UD exceptions for raw-mode guests when hypercalls are
     661 * enabled. For HM VMs, the hypercall would be handled via the
     662 * VMCALL/VMMCALL VM-exit.
     663 *
     664 * @param   pVCpu       Pointer to the VMCPU.
     665 */
     666VMM_INT_DECL(bool) gimHvShouldTrapXcptUD(PVMCPU pVCpu)
     667{
     668    PVM pVM = pVCpu->CTX_SUFF(pVM);
     669    if (   !HMIsEnabled(pVM)
     670        && gimHvAreHypercallsEnabled(pVCpu))
     671        return true;
     672    return false;
     673}
     674
     675
     676/**
     677 * Exception handler for #UD.
     678 *
     679 * @param   pVCpu       Pointer to the VMCPU.
     680 * @param   pCtx        Pointer to the guest-CPU context.
     681 * @param   pDis        Pointer to the disassembled instruction state at RIP.
     682 *                      Optional, can be NULL.
     683 *
     684 * @thread  EMT.
     685 */
     686VMM_INT_DECL(int) gimHvXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis)
     687{
     688    /*
     689     * If we didn't ask for #UD to be trapped, bail.
     690     */
     691    PVM pVM = pVCpu->CTX_SUFF(pVM);
     692    if (!gimHvShouldTrapXcptUD(pVCpu))
     693        return VERR_GIM_OPERATION_FAILED;
     694
     695    int rc = VINF_SUCCESS;
     696    if (!pDis)
     697    {
     698        /*
     699         * Disassemble the instruction at RIP to figure out if it's the Intel VMCALL instruction
     700         * or the AMD VMMCALL instruction and if so, handle it as a hypercall.
     701         */
     702        DISCPUSTATE Dis;
     703        rc = EMInterpretDisasCurrent(pVM, pVCpu, &Dis, NULL /* pcbInstr */);
     704        pDis = &Dis;
     705    }
     706
     707    if (RT_SUCCESS(rc))
     708    {
     709        CPUMCPUVENDOR enmGuestCpuVendor = CPUMGetGuestCpuVendor(pVM);
     710        if (   (   pDis->pCurInstr->uOpcode == OP_VMCALL
     711                && (   enmGuestCpuVendor == CPUMCPUVENDOR_INTEL
     712                    || enmGuestCpuVendor == CPUMCPUVENDOR_VIA))
     713            || (   pDis->pCurInstr->uOpcode == OP_VMMCALL
     714                && enmGuestCpuVendor == CPUMCPUVENDOR_AMD))
     715        {
     716            /*
     717             * Make sure guest ring-0 is the one making the hypercall.
     718             */
     719            if (CPUMGetGuestCPL(pVCpu))
     720                return VERR_GIM_HYPERCALL_ACCESS_DENIED;
     721
     722            /*
     723             * Perform the hypercall and update RIP.
     724             */
     725            rc = gimHvHypercall(pVCpu, pCtx);
     726            pCtx->rip += pDis->cbInstr;
     727            return rc;
     728        }
     729        return VERR_GIM_OPERATION_FAILED;
     730    }
     731    return VERR_GIM_OPERATION_FAILED;
     732}
     733
  • trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp

    r57851 r57989  
    4545 * @param   pVCpu           Pointer to the VMCPU.
    4646 * @param   pCtx            Pointer to the guest-CPU context.
     47 *
     48 * @remarks Guest RIP may or may not have been incremented at this point.
    4749 */
    4850VMM_INT_DECL(int) gimKvmHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
     
    353355 * @param   pDis        Pointer to the disassembled instruction state at RIP.
    354356 *                      Optional, can be NULL.
     357 *
     358 * @thread  EMT.
    355359 */
    356360VMM_INT_DECL(int) gimKvmXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis)
     
    364368        return VERR_GIM_OPERATION_FAILED;
    365369
    366     /*
    367      * Make sure guest ring-0 is the one making the hypercall.
    368      */
    369     if (CPUMGetGuestCPL(pVCpu))
    370         return VERR_GIM_HYPERCALL_ACCESS_DENIED;
    371 
    372370    int rc = VINF_SUCCESS;
    373371    if (!pDis)
     
    391389            || pDis->pCurInstr->uOpcode == OP_VMMCALL)
    392390        {
     391            /*
     392             * Make sure guest ring-0 is the one making the hypercall.
     393             */
     394            if (CPUMGetGuestCPL(pVCpu))
     395                return VERR_GIM_HYPERCALL_ACCESS_DENIED;
     396
    393397            if (   pDis->pCurInstr->uOpcode != pKvm->uOpCodeNative
    394398                && HMIsEnabled(pVM))
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r57857 r57989  
    51565156        {
    51575157            rc = GIMHypercall(pVCpu, pCtx);
    5158             if (RT_SUCCESS(rc))
     5158            if (   rc == VINF_SUCCESS
     5159                || rc == VINF_GIM_R3_HYPERCALL)
    51595160            {
    51605161                /* If the hypercall changes anything other than guest general-purpose registers,
    51615162                   we would need to reload the guest changed bits here before VM-reentry. */
    51625163                hmR0SvmUpdateRip(pVCpu, pCtx, 3);
    5163                 return VINF_SUCCESS;
     5164                return rc;
    51645165            }
    51655166        }
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r57886 r57989  
    1015310153
    1015410154        rc = GIMHypercall(pVCpu, pMixedCtx);
    10155         if (RT_SUCCESS(rc))
     10155        if (   rc == VINF_SUCCESS
     10156            || rc == VINF_GIM_R3_HYPERCALL)
    1015610157        {
    1015710158            /* If the hypercall changes anything other than guest general-purpose registers,
    1015810159               we would need to reload the guest changed bits here before VM-reentry. */
    1015910160            hmR0VmxAdvanceGuestRip(pVCpu, pMixedCtx, pVmxTransient);
    10160             return VINF_SUCCESS;
     10161            return rc;
    1016110162        }
    1016210163    }
  • trunk/src/VBox/VMM/VMMR3/EMHM.cpp

    r57358 r57989  
    4242#include "EMInternal.h"
    4343#include <VBox/vmm/vm.h>
     44#include <VBox/vmm/gim.h>
    4445#include <VBox/vmm/cpumdis.h>
    4546#include <VBox/dis.h>
  • trunk/src/VBox/VMM/VMMR3/EMRaw.cpp

    r57358 r57989  
    4343#include "EMInternal.h"
    4444#include <VBox/vmm/vm.h>
     45#include <VBox/vmm/gim.h>
    4546#include <VBox/vmm/cpumdis.h>
    4647#include <VBox/dis.h>
  • trunk/src/VBox/VMM/VMMR3/GIM.cpp

    r57358 r57989  
    7272static DECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM);
    7373static DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass);
    74 static FNPGMPHYSHANDLER gimR3Mmio2WriteHandler;
     74static FNPGMPHYSHANDLER  gimR3Mmio2WriteHandler;
    7575
    7676
     
    410410 * Registers the GIM device with VMM.
    411411 *
    412  * @param   pVM         Pointer to the VM.
    413  * @param   pDevIns     Pointer to the GIM device instance.
    414  */
    415 VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns)
    416 {
    417     pVM->gim.s.pDevInsR3 = pDevIns;
     412 * @param   pVM             Pointer to the VM.
     413 * @param   pDevInsR3       Pointer to the GIM device instance.
     414 * @param   pDebugStream    Pointer to the GIM device debug connection, can be
     415 *                          NULL.
     416 */
     417VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevInsR3, PPDMISTREAM pDebugStreamR3)
     418{
     419    pVM->gim.s.pDevInsR3 = pDevInsR3;
     420    pVM->gim.s.pDebugStreamR3 = pDebugStreamR3;
     421}
     422
     423
     424/**
     425 * Read data from a host debug session.
     426 *
     427 * @returns VBox status code.
     428 *
     429 * @param   pVM         Pointer to the VM.
     430 * @param   pvRead      The read buffer.
     431 * @param   pcbRead     The size of the read buffer as well as where to store
     432 *                      the number of bytes read.
     433 * @thread  EMT.
     434 */
     435VMMR3_INT_DECL(int) GIMR3DebugRead(PVM pVM, void *pvRead, size_t *pcbRead)
     436{
     437    PPDMISTREAM pDebugStream = pVM->gim.s.pDebugStreamR3;
     438    if (pDebugStream)
     439        return pDebugStream->pfnRead(pDebugStream, pvRead, pcbRead);
     440    return VERR_GIM_NO_DEBUG_CONNECTION;
     441}
     442
     443
     444/**
     445 * Write data to a host debug session.
     446 *
     447 * @returns VBox status code.
     448 *
     449 * @param   pVM         Pointer to the VM.
     450 * @param   pvWrite     The write buffer.
     451 * @param   pcbWrite    The size of the write buffer as well as where to store
     452 *                      the number of bytes written.
     453 * @thread  EMT.
     454 */
     455VMMR3_INT_DECL(int) GIMR3DebugWrite(PVM pVM, void *pvWrite, size_t *pcbWrite)
     456{
     457    PPDMISTREAM pDebugStream = pVM->gim.s.pDebugStreamR3;
     458    if (pDebugStream)
     459        return pDebugStream->pfnWrite(pDebugStream, pvWrite, pcbWrite);
     460    return VERR_GIM_NO_DEBUG_CONNECTION;
    418461}
    419462
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r57506 r57989  
    2727#include <iprt/string.h>
    2828#include <iprt/mem.h>
     29#include <iprt/semaphore.h>
    2930#include <iprt/spinlock.h>
    3031
    3132#include <VBox/vmm/cpum.h>
     33#include <VBox/vmm/mm.h>
    3234#include <VBox/vmm/ssm.h>
    3335#include <VBox/vmm/vm.h>
     
    4042*   Defined Constants And Macros                                                                                                 *
    4143*********************************************************************************************************************************/
    42 //#define GIMHV_HYPERCALL                 "GIMHvHypercall"
    43 
    4444/**
    4545 * GIM Hyper-V saved-state version.
     
    4747#define GIM_HV_SAVED_STATE_VERSION          UINT32_C(1)
    4848
    49 
    50 /*********************************************************************************************************************************
    51 *   Global Variables                                                                                                             *
    52 *********************************************************************************************************************************/
    5349#ifdef VBOX_WITH_STATISTICS
    5450# define GIMHV_MSRRANGE(a_uFirst, a_uLast, a_szName) \
     
    5955#endif
    6056
     57
     58/*********************************************************************************************************************************
     59*   Global Variables                                                                                                             *
     60*********************************************************************************************************************************/
    6161/**
    6262 * Array of MSR ranges supported by Hyper-V.
     
    7575    GIMHV_MSRRANGE(MSR_GIM_HV_RANGE9_START,  MSR_GIM_HV_RANGE9_END,  "Hyper-V range 9"),
    7676    GIMHV_MSRRANGE(MSR_GIM_HV_RANGE10_START, MSR_GIM_HV_RANGE10_END, "Hyper-V range 10"),
    77     GIMHV_MSRRANGE(MSR_GIM_HV_RANGE11_START, MSR_GIM_HV_RANGE11_END, "Hyper-V range 11")
     77    GIMHV_MSRRANGE(MSR_GIM_HV_RANGE11_START, MSR_GIM_HV_RANGE11_END, "Hyper-V range 11"),
     78    GIMHV_MSRRANGE(MSR_GIM_HV_RANGE12_START, MSR_GIM_HV_RANGE12_END, "Hyper-V range 12")
    7879};
    7980#undef GIMHV_MSRRANGE
     81
     82
     83/*********************************************************************************************************************************
     84*   Internal Functions                                                                                                           *
     85*********************************************************************************************************************************/
     86static int    gimR3HvInitDebugSupport(PVM pVM);
     87static void   gimR3HvTermDebugSupport(PVM pVM);
    8088
    8189
     
    105113    rc = CFGMR3QueryStringDef(pCfgNode, "VendorID", szVendor, sizeof(szVendor), "VBoxVBoxVBox");
    106114    AssertLogRelRCReturn(rc, rc);
     115
     116    if (!RTStrNCmp(szVendor, GIM_HV_VENDOR_MICROSOFT, sizeof(GIM_HV_VENDOR_MICROSOFT) - 1))
     117        pHv->fIsVendorMsHv = true;
    107118
    108119    /*
     
    129140
    130141        /* Miscellaneous features. */
    131         pHv->uMiscFeat = GIM_HV_MISC_FEAT_TIMER_FREQ
    132                        | GIM_HV_MISC_FEAT_GUEST_CRASH_MSRS;
     142        pHv->uMiscFeat = 0
     143                       //| GIM_HV_MISC_FEAT_GUEST_DEBUGGING
     144                       //| GIM_HV_MISC_FEAT_XMM_HYPERCALL_INPUT
     145                       | GIM_HV_MISC_FEAT_TIMER_FREQ
     146                       | GIM_HV_MISC_FEAT_GUEST_CRASH_MSRS
     147                       //| GIM_HV_MISC_FEAT_DEBUG_MSRS
     148                       ;
    133149
    134150        /* Hypervisor recommendations to the guest. */
    135151        pHv->uHyperHints = GIM_HV_HINT_MSR_FOR_SYS_RESET
    136152                         | GIM_HV_HINT_RELAX_TIME_CHECKS;
     153
     154        /* Expose more if we're posing as Microsoft. */
     155        if (pHv->fIsVendorMsHv)
     156        {
     157            pHv->uMiscFeat  |= GIM_HV_MISC_FEAT_GUEST_DEBUGGING
     158                             | GIM_HV_MISC_FEAT_DEBUG_MSRS;
     159
     160            pHv->uPartFlags |= GIM_HV_PART_FLAGS_DEBUGGING;
     161        }
    137162    }
    138163
     
    190215    HyperLeaf.uLeaf        = UINT32_C(0x40000000);
    191216    HyperLeaf.uEax         = UINT32_C(0x40000006); /* Minimum value for Hyper-V is 0x40000005. */
    192     /* Don't report vendor as 'Microsoft Hv' by default, see @bugref{7270#c152}. */
     217    /*
     218     * Don't report vendor as 'Microsoft Hv'[1] by default, see @bugref{7270#c152}.
     219     * [1]: ebx=0x7263694d ('rciM') ecx=0x666f736f ('foso') edx=0x76482074 ('vH t')
     220     */
    193221    {
    194222        uint32_t uVendorEbx;
     
    258286        pHv->uCrashCtl = MSR_GIM_HV_CRASH_CTL_NOTIFY_BIT;
    259287
     288    /*
     289     * Setup guest-host debugging connection.
     290     */
     291    if (pHv->uMiscFeat & GIM_HV_MISC_FEAT_GUEST_DEBUGGING)
     292    {
     293        rc = gimR3HvInitDebugSupport(pVM);
     294        AssertLogRelRCReturn(rc, rc);
     295
     296        /*
     297         * Pretend that hypercalls are enabled unconditionally when posing as Microsoft,
     298         * as Windows guests invoke debug hypercalls before enabling them via the hypercall MSR.
     299         */
     300        if (pHv->fIsVendorMsHv)
     301        {
     302            pHv->u64HypercallMsr |= MSR_GIM_HV_HYPERCALL_ENABLE_BIT;
     303            for (VMCPUID i = 0; i < pVM->cCpus; i++)
     304                VMMHypercallsEnable(&pVM->aCpus[i]);
     305        }
     306    }
     307
    260308    return VINF_SUCCESS;
    261309}
     
    323371{
    324372    gimR3HvReset(pVM);
     373
     374    PGIMHV pHv = &pVM->gim.s.u.Hv;
     375    if (pHv->uMiscFeat & GIM_HV_MISC_FEAT_GUEST_DEBUGGING)
     376        gimR3HvTermDebugSupport(pVM);
    325377    return VINF_SUCCESS;
    326378}
     
    352404 *
    353405 * @param   pVM     Pointer to the VM.
    354  * @thread EMT(0).
     406 *
     407 * @thread  EMT(0).
    355408 */
    356409VMMR3_INT_DECL(void) gimR3HvReset(PVM pVM)
     
    375428
    376429    /*
    377      * Reset MSRs.
     430     * Reset MSRs (Careful! Don't reset non-zero MSRs).
    378431     */
    379432    pHv->u64GuestOsIdMsr = 0;
     
    385438    pHv->uCrashP3        = 0;
    386439    pHv->uCrashP4        = 0;
     440
     441    /* Extra faking required while posing as Microsoft, see gimR3HvInit(). */
     442    if (   (pHv->uMiscFeat & GIM_HV_MISC_FEAT_GUEST_DEBUGGING)
     443        && pHv->fIsVendorMsHv)
     444    {
     445        pHv->u64HypercallMsr |= MSR_GIM_HV_HYPERCALL_ENABLE_BIT;
     446        for (VMCPUID i = 0; i < pVM->cCpus; i++)
     447            VMMHypercallsEnable(&pVM->aCpus[i]);
     448    }
    387449}
    388450
     
    870932}
    871933
     934
     935/**
     936 * Initializes Hyper-V guest debugging support.
     937 *
     938 * @returns VBox status code.
     939 * @param   pVM     Pointer to the VM.
     940 */
     941static int gimR3HvInitDebugSupport(PVM pVM)
     942{
     943    int rc = VINF_SUCCESS;
     944    PGIMHV pHv = &pVM->gim.s.u.Hv;
     945    pHv->pbHypercallIn = (uint8_t *)RTMemAllocZ(GIM_HV_PAGE_SIZE);
     946    if (RT_LIKELY(pHv->pbHypercallIn))
     947    {
     948        pHv->pbHypercallOut = (uint8_t *)RTMemAllocZ(GIM_HV_PAGE_SIZE);
     949        if (RT_LIKELY(pHv->pbHypercallOut))
     950            return VINF_SUCCESS;
     951        RTMemFree(pHv->pbHypercallIn);
     952    }
     953    return VERR_NO_MEMORY;
     954}
     955
     956
     957/**
     958 * Terminates Hyper-V guest debugging support.
     959 *
     960 * @param   pVM     Pointer to the VM.
     961 */
     962static void gimR3HvTermDebugSupport(PVM pVM)
     963{
     964    PGIMHV pHv = &pVM->gim.s.u.Hv;
     965    RTMemFree(pHv->pbHypercallIn);
     966    pHv->pbHypercallIn = NULL;
     967
     968    RTMemFree(pHv->pbHypercallOut);
     969    pHv->pbHypercallOut = NULL;
     970}
     971
     972
     973/**
     974 * Reads data from a debugger connection, asynchronous.
     975 *
     976 * @returns VBox status code.
     977 * @param   pVM         Pointer to the VM.
     978 * @param   pvBuf       Where to read the data.
     979 * @param   cbBuf       Size of the read buffer @a pvBuf.
     980 * @param   pcbRead     Where to store how many bytes were really read.
     981 * @param   cMsTimeout  Timeout of the read operation in milliseconds.
     982 *
     983 * @thread  EMT.
     984 */
     985static int gimR3HvDebugRead(PVM pVM, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead, uint32_t cMsTimeout)
     986{
     987    NOREF(cMsTimeout);      /** @todo implement */
     988    PGIMHV pHv = &pVM->gim.s.u.Hv;
     989    AssertCompile(sizeof(size_t) >= sizeof(uint32_t));
     990    size_t cbRead = cbBuf;
     991    int rc = GIMR3DebugRead(pVM, pvBuf, &cbRead);
     992    *pcbRead = (uint32_t)cbRead;
     993    return rc;
     994}
     995
     996
     997/**
     998 * Writes data to the debugger connection, asynchronous.
     999 *
     1000 * @returns VBox status code.
     1001 * @param   pVM         Pointer to the VM.
     1002 * @param   pvBuf       Pointer to the data to be written.
     1003 * @param   cbBuf       Size of the write buffer @a pvBuf.
     1004 * @param   pcbWritten  Where to store how many bytes were really written.
     1005 *
     1006 * @thread  EMT.
     1007 */
     1008static int gimR3HvDebugWrite(PVM pVM, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     1009{
     1010    PGIMHV pHv = &pVM->gim.s.u.Hv;
     1011    AssertCompile(sizeof(size_t) >= sizeof(uint32_t));
     1012    size_t cbWrite = cbBuf;
     1013    int rc = GIMR3DebugWrite(pVM, pvBuf, &cbWrite);
     1014    *pcbWritten = (uint32_t)cbWrite;
     1015    return rc;
     1016}
     1017
     1018
     1019/**
     1020 * Performs the HvPostDebugData hypercall.
     1021 *
     1022 * @returns VBox status code.
     1023 * @param   pVM         Pointer to the VM.
     1024 * @param   GCPhysOut   Where to write the hypercall output parameters after
     1025 *                      performing the hypercall.
     1026 * @param   prcHv       Where to store the result of the hypercall operation.
     1027 *
     1028 * @thread  EMT.
     1029 */
     1030VMMR3_INT_DECL(int) gimR3HvHypercallPostDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv)
     1031{
     1032    AssertPtr(pVM);
     1033    AssertPtr(prcHv);
     1034    PGIMHV pHv = &pVM->gim.s.u.Hv;
     1035    int    rcHv = GIM_HV_STATUS_OPERATION_DENIED;
     1036
     1037    /*
     1038     * Grab the parameters.
     1039     */
     1040    PGIMHVDEBUGPOSTIN pIn = (PGIMHVDEBUGPOSTIN)pHv->pbHypercallIn;
     1041    AssertPtrReturn(pIn, VERR_GIM_IPE_1);
     1042    uint32_t   cbWrite = pIn->cbWrite;
     1043    uint32_t   fFlags = pIn->fFlags;
     1044    uint8_t   *pbData = ((uint8_t *)pIn) + sizeof(PGIMHVDEBUGPOSTIN);
     1045
     1046    PGIMHVDEBUGPOSTOUT pOut = (PGIMHVDEBUGPOSTOUT)pHv->pbHypercallOut;
     1047    AssertPtrReturn(pOut, VERR_GIM_IPE_2);
     1048    uint32_t *pcbPendingWrite = &pOut->cbPending;
     1049
     1050    /*
     1051     * Perform the hypercall.
     1052     */
     1053#if 0
     1054    /* Currently disabled as Windows 10 guest passes us undocumented flags. */
     1055    if (fFlags & ~GIM_HV_DEBUG_POST_OPTIONS_MASK))
     1056        rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     1057#endif
     1058    if (cbWrite > GIM_HV_DEBUG_MAX_DATA_SIZE)
     1059        rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     1060    else if (!cbWrite)
     1061        rcHv = GIM_HV_STATUS_SUCCESS;
     1062    else if (cbWrite > 0)
     1063    {
     1064        bool fIgnorePacket = false;
     1065        if (pHv->fIsVendorMsHv)
     1066        {
     1067            /*
     1068             * Windows guests sends us ethernet frames over the Hyper-V debug connection.
     1069             * It sends DHCP/ARP queries with zero'd out MAC addresses and requires fudging up the
     1070             * packets somewhere.
     1071             *
     1072             * The Microsoft WinDbg debugger talks UDP and thus only expects the actual debug
     1073             * protocol payload.
     1074             *
     1075             * At present, we only handle guests configured with the "nodhcp" option. This makes
     1076             * the guest send ARP queries with a self-chosen IP and after a couple of attempts of
     1077             * receiving no replies, the guest picks its own IP address. After this, the guest
     1078             * starts sending the UDP packets we require. We thus ignore the initial ARP packets
     1079             * (and to be safe all non-UDP packets) until the guest eventually starts talking
     1080             * UDP. Then we can finally feed the UDP payload over the debug connection.
     1081             */
     1082            if (cbWrite > sizeof(RTNETETHERHDR))
     1083            {
     1084                PRTNETETHERHDR pEtherHdr = (PRTNETETHERHDR)pbData;
     1085                if (pEtherHdr->EtherType != RT_H2N_U16_C(RTNET_ETHERTYPE_IPV4))
     1086                    fIgnorePacket = true;       /* Supress passing ARP and other non IPv4 frames to debugger. */
     1087                else if (cbWrite > sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN)
     1088                {
     1089                    /* Extract UDP payload, recording the guest IP address to pass to the debugger. */
     1090                    PRTNETIPV4 pIp4Hdr = (PRTNETIPV4)(pbData + sizeof(RTNETETHERHDR));
     1091                    if (   pIp4Hdr->ip_v == 4
     1092                        && pIp4Hdr->ip_p == RTNETIPV4_PROT_UDP)
     1093                    {
     1094                        pHv->DbgGuestAddr = pIp4Hdr->ip_src;
     1095                        pbData += sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN;
     1096                        cbWrite -= sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN;
     1097                    }
     1098                    else
     1099                        fIgnorePacket = true;   /* Supress passing non-UDP packets to the debugger. */
     1100                }
     1101            }
     1102        }
     1103
     1104        if (!fIgnorePacket)
     1105        {
     1106            uint32_t cbReallyWritten = 0;
     1107            int rc2 = gimR3HvDebugWrite(pVM, pbData, cbWrite, &cbReallyWritten);
     1108            if (   RT_SUCCESS(rc2)
     1109                && cbReallyWritten == cbWrite)
     1110            {
     1111                *pcbPendingWrite = 0;
     1112                rcHv = GIM_HV_STATUS_SUCCESS;
     1113            }
     1114            else
     1115            {
     1116                /*
     1117                 * No need to update "*pcbPendingWrite" here as the guest isn't supposed to/doesn't
     1118                 * look at any of the output parameters when we fail the hypercall operation.
     1119                 */
     1120                rcHv = GIM_HV_STATUS_INSUFFICIENT_BUFFERS;
     1121            }
     1122        }
     1123        else
     1124        {
     1125            /* Pretend success. */
     1126            *pcbPendingWrite = 0;
     1127            rcHv = GIM_HV_STATUS_SUCCESS;
     1128        }
     1129    }
     1130
     1131    /*
     1132     * Update the guest memory with result.
     1133     */
     1134    int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysOut, pHv->pbHypercallOut, sizeof(GIMHVDEBUGPOSTOUT));
     1135    if (RT_FAILURE(rc))
     1136    {
     1137        LogRelMax(10, ("GIM: HyperV: HvPostDebugData failed to update guest memory. rc=%Rrc\n", rc));
     1138        rc = VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED;
     1139    }
     1140
     1141    *prcHv = rcHv;
     1142    return rc;
     1143}
     1144
     1145
     1146/**
     1147 * Performs the HvRetrieveDebugData hypercall.
     1148 *
     1149 * @returns VBox status code.
     1150 * @param   pVM         Pointer to the VM.
     1151 * @param   GCPhysOut   Where to write the hypercall output parameters after
     1152 *                      performing the hypercall.
     1153 * @param   prcHv       Where to store the result of the hypercall operation.
     1154 *
     1155 * @thread  EMT.
     1156 */
     1157VMMR3_INT_DECL(int) gimR3HvHypercallRetrieveDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv)
     1158{
     1159    AssertPtr(pVM);
     1160    AssertPtr(prcHv);
     1161    PGIMHV pHv = &pVM->gim.s.u.Hv;
     1162    int    rcHv = GIM_HV_STATUS_OPERATION_DENIED;
     1163
     1164    /*
     1165     * Grab the parameters.
     1166     */
     1167    PGIMHVDEBUGRETRIEVEIN pIn = (PGIMHVDEBUGRETRIEVEIN)pHv->pbHypercallIn;
     1168    AssertPtrReturn(pIn, VERR_GIM_IPE_1);
     1169    uint32_t   cbRead = pIn->cbRead;
     1170    uint32_t   fFlags = pIn->fFlags;
     1171    uint64_t   uTimeout = pIn->u64Timeout;
     1172    uint32_t   cMsTimeout = (fFlags & GIM_HV_DEBUG_RETREIVE_LOOP) ? (uTimeout * 100) / RT_NS_1MS_64 : 0;
     1173
     1174    PGIMHVDEBUGRETRIEVEOUT pOut = (PGIMHVDEBUGRETRIEVEOUT)pHv->pbHypercallOut;
     1175    AssertPtrReturn(pOut, VERR_GIM_IPE_2);
     1176    uint32_t   *pcbReallyRead = &pOut->cbRead;
     1177    uint32_t   *pcbRemainingRead = &pOut->cbRemaining;
     1178    void       *pvData = ((uint8_t *)pOut) + sizeof(GIMHVDEBUGRETRIEVEOUT);
     1179
     1180    /*
     1181     * Perform the hypercall.
     1182     */
     1183    *pcbReallyRead    = 0;
     1184    *pcbRemainingRead = cbRead;
     1185#if 0
     1186    /* Currently disabled as Windows 10 guest passes us undocumented flags. */
     1187    if (fFlags & ~GIM_HV_DEBUG_RETREIVE_OPTIONS_MASK)
     1188        rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     1189#endif
     1190    if (cbRead > GIM_HV_DEBUG_MAX_DATA_SIZE)
     1191        rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     1192    else if (fFlags & GIM_HV_DEBUG_RETREIVE_TEST_ACTIVITY)
     1193        rcHv = GIM_HV_STATUS_SUCCESS; /** @todo implement this. */
     1194    else if (!cbRead)
     1195        rcHv = GIM_HV_STATUS_SUCCESS;
     1196    else if (cbRead > 0)
     1197    {
     1198        int rc2 = gimR3HvDebugRead(pVM, pvData, cbRead, pcbReallyRead, cMsTimeout);
     1199        Assert(*pcbReallyRead <= cbRead);
     1200        if (   RT_SUCCESS(rc2)
     1201            && *pcbReallyRead > 0)
     1202        {
     1203            uint8_t abFrame[sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + sizeof(RTNETUDP)];
     1204            if (   pHv->fIsVendorMsHv
     1205                && *pcbReallyRead + sizeof(abFrame) <= GIM_HV_PAGE_SIZE)
     1206            {
     1207                /*
     1208                 * Windows guests pumps ethernet frames over the Hyper-V debug connection as
     1209                 * explained in gimR3HvHypercallPostDebugData(). Here, we reconstruct the packet
     1210                 * with the guest's self-chosen IP ARP address we saved in pHv->DbgGuestAddr.
     1211                 *
     1212                 * Note! We really need to pass the minimum IPv4 header length. The Windows 10 guest
     1213                 * is -not- happy if we include the IPv4 options field, i.e. using sizeof(RTNETIPV4)
     1214                 * instead of RTNETIPV4_MIN_LEN.
     1215                 */
     1216                RT_ZERO(abFrame);
     1217                PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)&abFrame[0];
     1218                PRTNETIPV4     pIpHdr  = (PRTNETIPV4)    (pEthHdr + 1);
     1219                PRTNETUDP      pUdpHdr = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
     1220
     1221                /* Ethernet */
     1222                pEthHdr->EtherType = RT_H2N_U16_C(RTNET_ETHERTYPE_IPV4);
     1223                /* IPv4 */
     1224                pIpHdr->ip_v       = 4;
     1225                pIpHdr->ip_hl      = RTNETIPV4_MIN_LEN / sizeof(uint32_t);
     1226                pIpHdr->ip_tos     = 0;
     1227                pIpHdr->ip_len     = RT_H2N_U16((uint16_t)*pcbReallyRead + sizeof(RTNETUDP) + RTNETIPV4_MIN_LEN);
     1228                pIpHdr->ip_id      = 0;
     1229                pIpHdr->ip_off     = 0;
     1230                pIpHdr->ip_ttl     = 255;
     1231                pIpHdr->ip_p       = RTNETIPV4_PROT_UDP;
     1232                pIpHdr->ip_sum     = 0;
     1233                pIpHdr->ip_src.u   = 0;
     1234                pIpHdr->ip_dst.u   = pHv->DbgGuestAddr.u;
     1235                pIpHdr->ip_sum     = RTNetIPv4HdrChecksum(pIpHdr);
     1236                /* UDP */
     1237                pUdpHdr->uh_ulen   = RT_H2N_U16_C((uint16_t)*pcbReallyRead + sizeof(*pUdpHdr));
     1238
     1239                /* Make room by moving the payload and prepending the headers. */
     1240                uint8_t *pbData = (uint8_t *)pvData;
     1241                memmove(pbData + sizeof(abFrame), pbData, *pcbReallyRead);
     1242                memcpy(pbData, &abFrame[0], sizeof(abFrame));
     1243
     1244                /* Update the adjusted sizes. */
     1245                *pcbReallyRead += sizeof(abFrame);
     1246                *pcbRemainingRead = cbRead - *pcbReallyRead;
     1247            }
     1248            rcHv = GIM_HV_STATUS_SUCCESS;
     1249        }
     1250        else
     1251            rcHv = GIM_HV_STATUS_NO_DATA;
     1252    }
     1253
     1254    /*
     1255     * Update the guest memory with result.
     1256     */
     1257    int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysOut, pHv->pbHypercallOut, sizeof(GIMHVDEBUGRETRIEVEOUT) + *pcbReallyRead);
     1258    if (RT_FAILURE(rc))
     1259    {
     1260        LogRelMax(10, ("GIM: HyperV: HvRetrieveDebugData failed to update guest memory. rc=%Rrc\n", rc));
     1261        rc = VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED;
     1262    }
     1263
     1264    *prcHv = rcHv;
     1265    return rc;
     1266}
     1267
  • trunk/src/VBox/VMM/include/EMHandleRCTmpl.h

    r56287 r57989  
    232232            break;
    233233
     234        /*
     235         * GIM hypercall.
     236         */
     237        case VINF_GIM_R3_HYPERCALL:
     238            rc = GIMHypercall(pVCpu, pCtx);
     239            break;
     240
    234241#ifdef EMHANDLERC_WITH_HM
    235242        /*
  • trunk/src/VBox/VMM/include/GIMHvInternal.h

    r57158 r57989  
    2222#include <VBox/vmm/cpum.h>
    2323
     24#include <iprt/net.h>
    2425
    2526/** @name Hyper-V base feature identification.
     
    3233#define GIM_HV_BASE_FEAT_PART_TIME_REF_COUNT_MSR  RT_BIT(1)
    3334/** Basic Synthetic Interrupt Controller MSRs available. */
    34 #define GIM_HV_BASE_FEAT_BASIC_SYNTH_IC           RT_BIT(2)
     35#define GIM_HV_BASE_FEAT_BASIC_SYNIC_MSRS         RT_BIT(2)
    3536/** Synthetic Timer MSRs available. */
    36 #define GIM_HV_BASE_FEAT_SYNTH_TIMER_MSRS         RT_BIT(3)
     37#define GIM_HV_BASE_FEAT_STIMER_MSRS              RT_BIT(3)
    3738/** APIC access MSRs (EOI, ICR, TPR) available. */
    3839#define GIM_HV_BASE_FEAT_APIC_ACCESS_MSRS         RT_BIT(4)
     
    125126#define GIM_HV_MISC_FEAT_TIMER_FREQ               RT_BIT(8)
    126127/** Support for injecting synthetic machine checks. */
    127 #define GIM_HV_MISC_FEAT_INJECT_SYNTH_MC_XCPT     RT_BIT(9)
     128#define GIM_HV_MISC_FEAT_INJECT_SYNMC_XCPT        RT_BIT(9)
    128129/** Support for guest crash MSRs. */
    129130#define GIM_HV_MISC_FEAT_GUEST_CRASH_MSRS         RT_BIT(10)
     
    360361
    361362/** Start of range 11. */
    362 #define MSR_GIM_HV_RANGE11_START                  UINT32_C(0x40000100)
     363#define MSR_GIM_HV_RANGE11_START                  UINT32_C(0x400000FF)
     364/** Undocumented debug options MSR. */
     365#define MSR_GIM_HV_DEBUG_OPTIONS_MSR              UINT32_C(0x400000FF)
     366/** End of range 11. */
     367#define MSR_GIM_HV_RANGE11_END                    MSR_GIM_HV_DEBUG_OPTIONS_MSR
     368
     369/** Start of range 12. */
     370#define MSR_GIM_HV_RANGE12_START                  UINT32_C(0x40000100)
    363371/** Guest crash MSR 0. */
    364372#define MSR_GIM_HV_CRASH_P0                       UINT32_C(0x40000100)
     
    373381/** Guest crash control. */
    374382#define MSR_GIM_HV_CRASH_CTL                      UINT32_C(0x40000105)
    375 /** End of range 11. */
    376 #define MSR_GIM_HV_RANGE11_END                    MSR_GIM_HV_CRASH_CTL
     383/** End of range 12. */
     384#define MSR_GIM_HV_RANGE12_END                    MSR_GIM_HV_CRASH_CTL
    377385/** @} */
    378386
     
    447455/** @} */
    448456
     457/** @name Hyper-V hypercall op codes.
     458 * @{
     459 */
     460/** Post debug data to hypervisor. */
     461#define GIM_HV_HYPERCALL_OP_POST_DEBUG_DATA       0x69
     462/** Retreive debug data from hypervisor. */
     463#define GIM_HV_HYPERCALL_OP_RETREIVE_DEBUG_DATA   0x6A
     464/** Reset debug session. */
     465#define GIM_HV_HYPERCALL_OP_RESET_DEBUG_SESSION   0x6B
     466/** @} */
     467
     468/** @name Hyper-V hypercall inputs.
     469 * @{
     470 */
     471/** The hypercall call operation code. */
     472#define GIM_HV_HYPERCALL_IN_CALL_CODE(a)         ((a) & UINT64_C(0xffff))
     473/** Whether it's a fast (register based) hypercall or not (memory-based). */
     474#define GIM_HV_HYPERCALL_IN_IS_FAST(a)           RT_BOOL((a) & RT_BIT_64(16))
     475/** Total number of reps for a rep hypercall. */
     476#define GIM_HV_HYPERCALL_IN_REP_COUNT(a)         (((a) << 32) & UINT64_C(0xfff))
     477/** Rep start index for a rep hypercall. */
     478#define GIM_HV_HYPERCALL_IN_REP_START_IDX(a)     (((a) << 48) & UINT64_C(0xfff))
     479/** Reserved bits range 1. */
     480#define GIM_HV_HYPERCALL_IN_RSVD_1(a)            (((a) << 17) & UINT64_C(0x7fff))
     481/** Reserved bits range 2. */
     482#define GIM_HV_HYPERCALL_IN_RSVD_2(a)            (((a) << 44) & UINT64_C(0xf))
     483/** Reserved bits range 3. */
     484#define GIM_HV_HYPERCALL_IN_RSVD_3(a)            (((a) << 60) & UINT64_C(0x7))
     485/** @} */
     486
     487
     488/** @name Hyper-V hypercall status codes.
     489 * @{
     490 */
     491/** Success. */
     492#define GIM_HV_STATUS_SUCCESS                                        0x00
     493/** Unrecognized hypercall. */
     494#define GIM_HV_STATUS_INVALID_HYPERCALL_CODE                         0x02
     495/** Invalid hypercall input (rep count, rsvd bits). */
     496#define GIM_HV_STATUS_INVALID_HYPERCALL_INPUT                        0x03
     497/** Hypercall guest-physical address not 8-byte aligned or crosses page boundary. */
     498#define GIM_HV_STATUS_INVALID_ALIGNMENT                              0x04
     499/** Invalid hypercall parameters. */
     500#define GIM_HV_STATUS_INVALID_PARAMETER                              0x05
     501/** Access denied. */
     502#define GIM_HV_STATUS_ACCESS_DENIED                                  0x06
     503/** The partition state not valid for specified op. */
     504#define GIM_HV_STATUS_INVALID_PARTITION_STATE                        0x07
     505/** The hypercall operation could not be performed. */
     506#define GIM_HV_STATUS_OPERATION_DENIED                               0x08
     507/** Specified partition property ID not recognized. */
     508#define GIM_HV_STATUS_UNKNOWN_PROPERTY                               0x09
     509/** Specified partition property value not within range. */
     510#define GIM_HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE                    0x0a
     511/** Insufficient memory for performing the hypercall. */
     512#define GIM_HV_STATUS_INSUFFICIENT_MEMORY                            0x0b
     513/** Maximum partition depth has been exceeded for the partition hierarchy. */
     514#define GIM_HV_STATUS_PARTITION_TOO_DEEP                             0x0c
     515/** The specified partition ID is not valid. */
     516#define GIM_HV_STATUS_INVALID_PARTITION_ID                           0x0d
     517/** The specified virtual processor index in invalid. */
     518#define GIM_HV_STATUS_INVALID_VP_INDEX                               0x0e
     519/** The specified port ID is not unique or doesn't exist. */
     520#define GIM_HV_STATUS_INVALID_PORT_ID                                0x11
     521/** The specified connection ID is not unique or doesn't exist. */
     522#define GIM_HV_STATUS_INVALID_CONNECTION_ID                          0x12
     523/** The target port doesn't have sufficient buffers for the caller to post a message. */
     524#define GIM_HV_STATUS_INSUFFICIENT_BUFFERS                           0x13
     525/** External interrupt not acknowledged.*/
     526#define GIM_HV_STATUS_NOT_ACKNOWLEDGED                               0x14
     527/** External interrupt acknowledged. */
     528#define GIM_HV_STATUS_ACKNOWLEDGED                                   0x16
     529/** Invalid state due to misordering Hv[Save|Restore]PartitionState. */
     530#define GIM_HV_STATUS_INVALID_SAVE_RESTORE_STATE                     0x17
     531/** Operation not perform due to a required feature of SynIc was disabled. */
     532#define GIM_HV_STATUS_INVALID_SYNIC_STATE                            0x18
     533/** Object or value already in use. */
     534#define GIM_HV_STATUS_OBJECT_IN_USE                                  0x19
     535/** Invalid proximity domain information. */
     536#define GIM_HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO                  0x1A
     537/** Attempt to retrieve data failed. */
     538#define GIM_HV_STATUS_NO_DATA                                        0x1B
     539/** Debug connection has not recieved any new data since the last time. */
     540#define GIM_HV_STATUS_INACTIVE                                       0x1C
     541/** A resource is unavailable for allocation. */
     542#define GIM_HV_STATUS_NO_RESOURCES                                   0x1D
     543/** A hypervisor feature is not available to the caller. */
     544#define GIM_HV_STATUS_FEATURE_UNAVAILABLE                            0x1E
     545/** The debug packet returned is partial due to an I/O error. */
     546#define GIM_HV_STATUS_PARTIAL_PACKET                                 0x1F
     547/** Processor feature SSE3 unsupported. */
     548#define GIM_HV_STATUS_PROC_FEAT_SSE3_NOT_SUPPORTED                   0x20
     549/** Processor feature LAHSAHF unsupported. */
     550#define GIM_HV_STATUS_PROC_FEAT_LAHSAHF_NOT_SUPPORTED                0x21
     551/** Processor feature SSSE3 unsupported. */
     552#define GIM_HV_STATUS_PROC_FEAT_SSSE3_NOT_SUPPORTED                  0x22
     553/** Processor feature SSE4.1 unsupported. */
     554#define GIM_HV_STATUS_PROC_FEAT_SSE4_1_NOT_SUPPORTED                 0x23
     555/** Processor feature SSE4.2 unsupported. */
     556#define GIM_HV_STATUS_PROC_FEAT_SSE4_2_NOT_SUPPORTED                 0x24
     557/** Processor feature SSE4A unsupported. */
     558#define GIM_HV_STATUS_PROC_FEAT_SSE4A_NOT_SUPPORTED                  0x25
     559/** Processor feature XOP unsupported. */
     560#define GIM_HV_STATUS_PROC_FEAT_XOP_NOT_SUPPORTED                    0x26
     561/** Processor feature POPCNT unsupported. */
     562#define GIM_HV_STATUS_PROC_FEAT_POPCNT_NOT_SUPPORTED                 0x27
     563/** Processor feature CMPXCHG16B unsupported. */
     564#define GIM_HV_STATUS_PROC_FEAT_CMPXCHG16B_NOT_SUPPORTED             0x28
     565/** Processor feature ALTMOVCR8 unsupported. */
     566#define GIM_HV_STATUS_PROC_FEAT_ALTMOVCR8_NOT_SUPPORTED              0x29
     567/** Processor feature LZCNT unsupported. */
     568#define GIM_HV_STATUS_PROC_FEAT_LZCNT_NOT_SUPPORTED                  0x2A
     569/** Processor feature misaligned SSE unsupported. */
     570#define GIM_HV_STATUS_PROC_FEAT_MISALIGNED_SSE_NOT_SUPPORTED         0x2B
     571/** Processor feature MMX extensions unsupported. */
     572#define GIM_HV_STATUS_PROC_FEAT_MMX_EXT_NOT_SUPPORTED                0x2C
     573/** Processor feature 3DNow! unsupported. */
     574#define GIM_HV_STATUS_PROC_FEAT_3DNOW_NOT_SUPPORTED                  0x2D
     575/** Processor feature Extended 3DNow! unsupported. */
     576#define GIM_HV_STATUS_PROC_FEAT_EXTENDED_3DNOW_NOT_SUPPORTED         0x2E
     577/** Processor feature 1GB large page unsupported. */
     578#define GIM_HV_STATUS_PROC_FEAT_PAGE_1GB_NOT_SUPPORTED               0x2F
     579/** Processor cache line flush size incompatible. */
     580#define GIM_HV_STATUS_PROC_CACHE_LINE_FLUSH_SIZE_INCOMPATIBLE        0x30
     581/** Processor feature XSAVE unsupported. */
     582#define GIM_HV_STATUS_PROC_FEAT_XSAVE_NOT_SUPPORTED                  0x31
     583/** Processor feature XSAVEOPT unsupported. */
     584#define GIM_HV_STATUS_PROC_FEAT_XSAVEOPT_NOT_SUPPORTED               0x32
     585/** The specified buffer was too small for all requested data. */
     586#define GIM_HV_STATUS_INSUFFICIENT_BUFFER                            0x33
     587/** Processor feature XSAVEOPT unsupported. */
     588#define GIM_HV_STATUS_PROC_FEAT_XSAVE_AVX_NOT_SUPPORTED              0x34
     589/** Processor feature XSAVEOPT unsupported. */
     590#define GIM_HV_STATUS_PROC_FEAT_XSAVE_FEAT_NOT_SUPPORTED             0x35   /** Huh, isn't this same as 0x31? */
     591/** Processor feature XSAVEOPT unsupported. */
     592#define GIM_HV_STATUS_PROC_FEAT_PAGE_XSAVE_SAVE_AREA_INCOMPATIBLE    0x36
     593/** Processor architecture unsupoorted. */
     594#define GIM_HV_STATUS_INCOMPATIBLE_PROCESSOR                         0x37
     595/** Max. domains for platform I/O remapping reached. */
     596#define GIM_HV_STATUS_INSUFFICIENT_DEVICE_DOMAINS                    0x38
     597/** Processor feature AES unsupported. */
     598#define GIM_HV_STATUS_PROC_FEAT_AES_NOT_SUPPORTED                    0x39
     599/** Processor feature PCMULQDQ unsupported. */
     600#define GIM_HV_STATUS_PROC_FEAT_PCMULQDQ_NOT_SUPPORTED               0x3A
     601/** Processor feature XSAVE features unsupported. */
     602#define GIM_HV_STATUS_PROC_FEAT_XSAVE_FEATURES_INCOMPATIBLE          0x3B
     603/** Generic CPUID validation error. */
     604#define GIM_HV_STATUS_CPUID_FEAT_VALIDATION_ERROR                    0x3C
     605/** XSAVE CPUID validation error. */
     606#define GIM_HV_STATUS_CPUID_XSAVE_FEAT_VALIDATION_ERROR              0x3D
     607/** Processor startup timed out. */
     608#define GIM_HV_STATUS_PROCESSOR_STARTUP_TIMEOUT                      0x3E
     609/** SMX enabled by the BIOS. */
     610#define GIM_HV_STATUS_SMX_ENABLED                                    0x3F
     611/** Processor feature PCID unsupported. */
     612#define GIM_HV_STATUS_PROC_FEAT_PCID_NOT_SUPPORTED                   0x40
     613/** Invalid LP index. */
     614#define GIM_HV_STATUS_INVALID_LP_INDEX                               0x41
     615/** Processor feature PCID unsupported. */
     616#define GIM_HV_STATUS_FEAT_FMA4_NOT_SUPPORTED                        0x42
     617/** Processor feature PCID unsupported. */
     618#define GIM_HV_STATUS_FEAT_F16C_NOT_SUPPORTED                        0x43
     619/** Processor feature PCID unsupported. */
     620#define GIM_HV_STATUS_PROC_FEAT_RDRAND_NOT_SUPPORTED                 0x44
     621/** Processor feature RDWRFSGS unsupported. */
     622#define GIM_HV_STATUS_PROC_FEAT_RDWRFSGS_NOT_SUPPORTED               0x45
     623/** Processor feature SMEP unsupported. */
     624#define GIM_HV_STATUS_PROC_FEAT_SMEP_NOT_SUPPORTED                   0x46
     625/** Processor feature enhanced fast string unsupported. */
     626#define GIM_HV_STATUS_PROC_FEAT_ENHANCED_FAST_STRING_NOT_SUPPORTED   0x47
     627/** Processor feature MOVBE unsupported. */
     628#define GIM_HV_STATUS_PROC_FEAT_MOVBE_NOT_SUPPORTED                  0x48
     629/** Processor feature BMI1 unsupported. */
     630#define GIM_HV_STATUS_PROC_FEAT_BMI1_NOT_SUPPORTED                   0x49
     631/** Processor feature BMI2 unsupported. */
     632#define GIM_HV_STATUS_PROC_FEAT_BMI2_NOT_SUPPORTED                   0x4A
     633/** Processor feature HLE unsupported. */
     634#define GIM_HV_STATUS_PROC_FEAT_HLE_NOT_SUPPORTED                    0x4B
     635/** Processor feature RTM unsupported. */
     636#define GIM_HV_STATUS_PROC_FEAT_RTM_NOT_SUPPORTED                    0x4C
     637/** Processor feature XSAVE FMA unsupported. */
     638#define GIM_HV_STATUS_PROC_FEAT_XSAVE_FMA_NOT_SUPPORTED              0x4D
     639/** Processor feature XSAVE AVX2 unsupported. */
     640#define GIM_HV_STATUS_PROC_FEAT_XSAVE_AVX2_NOT_SUPPORTED             0x4E
     641/** Processor feature NPIEP1 unsupported. */
     642#define GIM_HV_STATUS_PROC_FEAT_NPIEP1_NOT_SUPPORTED                 0x4F
     643/** @} */
     644
     645
     646/** @name Hyper-V debug support.
     647 * Options and constants for Hyper-V debug hypercalls.
     648 * @{
     649 */
     650/** Maximum debug data payload size in bytes. */
     651#define GIM_HV_DEBUG_MAX_DATA_SIZE                4088
     652
     653/** The undocumented bit for MSR_GIM_HV_DEBUG_OPTIONS_MSR that makes it all
     654 *  work. */
     655#define GIM_HV_DEBUG_OPTIONS_MSR_ENABLE           RT_BIT(2)
     656
     657/** Guest will perform the HvPostDebugData hypercall until completion. */
     658#define GIM_HV_DEBUG_POST_LOOP                    RT_BIT_32(0)
     659/** Mask of valid HvPostDebugData options. */
     660#define GIM_HV_DEBUG_POST_OPTIONS_MASK            RT_BIT_32(0)
     661
     662/** Guest will perform the HvRetrieveDebugData hypercall until completion. */
     663#define GIM_HV_DEBUG_RETREIVE_LOOP                RT_BIT_32(0)
     664/** Guest checks if any global debug session is active. */
     665#define GIM_HV_DEBUG_RETREIVE_TEST_ACTIVITY       RT_BIT_32(1)
     666/** Mask of valid HvRetrieveDebugData options. */
     667#define GIM_HV_DEBUG_RETREIVE_OPTIONS_MASK        RT_BIT_32(0) | RT_BIT_32(1)
     668
     669/** Guest requests purging of incoming debug data. */
     670#define GIM_HV_DEBUG_PURGE_INCOMING_DATA          RT_BIT_32(0)
     671/** Guest requests purging of outgoing debug data. */
     672#define GIM_HV_DEBUG_PURGE_OUTGOING_DATA          RT_BIT_32(1)
     673
     674/**
     675 * HvResetDebugData hypercall input.
     676 */
     677typedef struct GIMHVDEBUGRESETIN
     678{
     679    uint32_t fFlags;
     680    uint32_t uPadding;
     681} GIMHVDEBUGRESETIN;
     682/** Pointer to a HvResetDebugData input struct. */
     683typedef GIMHVDEBUGRESETIN *PGIMHVDEBUGRESETIN;
     684AssertCompileSize(GIMHVDEBUGRESETIN, 8);
     685
     686/**
     687 * HvPostDebugData hypercall input.
     688 */
     689typedef struct GIMHVDEBUGPOSTIN
     690{
     691    uint32_t cbWrite;
     692    uint32_t fFlags;
     693} GIMHVDEBUGPOSTIN;
     694/** Pointer to a HvPostDebugData input struct. */
     695typedef GIMHVDEBUGPOSTIN *PGIMHVDEBUGPOSTIN;
     696AssertCompileSize(GIMHVDEBUGPOSTIN, 8);
     697
     698/**
     699 * HvPostDebugData hypercall output.
     700 */
     701typedef struct GIMHVDEBUGPOSTOUT
     702{
     703    uint32_t cbPending;
     704    uint32_t uPadding;
     705} GIMHVDEBUGPOSTOUT;
     706/** Pointer to a HvPostDebugData output struct. */
     707typedef GIMHVDEBUGPOSTOUT *PGIMHVDEBUGPOSTOUT;
     708AssertCompileSize(GIMHVDEBUGPOSTOUT, 8);
     709
     710/**
     711 * HvRetrieveDebugData hypercall input.
     712 */
     713typedef struct GIMHVDEBUGRETRIEVEIN
     714{
     715    uint32_t cbRead;
     716    uint32_t fFlags;
     717    uint64_t u64Timeout;
     718} GIMHVDEBUGRETRIEVEIN;
     719/** Pointer to a HvRetrieveDebugData input struct. */
     720typedef GIMHVDEBUGRETRIEVEIN *PGIMHVDEBUGRETRIEVEIN;
     721AssertCompileSize(GIMHVDEBUGRETRIEVEIN, 16);
     722
     723/**
     724 * HvRetriveDebugData hypercall output.
     725 */
     726typedef struct GIMHVDEBUGRETRIEVEOUT
     727{
     728    uint32_t cbRead;
     729    uint32_t cbRemaining;
     730} GIMHVDEBUGRETRIEVEOUT;
     731/** Pointer to a HvRetrieveDebugData output struct. */
     732typedef GIMHVDEBUGRETRIEVEOUT *PGIMHVDEBUGRETRIEVEOUT;
     733AssertCompileSize(GIMHVDEBUGRETRIEVEOUT, 8);
     734/** @} */
     735
     736
    449737/** Hyper-V page size.  */
    450 #define GIM_HV_PAGE_SIZE                          0x1000
     738#define GIM_HV_PAGE_SIZE                          4096
     739
     740/** Microsoft Hyper-V vendor signature. */
     741#define GIM_HV_VENDOR_MICROSOFT                   "Microsoft Hv"
    451742
    452743/**
     
    476767typedef GIMHVREFTSC const *PCGIMHVREFTSC;
    477768
    478 
    479769/**
    480770 * GIM Hyper-V VM instance data.
     
    483773typedef struct GIMHV
    484774{
    485     /** @name MSRs.
    486      *  { */
     775    /** @name Primary MSRs.
     776     * @{ */
    487777    /** Guest OS identity MSR. */
    488778    uint64_t                    u64GuestOsIdMsr;
     
    494784
    495785    /** @name CPUID features.
    496      *  { */
     786     * @{ */
    497787    /** Basic features. */
    498788    uint32_t                    uBaseFeat;
     
    510800
    511801    /** @name Guest Crash MSRs.
    512      *  @{
     802     * @{
    513803     */
    514804    /** Guest crash control MSR. */
     
    526816    /** @} */
    527817
     818    /** @name Time management.
     819     * @{ */
    528820    /** Per-VM R0 Spinlock for protecting EMT writes to the TSC page. */
    529821    RTSPINLOCK                  hSpinlockR0;
     
    533825    /** The TSC frequency (in HZ) reported to the guest. */
    534826    uint64_t                    cTscTicksPerSecond;
     827    /** @} */
     828
     829    /** @name Hypercalls. */
     830    /* @{ */
     831    /** Pointer to the hypercall input parameter page - R3. */
     832    R3PTRTYPE(uint8_t *)        pbHypercallIn;
     833    /** Pointer to the hypercall output parameter page - R3. */
     834    R3PTRTYPE(uint8_t *)        pbHypercallOut;
     835    /** @} */
     836
     837    /** @name Guest debugging.
     838     * @{ */
     839    /** Whether we're posing as the official Microsoft vendor. */
     840    bool                        fIsVendorMsHv;
     841    bool                        afAlignment0[7];
     842    /** The auto IP address last chosen by the guest after failed ARP queries. */
     843    RTNETADDRIPV4               DbgGuestAddr;
     844    uint32_t                    uAlignment1;
     845    /** @} */
    535846
    536847    /** Array of MMIO2 regions. */
     
    566877VMMR3_INT_DECL(int)             gimR3HvDisableHypercallPage(PVM pVM);
    567878VMMR3_INT_DECL(int)             gimR3HvEnableHypercallPage(PVM pVM, RTGCPHYS GCPhysHypercallPage);
     879
     880VMMR3_INT_DECL(int)             gimR3HvHypercallPostDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv);
     881VMMR3_INT_DECL(int)             gimR3HvHypercallRetrieveDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv);
    568882#endif /* IN_RING3 */
    569883
    570884VMM_INT_DECL(bool)              gimHvIsParavirtTscEnabled(PVM pVM);
    571885VMM_INT_DECL(bool)              gimHvAreHypercallsEnabled(PVMCPU pVCpu);
     886VMM_INT_DECL(bool)              gimHvShouldTrapXcptUD(PVMCPU pVCpu);
     887VMM_INT_DECL(int)               gimHvXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis);
    572888VMM_INT_DECL(int)               gimHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
    573889VMM_INT_DECL(VBOXSTRICTRC)      gimHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
  • trunk/src/VBox/VMM/include/GIMInternal.h

    r55493 r57989  
    5252    uint32_t                        u32Padding;
    5353
    54     /** Pointer to the GIM device - ring-3 context. */
     54    /** Pointer to the GIM device - R3 ptr. */
    5555    R3PTRTYPE(PPDMDEVINS)            pDevInsR3;
     56    /** Pointer to the GIM device debug stream - R3 ptr. */
     57    R3PTRTYPE(PPDMISTREAM)           pDebugStreamR3;
    5658#if 0
    5759    /** Pointer to the provider's ring-3 hypercall handler. */
     
    105107VMMR3_INT_DECL(int)           GIMR3Mmio2HandlerPhysicalRegister(PVM pVM, PGIMMMIO2REGION pRegion);
    106108VMMR3_INT_DECL(int)           GIMR3Mmio2HandlerPhysicalDeregister(PVM pVM, PGIMMMIO2REGION pRegion);
     109
     110VMMR3_INT_DECL(int)           GIMR3DebugRead(PVM pVM, void *pvRead, size_t *pcbRead);
     111VMMR3_INT_DECL(int)           GIMR3DebugWrite(PVM pVM, void *pvWrite, size_t *pcbWrite);
    107112#endif /* IN_RING3 */
    108113
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