#include #include #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; /* Pre-calculated page order -> size conversion table */ static size_t page_order_bytes[] = { [VM_PAGE_4K] = 0x1000, [VM_PAGE_8K] = 0x2000, [VM_PAGE_16K] = 0x4000, [VM_PAGE_32K] = 0x8000, [VM_PAGE_64K] = 0x10000, [VM_PAGE_128K] = 0x20000, [VM_PAGE_256K] = 0x40000, [VM_PAGE_512K] = 0x80000, [VM_PAGE_1M] = 0x100000, [VM_PAGE_2M] = 0x200000, [VM_PAGE_4M] = 0x400000, [VM_PAGE_8M] = 0x800000, [VM_PAGE_16M] = 0x1000000, [VM_PAGE_32M] = 0x2000000, [VM_PAGE_64M] = 0x4000000, [VM_PAGE_128M] = 0x8000000, [VM_PAGE_256M] = 0x10000000, [VM_PAGE_512M] = 0x20000000, [VM_PAGE_1G] = 0x40000000, }; void vm_page_init_array() { size_t pmem_size = 0; memblock_iter_t it; for_each_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); page_array_count = nr_pages; printf("page_array covers 0x%zx bytes, %zu page frames\n", pmem_size, pmem_size / VM_PAGE_SIZE); printf("page_array is %zu bytes long\n", sizeof(vm_page_t) * nr_pages); for (size_t i = 0; i < nr_pages; i++) { memset(&page_array[i], 0x0, sizeof page_array[i]); } size_t nr_reserved = 0; for_each_reserved_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 |= VM_PAGE_RESERVED; nr_reserved++; } } printf("%zu reserved page frames\n", 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; } phys_addr_t vm_page_get_paddr(vm_page_t *pg) { return vm_page_get_pfn(pg) * VM_PAGE_SIZE; } void *vm_page_get_vaddr(vm_page_t *pg) { /* TODO */ return NULL; } size_t vm_page_get_pfn(vm_page_t *pg) { return ((uintptr_t)pg - (uintptr_t)page_array) / sizeof *pg; } size_t vm_page_order_to_bytes(vm_page_order_t order) { if (order < 0 || order > VM_PAGE_MAX_ORDER) { return 0; } return page_order_bytes[order]; } phys_addr_t vm_page_order_to_pages(vm_page_order_t order) { if (order < 0 || order > VM_PAGE_MAX_ORDER) { return 0; } return page_order_bytes[order] >> VM_PAGE_SHIFT; } vm_alignment_t vm_page_order_to_alignment(vm_page_order_t order) { if (order < 0 || order > VM_PAGE_MAX_ORDER) { return 0; } return ~(page_order_bytes[order] - 1); } size_t vm_bytes_to_pages(size_t bytes) { if (bytes & (VM_PAGE_SIZE-1)) { bytes &= ~(VM_PAGE_SIZE-1); bytes += VM_PAGE_SIZE; } bytes >>= VM_PAGE_SHIFT; return bytes; } vm_zone_t *vm_page_get_zone(vm_page_t *pg) { vm_pg_data_t *node = vm_pg_data_get(pg->p_node); if (!node) { return 0; } if (pg->p_zone >= VM_MAX_ZONES) { return NULL; } return &node->pg_zones[pg->p_zone]; }