VirtualBox

Changeset 51643 in vbox


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

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

Location:
trunk
Files:
26 edited

Legend:

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

    r51560 r51643  
    23532353/** Unknown or invalid GIM provider. */
    23542354#define VERR_GIM_INVALID_PROVIDER                   (-6306)
     2355/** GIM generic operation failed. */
     2356#define VERR_GIM_OPERATION_FAILED                   (-6307)
     2357/** The GIM provider does not support any hypercalls. */
     2358#define VERR_GIM_HYPERCALLS_NOT_AVAILABLE           (-6308)
     2359/** The guest has not setup use of the hypercalls. */
     2360#define VERR_GIM_HYPERCALLS_NOT_ENABLED             (-6309)
     2361/** The GIM device is not registered with GIM when it ought to be. */
     2362#define VERR_GIM_DEVICE_NOT_REGISTERED              (-6310)
    23552363/** @} */
    23562364
  • trunk/include/VBox/vmm/gim.h

    r51563 r51643  
    5757    GIMPROVIDERID_KVM
    5858} GIMPROVIDERID;
    59 AssertCompileSize(GIMPROVIDERID, 4);
     59AssertCompileSize(GIMPROVIDERID, sizeof(uint32_t));
    6060
    6161
     
    7474    bool                fMapped;
    7575    /** Alignment padding. */
    76     uint8_t             au8Alignment0[4];
     76    uint8_t             au8Alignment0[3];
    7777    /** Size of the region (must be page aligned). */
    7878    uint32_t            cbRegion;
     
    9494/** Pointer to a const GIM MMIO2 region. */
    9595typedef GIMMMIO2REGION const *PCGIMMMIO2REGION;
    96 AssertCompileMemberAlignment(GIMMMIO2REGION, cbRegion,   8);
    97 AssertCompileMemberAlignment(GIMMMIO2REGION, pvPageR0,   8);
     96AssertCompileMemberAlignment(GIMMMIO2REGION, cbRegion, 8);
     97AssertCompileMemberAlignment(GIMMMIO2REGION, pvPageR0, 8);
    9898
    9999
     
    153153VMMR0_INT_DECL(int)         GIMR0InitVM(PVM pVM);
    154154VMMR0_INT_DECL(int)         GIMR0TermVM(PVM pVM);
     155VMMR0_INT_DECL(int)         GIMR0UpdateParavirtTsc(PVM pVM, uint64_t u64Offset);
    155156/** @} */
    156157#endif /* IN_RING0 */
     
    171172
    172173VMMDECL(bool)               GIMIsEnabled(PVM pVM);
    173 VMMDECL(int)                GIMUpdateParavirtTsc(PVM pVM, uint64_t u64Offset);
     174VMMDECL(GIMPROVIDERID)      GIMGetProvider(PVM pVM);
    174175VMMDECL(bool)               GIMIsParavirtTscEnabled(PVM pVM);
    175176VMM_INT_DECL(int)           GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
  • trunk/include/VBox/vmm/hm_vmx.h

    r50905 r51643  
    44
    55/*
    6  * Copyright (C) 2006-2013 Oracle Corporation
     6 * Copyright (C) 2006-2014 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    134134AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    40);
    135135AssertCompileSize(VMXRESTOREHOST, 56);
     136AssertCompileSizeAlignment(VMXRESTOREHOST, 8);
    136137
    137138/** @name Host-state MSR lazy-restoration flags.
     
    779780typedef const EPTPT *PCEPTPT;
    780781
    781 /**
    782  * VPID flush types.
     782/** @name VMX VPID flush types.
     783 *  Warning!! Valid enum members are in accordance to the VT-x spec.
     784 * @{
    783785 */
    784786typedef enum
    785787{
    786788    /** Invalidate a specific page. */
    787     VMX_FLUSH_VPID_INDIV_ADDR                    = 0,
     789    VMXFLUSHVPID_INDIV_ADDR                    = 0,
    788790    /** Invalidate one context (specific VPID). */
    789     VMX_FLUSH_VPID_SINGLE_CONTEXT                = 1,
     791    VMXFLUSHVPID_SINGLE_CONTEXT                = 1,
    790792    /** Invalidate all contexts (all VPIDs). */
    791     VMX_FLUSH_VPID_ALL_CONTEXTS                  = 2,
     793    VMXFLUSHVPID_ALL_CONTEXTS                  = 2,
    792794    /** Invalidate a single VPID context retaining global mappings. */
    793     VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS = 3,
     795    VMXFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS = 3,
    794796    /** Unsupported by VirtualBox. */
    795     VMX_FLUSH_VPID_NOT_SUPPORTED                 = 0xbad,
     797    VMXFLUSHVPID_NOT_SUPPORTED                 = 0xbad0,
    796798    /** Unsupported by CPU. */
    797     VMX_FLUSH_VPID_NONE                          = 0xb00,
    798     /** 32bit hackishness. */
    799     VMX_FLUSH_VPID_32BIT_HACK                    = 0x7fffffff
    800 } VMX_FLUSH_VPID;
    801 
    802 /**
    803  * EPT flush types.
     799    VMXFLUSHVPID_NONE                          = 0xbad1
     800} VMXFLUSHVPID;
     801AssertCompileSize(VMXFLUSHVPID, 4);
     802/** @} */
     803
     804/** @name VMX EPT flush types.
     805 *  Warning!! Valid enums values below are in accordance to the VT-x spec.
     806 * @{
    804807 */
    805808typedef enum
    806809{
    807810    /** Invalidate one context (specific EPT). */
    808     VMX_FLUSH_EPT_SINGLE_CONTEXT                = 1,
     811    VMXFLUSHEPT_SINGLE_CONTEXT                 = 1,
    809812    /* Invalidate all contexts (all EPTs) */
    810     VMX_FLUSH_EPT_ALL_CONTEXTS                  = 2,
     813    VMXFLUSHEPT_ALL_CONTEXTS                   = 2,
    811814    /** Unsupported by VirtualBox.   */
    812     VMX_FLUSH_EPT_NOT_SUPPORTED                 = 0xbad,
     815    VMXFLUSHEPT_NOT_SUPPORTED                  = 0xbad0,
    813816    /** Unsupported by CPU. */
    814     VMX_FLUSH_EPT_NONE                          = 0xb00,
    815     /** 32bit hackishness. */
    816     VMX_FLUSH_EPT_32BIT_HACK                    = 0x7fffffff
    817 } VMX_FLUSH_EPT;
    818 /** @} */
    819 
    820 /** @name MSR autoload/store elements
     817    VMXFLUSHEPT_NONE                           = 0xbad1
     818} VMXFLUSHEPT;
     819AssertCompileSize(VMXFLUSHEPT, 4);
     820/** @} */
     821
     822/** @name VMX MSR autoload/store element.
     823 *  In accordance to VT-x spec.
    821824 * @{
    822825 */
     
    824827typedef struct
    825828{
     829    /** The MSR Id. */
    826830    uint32_t    u32Msr;
     831    /** Reserved (MBZ). */
    827832    uint32_t    u32Reserved;
     833    /** The MSR value. */
    828834    uint64_t    u64Value;
    829835} VMXAUTOMSR;
     
    877883/** Pointer to a VMXMSRS struct. */
    878884typedef VMXMSRS *PVMXMSRS;
     885AssertCompileSizeAlignment(VMXMSRS, 8);
    879886/** @} */
    880887
     
    21882195 * @param   pDescriptor Descriptor
    21892196 */
    2190 DECLASM(int) VMXR0InvEPT(VMX_FLUSH_EPT enmFlush, uint64_t *pDescriptor);
     2197DECLASM(int) VMXR0InvEPT(VMXFLUSHEPT enmFlush, uint64_t *pDescriptor);
    21912198
    21922199/**
     
    21962203 * @param   pDescriptor Descriptor
    21972204 */
    2198 DECLASM(int) VMXR0InvVPID(VMX_FLUSH_VPID enmFlush, uint64_t *pDescriptor);
     2205DECLASM(int) VMXR0InvVPID(VMXFLUSHVPID enmFlush, uint64_t *pDescriptor);
    21992206
    22002207/**
  • trunk/include/VBox/vmm/tm.h

    r44528 r51643  
    133133VMMDECL(uint64_t)       TMCpuTickGet(PVMCPU pVCpu);
    134134VMM_INT_DECL(uint64_t)  TMCpuTickGetNoCheck(PVMCPU pVCpu);
    135 VMM_INT_DECL(bool)      TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC);
    136 VMM_INT_DECL(uint64_t)  TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, bool *pfOffsettedTsc, uint64_t *poffRealTSC);
     135VMM_INT_DECL(bool)      TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfParavirtTsc);
     136VMM_INT_DECL(uint64_t)  TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, bool *pfOffsettedTsc, bool *pfParavirtTsc, uint64_t *poffRealTSC);
    137137VMM_INT_DECL(int)       TMCpuTickSet(PVM pVM, PVMCPU pVCpu, uint64_t u64Tick);
    138138VMM_INT_DECL(int)       TMCpuTickSetLastSeen(PVMCPU pVCpu, uint64_t u64LastSeenTick);
  • trunk/include/VBox/vmm/vm.h

    r51560 r51643  
    149149        struct HMCPU    s;
    150150#endif
    151         uint8_t             padding[5632];      /* multiple of 64 */
     151        uint8_t             padding[5696];      /* multiple of 64 */
    152152    } hm;
    153153
     
    235235
    236236    /** Align the following members on page boundary. */
    237     uint8_t                 abAlignment2[64];
     237    //uint8_t                 abAlignment2[64];
    238238
    239239    /** PGM part. */
  • trunk/include/VBox/vmm/vm.mac

    r51560 r51643  
    135135
    136136    .cpum                   resb 3584
    137     .hm                     resb 5632
     137    .hm                     resb 5696
    138138    .em                     resb 1472
    139139    .iem                    resb 3072
  • trunk/src/VBox/Devices/GIMDev/GIMDev.cpp

    r51561 r51643  
    115115            else
    116116                pCur->pvPageRC = NIL_RTRCPTR;
     117
     118            LogRel(("GIMDev: Registered %s\n", pCur->szDescription));
    117119        }
    118120    }
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r51567 r51643  
    85178517        mHWData->mKeyboardHIDType = data.keyboardHIDType;
    85188518        mHWData->mChipsetType = data.chipsetType;
     8519        mHWData->mParavirtProvider = data.paravirtProvider;
    85198520        mHWData->mEmulatedUSBCardReaderEnabled = data.fEmulatedUSBCardReader;
    85208521        mHWData->mHPETEnabled = data.fHPETEnabled;
  • trunk/src/VBox/VMM/Makefile.kmk

    r51165 r51643  
    545545        VMMR0/CPUMR0.cpp \
    546546        VMMR0/CPUMR0A.asm \
     547        VMMR0/GIMR0.cpp \
     548        VMMR0/GIMR0Hv.cpp \
    547549        VMMR0/GMMR0.cpp \
    548550        VMMR0/GVMMR0.cpp \
  • 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)
  • trunk/src/VBox/VMM/VMMR0/GIMR0.cpp

    r51560 r51643  
    2323#include "GIMHvInternal.h"
    2424
    25 #include <iprt/err.h>
     25#include <VBox/err.h>
    2626#include <VBox/vmm/vm.h>
    2727
     
    7272}
    7373
     74/**
     75 * Updates the paravirtualized TSC supported by the GIM provider.
     76 *
     77 * @returns VBox status code.
     78 * @retval VINF_SUCCESS if the paravirt. TSC is setup and in use.
     79 * @retval VERR_GIM_NOT_ENABLED if no GIM provider is configured for this VM.
     80 * @retval VERR_GIM_PVTSC_NOT_AVAILABLE if the GIM provider does not support any
     81 *         paravirt. TSC.
     82 * @retval VERR_GIM_PVTSC_NOT_IN_USE if the GIM provider supports paravirt. TSC
     83 *         but the guest isn't currently using it.
     84 *
     85 * @param   pVM         Pointer to the VM.
     86 * @param   u64Offset   The computed TSC offset.
     87 *
     88 * @thread EMT(pVCpu)
     89 */
     90VMMR0_INT_DECL(int) GIMR0UpdateParavirtTsc(PVM pVM, uint64_t u64Offset)
     91{
     92    if (!pVM->gim.s.fEnabled)
     93        return VERR_GIM_NOT_ENABLED;
     94
     95    switch (pVM->gim.s.enmProviderId)
     96    {
     97        case GIMPROVIDERID_HYPERV:
     98            return GIMR0HvUpdateParavirtTsc(pVM, u64Offset);
     99
     100        default:
     101            break;
     102    }
     103    return VERR_GIM_PVTSC_NOT_AVAILABLE;
     104}
     105
  • trunk/src/VBox/VMM/VMMR0/GIMR0Hv.cpp

    r51560 r51643  
    2323#include "GIMHvInternal.h"
    2424
    25 #include <iprt/err.h>
    26 #include <iprt/asm.h>
    27 #include <iprt/memobj.h>
     25#include <VBox/err.h>
    2826#include <VBox/vmm/gim.h>
    2927#include <VBox/vmm/vm.h>
    3028
     29#include <iprt/spinlock.h>
    3130
     31
     32#if 0
    3233/**
    3334 * Allocates and maps one physically contiguous page. The allocated page is
     
    8081    }
    8182}
     83#endif
     84
     85/**
     86 * Updates Hyper-V's reference TSC page.
     87 *
     88 * @returns VBox status code.
     89 * @param   pVM         Pointer to the VM.
     90 * @param   u64Offset   The computed TSC offset.
     91 * @thread  EMT.
     92 */
     93VMM_INT_DECL(int) GIMR0HvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset)
     94{
     95    Assert(GIMIsEnabled(pVM));
     96    bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
     97    if (RT_UNLIKELY(!fHvTscEnabled))
     98        return VERR_GIM_PVTSC_NOT_ENABLED;
     99
     100    PCGIMHV          pcHv     = &pVM->gim.s.u.Hv;
     101    PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
     102    PGIMHVREFTSC     pRefTsc  = (PGIMHVREFTSC)pcRegion->CTX_SUFF(pvPage);
     103    Assert(pRefTsc);
     104
     105    RTSpinlockAcquire(pcHv->hSpinlockR0);
     106    pRefTsc->i64TscOffset = u64Offset;
     107    if (pRefTsc->u32TscSequence < UINT32_C(0xfffffffe))
     108        ASMAtomicIncU32(&pRefTsc->u32TscSequence);
     109    else
     110        ASMAtomicWriteU32(&pRefTsc->u32TscSequence, 1);
     111    RTSpinlockRelease(pcHv->hSpinlockR0);
     112
     113    Assert(pRefTsc->u32TscSequence != 0);
     114    Assert(pRefTsc->u32TscSequence != UINT32_C(0xffffffff));
     115    return VINF_SUCCESS;
     116}
    82117
    83118
     
    90125VMMR0_INT_DECL(int) GIMR0HvInitVM(PVM pVM)
    91126{
    92 #if 0
    93127    AssertPtr(pVM);
    94128    Assert(GIMIsEnabled(pVM));
    95129
    96130    PGIMHV pHv = &pVM->gim.s.u.Hv;
    97     Assert(pHv->hMemObjTscPage == NIL_RTR0MEMOBJ);
     131    Assert(pHv->hSpinlockR0 == NIL_RTSPINLOCK);
    98132
    99     /*
    100      * Allocate the TSC page.
    101      */
    102     int rc = gimR0HvPageAllocZ(&pHv->hMemObjTscPage, &pHv->pvTscPageR0, &pHv->HCPhysTscPage);
    103     if (RT_FAILURE(rc))
    104         goto cleanup;
    105 #endif
    106 
    107     return VINF_SUCCESS;
    108 
    109 #if 0
    110 cleanup:
    111     gimR0HvPageFree(&pHv->hMemObjTscPage, &pHv->pvTscPageR0, &pHv->HCPhysTscPage);
     133    int rc = RTSpinlockCreate(&pHv->hSpinlockR0, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "Hyper-V");
    112134    return rc;
    113 #endif
    114135}
    115136
     
    125146    AssertPtr(pVM);
    126147    Assert(GIMIsEnabled(pVM));
    127 #if 0
     148
    128149    PGIMHV pHv = &pVM->gim.s.u.Hv;
    129     gimR0HvPageFree(&pHv->hMemObjTscPage, &pHv->pvTscPageR0, &pHv->HCPhysTscPage);
    130 #endif
     150    RTSpinlockDestroy(pHv->hSpinlockR0);
     151    pHv->hSpinlockR0 = NIL_RTSPINLOCK;
     152
    131153    return VINF_SUCCESS;
    132154}
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r51421 r51643  
    3030#include <VBox/vmm/iom.h>
    3131#include <VBox/vmm/tm.h>
     32#include <VBox/vmm/gim.h>
    3233
    3334#ifdef DEBUG_ramshankar
     
    22342235static void hmR0SvmUpdateTscOffsetting(PVMCPU pVCpu)
    22352236{
     2237    bool     fParavirtTsc = false;
    22362238    PSVMVMCB pVmcb = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb;
    2237     if (TMCpuTickCanUseRealTSC(pVCpu, &pVmcb->ctrl.u64TSCOffset))
    2238     {
    2239         uint64_t u64CurTSC = ASMReadTSC();
    2240         if (u64CurTSC + pVmcb->ctrl.u64TSCOffset > TMCpuTickGetLastSeen(pVCpu))
     2239    if (TMCpuTickCanUseRealTSC(pVCpu, &pVmcb->ctrl.u64TSCOffset, &fParavirtTsc))
     2240    {
     2241        uint64_t u64CurTSC   = ASMReadTSC();
     2242        uint64_t u64LastTick = TMCpuTickGetLastSeen(pVCpu);
     2243        if (fParavirtTsc)
     2244        {
     2245            if (u64CurTSC + pVmcb->ctrl.u64TSCOffset > u64LastTick)
     2246            {
     2247                pVmcb->ctrl.u64TSCOffset = u64LastTick - u64CurTSC;
     2248                STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffsetAdjusted);
     2249            }
     2250            int rc = GIMR0UpdateParavirtTsc(pVCpu->CTX_SUFF(pVM), pVmcb->ctrl.u64TSCOffset);
     2251            AssertRC(rc);
     2252            STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
     2253        }
     2254
     2255        if (u64CurTSC + pVmcb->ctrl.u64TSCOffset >= TMCpuTickGetLastSeen(pVCpu))
    22412256        {
    22422257            pVmcb->ctrl.u32InterceptCtrl1 &= ~SVM_CTRL1_INTERCEPT_RDTSC;
     
    22532268    else
    22542269    {
     2270        Assert(!fParavirtTsc);
    22552271        pVmcb->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_RDTSC;
    22562272        pVmcb->ctrl.u32InterceptCtrl2 |= SVM_CTRL2_INTERCEPT_RDTSCP;
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r51244 r51643  
    3434#include <VBox/vmm/selm.h>
    3535#include <VBox/vmm/tm.h>
     36#include <VBox/vmm/gim.h>
    3637#ifdef VBOX_WITH_REM
    3738# include <VBox/vmm/rem.h>
     
    336337*   Internal Functions                                                         *
    337338*******************************************************************************/
    338 static void               hmR0VmxFlushEpt(PVMCPU pVCpu, VMX_FLUSH_EPT enmFlush);
    339 static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr);
     339static void               hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush);
     340static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr);
    340341static int                hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntInfo, uint32_t cbInstr,
    341342                                                 uint32_t u32ErrCode, RTGCUINTREG GCPtrFaultAddress, uint32_t *puIntState);
     
    10671068    if (pMsrs->u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
    10681069    {
    1069         hmR0VmxFlushEpt(NULL /* pVCpu */, VMX_FLUSH_EPT_ALL_CONTEXTS);
     1070        hmR0VmxFlushEpt(NULL /* pVCpu */, VMXFLUSHEPT_ALL_CONTEXTS);
    10701071        pCpu->fFlushAsidBeforeUse = false;
    10711072    }
     
    16981699 * @remarks Can be called with interrupts disabled.
    16991700 */
    1700 static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMX_FLUSH_EPT enmFlush)
     1701static void hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush)
    17011702{
    17021703    uint64_t au64Descriptor[2];
    1703     if (enmFlush == VMX_FLUSH_EPT_ALL_CONTEXTS)
     1704    if (enmFlush == VMXFLUSHEPT_ALL_CONTEXTS)
    17041705        au64Descriptor[0] = 0;
    17051706    else
     
    17341735 * @remarks Can be called with interrupts disabled.
    17351736 */
    1736 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr)
     1737static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr)
    17371738{
    17381739    NOREF(pVM);
     
    17411742
    17421743    uint64_t au64Descriptor[2];
    1743     if (enmFlush == VMX_FLUSH_VPID_ALL_CONTEXTS)
     1744    if (enmFlush == VMXFLUSHVPID_ALL_CONTEXTS)
    17441745    {
    17451746        au64Descriptor[0] = 0;
     
    17951796            if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
    17961797            {
    1797                 hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_INDIV_ADDR, GCVirt);
     1798                hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, GCVirt);
    17981799                STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
    17991800            }
     
    19611962        {
    19621963            for (uint32_t i = 0; i < pVCpu->hm.s.TlbShootdown.cPages; i++)
    1963                 hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]);
     1964                hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]);
    19641965        }
    19651966        else
     
    21202121        if (pCpu->fFlushAsidBeforeUse)
    21212122        {
    2122             if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_SINGLE_CONTEXT)
    2123                 hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_SINGLE_CONTEXT, 0 /* GCPtr */);
    2124             else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_ALL_CONTEXTS)
     2123            if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_SINGLE_CONTEXT)
     2124                hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
     2125            else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_ALL_CONTEXTS)
    21252126            {
    2126                 hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_ALL_CONTEXTS, 0 /* GCPtr */);
     2127                hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
    21272128                pCpu->fFlushAsidBeforeUse = false;
    21282129            }
     
    21512152            {
    21522153                for (uint32_t i = 0; i < pVCpu->hm.s.TlbShootdown.cPages; i++)
    2153                     hmR0VmxFlushVpid(pVM, pVCpu, VMX_FLUSH_VPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]);
     2154                    hmR0VmxFlushVpid(pVM, pVCpu, VMXFLUSHVPID_INDIV_ADDR, pVCpu->hm.s.TlbShootdown.aPages[i]);
    21542155            }
    21552156            else
     
    22262227        {
    22272228            if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
    2228                 pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_SINGLE_CONTEXT;
     2229                pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_SINGLE_CONTEXT;
    22292230            else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
    2230                 pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_ALL_CONTEXTS;
     2231                pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_ALL_CONTEXTS;
    22312232            else
    22322233            {
    22332234                /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
    2234                 pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_NOT_SUPPORTED;
     2235                pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NOT_SUPPORTED;
    22352236                return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
    22362237            }
     
    22402241            {
    22412242                LogRel(("hmR0VmxSetupTaggedTlb: Unsupported EPTP memory type %#x.\n", pVM->hm.s.vmx.Msrs.u64EptVpidCaps));
    2242                 pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_NOT_SUPPORTED;
     2243                pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NOT_SUPPORTED;
    22432244                return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
    22442245            }
     
    22472248        {
    22482249            /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
    2249             pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_NOT_SUPPORTED;
     2250            pVM->hm.s.vmx.enmFlushEpt = VMXFLUSHEPT_NOT_SUPPORTED;
    22502251            return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
    22512252        }
     
    22602261        {
    22612262            if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
    2262                 pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_SINGLE_CONTEXT;
     2263                pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_SINGLE_CONTEXT;
    22632264            else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
    2264                 pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_ALL_CONTEXTS;
     2265                pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_ALL_CONTEXTS;
    22652266            else
    22662267            {
     
    22702271                if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
    22712272                    LogRel(("hmR0VmxSetupTaggedTlb: Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
    2272                 pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_NOT_SUPPORTED;
     2273                pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_NOT_SUPPORTED;
    22732274                pVM->hm.s.vmx.fVpid = false;
    22742275            }
     
    22782279            /*  Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
    22792280            Log4(("hmR0VmxSetupTaggedTlb: VPID supported without INVEPT support. Ignoring VPID.\n"));
    2280             pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_NOT_SUPPORTED;
     2281            pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_NOT_SUPPORTED;
    22812282            pVM->hm.s.vmx.fVpid = false;
    22822283        }
     
    27282729
    27292730    /* Initialize these always, see hmR3InitFinalizeR0().*/
    2730     pVM->hm.s.vmx.enmFlushEpt  = VMX_FLUSH_EPT_NONE;
    2731     pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_NONE;
     2731    pVM->hm.s.vmx.enmFlushEpt  = VMXFLUSHEPT_NONE;
     2732    pVM->hm.s.vmx.enmFlushVpid = VMXFLUSHVPID_NONE;
    27322733
    27332734    /* Setup the tagged-TLB flush handlers. */
     
    55655566    int  rc            = VERR_INTERNAL_ERROR_5;
    55665567    bool fOffsettedTsc = false;
     5568    bool fParavirtTsc  = false;
    55675569    PVM pVM            = pVCpu->CTX_SUFF(pVM);
    55685570    if (pVM->hm.s.vmx.fUsePreemptTimer)
    55695571    {
    5570         uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &pVCpu->hm.s.vmx.u64TSCOffset);
     5572        uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &fParavirtTsc,
     5573                                                                     &pVCpu->hm.s.vmx.u64TSCOffset);
    55715574
    55725575        /* Make sure the returned values have sane upper and lower boundaries. */
     
    55805583    }
    55815584    else
    5582         fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset);
     5585        fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset, &fParavirtTsc);
     5586
     5587    if (fParavirtTsc)
     5588    {
     5589        uint64_t const u64CurTsc   = ASMReadTSC();
     5590        uint64_t const u64LastTick = TMCpuTickGetLastSeen(pVCpu);
     5591        if (u64CurTsc + pVCpu->hm.s.vmx.u64TSCOffset < u64LastTick)
     5592        {
     5593            pVCpu->hm.s.vmx.u64TSCOffset = (u64LastTick - u64CurTsc);
     5594            STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffsetAdjusted);
     5595        }
     5596
     5597        Assert(u64CurTsc + pVCpu->hm.s.vmx.u64TSCOffset >= u64LastTick);
     5598        rc = GIMR0UpdateParavirtTsc(pVM, pVCpu->hm.s.vmx.u64TSCOffset);
     5599        if (RT_SUCCESS(rc))
     5600        {
     5601            /* Note: VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT takes precedence over TSC_OFFSET, applies to RDTSCP too. */
     5602            rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, 0);                                  AssertRC(rc);
     5603
     5604            pVCpu->hm.s.vmx.u32ProcCtls &= ~VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT;
     5605            rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVCpu->hm.s.vmx.u32ProcCtls);              AssertRC(rc);
     5606            STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
     5607            return;
     5608        }
     5609        /* else: Shouldn't really fail. If it does, fallback to offsetted TSC mode. */
     5610    }
    55835611
    55845612    if (fOffsettedTsc)
     
    1035810386              ("hmR0VmxExitRdmsr: failed, invalid error code %Rrc\n", rc));
    1035910387    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
    10360 
    1036110388    if (RT_LIKELY(rc == VINF_SUCCESS))
    1036210389    {
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r49481 r51643  
    3636#include <VBox/vmm/gvmm.h>
    3737#include <VBox/vmm/gmm.h>
     38#include <VBox/vmm/gim.h>
    3839#include <VBox/intnet.h>
    3940#include <VBox/vmm/hm.h>
     
    379380                    if (RT_SUCCESS(rc))
    380381                    {
    381                         GVMMR0DoneInitVM(pVM);
    382                         return rc;
     382                        rc = GIMR0InitVM(pVM);
     383                        if (RT_SUCCESS(rc))
     384                        {
     385                            GVMMR0DoneInitVM(pVM);
     386                            return rc;
     387                        }
     388
     389                        /* bail out*/
     390#ifdef VBOX_WITH_PCI_PASSTHROUGH
     391                        PciRawR0TermVM(pVM);
     392#endif
    383393                    }
    384394                }
    385 
    386                 /* bail out */
    387395            }
    388 #ifdef VBOX_WITH_PCI_PASSTHROUGH
    389             PciRawR0TermVM(pVM);
    390 #endif
    391396            HMR0TermVM(pVM);
    392397        }
     
    423428    if (GVMMR0DoingTermVM(pVM, pGVM))
    424429    {
     430        GIMR0TermVM(pVM);
     431
    425432        /** @todo I wish to call PGMR0PhysFlushHandyPages(pVM, &pVM->aCpus[idCpu])
    426433         *        here to make sure we don't leak any shared pages if we crash... */
  • trunk/src/VBox/VMM/VMMR3/GIM.cpp

    r51560 r51643  
    9090     */
    9191    int rc;
    92 #if 0
    93     rc = SSMR3RegisterInternal(pVM, "GIM", 0, GIM_SSM_VERSION, sizeof(GIM),
    94                                     NULL, NULL, NULL,
    95                                     NULL, gimR3Save, NULL,
    96                                     NULL, gimR3Load, NULL);
     92    rc = SSMR3RegisterInternal(pVM, "GIM", 0 /* uInstance */, GIM_SSM_VERSION, sizeof(GIM),
     93                                    NULL /* pfnLivePrep */, NULL /* pfnLiveExec */, NULL /* pfnLiveVote*/,
     94                                    NULL /* pfnSavePrep */, gimR3Save,              NULL /* pfnSaveDone */,
     95                                    NULL /* pfnLoadPrep */, gimR3Load,              NULL /* pfnLoadDone */);
    9796    if (RT_FAILURE(rc))
    9897        return rc;
    99 #endif
    10098
    10199    /*
     
    226224
    227225/**
    228  * Execute state save operation.
     226 * Executes state-save operation.
    229227 *
    230228 * @returns VBox status code.
     
    234232DECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM)
    235233{
    236     /** @todo save state. */
    237     return VINF_SUCCESS;
     234    AssertReturn(pVM,  VERR_INVALID_PARAMETER);
     235    AssertReturn(pSSM, VERR_SSM_INVALID_STATE);
     236
     237    /** @todo Save per-CPU data. */
     238    int rc;
     239#if 0
     240    for (VMCPUID i = 0; i < pVM->cCpus; i++)
     241    {
     242        rc = SSMR3PutXYZ(pSSM, pVM->aCpus[i].gim.s.XYZ);
     243    }
     244#endif
     245
     246    /*
     247     * Save per-VM data.
     248     */
     249    rc = SSMR3PutBool(pSSM, pVM->gim.s.fEnabled);
     250    AssertRCReturn(rc, rc);
     251    rc = SSMR3PutU32(pSSM, pVM->gim.s.enmProviderId);
     252    AssertRCReturn(rc, rc);
     253    rc = SSMR3PutU32(pSSM, pVM->gim.s.u32Version);
     254    AssertRCReturn(rc, rc);
     255
     256    /*
     257     * Save provider-specific data.
     258     */
     259    if (pVM->gim.s.fEnabled)
     260    {
     261        switch (pVM->gim.s.enmProviderId)
     262        {
     263            case GIMPROVIDERID_HYPERV:
     264                rc = GIMR3HvSave(pVM, pSSM);
     265                AssertRCReturn(rc, rc);
     266                break;
     267
     268            default:
     269                break;
     270        }
     271    }
     272
     273    return rc;
    238274}
    239275
     
    250286DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    251287{
    252     /** @todo load state. */
    253     return VINF_SUCCESS;
     288    if (uPass != SSM_PASS_FINAL)
     289        return VINF_SUCCESS;
     290
     291    /** @todo Load per-CPU data. */
     292    int rc;
     293#if 0
     294    for (VMCPUID i = 0; i < pVM->cCpus; i++)
     295    {
     296        rc = SSMR3PutXYZ(pSSM, pVM->aCpus[i].gim.s.XYZ);
     297    }
     298#endif
     299
     300    /*
     301     * Load per-VM data.
     302     */
     303    rc = SSMR3GetBool(pSSM, &pVM->gim.s.fEnabled);
     304    AssertRCReturn(rc, rc);
     305    rc = SSMR3GetU32(pSSM, (uint32_t *)&pVM->gim.s.enmProviderId);
     306    AssertRCReturn(rc, rc);
     307    rc = SSMR3GetU32(pSSM, &pVM->gim.s.u32Version);
     308    AssertRCReturn(rc, rc);
     309
     310    /*
     311     * Load provider-specific data.
     312     */
     313    if (pVM->gim.s.fEnabled)
     314    {
     315        switch (pVM->gim.s.enmProviderId)
     316        {
     317            case GIMPROVIDERID_HYPERV:
     318                rc = GIMR3HvLoad(pVM, pSSM, uVersion);
     319                AssertRCReturn(rc, rc);
     320                break;
     321
     322            default:
     323                break;
     324        }
     325    }
     326
     327    return rc;
    254328}
    255329
     
    266340VMMR3_INT_DECL(int) GIMR3Term(PVM pVM)
    267341{
     342    if (!pVM->gim.s.fEnabled)
     343        return VINF_SUCCESS;
     344
     345    switch (pVM->gim.s.enmProviderId)
     346    {
     347        case GIMPROVIDERID_HYPERV:
     348            return GIMR3HvTerm(pVM);
     349
     350        default:
     351            break;
     352    }
    268353    return VINF_SUCCESS;
    269354}
     
    350435 * @param   pRegion     Pointer to the GIM MMIO2 region.
    351436 */
    352 VMM_INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion)
     437VMMR3_INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion)
    353438{
    354439    AssertPtr(pVM);
     
    359444    if (pRegion->fMapped)
    360445    {
    361         PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage);
    362         int rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage);
     446        int rc = PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage);
     447        AssertRC(rc);
     448
     449        rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage);
    363450        if (RT_SUCCESS(rc))
    364451        {
     
    372459
    373460/**
    374  * Write access handler for a mapped MMIO2 region that presently ignores writes.
     461 * Write access handler for a mapped MMIO2 region. At present, this handler
     462 * simply ignores writes.
     463 *
     464 * In the future we might want to let the GIM provider decide what the handler
     465 * should do (like throwing #GP faults).
    375466 *
    376467 * @returns VBox status code.
     
    383474 * @param pvUser            User argument (NULL, not used).
    384475 */
    385 static DECLCALLBACK(int) gimR3Mmio2PageWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
    386                                                     PGMACCESSTYPE enmAccessType, void *pvUser)
     476static DECLCALLBACK(int) gimR3Mmio2WriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
     477                                                PGMACCESSTYPE enmAccessType, void *pvUser)
    387478{
    388479    /*
     
    402493 * @param   pRegion         Pointer to the GIM MMIO2 region.
    403494 * @param   GCPhysRegion    Where in the guest address space to map the region.
    404  * @param   pszDesc         Description of the region being mapped.
    405  */
    406 VMM_INT_DECL(int) GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion, const char *pszDesc)
     495 */
     496VMMR3_INT_DECL(int) GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion)
    407497{
    408498    PPDMDEVINS pDevIns = pVM->gim.s.pDevInsR3;
     
    412502    if (GCPhysRegion & PAGE_OFFSET_MASK)
    413503    {
    414         LogFunc(("%s: %#RGp not paging aligned\n", pszDesc, GCPhysRegion));
     504        LogFunc(("%s: %#RGp not paging aligned\n", pRegion->szDescription, GCPhysRegion));
    415505        return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
    416506    }
     
    421511    if (!PGMPhysIsGCPhysNormal(pVM, GCPhysRegion))
    422512    {
    423         LogFunc(("%s: %#RGp is not normal memory\n", pszDesc, GCPhysRegion));
     513        LogFunc(("%s: %#RGp is not normal memory\n", pRegion->szDescription, GCPhysRegion));
    424514        return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
    425515    }
    426516
    427     if (pRegion->fMapped)
    428     {
    429         LogFunc(("%s: A mapping for %#RGp already exists.\n", pszDesc, GCPhysRegion));
    430         return VERR_PGM_MAPPING_CONFLICT;
    431     }
    432 
    433     /*
    434      * Map the MMIO2 region over the guest-physical address.
     517    if (!pRegion->fRegistered)
     518    {
     519        LogFunc(("%s: Region has not been registered.\n"));
     520        return VERR_GIM_IPE_1;
     521    }
     522
     523    /*
     524     * Map the MMIO2 region over the specified guest-physical address.
    435525     */
    436526    int rc = PDMDevHlpMMIO2Map(pDevIns, pRegion->iRegion, GCPhysRegion);
     
    443533                                          PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
    444534                                          GCPhysRegion, GCPhysRegion + (pRegion->cbRegion - 1),
    445                                           gimR3Mmio2PageWriteHandler,  NULL /* pvUserR3 */,
     535                                          gimR3Mmio2WriteHandler,  NULL /* pvUserR3 */,
    446536                                          NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */,
    447537                                          NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */,
    448                                           pszDesc);
     538                                          pRegion->szDescription);
    449539        if (RT_SUCCESS(rc))
    450540        {
    451541            pRegion->fMapped    = true;
    452542            pRegion->GCPhysPage = GCPhysRegion;
    453             return VINF_SUCCESS;
     543            return rc;
    454544        }
    455545
     
    460550}
    461551
     552#if 0
     553/**
     554 * Registers the physical handler for the registered and mapped MMIO2 region.
     555 *
     556 * @returns VBox status code.
     557 * @param   pVM         Pointer to the VM.
     558 * @param   pRegion     Pointer to the GIM MMIO2 region.
     559 */
     560VMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalRegister(PVM pVM, PGIMMMIO2REGION pRegion)
     561{
     562    AssertPtr(pRegion);
     563    AssertReturn(pRegion->fRegistered, VERR_GIM_IPE_2);
     564    AssertReturn(pRegion->fMapped, VERR_GIM_IPE_3);
     565
     566    return PGMR3HandlerPhysicalRegister(pVM,
     567                                        PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
     568                                        pRegion->GCPhysPage, pRegion->GCPhysPage + (pRegion->cbRegion - 1),
     569                                        gimR3Mmio2WriteHandler,  NULL /* pvUserR3 */,
     570                                        NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */,
     571                                        NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */,
     572                                        pRegion->szDescription);
     573}
     574
     575
     576/**
     577 * Deregisters the physical handler for the MMIO2 region.
     578 *
     579 * @returns VBox status code.
     580 * @param   pVM         Pointer to the VM.
     581 * @param   pRegion     Pointer to the GIM MMIO2 region.
     582 */
     583VMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalDeregister(PVM pVM, PGIMMMIO2REGION pRegion)
     584{
     585    return PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage);
     586}
     587#endif
     588
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r51560 r51643  
    2626#include <iprt/string.h>
    2727#include <iprt/mem.h>
     28#include <iprt/spinlock.h>
    2829
    2930#include <VBox/vmm/cpum.h>
     31#include <VBox/vmm/ssm.h>
    3032#include <VBox/vmm/vm.h>
    3133#include <VBox/vmm/hm.h>
     
    111113    PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
    112114    pRegion->iRegion    = GIM_HV_HYPERCALL_PAGE_REGION_IDX;
     115    pRegion->fRCMapping = false;
    113116    pRegion->cbRegion   = PAGE_SIZE;
    114117    pRegion->GCPhysPage = NIL_RTGCPHYS;
    115     RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hypercall Page");
    116     Assert(!pRegion->fRCMapping);
    117     Assert(!pRegion->fMapped);
     118    RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hyper-V hypercall page");
    118119
    119120    pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
    120121    pRegion->iRegion    = GIM_HV_REF_TSC_PAGE_REGION_IDX;
     122    pRegion->fRCMapping = false;
    121123    pRegion->cbRegion   = PAGE_SIZE;
    122124    pRegion->GCPhysPage = NIL_RTGCPHYS;
    123     RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "TSC Page");
     125    RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hyper-V TSC page");
    124126
    125127    /*
     
    219221
    220222
     223VMMR3_INT_DECL(int) GIMR3HvTerm(PVM pVM)
     224{
     225    GIMR3HvReset(pVM);
     226    return VINF_SUCCESS;
     227}
     228
     229
    221230VMMR3_INT_DECL(void) GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta)
    222231{
     
    239248     * Unmap MMIO2 pages that the guest may have setup.
    240249     */
     250    LogRelFunc(("Resetting Hyper-V MMIO2 regions and MSRs...\n"));
    241251    PGIMHV pHv = &pVM->gim.s.u.Hv;
    242252    for (unsigned i = 0; i < RT_ELEMENTS(pHv->aMmio2Regions); i++)
     
    272282}
    273283
     284
     285/**
     286 * Hyper-V state-save operation.
     287 *
     288 * @returns VBox status code.
     289 * @param   pVM     Pointer to the VM.
     290 * @param   pSSM    Pointer to the SSM handle.
     291 */
     292VMMR3_INT_DECL(int) GIMR3HvSave(PVM pVM, PSSMHANDLE pSSM)
     293{
     294    PCGIMHV pcHv = &pVM->gim.s.u.Hv;
     295
     296    /** @todo Save per-VCPU data. */
     297
     298    /*
     299     * Save per-VM MSRs.
     300     */
     301    int rc = SSMR3PutU64(pSSM, pcHv->u64GuestOsIdMsr);          AssertRCReturn(rc, rc);
     302    rc = SSMR3PutU64(pSSM, pcHv->u64HypercallMsr);              AssertRCReturn(rc, rc);
     303    rc = SSMR3PutU64(pSSM, pcHv->u64TscPageMsr);                AssertRCReturn(rc, rc);
     304
     305    /*
     306     * Save Hyper-V features / capabilities.
     307     */
     308    rc = SSMR3PutU32(pSSM, pcHv->uBaseFeat);                    AssertRCReturn(rc, rc);
     309    rc = SSMR3PutU32(pSSM, pcHv->uPartFlags);                   AssertRCReturn(rc, rc);
     310    rc = SSMR3PutU32(pSSM, pcHv->uPowMgmtFeat);                 AssertRCReturn(rc, rc);
     311    rc = SSMR3PutU32(pSSM, pcHv->uMiscFeat);                    AssertRCReturn(rc, rc);
     312    rc = SSMR3PutU32(pSSM, pcHv->uHyperHints);                  AssertRCReturn(rc, rc);
     313
     314    /*
     315     * Save per-VM MMIO2 regions.
     316     */
     317    rc = SSMR3PutU32(pSSM, RT_ELEMENTS(pcHv->aMmio2Regions));
     318    for (unsigned i = 0; i < RT_ELEMENTS(pcHv->aMmio2Regions); i++)
     319    {
     320        /* Save the fields necessary to remap the regions upon load.*/
     321        PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[i];
     322        rc = SSMR3PutU8(pSSM,     pcRegion->iRegion);           AssertRCReturn(rc, rc);
     323        rc = SSMR3PutBool(pSSM,   pcRegion->fRCMapping);        AssertRCReturn(rc, rc);
     324        rc = SSMR3PutU32(pSSM,    pcRegion->cbRegion);          AssertRCReturn(rc, rc);
     325        rc = SSMR3PutGCPhys(pSSM, pcRegion->GCPhysPage);        AssertRCReturn(rc, rc);
     326        rc = SSMR3PutStrZ(pSSM,   pcRegion->szDescription);     AssertRCReturn(rc, rc);
     327    }
     328
     329    return VINF_SUCCESS;
     330}
     331
     332
     333/**
     334 * Hyper-V state-load operation, final pass.
     335 *
     336 * @returns VBox status code.
     337 * @param   pVM             Pointer to the VM.
     338 * @param   pSSM            Pointer to the SSM handle.
     339 * @param   uSSMVersion     The saved-state version.
     340 */
     341VMMR3_INT_DECL(int) GIMR3HvLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion)
     342{
     343    PGIMHV pHv = &pVM->gim.s.u.Hv;
     344
     345    /** @todo Load per-VCPU data. */
     346
     347    /*
     348     * Load per-VM MSRs.
     349     */
     350    int rc = SSMR3GetU64(pSSM, &pHv->u64GuestOsIdMsr);          AssertRCReturn(rc, rc);
     351    rc = SSMR3GetU64(pSSM, &pHv->u64HypercallMsr);              AssertRCReturn(rc, rc);
     352    rc = SSMR3GetU64(pSSM, &pHv->u64TscPageMsr);                AssertRCReturn(rc, rc);
     353
     354    /*
     355     * Save Hyper-V features / capabilities.
     356     */
     357    rc = SSMR3GetU32(pSSM, &pHv->uBaseFeat);                    AssertRCReturn(rc, rc);
     358    rc = SSMR3GetU32(pSSM, &pHv->uPartFlags);                   AssertRCReturn(rc, rc);
     359    rc = SSMR3GetU32(pSSM, &pHv->uPowMgmtFeat);                 AssertRCReturn(rc, rc);
     360    rc = SSMR3GetU32(pSSM, &pHv->uMiscFeat);                    AssertRCReturn(rc, rc);
     361    rc = SSMR3GetU32(pSSM, &pHv->uHyperHints);                  AssertRCReturn(rc, rc);
     362
     363    /*
     364     * Load per-VM MMIO2 regions.
     365     */
     366    uint32_t cRegions;
     367    rc = SSMR3GetU32(pSSM, &cRegions);
     368    if (cRegions != RT_ELEMENTS(pHv->aMmio2Regions))
     369    {
     370        LogRelFunc(("MMIO2 region array size mismatch. size=%u expected=%u\n", cRegions, RT_ELEMENTS(pHv->aMmio2Regions)));
     371        return VERR_SSM_FIELD_INVALID_VALUE;
     372    }
     373
     374    for (unsigned i = 0; i < RT_ELEMENTS(pHv->aMmio2Regions); i++)
     375    {
     376        /* The regions would have been registered while constructing the GIM device. */
     377        PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[i];
     378        rc = SSMR3GetU8(pSSM,     &pRegion->iRegion);           AssertRCReturn(rc, rc);
     379        rc = SSMR3GetBool(pSSM,   &pRegion->fRCMapping);        AssertRCReturn(rc, rc);
     380        rc = SSMR3GetU32(pSSM,    &pRegion->cbRegion);          AssertRCReturn(rc, rc);
     381        rc = SSMR3GetGCPhys(pSSM, &pRegion->GCPhysPage);        AssertRCReturn(rc, rc);
     382        rc = SSMR3GetStrZ(pSSM,    pRegion->szDescription, sizeof(pRegion->szDescription));
     383        AssertRCReturn(rc, rc);
     384    }
     385
     386    /*
     387     * Enable the Hypercall-page.
     388     */
     389    PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
     390    if (MSR_GIM_HV_HYPERCALL_IS_ENABLED(pHv->u64HypercallMsr))
     391    {
     392        Assert(pRegion->GCPhysPage != NIL_RTGCPHYS);
     393        if (pRegion->fRegistered)
     394        {
     395            rc = GIMR3HvEnableHypercallPage(pVM, pRegion->GCPhysPage);
     396            if (RT_FAILURE(rc))
     397                return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to enable the hypercall page. GCPhys=%#RGp rc=%Rrc"),
     398                                        pRegion->GCPhysPage, rc);
     399        }
     400        else
     401            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Hypercall MMIO2 region not registered. Missing GIM device?!"));
     402    }
     403
     404    /*
     405     * Enable the TSC-page.
     406     */
     407    pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
     408    if (MSR_GIM_HV_REF_TSC_IS_ENABLED(pHv->u64TscPageMsr))
     409    {
     410        Assert(pRegion->GCPhysPage != NIL_RTGCPHYS);
     411        if (pRegion->fRegistered)
     412        {
     413            rc = GIMR3HvEnableTscPage(pVM, pRegion->GCPhysPage);
     414            if (RT_FAILURE(rc))
     415                return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to enable the TSC page. GCPhys=%#RGp rc=%Rrc"),
     416                                        pRegion->GCPhysPage, rc);
     417        }
     418        else
     419            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("TSC-page MMIO2 region not registered. Missing GIM device?!"));
     420    }
     421
     422    return rc;
     423}
     424
     425
     426/**
     427 * Enables the Hyper-V TSC page.
     428 *
     429 * @returns VBox status code.
     430 * @param   pVM             Pointer to the VM.
     431 * @param   GCPhysTscPage   Where to map the TSC page.
     432 */
     433VMMR3_INT_DECL(int) GIMR3HvEnableTscPage(PVM pVM, RTGCPHYS GCPhysTscPage)
     434{
     435    PPDMDEVINSR3    pDevIns = pVM->gim.s.pDevInsR3;
     436    PGIMMMIO2REGION pRegion = &pVM->gim.s.u.Hv.aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
     437    AssertPtrReturn(pDevIns, VERR_GIM_DEVICE_NOT_REGISTERED);
     438
     439    int rc;
     440    if (pRegion->fMapped)
     441    {
     442        /*
     443         * Is it already enabled at the given guest-address?
     444         */
     445        if (pRegion->GCPhysPage == GCPhysTscPage)
     446            return VINF_SUCCESS;
     447
     448        /*
     449         * If it's mapped at a different address, unmap the previous address.
     450         */
     451        rc = GIMR3HvDisableTscPage(pVM);
     452        AssertRC(rc);
     453    }
     454
     455    /*
     456     * Map the TSC-page at the specified address.
     457     */
     458    Assert(!pRegion->fMapped);
     459    rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysTscPage);
     460    if (RT_SUCCESS(rc))
     461    {
     462        Assert(pRegion->GCPhysPage == GCPhysTscPage);
     463
     464        /*
     465         * Update the TSC scale. Windows guests expect a non-zero TSC sequence, otherwise
     466         * they fallback to using the reference count MSR which is not ideal in terms of VM-exits.
     467         *
     468         * Also, Hyper-V normalizes the time in 10 MHz, see:
     469         * http://technet.microsoft.com/it-it/sysinternals/dn553408%28v=vs.110%29
     470         */
     471        PGIMHVREFTSC pRefTsc = (PGIMHVREFTSC)pRegion->pvPageR3;
     472        Assert(pRefTsc);
     473
     474        uint64_t const u64TscKHz = TMCpuTicksPerSecond(pVM) / UINT64_C(1000);
     475        pRefTsc->u32TscSequence  = 1;
     476        //pRefTsc->u64TscScale     = ((UINT64_C(10000) << 32) / u64TscKHz) << 32;
     477        pRefTsc->u64TscScale     = 0xf4000000000000;
     478
     479        LogRel(("GIM: HyperV: Enabled TSC page at %#RGp (u64TscScale=%#RX64 u64TscKHz=%#RX64)\n", GCPhysTscPage,
     480                pRefTsc->u64TscScale, u64TscKHz));
     481        return VINF_SUCCESS;
     482    }
     483    else
     484        LogRelFunc(("GIMR3Mmio2Map failed. rc=%Rrc\n", rc));
     485
     486    return VERR_GIM_OPERATION_FAILED;
     487}
     488
     489
     490/**
     491 * Disables the Hyper-V TSC page.
     492 *
     493 * @returns VBox status code.
     494 * @param   pVM     Pointer to the VM.
     495 */
     496VMMR3_INT_DECL(int) GIMR3HvDisableTscPage(PVM pVM)
     497{
     498    PGIMHV pHv = &pVM->gim.s.u.Hv;
     499    PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
     500    if (pRegion->fMapped)
     501    {
     502        GIMR3Mmio2Unmap(pVM, pRegion);
     503        Assert(!pRegion->fMapped);
     504        LogRel(("GIM: HyperV: Disabled TSC-page\n"));
     505        return VINF_SUCCESS;
     506    }
     507    return VERR_GIM_PVTSC_NOT_ENABLED;
     508}
     509
     510
     511/**
     512 * Disables the Hyper-V Hypercall page.
     513 *
     514 * @returns VBox status code.
     515 */
     516VMMR3_INT_DECL(int) GIMR3HvDisableHypercallPage(PVM pVM)
     517{
     518    PGIMHV pHv = &pVM->gim.s.u.Hv;
     519    PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
     520    if (pRegion->fMapped)
     521    {
     522        GIMR3Mmio2Unmap(pVM, pRegion);
     523        Assert(!pRegion->fMapped);
     524        LogRel(("GIM: HyperV: Disabled Hypercall-page\n"));
     525        return VINF_SUCCESS;
     526    }
     527    return VERR_GIM_HYPERCALLS_NOT_ENABLED;
     528}
     529
     530
     531/**
     532 * Enables the Hyper-V Hypercall page.
     533 *
     534 * @returns VBox status code.
     535 * @param   pVM                     Pointer to the VM.
     536 * @param   GCPhysHypercallPage     Where to map the hypercall page.
     537 */
     538VMMR3_INT_DECL(int) GIMR3HvEnableHypercallPage(PVM pVM, RTGCPHYS GCPhysHypercallPage)
     539{
     540    PPDMDEVINSR3    pDevIns = pVM->gim.s.pDevInsR3;
     541    PGIMMMIO2REGION pRegion = &pVM->gim.s.u.Hv.aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
     542    AssertPtrReturn(pDevIns, VERR_GIM_DEVICE_NOT_REGISTERED);
     543
     544    if (pRegion->fMapped)
     545    {
     546        /*
     547         * Is it already enabled at the given guest-address?
     548         */
     549        if (pRegion->GCPhysPage == GCPhysHypercallPage)
     550            return VINF_SUCCESS;
     551
     552        /*
     553         * If it's mapped at a different address, unmap the previous address.
     554         */
     555        int rc2 = GIMR3HvDisableHypercallPage(pVM);
     556        AssertRC(rc2);
     557    }
     558
     559    /*
     560     * Map the hypercall-page at the specified address.
     561     */
     562    Assert(!pRegion->fMapped);
     563    int rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysHypercallPage);
     564    if (RT_SUCCESS(rc))
     565    {
     566        Assert(pRegion->GCPhysPage == GCPhysHypercallPage);
     567
     568        /*
     569         * Patch the hypercall-page.
     570         */
     571        if (HMIsEnabled(pVM))
     572        {
     573            size_t cbWritten = 0;
     574            rc = HMPatchHypercall(pVM, pRegion->pvPageR3, PAGE_SIZE, &cbWritten);
     575            if (   RT_SUCCESS(rc)
     576                && cbWritten < PAGE_SIZE - 1)
     577            {
     578                uint8_t *pbLast = (uint8_t *)pRegion->pvPageR3 + cbWritten;
     579                *pbLast = 0xc3;  /* RET */
     580
     581                LogRel(("GIM: HyperV: Enabled hypercalls at %#RGp\n", GCPhysHypercallPage));
     582                return VINF_SUCCESS;
     583            }
     584            else
     585                LogRelFunc(("HMPatchHypercall failed. rc=%Rrc cbWritten=%u\n", rc, cbWritten));
     586        }
     587        else
     588        {
     589            /** @todo Handle raw-mode hypercall page patching. */
     590            LogRelFunc(("Raw-mode not yet implemented!\n"));
     591        }
     592        GIMR3Mmio2Unmap(pVM, pRegion);
     593    }
     594    else
     595        LogRelFunc(("GIMR3Mmio2Map failed. rc=%Rrc\n", rc));
     596
     597    return rc;
     598}
     599
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r51220 r51643  
    733733        HM_REG_COUNTER(&pVCpu->hm.s.StatTlbShootdownFlush,      "/HM/CPU%d/Flush/Shootdown/TLB", "Inter-VCPU request to flush entire guest-TLB.");
    734734
     735        HM_REG_COUNTER(&pVCpu->hm.s.StatTscOffsetAdjusted,      "/HM/CPU%d/TSC/OffsetAdjusted", "TSC offset overflowed for paravirt. TSC. Fudged.");
     736        HM_REG_COUNTER(&pVCpu->hm.s.StatTscParavirt,            "/HM/CPU%d/TSC/Paravirt", "Paravirtualized TSC in effect.");
    735737        HM_REG_COUNTER(&pVCpu->hm.s.StatTscOffset,              "/HM/CPU%d/TSC/Offset", "TSC offsetting is in effect.");
    736738        HM_REG_COUNTER(&pVCpu->hm.s.StatTscIntercept,           "/HM/CPU%d/TSC/Intercept", "Guest is in catchup mode, intercept TSC accesses.");
     
    11721174    {
    11731175        CPUMClearGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP);
    1174         LogRel(("HM: RDTSCP disabled.\n"));
     1176        LogRel(("HM: RDTSCP disabled\n"));
    11751177    }
    11761178
     
    12411243
    12421244    LogRel((pVM->hm.s.fAllow64BitGuests
    1243             ? "HM: Guest support: 32-bit and 64-bit.\n"
    1244             : "HM: Guest support: 32-bit only.\n"));
     1245            ? "HM: Guest support: 32-bit and 64-bit\n"
     1246            : "HM: Guest support: 32-bit only\n"));
    12451247
    12461248    /*
     
    12871289            CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
    12881290        else
    1289             LogRel(("HM: NX not enabled on the host, unavailable to PAE guest.\n"));
     1291            LogRel(("HM: NX not enabled on the host, unavailable to PAE guest\n"));
    12901292    }
    12911293
     
    12961298    {
    12971299        LogRel(("HM: Nested paging enabled!\n"));
    1298         if (pVM->hm.s.vmx.enmFlushEpt == VMX_FLUSH_EPT_SINGLE_CONTEXT)
    1299             LogRel(("HM:   EPT flush type                = VMX_FLUSH_EPT_SINGLE_CONTEXT\n"));
    1300         else if (pVM->hm.s.vmx.enmFlushEpt == VMX_FLUSH_EPT_ALL_CONTEXTS)
    1301             LogRel(("HM:   EPT flush type                = VMX_FLUSH_EPT_ALL_CONTEXTS\n"));
    1302         else if (pVM->hm.s.vmx.enmFlushEpt == VMX_FLUSH_EPT_NOT_SUPPORTED)
    1303             LogRel(("HM:   EPT flush type                = VMX_FLUSH_EPT_NOT_SUPPORTED\n"));
     1300        if (pVM->hm.s.vmx.enmFlushEpt == VMXFLUSHEPT_SINGLE_CONTEXT)
     1301            LogRel(("HM:   EPT flush type                = VMXFLUSHEPT_SINGLE_CONTEXT\n"));
     1302        else if (pVM->hm.s.vmx.enmFlushEpt == VMXFLUSHEPT_ALL_CONTEXTS)
     1303            LogRel(("HM:   EPT flush type                = VMXFLUSHEPT_ALL_CONTEXTS\n"));
     1304        else if (pVM->hm.s.vmx.enmFlushEpt == VMXFLUSHEPT_NOT_SUPPORTED)
     1305            LogRel(("HM:   EPT flush type                = VMXFLUSHEPT_NOT_SUPPORTED\n"));
    13041306        else
    13051307            LogRel(("HM:   EPT flush type                = %d\n", pVM->hm.s.vmx.enmFlushEpt));
     
    13131315            /* Use large (2 MB) pages for our EPT PDEs where possible. */
    13141316            PGMSetLargePageUsage(pVM, true);
    1315             LogRel(("HM: Large page support enabled!\n"));
     1317            LogRel(("HM: Large page support enabled\n"));
    13161318        }
    13171319#endif
     
    13231325    {
    13241326        LogRel(("HM: VPID enabled!\n"));
    1325         if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_INDIV_ADDR)
    1326             LogRel(("HM:   VPID flush type               = VMX_FLUSH_VPID_INDIV_ADDR\n"));
    1327         else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_SINGLE_CONTEXT)
    1328             LogRel(("HM:   VPID flush type               = VMX_FLUSH_VPID_SINGLE_CONTEXT\n"));
    1329         else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_ALL_CONTEXTS)
    1330             LogRel(("HM:   VPID flush type               = VMX_FLUSH_VPID_ALL_CONTEXTS\n"));
    1331         else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
    1332             LogRel(("HM:   VPID flush type               = VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS\n"));
     1327        if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_INDIV_ADDR)
     1328            LogRel(("HM:   VPID flush type               = VMXFLUSHVPID_INDIV_ADDR\n"));
     1329        else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_SINGLE_CONTEXT)
     1330            LogRel(("HM:   VPID flush type               = VMXFLUSHVPID_SINGLE_CONTEXT\n"));
     1331        else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_ALL_CONTEXTS)
     1332            LogRel(("HM:   VPID flush type               = VMXFLUSHVPID_ALL_CONTEXTS\n"));
     1333        else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
     1334            LogRel(("HM:   VPID flush type               = VMXFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS\n"));
    13331335        else
    13341336            LogRel(("HM:   VPID flush type               = %d\n", pVM->hm.s.vmx.enmFlushVpid));
    13351337    }
    1336     else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_NOT_SUPPORTED)
    1337         LogRel(("HM: Ignoring VPID capabilities of CPU.\n"));
     1338    else if (pVM->hm.s.vmx.enmFlushVpid == VMXFLUSHVPID_NOT_SUPPORTED)
     1339        LogRel(("HM: Ignoring VPID capabilities of CPU\n"));
    13381340
    13391341    /*
     
    13471349    }
    13481350    if (pVM->hm.s.vmx.fUsePreemptTimer)
    1349         LogRel(("HM: VMX-preemption timer enabled (cPreemptTimerShift=%u).\n", pVM->hm.s.vmx.cPreemptTimerShift));
     1351        LogRel(("HM: VMX-preemption timer enabled (cPreemptTimerShift=%u)\n", pVM->hm.s.vmx.cPreemptTimerShift));
    13501352    else
    1351         LogRel(("HM: VMX-preemption timer disabled.\n"));
     1353        LogRel(("HM: VMX-preemption timer disabled\n"));
    13521354
    13531355    return VINF_SUCCESS;
     
    14651467        CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
    14661468
    1467     LogRel(("HM: TPR patching %s.\n", (pVM->hm.s.fTprPatchingAllowed) ? "enabled" : "disabled"));
     1469    LogRel(("HM: TPR patching %s\n", (pVM->hm.s.fTprPatchingAllowed) ? "enabled" : "disabled"));
    14681470
    14691471    LogRel((pVM->hm.s.fAllow64BitGuests
    1470             ? "HM: Guest support: 32-bit and 64-bit.\n"
    1471             : "HM: Guest support: 32-bit only.\n"));
     1472            ? "HM: Guest support: 32-bit and 64-bit\n"
     1473            : "HM: Guest support: 32-bit only\n"));
    14721474
    14731475    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/include/GIMHvInternal.h

    r51563 r51643  
    389389AssertCompile(MSR_GIM_HV_RANGE11_START <= MSR_GIM_HV_RANGE11_END);
    390390
     391/** @name Hyper-V MSR - Reset (MSR_GIM_HV_RESET).
     392 * @{
     393 */
     394/** The hypercall enable bit. */
     395#define MSR_GIM_HV_RESET_BIT                      RT_BIT_64(0)
     396/** Whether the hypercall-page is enabled or not. */
     397#define MSR_GIM_HV_RESET_IS_SET(a)                RT_BOOL((a) & MSR_GIM_HV_RESET_BIT)
     398/** @} */
    391399
    392400/** @name Hyper-V MSR - Hypercall (MSR_GIM_HV_HYPERCALL).
     
    434442    uint32_t            uReserved0;
    435443    uint64_t volatile   u64TscScale;
    436     uint64_t volatile   u64TscOffset;
     444    int64_t  volatile   i64TscOffset;
    437445} GIMHVTSCPAGE;
    438 /** Pointer to GIM VMCPU instance data. */
     446/** Pointer to Hyper-V reference TSC. */
    439447typedef GIMHVREFTSC *PGIMHVREFTSC;
     448/** Pointer to a const Hyper-V reference TSC. */
     449typedef GIMHVREFTSC const *PCGIMHVREFTSC;
     450
    440451
    441452/**
     
    465476    uint32_t                    u32Alignment0;
    466477
     478    /** Per-VM R0 Spinlock for protecting EMT writes to the TSC page. */
     479    RTSPINLOCK                  hSpinlockR0;
     480#if HC_ARCH_BITS == 32
     481    uint32_t                    u32Alignment1;
     482#endif
     483
    467484    /** Array of MMIO2 regions. */
    468485    GIMMMIO2REGION              aMmio2Regions[GIM_HV_REGION_IDX_MAX + 1];
     
    473490typedef GIMHV const *PCGIMHV;
    474491AssertCompileMemberAlignment(GIMHV, aMmio2Regions, 8);
     492AssertCompileMemberAlignment(GIMHV, hSpinlockR0, sizeof(uintptr_t));
    475493
    476494RT_C_DECLS_BEGIN
     
    479497VMMR0_INT_DECL(int)             GIMR0HvInitVM(PVM pVM);
    480498VMMR0_INT_DECL(int)             GIMR0HvTermVM(PVM pVM);
     499VMMR0_INT_DECL(int)             GIMR0HvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset);
    481500#endif /* IN_RING0 */
    482501
    483502#ifdef IN_RING3
    484503VMMR3_INT_DECL(int)             GIMR3HvInit(PVM pVM);
     504VMMR3_INT_DECL(int)             GIMR3HvTerm(PVM pVM);
    485505VMMR3_INT_DECL(void)            GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta);
    486506VMMR3_INT_DECL(void)            GIMR3HvReset(PVM pVM);
    487507VMMR3_INT_DECL(PGIMMMIO2REGION) GIMR3HvGetMmio2Regions(PVM pVM, uint32_t *pcRegions);
     508VMMR3_INT_DECL(int)             GIMR3HvSave(PVM pVM, PSSMHANDLE pSSM);
     509VMMR3_INT_DECL(int)             GIMR3HvLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion);
     510
     511VMMR3_INT_DECL(int)             GIMR3HvDisableTscPage(PVM pVM);
     512VMMR3_INT_DECL(int)             GIMR3HvEnableTscPage(PVM pVM, RTGCPHYS GCPhysTscPage);
     513VMMR3_INT_DECL(int)             GIMR3HvDisableHypercallPage(PVM pVM);
     514VMMR3_INT_DECL(int)             GIMR3HvEnableHypercallPage(PVM pVM, RTGCPHYS GCPhysHypercallPage);
    488515#endif /* IN_RING3 */
    489516
    490517VMM_INT_DECL(bool)              GIMHvIsParavirtTscEnabled(PVM pVM);
    491 VMM_INT_DECL(int)               GIMHvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset);
    492518VMM_INT_DECL(int)               GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
    493519VMM_INT_DECL(int)               GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
  • trunk/src/VBox/VMM/include/GIMInternal.h

    r51560 r51643  
    2929 * @{
    3030 */
     31
     32/** The saved state version. */
     33#define GIM_SSM_VERSION                          1
    3134
    3235/**
     
    8992
    9093#ifdef IN_RING3
    91 VMM_INT_DECL(int)           GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion);
    92 VMM_INT_DECL(int)           GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion, const char *pszDesc);
     94VMMR3_INT_DECL(int)           GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion);
     95VMMR3_INT_DECL(int)           GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion);
     96VMMR3_INT_DECL(int)           GIMR3Mmio2HandlerPhysicalRegister(PVM pVM, PGIMMMIO2REGION pRegion);
     97VMMR3_INT_DECL(int)           GIMR3Mmio2HandlerPhysicalDeregister(PVM pVM, PGIMMMIO2REGION pRegion);
    9398#endif /* IN_RING3 */
    9499
  • trunk/src/VBox/VMM/include/HMInternal.h

    r51220 r51643  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    313313    /** Set when we've initialized VMX or SVM. */
    314314    bool                        fInitialized;
    315 
    316315    /** Set if nested paging is enabled. */
    317316    bool                        fNestedPaging;
    318 
    319317    /** Set if nested paging is allowed. */
    320318    bool                        fAllowNestedPaging;
    321 
    322319    /** Set if large pages are enabled (requires nested paging). */
    323320    bool                        fLargePages;
    324 
    325321    /** Set if we can support 64-bit guests or not. */
    326322    bool                        fAllow64BitGuests;
    327 
    328323    /** Set if an IO-APIC is configured for this VM. */
    329324    bool                        fHasIoApic;
    330 
    331325    /** Set when TPR patching is allowed. */
    332326    bool                        fTprPatchingAllowed;
    333 
    334327    /** Set when we initialize VT-x or AMD-V once for all CPUs. */
    335328    bool                        fGlobalInit;
    336 
    337329    /** Set when TPR patching is active. */
    338330    bool                        fTPRPatchingActive;
     
    341333    /** Maximum ASID allowed. */
    342334    uint32_t                    uMaxAsid;
    343 
    344335    /** The maximum number of resumes loops allowed in ring-0 (safety precaution).
    345336     * This number is set much higher when RTThreadPreemptIsPending is reliable. */
     
    352343    /** Size of the guest patch memory block. */
    353344    uint32_t                    cbGuestPatchMem;
    354     uint32_t                    uPadding1;
     345    uint32_t                    u32Alignment0;
    355346
    356347#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
    357348    /** 32 to 64 bits switcher entrypoint. */
    358349    R0PTRTYPE(PFNHMSWITCHERHC)  pfnHost32ToGuest64R0;
    359     RTR0PTR                     uPadding2;
     350    RTR0PTR                     pvR0Alignment0;
    360351#endif
    361352
     
    365356         *  CPU. */
    366357        bool                        fSupported;
    367 
    368358        /** Set when we've enabled VMX. */
    369359        bool                        fEnabled;
    370 
    371360        /** Set if VPID is supported. */
    372361        bool                        fVpid;
    373 
    374362        /** Set if VT-x VPID is allowed. */
    375363        bool                        fAllowVpid;
    376 
    377364        /** Set if unrestricted guest execution is in use (real and protected mode without paging). */
    378365        bool                        fUnrestrictedGuest;
    379 
    380366        /** Set if unrestricted guest execution is allowed to be used. */
    381367        bool                        fAllowUnrestricted;
    382 
    383368        /** Whether we're using the preemption timer or not. */
    384369        bool                        fUsePreemptTimer;
     
    388373        /** Virtual address of the TSS page used for real mode emulation. */
    389374        R3PTRTYPE(PVBOXTSS)         pRealModeTSS;
    390 
    391375        /** Virtual address of the identity page table used for real mode and protected mode without paging emulation in EPT mode. */
    392376        R3PTRTYPE(PX86PD)           pNonPagingModeEPTPageTable;
    393377
     378        /** Physical address of the APIC-access page. */
     379        RTHCPHYS                    HCPhysApicAccess;
    394380        /** R0 memory object for the APIC-access page. */
    395381        RTR0MEMOBJ                  hMemObjApicAccess;
    396         /** Physical address of the APIC-access page. */
    397         RTHCPHYS                    HCPhysApicAccess;
    398382        /** Virtual address of the APIC-access page. */
    399383        R0PTRTYPE(uint8_t *)        pbApicAccess;
    400384
    401385#ifdef VBOX_WITH_CRASHDUMP_MAGIC
     386        RTHCPHYS                    HCPhysScratch;
    402387        RTR0MEMOBJ                  hMemObjScratch;
    403         RTHCPHYS                    HCPhysScratch;
    404388        R0PTRTYPE(uint8_t *)        pbScratch;
    405389#endif
    406390
    407391        /** Internal Id of which flush-handler to use for tagged-TLB entries. */
    408         unsigned                    uFlushTaggedTlb;
    409 
    410 #if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
    411         uint32_t                    u32Alignment;
    412 #endif
     392        uint32_t                    uFlushTaggedTlb;
     393        uint32_t                    u32Alignment0;
    413394        /** Host CR4 value (set by ring-0 VMX init) */
    414395        uint64_t                    u64HostCr4;
     
    418399        /** Whether the CPU supports VMCS fields for swapping EFER. */
    419400        bool                        fSupportsVmcsEfer;
    420         bool                        afAlignment1[7];
     401        uint8_t                     u8Alignment2[7];
    421402
    422403        /** VMX MSR values */
     
    424405
    425406        /** Flush types for invept & invvpid; they depend on capabilities. */
    426         VMX_FLUSH_EPT               enmFlushEpt;
    427         VMX_FLUSH_VPID              enmFlushVpid;
     407        VMXFLUSHEPT                 enmFlushEpt;
     408        VMXFLUSHVPID                enmFlushVpid;
    428409    } vmx;
    429410
     
    439420        /** Set when the hack to ignore VERR_SVM_IN_USE is active. */
    440421        bool                        fIgnoreInUseError;
    441 
     422        uint8_t                     u8Alignment0[4];
     423
     424        /** Physical address of the IO bitmap (12kb). */
     425        RTHCPHYS                    HCPhysIOBitmap;
    442426        /** R0 memory object for the IO bitmap (12kb). */
    443427        RTR0MEMOBJ                  hMemObjIOBitmap;
    444         /** Physical address of the IO bitmap (12kb). */
    445         RTHCPHYS                    HCPhysIOBitmap;
    446428        /** Virtual address of the IO bitmap. */
    447429        R0PTRTYPE(void *)           pvIOBitmap;
     
    452434        /** SVM revision. */
    453435        uint32_t                    u32Rev;
    454 
    455436        /** SVM feature bits from cpuid 0x8000000a */
    456437        uint32_t                    u32Features;
     
    458439
    459440    /**
    460      * AVL tree with all patches (active or disabled) sorted by guest instruction address
     441     * AVL tree with all patches (active or disabled) sorted by guest instruction
     442     * address.
    461443     */
    462444    AVLOU32TREE                     PatchTree;
     
    488470#define VMCSCACHE_MAX_ENTRY                             128
    489471
    490 /* Structure for storing read and write VMCS actions. */
     472/**
     473 * Structure for storing read and write VMCS actions.
     474 */
    491475typedef struct VMCSCACHE
    492476{
     
    546530/** Pointer to VMCSCACHE. */
    547531typedef VMCSCACHE *PVMCSCACHE;
     532AssertCompileSizeAlignment(VMCSCACHE, 8);
    548533
    549534/** VMX StartVM function. */
     
    597582    struct
    598583    {
    599         /** Physical address of the VM control structure (VMCS). */
    600         RTHCPHYS                    HCPhysVmcs;
    601         /** R0 memory object for the VM control structure (VMCS). */
    602         RTR0MEMOBJ                  hMemObjVmcs;
    603         /** Virtual address of the VM control structure (VMCS). */
    604         R0PTRTYPE(void *)           pvVmcs;
    605584        /** Ring 0 handlers for VT-x. */
    606585        PFNHMVMXSTARTVM             pfnStartVM;
    607586#if HC_ARCH_BITS == 32
    608         uint32_t                    u32Alignment1;
    609 #endif
    610 
     587        uint32_t                    u32Alignment0;
     588#endif
    611589        /** Current VMX_VMCS32_CTRL_PIN_EXEC. */
    612590        uint32_t                    u32PinCtls;
     
    620598        uint32_t                    u32EntryCtls;
    621599
    622         /** Physical address of the virtual APIC page for TPR caching. */
    623         RTHCPHYS                    HCPhysVirtApic;
    624         /** R0 memory object for the virtual APIC page for TPR caching. */
    625         RTR0MEMOBJ                  hMemObjVirtApic;
    626         /** Virtual address of the virtual APIC page for TPR caching. */
    627         R0PTRTYPE(uint8_t *)        pbVirtApic;
    628 #if HC_ARCH_BITS == 32
    629         uint32_t                    u32Alignment2;
    630 #endif
    631 
    632600        /** Current CR0 mask. */
    633601        uint32_t                    u32CR0Mask;
     
    638606        /** The updated-guest-state mask. */
    639607        volatile uint32_t           fUpdatedGuestState;
    640         /** Current EPTP. */
    641         RTHCPHYS                    HCPhysEPTP;
     608        uint32_t                    u32Alignment1;
     609
     610        /** Physical address of the VM control structure (VMCS). */
     611        RTHCPHYS                    HCPhysVmcs;
     612        /** R0 memory object for the VM control structure (VMCS). */
     613        RTR0MEMOBJ                  hMemObjVmcs;
     614        /** Virtual address of the VM control structure (VMCS). */
     615        R0PTRTYPE(void *)           pvVmcs;
     616
     617        /** Physical address of the virtual APIC page for TPR caching. */
     618        RTHCPHYS                    HCPhysVirtApic;
     619        /** R0 memory object for the virtual APIC page for TPR caching. */
     620        RTR0MEMOBJ                  hMemObjVirtApic;
     621        /** Virtual address of the virtual APIC page for TPR caching. */
     622        R0PTRTYPE(uint8_t *)        pbVirtApic;
    642623
    643624        /** Physical address of the MSR bitmap. */
     
    665646        R0PTRTYPE(void *)           pvHostMsr;
    666647
     648        /** Current EPTP. */
     649        RTHCPHYS                    HCPhysEPTP;
     650
    667651        /** Number of guest/host MSR pairs in the auto-load/store area. */
    668652        uint32_t                    cMsrs;
    669653        /** Whether the host MSR values are up-to-date in the auto-load/store area. */
    670654        bool                        fUpdatedHostMsrs;
    671         uint8_t                     u8Align[7];
     655        uint8_t                     u8Alignment0[3];
    672656
    673657        /** Host LSTAR MSR value to restore lazily while leaving VT-x. */
     
    681665        /** A mask of which MSRs have been swapped and need restoration. */
    682666        uint32_t                    fRestoreHostMsrs;
    683         uint32_t                    u32Alignment3;
     667        uint32_t                    u32Alignment2;
    684668
    685669        /** The cached APIC-base MSR used for identifying when to map the HC physical APIC-access page. */
     
    704688        } RealMode;
    705689
     690        /** VT-x error-reporting (mainly for ring-3 propagation). */
    706691        struct
    707692        {
     
    712697            RTCPUID                 idEnteredCpu;
    713698            RTCPUID                 idCurrentCpu;
    714             uint32_t                u32Padding;
     699            uint32_t                u32Alignment0;
    715700        } LastError;
    716701
    717         /** State of the VMCS. */
     702        /** Current state of the VMCS. */
    718703        uint32_t                    uVmcsState;
    719704        /** Which host-state bits to restore before being preempted. */
     
    721706        /** The host-state restoration structure. */
    722707        VMXRESTOREHOST              RestoreHost;
     708
    723709        /** Set if guest was executing in real mode (extra checks). */
    724710        bool                        fWasInRealMode;
    725         uint8_t                     u8Align2[7];
    726 
    727         /** Alignment padding. */
    728         uint32_t                    u32Padding;
     711        uint8_t                     u8Alignment1[7];
    729712    } vmx;
    730713
    731714    struct
    732715    {
     716        /** Ring 0 handlers for VT-x. */
     717        PFNHMSVMVMRUN               pfnVMRun;
     718#if HC_ARCH_BITS == 32
     719        uint32_t                    u32Alignment0;
     720#endif
     721
     722        /** Physical address of the host VMCB which holds additional host-state. */
     723        RTHCPHYS                    HCPhysVmcbHost;
    733724        /** R0 memory object for the host VMCB which holds additional host-state. */
    734725        RTR0MEMOBJ                  hMemObjVmcbHost;
    735         /** Physical address of the host VMCB which holds additional host-state. */
    736         RTHCPHYS                    HCPhysVmcbHost;
    737726        /** Virtual address of the host VMCB which holds additional host-state. */
    738727        R0PTRTYPE(void *)           pvVmcbHost;
    739728
     729        /** Physical address of the guest VMCB. */
     730        RTHCPHYS                    HCPhysVmcb;
    740731        /** R0 memory object for the guest VMCB. */
    741732        RTR0MEMOBJ                  hMemObjVmcb;
    742         /** Physical address of the guest VMCB. */
    743         RTHCPHYS                    HCPhysVmcb;
    744733        /** Virtual address of the guest VMCB. */
    745734        R0PTRTYPE(void *)           pvVmcb;
    746735
    747         /** Ring 0 handlers for VT-x. */
    748         PFNHMSVMVMRUN               pfnVMRun;
    749 
     736        /** Physical address of the MSR bitmap (8 KB). */
     737        RTHCPHYS                    HCPhysMsrBitmap;
    750738        /** R0 memory object for the MSR bitmap (8 KB). */
    751739        RTR0MEMOBJ                  hMemObjMsrBitmap;
    752         /** Physical address of the MSR bitmap (8 KB). */
    753         RTHCPHYS                    HCPhysMsrBitmap;
    754740        /** Virtual address of the MSR bitmap. */
    755741        R0PTRTYPE(void *)           pvMsrBitmap;
     
    758744         *  we should check if the VTPR changed on every VM-exit. */
    759745        bool                        fSyncVTpr;
    760         uint8_t                     u8Align[7];
    761 
    762         /** Alignment padding. */
    763         uint32_t                    u32Padding;
     746        uint8_t                     u8Alignment0[7];
    764747    } svm;
    765748
     
    791774        /** Pending IO operation type. */
    792775        HMPENDINGIO             enmType;
    793         uint32_t                uPadding;
     776        uint32_t                u32Alignment0;
    794777        RTGCPTR                 GCPtrRip;
    795778        RTGCPTR                 GCPtrRipNext;
     
    822805        RTGCPTR             aPages[HM_MAX_TLB_SHOOTDOWN_PAGES];
    823806        uint32_t            cPages;
    824         uint32_t            u32Padding; /**< Explicit alignment padding. */
     807        uint32_t            u32Alignment0; /**< Explicit alignment padding. */
    825808    } TlbShootdown;
    826809
     
    931914    STAMCOUNTER             StatSwitchLongJmpToR3;
    932915
     916    STAMCOUNTER             StatTscOffsetAdjusted;
     917    STAMCOUNTER             StatTscParavirt;
    933918    STAMCOUNTER             StatTscOffset;
    934919    STAMCOUNTER             StatTscIntercept;
     
    970955/** Pointer to HM VMCPU instance data. */
    971956typedef HMCPU *PHMCPU;
     957AssertCompileMemberAlignment(HMCPU, vmx, 8);
     958AssertCompileMemberAlignment(HMCPU, svm, 8);
     959AssertCompileMemberAlignment(HMCPU, Event, 8);
    972960
    973961
    974962#ifdef IN_RING0
    975 
    976963VMMR0DECL(PHMGLOBALCPUINFO) HMR0GetCurrentCpu(void);
    977964VMMR0DECL(PHMGLOBALCPUINFO) HMR0GetCurrentCpuEx(RTCPUID idCpu);
    978965
    979966
    980 #ifdef VBOX_STRICT
     967# ifdef VBOX_STRICT
    981968VMMR0DECL(void) HMDumpRegs(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    982969VMMR0DECL(void) HMR0DumpDescriptor(PCX86DESCHC pDesc, RTSEL Sel, const char *pszMsg);
    983 #else
    984 # define HMDumpRegs(a, b ,c)            do { } while (0)
    985 # define HMR0DumpDescriptor(a, b, c)    do { } while (0)
    986 #endif
     970# else
     971#  define HMDumpRegs(a, b ,c)            do { } while (0)
     972#  define HMR0DumpDescriptor(a, b, c)    do { } while (0)
     973# endif /* VBOX_STRICT */
    987974
    988975# ifdef VBOX_WITH_KERNEL_USING_XMM
     
    1004991 */
    1005992DECLASM(uint64_t) HMR0Get64bitCR3(void);
    1006 # endif
     993# endif  /* VBOX_WITH_HYBRID_32BIT_KERNEL */
    1007994
    1008995#endif /* IN_RING0 */
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r50953 r51643  
    77
    88/*
    9  * Copyright (C) 2006-2012 Oracle Corporation
     9 * Copyright (C) 2006-2014 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    408408    /* hm - 32-bit gcc won't align uint64_t naturally, so check. */
    409409    CHECK_MEMBER_ALIGNMENT(HM, uMaxAsid, 8);
    410     CHECK_MEMBER_ALIGNMENT(HM, vmx.u64HostCr4, 8);
    411     CHECK_MEMBER_ALIGNMENT(HM, vmx.Msrs.u64FeatureCtrl, 8);
    412     CHECK_MEMBER_ALIGNMENT(HM, StatTprPatchSuccess, 8);
     410    CHECK_MEMBER_ALIGNMENT(HM, vmx, 8);
     411    CHECK_MEMBER_ALIGNMENT(HM, vmx.Msrs, 8);
     412    CHECK_MEMBER_ALIGNMENT(HM, svm, 8);
     413    CHECK_MEMBER_ALIGNMENT(HM, PatchTree, 8);
     414    CHECK_MEMBER_ALIGNMENT(HM, aPatches, 8);
     415    CHECK_MEMBER_ALIGNMENT(HMCPU, vmx, 8);
     416    CHECK_MEMBER_ALIGNMENT(HMCPU, vmx.pfnStartVM, 8);
     417    CHECK_MEMBER_ALIGNMENT(HMCPU, vmx.HCPhysVmcs, 8);
     418    CHECK_MEMBER_ALIGNMENT(HMCPU, vmx.LastError, 8);
     419    CHECK_MEMBER_ALIGNMENT(HMCPU, svm, 8);
     420    CHECK_MEMBER_ALIGNMENT(HMCPU, svm.pfnVMRun, 8);
     421    CHECK_MEMBER_ALIGNMENT(HMCPU, Event, 8);
     422    CHECK_MEMBER_ALIGNMENT(HMCPU, Event.u64IntInfo, 8);
     423    CHECK_MEMBER_ALIGNMENT(HMCPU, DisState, 8);
    413424    CHECK_MEMBER_ALIGNMENT(HMCPU, StatEntry, 8);
    414     CHECK_MEMBER_ALIGNMENT(HMCPU, vmx.HCPhysVmcs, sizeof(RTHCPHYS));
    415     CHECK_MEMBER_ALIGNMENT(HMCPU, vmx.u32PinCtls, 8);
    416     CHECK_MEMBER_ALIGNMENT(HMCPU, DisState, 8);
    417     CHECK_MEMBER_ALIGNMENT(HMCPU, Event.u64IntInfo, 8);
    418425
    419426    /* Make sure the set is large enough and has the correct size. */
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