115 lines
3.4 KiB
C
115 lines
3.4 KiB
C
#include <metalsvm/stdlib.h>
|
|
#include <metalsvm/stdio.h>
|
|
#include <metalsvm/stdarg.h>
|
|
#include <metalsvm/mmu.h>
|
|
#include <asm/page.h>
|
|
|
|
#define PAGE_COUNT 10
|
|
#define VIRT_FROM_ADDR 0x100000000000
|
|
#define VIRT_TO_ADDR 0x200000000000
|
|
|
|
/*
|
|
* Simple helper to format our test results
|
|
*/
|
|
static void test(size_t expr, char *fmt, ...)
|
|
{
|
|
void _putchar(int c, void *arg) { kputchar(c); } // for kvprintf
|
|
|
|
static int c = 1;
|
|
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
|
|
kprintf("%s #%u:\t", (expr) ? "PASSED" : "FAILED", c++);
|
|
kvprintf(fmt, _putchar, NULL, 10, ap);
|
|
kputs("\n");
|
|
|
|
va_end(ap);
|
|
|
|
if (!expr)
|
|
abort();
|
|
}
|
|
|
|
/*
|
|
* This is a simple procedure to test the paging
|
|
* and memory management subsystem.
|
|
*
|
|
* We will map a single physical memory region to two virtual regions.
|
|
* When writing to the first one, we should be able to read the same contents
|
|
* from the second one.
|
|
*/
|
|
int paging(void* arg)
|
|
{
|
|
size_t c;
|
|
size_t *p1, *p2;
|
|
size_t virt_from, virt_to, virt_alloc;
|
|
size_t phys;
|
|
|
|
kprintf("paging test started...\n");
|
|
|
|
// allocate physical page frames
|
|
phys = get_pages(PAGE_COUNT);
|
|
test(phys, "get_pages(%lu) = 0x%lx", PAGE_COUNT, phys);
|
|
|
|
// create first mapping
|
|
virt_from = map_region(VIRT_FROM_ADDR, phys, PAGE_COUNT, 0);
|
|
test(virt_from, "map_region(0x%lx, 0x%lx, %lu, 0x%x) = 0x%lx", VIRT_FROM_ADDR, phys, PAGE_COUNT, 0, virt_from);
|
|
|
|
// check address translation
|
|
phys = virt_to_phys(virt_from);
|
|
test(phys, "virt_to_phys(0x%lx) = 0x%lx", virt_from, phys);
|
|
|
|
// write test data
|
|
p1 = (size_t *) virt_from;
|
|
for (c = 0; c < PAGE_COUNT*PAGE_SIZE/sizeof(size_t); c++) {
|
|
p1[c] = c;
|
|
}
|
|
|
|
// create second mapping pointing to the same page frames
|
|
virt_to = map_region(VIRT_TO_ADDR, phys, PAGE_COUNT, 0);
|
|
test(virt_to, "map_region(0x%lx, 0x%lx, %lu, 0x%x) = 0x%lx", VIRT_TO_ADDR, phys, PAGE_COUNT, 0, virt_to);
|
|
|
|
// check address translation
|
|
phys = virt_to_phys(virt_to);
|
|
test(phys, "virt_to_phys(0x%lx) = 0x%lx", virt_to, phys);
|
|
|
|
// check if both mapped areas are equal
|
|
p2 = (size_t *) virt_to;
|
|
for (c = 0; c < PAGE_COUNT*PAGE_SIZE/sizeof(size_t); c++) {
|
|
if (p1[c] != p2[c])
|
|
test(0, "data mismatch at *(%p) != *(%p)", &p1[c], &p2[c]);
|
|
}
|
|
test(1, "data is equal");
|
|
|
|
// try to remap without MAP_REMAP
|
|
virt_to = map_region(VIRT_TO_ADDR, phys+PAGE_SIZE, PAGE_COUNT, 0);
|
|
test(!virt_to, "map_region(0x%lx, 0x%lx, %lu, 0x%x) = 0x%lx (without MAP_REMAP flag)", VIRT_TO_ADDR, phys+PAGE_SIZE, PAGE_COUNT, 0, virt_to);
|
|
|
|
// try to remap with MAP_REMAP
|
|
virt_to = map_region(VIRT_TO_ADDR, phys+PAGE_SIZE, PAGE_COUNT, MAP_REMAP);
|
|
test(virt_to, "map_region(0x%lx, 0x%lx, %lu, 0x%x) = 0x%lx (with MAP_REMAP flag)", VIRT_TO_ADDR, phys+PAGE_SIZE, PAGE_COUNT, MAP_REMAP, virt_to);
|
|
|
|
// check if data is not equal anymore (we remapped with 1 page offset)
|
|
p2 = (size_t *) virt_to;
|
|
for (c = 0; c < PAGE_COUNT*PAGE_SIZE/sizeof(size_t); c++) {
|
|
if (p1[c] == p2[c])
|
|
test(0, "data match at *(%p) != *(%p)", &p1[c], &p2[c]);
|
|
}
|
|
test(1, "data is unequal");
|
|
|
|
// test vm_alloc
|
|
virt_alloc = map_region(0, phys, PAGE_COUNT, 0);
|
|
test(virt_alloc, "map_region(0x%lx, 0x%lx, %lu, 0x%x) = 0x%lx", 0, phys, PAGE_COUNT, 0, virt_alloc);
|
|
|
|
// data should match against new vm addr
|
|
p2 = (size_t *) virt_alloc;
|
|
for (c = 0; c < PAGE_COUNT*PAGE_SIZE/sizeof(size_t); c++) {
|
|
if (p1[c] != p2[c])
|
|
test(0, "data mismatch at *(%p) != *(%p)", &p1[c], &p2[c]);
|
|
}
|
|
test(1, "data is equal");
|
|
|
|
kprintf("FINISHED: all tests passed!\n");
|
|
|
|
return 0;
|
|
}
|