VirtualBox

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


Ignore:
Timestamp:
Jun 13, 2024 10:33:27 AM (8 months ago)
Author:
vboxsync
Message:

VMM/GIM: bugref:10703 Fix/re-implemented Hyper-V paravirt HvExtCallGetBootZeroedMemory hypercall to suit the latest (and actually used) Windows Hyper-V spec.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r104796 r104911  
    22332233     * Perform the hypercall.
    22342234     */
    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))
    22692251        {
    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;
    22742258        }
    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        }
    22922265    }
    22932266    else
    22942267    {
     2268        LogRelMax(10, ("GIM: HyperV: HvHypercallExtGetBootZeroedMem failed. rc=%Rrc\n", rc));
    22952269        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;
    22982271    }
    22992272
  • trunk/src/VBox/VMM/include/GIMHvInternal.h

    r99208 r104911  
    562562                                                   | MSR_GIM_HV_STIMER_SINTX)
    563563/** @} */
     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"
    564573
    565574/**
     
    10811090
    10821091/**
    1083  * HvExtCallGetBootZeroedMemory hypercall output.
    1084  */
    1085 typedef struct GIMHVEXTGETBOOTZEROMEM
     1092 * Hyper-V memory range for HvExtCallGetBootZeroedMemory.
     1093 */
     1094typedef struct GIMHVEXTMEMRANGE
    10861095{
    10871096    RTGCPHYS GCPhysStart;
    10881097    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 */
     1106typedef struct GIMHVEXTGETBOOTZEROMEM
     1107{
     1108    uint64_t            cRanges;
     1109    GIMHVEXTMEMRANGE    aRanges[GIM_HV_MAX_BOOT_ZEROED_MEM_RANGES];
    10891110} GIMHVEXTGETBOOTZEROMEM;
    10901111/** Pointer to a HvExtCallGetBootZeroedMemory output struct. */
    10911112typedef 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. */
     1114typedef GIMHVEXTGETBOOTZEROMEM const *PCGIMHVEXTGETBOOTZEROMEM;
     1115AssertCompileSize(GIMHVEXTGETBOOTZEROMEM, 4088);
     1116AssertCompile(sizeof(GIMHVEXTGETBOOTZEROMEM) <= GIM_HV_PAGE_SIZE);
     1117/** @} */
     1118
    11031119
    11041120/**
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