1/** 2 * \file 3 * \brief Modify flags (protect) new kernel memory test 4 */ 5 6/* 7 * Copyright (c) 2013, 2015, 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 <barrelfish/barrelfish.h> 16#include <barrelfish/sys_debug.h> // sys_debug_flush_cache() 17#include <barrelfish/threads.h> 18#include <barrelfish/except.h> 19#include <stdio.h> 20#include "debug.h" 21#include "tests.h" 22 23static void *vbase = NULL, *vend = NULL; 24static struct memobj *memobj = NULL; 25static struct vregion *vregion = NULL; 26 27#define EX_STACK_SIZE 16384 28static char ex_stack[EX_STACK_SIZE]; 29 30static void handler(enum exception_type type, int subtype, void *addr, 31 arch_registers_state_t *regs) 32{ 33 static int count = 0; 34 ++count; 35 DEBUG_MODIFY_FLAGS("got exception %d(%d) on %p [%d]\n", type, subtype, addr, count); 36 errval_t err; 37 assert(type == EXCEPT_PAGEFAULT); 38#ifdef __x86__ 39 assert(subtype == PAGEFLT_WRITE); 40#endif 41 assert(addr >= vbase && addr < vend); 42 DEBUG_MODIFY_FLAGS("got expected write pagefault on %p\n", addr); 43 // unprotect 4k page 44 genvaddr_t offset = (genvaddr_t)(lvaddr_t)addr - (genvaddr_t)(lvaddr_t)vbase; 45 err = memobj->f.protect(memobj, vregion, offset, 46 BASE_PAGE_SIZE, VREGION_FLAGS_READ_WRITE); 47 assert(err_is_ok(err)); 48} 49 50int modify_flags(void) 51{ 52 struct capref frame; 53 errval_t err; 54 size_t retsize; 55 err = frame_alloc(&frame, 16 * BASE_PAGE_SIZE, &retsize); 56 assert(err_is_ok(err)); 57 // map read-write 58 err = vspace_map_anon_attr(&vbase, &memobj, &vregion, retsize, &retsize, 59 VREGION_FLAGS_READ_WRITE); 60 assert(err_is_ok(err)); 61 err = memobj->f.fill(memobj, 0, frame, retsize); 62 assert(err_is_ok(err)); 63 err = memobj->f.pagefault(memobj, vregion, 0, 0); 64 assert(err_is_ok(err)); 65 assert(vbase); 66 vend = (unsigned char *)vbase + retsize; 67 unsigned char *base = vbase; 68 DEBUG_MODIFY_FLAGS("filling region %p\n", base); 69 for (int i = 0; i < retsize; i++) { 70 base[i] = i % 256; 71 } 72 sys_debug_flush_cache(); 73 DEBUG_MODIFY_FLAGS("checking region %p\n", base); 74 // check 75 for (int i = 0; i < retsize; i++) { 76 if (base[i] != i % 256) { 77 debug_printf("failed at %d\n", i); 78 } 79 assert(base[i] == i % 256); 80 } 81 sys_debug_flush_cache(); 82 // change region to read only 83 DEBUG_MODIFY_FLAGS("changing region %p perms to readonly\n", base); 84 err = memobj->f.protect(memobj, vregion, 0, retsize, VREGION_FLAGS_READ); 85 if (err_is_fail(err)) { 86 DEBUG_ERR(err, "protect"); 87 return 1; 88 } 89 // check (reads should not fault) 90 DEBUG_MODIFY_FLAGS("checking region %p\n", base); 91 printf("%d\n", base[0]); 92 for (int i = 0; i < retsize; i++) { 93 assert(base[i] == i % 256); 94 } 95 96 // register exception handler for writes 97 err = thread_set_exception_handler(handler, NULL, ex_stack, 98 ex_stack+EX_STACK_SIZE, NULL, NULL); 99 assert(err_is_ok(err)); 100 101 // this should fault 102 for (int i = 0; i < retsize / BASE_PAGE_SIZE; i++) { 103 DEBUG_MODIFY_FLAGS("provoke write pagefault on %p\n", base+i*BASE_PAGE_SIZE); 104 base[i * BASE_PAGE_SIZE] = 0x42; 105 } 106 107 printf("%s: done\n", __FUNCTION__); 108 return 0; 109} 110 111#ifdef STANDALONE 112int main(void) 113{ 114 return modify_flags(); 115} 116#endif 117