diff --git a/include/aos/paging_types.h b/include/aos/paging_types.h index c13fd3d..a7ed8b0 100644 --- a/include/aos/paging_types.h +++ b/include/aos/paging_types.h @@ -17,6 +17,7 @@ #include +#define VADDR_LOWEST_NON_NULL (64 * 1024) #define VADDR_OFFSET ((lvaddr_t)512UL*1024*1024*1024) // 1GB #define VADDR_SIZE (1UL << 48) #define VREGION_FLAGS_READ 0x01 // Reading allowed diff --git a/lib/aos/paging.c b/lib/aos/paging.c index dd8837e..b8c6d38 100644 --- a/lib/aos/paging.c +++ b/lib/aos/paging.c @@ -21,8 +21,6 @@ #include #include -static struct paging_state current; - #define PT_PT_SLAB_MIN_SPACE 18 #define PT_CHILDREN_SLAB_MIN_SPACE 12 @@ -30,6 +28,62 @@ static struct paging_state current; #define PT_PT_SLAB_INITIAL_SPACE SLAB_STATIC_SIZE(PT_PT_SLAB_MIN_SPACE, PT_META_MAX_SIZE) #define PT_CHILDREN_SLAB_INITIAL_SPACE SLAB_STATIC_SIZE(PT_CHILDREN_SLAB_MIN_SPACE, PT_CHILD_ARRAY_SIZE) +#define PT_STATIC_EXCEPTION_STACK_SIZE (4 * BASE_PAGE_SIZE) + +static struct paging_state current; +// initial page fault handler stack space +static char pt_static_exception_stack[PT_STATIC_EXCEPTION_STACK_SIZE]; + +static char *pt_exception_type_to_string(enum exception_type type, int subtype) +{ + switch(type) { + case EXCEPT_NULL: + return "EXCEPT_NULL"; + case EXCEPT_PAGEFAULT: + switch(subtype) { + case PAGEFLT_NULL: + return "EXCEPT_PAGEFAULT(Not mapped)"; + case PAGEFLT_READ: + return "EXCEPT_PAGEFAULT(READ)"; + case PAGEFLT_WRITE: + return "EXCEPT_PAGEFAULT(WRITE)"; + case PAGEFLT_EXEC: + return "EXCEPT_PAGEFAULT(EXEC)"; + default: + USER_PANIC("EXCEPT_PAGEFAULT has invalid subtype") + } + case EXCEPT_BREAKPOINT: + return "EXCEPT_BREAKPOINT"; + case EXCEPT_SINGLESTEP: + return "EXCEPT_SINGLESTEP"; + case EXCEPT_OTHER: + return "EXCEPT_OTHER"; + default: + USER_PANIC("Got invalid page fault type") + } +} + +static void pt_exception_handler(enum exception_type type, int subtype, + void *addr, arch_registers_state_t *regs) +{ + lvaddr_t ip = registers_get_ip(regs); + + debug_printf("Page Fault: type=%s, addr=%p, ip=%p\n", + pt_exception_type_to_string(type, subtype), + addr, + ip + ); + // debug_print_save_area(regs); + // debug_dump(regs); + + // abort on NULL pointer dereference + if(addr < (void *) VADDR_LOWEST_NON_NULL) { + USER_PANIC("[ERROR] NULL pointer dereference"); + } + + USER_PANIC("[ERROR] Page fault handling not yet implemented"); +} + /** * \brief Helper function that allocates a slot and * creates a aarch64 page table capability for a certain level @@ -330,7 +384,7 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr errval_t paging_init_params(struct spawn_domain_params *params) { errval_t err; - // debug_printf("paging_init\n"); + debug_printf("paging_init\n"); // (M2): Call paging_init_state for ¤t // TODO (M4): initialize self-paging handler // TIP: use thread_set_exception_handler() to setup a page fault handler @@ -355,6 +409,12 @@ errval_t paging_init_params(struct spawn_domain_params *params) // pt_print_state(¤t); } + // TODO rueegges: not sure this is sufficient? + err = thread_set_exception_handler(pt_exception_handler, NULL, (void*) pt_static_exception_stack, (void*) pt_static_exception_stack + PT_STATIC_EXCEPTION_STACK_SIZE, NULL, NULL); + if (err_is_fail(err)) { + return err_push(err, LIB_ERR_VREGION_PAGEFAULT_HANDLER); + } + set_current_paging_state(¤t); return SYS_ERR_OK; } @@ -381,7 +441,26 @@ errval_t paging_init_onthread(struct thread *t) { // TODO (M4): // - setup exception handler for thread `t'. - return LIB_ERR_NOT_IMPLEMENTED; + errval_t err; + + debug_printf("paging_init_onthread thread id: %lx\n", t->id); + + // TODO rueegges: Is this how we are supposed to get the exception handler stack? + size_t stack_size = PT_STATIC_EXCEPTION_STACK_SIZE; + struct capref frame; + err = frame_alloc(&frame, stack_size, &stack_size); + if (err_is_fail(err)) { + return err_push(err, LIB_ERR_FRAME_ALLOC); + } + + void *stack_base; + paging_map_frame(get_current_paging_state(), &stack_base, stack_size, frame); + + t->exception_handler = pt_exception_handler; + t->exception_stack = stack_base; + t->exception_stack_top = stack_base + stack_size; + + return SYS_ERR_OK; } diff --git a/lib/aos/threads.c b/lib/aos/threads.c index a59f54d..59f5a93 100644 --- a/lib/aos/threads.c +++ b/lib/aos/threads.c @@ -1110,6 +1110,10 @@ static int bootstrap_thread(struct spawn_domain_params *params) // Until we have self-paging, we cannot use the paging-region based thread // control block slab allocator, so just run main thread directly #ifndef SELF_PAGING_WORKS + // TODO rueegges: remove this when SELF_PAGING_WORKS. + // this is required to create threads for testing before we have self paging + size_t blocksize = sizeof(struct thread) + tls_block_total_len + THREAD_ALIGNMENT; + slab_init(&thread_slabs, blocksize, slab_default_refill); // we aren't prepared to run real threads yet main_thread(params); #else diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index 6f2235b..de3feb3 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -461,7 +461,7 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, struct paging_state _child_paging_state; struct paging_state *child_paging_state = &_child_paging_state; // 64 * 1024 is enough to catch null pointers and also enough to not conflict with child starting paging_alloc at VADDR_OFFSET - err = paging_init_state_foreign(child_paging_state, 64 * 1024, si->vspace_cap_l0_pagetable, get_default_slot_allocator()); + err = paging_init_state_foreign(child_paging_state, VADDR_LOWEST_NON_NULL, si->vspace_cap_l0_pagetable, get_default_slot_allocator()); if (err_is_fail(err)) return err_push(err, SPAWN_ERR_PAGING_INIT); // - Load the ELF binary diff --git a/usr/hello/hello.c b/usr/hello/hello.c index 7c54e04..8aa834a 100644 --- a/usr/hello/hello.c +++ b/usr/hello/hello.c @@ -26,10 +26,21 @@ #define HELLO_CMDLINE_READ_LEN 100 +static int null_dereference(void *ignored) { + debug_printf("[null_dereference] Oh no! :O\n"); + // cause a page fault (slight offset from null simulates NULL struct field access) + *((volatile char *)(NULL + 7)); + return 1; +} + int main(int argc, char *argv[]) { errval_t err; printf("Hello, world!\n"); + + // test page fault handling by doing a null dereference on a different thread + thread_create(null_dereference, NULL); + barrelfish_usleep(10000000); printf("argv:\n"); for(int i = 0; i < argc; ++i) {