1/** 2 * \file 3 * \brief Test invalid vnode invocations. 4 */ 5 6/* 7 * Copyright (c) 2014, HP Labs. 8 * Copyright (c) 2015, ETH Zurich. 9 * All rights reserved. 10 * 11 * This file is distributed under the terms in the attached LICENSE file. 12 * If you do not find this file, copies can be found by writing to: 13 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group. 14 */ 15 16#include <barrelfish/barrelfish.h> 17#include <barrelfish/cap_predicates.h> 18#include <stdio.h> 19#include "debug.h" 20#include "tests.h" 21 22#define FRAME_ACCESS_DEFAULT \ 23 (PTABLE_USER_SUPERVISOR | PTABLE_EXECUTE_DISABLE | PTABLE_READ_WRITE) 24 25static enum objtype types[7] = 26{ 27 ObjType_VNode_x86_64_pml4, 28 ObjType_VNode_x86_64_pdpt, 29 ObjType_VNode_x86_64_pdir, 30 ObjType_VNode_x86_64_ptable, 31 ObjType_Frame, 32 ObjType_Frame, 33 ObjType_Frame 34}; 35 36#define W SYS_ERR_WRONG_MAPPING 37#define O SYS_ERR_OK 38#define S SYS_ERR_VM_FRAME_TOO_SMALL 39 40static errval_t mapping_ok[4][7] = 41{ /*pml4*/ /*pdpt*/ /*pdir*/ /*pt*/ /*frm*/ /*2mfrm*/ /*1gfrm*/ 42/*pml4*/{ W, O, W, W, W, W, W }, 43/*pdpt*/{ W, W, O, W, S, S, O }, 44/*pdir*/{ W, W, W, O, S, O, O }, 45/*pt */{ W, W, W, W, O, O, O }, 46}; 47 48static int pass = 0, fail = 0; 49static void check_result(errval_t err, int dest, int src) 50{ 51 if (err_no(err) == mapping_ok[dest][src]) { 52 printf("%d<-%d PASSED (%s)\n", dest, src, err_getstring(err)); 53 pass++; 54 } else { 55 printf("%d<-%d FAILED (expected: %s, was %s)\n", 56 dest, src, err_getstring(mapping_ok[dest][src]), 57 err_getstring(err)); 58 fail++; 59 } 60} 61 62int invalid_mappings(void) 63{ 64 // outline: 65 // get pml4, pdpt, pdir, ptable, and frame 66 // check all combinations to make sure that restrictions are implemented 67 // correctly in kernel space 68 // VALID: 69 // map pdpt in pml4 70 // map pdir in pdpt 71 // map pt in pdir 72 // map frame in {pt, pdir, pdpt} 73 // INVALID: 74 // all other combinations 75 76 errval_t err; 77 struct capref caps[7]; 78 struct capref mapping; 79 80 // allocate slot for mapping cap: can reuse 81 err = slot_alloc(&mapping); 82 if (err_is_fail(err)) { 83 debug_printf("slot_alloc: %s (%ld)\n", err_getstring(err), err); 84 return 1; 85 } 86 87 // allocate caps 88 for (int i = 0; i < 5; i++) { 89 // get 4k block 90 struct capref mem; 91 err = ram_alloc(&mem, BASE_PAGE_BITS); 92 if (err_is_fail(err)) { 93 debug_printf("ram_alloc: %s (%ld)\n", err_getstring(err), err); 94 return 1; 95 } 96 97 // get slot for retype dest 98 err = slot_alloc(&caps[i]); 99 if (err_is_fail(err)) { 100 debug_printf("slot_alloc: %s (%ld)\n", err_getstring(err), err); 101 return 1; 102 } 103 // retype to selected type 104 err = cap_retype(caps[i], mem, 0, types[i], BASE_PAGE_SIZE, 1); 105 if (err_is_fail(err)) { 106 debug_printf("cap_retype: %s (%ld)\n", err_getstring(err), err); 107 return 1; 108 } 109 110 // cleanup source cap 111 DEBUG_INVALID_MAPPINGS("delete ram cap\n"); 112 err = cap_destroy(mem); 113 if (err_is_fail(err)) { 114 debug_printf("cap_delete(mem): %s (%ld)\n", err_getstring(err), err); 115 return 1; 116 } 117 } 118 119 // Do gigabyte frame tests 120 int last_source = 7; 121 122 // cap 6: 2M frame 123 size_t rb = 0; 124 err = frame_alloc(&caps[5], X86_64_LARGE_PAGE_SIZE, &rb); 125 if (err_is_fail(err) || rb != X86_64_LARGE_PAGE_SIZE) { 126 debug_printf("frame_alloc: %s (%ld)\n", err_getstring(err), err); 127 return 1; 128 } 129 // cap 7: 1G frame 130 err = frame_alloc(&caps[6], X86_64_HUGE_PAGE_SIZE, &rb); 131 if (err_is_fail(err) || rb != X86_64_HUGE_PAGE_SIZE) { 132 debug_printf("Cannot allocate 1GB frame (%s)\n", err_getcode(err)); 133 last_source = 6; 134 } 135 136 paging_x86_64_flags_t attr = 0; 137 // select dest (ignore frame, asserts) 138 for (int i = 0; i < 4; i++) { 139 // select source 140 for (int j = 0; j < last_source; j++) { 141 if (j >= 4) { 142 // frame 143 attr = FRAME_ACCESS_DEFAULT; 144 } else { 145 // ptable 146 attr = PTABLE_ACCESS_DEFAULT; 147 } 148 // try mapping 149 err = vnode_map(caps[i], caps[j], /*slot*/0, attr, /*off*/0, 150 /*count*/1, mapping); 151 check_result(err, i, j); 152 // unmap if mapping succeeded 153 if (err_is_ok(err)) { 154 err = vnode_unmap(caps[i], mapping); 155 if (err_is_fail(err)) { 156 DEBUG_ERR(err, "vnode_unmap"); 157 } 158 assert(err_is_ok(err)); 159 // XXX: better API? 160 err = cap_delete(mapping); 161 assert(err_is_ok(err)); 162 } 163 } 164 } 165 166 printf("All tests executed: %d PASSED, %d FAILED\n", pass, fail); 167 168 return 0; 169} 170 171#ifdef STANDALONE 172int main(void) 173{ 174 return invalid_mappings(); 175} 176#endif 177