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:
parent
2564505612
commit
336806eb55
@ -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 */
|
||||
|
@ -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
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user