Overhaul arm32's abort handlers:

- Assume a permission fault is always the result of an attempted
   write, so no need to disassemble the opcode.
   (as discussed with Richard Earnshaw/Jason Thorpe a week or two ago)

 - Split out non-MMU data aborts into separate functions, and deal
   correctly with XScale imprecise aborts. Specifically, the old code
   made no attempt to handle the double abort faults which can occur
   as a result of two consecutive external (imprecise) aborts. This
   was easy to provoke by read(2)ing from a /dev/mem offset which caused
   an external abort. With the old code, this would bring the system
   down instantly, with little clue as to why. (hint: tf_spsr held
   PSR_ABT32_MODE...)

 - Re-write badaddr_read() to use pcb_onfault instead of adding extra
   overhead to data_abort_handler(). A side effect of this is that it
   now benefits from the XScale double abort recovery.

 - Invoke the cpu-specific prefetch/data abort fixup routines only if
   the host cpu actually needs it. On other cpus, the code is optimised
   away.

 - Sprinkle __predict_{false,true} in all the right places.

 - G/C some excess debugging baggage.
This commit is contained in:
scw 2003-10-31 16:30:15 +00:00
parent 2564505612
commit 336806eb55
4 changed files with 648 additions and 527 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: bcopyinout.S,v 1.11 2003/10/13 21:22:40 scw Exp $ */
/* $NetBSD: bcopyinout.S,v 1.12 2003/10/31 16:30:15 scw Exp $ */
/*
* Copyright (c) 2002 Wasabi Systems, Inc.
@ -45,7 +45,7 @@
#include "bcopyinout_xscale.S"
#else
RCSID("$NetBSD: bcopyinout.S,v 1.11 2003/10/13 21:22:40 scw Exp $")
RCSID("$NetBSD: bcopyinout.S,v 1.12 2003/10/31 16:30:15 scw Exp $")
.text
.align 0
@ -712,3 +712,89 @@ ENTRY(kcopy)
mov pc, lr
#endif /* !__XSCALE__ */
#ifdef __PROG32
/*
* int badaddr_read_1(const uint8_t *src, uint8_t *dest)
*
* Copies a single 8-bit value from src to dest, returning 0 on success,
* else EFAULT if a page fault occurred.
*/
ENTRY(badaddr_read_1)
#ifdef MULTIPROCESSOR
/* XXX Probably not appropriate for non-Hydra SMPs */
stmfd sp!, {r0-r1, r14}
bl _C_LABEL(cpu_number)
ldr r2, .Lcpu_info
ldr r2, [r2, r0, lsl #2]
ldr r2, [r2, #CI_CURPCB]
ldmfd sp!, {r0-r1, r14}
#else
ldr r2, .Lcurpcb
ldr r2, [r2]
#endif
ldr ip, [r2, #PCB_ONFAULT]
adr r3, 1f
str r3, [r2, #PCB_ONFAULT]
ldrb r3, [r0]
strb r3, [r1]
mov r0, #0 /* No fault */
1: str ip, [r2, #PCB_ONFAULT]
mov pc, lr
/*
* int badaddr_read_2(const uint16_t *src, uint16_t *dest)
*
* Copies a single 16-bit value from src to dest, returning 0 on success,
* else EFAULT if a page fault occurred.
*/
ENTRY(badaddr_read_2)
#ifdef MULTIPROCESSOR
/* XXX Probably not appropriate for non-Hydra SMPs */
stmfd sp!, {r0-r1, r14}
bl _C_LABEL(cpu_number)
ldr r2, .Lcpu_info
ldr r2, [r2, r0, lsl #2]
ldr r2, [r2, #CI_CURPCB]
ldmfd sp!, {r0-r1, r14}
#else
ldr r2, .Lcurpcb
ldr r2, [r2]
#endif
ldr ip, [r2, #PCB_ONFAULT]
adr r3, 1f
str r3, [r2, #PCB_ONFAULT]
ldrh r3, [r0]
strh r3, [r1]
mov r0, #0 /* No fault */
1: str ip, [r2, #PCB_ONFAULT]
mov pc, lr
/*
* int badaddr_read_4(const uint32_t *src, uint32_t *dest)
*
* Copies a single 32-bit value from src to dest, returning 0 on success,
* else EFAULT if a page fault occurred.
*/
ENTRY(badaddr_read_4)
#ifdef MULTIPROCESSOR
/* XXX Probably not appropriate for non-Hydra SMPs */
stmfd sp!, {r0-r1, r14}
bl _C_LABEL(cpu_number)
ldr r2, .Lcpu_info
ldr r2, [r2, r0, lsl #2]
ldr r2, [r2, #CI_CURPCB]
ldmfd sp!, {r0-r1, r14}
#else
ldr r2, .Lcurpcb
ldr r2, [r2]
#endif
ldr ip, [r2, #PCB_ONFAULT]
adr r3, 1f
str r3, [r2, #PCB_ONFAULT]
ldr r3, [r0]
str r3, [r1]
mov r0, #0 /* No fault */
1: str ip, [r2, #PCB_ONFAULT]
mov pc, lr
#endif /* __PROG32 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: exception.S,v 1.12 2003/10/30 08:57:24 scw Exp $ */
/* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */
/*
* Copyright (c) 1994-1997 Mark Brinicombe.
@ -56,24 +56,6 @@
AST_ALIGNMENT_FAULT_LOCALS
/*
* General exception exit handler
*
* It exits straight away if not returning to USR mode.
* This loops around delivering any pending ASTs.
* Interrupts are disabled at suitable points to avoid ASTs
* being posted between testing and exit to user mode.
*
* This function uses PULLFRAMEFROMSVCANDEXIT and
* DO_AST_AND_RESTORE_ALIGNMENT_FAULTS thus should
* only be called if the exception handler used PUSHFRAMEINSVC
* followed by ENABLE_ALIGNMENT_FAULTS.
*/
exception_exit:
DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
PULLFRAMEFROMSVCANDEXIT
/*
* reset_entry:
*
@ -110,6 +92,10 @@ ASENTRY_NP(swi_entry)
* Handler for the Prefetch Abort exception.
*/
ASENTRY_NP(prefetch_abort_entry)
#ifdef __XSCALE__
nop /* Make absolutely sure any pending */
nop /* imprecise aborts have occurred. */
#endif
sub lr, lr, #0x00000004 /* Adjust the lr */
PUSHFRAMEINSVC
@ -144,6 +130,10 @@ abortprefetchmsg:
* Handler for the Data Abort exception.
*/
ASENTRY_NP(data_abort_entry)
#ifdef __XSCALE__
nop /* Make absolutely sure any pending */
nop /* imprecise aborts have occurred. */
#endif
sub lr, lr, #0x00000008 /* Adjust the lr */
PUSHFRAMEINSVC /* Push trap frame and switch */
@ -192,6 +182,25 @@ Laddress_exception_msg:
.asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
.balign 4
/*
* General exception exit handler
* (Placed here to be within range of all the references to it)
*
* It exits straight away if not returning to USR mode.
* This loops around delivering any pending ASTs.
* Interrupts are disabled at suitable points to avoid ASTs
* being posted between testing and exit to user mode.
*
* This function uses PULLFRAMEFROMSVCANDEXIT and
* DO_AST_AND_RESTORE_ALIGNMENT_FAULTS thus should
* only be called if the exception handler used PUSHFRAMEINSVC
* followed by ENABLE_ALIGNMENT_FAULTS.
*/
exception_exit:
DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
PULLFRAMEFROMSVCANDEXIT
/*
* undefined_entry:
*

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: armreg.h,v 1.27 2003/09/06 08:43:02 rearnsha Exp $ */
/* $NetBSD: armreg.h,v 1.28 2003/10/31 16:30:15 scw Exp $ */
/*
* Copyright (c) 1998, 2001 Ben Harris
@ -326,6 +326,8 @@
#define FAULT_PERM_S 0x0d /* Permission -- Section */
#define FAULT_PERM_P 0x0f /* Permission -- Page */
#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */
/*
* Address of the vector page, low and high versions.
*/