Cleanup up and correctly indented lots of comments.

Removed all the VALIDATE_TRAPFRAME junk.
Generally spring cleaned the code.
This commit is contained in:
mark 1997-10-14 11:19:15 +00:00
parent 6aca6ab9a4
commit 5be47da72c
1 changed files with 190 additions and 185 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: fault.c,v 1.14 1997/07/31 00:16:12 mark Exp $ */
/* $NetBSD: fault.c,v 1.15 1997/10/14 11:19:15 mark Exp $ */
/*
* Copyright (c) 1994-1997 Mark Brinicombe.
@ -46,14 +46,10 @@
/*
* Special compilation symbols
*
* DEBUG_FAULT_CORRECTION - Add debug code used to develop the register
* correction following a data abort.
*
* CONTINUE_AFTER_SVC_PREFETCH - Do not panic following a prefetch abort
* in SVC mode. Used during developement.
*/
#define DEBUG_FAULT_CORRECTION
/*#define CONTINUE_AFTER_SVC_PREFETCH*/
#include <sys/types.h>
@ -71,7 +67,12 @@
#include <machine/pte.h>
#include <machine/irqhandler.h>
#ifndef POSTMORTEM
#define postmortem(x)
#endif /* POSTMORTEM */
#ifdef PMAP_DEBUG
extern int pmap_debug_level;
#endif /* PMAP_DEBUG */
static int onfault_count = 0;
int pmap_modified_emulation __P((pmap_t, vm_offset_t));
@ -125,13 +126,13 @@ data_abort_handler(frame)
u_int fault_status;
u_int fault_pc;
u_int fault_instruction;
u_int s;
int s;
int fault_code;
u_quad_t sticks = 0;
int saved_lr = 0;
int error;
/*
* Enable IRQ's and FIQ's (disabled by CPU on abort) if trapframe
* Enable IRQ's (disabled by CPU on abort) if trapframe
* shows they were enabled.
*/
@ -152,22 +153,45 @@ data_abort_handler(frame)
fault_instruction = ReadWord(fault_pc);
/* More debug stuff */
s = spltty();
if (pmap_debug_level >= 0) {
#ifdef DIAGNOSTIC
if (current_intr_depth > 0) {
#ifdef DDB
printf("Fault with intr_depth > 0\n");
printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
aborts[fault_status & 0xf], fault_status & 0xfff,
fault_address, fault_pc);
printf("Instruction @V%08x = %08x\n",
fault_pc, fault_instruction);
Debugger();
#else
panic("Fault with intr_depth > 0\n");
#endif /* DDB */
}
if (cpu_dataabt_fixup(frame))
panic("fixup failed\n");
#endif /* DIAGNOSTIC */
(void)splx(s);
/* More debug stuff */
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0) {
s = spltty();
printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
aborts[fault_status & 0xf], fault_status & 0xfff,
fault_address, fault_pc);
printf("Instruction @V%08x = %08x\n",
fault_pc, fault_instruction);
(void)splx(s);
}
#endif
/* Call the cpu specific abort fixup routine */
error = cpu_dataabt_fixup(frame);
if (error == ABORT_FIXUP_RETURN)
return;
if (error == ABORT_FIXUP_FAILED)
panic("data abort fixup failed\n");
/* Extract the fault code from the fault status */
@ -178,8 +202,10 @@ data_abort_handler(frame)
if ((p = curproc) == 0)
p = &proc0;
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("fault in process %08x\n", (u_int)p);
#endif
/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
@ -218,9 +244,6 @@ copyfault:
if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
panic("Yikes pcb_onfault=%08x during USR mode fault\n",
(u_int)pcb->pcb_onfault);
#ifdef VALIDATE_TRAPFRAME
validate_trapframe(frame, 1);
#endif
#ifdef PORTMASTER
++onfault_count;
if (onfault_count == 10) {
@ -319,18 +342,21 @@ copyfault:
int rv;
vm_prot_t ftype;
/*
* Ok we have a permission fault in user mode. The only cause must be
* that a read only page has been written to. This may be genuine or it
* may be a bad access. In the future it may also be cause by the software
* emulation of the modified flag.
*/
/*
* Ok we have a permission fault in user mode. The only cause
* must be that a read only page has been written to. This may
* be genuine or it may be a bad access. In the future it may
* also be cause by the software emulation of the modified
* flag.
*/
va = trunc_page((vm_offset_t)fault_address);
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("ok we have a page permission fault - addr=V%08x ",
(u_int)va);
#endif
if ((fault_code & FAULT_USER) && va >= VM_MAXUSER_ADDRESS) {
printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
@ -341,14 +367,14 @@ copyfault:
break;
}
/*
* It is only a kernel address space fault iff:
* 1. (fault_code & FAULT_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
/*
* It is only a kernel address space fault iff:
* 1. (fault_code & FAULT_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
if ((fault_code & FAULT_USER) == 0
&& (va >= KERNEL_BASE || va <= VM_MIN_ADDRESS)) {
@ -358,9 +384,17 @@ copyfault:
printf("UND32 Data abort: '%s' status = %03x address = %08x PC = %08x\n",
aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
fault_pc);
postmortem(frame);
postmortem(frame);
trapsignal(p, SIGSEGV, TRAP_CODE);
goto out;
/*
* Force exit via userret()
* This is necessary as the FPE is an extension to userland
* that actually runs in a priveldged mode but uses USR mode
* permissions for its accesses.
*/
userret(p, frame->tf_pc, p->p_sticks);
return;
}
printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
@ -378,15 +412,19 @@ copyfault:
}
#endif
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("vmmap=%08x ", (u_int)map);
#endif
/*
* We need to know whether the page should be mapped as R or R/W.
* The MMU does not give us the info as to whether the fault was caused
* by a read or a write. This means we need to disassemble the instruction
* responcible and determine if it was a read or write instruction.
*/
/*
* We need to know whether the page should be mapped as
* R or R/W. The MMU does not give us the info as to
* whether the fault was caused by a read or a write.
* This means we need to disassemble the instruction
* responcible and determine if it was a read or write
* instruction.
*/
ftype = VM_PROT_READ;
@ -404,12 +442,13 @@ copyfault:
if (pmap_modified_emulation(map->pmap, va))
goto out;
else {
/* The page must be mapped to cause a permission fault. */
/* The page must be mapped to cause a permission fault. */
rv = vm_fault(map, va, ftype, FALSE);
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("fault result=%d\n", rv);
#endif
if (rv == KERN_SUCCESS)
goto out;
printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
@ -448,7 +487,7 @@ copyfault:
case FAULT_TRANS_P: /* Page Translation Fault */
case FAULT_TRANS_P | FAULT_USER: /* Page Translation Fault */
/* Ok page translation fault - The page does not exist */
/* Ok page translation fault - The page does not exist */
{
register vm_offset_t va;
register struct vmspace *vm = p->p_vmspace;
@ -460,8 +499,10 @@ copyfault:
va = trunc_page((vm_offset_t)fault_address);
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("ok we have a page fault - addr=V%08x ", (u_int)va);
#endif
if ((fault_code & FAULT_USER) && va >= VM_MAXUSER_ADDRESS) {
printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
@ -472,14 +513,14 @@ copyfault:
break;
}
/*
* It is only a kernel address space fault iff:
* 1. (fault_code & FAULT_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
/*
* It is only a kernel address space fault iff:
* 1. (fault_code & FAULT_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
if (fault_code == FAULT_TRANS_P
&& (va >= KERNEL_BASE || va < VM_MIN_ADDRESS))
@ -487,37 +528,42 @@ copyfault:
else
map = &vm->vm_map;
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("vmmap=%08x ", (u_int)map);
#endif
if (pmap_handled_emulation(map->pmap, va))
goto out;
/* debug_show_vm_map(map, "fault");*/
/* We need to know whether the page should be mapped as R or R/W.
* The MMU does not give us the info as to whether the fault was caused
* by a read or a write. This means we need to disassemble the instruction
* responcible and determine if it was a read or write instruction.
* For the moment we will cheat and make it read only. If it was a write
* When the instruction is re-executed we will get a permission fault
* instead.
*/
/*
* We need to know whether the page should be mapped
* as R or R/W. The MMU does not give us the info as
* to whether the fault was caused by a read or a write.
* This means we need to disassemble the instruction
* responcible and determine if it was a read or write
* instruction. For the moment we will cheat and make
* it read only. If it was a write, when the instruction
* is re-executed we will get a permission fault instead.
*/
ftype = VM_PROT_READ;
/* STR instruction ? */
/* STR instruction ? */
if ((fault_instruction & 0x0c100000) == 0x04000000)
ftype |= VM_PROT_WRITE;
/* STM instruction ? */
/* STM instruction ? */
else if ((fault_instruction & 0x0a100000) == 0x08000000)
ftype |= VM_PROT_WRITE;
/* SWP instruction ? */
/* SWP instruction ? */
else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
ftype |= VM_PROT_WRITE;
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("fault protection = %d\n", ftype);
#endif
#ifdef DIAGNOSTIC
if (va == 0 && map == kernel_map) {
@ -537,7 +583,7 @@ copyfault:
}
}
/* check if page table is mapped, if not, fault it first */
/* check if page table is mapped, if not, fault it first */
/*
if (*(((pt_entry_t **)(PROCESS_PAGE_TBLS_BASE + va >> (PD_SHIFT+2)))[]) == 0)
@ -550,10 +596,10 @@ copyfault:
if (nss > vm->vm_ssize)
vm->vm_ssize = nss;
va = trunc_page(vtopte(va));
/*
* for page table, increment wiring as long as not a page
* table fault as well
*/
/*
* for page table, increment wiring as long as not
* a page table fault as well
*/
if (map != kernel_map)
vm_map_pageable(map, va, round_page(va+1), FALSE);
if (fault_code == FAULT_TRANS_P)
@ -573,7 +619,7 @@ nogo:
aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
fault_pc);
disassemble(fault_pc);
postmortem(frame);
postmortem(frame);
trapsignal(p, SIGSEGV, TRAP_CODE);
break;
}
@ -582,7 +628,7 @@ nogo:
case FAULT_TRANS_S: /* Section Translation Fault */
case FAULT_TRANS_S | FAULT_USER: /* Section Translation Fault */
/* Section translation fault - the L1 page table does not exist */
/* Section translation fault - the L1 page table does not exist */
{
register vm_offset_t va;
register struct vmspace *vm = p->p_vmspace;
@ -593,18 +639,20 @@ nogo:
va = trunc_page((vm_offset_t)fault_address);
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("ok we have a section fault page addr=V%08x\n",
(u_int)va);
#endif
/*
* It is only a kernel address space fault iff:
* 1. (fault_code & FAULT_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
/*
* It is only a kernel address space fault iff:
* 1. (fault_code & FAULT_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
if (fault_code == FAULT_TRANS_S && va >= KERNEL_BASE)
map = kernel_map;
@ -616,7 +664,7 @@ nogo:
debug_show_vm_map(kernel_map, "kernel");
*/
/* We are mapping a page table so this must be kernel r/w */
/* We are mapping a page table so this must be kernel r/w */
ftype = VM_PROT_READ | VM_PROT_WRITE;
#ifdef DIAGNOSTIC
@ -640,25 +688,29 @@ nogo:
}
}
/* check if page table is mapped, if not, fault it first */
/* check if page table is mapped, if not, fault it first */
v = trunc_page(vtopte(va));
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("v=%08x\n", v);
#endif
rv = vm_fault(map, v, ftype, FALSE);
if (rv != KERN_SUCCESS)
goto nogo1;
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("vm_fault succeeded\n");
/* update increment wiring as this is a page table fault */
#endif
/* update increment wiring as this is a page table fault */
vm_map_pageable(map, v, round_page(v+1), FALSE);
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("faulting in page %08x\n", (u_int)va);
#endif
ftype = VM_PROT_READ;
rv = vm_fault(map, va, ftype, FALSE);
@ -666,10 +718,10 @@ nogo:
if (nss > vm->vm_ssize)
vm->vm_ssize = nss;
va = trunc_page(vtopte(va));
/*
* for page table, increment wiring as long as not a page
* table fault as well
*/
/*
* for page table, increment wiring as long as not
* a page table fault as well
*/
if (!v && map != kernel_map)
vm_map_pageable(map, va, round_page(va+1), FALSE);
if (fault_code == FAULT_TRANS_S)
@ -697,17 +749,20 @@ nogo1:
break;*/
default :
/* Are there any combinations I have missed ? */
/* Are there any combinations I have missed ? */
printf("fault status = %08x fault code = %08x\n",
fault_status, fault_code);
we_re_toast:
/* Were are dead, try and provide some debug infomation before dying */
/*
* Were are dead, try and provide some debug
* infomation before dying
*/
postmortem(frame);
panic("Fault cannot be handled\n");
panic("Fault cannot be handled (frame = %p)\n", frame);
break;
}
@ -715,14 +770,7 @@ out:
if ((fault_code & FAULT_USER) == 0)
return;
#ifdef VALIDATE_TRAPFRAME
validate_trapframe(frame, 1);
#endif
userret(p, frame->tf_pc, sticks);
#ifdef VALIDATE_TRAPFRAME
validate_trapframe(frame, 1);
#endif
}
@ -752,22 +800,24 @@ prefetch_abort_handler(frame)
int fault_code;
u_quad_t sticks;
pt_entry_t *pte;
/* Debug code */
int error;
#ifdef DIAGNOSTIC
/* Paranoia: We should always be in SVC32 mode at this point */
if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
s = spltty();
printf("fault being handled in non SVC32 mode\n");
postmortem(frame);
#ifdef PMAP_DEBUG
pmap_debug_level = 0;
#endif
(void)splx(s);
panic("Fault handler not in SVC mode\n");
}
#endif /* DIAGNOSTIC */
/*
* Enable IRQ's & FIQ's (disabled by the abort) This always comes
* Enable IRQ's (disabled by the abort) This always comes
* from user mode so we know interrupts were not disabled.
* But we check anyway.
*/
@ -781,10 +831,13 @@ prefetch_abort_handler(frame)
cnt.v_trap++;
#ifdef notyet
if (cpu_prefetchabt_fixup(frame))
panic("fixup failed\n");
#endif
/* Call the cpu specific abort fixup routine */
error = cpu_prefetchabt_fixup(frame);
if (error == ABORT_FIXUP_RETURN)
return;
if (error == ABORT_FIXUP_FAILED)
panic("prefetch abort fixup failed\n");
/* Get the current proc structure or proc0 if there is none */
@ -793,9 +846,10 @@ prefetch_abort_handler(frame)
printf("Prefetch about with curproc == 0\n");
}
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("prefetch fault in process %08x %s\n", (u_int)p, p->p_comm);
#endif
/*
* can't use curpcb, as it might be NULL; and we have p in a
* register anyway
@ -814,10 +868,15 @@ prefetch_abort_handler(frame)
}
#endif /* DIAGNOSTIC */
/* Was the prefectch abort from USR32 mode ? */
if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
sticks = p->p_sticks;
/* Modify the fault_code to reflect the USR/SVC state at time of fault */
/*
* Modify the fault_code to reflect the USR/SVC state
* at time of fault
*/
fault_code |= FAULT_USER;
p->p_md.md_regs = frame;
@ -830,13 +889,13 @@ prefetch_abort_handler(frame)
postmortem(frame);
#ifdef CONTINUE_AFTER_SVC_PREFETCH
printf("prefetch abort in SVC mode !\n");
printf("prefetch abort in non-USR mode !\n");
printf("The system should now be considered very unstable :-)\n");
sigexit(curproc, SIGILL);
/* Not reached */
panic("prefetch_abort_handler: How did we get here ?\n");
#else
panic("Prefetch abort in SVC mode\n");
panic("Prefetch abort in non-USR mode (frame=%p)\n", frame);
#endif /* CONTINUE_AFTER_SVC_PREFETCH */
}
@ -844,22 +903,40 @@ prefetch_abort_handler(frame)
fault_pc = frame->tf_pc;
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("prefetch_abort: PC = %08x\n", fault_pc);
#endif
/* Ok validate the address, can only execute in USER space */
if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
s = spltty();
printf("prefetch: pc (%08x) not in user process space\n",
fault_pc);
postmortem(frame);
/* postmortem(frame);*/
trapsignal(p, SIGSEGV, fault_pc);
(void)splx(s);
userret(p, frame->tf_pc, sticks);
return;
}
/* Is the page already mapped ? */
/* This is debugging for rev K SA110 silicon */
pte = pmap_pte(p->p_vmspace->vm_map.pmap, (vm_offset_t)fault_pc);
if (pte && *pte != 0) {
if (kernel_debug & 1) {
printf("prefetch_abort: page is already mapped - pte=%08x *pte=%08x\n",
pte, *pte);
printf("prefetch_abort: pc=%08x proc=%08x process=%s\n", fault_pc, p, p->p_comm);
printf("prefetch_abort: far=%08x fs=%x\n", cpu_faultaddress(), cpu_faultstatus());
printf("prefetch_abort: trapframe=%08x\n", (u_int)frame);
}
#ifdef DDB
if (kernel_debug & 2)
Debugger();
#endif
}
/* Ok read the fault address. This will fault the page in for us */
if (fetchuserword(fault_pc, &fault_instruction) != 0) {
@ -874,6 +951,7 @@ prefetch_abort_handler(frame)
#ifdef DIAGNOSTIC
/* More debug stuff */
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0) {
s = spltty();
printf("Instruction @V%08x = %08x\n", fault_pc,
@ -889,84 +967,11 @@ prefetch_abort_handler(frame)
(void)splx(s);
}
#endif /* PMAP_DEBUG */
#endif /* DIAGNOSTIC */
}
#ifdef VALIDATE_TRAPFRAME
validate_trapframe(frame, 4);
#endif
userret(p, frame->tf_pc, sticks);
#ifdef VALIDATE_TRAPFRAME
validate_trapframe(frame, 2);
#endif
}
#ifdef VALIDATE_TRAPFRAME
void
validate_trapframe(frame, where)
trapframe_t *frame;
int where;
{
char *ptr;
u_int mode;
if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
printf("VTF Warning : validate_trapframe : Not in SVC32 mode\n");
mode = frame->tf_spsr & PSR_MODE;
switch (where) {
case 1:
ptr = "data abort handler";
break;
case 2:
ptr = "prefetch abort handler";
if (mode != PSR_USR32_MODE)
printf("VTF Warning : %s : not USR32 mode\n", ptr);
break;
case 3:
ptr = "ast handler";
if (mode != PSR_USR32_MODE)
printf("VTF Warning : %s : not USR32 mode\n", ptr);
break;
case 4:
ptr = "syscall handler";
if (mode != PSR_USR32_MODE)
printf("VTF Warning : %s : not USR32 mode\n", ptr);
break;
case 5:
ptr = "undefined handler";
if (mode != PSR_USR32_MODE)
printf("VTF Warning : %s : not USR32 mode\n", ptr);
break;
case 6:
ptr = "sigreturn handler";
if (mode != PSR_USR32_MODE)
printf("VTF Warning : %s : not USR32 mode\n", ptr);
break;
default:
ptr = "unknown handler";
break;
}
if (frame->tf_usr_sp >= VM_MAXUSER_ADDRESS)
printf("VTF WARNING: %s : frame->tf_usr_sp >= VM_MAXUSER_ADDRESS [%08x]\n", ptr, frame->tf_usr_sp);
if (frame->tf_svc_lr >= 0xf1000000)
printf("VTF WARNING: %s : frame->tf_svc_lr >= 0xf1000000 [%08x]\n", ptr, frame->tf_svc_lr);
if (frame->tf_pc >= 0xf1000000)
printf("VTF WARNING: %s: frame->tf_pc >= 0xf1000000 [%08x]\n", ptr, frame->tf_pc);
if (frame->tf_pc < VM_MIN_ADDRESS)
printf("VTF WARNING: %s: frame->tf_pc >= VM_MIN_ADDRESS [%08x]\n", ptr, frame->tf_pc);
if (mode != PSR_USR32_MODE) {
if (frame->tf_svc_lr < 0xf0000000)
printf("VTF WARNING: %s : frame->tf_svc_lr < 0xf0000000 [%08x]\n", ptr, frame->tf_svc_lr);
if (frame->tf_pc < 0xf0000000)
printf("VTF WARNING: %s: frame->tf_pc < 0xf0000000 [%08x]\n", ptr, frame->tf_pc);
}
}
#endif /* VALIDATE_TRAPFRAME */
/* End of fault.c */