VirtualBox

Changeset 22613 in vbox


Ignore:
Timestamp:
Aug 31, 2009 3:40:33 PM (15 years ago)
Author:
vboxsync
Message:

Runtime/r0drv/linux: introduced hack to properly map pages on PAE systems without remap_pfn_range()

File:
1 edited

Legend:

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

    r22531 r22613  
    6262#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
    6363# define VBOX_USE_INSERT_PAGE
     64#endif
     65#if    defined(CONFIG_X86_PAE) \
     66    && (   HAVE_26_STYLE_REMAP_PAGE_RANGE \
     67        || (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE <  KERNEL_VERSION(2, 6, 11)))
     68# define VBOX_USE_PAE_HACK
    6469#endif
    6570
     
    11471152
    11481153
     1154#ifdef VBOX_USE_PAE_HACK
     1155/**
     1156 * Replace the PFN of a PTE entry of a reserved page. This hack is required for older Linux
     1157 * kernels which don't provide remap_pfn_range().
     1158 */
     1159static int fixPte(struct mm_struct *mm, unsigned long ulAddr, unsigned long long u64Phys)
     1160{
     1161    int rc = -ENOMEM;
     1162    pgd_t *pgd;
     1163
     1164    spin_lock(&mm->page_table_lock);
     1165
     1166    pgd = pgd_offset(mm, ulAddr);
     1167    if (!pgd_none(*pgd) && !pgd_bad(*pgd))
     1168    {
     1169        pmd_t *pmd = pmd_offset(pgd, ulAddr);
     1170        if (!pmd_none(*pmd))
     1171        {
     1172            pte_t *ptep = pte_offset_map(pmd, ulAddr);
     1173            if (ptep)
     1174            {
     1175                pte_t pte = *ptep;
     1176                pte.pte_high &= 0xfff00000;
     1177                pte.pte_high |= ((u64Phys >> 32) & 0x000fffff);
     1178                pte.pte_low  &= 0x00000fff;
     1179                pte.pte_low  |= (u64Phys & 0xfffff000);
     1180                set_pte(ptep, pte);
     1181                pte_unmap(ptep);
     1182                rc = 0;
     1183            }
     1184        }
     1185    }
     1186
     1187    spin_unlock(&mm->page_table_lock);
     1188    return rc;
     1189}
     1190#endif /* VBOX_USE_PAE_HACK */
     1191
     1192
    11491193int rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
    11501194{
     
    11841228            const size_t    cPages = pMemLnxToMap->Core.cb >> PAGE_SHIFT;
    11851229            size_t          iPage;
     1230#ifdef VBOX_USE_PAE_HACK
     1231            struct page     *pDummyPage = alloc_page(GFP_USER);
     1232            RTHCPHYS        DummyPhys;
     1233
     1234            if (!pDummyPage)
     1235                goto error;
     1236
     1237            SetPageReserved(pDummyPage);
     1238            DummyPhys = page_to_phys(pDummyPage);
     1239#endif
    11861240            rc = 0;
    11871241            if (pMemLnxToMap->cPages)
     
    11901244                {
    11911245#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
    1192                     uint64_t u64Phys = page_to_phys(pMemLnxToMap->apPages[iPage]);
     1246                    RTHCPHYS Phys = page_to_phys(pMemLnxToMap->apPages[iPage]);
    11931247#endif
    11941248#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
     
    11961250                    AssertBreakStmt(vma, rc = VERR_INTERNAL_ERROR);
    11971251#endif
    1198 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) && defined(RT_ARCH_X86)
     1252#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86)
    11991253                    /* remap_page_range() limitation on x86 */
    12001254                    AssertBreakStmt(u64Phys < _4G, rc = VERR_NO_MEMORY);
     
    12061260#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
    12071261                    rc = remap_pfn_range(vma, ulAddrCur, page_to_pfn(pMemLnxToMap->apPages[iPage]), PAGE_SIZE, fPg);
    1208 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
     1262#elif defined(VBOX_USE_PAE_HACK)
    12091263                    rc = remap_page_range(vma, ulAddrCur, u64Phys, PAGE_SIZE, fPg);
     1264                    if (rc)
     1265                    {
     1266                        rc = VERR_NO_MEMORY;
     1267                        break;
     1268                    }
     1269                    rc = fixPte(pTask->mm, ulAddrCur, u64Phys);
    12101270#else /* 2.4 */
    12111271                    rc = remap_page_range(ulAddrCur, u64Phys, PAGE_SIZE, fPg);
    12121272#endif
    12131273                    if (rc)
     1274                    {
     1275                        rc = VERR_NO_MEMORY;
    12141276                        break;
     1277                    }
    12151278                }
    12161279            }
     
    12351298                        AssertBreakStmt(vma, rc = VERR_INTERNAL_ERROR);
    12361299#endif
    1237 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) && defined(RT_ARCH_X86)
     1300#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86)
    12381301                        /* remap_page_range() limitation on x86 */
    12391302                        AssertBreakStmt(Phys < _4G, rc = VERR_NO_MEMORY);
     
    12421305#if   LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
    12431306                        rc = remap_pfn_range(vma, ulAddrCur, Phys, PAGE_SIZE, fPg);
    1244 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(HAVE_26_STYLE_REMAP_PAGE_RANGE)
    1245                         rc = remap_page_range(vma, ulAddrCur, Phys, PAGE_SIZE, fPg);
     1307#elif defined(VBOX_USE_PAE_HACK)
     1308                        rc = remap_page_range(vma, ulAddrCur, DummyPhys, PAGE_SIZE, fPg);
     1309                        if (rc)
     1310                        {
     1311                            rc = VERR_NO_MEMORY;
     1312                            break;
     1313                        }
     1314                        rc = fixPte(pTask->mm, ulAddrCur, Phys);
    12461315#else /* 2.4 */
    12471316                        rc = remap_page_range(ulAddrCur, Phys, PAGE_SIZE, fPg);
    12481317#endif
    12491318                        if (rc)
     1319                        {
     1320                            rc = VERR_NO_MEMORY;
    12501321                            break;
     1322                        }
    12511323                    }
    12521324                }
    12531325            }
     1326#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) && defined(CONFIG_X86_PAE)
     1327            __free_page(pDummyPage);
     1328#endif
    12541329            if (!rc)
    12551330            {
     
    12701345        }
    12711346
     1347#ifdef VBOX_USE_PAE_HACK
     1348error:
     1349#endif
    12721350        up_write(&pTask->mm->mmap_sem);
    12731351
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