VirtualBox

Changeset 58283 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Oct 16, 2015 3:20:38 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
103477
Message:

VMM/GIM: Implemented Hyper-V SINT2 and SIMP faking for making Windows 10 32-bit guests happy.

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp

    r58250 r58283  
    4141#ifdef IN_RING3
    4242/**
    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.
     43 * Read and validate slow hypercall parameters.
    4844 *
    4945 * @returns VBox status code.
     
    5147 * @param   pCtx              Pointer to the guest-CPU context.
    5248 * @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.
     49 * @param   enmParam          The hypercall parameter type.
    5750 * @param   prcHv             Where to store the Hyper-V status code. Only valid
    5851 *                            to the caller when this function returns
    5952 *                            VINF_SUCCESS.
    6053 */
    61 static int gimHvReadSlowHypercallParams(PVM pVM, PCPUMCTX pCtx, bool fIs64BitMode, PRTGCPHYS pGCPhysIn, PRTGCPHYS pGCPhysOut,
    62                                         int *prcHv)
     54static int gimHvReadSlowHypercallParam(PVM pVM, PCPUMCTX pCtx, bool fIs64BitMode, GIMHVHYPERCALLPARAM enmParam, int *prcHv)
    6355{
    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);
     56    int       rc = VINF_SUCCESS;
     57    PGIMHV    pHv = &pVM->gim.s.u.Hv;
     58    RTGCPHYS  GCPhysParam;
     59    void     *pvDst;
     60    if (enmParam == GIMHVHYPERCALLPARAM_IN)
     61    {
     62        GCPhysParam = fIs64BitMode ? pCtx->rdx : (pCtx->rbx << 32) | pCtx->ecx;
     63        pvDst = pHv->pbHypercallIn;
     64        pHv->GCPhysHypercallIn = GCPhysParam;
     65    }
     66    else
     67    {
     68        GCPhysParam = fIs64BitMode ? pCtx->r8 : (pCtx->rdi << 32) | pCtx->esi;
     69        pvDst = pHv->pbHypercallOut;
     70        pHv->GCPhysHypercallOut = GCPhysParam;
     71        Assert(enmParam == GIMHVHYPERCALLPARAM_OUT);
     72    }
     73
     74    const char *pcszParam = enmParam == GIMHVHYPERCALLPARAM_IN ? "input" : "output";  NOREF(pcszParam);
     75    if (RT_ALIGN_64(GCPhysParam, 8) == GCPhysParam)
     76    {
     77        if (PGMPhysIsGCPhysNormal(pVM, GCPhysParam))
     78        {
     79            rc = PGMPhysSimpleReadGCPhys(pVM, pvDst, GCPhysParam, GIM_HV_PAGE_SIZE);
    7980            if (RT_SUCCESS(rc))
    8081            {
    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             }
     82                *prcHv = GIM_HV_STATUS_SUCCESS;
     83                return VINF_SUCCESS;
     84            }
     85            LogRel(("GIM: HyperV: Failed reading %s param at %#RGp. rc=%Rrc\n", pcszParam, GCPhysParam, rc));
     86            rc = VERR_GIM_HYPERCALL_MEMORY_READ_FAILED;
    9587        }
    9688        else
     89        {
     90            Log(("GIM: HyperV: Invalid %s param address %#RGp\n", pcszParam, GCPhysParam));
    9791            *prcHv = GIM_HV_STATUS_INVALID_PARAMETER;
     92        }
    9893    }
    9994    else
     95    {
     96        Log(("GIM: HyperV: Misaligned %s param address %#RGp\n", pcszParam, GCPhysParam));
    10097        *prcHv = GIM_HV_STATUS_INVALID_ALIGNMENT;
     98    }
     99    return rc;
     100}
     101
     102
     103/**
     104 * Helper for reading and validating slow hypercall input and output parameters.
     105 *
     106 * @returns VBox status code.
     107 * @param   pVM               The cross context VM structure.
     108 * @param   pCtx              Pointer to the guest-CPU context.
     109 * @param   fIs64BitMode      Whether the guest is currently in 64-bit mode or not.
     110 * @param   prcHv             Where to store the Hyper-V status code. Only valid
     111 *                            to the caller when this function returns
     112 *                            VINF_SUCCESS.
     113 */
     114static int gimHvReadSlowHypercallParamsInOut(PVM pVM, PCPUMCTX pCtx, bool fIs64BitMode, int *prcHv)
     115{
     116    int rc = gimHvReadSlowHypercallParam(pVM, pCtx, fIs64BitMode, GIMHVHYPERCALLPARAM_IN, prcHv);
     117    if (   RT_SUCCESS(rc)
     118        && *prcHv == GIM_HV_STATUS_SUCCESS)
     119        rc = gimHvReadSlowHypercallParam(pVM, pCtx, fIs64BitMode, GIMHVHYPERCALLPARAM_OUT, prcHv);
    101120    return rc;
    102121}
     
    168187                {
    169188                    RTGCPHYS GCPhysOut;
    170                     rc = gimHvReadSlowHypercallParams(pVM, pCtx, fIs64BitMode, NULL /*pGCPhysIn*/, &GCPhysOut, &rcHv);
     189                    rc  = gimHvReadSlowHypercallParamsInOut(pVM, pCtx, fIs64BitMode, &rcHv);
    171190                    if (   RT_SUCCESS(rc)
    172191                        && rcHv == GIM_HV_STATUS_SUCCESS)
    173192                    {
    174                         LogRelMax(1, ("GIM: HyperV: Guest initiated debug data reception via hypercall\n"));
    175                         rc = gimR3HvHypercallRetrieveDebugData(pVM, GCPhysOut, &rcHv);
     193                        LogRelMax(1, ("GIM: HyperV: Initiated debug data reception via hypercall\n"));
     194                        rc = gimR3HvHypercallRetrieveDebugData(pVM, &rcHv);
    176195                        if (RT_FAILURE(rc))
    177196                            LogRelMax(10, ("GIM: HyperV: gimR3HvHypercallRetrieveDebugData failed. rc=%Rrc\n", rc));
     
    187206                if (pHv->uPartFlags & GIM_HV_PART_FLAGS_DEBUGGING)
    188207                {
    189                     RTGCPHYS GCPhysOut;
    190                     rc = gimHvReadSlowHypercallParams(pVM, pCtx, fIs64BitMode, NULL /*pGCPhysIn*/, &GCPhysOut, &rcHv);
     208                    rc = gimHvReadSlowHypercallParamsInOut(pVM, pCtx, fIs64BitMode, &rcHv);
    191209                    if (   RT_SUCCESS(rc)
    192210                        && rcHv == GIM_HV_STATUS_SUCCESS)
    193211                    {
    194                         LogRelMax(1, ("GIM: HyperV: Guest initiated debug data transmission via hypercall\n"));
    195                         rc = gimR3HvHypercallPostDebugData(pVM, GCPhysOut, &rcHv);
     212                        LogRelMax(1, ("GIM: HyperV: Initiated debug data transmission via hypercall\n"));
     213                        rc = gimR3HvHypercallPostDebugData(pVM, &rcHv);
    196214                        if (RT_FAILURE(rc))
    197215                            LogRelMax(10, ("GIM: HyperV: gimR3HvHypercallPostDebugData failed. rc=%Rrc\n", rc));
     
    210228                    if (!fHyperFast)
    211229                    {
    212                         rc = gimHvReadSlowHypercallParams(pVM, pCtx, fIs64BitMode, NULL /*pGCPhysIn*/, NULL /*pGCPhysOut*/,
    213                                                             &rcHv);
     230                        rc = gimHvReadSlowHypercallParam(pVM, pCtx, fIs64BitMode, GIMHVHYPERCALLPARAM_IN, &rcHv);
    214231                        if (   RT_SUCCESS(rc)
    215232                            && rcHv == GIM_HV_STATUS_SUCCESS)
     
    234251                            rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
    235252                        else
    236                             LogRelMax(1, ("GIM: HyperV: Guest resetting debug session via hypercall\n"));
     253                            LogRelMax(1, ("GIM: HyperV: Resetting debug session via hypercall\n"));
    237254                    }
     255                }
     256                else
     257                    rcHv = GIM_HV_STATUS_ACCESS_DENIED;
     258                break;
     259            }
     260
     261            case GIM_HV_HYPERCALL_OP_POST_MESSAGE:      /* Non-rep, memory IO. */
     262            {
     263                if (pHv->fIsInterfaceVs)
     264                {
     265                    rc = gimHvReadSlowHypercallParam(pVM, pCtx, fIs64BitMode, GIMHVHYPERCALLPARAM_IN, &rcHv);
     266                    if (   RT_SUCCESS(rc)
     267                        && rcHv == GIM_HV_STATUS_SUCCESS)
     268                    {
     269                        PGIMHVPOSTMESSAGEIN pMsgIn = (PGIMHVPOSTMESSAGEIN)pHv->pbHypercallIn;
     270                        PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     271                        if (    pMsgIn->uConnectionId  == GIM_HV_VMBUS_MSG_CONNECTION_ID
     272                            &&  pMsgIn->enmMessageType == GIMHVMSGTYPE_VMBUS
     273                            && !MSR_GIM_HV_SINT_IS_MASKED(pHvCpu->uSint2Msr)
     274                            &&  MSR_GIM_HV_SIMP_IS_ENABLED(pHvCpu->uSimpMsr))
     275                        {
     276                            RTGCPHYS GCPhysSimp = MSR_GIM_HV_SIMP_GPA(pHvCpu->uSimpMsr);
     277                            if (PGMPhysIsGCPhysNormal(pVM, GCPhysSimp))
     278                            {
     279                                /*
     280                                 * The VMBus client (guest) expects to see 0xf at offsets 4 and 16 and 1 at offset 0.
     281                                 */
     282                                GIMHVMSG HvMsg;
     283                                RT_ZERO(HvMsg);
     284                                HvMsg.MsgHdr.enmMessageType = GIMHVMSGTYPE_VMBUS;
     285                                HvMsg.MsgHdr.cbPayload = 0xf;
     286                                HvMsg.aPayload[0]      = 0xf;
     287                                uint16_t const offMsg = GIM_HV_VMBUS_MSG_SINT * sizeof(GIMHVMSG);
     288                                int rc2 = PGMPhysSimpleWriteGCPhys(pVM, GCPhysSimp + offMsg, &HvMsg, sizeof(HvMsg));
     289                                if (RT_SUCCESS(rc2))
     290                                    LogRel(("GIM: HyperV: SIMP hypercall faking message at %#RGp:%u\n", GCPhysSimp, offMsg));
     291                                else
     292                                {
     293                                    LogRel(("GIM: HyperV: Failed to write SIMP message at %#RGp:%u, rc=%Rrc\n", GCPhysSimp,
     294                                            offMsg, rc));
     295                                }
     296                            }
     297                        }
     298
     299                        /*
     300                         * Make the call fail after updating the SIMP, so the guest can go back to using
     301                         * the Hyper-V debug MSR interface. Any error code below GIM_HV_STATUS_NOT_ACKNOWLEDGED
     302                         * and the guest tries to proceed with initializing VMBus which is totally unnecessary
     303                         * for what we're trying to accomplish, i.e. convince guest to use Hyper-V debugging. Also,
     304                         * we don't implement other VMBus/SynIC functionality so the guest would #GP and die.
     305                         */
     306                        rcHv = GIM_HV_STATUS_NOT_ACKNOWLEDGED;
     307                    }
     308                    else
     309                        rcHv = GIM_HV_STATUS_INVALID_PARAMETER;
    238310                }
    239311                else
     
    404476        case MSR_GIM_HV_SINT2:
    405477        {
    406 #ifndef IN_RING3
    407             return VINF_CPUM_R3_MSR_READ;
    408 #else
    409             LogRelMax(10, ("GIM: HyperV: reading MSR_GIM_HV_SINT2 CS:RIP=%04x:%RX64\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestRIP(pVCpu)));
    410             *puValue = RT_BIT_64(16);
    411             return VERR_CPUM_RAISE_GP_0;
    412 #endif
     478            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     479            *puValue = pHvCpu->uSint2Msr;
     480            return VINF_SUCCESS;
    413481        }
    414482
    415483        case MSR_GIM_HV_SIMP:
    416484        {
    417 #ifndef IN_RING3
    418             return VINF_CPUM_R3_MSR_READ;
    419 #else
    420             LogRelMax(10, ("GIM: HyperV: reading MSR_GIM_HV_SIMP CS:RIP=%04x:%RX64\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestRIP(pVCpu)));
    421             *puValue = 0;
    422             return VINF_SUCCESS;
    423 #endif
     485            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     486            *puValue = pHvCpu->uSimpMsr;
     487            return VINF_SUCCESS;
    424488        }
    425489
     
    445509                return VINF_CPUM_R3_MSR_READ;
    446510#else
    447                 LogRelMax(1, ("GIM: HyperV: Guest querying debug options MSR, returning %#x\n", GIM_HV_DEBUG_OPTIONS_MSR_ENABLE));
     511                LogRelMax(1, ("GIM: HyperV: Guest queried debug options MSR\n"));
    448512                *puValue = GIM_HV_DEBUG_OPTIONS_MSR_ENABLE;
    449513                return VINF_SUCCESS;
     
    564628#ifndef IN_RING3
    565629            return VINF_CPUM_R3_MSR_WRITE;
    566 #else  /* IN_RING3 */
    567 # if 0
    568             /*
    569              * For now ignore writes to the hypercall MSR (i.e. keeps it disabled).
    570              * This is required to boot FreeBSD 10.1 (with Hyper-V enabled ofc),
    571              * see @bugref{7270#c116}.
    572              */
    573             return VINF_SUCCESS;
    574 # else
     630#else
     631            /** @todo There is/was a problem with hypercalls for FreeBSD 10.1 guests,
     632             *  see @bugref{7270#c116}. */
    575633            /* First, update all but the hypercall page enable bit. */
    576634            pHv->u64HypercallMsr = (uRawValue & ~MSR_GIM_HV_HYPERCALL_PAGE_ENABLE_BIT);
     
    602660
    603661            return VERR_CPUM_RAISE_GP_0;
    604 # endif
    605 #endif /* IN_RING3 */
     662#endif
    606663        }
    607664
     
    674731            pHv->uDebugSendBufferMsr = GCPhysBuffer;
    675732            if (PGMPhysIsGCPhysNormal(pVM, GCPhysBuffer))
    676                 LogRel(("GIM: HyperV: Guest set up debug send buffer at %#RGp\n", GCPhysBuffer));
     733                LogRel(("GIM: HyperV: Set up debug send buffer at %#RGp\n", GCPhysBuffer));
    677734            else
    678                 LogRel(("GIM: HyperV: Guest destroyed debug send buffer\n"));
     735                LogRel(("GIM: HyperV: Destroyed debug send buffer\n"));
    679736            pHv->uDebugSendBufferMsr = uRawValue;
    680737            return VINF_SUCCESS;
     
    690747            pHv->uDebugRecvBufferMsr = GCPhysBuffer;
    691748            if (PGMPhysIsGCPhysNormal(pVM, GCPhysBuffer))
    692                 LogRel(("GIM: HyperV: Guest set up debug receive buffer at %#RGp\n", GCPhysBuffer));
     749                LogRel(("GIM: HyperV: Set up debug receive buffer at %#RGp\n", GCPhysBuffer));
    693750            else
    694                 LogRel(("GIM: HyperV: Guest destroyed debug receive buffer\n"));
     751                LogRel(("GIM: HyperV: Destroyed debug receive buffer\n"));
    695752            return VINF_SUCCESS;
    696753#endif
     
    706763            if (PGMPhysIsGCPhysNormal(pVM, GCPhysBuffer))
    707764            {
    708                 LogRel(("GIM: HyperV: Guest set up debug pending buffer at %#RGp\n", uRawValue));
     765                LogRel(("GIM: HyperV: Set up debug pending buffer at %#RGp\n", uRawValue));
    709766
    710767                /* Indicate that there is always debug data to be read (guest will poll). */
     768                /** @todo Later implement this by doing the transport read in a separate
     769                 *        thread and updating this page, saves lots of VM-exits as the guest
     770                 *        won't poll and fail all the time. */
    711771                uint8_t uPendingData = 1;
    712772                int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysBuffer, (void *)&uPendingData, sizeof(uPendingData));
     
    715775            }
    716776            else
    717                 LogRel(("GIM: HyperV: Guest destroyed debug pending buffer\n"));
     777                LogRel(("GIM: HyperV: Destroyed debug pending buffer\n"));
    718778            return VINF_SUCCESS;
    719779#endif
     
    727787            if (MSR_GIM_HV_SYNTH_DEBUG_CONTROL_IS_WRITE(uRawValue))
    728788            {
    729                 LogRelMax(1, ("GIM: HyperV: Guest initiated debug data transmission via MSR\n",
     789                LogRelMax(1, ("GIM: HyperV: Initiated debug data transmission via MSR\n",
    730790                              MSR_GIM_HV_SYNTH_DEBUG_CONTROL_W_LEN(uRawValue)));
    731791                uint32_t cbWrite = MSR_GIM_HV_SYNTH_DEBUG_CONTROL_W_LEN(uRawValue);
     
    769829            else if (MSR_GIM_HV_SYNTH_DEBUG_CONTROL_IS_READ(uRawValue))
    770830            {
    771                 LogRelMax(1, ("GIM: HyperV: Guest initiated debug data reception via MSR\n"));
     831                LogRelMax(1, ("GIM: HyperV: Initiated debug data reception via MSR\n"));
    772832                if (PGMPhysIsGCPhysNormal(pVM, (RTGCPHYS)pHv->uDebugRecvBufferMsr))
    773833                {
     
    810870
    811871        case MSR_GIM_HV_SINT2:
    812 #ifndef IN_RING3
    813             return VINF_CPUM_R3_MSR_WRITE;
    814 #else
    815             LogRelMax(5, ("GIM: HyperV: Guest writing MSR_GIM_HV_SINT2 with %#RX64, ignoring CS:RIP=%04x:%RX64\n", uRawValue,
    816                            CPUMGetGuestCS(pVCpu), CPUMGetGuestRIP(pVCpu)));
    817             return VERR_CPUM_RAISE_GP_0;
    818 #endif
     872        {
     873#ifndef IN_RING3
     874            return VINF_CPUM_R3_MSR_WRITE;
     875#else
     876            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     877            uint8_t uVector = MSR_GIM_HV_SINT_VECTOR(uRawValue);
     878            if (  !MSR_GIM_HV_SINT_IS_MASKED(uRawValue)
     879                && uVector < 16)
     880            {
     881                LogRel(("GIM: HyperV: Programmed an invalid vector in SINT2, uVector=%u -> #GP(0)\n", uVector));
     882                return VERR_CPUM_RAISE_GP_0;
     883            }
     884
     885            pHvCpu->uSint2Msr = uRawValue;
     886            if (MSR_GIM_HV_SINT_IS_MASKED(uRawValue))
     887                LogRel(("GIM: HyperV: Masked SINT2\n"));
     888            else
     889                LogRel(("GIM: HyperV: Unmasked SINT2, uVector=%u\n", uVector));
     890            return VINF_SUCCESS;
     891#endif
     892        }
     893
     894        case MSR_GIM_HV_SIMP:
     895        {
     896#ifndef IN_RING3
     897            return VINF_CPUM_R3_MSR_WRITE;
     898#else
     899            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     900            pHvCpu->uSimpMsr = uRawValue;
     901            if (MSR_GIM_HV_SIMP_IS_ENABLED(uRawValue))
     902            {
     903                RTGCPHYS GCPhysSimp = MSR_GIM_HV_SIMP_GPA(uRawValue);
     904                if (PGMPhysIsGCPhysNormal(pVM, GCPhysSimp))
     905                {
     906                    uint8_t abSimp[PAGE_SIZE];
     907                    RT_ZERO(abSimp);
     908                    int rc2 = PGMPhysSimpleWriteGCPhys(pVM, GCPhysSimp, &abSimp[0], sizeof(abSimp));
     909                    if (RT_SUCCESS(rc2))
     910                        LogRel(("GIM: HyperV: Enabled synthetic interrupt message page at %#RGp\n", GCPhysSimp));
     911                    else
     912                    {
     913                        LogRel(("GIM: HyperV: WrMsr on MSR_GIM_HV_SIMP failed to update SIMP at %#RGp rc=%Rrc -> #GP(0)\n",
     914                                GCPhysSimp, rc2));
     915                        return VERR_CPUM_RAISE_GP_0;
     916                    }
     917                }
     918                else
     919                    LogRel(("GIM: HyperV: Enabled synthetic interrupt message page at invalid address %#RGp\n",GCPhysSimp));
     920            }
     921            else
     922                LogRel(("GIM: HyperV: Disabled synthetic interrupt message page\n"));
     923            return VINF_SUCCESS;
     924#endif
     925        }
    819926
    820927        case MSR_GIM_HV_CRASH_P0:  pHv->uCrashP0 = uRawValue;  return VINF_SUCCESS;
     
    838945                return VINF_CPUM_R3_MSR_WRITE;
    839946#else
    840                 LogRelMax(5, ("GIM: HyperV: Guest setting debug options MSR to %#RX64, ignoring\n", uRawValue));
     947                LogRelMax(5, ("GIM: HyperV: Write debug options MSR with %#RX64 ignored\n", uRawValue));
    841948                return VINF_SUCCESS;
    842949#endif
  • trunk/src/VBox/VMM/VMMR3/GIM.cpp

    r58248 r58283  
    8989     */
    9090    AssertCompile(sizeof(pVM->gim.s) <= sizeof(pVM->gim.padding));
     91    AssertCompile(sizeof(pVM->aCpus[0].gim.s) <= sizeof(pVM->aCpus[0].gim.padding));
     92
    9193
    9294    /*
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r58251 r58283  
    113113         */
    114114        rc = CFGMR3ValidateConfig(pCfgHv, "/HyperV/",
    115                                   "VendorID",
     115                                  "VendorID"
     116                                  "|VSInterface",
    116117                                  "" /* pszValidNodes */, "GIM/HyperV" /* pszWho */, 0 /* uInstance */);
    117118        if (RT_FAILURE(rc))
     
    132133    }
    133134
    134     pHv->fIsInterfaceVs = true;
     135    if (pHv->fIsVendorMsHv)
     136    {
     137        /** @cfgm{/GIM/HyperV/VSInterface, bool, true}
     138         * The Microsoft virtualization service interface (debugging). */
     139        rc = CFGMR3QueryBoolDef(pCfgHv, "VSInterface", &pHv->fIsInterfaceVs, true);
     140        AssertLogRelRCReturn(rc, rc);
     141    }
     142    else
     143        Assert(pHv->fIsInterfaceVs == false);
    135144
    136145    /*
     
    169178                         | GIM_HV_HINT_RELAX_TIME_CHECKS;
    170179
    171         /* Expose more if we're posing as Microsoft. */
    172         if (   pHv->fIsVendorMsHv
    173             /*&& !pHv->fIsInterfaceVs*/)
     180        /* Expose more if we're posing as Microsoft. We can, if needed, force MSR-based Hv
     181           debugging by not exposing these bits while exposing the VS interface.*/
     182        if (pHv->fIsVendorMsHv)
    174183        {
    175184            pHv->uMiscFeat  |= GIM_HV_MISC_FEAT_GUEST_DEBUGGING
     
    331340    if (pHv->uMiscFeat & GIM_HV_MISC_FEAT_GUEST_CRASH_MSRS)
    332341        pHv->uCrashCtl = MSR_GIM_HV_CRASH_CTL_NOTIFY_BIT;
    333 
    334     /*
    335      * Setup guest-host hypercall based debugging support.
    336      */
    337     if (pHv->uMiscFeat & GIM_HV_MISC_FEAT_GUEST_DEBUGGING)
    338     {
    339         rc = gimR3HvInitHypercallSupport(pVM);
    340         AssertLogRelRCReturn(rc, rc);
    341     }
     342    for (VMCPUID i = 0; i < pVM->cCpus; i++)
     343        pVM->aCpus[i].gim.s.u.HvCpu.uSint2Msr = MSR_GIM_HV_SINT_MASKED_BIT;
     344
     345    /*
     346     * Setup hypercall support.
     347     */
     348    rc = gimR3HvInitHypercallSupport(pVM);
     349    AssertLogRelRCReturn(rc, rc);
    342350
    343351    return VINF_SUCCESS;
     
    406414{
    407415    gimR3HvReset(pVM);
    408 
    409     PGIMHV pHv = &pVM->gim.s.u.Hv;
    410     if (pHv->uMiscFeat & GIM_HV_MISC_FEAT_GUEST_DEBUGGING)
    411         gimR3HvTermHypercallSupport(pVM);
     416    gimR3HvTermHypercallSupport(pVM);
    412417    return VINF_SUCCESS;
    413418}
     
    463468
    464469    /*
    465      * Reset MSRs (Careful! Don't reset non-zero MSRs).
     470     * Reset MSRs.
    466471     */
    467472    pHv->u64GuestOsIdMsr        = 0;
     
    477482    pHv->uDebugSendBufferMsr    = 0;
    478483    pHv->uDebugRecvBufferMsr    = 0;
     484    for (VMCPUID i = 0; i < pVM->cCpus; i++)
     485    {
     486        PVMCPU pVCpu = &pVM->aCpus[i];
     487        pVCpu->gim.s.u.HvCpu.uSint2Msr = MSR_GIM_HV_SINT_MASKED_BIT;
     488        pVCpu->gim.s.u.HvCpu.uSimpMsr  = 0;
     489    }
    479490}
    480491
     
    12091220 * @returns VBox status code.
    12101221 * @param   pVM         The cross context VM structure.
    1211  * @param   GCPhysOut   Where to write the hypercall output parameters after
    1212  *                      performing the hypercall.
    12131222 * @param   prcHv       Where to store the result of the hypercall operation.
    12141223 *
    12151224 * @thread  EMT.
    12161225 */
    1217 VMMR3_INT_DECL(int) gimR3HvHypercallPostDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv)
     1226VMMR3_INT_DECL(int) gimR3HvHypercallPostDebugData(PVM pVM, int *prcHv)
    12181227{
    12191228    AssertPtr(pVM);
     
    12651274     * Update the guest memory with result.
    12661275     */
    1267     int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysOut, pHv->pbHypercallOut, sizeof(GIMHVDEBUGPOSTOUT));
     1276    int rc = PGMPhysSimpleWriteGCPhys(pVM, pHv->GCPhysHypercallOut, pHv->pbHypercallOut, sizeof(GIMHVDEBUGPOSTOUT));
    12681277    if (RT_FAILURE(rc))
    12691278    {
     
    12821291 * @returns VBox status code.
    12831292 * @param   pVM         The cross context VM structure.
    1284  * @param   GCPhysOut   Where to write the hypercall output parameters after
    1285  *                      performing the hypercall.
    12861293 * @param   prcHv       Where to store the result of the hypercall operation.
    12871294 *
    12881295 * @thread  EMT.
    12891296 */
    1290 VMMR3_INT_DECL(int) gimR3HvHypercallRetrieveDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv)
     1297VMMR3_INT_DECL(int) gimR3HvHypercallRetrieveDebugData(PVM pVM, int *prcHv)
    12911298{
    12921299    AssertPtr(pVM);
     
    13451352     * Update the guest memory with result.
    13461353     */
    1347     int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysOut, pHv->pbHypercallOut, sizeof(GIMHVDEBUGRETRIEVEOUT) + *pcbReallyRead);
     1354    int rc = PGMPhysSimpleWriteGCPhys(pVM, pHv->GCPhysHypercallOut, pHv->pbHypercallOut,
     1355                                      sizeof(GIMHVDEBUGRETRIEVEOUT) + *pcbReallyRead);
    13481356    if (RT_FAILURE(rc))
    13491357    {
  • trunk/src/VBox/VMM/include/GIMHvInternal.h

    r58248 r58283  
    455455/** @} */
    456456
     457
     458/**
     459 * Hypercall parameter type.
     460 */
     461typedef enum GIMHVHYPERCALLPARAM
     462{
     463    GIMHVHYPERCALLPARAM_IN = 0,
     464    GIMHVHYPERCALLPARAM_OUT
     465} GIMHVHYPERCALLPARAM;
     466
     467
    457468/** @name Hyper-V hypercall op codes.
    458469 * @{
    459470 */
     471/** Post message to hypervisor or VMs. */
     472#define GIM_HV_HYPERCALL_OP_POST_MESSAGE          0x5C
    460473/** Post debug data to hypervisor. */
    461474#define GIM_HV_HYPERCALL_OP_POST_DEBUG_DATA       0x69
     
    465478#define GIM_HV_HYPERCALL_OP_RESET_DEBUG_SESSION   0x6B
    466479/** @} */
     480
    467481
    468482/** @name Hyper-V hypercall inputs.
     
    660674 */
    661675/** Debug send buffer operation success. */
    662 #define MSR_GIM_HV_SYNTH_DEBUG_STATUS_W_SUCCESS_BIT    RT_BIT_32(0)
     676#define MSR_GIM_HV_SYNTH_DEBUG_STATUS_W_SUCCESS_BIT    RT_BIT_64(0)
    663677/** Debug receive buffer operation success. */
    664 #define MSR_GIM_HV_SYNTH_DEBUG_STATUS_R_SUCCESS_BIT    RT_BIT_32(2)
     678#define MSR_GIM_HV_SYNTH_DEBUG_STATUS_R_SUCCESS_BIT    RT_BIT_64(2)
    665679/** Debug connection was reset. */
    666 #define MSR_GIM_HV_SYNTH_DEBUG_STATUS_CONN_RESET_BIT   RT_BIT_32(3)
    667 /** @} */
    668 
    669 
    670 /** @name Hyper-V hypercall debug support.
    671  * Options and constants for Hyper-V debug hypercalls.
    672  * @{
    673  */
     680#define MSR_GIM_HV_SYNTH_DEBUG_STATUS_CONN_RESET_BIT   RT_BIT_64(3)
     681/** @} */
     682
     683
     684/** @name Hyper-V MSR - synthetic interrupt (MSR_GIM_HV_SINTx).
     685 * @{
     686 */
     687/** The interrupt masked bit. */
     688#define MSR_GIM_HV_SINT_MASKED_BIT                     RT_BIT_64(16)
     689/** Whether the interrupt source is masked. */
     690#define MSR_GIM_HV_SINT_IS_MASKED(a)                   RT_BOOL((a) & MSR_GIM_HV_SINT_MASKED_BIT)
     691/** Interrupt vector. */
     692#define MSR_GIM_HV_SINT_VECTOR(a)                      ((a) & UINT64_C(0xff))
     693/** @} */
     694
     695
     696/** @name Hyper-V MSR - synthetic interrupt message page (MSR_GIM_HV_SIMP).
     697 * @{
     698 */
     699/** The SIMP enabled bit. */
     700#define MSR_GIM_HV_SIMP_ENABLED_BIT                    RT_BIT_64(0)
     701/** Whether the SIMP is enabled. */
     702#define MSR_GIM_HV_SIMP_IS_ENABLED(a)                  RT_BOOL((a) & MSR_GIM_HV_SIMP_ENABLED_BIT)
     703/** The SIMP guest-physical address. */
     704#define MSR_GIM_HV_SIMP_GPA(a)                         ((a) & UINT64_C(0xfffffffffffff000))
     705/** @} */
     706
     707
     708/** @name Hyper-V hypercall debug options.
     709 * @{ */
    674710/** Maximum debug data payload size in bytes. */
    675711#define GIM_HV_DEBUG_MAX_DATA_SIZE                4088
     
    695731/** Guest requests purging of outgoing debug data. */
    696732#define GIM_HV_DEBUG_PURGE_OUTGOING_DATA          RT_BIT_32(1)
     733/** @}*/
     734
     735
     736/** @name VMBus.
     737 *  These are just arbitrary definitions made up by Microsoft without
     738 *  any publicly available specification behind it.
     739 * @{ */
     740/** VMBus connection ID. */
     741#define GIM_HV_VMBUS_MSG_CONNECTION_ID            1
     742/** VMBus synthetic interrupt source. */
     743#define GIM_HV_VMBUS_MSG_SINT                     2
     744/** @} */
     745
     746
     747/** @name Hyper-V synthetic interrupt message type.
     748 * @{
     749 */
     750typedef enum GIMHVMSGTYPE
     751{
     752    GIMHVMSGTYPE_NONE                 = 0,              /* Common messages */
     753    GIMHVMSGTYPE_VMBUS                = 1,              /* Guest messages */
     754    GIMHVMSGTYPE_UNMAPPEDGPA          = 0x80000000,     /* Hypervisor messages */
     755    GIMHVMSGTYPE_GPAINTERCEPT         = 0x80000001,
     756    GIMHVMSGTYPE_TIMEREXPIRED         = 0x80000010,
     757    GIMHVMSGTYPE_INVALIDVPREGVAL      = 0x80000020,
     758    GIMHVMSGTYPE_UNRECOVERABLEXCPT    = 0x80000021,
     759    GIMHVMSGTYPE_UNSUPPORTEDFEAT      = 0x80000022,
     760    GIMHVMSGTYPE_APICEOI              = 0x80000030,
     761    GIMHVMSGTYPE_X64LEGACYFPERROR     = 0x80000031,
     762    GIMHVMSGTYPE_EVENTLOGBUFSCOMPLETE = 0x80000040,
     763    GIMHVMSGTYPE_X64IOPORTINTERCEPT   = 0x80010000,
     764    GIMHVMSGTYPE_X64MSRINTERCEPT      = 0x80010001,
     765    GIMHVMSGTYPE_X64CPUIDINTERCEPT    = 0x80010002,
     766    GIMHVMSGTYPE_X64XCPTINTERCEPT     = 0x80010003
     767} GIMHVMSGTYPE;
     768AssertCompileSize(GIMHVMSGTYPE, 4);
     769/** @} */
     770
     771
     772/** @name Hyper-V synthetic interrupt message format.
     773 * @{ */
     774#define GIM_HV_MSG_SIZE                           256
     775#define GIM_HV_MSG_MAX_PAYLOAD_SIZE               240
     776#define GIM_HV_MSG_MAX_PAYLOAD_UNITS               30
     777
     778/**
     779 * Synthetic interrupt message flags.
     780 */
     781typedef union GIMHVMSGFLAGS
     782{
     783    struct
     784    {
     785        uint8_t  u1Pending  : 1;
     786        uint8_t  u7Reserved : 7;
     787    } n;
     788    uint8_t u;
     789} GIMHVMSGFLAGS;
     790AssertCompileSize(GIMHVMSGFLAGS, sizeof(uint8_t));
     791
     792/**
     793 * Synthetic interrupt message header.
     794 *
     795 * @remarks The layout of this structure differs from
     796 *          the Hyper-V spec. Aug 8, 2013 v4.0a. Layout
     797 *          in accordance w/ VMBus client expectations.
     798 */
     799typedef struct GIMHVMSGHDR
     800{
     801    GIMHVMSGTYPE    enmMessageType;
     802    uint8_t         cbPayload;
     803    GIMHVMSGFLAGS   MessageFlags;
     804    uint16_t        uRsvd;
     805    union
     806    {
     807        uint64_t    uOriginatorId;
     808        uint64_t    uPartitionId;
     809        uint64_t    uPortId;
     810    } msgid;
     811} GIMHVMSGHDR;
     812/** Pointer to a synthetic interrupt message header. */
     813typedef GIMHVMSGHDR *PGIMHVMSGHDR;
     814AssertCompileMemberOffset(GIMHVMSGHDR, cbPayload,    4);
     815AssertCompileMemberOffset(GIMHVMSGHDR, MessageFlags, 5);
     816AssertCompileMemberOffset(GIMHVMSGHDR, msgid,        8);
     817AssertCompileSize(GIMHVMSGHDR, GIM_HV_MSG_SIZE - GIM_HV_MSG_MAX_PAYLOAD_SIZE);
     818
     819/**
     820 * Synthetic interrupt message.
     821 */
     822typedef struct GIMHVMSG
     823{
     824    GIMHVMSGHDR     MsgHdr;
     825    uint64_t        aPayload[GIM_HV_MSG_MAX_PAYLOAD_UNITS];
     826} GIMHVMSG;
     827/** Pointer to a synthetic interrupt message. */
     828typedef GIMHVMSG *PGIMHVMSG;
     829AssertCompileSize(GIMHVMSG, GIM_HV_MSG_SIZE);
     830/** @} */
     831
     832
     833/** @name Hyper-V hypercall parameters.
     834 * @{ */
     835/**
     836 * HvPostMessage hypercall input.
     837 */
     838typedef struct GIMHVPOSTMESSAGEIN
     839{
     840    uint32_t      uConnectionId;
     841    uint32_t      uPadding;
     842    GIMHVMSGTYPE  enmMessageType;
     843    uint32_t      cbPayload;
     844} GIMHVPOSTMESSAGEIN;
     845/** Pointer to a HvPostMessage input struct. */
     846typedef GIMHVPOSTMESSAGEIN *PGIMHVPOSTMESSAGEIN;
     847AssertCompileSize(GIMHVPOSTMESSAGEIN, 16);
    697848
    698849/**
     
    8531004    /** @name Hypercalls. */
    8541005    /* @{ */
     1006    /** Guest address of the hypercall input parameter page. */
     1007    RTGCPHYS                    GCPhysHypercallIn;
     1008    /** Guest address of the hypercall output parameter page. */
     1009    RTGCPHYS                    GCPhysHypercallOut;
    8551010    /** Pointer to the hypercall input parameter page - R3. */
    8561011    R3PTRTYPE(uint8_t *)        pbHypercallIn;
     
    8891044AssertCompileMemberAlignment(GIMHV, hSpinlockR0, sizeof(uintptr_t));
    8901045
     1046/**
     1047 * GIM Hyper-V VCPU instance data.
     1048 * Changes to this must checked against the padding of the gim union in VMCPU!
     1049 */
     1050typedef struct GIMHVCPU
     1051{
     1052    /** @name Synthetic interrupt MSRs.
     1053     * @{ */
     1054    /** Synthetic interrupt message page MSR. */
     1055    uint64_t                    uSimpMsr;
     1056    /** Interrupt source 2 MSR. */
     1057    uint64_t                    uSint2Msr;
     1058    /** @} */
     1059} GIMHVCPU;
     1060/** Pointer to per-VCPU GIM Hyper-V instance data. */
     1061typedef GIMHVCPU *PGIMHVCPU;
     1062/** Pointer to const per-VCPU GIM Hyper-V instance data. */
     1063typedef GIMHVCPU const *PCGIMHVCPU;
     1064
     1065
    8911066RT_C_DECLS_BEGIN
    8921067
     
    9121087VMMR3_INT_DECL(int)             gimR3HvEnableHypercallPage(PVM pVM, RTGCPHYS GCPhysHypercallPage);
    9131088
    914 VMMR3_INT_DECL(int)             gimR3HvHypercallPostDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv);
    915 VMMR3_INT_DECL(int)             gimR3HvHypercallRetrieveDebugData(PVM pVM, RTGCPHYS GCPhysOut, int *prcHv);
     1089VMMR3_INT_DECL(int)             gimR3HvHypercallPostDebugData(PVM pVM, int *prcHv);
     1090VMMR3_INT_DECL(int)             gimR3HvHypercallRetrieveDebugData(PVM pVM, int *prcHv);
    9161091VMMR3_INT_DECL(int)             gimR3HvDebugWrite(PVM pVM, void *pvData, uint32_t cbWrite, uint32_t *pcbWritten, bool fUdpPkt);
    9171092VMMR3_INT_DECL(int)             gimR3HvDebugRead(PVM pVM, void *pvBuf, uint32_t cbBuf, uint32_t cbRead, uint32_t *pcbRead,
  • trunk/src/VBox/VMM/include/GIMInternal.h

    r57989 r58283  
    9797    {
    9898        GIMKVMCPU KvmCpu;
     99        GIMHVCPU  HvCpu;
    99100    } u;
    100101} GIMCPU;
Note: See TracChangeset for help on using the changeset viewer.

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