Files
mango/sandbox/vm/vm_page.c

134 lines
2.9 KiB
C

#include <socks/types.h>
#include <socks/memblock.h>
#include <socks/vm.h>
#include <string.h>
#include <stdio.h>
/* 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;
}