Skip to content

vmalloc() and vmap()

Purpose

vmalloc() allocates virtually contiguous kernel memory.

Unlike kmalloc(), which requires physically contiguous pages, vmalloc() allocates individual pages from the Buddy Allocator and maps them into a contiguous virtual address range.

This allows the kernel to allocate large memory regions even when physical memory is fragmented.

Besides vmalloc(), Linux also provides vmap(), which creates a virtually contiguous mapping from an existing array of physical pages instead of allocating new pages.

Both APIs build virtually contiguous kernel virtual memory while differing in how the backing pages are managed.


Memory Layout

Virtual Address Space

+-----------+
|  Page 0   | ─────────────► PFN 12
+-----------+
|  Page 1   | ─────────────► PFN 87
+-----------+
|  Page 2   | ─────────────► PFN 35
+-----------+
|  Page 3   | ─────────────► PFN 201
+-----------+

Virtual Memory
    Contiguous

Physical Memory
    Non-contiguous

Relationship with Buddy Allocator

Each page mapped by vmalloc() is allocated independently from the Buddy Allocator.

vmalloc()


    ├── alloc_pages(order = 0)
    ├── alloc_pages(order = 0)
    ├── alloc_pages(order = 0)
    └── alloc_pages(order = 0)



Create Virtual Mapping



Return Virtual Address

Since every page is allocated independently, the backing physical pages do not need to be contiguous.


vmap()

Unlike vmalloc(), vmap() does not allocate physical pages.

Instead, it creates a virtually contiguous mapping for pages that already exist. The caller supplies an array of struct page *, and vmap() builds a contiguous virtual address range that maps those pages.

Caller

alloc_pages()
alloc_pages()
alloc_pages()



     vmap()



Create Virtual Mapping



Return Virtual Address

The caller still owns the backing pages. Removing the mapping with vunmap() does not free those pages.


Address Translation

The kernel can translate a virtual address back to its backing page by using vmalloc_to_page().

Virtual Address



Locate vmalloc area



Calculate page index



struct page



Physical Frame Number (PFN)

Advantages

  • Supports large kernel allocations.
  • Does not require contiguous physical memory.
  • Works even when physical memory is fragmented.
  • Simplifies allocation of large software buffers.

Limitations

  • Slightly slower than kmalloc().
  • Requires page table mappings.
  • Physical pages are scattered, making it unsuitable for hardware that requires contiguous DMA buffers.

Typical Use Cases

  • Large kernel buffers
  • Large lookup tables
  • Software-managed memory pools
  • Kernel data structures that do not require physically contiguous memory

Ownership Comparison

The main difference between vmalloc() and vmap() is ownership of the backing pages.

API Allocates Pages Owns Pages Removes Mapping Frees Pages
vmalloc() Yes Yes vfree() vfree()
vmap() No No vunmap() Caller
vmalloc()


alloc_pages()



Virtual Mapping


vfree()



Mapping removed
Pages freed

======================

Caller

alloc_pages()



vmap()



Virtual Mapping


vunmap()



Mapping removed

Caller

free_pages()

Comparison

Item kmalloc() vmalloc() vmap()
Virtual Address Contiguous Contiguous Contiguous
Physical Memory Contiguous Not required Determined by caller
Backing Allocation SLUB Buddy + Page Mapping Existing Pages
Allocation Unit Object Individual Pages Existing Pages
Suitable for DMA Yes Generally No Depends on backing pages
Allocation Speed Faster Slower Faster than vmalloc() (no page allocation)