VirtualBox

Ignore:
Timestamp:
Jun 13, 2024 10:33:27 AM (7 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.

File:
1 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
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