Stealing memory from the mmap to init phys alloc

This commit is contained in:
Thomas Oltmann 2025-03-18 03:59:48 +01:00
parent 4556fd1eed
commit a250490e69
2 changed files with 44 additions and 18 deletions

View file

@ -36,6 +36,7 @@
#include "x86_64/mem.h"
#include "bootboot.h"
#include "ram.h"
#include "pci.h"
#include "std.h"
#include "tar.h"
@ -84,6 +85,7 @@ struct mem_range range_ptr[10];
* Entry point, called by BOOTBOOT Loader *
******************************************/
void _start() {
ram_init();
/*** NOTE: this code runs on all cores in parallel ***/
unsigned info[4];

View file

@ -26,7 +26,6 @@ struct free_block {
};
struct ram_layer {
uint64_t total_blocks;
uint64_t first_free;
bitmap *avail_bitmap;
bitmap *frag_bitmap;
@ -230,25 +229,10 @@ ram_free_frame(frame_addr frame)
free_block(frame.base);
}
static void
ram_alloc_datastructures()
{
#if 0
uint64_t neededBytes = 0;
for (unsigned level = 0; level < ram_num_levels; level++) {
neededBytes += 2 * BITMAP_SIZE();
}
for (unsigned level = 0; level < ram_num_levels; level++) {
}
#endif
}
// Find largest memory address available
static uint64_t
ram_find_addr_limit(void)
{
// Find largest memory address available
uint64_t addrLimit = 0;
MMapEnt *ment = &bootboot.mmap;
while ((uint64_t)ment < (uint64_t)&bootboot + bootboot.size) {
@ -256,14 +240,44 @@ ram_find_addr_limit(void)
uint64_t length = MMapEnt_Size(ment); // in bytes
uint64_t end = start + length;
if (addrLimit < end) addrLimit = end;
printf("%x %p %lu\n", MMapEnt_Type(ment), (void *)start, length);
ment++;
}
return addrLimit;
}
// Find largest contiguous free range
static MMapEnt *
ram_find_donor_range(void)
{
MMapEnt *donor = NULL;
MMapEnt *ment = &bootboot.mmap;
for (; (uint64_t)ment < (uint64_t)&bootboot + bootboot.size; ment++) {
if (!MMapEnt_IsFree(ment)) continue;
if (!donor || MMapEnt_Size(donor) < MMapEnt_Size(ment)) {
donor = ment;
}
}
return donor;
}
static void *
ram_steal_memory(MMapEnt *donor, size_t nbytes)
{
nbytes = (nbytes + 15) & 0xFFFFFFFFFFFFFFF0ul;
printf("ram_steal_memory: donor size = %lu, nbytes = %lu\n", MMapEnt_Size(donor), nbytes);
ASSERT(MMapEnt_Size(donor) >= nbytes);
donor->size -= nbytes;
uint64_t addr = donor->ptr + donor->size;
return (void *)addr;
}
void
ram_init(void)
{
MMapEnt *donor = ram_find_donor_range();
ASSERT(donor != NULL);
// Calculate how many levels we need
uint64_t addrLimit = ram_find_addr_limit();
addrLimit = next_pow2(addrLimit);
@ -272,8 +286,18 @@ ram_init(void)
}
ram_num_levels = __builtin_ffsl(addrLimit); // log2(addrLimit) + 1
ram_num_levels -= 12;
printf("addrLimit = %lu\n", addrLimit);
printf("ram_num_levels = %u\n", ram_num_levels);
ram_alloc_datastructures();
for (unsigned level = 0; level < ram_num_levels; level++) {
ram_layers[level].first_free = INVALID_FRAME_ADDR;
size_t bitmapSize = BITMAP_SIZE(1ul << (ram_num_levels - level - 1));
ram_layers[level].avail_bitmap = ram_steal_memory(donor, bitmapSize);
ram_layers[level].frag_bitmap = ram_steal_memory(donor, bitmapSize);
}
// Realign donor range to page boundaries
donor->size &= UINT64_C(0xFFFFFFFFFFFFF00F);
#if 0
// Mark all free memory blocks as available