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:
parent
225ed6d7bd
commit
d12d57dcd8
@ -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,
|
static void pagefault( struct proc *pr,
|
||||||
reg_t *saved_lr,
|
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;
|
int in_physcopy = 0, in_memset = 0;
|
||||||
|
|
||||||
reg_t pagefault_addr, pagefault_status;
|
|
||||||
message m_pagefault;
|
message m_pagefault;
|
||||||
int err;
|
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) &&
|
in_physcopy = (*saved_lr > (vir_bytes) phys_copy) &&
|
||||||
(*saved_lr < (vir_bytes) phys_copy_fault);
|
(*saved_lr < (vir_bytes) phys_copy_fault);
|
||||||
|
|
||||||
@ -61,9 +54,6 @@ static void pagefault( struct proc *pr,
|
|||||||
|
|
||||||
if((is_nested || iskernelp(pr)) &&
|
if((is_nested || iskernelp(pr)) &&
|
||||||
catch_pagefaults && (in_physcopy || in_memset)) {
|
catch_pagefaults && (in_physcopy || in_memset)) {
|
||||||
#if 0
|
|
||||||
printf("pf caught! addr 0x%lx\n", pagefault_addr);
|
|
||||||
#endif
|
|
||||||
if (is_nested) {
|
if (is_nested) {
|
||||||
if(in_physcopy) {
|
if(in_physcopy) {
|
||||||
assert(!in_memset);
|
assert(!in_memset);
|
||||||
@ -153,6 +143,8 @@ void exception_handler(int is_nested, reg_t *saved_lr, int vector)
|
|||||||
|
|
||||||
ep = &ex_data[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
|
* handle special cases for nested problems as they might be tricky or filter
|
||||||
* them out quickly if the traps are not nested
|
* 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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ ENTRY(\exc_name\()_entry)
|
|||||||
/* save the pointer to the current process */
|
/* save the pointer to the current process */
|
||||||
ldr fp, [sp]
|
ldr fp, [sp]
|
||||||
/* save the exception pc (saved lr_user) */
|
/* save the exception pc (saved lr_user) */
|
||||||
ldr r4, [fp, #PCREG]
|
add r4, fp, #PCREG
|
||||||
|
|
||||||
/* stop user process cycles */
|
/* stop user process cycles */
|
||||||
mov r0, fp /* first param: caller proc ptr */
|
mov r0, fp /* first param: caller proc ptr */
|
||||||
|
@ -421,17 +421,6 @@ static void ser_debug(const int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_SERIAL
|
#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()
|
static void ser_dump_vfs()
|
||||||
{
|
{
|
||||||
|
@ -1894,3 +1894,15 @@ void release_fpu(struct proc * p) {
|
|||||||
if (*fpu_owner_ptr == p)
|
if (*fpu_owner_ptr == p)
|
||||||
*fpu_owner_ptr = NULL;
|
*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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user