1/** 2 * \file 3 * \brief Test program for large page code 4 */ 5 6/* 7 * Copyright (c) 2013, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16#include <stdio.h> 17 18#define SAFE_VADDR (genvaddr_t)(8ULL<<39) 19#define SAFE_PMAP_ADDR (genvaddr_t)(9ULL<<39) 20// 2M 21#define DEFAULT_SIZE X86_64_LARGE_PAGE_SIZE 22 23static enum objtype type[] = { 24 ObjType_VNode_x86_64_pml4, 25 ObjType_VNode_x86_64_pdpt, 26 ObjType_VNode_x86_64_pdir, 27 ObjType_VNode_x86_64_ptable 28}; 29 30// the offsets of the indices for the different page table levels 31static uint8_t offsets[] = { 39, 30, 21, 12 }; 32 33static paging_x86_64_flags_t PAGE_DEFAULT_ACCESS = 34 PTABLE_USER_SUPERVISOR | 35 PTABLE_EXECUTE_DISABLE | 36 PTABLE_READ_WRITE; 37 38static vregion_flags_t PMAP_DEFAULT_ACCESS = 39 VREGION_FLAGS_READ_WRITE; 40 41static void test_region(uint32_t *buf, size_t size) 42{ 43 int j = 0; 44 for (int i = 0; i < size; i+=4) { 45 j+=4; 46 if( (size-j) < 200) 47 { 48 printf("%i, ", i); 49 } 50 51 buf[i/4] = i; 52 } 53 for (int i = 0; i < size; i+=4) { 54 assert(buf[i/4] == i); 55 } 56 printf("\n\n"); 57 58} 59 60 61int main(void) 62{ 63 struct capref frame, smallframe, vnodes[4], mappings[4]; 64 size_t bytes = DEFAULT_SIZE; 65 size_t bits = 4*1024; 66 errval_t err; 67 68 //get 4k frame cap 69 err = frame_alloc(&smallframe, bits, &bits); 70 assert(err_is_ok(err)); 71 assert(bits >= 4*1024); 72 // get 2M frame cap 73 err = frame_alloc(&frame, bytes, &bytes); 74 assert(err_is_ok(err)); 75 assert(bytes >= DEFAULT_SIZE); 76 77 // check that we have the necessary ptables (note: this is not how you 78 // should do this cf. with pmap_target.c 79 // setup reference to pml4 capability 80 vnodes[0] = (struct capref) { 81 .cnode = cnode_page, 82 .slot = 0, 83 }; 84 // note we start iterating on 1, because we're using index 0 as the 85 // well-known pml4 capref 86 for (int i = 1; i < sizeof(type) / sizeof(type[0]); i++) { 87 err = slot_alloc(&vnodes[i]); 88 assert(err_is_ok(err)); 89 err = slot_alloc(&mappings[i]); 90 assert(err_is_ok(err)); 91 printf("creating vnode for level %d, type %d\n", i, type[i]); 92 err = vnode_create(vnodes[i], type[i]); 93 assert(err_is_ok(err)); 94 uint32_t slot = (SAFE_VADDR >> offsets[i-1]) & 0x1f; 95 printf("mapping into slot %d on level %d\n", slot, i-1); 96 err = vnode_map(vnodes[i-1], vnodes[i], slot, PTABLE_ACCESS_DEFAULT, 97 0, 1, mappings[i]); 98 if (err_is_fail(err)) { 99 // this means we already have a page table for this level 100 // XXX: right now we've chosen the SAFE_VADDR such that we don't have 101 // any intermediate level page tables so we don't need to worry 102 // about this case 103 printf("there was a page table already?\n"); 104 printf("vnode_map: %s\n", err_getstring(err)); 105 exit(1); 106 } 107 } 108 109// map as 4k and 2m frames with vnode_map 110// used to test the kernel code 111#if 1 112 err = slot_alloc(&mappings[0]); 113 assert(err_is_ok(err)); 114 //printf("start 4k vnode map"); 115 err = vnode_map(vnodes[3], smallframe, (SAFE_VADDR>>offsets[3])&0x1f, 116 PAGE_DEFAULT_ACCESS, 0, 4*1024 / X86_64_BASE_PAGE_SIZE, mappings[0]); 117#endif 118#if 0 119 if (err_is_fail(err)) { 120 printf("error in vnode_map: %s\n", err_getstring(err)); 121 exit(1); 122 } 123 124 test_region((uint32_t*)SAFE_VADDR, 4*1024); 125 126 // FROM HERE: unmap and try to map as large page 127 128 // unmap frame 129 printf("start 4k unmap\n"); 130 err = vnode_unmap(vnodes[3], smallframe, (SAFE_VADDR>>offsets[3])&0x1f, 131 4*1024 / X86_64_BASE_PAGE_SIZE); 132 if (err_is_fail(err)) { 133 printf("vnode_unmap: %s\n", err_getstring(err)); 134 } 135 assert(err_is_ok(err)); 136 // unmap level 3 page table 137 err = vnode_unmap(vnodes[2], vnodes[3], SAFE_VADDR>>offsets[2]&0x1f, 1); 138 assert(err_is_ok(err)); 139 140 // map as 2M large page 141 printf("start 2m vnodemap\n"); 142 err = vnode_map(vnodes[2], frame, SAFE_VADDR>>offsets[2]&0x1f, 143 PAGE_DEFAULT_ACCESS, 0, DEFAULT_SIZE / X86_64_LARGE_PAGE_SIZE); 144 if (err_is_fail(err)) { 145 printf("error in vnode_map: %s\n", err_getstring(err)); 146 exit(1); 147 } 148 149 test_region((uint32_t*)SAFE_VADDR, DEFAULT_SIZE); 150 151 err = vnode_unmap(vnodes[2], frame, SAFE_VADDR>>offsets[2]&0x1f, DEFAULT_SIZE / X86_64_LARGE_PAGE_SIZE); 152 if (err_is_fail(err)) { 153 printf("vnode_unmap: %s\n", err_getstring(err)); 154 } 155 assert(err_is_ok(err)); 156#endif 157 158 struct pmap *pmap; 159 160//normal page via pmap interface 161// used to test if 4k code still works 162// (although this would break the whole barrelfish boot) 163#if 0 164 printf("\n\nstart 4k map with pmap\n"); 165 bits = 4*1024; 166 printf(" frame_alloc\n"); 167 err = frame_alloc(&smallframe, bits, &bits); 168 assert(err_is_ok(err)); 169 assert(bits >= 4*1024); 170 printf(" get pmap\n"); 171 pmap = get_current_pmap(); 172 173 174 printf(" map\n"); 175 err = pmap->f.map(pmap, SAFE_PMAP_ADDR, smallframe, 0, bits, PMAP_DEFAULT_ACCESS, NULL, &bits); 176 if (err_is_fail(err)) 177 { 178 printf("error in pmap: %s\n", err_getstring(err)); 179 } 180 test_region((uint32_t*)SAFE_PMAP_ADDR, 4*1024); 181 182 printf("\tunmap\n"); 183 err = pmap->f.unmap(pmap, SAFE_PMAP_ADDR, bits, NULL); 184#endif 185 186 187//large page via pmap interface 188// used to test the 2M pages on a safe address 189// looped 10 times to see if unmap does work 190#if 0 191 printf("start 2m map with pmap\n"); 192 bytes = DEFAULT_SIZE; 193 err = frame_alloc(&frame, bytes, &bytes); 194 assert(err_is_ok(err)); 195 assert(bytes >= DEFAULT_SIZE); 196 197 pmap = get_current_pmap(); 198 199 for(int i = 0; i<10; ++i){ 200 printf("map %i\n", i); 201 err = pmap->f.map(pmap, SAFE_PMAP_ADDR, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes); 202 if (err_is_fail(err)) 203 { 204 printf("error in pmap: %s\n", err_getstring(err)); 205 exit(1); 206 } 207 208 test_region((uint32_t*)SAFE_PMAP_ADDR, DEFAULT_SIZE); 209 210 err = pmap->f.unmap(pmap, SAFE_PMAP_ADDR, bytes, NULL); 211 if (err_is_fail(err)) 212 { 213 printf("error in unmap: %s\n", err_getstring(err)); 214 exit(1); 215 } 216 }//end for 217#endif 218 219 220 struct memobj a; 221 genvaddr_t address; 222 223//test determine_addr_raw as address obtainer 224// mapping 4k page 225#if 0 226 printf("determine_addr 4k\n"); 227 bits = 4*1024; 228 err = frame_alloc(&smallframe, bits, &bits); 229 assert(err_is_ok(err)); 230 assert(bits >= 4*1024); 231 232 //determine address 233 a.size = bits; 234 address = 0; 235 pmap = get_current_pmap(); 236 err = pmap->f.determine_addr_raw(pmap, a.size, BASE_PAGE_SIZE, &address); 237 printf("address: %lx\n", (unsigned long) address); 238 if (err_is_fail(err)) 239 { 240 printf("error in determine_addr: %s\n", err_getstring(err)); 241 exit(1); 242 } 243 244 err = pmap->f.map(pmap, address, smallframe, 0, bits, PMAP_DEFAULT_ACCESS, NULL, &bits); 245 if (err_is_fail(err)) 246 { 247 printf("error in pmap: %s\n", err_getstring(err)); 248 exit(1); 249 } 250 test_region((uint32_t*)address, 4*1024); 251#endif 252 253 254// determine_addr_raw for 2m pages 255// for loop inserted currently 256// this was the only way multiple large pages could be accessed 257// no longer necessary 258#if 0 259 printf("determine_addr 2m\n"); 260 genvaddr_t* addresses = malloc(200*sizeof(genvaddr_t)); 261for(int i = 0; i<200; ++i){ 262 bytes = DEFAULT_SIZE; 263 err = frame_alloc(&frame, bytes, &bytes); 264 assert(err_is_ok(err)); 265 assert(bytes >= DEFAULT_SIZE); 266 267 a.size = bytes; 268 printf("a.size: %x, %i\n", (unsigned int) a.size, (unsigned int) a.size); 269 address = 0; 270 pmap = get_current_pmap(); 271 err = pmap->f.determine_addr_raw(pmap, a.size, LARGE_PAGE_SIZE, &address); 272 printf("address: %x\n", (unsigned int) address); 273 if(err_is_fail(err)) 274 { 275 printf("error in determine_addr: %s\n", err_getstring(err)); 276 exit(1); 277 } 278 279 err = pmap->f.map(pmap, address, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes); 280 if (err_is_fail(err)) 281 { 282 printf("error in pmap: %s\n", err_getstring(err)); 283 exit(1); 284 } 285 addresses[i] = address; 286} 287for(int i = 0; i<200; ++i){ 288 test_region((uint32_t*)addresses[i], DEFAULT_SIZE); 289} 290#endif 291 292 293// multiple large pages with one go 294// the for loop is to test unmap 295#if 1 296 printf("multiple 2m\n"); 297 bytes = 10*DEFAULT_SIZE; 298 err = frame_alloc(&frame, bytes, &bytes); 299 assert(err_is_ok(err)); 300 assert(bytes >= 10*DEFAULT_SIZE); 301 302 a.size = bytes; 303 printf("a.size: %x, %i\n", (unsigned int) a.size, (unsigned int) a.size); 304 address = 0; 305 pmap = get_current_pmap(); 306 err = pmap->f.determine_addr_raw(pmap, a.size, LARGE_PAGE_SIZE, &address); 307 printf("address: %x\n", (unsigned int) address); 308 if(err_is_fail(err)) 309 { 310 printf("error in determine_addr: %s\n", err_getstring(err)); 311 exit(1); 312 } 313for (int i=0; i<10; ++i) { 314printf("map %i\n", i); 315 err = pmap->f.map(pmap, address, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes); 316 if (err_is_fail(err)) 317 { 318 printf("error in pmap: %s\n", err_getstring(err)); 319 exit(1); 320 } 321 322 test_region((uint32_t*)address, 10*DEFAULT_SIZE); 323 324 err = pmap->f.unmap(pmap, address, bytes, NULL); 325 if (err_is_fail(err)) 326 { 327 printf("error in unmap: %s\n", err_getstring(err)); 328 exit(1); 329 } 330}//endfor 331#endif 332 printf("exited successfully\n"); 333 return 0; 334} 335