/** * Frees memory allocated using RTMemContAlloc(). * * @param pv Pointer to return from RTMemContAlloc(). * @param cb The cb parameter passed to RTMemContAlloc(). */ RTR0DECL(void) RTMemContFree(void *pv, size_t cb) { if (pv) { int cOrder; unsigned cPages; unsigned iPage; struct page *paPages; IPRT_LINUX_SAVE_EFL_AC(); /* validate */ AssertMsg(!((uintptr_t)pv & PAGE_OFFSET_MASK), ("pv=%p\n", pv)); Assert(cb > 0); /* calc order and get pages */ cb = RT_ALIGN_Z(cb, PAGE_SIZE); cPages = cb >> PAGE_SHIFT; cOrder = CalcPowerOf2Order(cPages); paPages = virt_to_page(pv); /* * Restore page attributes freeing the pages. */ for (iPage = 0; iPage < cPages; iPage++) { ClearPageReserved(&paPages[iPage]); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 20) /** @todo find the exact kernel where change_page_attr was introduced. */ MY_SET_PAGES_NOEXEC(&paPages[iPage], 1); #endif } __free_pages(paPages, cOrder); IPRT_LINUX_RESTORE_EFL_AC(); } }
/** * Frees the physical pages allocated by the rtR0MemObjLinuxAllocPages() call. * * This method does NOT free the object. * * @param pMemLnx The object which physical pages should be freed. */ static void rtR0MemObjLinuxFreePages(PRTR0MEMOBJLNX pMemLnx) { size_t iPage = pMemLnx->cPages; if (iPage > 0) { /* * Restore the page flags. */ while (iPage-- > 0) { ClearPageReserved(pMemLnx->apPages[iPage]); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22) #else MY_SET_PAGES_NOEXEC(pMemLnx->apPages[iPage], 1); #endif } /* * Free the pages. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22) if (!pMemLnx->fContiguous) { iPage = pMemLnx->cPages; while (iPage-- > 0) __free_page(pMemLnx->apPages[iPage]); } else #endif __free_pages(pMemLnx->apPages[0], rtR0MemObjLinuxOrder(pMemLnx->cPages)); pMemLnx->cPages = 0; } }