VirtualBox

Changeset 51643 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Jun 18, 2014 11:06:06 AM (11 years ago)
Author:
vboxsync
Message:

VMM/GIM: More bits for Hyper-V implementation.

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

Legend:

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

    r51422 r51643  
    17491749    if (RT_UNLIKELY(rc != VINF_SUCCESS))
    17501750    {
    1751         Assert(rc == VERR_CPUM_RAISE_GP_0);
     1751        Assert(rc == VERR_CPUM_RAISE_GP_0 || rc == VERR_EM_INTERPRETER);
    17521752        Log4(("EM: Refuse RDMSR: rc=%Rrc\n", rc));
    17531753        return VERR_EM_INTERPRETER;
  • trunk/src/VBox/VMM/VMMAll/GIMAll.cpp

    r51563 r51643  
    4545
    4646/**
     47 * Gets the GIM provider configured for this VM.
     48 *
     49 * @returns The GIM provider Id.
     50 * @param   pVM     Pointer to the VM.
     51 */
     52VMMDECL(GIMPROVIDERID) GIMGetProvider(PVM pVM)
     53{
     54    return pVM->gim.s.enmProviderId;
     55}
     56
     57
     58/**
    4759 * Implements a GIM hypercall with the provider configured for the VM.
    4860 *
     
    6779    }
    6880}
    69 
    70 
    71 /**
    72  * Updates the paravirtualized TSC supported by the GIM provider.
    73  *
    74  * @returns VBox status code.
    75  * @retval VINF_SUCCESS if the paravirt. TSC is setup and in use.
    76  * @retval VERR_GIM_NOT_ENABLED if no GIM provider is configured for this VM.
    77  * @retval VERR_GIM_PVTSC_NOT_AVAILABLE if the GIM provider does not support any
    78  *         paravirt. TSC.
    79  * @retval VERR_GIM_PVTSC_NOT_IN_USE if the GIM provider supports paravirt. TSC
    80  *         but the guest isn't currently using it.
    81  *
    82  * @param   pVM         Pointer to the VM.
    83  * @param   u64Offset   The computed TSC offset.
    84  *
    85  * @thread EMT(pVCpu)
    86  */
    87 VMMDECL(int) GIMUpdateParavirtTsc(PVM pVM, uint64_t u64Offset)
    88 {
    89     if (!pVM->gim.s.fEnabled)
    90         return VERR_GIM_NOT_ENABLED;
    91 
    92     switch (pVM->gim.s.enmProviderId)
    93     {
    94         case GIMPROVIDERID_HYPERV:
    95             return GIMHvUpdateParavirtTsc(pVM, u64Offset);
    96 
    97         default:
    98             break;
    99     }
    100     return VERR_GIM_PVTSC_NOT_AVAILABLE;
    101 }
    102 
    10381
    10482VMMDECL(bool) GIMIsParavirtTscEnabled(PVM pVM)
  • trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp

    r51563 r51643  
    2828#include <VBox/vmm/vm.h>
    2929#include <VBox/vmm/pgm.h>
     30#include <VBox/vmm/pdmdev.h>
     31
     32#include <iprt/asm-amd64-x86.h>
     33#include <iprt/spinlock.h>
    3034
    3135
     
    5357{
    5458    return MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
    55 }
    56 
    57 
    58 /**
    59  * Updates Hyper-V's reference TSC page.
    60  *
    61  * @returns VBox status code.
    62  * @param   pVM         Pointer to the VM.
    63  * @param   u64Offset   The computed TSC offset.
    64  * @thread EMT(pVCpu)
    65  */
    66 VMM_INT_DECL(int) GIMHvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset)
    67 {
    68     Assert(GIMIsEnabled(pVM));
    69     bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
    70     if (!fHvTscEnabled)
    71         return VERR_GIM_PVTSC_NOT_ENABLED;
    72 
    73     PGIMHV          pHv      = &pVM->gim.s.u.Hv;
    74     PGIMMMIO2REGION pRegion  = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
    75     PGIMHVREFTSC    pRefTsc  = (PGIMHVREFTSC)pRegion->CTX_SUFF(pvPage);
    76     Assert(pRefTsc);
    77 
    78     /** @todo Protect this with a spinlock! */
    79     pRefTsc->u64TscScale  = UINT64_C(0x1000000000000000);
    80     pRefTsc->u64TscOffset = u64Offset;
    81     ASMAtomicIncU32(&pRefTsc->u32TscSequence);
    82 
    83     return VINF_SUCCESS;
    8459}
    8560
     
    10479        case MSR_GIM_HV_TIME_REF_COUNT:
    10580        {
    106             /* Hyper-V reports the time in 100ns units. */
     81            /* Hyper-V reports the time in 100 ns units (10 MHz). */
    10782            uint64_t u64Tsc      = TMCpuTickGet(pVCpu);
    10883            uint64_t u64TscHz    = TMCpuTicksPerSecond(pVM);
     
    129104
    130105        case MSR_GIM_HV_TSC_FREQ:
    131             *puValue = TMCpuTicksPerSecond(pVM);
    132             return VINF_SUCCESS;
     106#ifndef IN_RING3
     107            return VERR_EM_INTERPRETER;
     108#else
     109            LogRel(("GIM: MSR_GIM_HV_TSC_FREQ %u\n", TMCpuTicksPerSecond(pVM)));
     110            //*puValue = TMCpuTicksPerSecond(pVM);
     111            *puValue = 2690000000;
     112            return VINF_SUCCESS;
     113#endif
    133114
    134115        case MSR_GIM_HV_APIC_FREQ:
    135116            /** @todo Fix this later! Get the information from DevApic. */
    136117            *puValue = UINT32_C(1000000000); /* TMCLOCK_FREQ_VIRTUAL */
     118            return VINF_SUCCESS;
     119
     120        case MSR_GIM_HV_RESET:
     121            *puValue = 0;
    137122            return VINF_SUCCESS;
    138123
     
    171156            if (!uRawValue)
    172157            {
    173                 GIMR3Mmio2Unmap(pVM, &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]);
     158                GIMR3HvDisableHypercallPage(pVM);
    174159                pHv->u64HypercallMsr &= ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT;
    175                 Log4Func(("Disabled hypercalls\n"));
    176160            }
    177161            pHv->u64GuestOsIdMsr = uRawValue;
     
    196180            }
    197181
    198             PPDMDEVINSR3    pDevIns = pVM->gim.s.pDevInsR3;
    199             PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
    200             AssertPtr(pDevIns);
    201             AssertPtr(pRegion);
    202 
    203             /*
    204              * Is the guest disabling the hypercall-page? Allow it regardless of the Guest-OS Id Msr.
    205              */
     182            /* Is the guest disabling the hypercall-page? Allow it regardless of the Guest-OS Id Msr. */
    206183            if (!fEnable)
    207184            {
    208                 GIMR3Mmio2Unmap(pVM, pRegion);
     185                GIMR3HvDisableHypercallPage(pVM);
    209186                pHv->u64HypercallMsr = uRawValue;
    210                 Log4Func(("Disabled hypercalls\n"));
    211                 return VINF_SUCCESS;
    212             }
    213 
    214             /*
    215              * Map the hypercall-page.
    216              */
     187                return VINF_SUCCESS;
     188            }
     189
     190            /* Enable the hypercall-page. */
    217191            RTGCPHYS GCPhysHypercallPage = MSR_GIM_HV_HYPERCALL_GUEST_PFN(uRawValue) << PAGE_SHIFT;
    218             int rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysHypercallPage, "Hyper-V Hypercall-page");
     192            int rc = GIMR3HvEnableHypercallPage(pVM, GCPhysHypercallPage);
    219193            if (RT_SUCCESS(rc))
    220194            {
    221                 /*
    222                  * Patch the hypercall-page.
    223                  */
    224                 if (HMIsEnabled(pVM))
    225                 {
    226                     size_t cbWritten = 0;
    227                     rc = HMPatchHypercall(pVM, pRegion->pvPageR3, PAGE_SIZE, &cbWritten);
    228                     if (   RT_SUCCESS(rc)
    229                         && cbWritten < PAGE_SIZE - 1)
    230                     {
    231                         uint8_t *pbLast = (uint8_t *)pRegion->pvPageR3 + cbWritten;
    232                         *pbLast = 0xc3;  /* RET */
    233 
    234                         pHv->u64HypercallMsr = uRawValue;
    235                         LogRelFunc(("Enabled hypercalls at %#RGp\n", GCPhysHypercallPage));
    236                         LogRelFunc(("%.*Rhxd\n", cbWritten + 1, (uint8_t *)pRegion->pvPageR3));
    237                         return VINF_SUCCESS;
    238                     }
    239 
    240                     LogFunc(("MSR_GIM_HV_HYPERCALL: HMPatchHypercall failed. rc=%Rrc cbWritten=%u\n", rc, cbWritten));
    241                 }
    242                 else
    243                 {
    244                     /** @todo Handle raw-mode hypercall page patching. */
    245                     LogRelFunc(("MSR_GIM_HV_HYPERCALL: raw-mode not yet implemented!\n"));
    246                 }
    247 
    248                 GIMR3Mmio2Unmap(pVM, pRegion);
    249             }
    250             else
    251                 LogFunc(("MSR_GIM_HV_HYPERCALL: GIMR3Mmio2Map failed. rc=%Rrc -> #GP(0)\n", rc));
     195                pHv->u64HypercallMsr = uRawValue;
     196                return VINF_SUCCESS;
     197            }
    252198
    253199            return VERR_CPUM_RAISE_GP_0;
     
    263209            pHv->u64TscPageMsr = (uRawValue & ~MSR_GIM_HV_REF_TSC_ENABLE_BIT);
    264210
    265             PPDMDEVINSR3    pDevIns = pVM->gim.s.pDevInsR3;
    266             PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
    267             AssertPtr(pDevIns);
    268             AssertPtr(pRegion);
    269 
    270             /*
    271              * Is the guest disabling the TSC-page?
    272              */
     211            /* Is the guest disabling the TSC-page? */
    273212            bool fEnable = RT_BOOL(uRawValue & MSR_GIM_HV_REF_TSC_ENABLE_BIT);
    274213            if (!fEnable)
    275214            {
    276                 GIMR3Mmio2Unmap(pVM, pRegion);
    277                 Log4Func(("Disabled TSC-page\n"));
    278                 return VINF_SUCCESS;
    279             }
    280 
    281             /*
    282              * Map the TSC-page.
    283              */
     215                GIMR3HvDisableTscPage(pVM);
     216                pHv->u64TscPageMsr = uRawValue;
     217                return VINF_SUCCESS;
     218            }
     219
     220            /* Enable the TSC-page. */
    284221            RTGCPHYS GCPhysTscPage = MSR_GIM_HV_REF_TSC_GUEST_PFN(uRawValue) << PAGE_SHIFT;
    285             int rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysTscPage, "Hyper-V TSC-page");
     222            int rc = GIMR3HvEnableTscPage(pVM, GCPhysTscPage);
    286223            if (RT_SUCCESS(rc))
    287224            {
    288225                pHv->u64TscPageMsr = uRawValue;
    289                 Log4Func(("MSR_GIM_HV_REF_TSC: Enabled Hyper-V TSC page at %#RGp\n", GCPhysTscPage));
    290                 return VINF_SUCCESS;
    291             }
    292             else
    293                 LogFunc(("MSR_GIM_HV_REF_TSC: GIMR3Mmio2Map failed. rc=%Rrc -> #GP(0)\n", rc));
     226                return VINF_SUCCESS;
     227            }
    294228
    295229            return VERR_CPUM_RAISE_GP_0;
     230#endif  /* !IN_RING3 */
     231        }
     232
     233        case MSR_GIM_HV_RESET:
     234        {
     235#ifndef IN_RING3
     236            return VERR_EM_INTERPRETER;
     237#else
     238            if (MSR_GIM_HV_RESET_IS_SET(uRawValue))
     239            {
     240                LogRel(("GIM: HyperV: Reset initiated by MSR.\n"));
     241                int rc = PDMDevHlpVMReset(pVM->gim.s.pDevInsR3);
     242                AssertRC(rc);
     243            }
     244            /* else: Ignore writes to other bits. */
     245            return VINF_SUCCESS;
    296246#endif  /* !IN_RING3 */
    297247        }
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r49640 r51643  
    10361036        uint8_t  idMmio2 = PGM_MMIO2_PAGEID_GET_MMIO2_ID(PGM_PAGE_GET_PAGEID(pPage));
    10371037        uint32_t iPage   = PGM_MMIO2_PAGEID_GET_IDX(PGM_PAGE_GET_PAGEID(pPage));
    1038         AssertLogRelReturn((uint8_t)(idMmio2 - 1U)< RT_ELEMENTS(pVM->pgm.s.CTX_SUFF(apMmio2Ranges)),
    1039                             VERR_PGM_PHYS_PAGE_MAP_MMIO2_IPE);
     1038        AssertLogRelMsgReturn((uint8_t)(idMmio2 - 1U) < RT_ELEMENTS(pVM->pgm.s.CTX_SUFF(apMmio2Ranges)),
     1039                              ("idMmio2=%u size=%u type=%u GCPHys=%#RGp Id=%u State=%u", idMmio2,
     1040                               RT_ELEMENTS(pVM->pgm.s.CTX_SUFF(apMmio2Ranges)), PGM_PAGE_GET_TYPE(pPage), GCPhys,
     1041                               pPage->s.idPage, pPage->s.uStateY),
     1042                              VERR_PGM_PHYS_PAGE_MAP_MMIO2_IPE);
    10401043        PPGMMMIO2RANGE pMmio2Range = pVM->pgm.s.CTX_SUFF(apMmio2Ranges)[idMmio2 - 1];
    10411044        AssertLogRelReturn(pMmio2Range, VERR_PGM_PHYS_PAGE_MAP_MMIO2_IPE);
  • trunk/src/VBox/VMM/VMMAll/TMAllCpu.cpp

    r44933 r51643  
    2525#include "TMInternal.h"
    2626#include <VBox/vmm/vm.h>
     27#include <VBox/vmm/gim.h>
    2728#include <VBox/sup.h>
    2829
     
    140141 *
    141142 * @returns true/false accordingly.
    142  * @param   pVCpu       Pointer to the VMCPU.
     143 * @param   pVCpu           Pointer to the VMCPU.
    143144 * @param   poffRealTSC     The offset against the TSC of the current CPU.
    144145 *                          Can be NULL.
    145  * @thread EMT.
    146  */
    147 VMM_INT_DECL(bool) TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC)
     146 * @param   pfParavirtTsc   Where to store whether paravirt. TSC can be used or
     147 *                          not.
     148 * @thread EMT(pVCpu).
     149 */
     150VMM_INT_DECL(bool) TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfParavirtTsc)
    148151{
    149152    PVM pVM = pVCpu->CTX_SUFF(pVM);
     153    bool fParavirtTsc = false;
    150154
    151155    /*
    152156     * We require:
     157     *     1. Use of a paravirtualized TSC is enabled by the guest.
     158     *     (OR)
    153159     *     1. A fixed TSC, this is checked at init time.
    154160     *     2. That the TSC is ticking (we shouldn't be here if it isn't)
     
    158164     *          c) we're not using warp drive (accelerated virtual guest time).
    159165     */
    160     if (    pVM->tm.s.fMaybeUseOffsettedHostTSC
    161         &&  RT_LIKELY(pVCpu->tm.s.fTSCTicking)
    162         &&  (   pVM->tm.s.fTSCUseRealTSC
    163              || (   !pVM->tm.s.fVirtualSyncCatchUp
    164                  && RT_LIKELY(pVM->tm.s.fVirtualSyncTicking)
    165                  && !pVM->tm.s.fVirtualWarpDrive))
    166        )
     166    if (    (*pfParavirtTsc = GIMIsParavirtTscEnabled(pVM)) == true
     167        ||  (    pVM->tm.s.fMaybeUseOffsettedHostTSC
     168             &&  RT_LIKELY(pVCpu->tm.s.fTSCTicking)
     169             &&  (   pVM->tm.s.fTSCUseRealTSC
     170                 || (   !pVM->tm.s.fVirtualSyncCatchUp
     171                     && RT_LIKELY(pVM->tm.s.fVirtualSyncTicking)
     172                     && !pVM->tm.s.fVirtualWarpDrive))))
    167173    {
    168174        if (!pVM->tm.s.fTSCUseRealTSC)
     
    233239 * @returns The number of host CPU clock ticks to the next timer deadline.
    234240 * @param   pVCpu           The current CPU.
     241 * @param   pfParavirtTsc   Where to store whether paravirt. TSC can be used or
     242 *                          not.
    235243 * @param   poffRealTSC     The offset against the TSC of the current CPU.
     244 *
    236245 * @thread  EMT(pVCpu).
    237  * @remarks Superset of TMCpuTickCanUseRealTSC.
    238  */
    239 VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, bool *pfOffsettedTsc, uint64_t *poffRealTSC)
     246 * @remarks Superset of TMCpuTickCanUseRealTSC().
     247 */
     248VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, bool *pfOffsettedTsc, bool *pfParavirtTsc,
     249                                                        uint64_t *poffRealTSC)
    240250{
    241251    PVM         pVM = pVCpu->CTX_SUFF(pVM);
     
    244254    /*
    245255     * We require:
     256     *     1. Use of a paravirtualized TSC is enabled by the guest.
     257     *     (OR)
    246258     *     1. A fixed TSC, this is checked at init time.
    247259     *     2. That the TSC is ticking (we shouldn't be here if it isn't)
     
    251263     *          c) we're not using warp drive (accelerated virtual guest time).
    252264     */
    253     if (    pVM->tm.s.fMaybeUseOffsettedHostTSC
    254         &&  RT_LIKELY(pVCpu->tm.s.fTSCTicking)
    255         &&  (   pVM->tm.s.fTSCUseRealTSC
    256              || (   !pVM->tm.s.fVirtualSyncCatchUp
    257                  && RT_LIKELY(pVM->tm.s.fVirtualSyncTicking)
    258                  && !pVM->tm.s.fVirtualWarpDrive))
    259        )
     265    if (    (*pfParavirtTsc = GIMIsParavirtTscEnabled(pVM)) == true
     266        ||  (    pVM->tm.s.fMaybeUseOffsettedHostTSC
     267             &&  RT_LIKELY(pVCpu->tm.s.fTSCTicking)
     268             &&  (   pVM->tm.s.fTSCUseRealTSC
     269                 || (   !pVM->tm.s.fVirtualSyncCatchUp
     270                     && RT_LIKELY(pVM->tm.s.fVirtualSyncTicking)
     271                     && !pVM->tm.s.fVirtualWarpDrive))))
    260272    {
    261273        *pfOffsettedTsc = true;
     
    293305        cTicksToDeadline = tmCpuCalcTicksToDeadline(TMVirtualSyncGetNsToDeadline(pVM));
    294306    }
     307
    295308    return cTicksToDeadline;
    296309}
     
    412425
    413426/**
    414  * Gets the last seen CPU timestamp counter.
    415  *
    416  * @returns last seen TSC
     427 * Gets the last seen CPU timestamp counter of the guest.
     428 *
     429 * @returns the last seen TSC.
    417430 * @param   pVCpu               Pointer to the VMCPU.
    418431 *
    419  * @thread  EMT which TSC is to be set.
     432 * @thread  EMT(pVCpu).
    420433 */
    421434VMM_INT_DECL(uint64_t) TMCpuTickGetLastSeen(PVMCPU pVCpu)
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