VirtualBox

Ignore:
Timestamp:
Jul 4, 2023 6:37:35 AM (23 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
158085
Message:

Runtime/RTR0MemObj*: Add PhysHighest parameter to RTR0MemObjAllocCont to indicate the maximum allowed physical address for an allocation, bugref:10457

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c

    r100319 r100355  
    149149/** Pointer to the linux memory object. */
    150150typedef RTR0MEMOBJLNX *PRTR0MEMOBJLNX;
     151
     152
     153/*********************************************************************************************************************************
     154*   Global Variables                                                                                                             *
     155*********************************************************************************************************************************/
     156/*
     157 * Linux allows only a coarse selection of zones for
     158 * allocations matching a particular maximum physical address.
     159 *
     160 * Sorted from high to low physical address!
     161 */
     162static const struct
     163{
     164    RTHCPHYS    PhysHighest;
     165    gfp_t       fGfp;
     166} g_aZones[] =
     167{
     168    { NIL_RTHCPHYS,      GFP_KERNEL },
     169#if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32)
     170    { _4G - 1,           GFP_DMA32  }, /* ZONE_DMA32: 0-4GB */
     171#elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
     172    { _4G - 1,           GFP_DMA    }, /* ZONE_DMA: 0-4GB */
     173#endif
     174#if defined(RT_ARCH_AMD64)
     175    { _16M - 1,          GFP_DMA    }, /* ZONE_DMA: 0-16MB */
     176#elif defined(RT_ARCH_X86)
     177    { 896 * _1M - 1,     GFP_USER   }, /* ZONE_NORMAL (32-bit hosts): 0-896MB */
     178#endif
     179};
    151180
    152181
     
    9721001
    9731002
    974 DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable, const char *pszTag)
     1003DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest,
     1004                                          bool fExecutable, const char *pszTag)
    9751005{
    9761006    IPRT_LINUX_SAVE_EFL_AC();
    9771007    PRTR0MEMOBJLNX pMemLnx;
    9781008    int rc;
    979 
    980 #if (defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32)
    981     /* ZONE_DMA32: 0-4GB */
    982     rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, GFP_DMA32,
    983                                    true /* contiguous */, fExecutable, VERR_NO_CONT_MEMORY, pszTag);
    984     if (RT_FAILURE(rc))
    985 #endif
    986 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64)
    987         /* ZONE_DMA: 0-16MB */
    988         rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, GFP_DMA,
     1009    uint32_t idxZone;
     1010
     1011    /*
     1012     * The last zone must be able to satisfy the PhysHighest requirement or there
     1013     * will be no zone at all.
     1014     */
     1015    if (g_aZones[RT_ELEMENTS(g_aZones) - 1].PhysHighest > PhysHighest)
     1016    {
     1017        IPRT_LINUX_RESTORE_EFL_AC();
     1018        AssertMsgFailedReturn(("No zone can satisfy PhysHighest=%RHp!\n", PhysHighest),
     1019                              VERR_NO_CONT_MEMORY);
     1020    }
     1021
     1022    /* Find the first zone matching our PhysHighest requirement. */
     1023    idxZone = 0;
     1024    for (;;)
     1025    {
     1026        if (g_aZones[idxZone].PhysHighest <= PhysHighest)
     1027            break; /* We found a zone satisfying the requirement. */
     1028        idxZone++;
     1029    }
     1030
     1031    /* Now try to allocate pages from all the left zones until one succeeds. */
     1032    for (;;)
     1033    {
     1034        rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, g_aZones[idxZone].fGfp,
    9891035                                       true /* contiguous */, fExecutable, VERR_NO_CONT_MEMORY, pszTag);
    990 #else
    991         /* ZONE_NORMAL (32-bit hosts): 0-896MB */
    992         rc = rtR0MemObjLinuxAllocPages(&pMemLnx, RTR0MEMOBJTYPE_CONT, cb, PAGE_SIZE, GFP_USER,
    993                                        true /* contiguous */, fExecutable, VERR_NO_CONT_MEMORY, pszTag);
    994 #endif
     1036        idxZone++;
     1037        if (RT_SUCCESS(rc) || idxZone == RT_ELEMENTS(g_aZones))
     1038            break;
     1039    }
    9951040    if (RT_SUCCESS(rc))
    9961041    {
     
    9981043        if (RT_SUCCESS(rc))
    9991044        {
    1000 #if defined(RT_STRICT) && (defined(RT_ARCH_AMD64) || defined(CONFIG_HIGHMEM64G))
     1045#if defined(RT_STRICT)
    10011046            size_t iPage = pMemLnx->cPages;
    10021047            while (iPage-- > 0)
    1003                 Assert(page_to_phys(pMemLnx->apPages[iPage]) < _4G);
     1048                Assert(page_to_phys(pMemLnx->apPages[iPage]) < PhysHighest);
    10041049#endif
    10051050            pMemLnx->Core.u.Cont.Phys = page_to_phys(pMemLnx->apPages[0]);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette