sp1: mm: Add pageframe allocation groundwork

This is mostly complete and would just need some spinlocks introduced
eventually before we get to multiprocessing.

Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
2026-04-18 21:05:37 -04:00
parent 9dfb6d9e2b
commit 182b080957
2 changed files with 170 additions and 0 deletions
+152
View File
@@ -12,9 +12,13 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/units.h> #include <sys/units.h>
#include <mm/physmem.h> #include <mm/physmem.h>
#include <mm/vm.h>
#include <mu/param.h> #include <mu/param.h>
#include <lib/printf.h> #include <lib/printf.h>
#include <os/bpt.h> #include <os/bpt.h>
#include <string.h>
#define MEM_SCAN_START 0x00100000
#define pr_trace(fmt, ...) \ #define pr_trace(fmt, ...) \
printf("physseg: " fmt, ##__VA_ARGS__) printf("physseg: " fmt, ##__VA_ARGS__)
@@ -45,6 +49,11 @@ static const char *typetab[] = {
static uintptr_t highest_usable; static uintptr_t highest_usable;
static size_t mem_total = 0; static size_t mem_total = 0;
static size_t mem_usable = 0; static size_t mem_usable = 0;
static size_t bitmap_size = 0;
static size_t last_idx = 0;
static size_t bitmap_free_start = 0;
static size_t highest_frame_idx = 0;
static uint8_t *bitmap;
static inline void static inline void
physmem_print_size(const char *title, size_t len) physmem_print_size(const char *title, size_t len)
@@ -62,6 +71,142 @@ physmem_print_size(const char *title, size_t len)
} }
} }
/*
* Populate physical memory bitmap.
*/
static void
physmem_bitmap_fill(void)
{
struct mem_entry entry;
status_t status;
for (size_t i = 0;; ++i) {
status = bpt_mem_entry_i(i, &entry);
/* Are there no more entries? */
if (status != STATUS_SUCCESS) {
break;
}
if (entry.base < MEM_SCAN_START) {
continue;
}
if (bitmap_free_start == 0) {
bitmap_free_start = entry.base / PAGESIZE;
}
for (size_t j = 0; j < entry.length; j += PAGESIZE) {
CLRBIT(bitmap, (entry.base + j) / PAGESIZE);
}
}
}
/*
* Allocate memory used for the bitmap
*/
static void
physmem_bitmap_alloc(void)
{
struct mem_entry entry;
status_t status;
for (size_t i = 0;; ++i) {
status = bpt_mem_entry_i(i, &entry);
/* Are there no more entries? */
if (status != STATUS_SUCCESS) {
break;
}
if (entry.type != MEMORY_USABLE) {
continue;
}
if (entry.length < bitmap_size) {
continue;
}
bitmap = pma_to_vma(entry.length);
memset(bitmap, 0xFFFFFFFF, bitmap_size);
break;
}
physmem_bitmap_fill();
}
/*
* Allocate page frames.
*
* @count: Number of frames to allocate.
*/
static uintptr_t
__physmem_alloc_frame(size_t count)
{
size_t frames = 0;
ssize_t idx = -1;
uintptr_t ret = 0;
for (size_t i = last_idx; i < highest_frame_idx; ++i) {
if (!TESTBIT(bitmap, i)) {
if (idx < 0)
idx = i;
if (++frames >= count)
break;
continue;
}
idx = -1;
frames = 0;
}
if (idx < 0 || frames != count) {
ret = 0;
goto done;
}
for (size_t i = idx; i < idx + count; ++i) {
SETBIT(bitmap, i);
}
ret = idx * PAGESIZE;
last_idx = idx;
memset(pma_to_vma(ret), 0, count * PAGESIZE);
done:
return ret;
}
uintptr_t
mm_physmem_alloc(size_t count)
{
uintptr_t ret;
if (count == 0) {
return 0;
}
if ((ret = __physmem_alloc_frame(count)) == 0) {
last_idx = 0;
ret = __physmem_alloc_frame(count);
}
return ret;
}
/*
* Central frame freeing routine
*/
void
pmm_free_frame(uintptr_t base, size_t count)
{
size_t stop_at = base + (count * PAGESIZE);
base = ALIGN_UP(base, PAGESIZE);
for (uintptr_t p = base; p < stop_at; p += PAGESIZE) {
CLRBIT(bitmap, p / PAGESIZE);
}
}
/* /*
* Begin scanning physical memory for usable entries * Begin scanning physical memory for usable entries
* and other information * and other information
@@ -102,10 +247,17 @@ physmem_probe(void)
mem_usable += entry.length; mem_usable += entry.length;
} }
/* Obtain the size of the bitmap */
highest_frame_idx = highest_usable / PAGESIZE;
bitmap_size = highest_frame_idx / 8;
/* Print memory stats */ /* Print memory stats */
pr_trace("begin stats\n"); pr_trace("begin stats\n");
physmem_print_size("usable", mem_usable); physmem_print_size("usable", mem_usable);
physmem_print_size("total", mem_total); physmem_print_size("total", mem_total);
/* Allocate a new bitmap */
physmem_bitmap_alloc();
} }
void void
+18
View File
@@ -12,9 +12,27 @@
#ifndef _MM_PHYSMEM_H_ #ifndef _MM_PHYSMEM_H_
#define _MM_PHYSMEM_H_ 1 #define _MM_PHYSMEM_H_ 1
#include <sys/types.h>
/* /*
* Initialize the physical memory management * Initialize the physical memory management
*/ */
void mm_physmem_init(void); void mm_physmem_init(void);
/*
* Allocate one or more frames and return the page
* aligned base
*
* @count: Number of frames to allocate
*/
uintptr_t mm_physmem_alloc(size_t count);
/*
* Free one or more physical memory frames
*
* @base: Memory base to free at
* @count: Number of frames to free
*/
void mm_physmem_free(uintptr_t base, size_t count);
#endif /* !_MM_PHYSMEM_H_ */ #endif /* !_MM_PHYSMEM_H_ */