Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm32/arm32 The page and section fault handling pat...
details: https://anonhg.NetBSD.org/src/rev/156651eb011e
branches: trunk
changeset: 467353:156651eb011e
user: mycroft <mycroft%NetBSD.org@localhost>
date: Tue Mar 23 18:02:02 1999 +0000
description:
The page and section fault handling paths are essentially identical, so
combine them. This also fixes a performance issue, in that we always
faulted pages twice in order to write them.
diffstat:
sys/arch/arm32/arm32/fault.c | 304 +++++-------------------------------------
1 files changed, 38 insertions(+), 266 deletions(-)
diffs (truncated from 392 to 300 lines):
diff -r c13ff323d665 -r 156651eb011e sys/arch/arm32/arm32/fault.c
--- a/sys/arch/arm32/arm32/fault.c Tue Mar 23 17:55:03 1999 +0000
+++ b/sys/arch/arm32/arm32/fault.c Tue Mar 23 18:02:02 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fault.c,v 1.38 1999/03/23 17:14:35 mycroft Exp $ */
+/* $NetBSD: fault.c,v 1.39 1999/03/23 18:02:02 mycroft Exp $ */
/*
* Copyright (c) 1994-1997 Mark Brinicombe.
@@ -330,48 +330,29 @@
panic("Unhandled trap (frame = %p)", frame);
#endif /* DDB */
+ case FAULT_TRANS_P: /* Page Translation Fault */
+ case FAULT_PERM_P: /* Page Permission Fault */
+ case FAULT_TRANS_S: /* Section Translation Fault */
case FAULT_PERM_S: /* Section Permission Fault */
- /*
- * Section permission faults should not happen often.
- * Only from user processes mis-behaving.
- * If this happens from SVC mode then we are in trouble.
- */
- if (user == 0)
- goto we_re_toast;
-
- report_abort("", fault_status, fault_address, fault_pc);
- trapsignal(p, SIGSEGV, TRAP_CODE);
- break;
-
- case FAULT_PERM_P: /* Page Permission Fault */
- /* Ok we have a permission fault in user or kernel mode */
+ /*
+ * Page/section translation/permission fault -- need to fault in
+ * the page and possibly the page table page.
+ */
{
register vm_offset_t va;
register struct vmspace *vm = p->p_vmspace;
register vm_map_t map;
int rv;
vm_prot_t ftype;
+ extern vm_map_t kernel_map;
- /*
- * Ok we have a permission fault in user mode. This will be
- * caused by writing read-only pages or by reading/writing
- * pages with no USR access from USR mode. This may be
- * a genuine fault or it may be a bad access.
- * It can also be caused software PTE modified bit emulation
- */
va = trunc_page((vm_offset_t)fault_address);
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
- printf("page permission fault: addr=V%08lx ", va);
+ printf("page fault: addr=V%08lx ", va);
#endif
-
- if (va >= VM_MAXUSER_ADDRESS && user) {
- report_abort("", fault_status, fault_address, fault_pc);
- trapsignal(p, SIGSEGV, TRAP_CODE);
- break;
- }
-
+
/*
* It is only a kernel address space fault iff:
* 1. user == 0 and
@@ -380,10 +361,9 @@
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
- if (user == 0 && (va >= VM_MIN_KERNEL_ADDRESS
- || va <= VM_MIN_ADDRESS)) {
+ if (!user &&
+ (va >= VM_MIN_KERNEL_ADDRESS || va < VM_MIN_ADDRESS)) {
/* Was the fault due to the FPE/IPKDB ? */
-
if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
report_abort("UND32", fault_status,
fault_address, fault_pc);
@@ -399,285 +379,77 @@
userret(p, frame->tf_pc, p->p_sticks);
return;
}
-
- goto we_re_toast;
+ map = kernel_map;
} else
map = &vm->vm_map;
-#ifdef DIAGNOSTIC
- if (va == 0 && map == kernel_map) {
- printf("fault: bad kernel access at %lx\n", va);
- goto we_re_toast;
- }
-#endif
-
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("vmmap=%p ", 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.
- */
- ftype = VM_PROT_READ;
-
- /* STR instruction ? */
- if ((fault_instruction & 0x0c100000) == 0x04000000)
- ftype |= VM_PROT_WRITE;
- /* STM or CDT instruction ? */
- else if ((fault_instruction & 0x0a100000) == 0x08000000)
- ftype |= VM_PROT_WRITE;
- /* STRH, STRSH or STRSB instruction ? */
- else if ((fault_instruction & 0x0e100090) == 0x00000090)
- ftype |= VM_PROT_WRITE;
- /* SWP instruction ? */
- else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
- ftype |= VM_PROT_WRITE;
-
- if (pmap_modified_emulation(map->pmap, va))
- goto out;
- else {
- /* The page must be mapped to cause a permission fault. */
-#if defined(UVM)
- rv = uvm_fault(map, va, 0, ftype);
-#else
- rv = vm_fault(map, va, ftype, FALSE);
-#endif
-#ifdef PMAP_DEBUG
- if (pmap_debug_level >= 0)
- printf("fault result=%d\n", rv);
-#endif
- if (rv == KERN_SUCCESS)
- goto out;
-
- report_abort("", fault_status, fault_address, fault_pc);
- if (rv == KERN_RESOURCE_SHORTAGE) {
- printf("UVM: pid %d (%s), uid %d killed: "
- "out of swap\n", p->p_pid, p->p_comm,
- p->p_cred && p->p_ucred ?
- p->p_ucred->cr_uid : -1);
- trapsignal(p, SIGKILL, TRAP_CODE);
- } else {
- trapsignal(p, SIGSEGV, TRAP_CODE);
- }
- break;
- }
- break;
- }
-
- case FAULT_TRANS_P: /* Page Translation Fault */
- /* Ok page translation fault - The page does not exist */
- {
- register vm_offset_t va;
- register struct vmspace *vm = p->p_vmspace;
- register vm_map_t map;
- int rv;
- vm_prot_t ftype;
- extern vm_map_t kernel_map;
- u_int nss;
-
- va = trunc_page((vm_offset_t)fault_address);
-
-#ifdef PMAP_DEBUG
- if (pmap_debug_level >= 0)
- printf("page fault: addr=V%08lx ", va);
-#endif
-
- if (va >= VM_MAXUSER_ADDRESS && user) {
- report_abort("", fault_status, fault_address, fault_pc);
- trapsignal(p, SIGSEGV, TRAP_CODE);
- break;
- }
-
- /*
- * It is only a kernel address space fault iff:
- * 1. 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 (user == 0 && (va >= VM_MIN_KERNEL_ADDRESS
- || va < VM_MIN_ADDRESS))
- map = kernel_map;
- else
- map = &vm->vm_map;
-
-#ifdef PMAP_DEBUG
- if (pmap_debug_level >= 0)
- printf("vmmap=%p ", map);
-#endif
- if (pmap_handled_emulation(map->pmap, va))
- goto out;
-
- /*
* 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.
+ * responsible and determine if it was a read or write
+ * instruction.
*/
-
- ftype = VM_PROT_READ;
-
/* STR instruction ? */
if ((fault_instruction & 0x0c100000) == 0x04000000)
- ftype |= VM_PROT_WRITE;
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
/* STM or CDT instruction ? */
else if ((fault_instruction & 0x0a100000) == 0x08000000)
- ftype |= VM_PROT_WRITE;
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
/* STRH, STRSH or STRSB instruction ? */
else if ((fault_instruction & 0x0e100090) == 0x00000090)
- ftype |= VM_PROT_WRITE;
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
/* SWP instruction ? */
else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
- ftype |= VM_PROT_WRITE;
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
+ else
+ ftype = VM_PROT_READ;
#ifdef PMAP_DEBUG
if (pmap_debug_level >= 0)
printf("fault protection = %d\n", ftype);
#endif
-#ifdef DIAGNOSTIC
- if (va == 0 && map == kernel_map) {
- printf("trap: bad kernel access at %lx\n", va);
- goto we_re_toast;
- }
-#endif /* DIAGNOSTIC */
-
- nss = 0;
- if ((caddr_t)va >= vm->vm_maxsaddr
- && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
- && map != kernel_map) {
- nss = clrnd(btoc(USRSTACK-(u_int)va));
- if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
- rv = KERN_FAILURE;
- goto nogo;
- }
- }
+ if ((ftype & VM_PROT_WRITE) ?
+ pmap_modified_emulation(map->pmap, va) :
+ pmap_handled_emulation(map->pmap, va))
+ goto out;
#if defined(UVM)
rv = uvm_fault(map, va, 0, ftype);
#else
rv = vm_fault(map, va, ftype, FALSE);
#endif
- if (rv == KERN_SUCCESS) {
- if (nss > vm->vm_ssize)
- vm->vm_ssize = nss;
- if (fault_code == FAULT_TRANS_P)
- return;
+ if (rv == KERN_SUCCESS)
goto out;
- }
-nogo:
- if (user == 0) {
- if (pcb->pcb_onfault)
- goto copyfault;
- printf("Failed page fault in kernel\n");
- printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n",
- map, va, ftype, rv);
- goto we_re_toast;
- }
- report_abort("", fault_status, fault_address, fault_pc);
- trapsignal(p, SIGSEGV, TRAP_CODE);
- break;
- }
-
- case FAULT_TRANS_S: /* Section Translation Fault */
- /* Section translation fault - the L1 page table does not exist */
- {
- register vm_offset_t va;
- register struct vmspace *vm = p->p_vmspace;
- register vm_map_t map;
- int rv;
- vm_prot_t ftype;
- u_int nss;
-
Home |
Main Index |
Thread Index |
Old Index