Explicitly check page boundaries when adding bootloader-provided memory regions

This commit is contained in:
Josh Holtrop 2021-08-16 17:35:11 -04:00
parent ebfeca47b5
commit 6b1de7c9d4
2 changed files with 38 additions and 18 deletions

View File

@ -1,15 +1,15 @@
#include "mm.h" #include "mm.h"
#define PAGE_SIZE 4096u
typedef struct mm_page_entry_s { typedef struct mm_page_entry_s {
size_t count; size_t count;
struct mm_page_entry_s * next; struct mm_page_entry_s * next;
} mm_region_entry_t; } mm_region_entry_t;
static mm_region_entry_t * mm_next_free_region; static mm_region_entry_t * mm_next_free_region;
static size_t mm_free_page_count; static size_t mm_free_pages;
static size_t mm_total_ram; static size_t mm_total_ram;
static size_t kernel_start_address;
static size_t kernel_size;
extern uint8_t _hos_mem_start; extern uint8_t _hos_mem_start;
extern uint8_t _hos_mem_end; extern uint8_t _hos_mem_end;
@ -22,12 +22,11 @@ static void mm_add_ram_region(size_t base, size_t size)
region->next = mm_next_free_region; region->next = mm_next_free_region;
mm_next_free_region = region; mm_next_free_region = region;
mm_total_ram += size; mm_total_ram += size;
mm_free_page_count = pages; mm_free_pages = pages;
} }
void mm_register_ram_region(uint64_t base, size_t size) void mm_register_ram_region(uint64_t base, size_t size)
{ {
size &= ~(PAGE_SIZE - 1u);
/* Ignore any RAM region above 4GB. */ /* Ignore any RAM region above 4GB. */
if (base >= 0x100000000ull) if (base >= 0x100000000ull)
{ {
@ -37,34 +36,43 @@ void mm_register_ram_region(uint64_t base, size_t size)
{ {
size = (size_t)(0x100000000ull - base); size = (size_t)(0x100000000ull - base);
} }
size_t end_address = mm_page_floor((size_t)base + size);
size_t start_address = mm_page_ceil(base);
size = end_address - start_address;
if (size < PAGE_SIZE)
{
return;
}
size_t kernel_end_address = kernel_start_address + kernel_size;
/* Add regions before and after kernel RAM. */ /* Add regions before and after kernel RAM. */
size_t region_base = (size_t)base; if (start_address < kernel_start_address)
if (region_base < (size_t)&_hos_mem_start)
{ {
/* RAM region begins before kernel RAM. */ /* RAM region begins before kernel RAM. */
size_t this_sz = size; size_t this_sz = size;
if ((region_base + this_sz) > (size_t)&_hos_mem_start) if ((start_address + this_sz) > kernel_start_address)
{ {
this_sz = (size_t)&_hos_mem_start - region_base; this_sz = kernel_start_address - start_address;
} }
mm_add_ram_region(region_base, this_sz); mm_add_ram_region(start_address, this_sz);
} }
if ((region_base + size) > (size_t)&_hos_mem_end) if ((start_address + size) > kernel_end_address)
{ {
/* RAM region ends after kernel RAM. */ /* RAM region ends after kernel RAM. */
size_t this_sz = size; size_t this_sz = size;
if (region_base < (size_t)&_hos_mem_end) if (start_address < kernel_end_address)
{ {
this_sz = (region_base + size) - (size_t)&_hos_mem_end; this_sz = (start_address + size) - kernel_end_address;
region_base = (size_t)&_hos_mem_end; start_address = kernel_end_address;
} }
mm_add_ram_region(region_base, this_sz); mm_add_ram_region(start_address, this_sz);
} }
} }
void mm_init(void) void mm_init(void)
{ {
mm_total_ram = mm_get_kernel_size();; kernel_start_address = mm_page_floor((size_t)&_hos_mem_start);
kernel_size = mm_page_ceil((size_t)&_hos_mem_end - kernel_start_address);
mm_total_ram = kernel_size;
} }
size_t mm_get_total_ram(void) size_t mm_get_total_ram(void)
@ -74,10 +82,10 @@ size_t mm_get_total_ram(void)
size_t mm_get_kernel_address(void) size_t mm_get_kernel_address(void)
{ {
return (size_t)&_hos_mem_start; return kernel_start_address;
} }
size_t mm_get_kernel_size(void) size_t mm_get_kernel_size(void)
{ {
return &_hos_mem_end - &_hos_mem_start; return kernel_size;
} }

View File

@ -4,6 +4,18 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define PAGE_SIZE 4096u
static inline size_t mm_page_floor(size_t bytes)
{
return bytes & ~(PAGE_SIZE - 1u);
}
static inline size_t mm_page_ceil(size_t bytes)
{
return (bytes + PAGE_SIZE - 1u) & ~(PAGE_SIZE - 1u);
}
void mm_init(void); void mm_init(void);
void mm_register_ram_region(uint64_t base, size_t size); void mm_register_ram_region(uint64_t base, size_t size);
size_t mm_get_total_ram(void); size_t mm_get_total_ram(void);