Skip to content

Day94 - vmalloc() and vmap() Internals

Objectives

In this lab, we extend the virtual memory subsystem by introducing vmap() and vunmap().

Unlike vmalloc(), which allocates backing pages internally, vmap() creates a virtually contiguous mapping from an existing array of physical pages.

By the end of this lab, you will understand:

  • How Linux builds virtually contiguous memory.
  • The difference between page allocation and virtual mapping.
  • Why vmalloc() and vmap() share the same mapping subsystem.
  • The ownership model of backing physical pages.

Background

Linux provides multiple ways to obtain kernel memory.

kmalloc() allocates physically contiguous memory.

vmalloc() allocates individual physical pages and combines them into one virtually contiguous region.

vmap() performs only the second half of that work—it maps pages that already exist.

kmalloc()

Physical Memory

+-------------------------------+
| Contiguous Physical Pages     |
+-------------------------------+

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

vmalloc()

alloc_pages()

PFN 10
PFN 37
PFN 82
PFN 19



Virtual Mapping



Virtual Address

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

vmap()

Existing Pages

PFN 3
PFN 15
PFN 90
PFN 41



Virtual Mapping



Virtual Address

Lab 1 — Virtual Mapping Manager

The first step is to separate virtual mapping management from page allocation.

The mapping manager is responsible for:

  • allocating virtual addresses
  • storing mapping information
  • translating virtual addresses
  • releasing mappings

Both vmalloc() and vmap() share this subsystem.

vm_mapping_create()

vm_mapping_destroy()

vm_mapping_to_page()

vm_mapping_destroy_all()

Verified:

  • Mapping creation
  • Address translation
  • Mapping removal
  • Multiple mappings
  • Ownership handling

Lab 2 — vmalloc()

vmalloc() performs two operations.

alloc_pages()



Create Virtual Mapping



Return Virtual Address

When vfree() is called:

Remove Mapping



Release Pages

The caller does not manage the backing pages directly.


Lab 3 — Physically Non-contiguous Pages

To demonstrate virtual mapping, physical memory was intentionally fragmented.

Example:

Virtual Address

0x10000000
0x10001000



PFN 1

PFN 3

Although the physical pages are scattered, the virtual address range remains completely contiguous.


Lab 4 — vmap()

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

Instead, the caller supplies an existing page array.

Caller

alloc_pages()



     vmap()



Virtual Mapping



Return Virtual Address

After calling vunmap():

  • the virtual mapping disappears
  • the backing pages remain allocated

The caller must eventually release those pages.


Lab 5 — Mixing vmalloc() and vmap()

The same virtual mapping manager can simultaneously manage:

  • vmalloc() mappings
  • vmap() mappings
vmalloc()


alloc_pages()



Owned Mapping

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

Caller

alloc_pages()



External Mapping

Different ownership leads to different cleanup behavior.

API Owns Pages Remove Mapping Release Pages
vmalloc() Yes vfree() vfree()
vmap() No vunmap() Caller

This ownership model is the primary difference between the two APIs.


Summary

In this lab we implemented a reusable virtual mapping subsystem shared by both vmalloc() and vmap().

The key takeaway is that virtual address mapping and physical page allocation are independent operations.

vmalloc() performs both allocation and mapping.

vmap() performs only mapping.

Understanding this separation makes it easier to understand how Linux manages large kernel memory regions and why different kernel subsystems can share the same virtual mapping infrastructure.