#include #include #include // ASSESSMENT M1: these lines show mapping to fixed locations and read/write // used to avoid conflicts between tests static lvaddr_t vaddr = 0x0000100000000000L; static void test_paging_run(errval_t func(struct paging_state *paging_state), char *name, struct paging_state *paging_state) { errval_t err; // debug_printf("TEST_PAGING %19s: start\n", name); err = func(paging_state); if (err_is_ok(err)) { debug_printf("TEST_PAGING %23s: OK\n", name); } else { debug_printf("TEST_PAGING %23s: ERR\n", name); USER_PANIC_ERR(err, "Test Failed with Error"); } } static errval_t test_paging_full_l3(struct paging_state *paging_state) { errval_t err; size_t mapping_size = BASE_PAGE_SIZE; // map all entries of a single l3 table for(size_t i = 0; i < VMSAv8_64_PTABLE_NUM_ENTRIES; ++i) { struct capref frame; err = frame_alloc(&frame, mapping_size, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_ALLOC); } err = paging_map_fixed_attr(paging_state, vaddr, frame, mapping_size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); } // verify mapping using a random value at a random location uint8_t val = rand() % 256; memset((void *) vaddr, val, mapping_size); if(*((uint8_t *) vaddr + (rand() % mapping_size)) != val) { return ERR_INVALID_ARGS; } vaddr += mapping_size; } return SYS_ERR_OK; } static errval_t test_paging_full_l2(struct paging_state *paging_state) { errval_t err; size_t mapping_size = BASE_PAGE_SIZE; // map a page in all slots of a single l2 node (the 0-th slot was already used in a previous test) for(size_t i = 1; i < VMSAv8_64_PTABLE_NUM_ENTRIES; ++i) { struct capref frame; err = frame_alloc(&frame, mapping_size, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_ALLOC); } err = paging_map_fixed_attr(paging_state, vaddr, frame, mapping_size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); } // verify mapping using a random value at a random location uint8_t val = rand() % 256; memset((void *) vaddr, val, mapping_size); if(*((uint8_t *) vaddr + (rand() % mapping_size)) != val) { return ERR_INVALID_ARGS; } vaddr += LARGE_PAGE_SIZE; } return SYS_ERR_OK; } static errval_t test_paging_big_regions(struct paging_state *paging_state) { errval_t err; size_t mapping_size; // map larger areas for(size_t i = 1; i <= VMSAv8_64_PTABLE_NUM_ENTRIES - 1; ++i) { mapping_size = i * BASE_PAGE_SIZE; struct capref frame; err = frame_alloc(&frame, mapping_size, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_ALLOC); } err = paging_map_fixed_attr(paging_state, vaddr, frame, mapping_size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); } // verify mapping using a random value at a random location uint8_t val = rand() % 256; memset((void *) vaddr, val, mapping_size); if(*((uint8_t *) vaddr + (rand() % mapping_size)) != val) { return ERR_INVALID_ARGS; } vaddr += LARGE_PAGE_SIZE; } return SYS_ERR_OK; } static errval_t test_paging_map_frame(struct paging_state *paging_state) { errval_t err; for(size_t mapping_size = BASE_PAGE_SIZE; mapping_size <= LARGE_PAGE_SIZE - 1; mapping_size += BASE_PAGE_SIZE) { void *retaddr; struct capref frame; err = frame_alloc(&frame, mapping_size, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_ALLOC); } err = paging_map_frame_attr(paging_state, &retaddr, mapping_size, frame, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); } // verify mapping using a random value at a random location uint8_t val = rand() % 256; memset(retaddr, val, mapping_size); if(*((uint8_t *)retaddr + (rand() % mapping_size)) != val) { return ERR_INVALID_ARGS; } } return SYS_ERR_OK; } static errval_t test_paging_unmap(struct paging_state *paging_state) { errval_t err; void *retaddr; struct capref frame; err = frame_alloc(&frame, BASE_PAGE_SIZE, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_ALLOC); } err = paging_map_frame_attr(paging_state, &retaddr, BASE_PAGE_SIZE, frame, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); } // check that it is mapped *(uint8_t *) retaddr = 1; assert(*(uint8_t *)retaddr == 1); err = paging_unmap(paging_state, retaddr); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_UNMAP); } // check that it was unmapped // *(uint8_t *) retaddr = 1; err = paging_map_fixed_attr(paging_state, (lvaddr_t) retaddr, frame, BASE_PAGE_SIZE, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); } // check that it is mapped assert(*(uint8_t *)retaddr == 1); return SYS_ERR_OK; } static errval_t test_paging_foreign(struct paging_state *ignored) { errval_t err; // setup all the stuff for the test struct capref rootcn_cap; struct cnoderef rootcn; struct cnoderef pagecn; struct paging_state st; err = cnode_create_l1(&rootcn_cap, &rootcn); assert(err_is_ok(err)); err = cnode_create_foreign_l2(rootcn_cap, ROOTCN_SLOT_PAGECN, &pagecn); assert(err_is_ok(err)); struct capref l0 = { .cnode = pagecn, .slot = PAGECN_SLOT_VROOT, }; err = vnode_create(l0, ObjType_VNode_AARCH64_l0); assert(err_is_ok(err)); // initialize foreign state err = paging_init_state_foreign(&st, VADDR_OFFSET, l0, get_default_slot_allocator()); if (err_is_fail(err)) { return err; } size_t mapping_size = BASE_PAGE_SIZE; // map all entries of a single l3 table in the foreign state for(size_t i = 0; i < VMSAv8_64_PTABLE_NUM_ENTRIES; ++i) { struct capref frame; err = frame_alloc(&frame, mapping_size, NULL); if (err_is_fail(err)) { return err; } err = paging_map_fixed_attr(&st, vaddr, frame, mapping_size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err; } vaddr += mapping_size; } return SYS_ERR_OK; } void do_test_paging(void) { test_paging_run(test_paging_full_l3, "test_paging_full_l3", get_current_paging_state()); test_paging_run(test_paging_full_l2, "test_paging_full_l2", get_current_paging_state()); test_paging_run(test_paging_big_regions, "test_paging_big_regions", get_current_paging_state()); test_paging_run(test_paging_map_frame, "test_paging_map_frame", get_current_paging_state()); test_paging_run(test_paging_unmap, "test_paging_unmap", get_current_paging_state()); test_paging_run(test_paging_foreign, "test_paging_foreign", NULL); // Test paging for (int i = 0; i < 40; i++) { debug_printf("TEST: page %lu\n", i); char *data = alloc_frame(5176*4096, 16, NULL, NULL); memset(data, 33, 5176*4096); } }