Day93 - vmalloc() Internals¶
Goal¶
Understand how vmalloc() provides virtually contiguous memory by mapping multiple independent physical pages allocated from the Buddy Allocator.
Build a userspace simulator that models the core concepts behind the Linux kernel vmalloc() implementation, including virtual address allocation, page mapping, address translation, and memory release.
What I Learned¶
Virtual vs Physical Memory¶
Unlike kmalloc(), which requires physically contiguous memory, vmalloc() allocates individual pages from the Buddy Allocator and maps them into a contiguous virtual address range.
This allows large memory allocations without requiring contiguous physical memory.
Virtual Address Space
0x10000000
│
▼
+-----------+
| Page 0 | ───────────────► PFN 1
+-----------+
| Page 1 | ───────────────► PFN 3
+-----------+
| Page 2 | ───────────────► PFN 8
+-----------+
| Page 3 | ───────────────► PFN 2
+-----------+
Virtual Address
Contiguous
Physical Pages
Non-contiguous
vmalloc Architecture¶
The simulator is built on top of the existing memory subsystem:
Each vmalloc() allocation creates a virtual memory area that records:
- Virtual address
- Requested size
- Number of mapped pages
- Backing
struct pagearray
Address Translation¶
The simulator implements vmalloc_to_page() to translate any virtual address inside a vmalloc area into its corresponding backing page.
Translation consists of:
- Locate the containing vmalloc area.
- Calculate the page offset.
- Convert the offset into a page index.
- Return the mapped
struct page.
Memory Lifecycle¶
Each vmalloc area owns its backing pages.
vmalloc()
│
▼
alloc_pages(order = 0)
│
▼
Create vmalloc_area
│
▼
Return virtual address
...
vfree()
│
▼
free_pages()
│
▼
Remove vmalloc_area
Labs¶
Lab 1 - Basic Allocation and Free¶
Verified:
vmalloc()vfree()- Virtual address allocation
- Page count calculation
- Area removal
- Memory cleanup
Lab 2 - Virtual Address Translation¶
Implemented and verified:
vmalloc_to_page()- Page index calculation
- Address boundary handling
- Invalid address detection
Lab 3 - Physically Non-contiguous Pages¶
Created fragmented physical memory by reserving Buddy pages before calling vmalloc().
Verified that:
- Virtual addresses remain contiguous.
- Physical pages are not contiguous.
- Address translation still returns the correct backing pages.
Lab 4 - Linux Kernel Verification¶
Verified the simulator against the real Linux kernel using:
vmalloc()vmalloc_to_page()page_to_pfn()vfree()
Observed that:
- Virtual addresses increase by one
PAGE_SIZE. - Physical page frame numbers (PFNs) are not necessarily contiguous.
- The Raspberry Pi 5 kernel uses a 16 KiB page size, while the simulator uses 4 KiB pages. Although the page size differs, the address translation principle remains identical.
APIs¶
Memory Management¶
vmalloc()vfree()vmalloc_to_page()
Buddy Allocator¶
alloc_pages()free_pages()
Learning Summary¶
Today I implemented a simplified version of the Linux kernel vmalloc() subsystem.
Unlike kmalloc(), which depends on physically contiguous memory, vmalloc() builds a contiguous virtual address space by mapping independently allocated physical pages.
The simulator demonstrates the complete lifecycle of a vmalloc allocation, including virtual address management, page mapping, address translation, and memory release. The behavior was further verified using a real Linux kernel module, confirming that contiguous virtual addresses can be backed by non-contiguous physical pages.