VirtualBox

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


Ignore:
Timestamp:
Aug 26, 2016 11:44:40 AM (8 years ago)
Author:
vboxsync
Message:

VMM/GIM/HyperV: Add partial support for synthetic interrupt controller (still disabled, i.e. not exposed to guest).

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

Legend:

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

    r62653 r63648  
    2929#include <VBox/vmm/pdmapi.h>
    3030#include <VBox/vmm/pgm.h>
     31#include <VBox/vmm/apic.h>
    3132#include "GIMHvInternal.h"
    3233#include "GIMInternal.h"
     
    285286                    {
    286287                        PGIMHVPOSTMESSAGEIN pMsgIn = (PGIMHVPOSTMESSAGEIN)pHv->pbHypercallIn;
    287                         PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     288                        PCGIMHVCPU          pHvCpu = &pVCpu->gim.s.u.HvCpu;
    288289                        if (    pMsgIn->uConnectionId  == GIM_HV_VMBUS_MSG_CONNECTION_ID
    289290                            &&  pMsgIn->enmMessageType == GIMHVMSGTYPE_VMBUS
    290                             && !MSR_GIM_HV_SINT_IS_MASKED(pHvCpu->auSintXMsr[GIM_HV_VMBUS_MSG_SINT])
     291                            && !MSR_GIM_HV_SINT_IS_MASKED(pHvCpu->auSintMsrs[GIM_HV_VMBUS_MSG_SINT])
    291292                            &&  MSR_GIM_HV_SIMP_IS_ENABLED(pHvCpu->uSimpMsr))
    292293                        {
     
    332333
    333334            default:
     335            {
     336                LogRel(("GIM: HyperV: Unknown/invalid hypercall opcode %#x (%u)\n", uHyperOp, uHyperOp));
    334337                rcHv = GIM_HV_STATUS_INVALID_HYPERCALL_CODE;
    335338                break;
     339            }
    336340        }
    337341    }
     
    414418#endif
    415419
     420/**
     421 * Gets the time reference count for the current VM.
     422 *
     423 * @returns The time reference count.
     424 * @param   pVCpu       The cross context virtual CPU structure.
     425 */
     426DECLINLINE(uint64_t) gimHvGetTimeRefCount(PVMCPU pVCpu)
     427{
     428    /* Hyper-V reports the time in 100 ns units (10 MHz). */
     429    VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
     430    PCGIMHV pHv = &pVCpu->CTX_SUFF(pVM)->gim.s.u.Hv;
     431    uint64_t const u64Tsc        = TMCpuTickGet(pVCpu);     /** @todo should we be passing VCPU0 always? */
     432    uint64_t const u64TscHz      = pHv->cTscTicksPerSecond;
     433    uint64_t const u64Tsc100NS   = u64TscHz / UINT64_C(10000000); /* 100 ns */
     434    uint64_t const uTimeRefCount = (u64Tsc / u64Tsc100NS);
     435    return uTimeRefCount;
     436}
     437
     438
     439/**
     440 * Starts the synthetic timer.
     441 *
     442 * @param   pVCpu       The cross context virtual CPU structure.
     443 * @param   pHvStimer   Pointer to the Hyper-V synthetic timer.
     444 *
     445 * @remarks Caller needs to hold the timer critical section.
     446 * @thread  Any.
     447 */
     448VMM_INT_DECL(void) gimHvStartStimer(PVMCPU pVCpu, PCGIMHVSTIMER pHvStimer)
     449{
     450    PTMTIMER pTimer = pHvStimer->CTX_SUFF(pTimer);
     451    Assert(TMTimerIsLockOwner(pTimer));
     452
     453    uint64_t const uTimerCount = pHvStimer->uStimerCountMsr;
     454    if (uTimerCount)
     455    {
     456        uint64_t const uTimerCountNS = uTimerCount * 100;
     457
     458        /* For periodic timers, 'uTimerCountNS' represents the relative interval. */
     459        if (MSR_GIM_HV_STIMER_IS_PERIODIC(pHvStimer->uStimerConfigMsr))
     460        {
     461            TMTimerSetNano(pTimer, uTimerCountNS);
     462            LogFlow(("GIM%u: HyperV: Started relative periodic STIMER%u with uTimerCountNS=%RU64\n", pVCpu->idCpu,
     463                     pHvStimer->idxStimer, uTimerCountNS));
     464        }
     465        else
     466        {
     467            /* For one-shot timers, 'uTimerCountNS' represents an absolute expiration wrt to Hyper-V reference time,
     468               we convert it to a relative time and program the timer. */
     469            uint64_t const uCurRefTimeNS = gimHvGetTimeRefCount(pVCpu) * 100;
     470            if (uTimerCountNS > uCurRefTimeNS)
     471            {
     472                uint64_t const uRelativeNS = uTimerCountNS - uCurRefTimeNS;
     473                TMTimerSetNano(pTimer, uRelativeNS);
     474                LogFlow(("GIM%u: HyperV: Started one-shot relative STIMER%u with uRelativeNS=%RU64\n", pVCpu->idCpu,
     475                         pHvStimer->idxStimer, uRelativeNS));
     476            }
     477        }
     478        /** @todo frequency hinting? */
     479    }
     480}
     481
     482
     483/**
     484 * Stops the synthetic timer for the given VCPU.
     485 *
     486 * @param   pVCpu       The cross context virtual CPU structure.
     487 * @param   pHvStimer   Pointer to the Hyper-V synthetic timer.
     488 *
     489 * @remarks Caller needs to the hold the timer critical section.
     490 * @thread  EMT(pVCpu).
     491 */
     492static void gimHvStopStimer(PVMCPU pVCpu, PGIMHVSTIMER pHvStimer)
     493{
     494    VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
     495
     496    PTMTIMER  pTimer = pHvStimer->CTX_SUFF(pTimer);
     497    Assert(TMTimerIsLockOwner(pTimer));
     498
     499    if (TMTimerIsActive(pHvStimer->CTX_SUFF(pTimer)))
     500        TMTimerStop(pHvStimer->CTX_SUFF(pTimer));
     501}
     502
    416503
    417504/**
     
    432519{
    433520    NOREF(pRange);
    434     PVM    pVM = pVCpu->CTX_SUFF(pVM);
    435     PGIMHV pHv = &pVM->gim.s.u.Hv;
     521    PVM     pVM = pVCpu->CTX_SUFF(pVM);
     522    PCGIMHV pHv = &pVM->gim.s.u.Hv;
    436523
    437524    switch (idMsr)
    438525    {
    439526        case MSR_GIM_HV_TIME_REF_COUNT:
    440         {
    441             /* Hyper-V reports the time in 100 ns units (10 MHz). */
    442             uint64_t u64Tsc      = TMCpuTickGet(pVCpu);
    443             uint64_t u64TscHz    = pHv->cTscTicksPerSecond;
    444             uint64_t u64Tsc100Ns = u64TscHz / UINT64_C(10000000); /* 100 ns */
    445             *puValue = (u64Tsc / u64Tsc100Ns);
    446             return VINF_SUCCESS;
    447         }
     527            *puValue = gimHvGetTimeRefCount(pVCpu);
     528            return VINF_SUCCESS;
    448529
    449530        case MSR_GIM_HV_VP_INDEX:
     
    452533
    453534        case MSR_GIM_HV_TPR:
    454             return PDMApicReadMsr(pVCpu, MSR_IA32_X2APIC_TPR, puValue);
     535            *puValue = APICHvGetTpr(pVCpu);
     536            return VINF_SUCCESS;
    455537
    456538        case MSR_GIM_HV_ICR:
    457             return PDMApicReadMsr(pVCpu, MSR_IA32_X2APIC_ICR, puValue);
     539            *puValue = APICHvGetIcr(pVCpu);
     540            return VINF_SUCCESS;
    458541
    459542        case MSR_GIM_HV_GUEST_OS_ID:
     
    491574        {
    492575            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
    493             *puValue = pHvCpu->auSintXMsr[idMsr - MSR_GIM_HV_SINT0];
     576            *puValue = pHvCpu->auSintMsrs[idMsr - MSR_GIM_HV_SINT0];
     577            return VINF_SUCCESS;
     578        }
     579
     580        case MSR_GIM_HV_STIMER0_CONFIG:
     581        case MSR_GIM_HV_STIMER1_CONFIG:
     582        case MSR_GIM_HV_STIMER2_CONFIG:
     583        case MSR_GIM_HV_STIMER3_CONFIG:
     584        {
     585            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     586            uint8_t const idxStimer  = (idMsr - MSR_GIM_HV_STIMER0_CONFIG) >> 1;
     587            PCGIMHVSTIMER pcHvStimer = &pHvCpu->aStimers[idxStimer];
     588            *puValue = pcHvStimer->uStimerConfigMsr;
     589            return VINF_SUCCESS;
     590        }
     591
     592        case MSR_GIM_HV_STIMER0_COUNT:
     593        case MSR_GIM_HV_STIMER1_COUNT:
     594        case MSR_GIM_HV_STIMER2_COUNT:
     595        case MSR_GIM_HV_STIMER3_COUNT:
     596        {
     597            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     598            uint8_t const idxStimer  = (idMsr - MSR_GIM_HV_STIMER0_COUNT) >> 1;
     599            PCGIMHVSTIMER pcHvStimer = &pHvCpu->aStimers[idxStimer];
     600            *puValue = pcHvStimer->uStimerCountMsr;
     601            return VINF_SUCCESS;
     602        }
     603
     604        case MSR_GIM_HV_EOM:
     605        {
     606            *puValue = 0;
     607            return VINF_SUCCESS;
     608        }
     609
     610        case MSR_GIM_HV_SCONTROL:
     611        {
     612            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     613            *puValue = pHvCpu->uSControlMsr;
    494614            return VINF_SUCCESS;
    495615        }
     
    580700    {
    581701        case MSR_GIM_HV_TPR:
    582             return PDMApicWriteMsr(pVCpu, MSR_IA32_X2APIC_TPR, uRawValue);
     702            return APICHvSetTpr(pVCpu, uRawValue);
    583703
    584704        case MSR_GIM_HV_EOI:
    585             return PDMApicWriteMsr(pVCpu, MSR_IA32_X2APIC_EOI, uRawValue);
     705            return APICHvSetEoi(pVCpu, uRawValue);
    586706
    587707        case MSR_GIM_HV_ICR:
    588             return PDMApicWriteMsr(pVCpu, MSR_IA32_X2APIC_ICR, uRawValue);
     708            return APICHvSetIcr(pVCpu, uRawValue);
    589709
    590710        case MSR_GIM_HV_GUEST_OS_ID:
     
    734854                else
    735855                {
    736                     LogRelMax(5, ("GIM: HyperV%u: APIC-assist page address %#RGp invalid!\n", pVCpu->idCpu,
     856                    LogRelMax(5, ("GIM%u: HyperV: APIC-assist page address %#RGp invalid!\n", pVCpu->idCpu,
    737857                                  GCPhysApicAssistPage));
    738858                }
     
    9051025                }
    9061026                else
    907                     LogRelMax(5, ("GIM: HyperV: Debug receive buffer address %#RGp invalid! Ignoring debug read!\n", (RTGCPHYS)pHv->uDbgRecvBufferMsr));
     1027                {
     1028                    LogRelMax(5, ("GIM: HyperV: Debug receive buffer address %#RGp invalid! Ignoring debug read!\n",
     1029                                  (RTGCPHYS)pHv->uDbgRecvBufferMsr));
     1030                }
    9081031            }
    9091032            return VINF_SUCCESS;
     
    9161039        case MSR_GIM_HV_SINT12:   case MSR_GIM_HV_SINT13:   case MSR_GIM_HV_SINT14:   case MSR_GIM_HV_SINT15:
    9171040        {
    918 #ifndef IN_RING3
    919             /** @todo make this RZ later? */
    920             return VINF_CPUM_R3_MSR_WRITE;
    921 #else
    922             PGIMHVCPU    pHvCpu     = &pVCpu->gim.s.u.HvCpu;
    923             uint8_t      uVector    = MSR_GIM_HV_SINT_VECTOR(uRawValue);
     1041            uint8_t      uVector    = MSR_GIM_HV_SINT_GET_VECTOR(uRawValue);
    9241042            bool const   fVMBusMsg  = RT_BOOL(idMsr == GIM_HV_VMBUS_MSG_SINT);
    9251043            size_t const idxSintMsr = idMsr - MSR_GIM_HV_SINT0;
     
    9271045            if (uVector < GIM_HV_SINT_VECTOR_VALID_MIN)
    9281046            {
    929                 LogRel(("GIM: HyperV%u: Programmed an invalid vector in SINT%u (%s), uVector=%u -> #GP(0)\n", pVCpu->idCpu,
     1047                LogRel(("GIM%u: HyperV: Programmed an invalid vector in SINT%u (%s), uVector=%u -> #GP(0)\n", pVCpu->idCpu,
    9301048                        idxSintMsr, pszDesc, uVector));
    9311049                return VERR_CPUM_RAISE_GP_0;
    9321050            }
    9331051
    934             pHvCpu->auSintXMsr[idxSintMsr] = uRawValue;
     1052            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     1053            pHvCpu->auSintMsrs[idxSintMsr] = uRawValue;
    9351054            if (fVMBusMsg)
    9361055            {
    9371056                if (MSR_GIM_HV_SINT_IS_MASKED(uRawValue))
    938                     LogRel(("GIM: HyperV%u: Masked SINT%u (%s)\n", pVCpu->idCpu, idxSintMsr, pszDesc));
     1057                    Log(("GIM%u: HyperV: Masked SINT%u (%s)\n", pVCpu->idCpu, idxSintMsr, pszDesc));
    9391058                else
    940                     LogRel(("GIM: HyperV%u: Unmasked SINT%u (%s), uVector=%u\n", pVCpu->idCpu, idxSintMsr, pszDesc, uVector));
    941             }
    942             return VINF_SUCCESS;
    943 #endif
     1059                    Log(("GIM%u: HyperV: Unmasked SINT%u (%s), uVector=%u\n", pVCpu->idCpu, idxSintMsr, pszDesc, uVector));
     1060            }
     1061            Log(("GIM%u: HyperV: Written SINT%u=%#RX64\n", pVCpu->idCpu, idxSintMsr, uRawValue));
     1062            return VINF_SUCCESS;
     1063        }
     1064
     1065        case MSR_GIM_HV_SCONTROL:
     1066        {
     1067#ifndef IN_RING3
     1068            /** @todo make this RZ later? */
     1069            return VINF_CPUM_R3_MSR_WRITE;
     1070#else
     1071            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     1072            pHvCpu->uSControlMsr = uRawValue;
     1073            if (MSR_GIM_HV_SCONTROL_IS_ENABLED(uRawValue))
     1074                LogRel(("GIM%u: HyperV: Synthetic interrupt control enabled\n", pVCpu->idCpu));
     1075            else
     1076                LogRel(("GIM%u: HyperV: Synthetic interrupt control disabled\n", pVCpu->idCpu));
     1077            return VINF_SUCCESS;
     1078#endif
     1079        }
     1080
     1081        case MSR_GIM_HV_STIMER0_CONFIG:
     1082        case MSR_GIM_HV_STIMER1_CONFIG:
     1083        case MSR_GIM_HV_STIMER2_CONFIG:
     1084        case MSR_GIM_HV_STIMER3_CONFIG:
     1085        {
     1086            PGIMHVCPU     pHvCpu    = &pVCpu->gim.s.u.HvCpu;
     1087            uint8_t const idxStimer = (idMsr - MSR_GIM_HV_STIMER0_CONFIG) >> 1;
     1088
     1089            /* Validate the writable bits. */
     1090            if (RT_LIKELY(!(uRawValue & ~MSR_GIM_HV_STIMER_RW_VALID)))
     1091            {
     1092                Assert(idxStimer < RT_ELEMENTS(pHvCpu->aStimers));
     1093                PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer];
     1094                PTMTIMER     pTimer    = pHvStimer->CTX_SUFF(pTimer);
     1095
     1096                /* Lock to prevent concurrent access from the timer callback. */
     1097                int rc = TMTimerLock(pTimer, VERR_IGNORED);
     1098                if (rc == VINF_SUCCESS)
     1099                {
     1100                    /* Update the MSR value. */
     1101                    pHvStimer->uStimerConfigMsr = uRawValue;
     1102                    Log(("GIM%u: HyperV: Set STIMER_CONFIG%u=%#RX64\n", pVCpu->idCpu, idxStimer, uRawValue));
     1103
     1104                    /* Process the MSR bits. */
     1105                    if (   !MSR_GIM_HV_STIMER_GET_SINTX(uRawValue)   /* Writing SINTx as 0 causes the timer to be disabled. */
     1106                        || !MSR_GIM_HV_STIMER_IS_ENABLED(uRawValue))
     1107                    {
     1108                        pHvStimer->uStimerConfigMsr &= ~MSR_GIM_HV_STIMER_ENABLE;
     1109                        gimHvStopStimer(pVCpu, pHvStimer);
     1110                        Log(("GIM%u: HyperV: Disabled STIMER_CONFIG%u\n", pVCpu->idCpu, idxStimer));
     1111                    }
     1112                    else if (MSR_GIM_HV_STIMER_IS_ENABLED(uRawValue))
     1113                    {
     1114                        /* Auto-enable implies writing to the STIMERx_COUNT MSR is what starts the timer. */
     1115                        if (!MSR_GIM_HV_STIMER_IS_AUTO_ENABLED(uRawValue))
     1116                        {
     1117                            if (!TMTimerIsActive(pHvStimer->CTX_SUFF(pTimer)))
     1118                            {
     1119                                gimHvStartStimer(pVCpu, pHvStimer);
     1120                                Log(("GIM%u: HyperV: Started STIMER%u\n", pVCpu->idCpu, idxStimer));
     1121                            }
     1122                            else
     1123                            {
     1124                                /*
     1125                                 * Enabling a timer that's already enabled is undefined behaviour,
     1126                                 * see Hyper-V spec. 15.3.1 "Synthetic Timer Configuration Register".
     1127                                 *
     1128                                 * Our implementation just re-starts the timer. Guests that comform to
     1129                                 * the Hyper-V specs. should not be doing this anyway.
     1130                                 */
     1131                                AssertFailed();
     1132                                gimHvStopStimer(pVCpu, pHvStimer);
     1133                                gimHvStartStimer(pVCpu, pHvStimer);
     1134                            }
     1135                        }
     1136                    }
     1137
     1138                    TMTimerUnlock(pTimer);
     1139                }
     1140                return rc;
     1141            }
     1142#ifndef IN_RING3
     1143            return VINF_CPUM_R3_MSR_WRITE;
     1144#else
     1145            LogRel(("GIM%u: HyperV: Setting reserved bits of STIMER%u MSR (uRawValue=%#RX64) -> #GP(0)\n", pVCpu->idCpu,
     1146                    idxStimer, uRawValue));
     1147            return VERR_CPUM_RAISE_GP_0;
     1148#endif
     1149        }
     1150
     1151        case MSR_GIM_HV_STIMER0_COUNT:
     1152        case MSR_GIM_HV_STIMER1_COUNT:
     1153        case MSR_GIM_HV_STIMER2_COUNT:
     1154        case MSR_GIM_HV_STIMER3_COUNT:
     1155        {
     1156            PGIMHVCPU     pHvCpu    = &pVCpu->gim.s.u.HvCpu;
     1157            uint8_t const idxStimer = (idMsr - MSR_GIM_HV_STIMER0_CONFIG) >> 1;
     1158            Assert(idxStimer < RT_ELEMENTS(pHvCpu->aStimers));
     1159            PGIMHVSTIMER  pHvStimer = &pHvCpu->aStimers[idxStimer];
     1160            int const     rcBusy    = VINF_CPUM_R3_MSR_WRITE;
     1161
     1162            /*
     1163             * Writing zero to this MSR disables the timer regardless of whether the auto-enable
     1164             * flag is set in the config MSR corresponding to the timer.
     1165             */
     1166            if (!uRawValue)
     1167            {
     1168                gimHvStopStimer(pVCpu, pHvStimer);
     1169                pHvStimer->uStimerCountMsr = 0;
     1170                Log(("GIM%u: HyperV: Set STIMER_COUNT%u=%RU64, stopped timer\n", pVCpu->idCpu, idxStimer, uRawValue));
     1171                return VINF_SUCCESS;
     1172            }
     1173
     1174            /*
     1175             * Concurrent writes to the config. MSR can't happen as it's serialized by way
     1176             * of being done on the same EMT as this.
     1177             */
     1178            if (MSR_GIM_HV_STIMER_IS_AUTO_ENABLED(pHvStimer->uStimerConfigMsr))
     1179            {
     1180                PTMTIMER pTimer = pHvStimer->CTX_SUFF(pTimer);
     1181                int rc = TMTimerLock(pTimer, rcBusy);
     1182                if (rc == VINF_SUCCESS)
     1183                {
     1184                    pHvStimer->uStimerCountMsr = uRawValue;
     1185                    gimHvStartStimer(pVCpu, pHvStimer);
     1186                    TMTimerUnlock(pTimer);
     1187                    Log(("GIM%u: HyperV: Set STIMER_COUNT%u=%RU64 %RU64 msec, auto-started timer\n", pVCpu->idCpu, idxStimer,
     1188                         uRawValue, (uRawValue * 100) / RT_NS_1MS_64));
     1189                }
     1190                return rc;
     1191            }
     1192
     1193            /* Simple update of the counter without any timer start/stop side-effects. */
     1194            pHvStimer->uStimerCountMsr = uRawValue;
     1195            Log(("GIM%u: HyperV: Set STIMER_COUNT%u=%RU64\n", pVCpu->idCpu, idxStimer, uRawValue));
     1196            return VINF_SUCCESS;
     1197        }
     1198
     1199        case MSR_GIM_HV_EOM:
     1200        {
     1201            /** @todo implement EOM. */
     1202            Log(("GIM%u: HyperV: EOM\n", pVCpu->idCpu));
     1203            return VINF_SUCCESS;
    9441204        }
    9451205
     
    9491209            return VINF_CPUM_R3_MSR_WRITE;
    9501210#else
    951             PGIMHVCPU pHvCpu  = &pVCpu->gim.s.u.HvCpu;
     1211            PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
    9521212            pHvCpu->uSiefpMsr = uRawValue;
    9531213            if (MSR_GIM_HV_SIEF_PAGE_IS_ENABLED(uRawValue))
     
    9591219                    if (RT_SUCCESS(rc))
    9601220                    {
     1221                        LogRel(("GIM%u: HyperV: Enabled synthetic interrupt event flags page at %#RGp\n", pVCpu->idCpu,
     1222                                GCPhysSiefPage));
    9611223                        /** @todo SIEF setup. */
    9621224                        return VINF_SUCCESS;
     
    9641226                }
    9651227                else
    966                     LogRelMax(5, ("GIM: HyperV%u: SIEF page address %#RGp invalid!\n", pVCpu->idCpu, GCPhysSiefPage));
     1228                    LogRelMax(5, ("GIM%u: HyperV: SIEF page address %#RGp invalid!\n", pVCpu->idCpu, GCPhysSiefPage));
    9671229            }
    9681230            else
     
    9761238        case MSR_GIM_HV_SIMP:
    9771239        {
    978             if (!pHv->fDbgEnabled)
    979                 return VERR_CPUM_RAISE_GP_0;
    9801240#ifndef IN_RING3
    9811241            return VINF_CPUM_R3_MSR_WRITE;
     
    9921252                    int rc2 = PGMPhysSimpleWriteGCPhys(pVM, GCPhysSimp, &abSimp[0], sizeof(abSimp));
    9931253                    if (RT_SUCCESS(rc2))
    994                         LogRel(("GIM: HyperV: Enabled synthetic interrupt message page at %#RGp\n", GCPhysSimp));
     1254                        LogRel(("GIM%u: HyperV: Enabled synthetic interrupt message page at %#RGp\n", pVCpu->idCpu, GCPhysSimp));
    9951255                    else
    9961256                    {
    997                         LogRel(("GIM: HyperV: WrMsr on MSR_GIM_HV_SIMP failed to update SIMP at %#RGp rc=%Rrc -> #GP(0)\n",
    998                                 GCPhysSimp, rc2));
     1257                        LogRel(("GIM%u: HyperV: Failed to update synthetic interrupt message page at %#RGp. uSimpMsr=%#RX64 rc=%Rrc\n",
     1258                                pVCpu->idCpu, pHvCpu->uSimpMsr, GCPhysSimp, rc2));
    9991259                        return VERR_CPUM_RAISE_GP_0;
    10001260                    }
    10011261                }
    10021262                else
    1003                     LogRel(("GIM: HyperV: Enabled synthetic interrupt message page at invalid address %#RGp\n",GCPhysSimp));
     1263                {
     1264                    LogRel(("GIM%u: HyperV: Enabled synthetic interrupt message page at invalid address %#RGp\n", pVCpu->idCpu,
     1265                            GCPhysSimp));
     1266                }
    10041267            }
    10051268            else
    1006                 LogRel(("GIM: HyperV: Disabled synthetic interrupt message page\n"));
     1269                LogRel(("GIM%u: HyperV: Disabled synthetic interrupt message page\n", pVCpu->idCpu));
    10071270            return VINF_SUCCESS;
    10081271#endif
  • trunk/src/VBox/VMM/VMMR3/GIM.cpp

    r62641 r63648  
    347347    }
    348348    return VINF_SUCCESS;
     349}
     350
     351
     352/**
     353 * Applies relocations to data and code managed by this
     354 * component. This function will be called at init and
     355 * whenever the VMM need to relocate it self inside the GC.
     356 *
     357 * @param   pVM         The cross context VM structure.
     358 * @param   offDelta    Relocation delta relative to old location.
     359 */
     360VMMR3_INT_DECL(void) GIMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
     361{
     362    switch (pVM->gim.s.enmProviderId)
     363    {
     364        case GIMPROVIDERID_HYPERV:
     365            gimR3HvRelocate(pVM, offDelta);
     366            break;
     367
     368        default:
     369            break;
     370    }
    349371}
    350372
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r62642 r63648  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_GIM
     23#include <VBox/vmm/apic.h>
    2324#include <VBox/vmm/gim.h>
    2425#include <VBox/vmm/cpum.h>
     
    4950 * GIM Hyper-V saved-state version.
    5051 */
    51 #define GIM_HV_SAVED_STATE_VERSION                UINT32_C(2)
     52#define GIM_HV_SAVED_STATE_VERSION                UINT32_C(3)
     53/** Saved states, prior to any synthetic interrupt controller support. */
     54#define GIM_HV_SAVED_STATE_VERSION_PRE_SYNIC      UINT32_C(2)
    5255/** Vanilla saved states, prior to any debug support. */
    5356#define GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG      UINT32_C(1)
     
    180183static void   gimR3HvTermHypercallSupport(PVM pVM);
    181184static int    gimR3HvInitDebugSupport(PVM pVM);
    182 #if 0 /** @todo currently unused, which is probably very wrong */
    183185static void   gimR3HvTermDebugSupport(PVM pVM);
    184 #endif
    185 
     186static DECLCALLBACK(void) gimR3HvTimerCallback(PVM pVM, PTMTIMER pTimer, void *pvUser);
    186187
    187188/**
     
    197198    AssertReturn(pVM->gim.s.enmProviderId == GIMPROVIDERID_HYPERV, VERR_INTERNAL_ERROR_5);
    198199
    199     int rc;
    200200    PGIMHV pHv = &pVM->gim.s.u.Hv;
    201201
     
    209209         * Validate the Hyper-V settings.
    210210         */
    211         rc = CFGMR3ValidateConfig(pCfgHv, "/HyperV/",
     211        int rc2 = CFGMR3ValidateConfig(pCfgHv, "/HyperV/",
    212212                                  "VendorID"
    213213                                  "|VSInterface"
    214214                                  "|HypercallDebugInterface",
    215215                                  "" /* pszValidNodes */, "GIM/HyperV" /* pszWho */, 0 /* uInstance */);
    216         if (RT_FAILURE(rc))
    217             return rc;
     216        if (RT_FAILURE(rc2))
     217            return rc2;
    218218    }
    219219
     
    221221     * The Hyper-V vendor signature, must be 12 characters. */
    222222    char szVendor[13];
    223     rc = CFGMR3QueryStringDef(pCfgHv, "VendorID", szVendor, sizeof(szVendor), "VBoxVBoxVBox");
     223    int rc = CFGMR3QueryStringDef(pCfgHv, "VendorID", szVendor, sizeof(szVendor), "VBoxVBoxVBox");
    224224    AssertLogRelRCReturn(rc, rc);
    225225    AssertLogRelMsgReturn(strlen(szVendor) == 12,
     
    255255                       //| GIM_HV_BASE_FEAT_VP_RUNTIME_MSR
    256256                       | GIM_HV_BASE_FEAT_PART_TIME_REF_COUNT_MSR
    257                        //| GIM_HV_BASE_FEAT_BASIC_SYNTH_IC
    258                        //| GIM_HV_BASE_FEAT_SYNTH_TIMER_MSRS
     257                       //| GIM_HV_BASE_FEAT_BASIC_SYNIC_MSRS
     258                       //| GIM_HV_BASE_FEAT_STIMER_MSRS
    259259                       | GIM_HV_BASE_FEAT_APIC_ACCESS_MSRS
    260260                       | GIM_HV_BASE_FEAT_HYPERCALL_MSRS
     
    279279        /* Hypervisor recommendations to the guest. */
    280280        pHv->uHyperHints = GIM_HV_HINT_MSR_FOR_SYS_RESET
    281                          | GIM_HV_HINT_RELAX_TIME_CHECKS;
     281                         | GIM_HV_HINT_RELAX_TIME_CHECKS
     282                         //| GIM_HV_HINT_X2APIC_MSRS
     283                         ;
    282284
    283285        /* Expose more if we're posing as Microsoft. We can, if needed, force MSR-based Hv
     
    347349    RT_ZERO(HyperLeaf);
    348350    HyperLeaf.uLeaf        = UINT32_C(0x40000000);
    349     HyperLeaf.uEax         = UINT32_C(0x40000006); /* Minimum value for Hyper-V is 0x40000005. */
     351    if (   pHv->fIsVendorMsHv
     352        && pHv->fIsInterfaceVs)
     353        HyperLeaf.uEax     = UINT32_C(0x40000082); /* Since we expose 0x40000082 below for the Hyper-V PV-debugging case. */
     354    else
     355        HyperLeaf.uEax     = UINT32_C(0x40000006); /* Minimum value for Hyper-V default is 0x40000005. */
    350356    /*
    351357     * Don't report vendor as 'Microsoft Hv'[1] by default, see @bugref{7270#c152}.
     
    404410    AssertLogRelRCReturn(rc, rc);
    405411
     412    RT_ZERO(HyperLeaf);
     413    HyperLeaf.uLeaf        = UINT32_C(0x40000005);
     414    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
     415    AssertLogRelRCReturn(rc, rc);
     416
     417    /* Leaf 0x40000006 is inserted in gimR3HvInitCompleted(). */
     418
    406419    if (   pHv->fIsVendorMsHv
    407420        && pHv->fIsInterfaceVs)
     
    437450    for (unsigned i = 0; i < RT_ELEMENTS(g_aMsrRanges_HyperV); i++)
    438451    {
    439         rc = CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_HyperV[i]);
    440         AssertLogRelRCReturn(rc, rc);
     452        int rc2 = CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_HyperV[i]);
     453        AssertLogRelRCReturn(rc2, rc2);
    441454    }
    442455
     
    449462    {
    450463        PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu;
    451         for (size_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintXMsr); idxSintMsr++)
    452             pHvCpu->auSintXMsr[idxSintMsr] = MSR_GIM_HV_SINT_MASKED;
     464        for (uint8_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSintMsr++)
     465            pHvCpu->auSintMsrs[idxSintMsr] = MSR_GIM_HV_SINT_MASKED;
    453466    }
    454467
     
    464477    rc = gimR3HvInitDebugSupport(pVM);
    465478    AssertLogRelRCReturn(rc, rc);
     479
     480    /*
     481     * Setup up the per-VCPU synthetic timers.
     482     */
     483    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     484    {
     485        PVMCPU       pVCpu     = &pVM->aCpus[idCpu];
     486        PGIMHVCPU    pHvCpu    = &pVCpu->gim.s.u.HvCpu;
     487
     488        for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++)
     489        {
     490            PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer];
     491
     492            /* Associate the synthetic timer with its corresponding VCPU. */
     493            pHvStimer->idCpu     = pVCpu->idCpu;
     494            pHvStimer->idxStimer = idxStimer;
     495
     496            /* Create the timer and associate the context pointers. */
     497            RTStrPrintf(&pHvStimer->szTimerDesc[0], sizeof(pHvStimer->szTimerDesc), "Hyper-V[%u] Timer%u", pVCpu->idCpu,
     498                        idxStimer);
     499            rc = TMR3TimerCreateInternal(pVM, TMCLOCK_VIRTUAL_SYNC, gimR3HvTimerCallback, pHvStimer /* pvUser */,
     500                                         pHvStimer->szTimerDesc, &pHvStimer->pTimerR3);
     501            AssertLogRelRCReturn(rc, rc);
     502            pHvStimer->pTimerR0 = TMTimerR0Ptr(pHvStimer->pTimerR3);
     503            pHvStimer->pTimerRC = TMTimerRCPtr(pHvStimer->pTimerR3);
     504        }
     505    }
     506
     507    /*
     508     * Inform APIC whether Hyper-V compatibility mode is enabled or not.
     509     */
     510    if (pHv->uHyperHints & GIM_HV_HINT_X2APIC_MSRS)
     511        APICR3HvSetCompatMode(pVM, true);
     512
     513    /*
     514     * Register statistics.
     515     */
     516    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     517    {
     518        PVMCPU    pVCpu  = &pVM->aCpus[idCpu];
     519        PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     520
     521        for (size_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStatStimerFired); idxStimer++)
     522        {
     523            int rc2 = STAMR3RegisterF(pVM, &pHvCpu->aStatStimerFired[idxStimer], STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS,
     524                                     STAMUNIT_OCCURENCES, "Number of times the synthetic timer fired.",
     525                                     "/GIM/HyperV/%u/Stimer%u_Fired", idCpu, idxStimer);
     526            AssertLogRelRCReturn(rc2, rc2);
     527        }
     528    }
    466529
    467530    return VINF_SUCCESS;
     
    516579    gimR3HvReset(pVM);
    517580    gimR3HvTermHypercallSupport(pVM);
     581    gimR3HvTermDebugSupport(pVM);
     582
     583    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     584    {
     585        PGIMHVCPU pHvCpu = &pVM->aCpus[idCpu].gim.s.u.HvCpu;
     586        for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++)
     587        {
     588            PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer];
     589            TMR3TimerDestroy(pHvStimer->pTimerR3);
     590        }
     591    }
     592
    518593    return VINF_SUCCESS;
     594}
     595
     596
     597/**
     598 * Applies relocations to data and code managed by this
     599 * component. This function will be called at init and
     600 * whenever the VMM need to relocate it self inside the GC.
     601 *
     602 * @param   pVM         The cross context VM structure.
     603 * @param   offDelta    Relocation delta relative to old location.
     604 */
     605VMMR3_INT_DECL(void) gimR3HvRelocate(PVM pVM, RTGCINTPTR offDelta)
     606{
     607    RT_NOREF1(offDelta);
     608    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     609    {
     610        PGIMHVCPU pHvCpu = &pVM->aCpus[idCpu].gim.s.u.HvCpu;
     611        for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++)
     612        {
     613            PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer];
     614            pHvStimer->pTimerRC = TMTimerRCPtr(pHvStimer->pTimerR3);
     615        }
     616    }
    519617}
    520618
     
    568666    {
    569667        PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu;
     668        pHvCpu->uSControlMsr = 0;
    570669        pHvCpu->uSimpMsr  = 0;
    571670        pHvCpu->uSiefpMsr = 0;
    572671        pHvCpu->uApicAssistPageMsr = 0;
    573         for (size_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintXMsr); idxSintMsr++)
    574             pHvCpu->auSintXMsr[idxSintMsr] = MSR_GIM_HV_SINT_MASKED;
     672
     673        for (uint8_t idxSint = 0; idxSint < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSint++)
     674            pHvCpu->auSintMsrs[idxSint] = MSR_GIM_HV_SINT_MASKED;
     675
     676        for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++)
     677        {
     678            PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer];
     679            pHvStimer->uStimerConfigMsr = 0;
     680            pHvStimer->uStimerCountMsr  = 0;
     681        }
    575682    }
    576683}
     
    741848        PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu;
    742849        SSMR3PutU64(pSSM, pHvCpu->uSimpMsr);
    743         SSMR3PutU64(pSSM, pHvCpu->auSintXMsr[GIM_HV_VMBUS_MSG_SINT]);
     850        for (size_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSintMsr++)
     851            SSMR3PutU64(pSSM, pHvCpu->auSintMsrs[idxSintMsr]);
    744852    }
    745853
     
    760868     * Load the Hyper-V SSM version first.
    761869     */
    762     uint32_t uHvSavedStatVersion;
    763     int rc = SSMR3GetU32(pSSM, &uHvSavedStatVersion);
     870    uint32_t uHvSavedStateVersion;
     871    int rc = SSMR3GetU32(pSSM, &uHvSavedStateVersion);
    764872    AssertRCReturn(rc, rc);
    765     if (   uHvSavedStatVersion != GIM_HV_SAVED_STATE_VERSION
    766         && uHvSavedStatVersion != GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG)
     873    if (   uHvSavedStateVersion != GIM_HV_SAVED_STATE_VERSION
     874        && uHvSavedStateVersion != GIM_HV_SAVED_STATE_VERSION_PRE_SYNIC
     875        && uHvSavedStateVersion != GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG)
    767876        return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS,
    768877                                 N_("Unsupported Hyper-V saved-state version %u (current %u)!"),
    769                                  uHvSavedStatVersion, GIM_HV_SAVED_STATE_VERSION);
     878                                 uHvSavedStateVersion, GIM_HV_SAVED_STATE_VERSION);
    770879
    771880    /*
     
    855964     * Load the debug support data.
    856965     */
    857     if (uHvSavedStatVersion > GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG)
     966    if (uHvSavedStateVersion > GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG)
    858967    {
    859968        SSMR3GetU64(pSSM, &pHv->uDbgPendingBufferMsr);
     
    870979            PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu;
    871980            SSMR3GetU64(pSSM, &pHvCpu->uSimpMsr);
    872             SSMR3GetU64(pSSM, &pHvCpu->auSintXMsr[GIM_HV_VMBUS_MSG_SINT]);
     981            if (uHvSavedStateVersion <= GIM_HV_SAVED_STATE_VERSION_PRE_SYNIC)
     982                SSMR3GetU64(pSSM, &pHvCpu->auSintMsrs[GIM_HV_VMBUS_MSG_SINT]);
     983            else
     984            {
     985                for (uint8_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSintMsr++)
     986                    SSMR3GetU64(pSSM, &pHvCpu->auSintMsrs[idxSintMsr]);
     987            }
    873988        }
    874989
     
    9101025        {
    9111026            /** @todo Inform APIC. */
    912             LogRel(("GIM: HyperV%u: Enabled APIC-assist page at %#RGp\n", pVCpu->idCpu, GCPhysApicAssistPage));
     1027            LogRel(("GIM%u: HyperV: Enabled APIC-assist page at %#RGp\n", pVCpu->idCpu, GCPhysApicAssistPage));
    9131028        }
    9141029        else
    9151030        {
    916             LogRelFunc(("GIM: HyperV%u: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));
     1031            LogRelFunc(("GIM%u: HyperV: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));
    9171032            rc = VERR_GIM_OPERATION_FAILED;
    9181033        }
     
    9221037    }
    9231038
    924     LogRelFunc(("GIM: HyperV%u: Failed to alloc %u bytes\n", pVCpu->idCpu, cbApicAssistPage));
     1039    LogRelFunc(("GIM%u: HyperV: Failed to alloc %u bytes\n", pVCpu->idCpu, cbApicAssistPage));
    9251040    return VERR_NO_MEMORY;
    9261041}
     
    9351050VMMR3_INT_DECL(int) gimR3HvDisableApicAssistPage(PVMCPU pVCpu)
    9361051{
    937     LogRel(("GIM: HyperV%u: Disabled APIC-assist page\n", pVCpu->idCpu));
     1052    LogRel(("GIM%u: HyperV: Disabled APIC-assist page\n", pVCpu->idCpu));
    9381053    /** @todo inform APIC */
    9391054    return VINF_SUCCESS;
     1055}
     1056
     1057
     1058/**
     1059 * Hyper-V synthetic timer callback.
     1060 *
     1061 * @param   pVM         The cross context VM structure.
     1062 * @param   pTimer      Pointer to timer.
     1063 * @param   pvUser      Pointer to the synthetic timer.
     1064 */
     1065static DECLCALLBACK(void) gimR3HvTimerCallback(PVM pVM, PTMTIMER pTimer, void *pvUser)
     1066{
     1067    PGIMHVSTIMER pHvStimer = (PGIMHVSTIMER)pvUser;
     1068    Assert(pHvStimer);
     1069    Assert(TMTimerIsLockOwner(pTimer));
     1070    Assert(pHvStimer->idCpu < pVM->cCpus);
     1071
     1072    PVMCPU    pVCpu  = &pVM->aCpus[pHvStimer->idCpu];
     1073    PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu;
     1074    Assert(pHvStimer->idxStimer < RT_ELEMENTS(pHvCpu->aStatStimerFired));
     1075
     1076    STAM_COUNTER_INC(&pHvCpu->aStatStimerFired[pHvStimer->idxStimer]);
     1077
     1078    uint64_t const uStimerConfig = pHvStimer->uStimerConfigMsr;
     1079    uint16_t const idxSint       = MSR_GIM_HV_STIMER_GET_SINTX(uStimerConfig);
     1080    if (RT_LIKELY(idxSint < RT_ELEMENTS(pHvCpu->auSintMsrs)))
     1081    {
     1082        uint64_t const uSint = pHvCpu->auSintMsrs[idxSint];
     1083        if (!MSR_GIM_HV_SINT_IS_MASKED(uSint))
     1084        {
     1085            uint8_t const uVector  = MSR_GIM_HV_SINT_GET_VECTOR(uSint);
     1086            bool const    fAutoEoi = MSR_GIM_HV_SINT_IS_AUTOEOI(uSint);
     1087            APICHvSendInterrupt(pVCpu, uVector, fAutoEoi, XAPICTRIGGERMODE_EDGE);
     1088        }
     1089    }
     1090
     1091    /* Re-arm the timer if it's periodic. */
     1092    if (MSR_GIM_HV_STIMER_IS_PERIODIC(uStimerConfig))
     1093        gimHvStartStimer(pVCpu, pHvStimer);
    9401094}
    9411095
     
    9681122        {
    9691123            /** @todo SIEF setup. */
    970             LogRel(("GIM: HyperV%u: Enabled SIEF page at %#RGp\n", pVCpu->idCpu, GCPhysSiefPage));
     1124            LogRel(("GIM%u: HyperV: Enabled SIEF page at %#RGp\n", pVCpu->idCpu, GCPhysSiefPage));
    9711125        }
    9721126        else
    9731127        {
    974             LogRelFunc(("GIM: HyperV%u: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));
     1128            LogRelFunc(("GIM%u: HyperV: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));
    9751129            rc = VERR_GIM_OPERATION_FAILED;
    9761130        }
     
    9801134    }
    9811135
    982     LogRelFunc(("GIM: HyperV%u: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSiefPage));
     1136    LogRelFunc(("GIM%u: HyperV: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSiefPage));
    9831137    return VERR_NO_MEMORY;
    9841138}
     
    9931147VMMR3_INT_DECL(int) gimR3HvDisableSiefPage(PVMCPU pVCpu)
    9941148{
    995     LogRel(("GIM: HyperV%u: Disabled APIC-assist page\n", pVCpu->idCpu));
     1149    LogRel(("GIM%u: HyperV: Disabled APIC-assist page\n", pVCpu->idCpu));
    9961150    /** @todo SIEF teardown. */
    9971151    return VINF_SUCCESS;
     
    11421296        {
    11431297            /** @todo SIM setup. */
    1144             LogRel(("GIM: HyperV%u: Enabled SIM page at %#RGp\n", pVCpu->idCpu, GCPhysSimPage));
     1298            LogRel(("GIM%u: HyperV: Enabled SIM page at %#RGp\n", pVCpu->idCpu, GCPhysSimPage));
    11451299        }
    11461300        else
    11471301        {
    1148             LogRelFunc(("GIM: HyperV%u: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));
     1302            LogRelFunc(("GIM%u: HyperV: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));
    11491303            rc = VERR_GIM_OPERATION_FAILED;
    11501304        }
     
    11541308    }
    11551309
    1156     LogRelFunc(("GIM: HyperV%u: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSimPage));
     1310    LogRelFunc(("GIM%u: HyperV: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSimPage));
    11571311    return VERR_NO_MEMORY;
    11581312}
     
    11671321VMMR3_INT_DECL(int) gimR3HvDisableSimPage(PVMCPU pVCpu)
    11681322{
    1169     LogRel(("GIM: HyperV%u: Disabled SIM page\n", pVCpu->idCpu));
     1323    LogRel(("GIM%u: HyperV: Disabled SIM page\n", pVCpu->idCpu));
    11701324    /** @todo SIM teardown. */
    11711325    return VINF_SUCCESS;
     
    14001554
    14011555
    1402 #if 0 /** @todo currently unused, which is probably very wrong */
    14031556/**
    14041557 * Terminates Hyper-V guest debug support.
     
    14151568    }
    14161569}
    1417 #endif
    14181570
    14191571
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r62869 r63648  
    12641264    DBGFR3Relocate(pVM, offDelta);
    12651265    PDMR3Relocate(pVM, offDelta);
     1266    GIMR3Relocate(pVM, offDelta);
    12661267}
    12671268
  • trunk/src/VBox/VMM/include/GIMHvInternal.h

    r62641 r63648  
    476476/** Whether the SIEF page is enabled or not. */
    477477#define MSR_GIM_HV_SIEF_PAGE_IS_ENABLED(a)        RT_BOOL((a) & MSR_GIM_HV_SIEF_PAGE_ENABLE)
     478/** @} */
     479
     480/** @name Hyper-V MSR - Synthetic Interrupt Control (MSR_GIM_HV_CONTROL).
     481 * @{
     482 */
     483/** The SControl enable mask. */
     484#define MSR_GIM_HV_SCONTROL_ENABLE                RT_BIT_64(0)
     485/** Whether SControl is enabled or not. */
     486#define MSR_GIM_HV_SCONTROL_IS_ENABLED(a)         RT_BOOL((a) & MSR_GIM_HV_SCONTROL_ENABLE)
     487/** @} */
     488
     489/** @name Hyper-V MSR - Synthetic Timer Config (MSR_GIM_HV_STIMER_CONFIG).
     490 * @{
     491 */
     492/** The Stimer enable mask. */
     493#define MSR_GIM_HV_STIMER_ENABLE                  RT_BIT_64(0)
     494/** Whether Stimer is enabled or not. */
     495#define MSR_GIM_HV_STIMER_IS_ENABLED(a)           RT_BOOL((a) & MSR_GIM_HV_STIMER_ENABLE)
     496/** The Stimer periodic mask. */
     497#define MSR_GIM_HV_STIMER_PERIODIC                RT_BIT_64(1)
     498/** Whether Stimer is enabled or not. */
     499#define MSR_GIM_HV_STIMER_IS_PERIODIC(a)          RT_BOOL((a) & MSR_GIM_HV_STIMER_PERIODIC)
     500/** The Stimer lazy mask. */
     501#define MSR_GIM_HV_STIMER_LAZY                    RT_BIT_64(2)
     502/** Whether Stimer is enabled or not. */
     503#define MSR_GIM_HV_STIMER_IS_LAZY(a)              RT_BOOL((a) & MSR_GIM_HV_STIMER_LAZY)
     504/** The Stimer auto-enable mask. */
     505#define MSR_GIM_HV_STIMER_AUTO_ENABLE             RT_BIT_64(3)
     506/** Whether Stimer is enabled or not. */
     507#define MSR_GIM_HV_STIMER_IS_AUTO_ENABLED(a)      RT_BOOL((a) & MSR_GIM_HV_STIMER_AUTO_ENABLE)
     508/** The Stimer SINTx mask (bits 16:19). */
     509#define MSR_GIM_HV_STIMER_SINTX                   UINT64_C(0xf0000)
     510/** Gets the Stimer synthetic interrupt source. */
     511#define MSR_GIM_HV_STIMER_GET_SINTX(a)            (((a) >> 16) & 0xf)
     512/** The Stimer valid read/write mask. */
     513#define MSR_GIM_HV_STIMER_RW_VALID                (  MSR_GIM_HV_STIMER_ENABLE | MSR_GIM_HV_STIMER_PERIODIC    \
     514                                                   | MSR_GIM_HV_STIMER_LAZY   | MSR_GIM_HV_STIMER_AUTO_ENABLE \
     515                                                   | MSR_GIM_HV_STIMER_SINTX)
    478516/** @} */
    479517
     
    726764/** Whether the interrupt source is masked. */
    727765#define MSR_GIM_HV_SINT_IS_MASKED(a)                   RT_BOOL((a) & MSR_GIM_HV_SINT_MASKED)
    728 /** Interrupt vector. */
    729 #define MSR_GIM_HV_SINT_VECTOR(a)                      ((a) & UINT64_C(0xff))
     766/** Gets the interrupt vector. */
     767#define MSR_GIM_HV_SINT_GET_VECTOR(a)                  ((a) & UINT64_C(0xff))
     768/** The AutoEoi mask. */
     769#define MSR_GIM_HV_SINT_AUTOEOI                        RT_BIT_64(17)
     770/** Gets whether AutoEoi is enabled for the synthetic interrupt. */
     771#define MSR_GIM_HV_SINT_IS_AUTOEOI(a)                  RT_BOOL((a) & MSR_GIM_HV_SINT_AUTOEOI)
    730772/** @} */
    731773
     
    787829/** SynIC version register. */
    788830#define GIM_HV_SVERSION                           1
    789 /** Number of synthetic interrupt sources. */
     831/** Number of synthetic interrupt sources (warning, fixed in saved-states!). */
    790832#define GIM_HV_SINT_COUNT                         16
    791833/** Lowest valid vector for synthetic interrupt. */
     
    793835/** Highest valid vector for synthetic interrupt. */
    794836#define GIM_HV_SINT_VECTOR_VALID_MAX              255
     837/** Number of synthetic timers. */
     838#define GIM_HV_STIMER_COUNT                       4
    795839/** @} */
    796840
    797841/** @name Hyper-V synthetic interrupt message type.
     842 * See 14.8.2 "SynIC Message Types"
    798843 * @{
    799844 */
     
    11361181
    11371182/**
    1138  * GIM Hyper-V VCPU instance data.
     1183 * Hyper-V per-VCPU synthetic timer.
     1184 */
     1185typedef struct GIMHVSTIMER
     1186{
     1187    /** Synthetic timer object - R0 ptr. */
     1188    PTMTIMERR0                  pTimerR0;
     1189    /** Synthetic timer object - R3 ptr. */
     1190    PTMTIMERR3                  pTimerR3;
     1191    /** Synthetic timer object - RC ptr. */
     1192    PTMTIMERRC                  pTimerRC;
     1193    /** RC alignment padding. */
     1194    RTRCPTR                     uAlignment0;
     1195    /** Virtual CPU ID this timer belongs to (for reverse mapping). */
     1196    VMCPUID                     idCpu;
     1197    /** The index of this timer in the auStimers array (for reverse mapping). */
     1198    uint32_t                    idxStimer;
     1199    /** Synthetic timer config MSR. */
     1200    uint64_t                    uStimerConfigMsr;
     1201    /** Synthetic timer count MSR. */
     1202    uint64_t                    uStimerCountMsr;
     1203    /** Timer description. */
     1204    char                        szTimerDesc[24];
     1205
     1206} GIMHVSTIMER;
     1207/** Pointer to per-VCPU Hyper-V synthetic timer. */
     1208typedef GIMHVSTIMER *PGIMHVSTIMER;
     1209/** Pointer to a const per-VCPU Hyper-V synthetic timer. */
     1210typedef GIMHVSTIMER const *PCGIMHVSTIMER;
     1211AssertCompileSizeAlignment(GIMHVSTIMER, 8);
     1212
     1213/**
     1214 * Hyper-V VCPU instance data.
    11391215 * Changes to this must checked against the padding of the gim union in VMCPU!
    11401216 */
     
    11461222    uint64_t                    uSimpMsr;
    11471223    /** Interrupt source MSRs. */
    1148     uint64_t                    auSintXMsr[GIM_HV_SINT_COUNT];
     1224    uint64_t                    auSintMsrs[GIM_HV_SINT_COUNT];
    11491225    /** Synethtic interrupt events flag page MSR. */
    11501226    uint64_t                    uSiefpMsr;
    11511227    /** APIC-assist page MSR. */
    11521228    uint64_t                    uApicAssistPageMsr;
     1229    /** Synthetic interrupt control MSR. */
     1230    uint64_t                    uSControlMsr;
     1231    /** Synthetic timers. */
     1232    GIMHVSTIMER                 aStimers[GIM_HV_STIMER_COUNT];
     1233    /** @} */
     1234
     1235    /** @name Statistics.
     1236     * @{ */
     1237    STAMCOUNTER                 aStatStimerFired[GIM_HV_STIMER_COUNT];
    11531238    /** @} */
    11541239} GIMHVCPU;
     
    12051290VMM_INT_DECL(VBOXSTRICTRC)      gimHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue);
    12061291
     1292VMM_INT_DECL(void)              gimHvStartStimer(PVMCPU pVCpu, PCGIMHVSTIMER pHvStimer);
     1293
    12071294RT_C_DECLS_END
    12081295
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