76 lines
2.1 KiB
C
76 lines
2.1 KiB
C
/* ### The flat memory model ###
|
|
|
|
under this memory model, the system memory is represented by
|
|
a single contiguous array of vm_pages. this array spans from
|
|
physical address up to the last available byte, as provided by
|
|
memblock. any extra reserved regions after the last available
|
|
byte will not be included to save memory.
|
|
|
|
this memory model is good for systems with a smaller amount of
|
|
physical memory that is mostly contiguous with few holes or
|
|
reserved regions. it is simpler and has less overhead.
|
|
|
|
for systems with a large amount of memory, or with large
|
|
amounts of reserved memory (especially those whose reserved
|
|
memory outstripts free memory), the sparse memory model may
|
|
be a better choice.
|
|
*/
|
|
#include <mango/vm.h>
|
|
#include <mango/memblock.h>
|
|
#include <mango/printk.h>
|
|
|
|
/* array of pages, one for each physical page frame present in RAM */
|
|
static struct vm_page *page_array = NULL;
|
|
|
|
/* number of pages stored in page_array */
|
|
static size_t page_array_count = 0;
|
|
|
|
void vm_flat_init(void)
|
|
{
|
|
printk("vm: using flat memory model");
|
|
size_t pmem_size = 0;
|
|
|
|
struct memblock_iter it;
|
|
for_each_free_mem_range (&it, 0x0, UINTPTR_MAX) {
|
|
if (pmem_size < it.it_limit + 1) {
|
|
pmem_size = it.it_limit + 1;
|
|
}
|
|
}
|
|
|
|
size_t nr_pages = pmem_size / VM_PAGE_SIZE;
|
|
if (pmem_size % VM_PAGE_SIZE) {
|
|
nr_pages++;
|
|
}
|
|
|
|
page_array = memblock_alloc(sizeof(struct vm_page) * nr_pages, 8);
|
|
page_array_count = nr_pages;
|
|
|
|
size_t nr_reserved = nr_pages;
|
|
|
|
for (size_t i = 0; i < nr_pages; i++) {
|
|
page_array[i].p_flags = VM_PAGE_RESERVED;
|
|
}
|
|
|
|
for_each_free_mem_range(&it, 0x0, UINTPTR_MAX) {
|
|
for (uintptr_t i = it.it_base; i < it.it_limit; i += VM_PAGE_SIZE) {
|
|
size_t pfn = i / VM_PAGE_SIZE;
|
|
|
|
page_array[pfn].p_flags = 0;
|
|
nr_reserved--;
|
|
}
|
|
}
|
|
|
|
printk("vm: page array has %zu pages, %zu reserved", nr_pages, nr_reserved);
|
|
}
|
|
|
|
struct vm_page *vm_page_get_flat(phys_addr_t addr)
|
|
{
|
|
size_t pfn = addr / VM_PAGE_SIZE;
|
|
return pfn < page_array_count ? &page_array[pfn] : NULL;
|
|
}
|
|
|
|
size_t vm_page_get_pfn_flat(struct vm_page *pg)
|
|
{
|
|
return ((uintptr_t)pg - (uintptr_t)page_array) / sizeof *pg;
|
|
}
|