1/** 2 * \file 3 * \brief New retype test 4 */ 5 6/* 7 * Copyright (c) 2016, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <barrelfish/barrelfish.h> 17 18// adapted from usr/monitor/capops/internal.h 19#define GOTO_IF_ERR(err, label) do { \ 20 if (err_is_fail(err)) { \ 21 printf("...fail: %s\n", err_getstring(err)); \ 22 result = 1; \ 23 goto label; \ 24 } \ 25} while (0) 26 27static bool quiet = false; 28 29#define OUT(fmt...) \ 30do { \ 31 if (!quiet) { \ 32 printf(fmt); \ 33 } \ 34} while(0) 35 36//{{{1 setup & helpers 37static struct capref bunch_o_ram; 38static struct frame_identity bor_id; 39 40 41static errval_t frame_ram_identify(struct capref cap, struct frame_identity *id) 42{ 43 errval_t err; 44 45 46 47 struct capability thecap; 48 err = cap_direct_identify(cap, &thecap); 49 if (err_is_fail(err)) { 50 return err; 51 } 52 53 assert(type_is_mappable(thecap.type) || thecap.type == ObjType_RAM); 54 55 id->base = get_address(&thecap); 56 id->bytes = get_size(&thecap); 57 id->pasid = get_pasid(&thecap); 58 59 return SYS_ERR_OK; 60} 61 62static void setup(size_t bytes) 63{ 64 errval_t err; 65 err = ram_alloc(&bunch_o_ram, log2ceil(bytes)); 66 assert(err_is_ok(err)); 67 68 err = frame_ram_identify(bunch_o_ram, &bor_id); 69 assert(err_is_ok(err)); 70} 71 72static void cleanup(void) 73{ 74 errval_t err; 75 err = cap_revoke(bunch_o_ram); 76 assert(err_is_ok(err)); 77 err = cap_destroy(bunch_o_ram); 78 assert(err_is_ok(err)); 79} 80 81static void print_unexpected(char *info, genpaddr_t expected_base, 82 char *expected_size, genpaddr_t actual_base, 83 size_t actual_size) 84{ 85 printf("...fail: %sexpected %#"PRIxGENPADDR", %s; got %#"PRIxGENPADDR", %zu bytes\n", 86 info, expected_base, expected_size, actual_base, actual_size); 87} 88 89//{{{1 test_retype_single 90static int test_retype_single(void) 91{ 92 OUT("%s:\n", __FUNCTION__); 93 setup(LARGE_PAGE_SIZE); 94 95 int result = 0; 96 errval_t err; 97 struct frame_identity fi; 98 struct capref cap, cap2, cnram, cncap; 99 100 /* get slots for results */ 101 err = slot_alloc(&cap); 102 assert(err_is_ok(err)); 103 err = slot_alloc(&cap2); 104 assert(err_is_ok(err)); 105 err = slot_alloc(&cnram); 106 assert(err_is_ok(err)); 107 err = slot_alloc(&cncap); 108 assert(err_is_ok(err)); 109 110 /* allocate 4kB Frame at offset 0 of 2MB region */ 111 OUT(" allocate 4kB Frame at offset 0 of 2MB region: "); 112 err = cap_retype(cap, bunch_o_ram, 0, ObjType_Frame, BASE_PAGE_SIZE, 1); 113 GOTO_IF_ERR(err, out); 114 err = frame_ram_identify(cap, &fi); 115 assert(err_is_ok(err)); 116 117 if (bor_id.base != fi.base || fi.bytes != BASE_PAGE_SIZE) { 118 print_unexpected("", bor_id.base, "4kB", fi.base, fi.bytes); 119 result = 1; 120 goto out; 121 } 122 OUT("...ok\n"); 123 124 /* allocate 16kB RAM at offset 4kB of 2MB region */ 125 OUT(" allocate 16kB RAM at offset 4kB of 2MB region: "); 126 err = cap_retype(cap2, bunch_o_ram, BASE_PAGE_SIZE, ObjType_RAM, BASE_PAGE_SIZE * 4, 1); 127 GOTO_IF_ERR(err, out); 128 err = frame_ram_identify(cap2, &fi); 129 assert(err_is_ok(err)); 130 131 if (bor_id.base + BASE_PAGE_SIZE != fi.base || fi.bytes != 4*BASE_PAGE_SIZE) { 132 print_unexpected("", bor_id.base + BASE_PAGE_SIZE, "16kB", fi.base, fi.bytes); 133 result = 1; 134 goto out; 135 } 136 OUT("...ok\n"); 137 138#if 0 // this test does not make sense with twolevel cspace layout 139 /* split 16kB into 4kB CNode, and 3x4kB Frame */ 140 OUT(" split 16kB into 4kB CNode, and 3x4kB Frame: "); 141 err = cap_retype(cnram, cap2, 0, ObjType_RAM, BASE_PAGE_SIZE, 1); 142 GOTO_IF_ERR(err, out); 143 err = cnode_create_from_mem(cncap, cnram, &tmp.cnode, DEFAULT_CNODE_BITS); 144 GOTO_IF_ERR(err, out); 145 tmp.slot = 0; 146 147 err = cap_retype(tmp, cap2, BASE_PAGE_SIZE, ObjType_Frame, BASE_PAGE_SIZE, 3); 148 GOTO_IF_ERR(err, out); 149 // offset of slot 0 is 8kB --> addrs should be (2+slot) * BASE_PAGE_SIZE 150 for (tmp.slot = 0; tmp.slot <= 2; tmp.slot++) { 151 err = frame_ram_identify(tmp, &fi); 152 assert(err_is_ok(err)); 153 if (bor_id.base + (2+tmp.slot)*BASE_PAGE_SIZE != fi.base || 154 fi.bytes != BASE_PAGE_SIZE) 155 { 156 char buf[16]; 157 snprintf(buf, 16, "slot %d: ", tmp.slot); 158 print_unexpected(buf, bor_id.base + (2+tmp.slot) * BASE_PAGE_SIZE, 159 "4kB", fi.base, fi.bytes); 160 result = 1; 161 goto out; 162 } 163 } 164 165 OUT("...ok\n"); 166#endif 167 168 169out: 170 slot_free(cap); 171 slot_free(cap2); 172 slot_free(cnram); 173 slot_free(cncap); 174 /* this also cleans up any descendants of bunch_o_ram */ 175 cleanup(); 176 return result; 177} 178 179//{{{1 test_retype_multi 180static int test_retype_multi(void) 181{ 182 OUT("%s:\n", __FUNCTION__); 183 setup(LARGE_PAGE_SIZE); 184 185 int result = 0; 186 errval_t err; 187 struct frame_identity fi; 188 struct capref cap, cap2; 189 190 /* get slots for results */ 191 err = slot_alloc(&cap); 192 assert(err_is_ok(err)); 193 err = slot_alloc(&cap2); 194 assert(err_is_ok(err)); 195 196 /* allocate 4kB Frame at offset 0 of 2MB region */ 197 OUT(" allocate 4kB Frame at offset 0 of 2MB region: "); 198 err = cap_retype(cap, bunch_o_ram, 0, ObjType_Frame, BASE_PAGE_SIZE, 1); 199 GOTO_IF_ERR(err, out); 200 err = frame_ram_identify(cap, &fi); 201 assert(err_is_ok(err)); 202 203 if (bor_id.base != fi.base || fi.bytes != BASE_PAGE_SIZE) { 204 print_unexpected("", bor_id.base, "4kB", fi.base, fi.bytes); 205 result = 1; 206 goto out; 207 } 208 OUT("...ok\n"); 209 210 /* allocate 16kB RAM at offset 4kB of 2MB region */ 211 OUT(" allocate 16kB RAM at offset 4kB of 2MB region: "); 212 err = cap_retype(cap2, bunch_o_ram, BASE_PAGE_SIZE, ObjType_RAM, BASE_PAGE_SIZE * 4, 1); 213 GOTO_IF_ERR(err, out); 214 err = frame_ram_identify(cap2, &fi); 215 assert(err_is_ok(err)); 216 217 if (bor_id.base + BASE_PAGE_SIZE != fi.base || fi.bytes != 4*BASE_PAGE_SIZE) { 218 print_unexpected("", bor_id.base + BASE_PAGE_SIZE, "16kB", fi.base, fi.bytes); 219 result = 1; 220 goto out; 221 } 222 OUT("...ok\n"); 223 224 /* delete first cap and retype first 4k again */ 225 OUT(" deleting first 4kB descendant\n"); 226 err = cap_delete(cap); 227 assert(err_is_ok(err)); 228 229 OUT(" allocating first 4kB again: "); 230 err = cap_retype(cap, bunch_o_ram, 0, ObjType_RAM, BASE_PAGE_SIZE, 1); 231 GOTO_IF_ERR(err, out); 232 err = frame_ram_identify(cap, &fi); 233 assert(err_is_ok(err)); 234 235 if (bor_id.base != fi.base || fi.bytes != BASE_PAGE_SIZE) { 236 print_unexpected("", bor_id.base, "4kB", fi.base, fi.bytes); 237 result = 1; 238 goto out; 239 } 240 OUT("...ok\n"); 241 242out: 243 slot_free(cap); 244 slot_free(cap2); 245 /* this also cleans up any descendants of bunch_o_ram */ 246 cleanup(); 247 return result; 248} 249 250//{{{1 test_retype_overlap 251static int test_retype_overlap(void) 252{ 253 errval_t err; 254 int result = 0; 255 struct capref cap, cap2; 256 //struct frame_identity fi; 257 258 err = slot_alloc(&cap); 259 assert(err_is_ok(err)); 260 err = slot_alloc(&cap2); 261 assert(err_is_ok(err)); 262 263 setup(LARGE_PAGE_SIZE); 264 OUT("overlap testing with 32 pages allocated at offset 0:\n"); 265 err = cap_retype(cap, bunch_o_ram, 0, ObjType_Frame, 32*BASE_PAGE_SIZE, 1); 266 assert(err_is_ok(err)); 267 268 OUT(" allocating 16 pages at offset 16 pages: "); 269 err = cap_retype(cap2, bunch_o_ram, 16*BASE_PAGE_SIZE, 270 ObjType_Frame, 16*BASE_PAGE_SIZE, 1); 271 if (err_no(err) != SYS_ERR_REVOKE_FIRST) { 272 OUT("...fail: %s\n", err_getstring(err)); 273 result = 1; 274 goto out; 275 } 276 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 277 278 OUT(" allocating 4kB at offset 31 pages: "); 279 err = cap_retype(cap2, bunch_o_ram, BASE_PAGE_SIZE, 280 ObjType_Frame, 31*BASE_PAGE_SIZE, 1); 281 if (err_no(err) != SYS_ERR_REVOKE_FIRST) { 282 OUT("...fail: %s\n", err_getstring(err)); 283 result = 1; 284 goto out; 285 } 286 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 287 288 OUT(" allocating 16kB at offset 31 pages: "); 289 err = cap_retype(cap2, bunch_o_ram, 4*BASE_PAGE_SIZE, 290 ObjType_Frame, 31*BASE_PAGE_SIZE, 1); 291 if (err_no(err) != SYS_ERR_REVOKE_FIRST) { 292 OUT("...fail: %s\n", err_getstring(err)); 293 result = 1; 294 goto out; 295 } 296 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 297 298 OUT(" allocating 32 pages at offset 0: "); 299 err = cap_retype(cap2, bunch_o_ram, 0, 300 ObjType_Frame, 32*BASE_PAGE_SIZE, 1); 301 if (err_no(err) != SYS_ERR_REVOKE_FIRST) { 302 OUT("...fail: %s\n", err_getstring(err)); 303 result = 1; 304 goto out; 305 } 306 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 307 308out: 309 slot_free(cap); 310 slot_free(cap2); 311 cleanup(); 312 return result; 313} 314 315//{{{1 test_non_aligned 316static int test_non_aligned(void) 317{ 318 errval_t err; 319 int result = 0; 320 struct capref cap; 321 322 err = slot_alloc(&cap); 323 assert(err_is_ok(err)); 324 325 setup(LARGE_PAGE_SIZE); 326 OUT(" offset 1024: "); 327 err = cap_retype(cap, bunch_o_ram, 1024, ObjType_Frame, 32*BASE_PAGE_SIZE, 1); 328 if (err_no(err) != SYS_ERR_RETYPE_INVALID_OFFSET) { 329 OUT("...fail: %s\n", err_getstring(err)); 330 result = 1; 331 goto out; 332 } 333 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 334 OUT(" offset >= object size: "); 335 err = cap_retype(cap, bunch_o_ram, LARGE_PAGE_SIZE, ObjType_Frame, 336 32*BASE_PAGE_SIZE, 1); 337 if (err_no(err) != SYS_ERR_RETYPE_INVALID_OFFSET) { 338 OUT("...fail: %s\n", err_getstring(err)); 339 result = 1; 340 goto out; 341 } 342 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 343 OUT(" offset + objects >= object size: "); 344 err = cap_retype(cap, bunch_o_ram, LARGE_PAGE_SIZE - 31*BASE_PAGE_SIZE, ObjType_Frame, 345 32*BASE_PAGE_SIZE, 1); 346 if (err_no(err) != SYS_ERR_RETYPE_INVALID_OFFSET) { 347 OUT("...fail: %s\n", err_getstring(err)); 348 result = 1; 349 goto out; 350 } 351 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 352 OUT(" object size 6kB: "); 353 err = cap_retype(cap, bunch_o_ram, 0, ObjType_Frame, 6144, 1); 354 if (err_no(err) != SYS_ERR_INVALID_SIZE) { 355 OUT("...fail: %s\n", err_getstring(err)); 356 result = 1; 357 goto out; 358 } 359 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 360 361 OUT(" objects do not fit into cap: "); 362 err = cap_retype(cap, bunch_o_ram, 0, ObjType_Frame, BASE_PAGE_SIZE, 513); 363 if (err_no(err) != SYS_ERR_RETYPE_INVALID_COUNT) { 364 OUT("...fail: %s\n", err_getstring(err)); 365 result = 1; 366 goto out; 367 } 368 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 369 370 OUT(" object larger than cap: "); 371 err = cap_retype(cap, bunch_o_ram, 0, ObjType_Frame, 513*BASE_PAGE_SIZE, 1); 372 if (err_no(err) != SYS_ERR_INVALID_SIZE) { 373 OUT("...fail: %s\n", err_getstring(err)); 374 result = 1; 375 goto out; 376 } 377 OUT("...ok: retype fails with '%s'\n", err_getstring(err)); 378 379out: 380 slot_free(cap); 381 cleanup(); 382 return result; 383} 384 385//{{{1 main 386int main(int argc, char *argv[]) 387{ 388 if (argc >= 2) { 389 quiet = !strncmp(argv[1], "quiet", 5); 390 } 391 int result = 0; 392 OUT("0: Non-overlapping retype test, no deletion\n"); 393 result |= test_retype_single() << 0; 394 OUT("1: Non-overlapping retype test, with deletions\n"); 395 result |= test_retype_multi() << 1; 396 OUT("2: Overlapping retype test\n"); 397 result |= test_retype_overlap() << 2; 398 OUT("3: Non-aligned retype test\n"); 399 result |= test_non_aligned() << 3; 400 401 printf("retype: result: %x\n", result); 402 403 return result; 404} 405