diff --git a/include/socks/vm.h b/include/socks/vm.h index a748f95..e5a2da6 100644 --- a/include/socks/vm.h +++ b/include/socks/vm.h @@ -30,6 +30,11 @@ typedef struct vm_object { unsigned int reserved; } vm_object_t; +typedef enum vm_model { + VM_MODEL_FLAT = 1, + VM_MODEL_SPARSE, +} vm_model_t; + typedef enum vm_prot { VM_PROT_READ = 0x01u, VM_PROT_WRITE = 0x02u, @@ -207,6 +212,8 @@ typedef struct vm_page { } __attribute__((aligned(2 * sizeof(unsigned long)))) vm_page_t; extern kern_status_t vm_bootstrap(const vm_zone_descriptor_t *zones, size_t nr_zones); +extern vm_model_t vm_memory_model(void); +extern void vm_set_memory_model(vm_model_t model); extern vm_pg_data_t *vm_pg_data_get(vm_node_id_t node); @@ -247,4 +254,9 @@ extern void *kmalloc(size_t count, vm_flags_t flags); extern void *kzalloc(size_t count, vm_flags_t flags); extern void kfree(void *p); +/* Flat memory model functions */ +extern void vm_flat_init(void); +extern vm_page_t *vm_page_get_flat(phys_addr_t addr); +extern size_t vm_page_get_pfn_flat(vm_page_t *pg); + #endif diff --git a/vm/bootstrap.c b/vm/bootstrap.c index 5109a38..6549d02 100644 --- a/vm/bootstrap.c +++ b/vm/bootstrap.c @@ -18,7 +18,8 @@ kern_status_t vm_bootstrap(const vm_zone_descriptor_t *zones, size_t nr_zones) node_data = memblock_alloc(sizeof(vm_pg_data_t) * numa_count, 8); printk("vm: initialising %u node%s", numa_count, numa_count > 1 ? "s" : ""); - vm_page_init_array(); + vm_set_memory_model(VM_MODEL_FLAT); + vm_flat_init(); for (size_t i = 0; i < nr_zones; i++) { vm_zone_init(&node_data->pg_zones[zones[i].zd_id], &zones[i]); diff --git a/vm/flat.c b/vm/flat.c new file mode 100644 index 0000000..c67d32b --- /dev/null +++ b/vm/flat.c @@ -0,0 +1,58 @@ +#include +#include +#include + +/* array of pages, one for each physical page frame present in RAM */ +static vm_page_t *page_array = NULL; + +/* number of pages stored in page_array */ +static size_t page_array_count = 0; + +void vm_flat_init() +{ + printk("vm: using flat memory model"); + size_t pmem_size = 0; + + memblock_iter_t 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(vm_page_t) * 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); +} + +vm_page_t *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(vm_page_t *pg) +{ + return ((uintptr_t)pg - (uintptr_t)page_array) / sizeof *pg; +} diff --git a/vm/model.c b/vm/model.c new file mode 100644 index 0000000..ed379dc --- /dev/null +++ b/vm/model.c @@ -0,0 +1,13 @@ +#include + +static vm_model_t model; + +vm_model_t vm_memory_model(void) +{ + return model; +} + +void vm_set_memory_model(vm_model_t m) +{ + model = m; +} diff --git a/vm/page.c b/vm/page.c index 63a43b7..5ac08c6 100644 --- a/vm/page.c +++ b/vm/page.c @@ -4,12 +4,6 @@ #include #include -/* array of pages, one for each physical page frame present in RAM */ -static vm_page_t *page_array = NULL; - -/* number of pages stored in page_array */ -static size_t page_array_count = 0; - /* Pre-calculated page order -> size conversion table */ static size_t page_order_bytes[] = { [VM_PAGE_4K] = 0x1000, @@ -64,47 +58,14 @@ void *vm_phys_to_virt(phys_addr_t p) return (void *)(VM_PAGEMAP_BASE + p); } -void vm_page_init_array() -{ - size_t pmem_size = 0; - - memblock_iter_t 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(vm_page_t) * 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); -} - vm_page_t *vm_page_get(phys_addr_t addr) { - size_t pfn = addr / VM_PAGE_SIZE; - return pfn < page_array_count ? &page_array[pfn] : NULL; + switch (vm_memory_model()) { + case VM_MODEL_FLAT: + return vm_page_get_flat(addr); + default: + return NULL; + } } phys_addr_t vm_page_get_paddr(vm_page_t *pg) @@ -119,7 +80,12 @@ void *vm_page_get_vaddr(vm_page_t *pg) size_t vm_page_get_pfn(vm_page_t *pg) { - return ((uintptr_t)pg - (uintptr_t)page_array) / sizeof *pg; + switch (vm_memory_model()) { + case VM_MODEL_FLAT: + return vm_page_get_pfn_flat(pg); + default: + return 0; + } } size_t vm_page_order_to_bytes(vm_page_order_t order)