92 lines
2.3 KiB
C
92 lines
2.3 KiB
C
#include "mm.h"
|
|
|
|
typedef struct mm_page_entry_s {
|
|
size_t count;
|
|
struct mm_page_entry_s * next;
|
|
} mm_region_entry_t;
|
|
|
|
static mm_region_entry_t * mm_next_free_region;
|
|
static size_t mm_free_pages;
|
|
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_end;
|
|
|
|
static void mm_add_ram_region(size_t base, size_t size)
|
|
{
|
|
mm_region_entry_t * region = (mm_region_entry_t *)base;
|
|
size_t pages = size / PAGE_SIZE;
|
|
region->count = pages;
|
|
region->next = mm_next_free_region;
|
|
mm_next_free_region = region;
|
|
mm_total_ram += size;
|
|
mm_free_pages = pages;
|
|
}
|
|
|
|
void mm_register_ram_region(uint64_t base, size_t size)
|
|
{
|
|
/* Ignore any RAM region above 4GB. */
|
|
if (base >= 0x100000000ull)
|
|
{
|
|
return;
|
|
}
|
|
if ((base + size) > 0x100000000ull)
|
|
{
|
|
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. */
|
|
if (start_address < kernel_start_address)
|
|
{
|
|
/* RAM region begins before kernel RAM. */
|
|
size_t this_sz = size;
|
|
if ((start_address + this_sz) > kernel_start_address)
|
|
{
|
|
this_sz = kernel_start_address - start_address;
|
|
}
|
|
mm_add_ram_region(start_address, this_sz);
|
|
}
|
|
if ((start_address + size) > kernel_end_address)
|
|
{
|
|
/* RAM region ends after kernel RAM. */
|
|
size_t this_sz = size;
|
|
if (start_address < kernel_end_address)
|
|
{
|
|
this_sz = (start_address + size) - kernel_end_address;
|
|
start_address = kernel_end_address;
|
|
}
|
|
mm_add_ram_region(start_address, this_sz);
|
|
}
|
|
}
|
|
|
|
void mm_init(void)
|
|
{
|
|
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)
|
|
{
|
|
return mm_total_ram;
|
|
}
|
|
|
|
size_t mm_get_kernel_address(void)
|
|
{
|
|
return kernel_start_address;
|
|
}
|
|
|
|
size_t mm_get_kernel_size(void)
|
|
{
|
|
return kernel_size;
|
|
}
|