Austin Shafer

home contact

FreeBSD Memory Management Notes

Random notes on virtual memory and allocation functions

The FreeBSD virtual memory system is quite powerful and complicated. Additionally there are many unspoken rules of which functions to use for which task. This document serves as a collection of such functions and how they fit into the greater picture. It is not comprehensive.

The best description of any FreeBSD kernel subsystem can usually be found in "The Design and Implementation of the FreeBSD Operating System". The book goes into far more depth (particularly of the zone allocator).

Kernel malloc(9)

This is the generic memory management interface for kernel programming. It's easy to use and is similar to userland malloc, with the addition of a type field. The type is used to track related allocations, and the debugging kernel options will print warnings when memory of that allocation type is leaked during kernel module unloading.

uma(9)

The zone allocator, also known as the uniform memory allocator. It is well suited for allocating many objects of the same size. It has a rich interface for allocation, and UMA zones can be seen in the vmstat command.

Virtual Memory Interface

This is not even close to comprehensive, it is meant to be a collection of my notes about methods that weren't as widely documented as other parts of the kernel.

Virtual pages are kept track of by vm_page_t structures (struct vm_page). The system initializes pages for memory available in the system in sys/vm/vm_init. vm_page_t's are added to vm_object_t's which record memory regions in a virtual address space. I'm going to end up leaving a lot of functions out, I'll only include the ones I didn't readily find online or in books.

vmem_alloc(9)

Allocates space in the virtual memory space given. Useful for reserving portions of the kernel virtual address space(kva) so that vm_page_t's can be mapped into kva. Doesn't actually allocate memory, just a virtual address region.

vm_phys_fictitious_reg_range

vm_page_t's for device memory are given the PG_FICTITIOUS flag. This flag signifies a fake page and is treated differently by the subsystem (its wire count stays at 1 for example). This function initializes a range of vm_page_t's as fictitous pages, which can then be used by device drivers to back page requests and such. An example is initializing pages for a framebuffer which will be mapped into a processes address space.

PHYS_TO_VM_PAGE

This finds the vm_page_t corresponding to the physical address given. VM_TO_PHYS_PAGE basically does the opposite. Problems with this usually result from not calling vm_phys_fictitious_reg_rang (and maybe pmap_qenter) beforehand. Despite being in all caps it is not a macro.

pmap(9) module

The pmap module is architecture specific, and performs low level memory functions like adding a page table entry to the appropriate table. The man pages are quite good for this module, and the book fills in any remaining holes.

The pmap layer's job is to abstract away all aspects of the physical page mappings. It maintains the page/directory tables used by the hardware and exposes a machine-independent interface to manipulate physical mappings. This makes porting to new architectures much easier and keeps the common bits of the virtual memory system readable.

pmap_qenter(9)

This maps wired pages into KVA. From reading source code it is usually paired with vmem_alloc, as it requires a virtual address to map the physical pages to. It's opposite is pmap_qremove. sys/arm/nvidia/drm2/tegra_bo.c has a good example of this.