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
This commit is contained in:
Ben Gras 2013-05-21 14:57:57 +02:00
parent 225ed6d7bd
commit d12d57dcd8
4 changed files with 34 additions and 26 deletions

View file

@ -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;
}

View file

@ -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 */

View file

@ -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()
{

View file

@ -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);
}
}