From d12d57dcd872822ad7259dd7976c6a9bc89dee3e Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 21 May 2013 14:57:57 +0200 Subject: [PATCH] arm: recognize instruction fetch pagefault . an instruction fetch pagefault generates a prefetch abort exception, this should also be a source of a pagefault event . the saved_lr argument to the C exception handler was sometimes an address, sometimes a pointer to that address; the kernel sometimes dereferences it, so it should always be an in-kernel address, never a userspace address. fix in mpx.S makes it always a pointer. . move dumping of all processes over serial out of the arch-specific arch_system.c --- kernel/arch/earm/exception.c | 35 ++++++++++++++++++++-------------- kernel/arch/earm/mpx.S | 2 +- kernel/arch/i386/arch_system.c | 11 ----------- kernel/proc.c | 12 ++++++++++++ 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/kernel/arch/earm/exception.c b/kernel/arch/earm/exception.c index 2a2ca0f14..84b4fe62a 100644 --- a/kernel/arch/earm/exception.c +++ b/kernel/arch/earm/exception.c @@ -37,22 +37,15 @@ static void proc_stacktrace_execute(struct proc *whichproc, reg_t v_bp, reg_t pc static void pagefault( struct proc *pr, reg_t *saved_lr, - int is_nested) + int is_nested, + u32_t pagefault_addr, + u32_t pagefault_status) { int in_physcopy = 0, in_memset = 0; - reg_t pagefault_addr, pagefault_status; message m_pagefault; int err; - pagefault_addr = read_dfar(); - pagefault_status = read_dfsr(); - -#if 0 - printf("kernel: pagefault in pr %d, addr 0x%lx, his ttbr 0x%lx, actual ttbr 0x%lx\n", - pr->p_endpoint, pagefault_addr, pr->p_seg.p_ttbr, read_ttbr0()); -#endif - in_physcopy = (*saved_lr > (vir_bytes) phys_copy) && (*saved_lr < (vir_bytes) phys_copy_fault); @@ -61,9 +54,6 @@ static void pagefault( struct proc *pr, if((is_nested || iskernelp(pr)) && catch_pagefaults && (in_physcopy || in_memset)) { -#if 0 - printf("pf caught! addr 0x%lx\n", pagefault_addr); -#endif if (is_nested) { if(in_physcopy) { assert(!in_memset); @@ -153,6 +143,8 @@ void exception_handler(int is_nested, reg_t *saved_lr, int vector) ep = &ex_data[vector]; + assert((vir_bytes) saved_lr >= kinfo.vir_kern_start); + /* * handle special cases for nested problems as they might be tricky or filter * them out quickly if the traps are not nested @@ -179,7 +171,22 @@ void exception_handler(int is_nested, reg_t *saved_lr, int vector) } if (vector == DATA_ABORT_VECTOR) { - pagefault(saved_proc, saved_lr, is_nested); + pagefault(saved_proc, saved_lr, is_nested, read_dfar(), read_dfsr()); + return; + } + + if (!is_nested && vector == PREFETCH_ABORT_VECTOR) { + reg_t ifar = read_ifar(), ifsr = read_ifsr(); + + /* The saved_lr is the instruction we're going to execute after + * the fault is handled; IFAR is the address that pagefaulted + * while fetching the instruction. As far as we know the two + * should be the same, if not this assumption will lead to very + * hard to debug problems (instruction executing being off by one) + * and this assumption needs re-examining, hence the assert. + */ + assert(*saved_lr == ifar); + pagefault(saved_proc, saved_lr, is_nested, ifar, ifsr); return; } diff --git a/kernel/arch/earm/mpx.S b/kernel/arch/earm/mpx.S index 622bc83f9..dba2b8446 100644 --- a/kernel/arch/earm/mpx.S +++ b/kernel/arch/earm/mpx.S @@ -83,7 +83,7 @@ ENTRY(\exc_name\()_entry) /* save the pointer to the current process */ ldr fp, [sp] /* save the exception pc (saved lr_user) */ - ldr r4, [fp, #PCREG] + add r4, fp, #PCREG /* stop user process cycles */ mov r0, fp /* first param: caller proc ptr */ diff --git a/kernel/arch/i386/arch_system.c b/kernel/arch/i386/arch_system.c index 2c5e0931e..bb12b0682 100644 --- a/kernel/arch/i386/arch_system.c +++ b/kernel/arch/i386/arch_system.c @@ -421,17 +421,6 @@ static void ser_debug(const int c) } #if DEBUG_SERIAL -void ser_dump_proc() -{ - struct proc *pp; - - for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++) - { - if (isemptyp(pp)) - continue; - print_proc_recursive(pp); - } -} static void ser_dump_vfs() { diff --git a/kernel/proc.c b/kernel/proc.c index a15039315..e60e55071 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -1894,3 +1894,15 @@ void release_fpu(struct proc * p) { if (*fpu_owner_ptr == p) *fpu_owner_ptr = NULL; } + +void ser_dump_proc() +{ + struct proc *pp; + + for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++) + { + if (isemptyp(pp)) + continue; + print_proc_recursive(pp); + } +} -- 2.44.0