Changeset 51560 in vbox
- Timestamp:
- Jun 6, 2014 5:17:02 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 94218
- Location:
- trunk
- Files:
-
- 3 added
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r51342 r51560 4 4 5 5 /* 6 * Copyright (C) 2006-201 3Oracle Corporation6 * Copyright (C) 2006-2014 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 1088 1088 /** Reason for leaving RZ: I/O port write. */ 1089 1089 #define VINF_IOM_R3_IOPORT_WRITE 2621 1090 /** Reason for leaving RZ: MMIO read. */ 1091 #define VINF_IOM_R3_MMIO_READ 2623 1090 1092 /** Reason for leaving RZ: MMIO write. */ 1091 #define VINF_IOM_R3_MMIO_READ 26231092 /** Reason for leaving RZ: MMIO read. */1093 1093 #define VINF_IOM_R3_MMIO_WRITE 2624 1094 1094 /** Reason for leaving RZ: MMIO read/write. */ … … 2016 2016 #define VERR_HM_NO_32_TO_64_SWITCHER (-4106) 2017 2017 /** HMR0Leave was called on the wrong CPU. */ 2018 #define VERR_HM_WRONG_CPU _1(-4107)2018 #define VERR_HM_WRONG_CPU (-4107) 2019 2019 /** Internal processing error \#1 in the HM code. */ 2020 2020 #define VERR_HM_IPE_1 (-4108) … … 2029 2029 /** Internal processing error \#3 in the HM code. */ 2030 2030 #define VERR_HM_IPE_3 (-4113) 2031 /** Internal processing error \# 3in the HM code. */2031 /** Internal processing error \#4 in the HM code. */ 2032 2032 #define VERR_HM_IPE_4 (-4114) 2033 /** Internal processing error \# 3in the HM code. */2033 /** Internal processing error \#5 in the HM code. */ 2034 2034 #define VERR_HM_IPE_5 (-4115) 2035 2035 /** Invalid HM64ON32OP value. */ … … 2308 2308 /** Syntax error - buggy parser. */ 2309 2309 #define VERR_DBGC_PARSE_BUG (VERR_DBGC_PARSE_LOWEST + 25) 2310 2311 2312 /** @} */ 2310 /** @} */ 2311 2313 2312 2314 2313 /** @name VBox Extension Pack Status Codes … … 2327 2326 2328 2327 2329 /** @} */2330 2331 2328 /** @name VBox Guest Control Status Codes 2332 2329 * @{ … … 2339 2336 2340 2337 2338 /** @name GIM Status Codes 2339 * @{ 2340 */ 2341 /** No GIM provider is configured for this VM. */ 2342 #define VERR_GIM_NOT_ENABLED (-6300) 2343 /** GIM internal processing error \#1. */ 2344 #define VERR_GIM_IPE_1 (-6301) 2345 /** GIM internal processing error \#2. */ 2346 #define VERR_GIM_IPE_2 (-6302) 2347 /** GIM internal processing error \#3. */ 2348 #define VERR_GIM_IPE_3 (-6303) 2349 /** The GIM provider does not support any paravirtualized TSC. */ 2350 #define VERR_GIM_PVTSC_NOT_AVAILABLE (-6304) 2351 /** The guest has not setup use of the paravirtualized TSC. */ 2352 #define VERR_GIM_PVTSC_NOT_ENABLED (-6305) 2353 /** Unknown or invalid GIM provider. */ 2354 #define VERR_GIM_INVALID_PROVIDER (-6306) 2355 /** @} */ 2356 2357 2341 2358 /* SED-END */ 2342 2359 -
trunk/include/VBox/log.h
r51557 r51560 98 98 /** Floppy Controller Device group. */ 99 99 LOG_GROUP_DEV_FDC, 100 /** Guest Interface Manager Device group. */ 101 LOG_GROUP_DEV_GIM, 100 102 /** High Precision Event Timer Device group. */ 101 103 LOG_GROUP_DEV_HPET, … … 790 792 "DEV_EHCI", \ 791 793 "DEV_FDC", \ 794 "DEV_GIM", \ 792 795 "DEV_HPET", \ 793 796 "DEV_IDE", \ -
trunk/include/VBox/vmm/gim.h
r51333 r51560 44 44 45 45 /** 46 * Providers identifiers.46 * GIM Provider Identifiers. 47 47 */ 48 48 typedef enum GIMPROVIDERID … … 55 55 GIMPROVIDERID_HYPERV, 56 56 /** Linux KVM Interface. */ 57 GIMPROVIDERID_KVM, 58 /** Ensure 32-bit type. */ 59 GIMPROVIDERID_32BIT_HACK = 0x7fffffff 57 GIMPROVIDERID_KVM 60 58 } GIMPROVIDERID; 59 AssertCompileSize(GIMPROVIDERID, 4); 60 61 62 /** 63 * A GIM MMIO2 region record. 64 */ 65 typedef struct GIMMMIO2REGION 66 { 67 /** The region index. */ 68 uint8_t iRegion; 69 /** Whether an RC mapping is required. */ 70 bool fRCMapping; 71 /** Whether this region has been registered. */ 72 bool fRegistered; 73 /** Whether this region is currently mapped. */ 74 bool fMapped; 75 /** Alignment padding. */ 76 uint8_t au8Alignment0[4]; 77 /** Size of the region (must be page aligned). */ 78 uint32_t cbRegion; 79 /** Alignment padding. */ 80 uint32_t u32Alignment0; 81 /** The host ring-0 address of the first page in the region. */ 82 R0PTRTYPE(void *) pvPageR0; 83 /** The host ring-3 address of the first page in the region. */ 84 R3PTRTYPE(void *) pvPageR3; 85 /** The ring-context address of the first page in the region. */ 86 RCPTRTYPE(void *) pvPageRC; 87 /** The guest-physical address of the first page in the region. */ 88 RTGCPHYS GCPhysPage; 89 /** The description of the region. */ 90 char szDescription[32]; 91 } GIMMMIO2REGION; 92 /** Pointer to a GIM MMIO2 region. */ 93 typedef GIMMMIO2REGION *PGIMMMIO2REGION; 94 /** Pointer to a const GIM MMIO2 region. */ 95 typedef GIMMMIO2REGION const *PCGIMMMIO2REGION; 96 AssertCompileMemberAlignment(GIMMMIO2REGION, cbRegion, 8); 97 AssertCompileMemberAlignment(GIMMMIO2REGION, pvPageR0, 8); 61 98 62 99 … … 114 151 * @{ 115 152 */ 116 153 VMMR0_INT_DECL(int) GIMR0InitVM(PVM pVM); 154 VMMR0_INT_DECL(int) GIMR0TermVM(PVM pVM); 117 155 /** @} */ 118 156 #endif /* IN_RING0 */ … … 124 162 * @{ 125 163 */ 126 VMMR3_INT_DECL(int) GIMR3Init(PVM pVM); 127 VMMR3_INT_DECL(int) GIMR3Term(PVM pVM); 164 VMMR3_INT_DECL(int) GIMR3Init(PVM pVM); 165 VMMR3_INT_DECL(int) GIMR3Term(PVM pVM); 166 VMMR3_INT_DECL(void) GIMR3Reset(PVM pVM); 167 VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns); 168 VMMR3DECL(PGIMMMIO2REGION) GIMR3GetMmio2Regions(PVM pVM, uint32_t *pcRegions); 128 169 /** @} */ 129 170 #endif /* IN_RING3 */ 130 171 131 VMMDECL(bool) GIMIsEnabled(PVM pVM); 132 VMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx); 133 VMM_INT_DECL(int) GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue); 134 VMM_INT_DECL(int) GIMWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue); 172 VMMDECL(bool) GIMIsEnabled(PVM pVM); 173 VMMDECL(int) GIMUpdateParavirtTsc(PVM pVM, uint64_t u64Offset); 174 VMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx); 175 VMM_INT_DECL(int) GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue); 176 VMM_INT_DECL(int) GIMWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue); 135 177 136 178 /** @} */ … … 138 180 RT_C_DECLS_END 139 181 140 #endif 182 #endif /* ___VBox_vmm_gim_h */ 141 183 -
trunk/include/VBox/vmm/hm.h
r50608 r51560 4 4 5 5 /* 6 * Copyright (C) 2006-201 3Oracle Corporation6 * Copyright (C) 2006-2014 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 144 144 VMM_INT_DECL(int) HMAmdIsSubjectToErratum170(uint32_t *pu32Family, uint32_t *pu32Model, uint32_t *pu32Stepping); 145 145 VMM_INT_DECL(bool) HMSetSingleInstruction(PVMCPU pVCpu, bool fEnable); 146 VMM_INT_DECL(int) HMPatchHypercall(PVM pVM, void *pvBuf, size_t cbBuf, size_t *pcbWritten); 146 147 147 148 #ifndef IN_RC -
trunk/include/VBox/vmm/vm.h
r50953 r51560 4 4 5 5 /* 6 * Copyright (C) 2006-201 3Oracle Corporation6 * Copyright (C) 2006-2014 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 1122 1122 struct GIM s; 1123 1123 #endif 1124 uint8_t padding[ 64]; /* multiple of 64 */1124 uint8_t padding[256]; /* multiple of 64 */ 1125 1125 } gim; 1126 1126 … … 1147 1147 1148 1148 /** Padding for aligning the cpu array on a page boundary. */ 1149 uint8_t abAlignment2[ 350];1149 uint8_t abAlignment2[158]; 1150 1150 1151 1151 /* ---- end small stuff ---- */ -
trunk/include/VBox/vmm/vm.mac
r50953 r51560 4 4 5 5 ; 6 ; Copyright (C) 2006-201 3Oracle Corporation6 ; Copyright (C) 2006-2014 Oracle Corporation 7 7 ; 8 8 ; This file is part of VirtualBox Open Source Edition (OSE), as -
trunk/src/VBox/Devices/Makefile.kmk
r50686 r51560 151 151 PC/DevFwCommon.cpp \ 152 152 PC/DevPcArch.cpp \ 153 GIMDev/GIMDev.cpp \ 153 154 VMMDev/VMMDev.cpp \ 154 155 $(if $(VBOX_WITH_HGCM),VMMDev/VMMDevHGCM.cpp,) \ -
trunk/src/VBox/Devices/build/VBoxDD.cpp
r50686 r51560 192 192 return rc; 193 193 #endif 194 rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceGIMDev); 195 if (RT_FAILURE(rc)) 196 return rc; 194 197 195 198 return VINF_SUCCESS; -
trunk/src/VBox/Devices/build/VBoxDD.h
r50686 r51560 147 147 extern const PDMDRVREG g_DrvPciRaw; 148 148 #endif 149 extern const PDMDEVREG g_DeviceGIMDev; 149 150 150 151 #ifdef VBOX_WITH_USB -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r51476 r51560 1194 1194 InsertConfigNode(pRoot, "GIM", &pParavirtNode); 1195 1195 const char *pcszParavirtProvider; 1196 bool fGimDeviceNeeded = true; 1196 1197 switch (paravirtProvider) 1197 1198 { 1198 1199 case ParavirtProvider_None: 1199 1200 pcszParavirtProvider = "None"; 1201 fGimDeviceNeeded = false; 1200 1202 break; 1201 1203 1202 1204 case ParavirtProvider_Default: /** @todo Choose a provider based on guest OS type. There is no "Default" provider. */ 1203 1205 pcszParavirtProvider = "None"; 1206 fGimDeviceNeeded = false; 1204 1207 break; 1205 1208 … … 1209 1212 pcszParavirtProvider = "Minimal"; 1210 1213 else 1214 { 1211 1215 pcszParavirtProvider = "None"; 1216 fGimDeviceNeeded = false; 1217 } 1212 1218 break; 1213 1219 } … … 1339 1345 1340 1346 InsertConfigNode(pRoot, "Devices", &pDevices); 1347 1348 /* 1349 * GIM Device 1350 */ 1351 if (fGimDeviceNeeded) 1352 { 1353 InsertConfigNode(pDevices, "GIMDev", &pDev); 1354 InsertConfigNode(pDev, "0", &pInst); 1355 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1356 //InsertConfigNode(pInst, "Config", &pCfg); 1357 } 1341 1358 1342 1359 /* -
trunk/src/VBox/VMM/VMMAll/GIMAll.cpp
r51367 r51560 37 37 * 38 38 * @param pVM Pointer to the VM. 39 * @internal40 39 */ 41 40 VMMDECL(bool) GIMIsEnabled(PVM pVM) … … 65 64 default: 66 65 AssertMsgFailed(("GIMHypercall: for unknown provider %u\n", pVM->gim.s.enmProviderId)); 67 return VERR_ INTERNAL_ERROR_5; /** @todo Define and use VERR_GIM_HYPERCALL_UNEXPECTED */;66 return VERR_GIM_IPE_3; 68 67 } 68 } 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; 69 101 } 70 102 -
trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp
r51367 r51560 16 16 */ 17 17 18 19 18 /******************************************************************************* 20 19 * Header Files * … … 22 21 #define LOG_GROUP LOG_GROUP_GIM 23 22 #include "GIMHvInternal.h" 23 #include "GIMInternal.h" 24 24 25 25 #include <VBox/err.h> 26 #include <VBox/vmm/hm.h> 26 27 #include <VBox/vmm/tm.h> 27 28 #include <VBox/vmm/vm.h> 28 29 DECLEXPORT(int) GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx) 29 #include <VBox/vmm/pgm.h> 30 31 32 /** 33 * Handles the Hyper-V hypercall. 34 * 35 * @returns VBox status code. 36 * @param pVCpu Pointer to the VMCPU. 37 * @param pCtx Pointer to the guest-CPU context. 38 */ 39 VMMDECL(int) GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx) 30 40 { 31 41 return VINF_SUCCESS; … … 33 43 34 44 35 DECLEXPORT(int) GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 45 /** 46 * Updates Hyper-V's reference TSC page. 47 * 48 * @returns VBox status code. 49 * @param pVM Pointer to the VM. 50 * @param u64Offset The computed TSC offset. 51 * @thread EMT(pVCpu) 52 */ 53 VMMDECL(int) GIMHvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset) 54 { 55 Assert(GIMIsEnabled(pVM)); 56 bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr); 57 if (!fHvTscEnabled) 58 return VERR_GIM_PVTSC_NOT_ENABLED; 59 60 PGIMHV pHv = &pVM->gim.s.u.Hv; 61 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 62 PGIMHVREFTSC pRefTsc = (PGIMHVREFTSC)pRegion->CTX_SUFF(pvPage); 63 Assert(pRefTsc); 64 65 /** @todo Protect this with a spinlock! */ 66 pRefTsc->u64TscScale = UINT64_C(0x1000000000000000); 67 pRefTsc->u64TscOffset = u64Offset; 68 ASMAtomicIncU32(&pRefTsc->u32TscSequence); 69 70 return VINF_SUCCESS; 71 } 72 73 74 /** 75 * MSR read handler for Hyper-V. 76 * 77 * @returns VBox status code. 78 * @param pVCpu Pointer to the VMCPU. 79 * @param idMsr The MSR being read. 80 * @param pRange The range this MSR belongs to. 81 * @param puValue Where to store the MSR value read. 82 */ 83 VMMDECL(int) GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 36 84 { 37 85 NOREF(pRange); 86 PVM pVM = pVCpu->CTX_SUFF(pVM); 87 PGIMHV pHv = &pVM->gim.s.u.Hv; 88 38 89 switch (idMsr) 39 90 { … … 42 93 /* Hyper-V reports the time in 100ns units. */ 43 94 uint64_t u64Tsc = TMCpuTickGet(pVCpu); 44 uint64_t u64TscHz = TMCpuTicksPerSecond(pV Cpu->CTX_SUFF(pVM));95 uint64_t u64TscHz = TMCpuTicksPerSecond(pVM); 45 96 uint64_t u64Tsc100Ns = u64TscHz / UINT64_C(10000000); /* 100 ns */ 46 97 *puValue = (u64Tsc / u64Tsc100Ns); … … 50 101 case MSR_GIM_HV_VP_INDEX: 51 102 *puValue = pVCpu->idCpu; 103 return VINF_SUCCESS; 104 105 case MSR_GIM_HV_GUEST_OS_ID: 106 *puValue = pHv->u64GuestOsIdMsr; 107 return VINF_SUCCESS; 108 109 case MSR_GIM_HV_HYPERCALL: 110 *puValue = pHv->u64HypercallMsr; 111 return VINF_SUCCESS; 112 113 case MSR_GIM_HV_REF_TSC: 114 *puValue = pHv->u64TscPageMsr; 115 return VINF_SUCCESS; 116 117 case MSR_GIM_HV_TSC_FREQ: 118 *puValue = TMCpuTicksPerSecond(pVM); 119 return VINF_SUCCESS; 120 121 case MSR_GIM_HV_APIC_FREQ: 122 /** @todo Fix this later! Get the information from DevApic. */ 123 *puValue = UINT32_C(1000000000); /* TMCLOCK_FREQ_VIRTUAL */ 52 124 return VINF_SUCCESS; 53 125 … … 61 133 62 134 63 DECLEXPORT(int) GIMHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) 135 /** 136 * MSR write handler for Hyper-V. 137 * 138 * @returns VBox status code. 139 * @param pVCpu Pointer to the VMCPU. 140 * @param idMsr The MSR being written. 141 * @param pRange The range this MSR belongs to. 142 * @param uValue The value to set, ignored bits masked. 143 * @param uRawValue The raw value with the ignored bits not masked. 144 */ 145 VMMDECL(int) GIMHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) 64 146 { 65 LogRel(("GIMHvWriteMsr: Unknown/invalid WrMsr %#RX32 -> #GP(0)\n", idMsr)); 147 NOREF(pRange); NOREF(uValue); 148 PVM pVM = pVCpu->CTX_SUFF(pVM); 149 PGIMHV pHv = &pVM->gim.s.u.Hv; 150 151 switch (idMsr) 152 { 153 case MSR_GIM_HV_GUEST_OS_ID: 154 { 155 #ifndef IN_RING3 156 return VERR_EM_INTERPRETER; 157 #else 158 /* Disable the hypercall-page if 0 is written to this MSR. */ 159 if (!uRawValue) 160 { 161 GIMR3Mmio2Unmap(pVM, &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]); 162 pHv->u64HypercallMsr &= ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT; 163 Log4Func(("Disabled hypercalls\n")); 164 } 165 pHv->u64GuestOsIdMsr = uRawValue; 166 return VINF_SUCCESS; 167 #endif /* !IN_RING3 */ 168 } 169 170 case MSR_GIM_HV_HYPERCALL: 171 { 172 #ifndef IN_RING3 173 return VERR_EM_INTERPRETER; 174 #else /* IN_RING3 */ 175 /* First, update all but the hypercall enable bit. */ 176 pHv->u64HypercallMsr = (uRawValue & ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT); 177 178 /* Hypercalls can only be enabled when the guest has set the Guest-OS Id Msr. */ 179 bool fEnable = RT_BOOL(uRawValue & MSR_GIM_HV_HYPERCALL_ENABLE_BIT); 180 if ( fEnable 181 && !pHv->u64GuestOsIdMsr) 182 { 183 return VINF_SUCCESS; 184 } 185 186 PPDMDEVINSR3 pDevIns = pVM->gim.s.pDevInsR3; 187 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 188 AssertPtr(pDevIns); 189 AssertPtr(pRegion); 190 191 /* 192 * Is the guest disabling the hypercall-page? Allow it regardless of the Guest-OS Id Msr. 193 */ 194 if (!fEnable) 195 { 196 GIMR3Mmio2Unmap(pVM, pRegion); 197 pHv->u64HypercallMsr = uRawValue; 198 Log4Func(("Disabled hypercalls\n")); 199 return VINF_SUCCESS; 200 } 201 202 /* 203 * Map the hypercall-page. 204 */ 205 RTGCPHYS GCPhysHypercallPage = MSR_GIM_HV_HYPERCALL_GUEST_PFN(uRawValue) << PAGE_SHIFT; 206 int rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysHypercallPage, "Hyper-V Hypercall-page"); 207 if (RT_SUCCESS(rc)) 208 { 209 /* 210 * Patch the hypercall-page. 211 */ 212 if (HMIsEnabled(pVM)) 213 { 214 size_t cbWritten = 0; 215 rc = HMPatchHypercall(pVM, pRegion->pvPageR3, PAGE_SIZE, &cbWritten); 216 if ( RT_SUCCESS(rc) 217 && cbWritten < PAGE_SIZE - 1) 218 { 219 uint8_t *pbLast = (uint8_t *)pRegion->pvPageR3 + cbWritten; 220 *pbLast = 0xc3; /* RET */ 221 222 pHv->u64HypercallMsr = uRawValue; 223 LogRelFunc(("Enabled hypercalls at %#RGp\n", GCPhysHypercallPage)); 224 LogRelFunc(("%.*Rhxd\n", cbWritten + 1, (uint8_t *)pRegion->pvPageR3)); 225 return VINF_SUCCESS; 226 } 227 228 LogFunc(("MSR_GIM_HV_HYPERCALL: HMPatchHypercall failed. rc=%Rrc cbWritten=%u\n", rc, cbWritten)); 229 } 230 else 231 { 232 /** @todo Handle raw-mode hypercall page patching. */ 233 LogRelFunc(("MSR_GIM_HV_HYPERCALL: raw-mode not yet implemented!\n")); 234 } 235 236 GIMR3Mmio2Unmap(pVM, pRegion); 237 } 238 else 239 LogFunc(("MSR_GIM_HV_HYPERCALL: GIMR3Mmio2Map failed. rc=%Rrc -> #GP(0)\n", rc)); 240 241 return VERR_CPUM_RAISE_GP_0; 242 #endif /* !IN_RING3 */ 243 } 244 245 case MSR_GIM_HV_REF_TSC: 246 { 247 #ifndef IN_RING3 248 return VERR_EM_INTERPRETER; 249 #else /* IN_RING3 */ 250 /* First, update all but the TSC-page enable bit. */ 251 pHv->u64TscPageMsr = (uRawValue & ~MSR_GIM_HV_REF_TSC_ENABLE_BIT); 252 253 PPDMDEVINSR3 pDevIns = pVM->gim.s.pDevInsR3; 254 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; 255 AssertPtr(pDevIns); 256 AssertPtr(pRegion); 257 258 /* 259 * Is the guest disabling the TSC-page? 260 */ 261 bool fEnable = RT_BOOL(uRawValue & MSR_GIM_HV_REF_TSC_ENABLE_BIT); 262 if (!fEnable) 263 { 264 GIMR3Mmio2Unmap(pVM, pRegion); 265 Log4Func(("Disabled TSC-page\n")); 266 return VINF_SUCCESS; 267 } 268 269 /* 270 * Map the TSC-page. 271 */ 272 RTGCPHYS GCPhysTscPage = MSR_GIM_HV_REF_TSC_GUEST_PFN(uRawValue) << PAGE_SHIFT; 273 int rc = GIMR3Mmio2Map(pVM, pRegion, GCPhysTscPage, "Hyper-V TSC-page"); 274 if (RT_SUCCESS(rc)) 275 { 276 pHv->u64TscPageMsr = uRawValue; 277 Log4Func(("MSR_GIM_HV_REF_TSC: Enabled Hyper-V TSC page at %#RGp\n", GCPhysTscPage)); 278 return VINF_SUCCESS; 279 } 280 else 281 LogFunc(("MSR_GIM_HV_REF_TSC: GIMR3Mmio2Map failed. rc=%Rrc -> #GP(0)\n", rc)); 282 283 return VERR_CPUM_RAISE_GP_0; 284 #endif /* !IN_RING3 */ 285 } 286 287 case MSR_GIM_HV_TIME_REF_COUNT: /* Read-only MSRs. */ 288 case MSR_GIM_HV_VP_INDEX: 289 case MSR_GIM_HV_TSC_FREQ: 290 case MSR_GIM_HV_APIC_FREQ: 291 LogFunc(("WrMsr on read-only MSR %#RX32 -> #GP(0)\n", idMsr)); 292 return VERR_CPUM_RAISE_GP_0; 293 294 default: 295 #ifdef IN_RING3 296 static uint32_t s_cTimes = 0; 297 if (s_cTimes++ < 20) 298 LogRel(("GIM: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr, uRawValue & UINT64_C(0xffffffff00000000), 299 uRawValue & UINT64_C(0xffffffff))); 300 #endif 301 LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue)); 302 break; 303 } 304 66 305 return VERR_CPUM_RAISE_GP_0; 67 306 } -
trunk/src/VBox/VMM/VMMAll/HMAll.cpp
r47619 r51560 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 38 38 39 39 40 41 40 /** 42 41 * Checks whether HM (VT-x/AMD-V) is being used by this VM. … … 79 78 } 80 79 80 81 81 /** 82 82 * Invalidates a guest page … … 103 103 } 104 104 105 105 106 /** 106 107 * Flushes the guest TLB. … … 118 119 } 119 120 121 120 122 #ifdef IN_RING0 121 122 123 /** 123 124 * Dummy RTMpOnSpecific handler since RTMpPokeCpu couldn't be used. … … 173 174 } 174 175 } 175 176 176 #endif /* IN_RING0 */ 177 178 177 179 #ifndef IN_RC 178 179 180 /** 180 181 * Poke an EMT so it can perform the appropriate TLB shootdowns. … … 270 271 return VINF_SUCCESS; 271 272 } 272 273 273 #endif /* !IN_RC */ 274 274 … … 448 448 } 449 449 450 451 /** 452 * Patches the instructions necessary for making a hypercall to the hypervisor. 453 * Used by GIM. 454 * 455 * @returns VBox status code. 456 * @param pVM Pointer to the VM. 457 * @param pvBuf The buffer in the hypercall page(s) to be patched. 458 * @param cbBuf The size of the buffer. 459 * @param pcbWritten Where to store the number of bytes patched. This 460 * is reliably updated only when this function returns 461 * VINF_SUCCESS. 462 */ 463 VMM_INT_DECL(int) HMPatchHypercall(PVM pVM, void *pvBuf, size_t cbBuf, size_t *pcbWritten) 464 { 465 AssertReturn(pvBuf, VERR_INVALID_POINTER); 466 AssertReturn(pcbWritten, VERR_INVALID_POINTER); 467 AssertReturn(HMIsEnabled(pVM), VERR_HM_IPE_5); 468 469 if (pVM->hm.s.vmx.fSupported) 470 { 471 uint8_t abHypercall[] = { 0x0F, 0x01, 0xC1 }; /* VMCALL */ 472 if (RT_LIKELY(cbBuf >= sizeof(abHypercall))) 473 { 474 memcpy(pvBuf, abHypercall, sizeof(abHypercall)); 475 *pcbWritten = sizeof(abHypercall); 476 return VINF_SUCCESS; 477 } 478 return VERR_BUFFER_OVERFLOW; 479 } 480 else 481 { 482 Assert(pVM->hm.s.svm.fSupported); 483 uint8_t abHypercall[] = { 0x0F, 0x01, 0xD9 }; /* VMMCALL */ 484 if (RT_LIKELY(cbBuf >= sizeof(abHypercall))) 485 { 486 memcpy(pvBuf, abHypercall, sizeof(abHypercall)); 487 *pcbWritten = sizeof(abHypercall); 488 return VINF_SUCCESS; 489 } 490 return VERR_BUFFER_OVERFLOW; 491 } 492 } 493 -
trunk/src/VBox/VMM/VMMR0/HMR0.cpp
r51433 r51560 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 15 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 16 */ 17 18 17 19 18 /******************************************************************************* … … 1229 1228 1230 1229 /** 1231 * Does Ring-0 perVM HM initialization.1230 * Does ring-0 per-VM HM initialization. 1232 1231 * 1233 1232 * This will copy HM global into the VM structure and call the CPU specific … … 1298 1297 1299 1298 /** 1300 * Does Ring-0 per VM HM termination.1299 * Does ring-0 per VM HM termination. 1301 1300 * 1302 1301 * @returns VBox status code. … … 1461 1460 { 1462 1461 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 1463 VMCPU_ASSERT_EMT_RETURN(pVCpu, VERR_HM_WRONG_CPU _1);1462 VMCPU_ASSERT_EMT_RETURN(pVCpu, VERR_HM_WRONG_CPU); 1464 1463 1465 1464 RTCPUID idCpu = RTMpCpuId(); -
trunk/src/VBox/VMM/VMMR3/GIM.cpp
r51367 r51560 28 28 * A GIM provider implements a particular hypervisor interface such as Microsoft 29 29 * Hyper-V, Linux KVM and so on. It hooks into various components in the VMM to 30 * ease the guest in running under a recognized, virtualized environment. This 31 * is also referred to as paravirtualization interfaces. 32 * 33 * The idea behind this is primarily for making guests more accurate and 34 * efficient when operating in a virtualized environment. 35 * 36 * For instance, a guest when interfaced to VirtualBox through a GIM provider 37 * may rely on the provider (and VirtualBox ultimately) for providing the 38 * correct TSC frequency and may therefore not have to caliberate the TSC 39 * itself, resulting in higher accuracy and saving several CPU cycles. 30 * ease the guest in running under a recognized, virtualized environment. 31 * 32 * If the GIM provider configured for the VM needs to be recognized by the guest 33 * OS inorder to make use of features supported by the interface. Since it 34 * requires co-operation from the guest OS, a GIM provider is also referred to 35 * as a paravirtualization interface. 36 * 37 * One of the ideas behind this, is primarily for making guests more accurate 38 * and efficient when operating in a virtualized environment. For instance, a 39 * guest OS which interfaces to VirtualBox through a GIM provider may rely on 40 * the provider (and VirtualBox ultimately) for providing the correct TSC 41 * frequency of the host processor and may therefore not have to caliberate the 42 * TSC itself, resulting in higher accuracy and saving several CPU cycles. 40 43 * 41 44 * At most, only one GIM provider can be active for a running VM and cannot be … … 52 55 #include <VBox/vmm/hm.h> 53 56 #include <VBox/vmm/ssm.h> 57 #include <VBox/vmm/pdmdev.h> 54 58 55 59 #include <iprt/err.h> … … 140 144 { 141 145 LogRel(("GIM: Provider \"%s\" unknown.\n", szProvider)); 142 rc = VERR_ NOT_SUPPORTED;146 rc = VERR_GIM_INVALID_PROVIDER; 143 147 } 144 148 } 145 149 return rc; 146 150 } 151 152 #if 0 153 VMM_INT_DECL(int) GIMR3InitFinalize(PVM pVM) 154 { 155 LogFlow(("GIMR3InitFinalize\n")); 156 157 if (!pVM->gim.s.fEnabled) 158 return VINF_SUCCESS; 159 160 switch (pVM->gim.s.enmProviderId) 161 { 162 case GIMPROVIDERID_MINIMAL: 163 { 164 GIMR3MinimalInitFinalize(pVM); 165 break; 166 } 167 168 case GIMPROVIDERID_HYPERV: 169 { 170 GIMR3HvInitFinalize(pVM); 171 break; 172 } 173 174 case GIMPROVIDERID_KVM: /** @todo KVM. */ 175 default: 176 { 177 AssertMsgFailed(("Invalid provider Id %#x\n", pVM->gim.s.enmProviderId)); 178 break; 179 } 180 } 181 } 182 #endif 147 183 148 184 … … 233 269 } 234 270 271 272 /** 273 * The VM is being reset. 274 * 275 * For the GIM component this means unmapping and unregistering MMIO2 regions 276 * and other provider-specific resets. 277 * 278 * @returns VBox status code. 279 * @param pVM Pointer to the VM. 280 */ 281 VMMR3_INT_DECL(void) GIMR3Reset(PVM pVM) 282 { 283 if (!pVM->gim.s.fEnabled) 284 return; 285 286 switch (pVM->gim.s.enmProviderId) 287 { 288 case GIMPROVIDERID_HYPERV: 289 return GIMR3HvReset(pVM); 290 291 default: 292 break; 293 } 294 } 295 296 297 /** 298 * Registers the GIM device with VMM. 299 * 300 * @param pVM Pointer to the VM. 301 * @param pDevIns Pointer to the GIM device instance. 302 */ 303 VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns) 304 { 305 pVM->gim.s.pDevInsR3 = pDevIns; 306 } 307 308 309 /** 310 * Returns the array of MMIO2 regions that are expected to be registered and 311 * later mapped into the guest-physical address space for the GIM provider 312 * configured for the VM. 313 * 314 * @returns Pointer to an array of GIM MMIO2 regions, may return NULL. 315 * @param pVM Pointer to the VM. 316 * @param pcRegions Where to store the number of items in the array. 317 * 318 * @remarks The caller does not own and therefore must -NOT- try to free the 319 * returned pointer. 320 */ 321 VMMR3DECL(PGIMMMIO2REGION) GIMR3GetMmio2Regions(PVM pVM, uint32_t *pcRegions) 322 { 323 Assert(pVM); 324 Assert(pcRegions); 325 326 *pcRegions = 0; 327 if (!pVM->gim.s.fEnabled) 328 return NULL; 329 330 switch (pVM->gim.s.enmProviderId) 331 { 332 case GIMPROVIDERID_HYPERV: 333 return GIMR3HvGetMmio2Regions(pVM, pcRegions); 334 335 case GIMPROVIDERID_KVM: /** @todo KVM. */ 336 default: 337 break; 338 } 339 340 return NULL; 341 } 342 343 344 /** 345 * Unmaps a registered MMIO2 region in the guest address space and removes any 346 * access handlers for it. 347 * 348 * @returns VBox status code. 349 * @param pVM Pointer to the VM. 350 * @param pRegion Pointer to the GIM MMIO2 region. 351 */ 352 VMM_INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion) 353 { 354 AssertPtr(pVM); 355 AssertPtr(pRegion); 356 357 PPDMDEVINS pDevIns = pVM->gim.s.pDevInsR3; 358 AssertPtr(pDevIns); 359 if (pRegion->fMapped) 360 { 361 PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage); 362 int rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage); 363 if (RT_SUCCESS(rc)) 364 { 365 pRegion->fMapped = false; 366 pRegion->GCPhysPage = NIL_RTGCPHYS; 367 } 368 } 369 return VINF_SUCCESS; 370 } 371 372 373 /** 374 * Write access handler for a mapped MMIO2 region that presently ignores writes. 375 * 376 * @returns VBox status code. 377 * @param pVM Pointer to the VM. 378 * @param GCPhys The guest-physical address of the region. 379 * @param pvPhys Pointer to the region in the guest address space. 380 * @param pvBuf Pointer to the data being read/written. 381 * @param cbBuf The size of the buffer in @a pvBuf. 382 * @param enmAccessType The type of access. 383 * @param pvUser User argument (NULL, not used). 384 */ 385 static DECLCALLBACK(int) gimR3Mmio2PageWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, 386 PGMACCESSTYPE enmAccessType, void *pvUser) 387 { 388 /* 389 * Ignore writes to the mapped MMIO2 page. 390 */ 391 Assert(enmAccessType == PGMACCESSTYPE_WRITE); 392 return VINF_SUCCESS; /** @todo Hyper-V says we should #GP(0) fault for writes to the Hypercall and TSC page. */ 393 } 394 395 396 /** 397 * Maps a registered MMIO2 region in the guest address space. The region will be 398 * made read-only and writes from the guest will be ignored. 399 * 400 * @returns VBox status code. 401 * @param pVM Pointer to the VM. 402 * @param pRegion Pointer to the GIM MMIO2 region. 403 * @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) 407 { 408 PPDMDEVINS pDevIns = pVM->gim.s.pDevInsR3; 409 AssertPtr(pDevIns); 410 411 /* The guest-physical address must be page-aligned. */ 412 if (GCPhysRegion & PAGE_OFFSET_MASK) 413 { 414 LogFunc(("%s: %#RGp not paging aligned\n", pszDesc, GCPhysRegion)); 415 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS; 416 } 417 418 /* Allow only normal pages to be overlaid using our MMIO2 pages (disallow MMIO, ROM, reserved pages). */ 419 /** @todo Hyper-V doesn't seem to be very strict about this, may be relax 420 * later if some guest really requires it. */ 421 if (!PGMPhysIsGCPhysNormal(pVM, GCPhysRegion)) 422 { 423 LogFunc(("%s: %#RGp is not normal memory\n", pszDesc, GCPhysRegion)); 424 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS; 425 } 426 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. 435 */ 436 int rc = PDMDevHlpMMIO2Map(pDevIns, pRegion->iRegion, GCPhysRegion); 437 if (RT_SUCCESS(rc)) 438 { 439 /* 440 * Install access-handlers for the mapped page to prevent (ignore) writes to it from the guest. 441 */ 442 rc = PGMR3HandlerPhysicalRegister(pVM, 443 PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, 444 GCPhysRegion, GCPhysRegion + (pRegion->cbRegion - 1), 445 gimR3Mmio2PageWriteHandler, NULL /* pvUserR3 */, 446 NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */, 447 NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */, 448 pszDesc); 449 if (RT_SUCCESS(rc)) 450 { 451 pRegion->fMapped = true; 452 pRegion->GCPhysPage = GCPhysRegion; 453 return VINF_SUCCESS; 454 } 455 456 PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, GCPhysRegion); 457 } 458 459 return rc; 460 } 461 -
trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
r51367 r51560 20 20 *******************************************************************************/ 21 21 #define LOG_GROUP LOG_GROUP_GIM 22 #include "GIMHvInternal.h"23 22 #include "GIMInternal.h" 24 23 … … 26 25 #include <iprt/err.h> 27 26 #include <iprt/string.h> 27 #include <iprt/mem.h> 28 28 29 29 #include <VBox/vmm/cpum.h> … … 79 79 80 80 int rc; 81 #if 0 82 pVM->gim.s.pfnHypercallR3 = &GIMHvHypercall; 83 if (!HMIsEnabled(pVM)) 84 { 85 rc = PDMR3LdrGetSymbolRC(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallRC); 86 AssertRCReturn(rc, rc); 87 } 88 rc = PDMR3LdrGetSymbolR0(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallR0); 89 AssertRCReturn(rc, rc); 90 #endif 81 PGIMHV pHv = &pVM->gim.s.u.Hv; 91 82 92 83 /* 93 84 * Determine interface capabilities based on the version. 94 85 */ 95 uint32_t uBaseFeat = 0;96 uint32_t uPartFlags = 0;97 uint32_t uPowMgmtFeat = 0;98 uint32_t uMiscFeat = 0;99 uint32_t uHyperHints = 0;100 86 if (!pVM->gim.s.u32Version) 101 87 { 102 uBaseFeat = 0 103 //| GIM_HV_BASE_FEAT_VP_RUNTIME_MSR 104 | GIM_HV_BASE_FEAT_PART_REF_COUNT_MSR 105 //| GIM_HV_BASE_FEAT_BASIC_SYNTH_IC 106 //| GIM_HV_BASE_FEAT_SYNTH_TIMER_MSRS 107 //| GIM_HV_BASE_FEAT_APIC_ACCESS_MSRS 108 //| GIM_HV_BASE_FEAT_HYPERCALL_MSRS 109 | GIM_HV_BASE_FEAT_VP_ID_MSR 110 //| GIM_HV_BASE_FEAT_VIRT_SYS_RESET_MSR 111 //| GIM_HV_BASE_FEAT_STAT_PAGES_MSR 112 //| GIM_HV_BASE_FEAT_PART_REF_TSC_MSR 113 //| GIM_HV_BASE_FEAT_GUEST_IDLE_STATE_MSR 114 //| GIM_HV_BASE_FEAT_TIMER_FREQ_MSRS 115 //| GIM_HV_BASE_FEAT_DEBUG_MSRS 116 ; 117 118 pVM->gim.s.u.hv.u16HyperIdVersionMajor = VBOX_VERSION_MAJOR; 119 pVM->gim.s.u.hv.u16HyperIdVersionMajor = VBOX_VERSION_MINOR; 120 pVM->gim.s.u.hv.u32HyperIdBuildNumber = VBOX_VERSION_BUILD; 88 pHv->uBaseFeat = 0 89 //| GIM_HV_BASE_FEAT_VP_RUNTIME_MSR 90 | GIM_HV_BASE_FEAT_PART_TIME_REF_COUNT_MSR 91 //| GIM_HV_BASE_FEAT_BASIC_SYNTH_IC 92 //| GIM_HV_BASE_FEAT_SYNTH_TIMER_MSRS 93 //| GIM_HV_BASE_FEAT_APIC_ACCESS_MSRS 94 | GIM_HV_BASE_FEAT_HYPERCALL_MSRS 95 | GIM_HV_BASE_FEAT_VP_ID_MSR 96 //| GIM_HV_BASE_FEAT_VIRT_SYS_RESET_MSR 97 //| GIM_HV_BASE_FEAT_STAT_PAGES_MSR 98 | GIM_HV_BASE_FEAT_PART_REF_TSC_MSR 99 //| GIM_HV_BASE_FEAT_GUEST_IDLE_STATE_MSR 100 | GIM_HV_BASE_FEAT_TIMER_FREQ_MSRS 101 //| GIM_HV_BASE_FEAT_DEBUG_MSRS 102 ; 103 104 pHv->uMiscFeat = GIM_HV_MISC_FEAT_TIMER_FREQ; 105 } 106 107 /* 108 * Populate the required fields in MMIO2 region records for registering. 109 */ 110 AssertCompile(GIM_HV_PAGE_SIZE == PAGE_SIZE); 111 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; 112 pRegion->iRegion = GIM_HV_HYPERCALL_PAGE_REGION_IDX; 113 pRegion->cbRegion = PAGE_SIZE; 114 pRegion->GCPhysPage = NIL_RTGCPHYS; 115 RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "Hypercall Page"); 116 Assert(!pRegion->fRCMapping); 117 Assert(!pRegion->fMapped); 118 119 pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; 120 pRegion->iRegion = GIM_HV_REF_TSC_PAGE_REGION_IDX; 121 pRegion->cbRegion = PAGE_SIZE; 122 pRegion->GCPhysPage = NIL_RTGCPHYS; 123 RTStrCopy(pRegion->szDescription, sizeof(pRegion->szDescription), "TSC Page"); 124 125 /* 126 * Make sure the CPU ID bit are in accordance to the Hyper-V 127 * requirement and other paranoia checks. 128 * See "Requirements for implementing the Microsoft hypervisor interface" spec. 129 */ 130 Assert(!(pHv->uPartFlags & ( GIM_HV_PART_FLAGS_CREATE_PART 131 | GIM_HV_PART_FLAGS_ACCESS_MEMORY_POOL 132 | GIM_HV_PART_FLAGS_ACCESS_PART_ID 133 | GIM_HV_PART_FLAGS_ADJUST_MSG_BUFFERS 134 | GIM_HV_PART_FLAGS_CREATE_PORT 135 | GIM_HV_PART_FLAGS_ACCESS_STATS 136 | GIM_HV_PART_FLAGS_CPU_MGMT 137 | GIM_HV_PART_FLAGS_CPU_PROFILER))); 138 Assert((pHv->uBaseFeat & (GIM_HV_BASE_FEAT_HYPERCALL_MSRS | GIM_HV_BASE_FEAT_VP_ID_MSR)) 139 == (GIM_HV_BASE_FEAT_HYPERCALL_MSRS | GIM_HV_BASE_FEAT_VP_ID_MSR)); 140 for (unsigned i = 0; i < RT_ELEMENTS(pHv->aMmio2Regions); i++) 141 { 142 PCGIMMMIO2REGION pcCur = &pHv->aMmio2Regions[i]; 143 Assert(!pcCur->fRCMapping); 144 Assert(!pcCur->fMapped); 145 Assert(pcCur->GCPhysPage == NIL_RTGCPHYS); 121 146 } 122 147 … … 159 184 160 185 HyperLeaf.uLeaf = UINT32_C(0x40000003); 161 HyperLeaf.uEax = uBaseFeat;162 HyperLeaf.uEbx = uPartFlags;163 HyperLeaf.uEcx = uPowMgmtFeat;164 HyperLeaf.uEdx = uMiscFeat;186 HyperLeaf.uEax = pHv->uBaseFeat; 187 HyperLeaf.uEbx = pHv->uPartFlags; 188 HyperLeaf.uEcx = pHv->uPowMgmtFeat; 189 HyperLeaf.uEdx = pHv->uMiscFeat; 165 190 rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf); 166 191 AssertLogRelRCReturn(rc, rc); … … 169 194 * Insert all MSR ranges of Hyper-V. 170 195 */ 171 for (u int32_ti = 0; i < RT_ELEMENTS(g_aMsrRanges_HyperV); i++)196 for (unsigned i = 0; i < RT_ELEMENTS(g_aMsrRanges_HyperV); i++) 172 197 { 173 198 rc = CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_HyperV[i]); 174 199 AssertLogRelRCReturn(rc, rc); 175 200 } 201 176 202 return VINF_SUCCESS; 177 203 } 204 205 206 #if 0 207 VMMR3_INT_DECL(int) GIMR3HvInitFinalize(PVM pVM) 208 { 209 pVM->gim.s.pfnHypercallR3 = &GIMHvHypercall; 210 if (!HMIsEnabled(pVM)) 211 { 212 rc = PDMR3LdrGetSymbolRC(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallRC); 213 AssertRCReturn(rc, rc); 214 } 215 rc = PDMR3LdrGetSymbolR0(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallR0); 216 AssertRCReturn(rc, rc); 217 } 218 #endif 178 219 179 220 … … 186 227 } 187 228 229 230 /** 231 * The VM is being reset. This resets Hyper-V provider MSRs and unmaps whatever 232 * Hyper-V regions that the guest may have mapped. 233 * 234 * @param pVM Pointer to the VM. 235 */ 236 VMMR3_INT_DECL(void) GIMR3HvReset(PVM pVM) 237 { 238 /* 239 * Unmap MMIO2 pages that the guest may have setup. 240 */ 241 PGIMHV pHv = &pVM->gim.s.u.Hv; 242 for (unsigned i = 0; i < RT_ELEMENTS(pHv->aMmio2Regions); i++) 243 { 244 PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[i]; 245 GIMR3Mmio2Unmap(pVM, pRegion); 246 } 247 248 /* 249 * Reset MSRs. 250 */ 251 pHv->u64GuestOsIdMsr = 0; 252 pHv->u64HypercallMsr = 0; 253 pHv->u64TscPageMsr = 0; 254 } 255 256 257 /** 258 * Returns a pointer to the MMIO2 regions supported by Hyper-V. 259 * 260 * @returns Pointer to an array of MMIO2 regions. 261 * @param pVM Pointer to the VM. 262 * @param pcRegions Where to store the number of regions in the array. 263 */ 264 VMMR3_INT_DECL(PGIMMMIO2REGION) GIMR3HvGetMmio2Regions(PVM pVM, uint32_t *pcRegions) 265 { 266 Assert(GIMIsEnabled(pVM)); 267 PGIMHV pHv = &pVM->gim.s.u.Hv; 268 269 *pcRegions = RT_ELEMENTS(pHv->aMmio2Regions); 270 Assert(*pcRegions <= UINT8_MAX); /* See PGMR3PhysMMIO2Register(). */ 271 return pHv->aMmio2Regions; 272 } 273 -
trunk/src/VBox/VMM/VMMR3/VM.cpp
r51367 r51560 986 986 if (RT_SUCCESS(rc)) 987 987 { 988 rc = PDMR3Init(pVM); 988 /* GIM must be init'd before PDM, DevGIM construction may 989 require GIM provider to be setup. */ 990 rc = GIMR3Init(pVM); 989 991 if (RT_SUCCESS(rc)) 990 992 { 991 /* GIM must be init'd after PDM, may rely on PDMR3 for 992 symbol resolution. */ 993 rc = GIMR3Init(pVM); 993 rc = PDMR3Init(pVM); 994 994 if (RT_SUCCESS(rc)) 995 995 { … … 1011 1011 rc = REMR3InitFinalize(pVM); 1012 1012 #endif 1013 1014 1013 if (RT_SUCCESS(rc)) 1015 1014 { … … 1025 1024 } 1026 1025 1027 int rc2 = GIMR3Term(pVM);1026 int rc2 = PDMR3Term(pVM); 1028 1027 AssertRC(rc2); 1029 1028 } 1030 int rc2 = PDMR3Term(pVM);1029 int rc2 = GIMR3Term(pVM); 1031 1030 AssertRC(rc2); 1032 1031 } … … 2798 2797 CSAMR3Reset(pVM); 2799 2798 #endif 2799 GIMR3Reset(pVM); /* This must come *before* PDM. */ 2800 2800 PDMR3Reset(pVM); 2801 2801 PGMR3Reset(pVM); -
trunk/src/VBox/VMM/include/GIMHvInternal.h
r51367 r51560 19 19 #define ___GIMHvInternal_h 20 20 21 #include <iprt/cdefs.h> 22 #include <VBox/types.h> 21 #include <VBox/vmm/gim.h> 23 22 #include <VBox/vmm/cpum.h> 24 23 25 24 /** @name Hyper-V base feature identification. 26 * Base features based on current partition privileges.25 * Features based on current partition privileges (per-VM). 27 26 * @{ 28 27 */ … … 30 29 #define GIM_HV_BASE_FEAT_VP_RUNTIME_MSR RT_BIT(0) 31 30 /** Partition reference counter MSR available. */ 32 #define GIM_HV_BASE_FEAT_PART_ REF_COUNT_MSRRT_BIT(1)31 #define GIM_HV_BASE_FEAT_PART_TIME_REF_COUNT_MSR RT_BIT(1) 33 32 /** Basic Synthetic Interrupt Controller MSRs available. */ 34 33 #define GIM_HV_BASE_FEAT_BASIC_SYNTH_IC RT_BIT(2) … … 49 48 /** Virtual guest idle state MSR available. */ 50 49 #define GIM_HV_BASE_FEAT_GUEST_IDLE_STATE_MSR RT_BIT(10) 51 /** Timer frequency MSRs available. */50 /** Timer frequency MSRs (TSC and APIC) available. */ 52 51 #define GIM_HV_BASE_FEAT_TIMER_FREQ_MSRS RT_BIT(11) 53 52 /** Debug MSRs available. */ … … 212 211 /** Per-VM reference counter (R) */ 213 212 #define MSR_GIM_HV_TIME_REF_COUNT UINT32_C(0x40000020) 214 /** Per-VM TSC (R) */213 /** Per-VM TSC page (R/W) */ 215 214 #define MSR_GIM_HV_REF_TSC UINT32_C(0x40000021) 216 215 /** Frequency of TSC in Hz as reported by the hypervisor (R) */ … … 390 389 AssertCompile(MSR_GIM_HV_RANGE11_START <= MSR_GIM_HV_RANGE11_END); 391 390 391 392 /** @name Hyper-V MSR - Hypercall (MSR_GIM_HV_HYPERCALL). 393 * @{ 394 */ 395 /** Guest-physical page frame number of the hypercall-page. */ 396 #define MSR_GIM_HV_HYPERCALL_GUEST_PFN(a) ((a) >> 12) 397 /** The hypercall enable bit. */ 398 #define MSR_GIM_HV_HYPERCALL_ENABLE_BIT RT_BIT_64(0) 399 /** Whether the hypercall-page is enabled or not. */ 400 #define MSR_GIM_HV_HYPERCALL_IS_ENABLED(a) RT_BOOL((a) & MSR_GIM_HV_HYPERCALL_ENABLE_BIT) 401 /** @} */ 402 403 /** @name Hyper-V MSR - Reference TSC (MSR_GIM_HV_REF_TSC). 404 * @{ 405 */ 406 /** Guest-physical page frame number of the TSC-page. */ 407 #define MSR_GIM_HV_REF_TSC_GUEST_PFN(a) ((a) >> 12) 408 /** The TSC-page enable bit. */ 409 #define MSR_GIM_HV_REF_TSC_ENABLE_BIT RT_BIT_64(0) 410 /** Whether the TSC-page is enabled or not. */ 411 #define MSR_GIM_HV_REF_TSC_IS_ENABLED(a) RT_BOOL((a) & MSR_GIM_HV_REF_TSC_ENABLE_BIT) 412 /** @} */ 413 414 /** Hyper-V page size. */ 415 #define GIM_HV_PAGE_SIZE 0x1000 416 417 /** 418 * MMIO2 region indices. 419 */ 420 /** The hypercall page region. */ 421 #define GIM_HV_HYPERCALL_PAGE_REGION_IDX UINT8_C(0) 422 /** The TSC page region. */ 423 #define GIM_HV_REF_TSC_PAGE_REGION_IDX UINT8_C(1) 424 /** The maximum region index (must be <= UINT8_MAX). */ 425 #define GIM_HV_REGION_IDX_MAX GIM_HV_REF_TSC_PAGE_REGION_IDX 426 427 /** 428 * Hyper-V TSC (HV_REFERENCE_TSC_PAGE) structure placed in the TSC reference 429 * page. 430 */ 431 typedef struct GIMHVREFTSC 432 { 433 uint32_t volatile u32TscSequence; 434 uint32_t uReserved0; 435 uint64_t volatile u64TscScale; 436 uint64_t volatile u64TscOffset; 437 } GIMHVTSCPAGE; 438 /** Pointer to GIM VMCPU instance data. */ 439 typedef GIMHVREFTSC *PGIMHVREFTSC; 440 441 /** 442 * GIM Hyper-V VM Instance data. 443 * Changes to this must checked against the padding of the gim union in VM! 444 */ 445 typedef struct GIMHV 446 { 447 /** Guest OS identity MSR. */ 448 uint64_t u64GuestOsIdMsr; 449 /** Hypercall MSR. */ 450 uint64_t u64HypercallMsr; 451 /** Reference TSC page MSR. */ 452 uint64_t u64TscPageMsr; 453 454 /** Basic features. */ 455 uint32_t uBaseFeat; 456 /** Partition flags. */ 457 uint32_t uPartFlags; 458 /** Power management features. */ 459 uint32_t uPowMgmtFeat; 460 /** Miscellaneous features. */ 461 uint32_t uMiscFeat; 462 /** Hypervisor hints. */ 463 uint32_t uHyperHints; 464 /** Alignment padding. */ 465 uint32_t u32Alignment0; 466 467 /** Array of MMIO2 regions. */ 468 GIMMMIO2REGION aMmio2Regions[GIM_HV_REGION_IDX_MAX + 1]; 469 } GIMHV; 470 /** Pointer to per-VM GIM Hyper-V instance data. */ 471 typedef GIMHV *PGIMHV; 472 /** Pointer to const per-VM GIM Hyper-V instance data. */ 473 typedef GIMHV const *PCGIMHV; 474 AssertCompileMemberAlignment(GIMHV, aMmio2Regions, 8); 475 392 476 RT_C_DECLS_BEGIN 477 478 #ifdef IN_RING0 479 VMMR0_INT_DECL(int) GIMR0HvInitVM(PVM pVM); 480 VMMR0_INT_DECL(int) GIMR0HvTermVM(PVM pVM); 481 #endif /* IN_RING0 */ 393 482 394 483 #ifdef IN_RING3 395 484 VMMR3_INT_DECL(int) GIMR3HvInit(PVM pVM); 396 485 VMMR3_INT_DECL(void) GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta); 486 VMMR3_INT_DECL(void) GIMR3HvReset(PVM pVM); 487 VMMR3_INT_DECL(PGIMMMIO2REGION) GIMR3HvGetMmio2Regions(PVM pVM, uint32_t *pcRegions); 397 488 #endif /* IN_RING3 */ 398 489 490 VMMDECL(int) GIMHvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset); 399 491 VMMDECL(int) GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx); 400 492 VMMDECL(int) GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue); -
trunk/src/VBox/VMM/include/GIMInternal.h
r51333 r51560 20 20 21 21 #include <VBox/vmm/gim.h> 22 #include "GIMHvInternal.h" 22 23 23 24 RT_C_DECLS_BEGIN … … 42 43 uint32_t u32Version; 43 44 45 /** Pointer to the GIM device - ring-3 context. */ 46 R3PTRTYPE(PPDMDEVINS) pDevInsR3; 44 47 #if 0 45 48 /** Pointer to the provider's ring-3 hypercall handler. */ … … 67 70 union 68 71 { 69 struct 70 { 71 } minimal; 72 73 struct 74 { 75 /** Hypervisor system identity - Minor version number. */ 76 uint16_t u16HyperIdVersionMinor; 77 /** Hypervisor system identity - Major version number. */ 78 uint16_t u16HyperIdVersionMajor; 79 /** Hypervisor system identify - Build number. */ 80 uint32_t u32HyperIdBuildNumber; 81 82 /** Guest OS identity MSR. */ 83 uint64_t u64GuestOsIdMsr; 84 /** Reference TSC page MSR. */ 85 uint64_t u64TscPageMsr; 86 } hv; 72 GIMHV Hv; 87 73 88 74 /** @todo KVM and others. */ … … 102 88 typedef GIMCPU *PGIMCPU; 103 89 104 105 #ifdef IN_RING0 106 #endif /* IN_RING0 */ 90 #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); 93 #endif /* IN_RING3 */ 107 94 108 95 /** @} */
Note:
See TracChangeset
for help on using the changeset viewer.