1#include <pager/pager.h> 2#include <stdio.h> 3 4// hardcoded for ARM pmap (should get from pmap) 5#define VSPACE_BEGIN ((lvaddr_t)1UL*1024*1024*1024) // 1G 6 7static bool is_in_pmap(genvaddr_t vaddr) 8{ 9 struct pmap *pmap = get_current_pmap(); 10 11 errval_t err = pmap->f.lookup(pmap, vaddr, NULL); 12 return err_is_ok(err); 13} 14 15static errval_t alloc_4k(struct capref *retframe) 16{ 17 assert(retframe); 18 size_t frame_sz = 4096u; 19 errval_t err = frame_alloc(retframe, frame_sz, &frame_sz); 20 if (err_is_fail(err)) { 21 DEBUG_ERR(err, "frame_alloc"); 22 return err; 23 } 24 if (frame_sz > 4096) { 25 printf("alloc_4k: wasting %zu bytes of memory\n", frame_sz - 4096); 26 } 27 return SYS_ERR_OK; 28} 29 30static errval_t handle_pagefault(void *addr) 31{ 32 errval_t result = SYS_ERR_OK; 33 errval_t err; 34 genvaddr_t vaddr = vspace_lvaddr_to_genvaddr((lvaddr_t)addr); 35 if (vaddr > VSPACE_BEGIN) { 36 if (is_in_pmap(vaddr)) { 37 printf("handle_pagefault: returning -- mapping exists already in pmap?\n"); 38 } else { 39 printf("handle_pagefault: no mapping for address, allocating frame\n"); 40 struct capref frame; 41 err = alloc_4k(&frame); 42 if (err_is_fail(err)) { 43 DEBUG_ERR(err, "alloc_4k"); 44 } 45 struct pmap *pmap = get_current_pmap(); 46 err = pmap->f.map(pmap, vaddr, frame, 0, 4096, 47 VREGION_FLAGS_READ_WRITE, NULL, NULL); 48 if (err_is_fail(err)) { 49 DEBUG_ERR(err, "pmap->f.map"); 50 } 51 printf("handle_pagefault: returning -- did install page\n"); 52 return SYS_ERR_OK; 53 } 54 } else { 55 printf("handle_pagefault: invalid access to %p (< 0x%" PRIxLVADDR ")\n", addr, VSPACE_BEGIN); 56 // TODO: good error code 57 return LIB_ERR_PMAP_ADDR_NOT_FREE; 58 } 59 60 return result; 61} 62 63static void exn_handler(enum exception_type type, int subtype, 64 void *addr, arch_registers_state_t *regs) 65{ 66 printf("exn_handler: exception type=%d, subtype=%d, addr=%p\n", 67 type, subtype, addr); 68 errval_t err; 69 if (type == EXCEPT_PAGEFAULT) { 70 err = handle_pagefault(addr); 71 if (err_is_fail(err)) { 72 // could not handle page fault, exiting for now 73 // TODO: do something sensible here 74 exit(1); 75 } 76 } else { 77 printf("exn_handler: don't know what to do with exception type %d\n", type); 78 } 79 return; 80} 81 82#define INTERNAL_STACK_SIZE (1<<14) 83static char internal_ex_stack[INTERNAL_STACK_SIZE]; 84 85errval_t pager_install_handler(char *ex_stack, size_t stack_size) 86{ 87 // setup exception stack pointers 88 char *ex_stack_top = NULL; 89 if (ex_stack && stack_size >= 4096u) { 90 ex_stack_top = ex_stack + stack_size; 91 } else { // use our exception stack region 92 ex_stack = internal_ex_stack; 93 ex_stack_top = ex_stack + INTERNAL_STACK_SIZE; 94 } 95 assert(ex_stack); 96 assert(ex_stack_top); 97 98 exception_handler_fn old_handler; 99 errval_t err; 100 void *old_stack_base, *old_stack_top; 101 102 err = thread_set_exception_handler(exn_handler, &old_handler, 103 ex_stack, ex_stack_top, &old_stack_base, &old_stack_top); 104 if (err_is_fail(err)) { 105 DEBUG_ERR(err, "thread_set_exception_handler"); 106 } 107 return 0; 108} 109