[boot][kernel] Replace frame allocator with bitmap-based one

The previous frame allocator involved a lot of splitting and merging
linked lists and lost all information about frames while they were
allocated. The new allocator is based on an array of descriptor
structures and a bitmap. Each memory map region of allocatable memory
becomes one or more descriptors, each mapping up to 1GiB of physical
memory. The descriptors implement two levels of a bitmap tree, and have
a pointer into the large contiguous bitmap to track individual pages.
This commit is contained in:
Justin C. Miller
2021-01-22 00:16:01 -08:00
parent fd8552ca3a
commit aae18fd035
14 changed files with 419 additions and 212 deletions

View File

@@ -4,17 +4,21 @@
#include <stdint.h>
#include "kutil/linked_list.h"
struct frame_block;
using frame_block_list = kutil::linked_list<frame_block>;
namespace kernel {
namespace args {
struct frame_block;
}}
/// Allocator for physical memory frames
class frame_allocator
{
public:
/// Default constructor
frame_allocator();
using frame_block = kernel::args::frame_block;
/// Constructor
/// \arg blocks The bootloader-supplied frame bitmap block list
/// \arg count Number of entries in the block list
frame_allocator(frame_block *frames, size_t count);
/// Get free frames from the free list. Only frames from the first free block
/// are returned, so the number may be less than requested, but they will
@@ -29,26 +33,18 @@ public:
/// \arg count The number of frames to be freed
void free(uintptr_t address, size_t count);
/// Mark frames as used
/// \arg address The physical address of the first frame to free
/// \arg count The number of frames to be freed
void used(uintptr_t address, size_t count);
/// Get the global frame allocator
static frame_allocator & get();
private:
frame_block_list m_free; ///< Free frames list
frame_block *m_blocks;
long m_count;
frame_allocator() = delete;
frame_allocator(const frame_allocator &) = delete;
};
/// A block of contiguous frames. Each `frame_block` represents contiguous
/// physical frames with the same attributes.
struct frame_block
{
uintptr_t address;
uint32_t count;
/// Compare two blocks by address.
/// \arg rhs The right-hand comparator
/// \returns <0 if this is sorts earlier, >0 if this sorts later, 0 for equal
int compare(const frame_block &rhs) const;
};