Changeset 104911 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jun 13, 2024 10:33:27 AM (8 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
r104796 r104911 2233 2233 * Perform the hypercall. 2234 2234 */ 2235 /** @todo r=bird: This is *nothing* like the microsoft description (2024-05-28). 2236 * https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercalls/hvextcallgetbootzeroedmemory 2237 * 2238 * It describes this as returning pages known to be all zeros at the time this 2239 * hypercall is made. What we return instead is a is a single entry: 2240 * GIMHVEXTGETBOOTZEROMEM::GCPhysStart = 0; 2241 * GIMHVEXTGETBOOTZEROMEM::cPages = SUM(PGMRAMRANGE.cb) >> GIM_HV_PAGE_SHIFT; 2242 * 2243 * This isn't right for any VM configuration, given that VGA & MMIO & ROM memory 2244 * starts at 0xa0000 and contains pages that aren't zero. For VM configurations 2245 * with more than 3GB (or 2) of memory, it doesn't take into account the RAM hole 2246 * below 4G. 2247 * 2248 * A much better approach for VMs with large configs, but still not really correct, 2249 * would be to find the highest RAM address (non-MMIO, non-MMIO2, non-ROM) and 2250 * convert it to a page count and assign that to cPages. 2251 * 2252 * A slight improvement would be to report two or three ranges: 2253 * [0] = 0x00000-0xa0000, 2254 * [1] = 1MB - RamHole, 2255 * [2] = 4GB - EndOfRam; 2256 * 2257 * The best would be to implement this directly PGM, as the number of mapped RAM 2258 * ranges doesn't need to be constant during the call if other VCPUs are 2259 * enabling/disabling devices and such. 2260 */ 2261 uint32_t const cRanges = PGMR3PhysGetRamRangeCount(pVM); 2262 pOut->cPages = 0; 2263 for (uint32_t iRange = 0; iRange < cRanges; iRange++) 2264 { 2265 RTGCPHYS GCPhysStart; 2266 RTGCPHYS GCPhysEnd; 2267 int rc = PGMR3PhysGetRange(pVM, iRange, &GCPhysStart, &GCPhysEnd, NULL /* pszDesc */, NULL /* fIsMmio */); 2268 if (RT_FAILURE(rc)) 2235 AssertCompileMembersSameSizeAndOffset(PGMPHYSRANGES, cRanges, GIMHVEXTGETBOOTZEROMEM, cRanges); 2236 AssertCompileMembersAtSameOffset(PGMPHYSRANGES, aRanges, GIMHVEXTGETBOOTZEROMEM, aRanges); 2237 AssertCompileMembersSameSizeAndOffset(PGMPHYSRANGE, GCPhysStart, GIMHVEXTMEMRANGE, GCPhysStart); 2238 AssertCompileMembersSameSizeAndOffset(PGMPHYSRANGE, cPages, GIMHVEXTMEMRANGE, cPages); 2239 AssertCompile(RT_ELEMENTS(pOut->aRanges) == GIM_HV_MAX_BOOT_ZEROED_MEM_RANGES); 2240 2241 int rcHv; 2242 int rc = PGMR3PhysGetRamBootZeroedRanges(pVM, (PPGMPHYSRANGES)pOut, RT_ELEMENTS(pOut->aRanges)); 2243 if ( RT_SUCCESS(rc) 2244 || rc == VERR_BUFFER_OVERFLOW) 2245 { 2246 /* 2247 * Update the guest memory with result. 2248 */ 2249 rc = PGMPhysSimpleWriteGCPhys(pVM, pHv->GCPhysHypercallOut, pHv->pbHypercallOut, sizeof(GIMHVEXTGETBOOTZEROMEM)); 2250 if (RT_SUCCESS(rc)) 2269 2251 { 2270 LogRelMax(10, ("GIM: HyperV: HvHypercallExtGetBootZeroedMem: PGMR3PhysGetRange failed for iRange(%u) rc=%Rrc\n", 2271 iRange, rc)); 2272 *prcHv = GIM_HV_STATUS_OPERATION_DENIED; 2273 return rc; 2252 LogRel(("GIM: HyperV: Queried boot zeroed guest memory as %u ranges\n", pOut->cRanges)); 2253 for (uint32_t i = 0; i < pOut->cRanges; i++) 2254 LogRel(("GIM: HyperV: RAM range [%u] from %#RGp to %#RGp (%u pages, %' Rhcb)\n", i, pOut->aRanges[i].GCPhysStart, 2255 pOut->aRanges[i].GCPhysStart + pOut->aRanges[i].cPages * GUEST_PAGE_SIZE - 1, pOut->aRanges[i].cPages, 2256 pOut->aRanges[i].cPages * GUEST_PAGE_SIZE)); 2257 rcHv = GIM_HV_STATUS_SUCCESS; 2274 2258 } 2275 2276 RTGCPHYS const cbRange = RT_ALIGN(GCPhysEnd - GCPhysStart + 1, GUEST_PAGE_SIZE); 2277 pOut->cPages += cbRange >> GIM_HV_PAGE_SHIFT; 2278 if (iRange == 0) 2279 pOut->GCPhysStart = GCPhysStart; 2280 } 2281 2282 /* 2283 * Update the guest memory with result. 2284 */ 2285 int rcHv; 2286 int rc = PGMPhysSimpleWriteGCPhys(pVM, pHv->GCPhysHypercallOut, pHv->pbHypercallOut, sizeof(GIMHVEXTGETBOOTZEROMEM)); 2287 if (RT_SUCCESS(rc)) 2288 { 2289 LogRel(("GIM: HyperV: Queried boot zeroed guest memory range (starting at %#RGp spanning %u pages) at %#RGp\n", 2290 pOut->GCPhysStart, pOut->cPages, pHv->GCPhysHypercallOut)); 2291 rcHv = GIM_HV_STATUS_SUCCESS; 2259 else 2260 { 2261 LogRelMax(10, ("GIM: HyperV: HvHypercallExtGetBootZeroedMem hypercall failed to update guest memory. rc=%Rrc\n", rc)); 2262 rcHv = GIM_HV_STATUS_OPERATION_DENIED; 2263 rc = VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED; 2264 } 2292 2265 } 2293 2266 else 2294 2267 { 2268 LogRelMax(10, ("GIM: HyperV: HvHypercallExtGetBootZeroedMem failed. rc=%Rrc\n", rc)); 2295 2269 rcHv = GIM_HV_STATUS_OPERATION_DENIED; 2296 LogRelMax(10, ("GIM: HyperV: HvHypercallExtGetBootZeroedMem failed to update guest memory. rc=%Rrc\n", rc)); 2297 rc = VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED; 2270 rc = VERR_GIM_HYPERCALL_FAILED; 2298 2271 } 2299 2272 -
trunk/src/VBox/VMM/include/GIMHvInternal.h
r99208 r104911 562 562 | MSR_GIM_HV_STIMER_SINTX) 563 563 /** @} */ 564 565 566 /** Hyper-V page size. */ 567 #define GIM_HV_PAGE_SIZE 4096 568 /** Hyper-V page shift. */ 569 #define GIM_HV_PAGE_SHIFT 12 570 571 /** Microsoft Hyper-V vendor signature. */ 572 #define GIM_HV_VENDOR_MICROSOFT "Microsoft Hv" 564 573 565 574 /** … … 1081 1090 1082 1091 /** 1083 * H vExtCallGetBootZeroedMemory hypercall output.1084 */ 1085 typedef struct GIMHVEXT GETBOOTZEROMEM1092 * Hyper-V memory range for HvExtCallGetBootZeroedMemory. 1093 */ 1094 typedef struct GIMHVEXTMEMRANGE 1086 1095 { 1087 1096 RTGCPHYS GCPhysStart; 1088 1097 uint64_t cPages; 1098 } GIMHVEXTMEMRANGE; 1099 1100 /** Maximum number of zeroed memory ranges supported by Hyper-V. */ 1101 #define GIM_HV_MAX_BOOT_ZEROED_MEM_RANGES 255 1102 1103 /** 1104 * HvExtCallGetBootZeroedMemory hypercall output. 1105 */ 1106 typedef struct GIMHVEXTGETBOOTZEROMEM 1107 { 1108 uint64_t cRanges; 1109 GIMHVEXTMEMRANGE aRanges[GIM_HV_MAX_BOOT_ZEROED_MEM_RANGES]; 1089 1110 } GIMHVEXTGETBOOTZEROMEM; 1090 1111 /** Pointer to a HvExtCallGetBootZeroedMemory output struct. */ 1091 1112 typedef GIMHVEXTGETBOOTZEROMEM *PGIMHVEXTGETBOOTZEROMEM; 1092 AssertCompileSize(GIMHVEXTGETBOOTZEROMEM, 16); 1093 /** @} */ 1094 1095 1096 /** Hyper-V page size. */ 1097 #define GIM_HV_PAGE_SIZE 4096 1098 /** Hyper-V page shift. */ 1099 #define GIM_HV_PAGE_SHIFT 12 1100 1101 /** Microsoft Hyper-V vendor signature. */ 1102 #define GIM_HV_VENDOR_MICROSOFT "Microsoft Hv" 1113 /** Pointer to a const HvExtCallGetBootZeroedMemory output struct. */ 1114 typedef GIMHVEXTGETBOOTZEROMEM const *PCGIMHVEXTGETBOOTZEROMEM; 1115 AssertCompileSize(GIMHVEXTGETBOOTZEROMEM, 4088); 1116 AssertCompile(sizeof(GIMHVEXTGETBOOTZEROMEM) <= GIM_HV_PAGE_SIZE); 1117 /** @} */ 1118 1103 1119 1104 1120 /**
Note:
See TracChangeset
for help on using the changeset viewer.