ARM: Allow to mask data aborts
Sometimes it's useful to test if a memory operation works or aborts. This adds data_abort_mask() to ignore data aborts and data_abort_unmask() to enable them again. This is used in the next step for the 'md' command so that illegal addresses just show 'xxxxxxxx' instead of crashing the system. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
86759346ba
commit
b42a3e2f68
|
@ -88,6 +88,21 @@
|
|||
movs pc, lr
|
||||
.endm
|
||||
|
||||
.macro try_data_abort
|
||||
ldr r13, =arm_ignore_data_abort @ check try mode
|
||||
ldr r13, [r13]
|
||||
cmp r13, #0
|
||||
beq do_abort_\@
|
||||
ldr r13, =arm_data_abort_occurred
|
||||
str r13, [r13]
|
||||
mrs r13, spsr @ read saved CPSR
|
||||
tst r13, #1<<5 @ check Thumb mode
|
||||
subeq lr, #4 @ next ARM instr
|
||||
subne lr, #6 @ next Thumb instr
|
||||
movs pc, lr
|
||||
do_abort_\@:
|
||||
.endm
|
||||
|
||||
.macro get_irq_stack @ setup IRQ stack
|
||||
ldr sp, IRQ_STACK_START
|
||||
.endm
|
||||
|
@ -122,6 +137,7 @@ prefetch_abort:
|
|||
|
||||
.align 5
|
||||
data_abort:
|
||||
try_data_abort
|
||||
get_bad_stack
|
||||
bad_save_user_regs
|
||||
bl do_data_abort
|
||||
|
@ -202,5 +218,11 @@ _fiq: .word fiq
|
|||
|
||||
.section .data
|
||||
.align 4
|
||||
.global arm_ignore_data_abort
|
||||
arm_ignore_data_abort:
|
||||
.word arm_ignore_data_abort /* When != 0 data aborts are ignored */
|
||||
.global arm_data_abort_occurred
|
||||
arm_data_abort_occurred:
|
||||
.word arm_data_abort_occurred /* set != 0 by the data abort handler */
|
||||
abort_stack:
|
||||
.space 8
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <abort.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/unwind.h>
|
||||
|
||||
|
@ -161,3 +162,19 @@ void do_irq (struct pt_regs *pt_regs)
|
|||
printf ("interrupt request\n");
|
||||
do_exception(pt_regs);
|
||||
}
|
||||
|
||||
extern volatile int arm_ignore_data_abort;
|
||||
extern volatile int arm_data_abort_occurred;
|
||||
|
||||
void data_abort_mask(void)
|
||||
{
|
||||
arm_data_abort_occurred = 0;
|
||||
arm_ignore_data_abort = 1;
|
||||
}
|
||||
|
||||
int data_abort_unmask(void)
|
||||
{
|
||||
arm_ignore_data_abort = 0;
|
||||
|
||||
return arm_data_abort_occurred != 0;
|
||||
}
|
||||
|
|
|
@ -5,4 +5,8 @@
|
|||
#define ARCH_HAS_STACK_DUMP
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_EXCEPTIONS
|
||||
#define ARCH_HAS_DATA_ABORT_MASK
|
||||
#endif
|
||||
|
||||
#endif /* _BAREBOX_H_ */
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef __ABORT_H
|
||||
#define __ABORT_H
|
||||
|
||||
#include <asm/barebox.h>
|
||||
|
||||
#ifdef ARCH_HAS_DATA_ABORT_MASK
|
||||
|
||||
/*
|
||||
* data_abort_mask - ignore data aborts
|
||||
*
|
||||
* If data aborts are ignored the data abort handler
|
||||
* will just return.
|
||||
*/
|
||||
void data_abort_mask(void);
|
||||
|
||||
/*
|
||||
* data_abort_unmask - Enable data aborts
|
||||
*
|
||||
* returns true if a data abort has happened between calling data_abort_mask()
|
||||
* and data_abort_unmask()
|
||||
*/
|
||||
int data_abort_unmask(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void data_abort_mask(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int data_abort_unmask(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ABORT_H */
|
Loading…
Reference in New Issue