Physical page allocator
From WhitixDoc
| |
memory/pg_alloc.c
| |
| The page allocator, which allocates physical pages for the virtual memory layer. |
| |
|
Whitix's physical page allocator allocates physical pages from an stacks of pages. The stack itself is allocated during the kernel's startup, and its size depends on the total amount of physical memory available.
Contents |
Overview
Virtual memory requires physical memory to work, and Whitix needs to allocate and free pages on demand. The physical page allocator stores two stacks of page structures after the kernel in memory (starting at 1MB; see line 51), one for ISA devices (such as the floppy), and one for normal pages.
The page structures, known as PhysPage, contain the address of the page, and the number of references to it. Functions such as PageAlloc() return a PhysPage structure, as some memory management code, such as the file memory mapper, need to keep track of references to a certain page.
Startup
Reserving areas of memory
When the architecture-specific code is setting up its idea of physical memory, it calls PageEarlyInit. This function constructs a bitmap right at the end of physical memory as a "reserved bitmap". (At this point in the kernel's startup process, there is a 1:1 mapping between virtual and physical memory.) This allows other parts of the kernel to reserve areas of physical memory below 16MB via PageReserveArea (which uses the code in lib/bitmap.c to alter the bitmap), so that they won't be allocated later.
PageEarlyInit reserves a number of areas common to several architectures, such as the first page of memory, the kernel code and data, and the memory for the page stacks, page structures and waitqueues. The reserved bitmap lasts until PageInit, so other architecture-specific functions have a chance to reserve parts of physical memory.
Stack creation
PageInit is called by the architecture-specific later on in kernel startup (typically at the end of ArchInit). Its main function is to create the page stacks, push unreserved pages onto them, and deallocate the reserved bitmap. Two stacks are created (see below), and BmapGetBit is used for the ISA stack to check if the page to be pushed has been reserved.
Once the stacks are created, the bitmap is destroyed, and the waitqueues are allocated and setup using INIT_WAITQUEUE_HEAD.
The page stacks
Types of stack
There are two stacks of physical pages in the Whitix virtual memory subsystem. One stack, which contains the free pages from 0 to 16MB, is for ISA DMA, which, due to hardware limitations, can only transfer to a physical address less than 16MB. Devices which use ISA DMA include floppy drives. The other stack is for all pages with a physical address of 16MB+, known as the normal page stack.
The stacks searched depend on the type of function called: normal page requests, from PageAlloc typically allocate from the normal page stack, and then from the ISA page stack, whereas ISA DMA requests, from PageAllocLow, can only be fulfilled by the ISA DMA stack.
Allocation
The stack keeps a head pointer to a linked list of pages. When a page is allocated to a caller and if the number of free pages is above zero, the PageAlloc functions get a pointer to the first page on the stack and remove it from the list.
When PageAlloc and PageAllocLow allocate a page, the number of free pages is updated. If it reaches zero in the normal page stack, PageAlloc calls PageAllocLow. If there are zero free pages in the ISA DMA stack, PageAllocLow panics and halts the kernel. (In future, the kernel should try to free up memory from the buffer cache).
Waitqueues
The stack structure also points to a list of waitqueues (which are located in memory after the PhysPage structures). The waitqueues are used by higher virtual memory code, such as the file memory mapping code, where operations on a shared page (such as reading in the page) need to be atomic (and so some processes have to wait for the operation to finish). One waitqueue is shared between 4MB worth of pages.