Implement a badaddr_read() routine which performs a load of the
specified size for the caller, and returns true or false indicating whether or not a Data Abort occurred (i.e. the address was "bad").
This commit is contained in:
parent
d16c00cfb2
commit
42a10f6cd4
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fault.c,v 1.2 2001/09/05 16:17:35 matt Exp $ */
|
||||
/* $NetBSD: fault.c,v 1.3 2001/11/09 17:58:01 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994-1997 Mark Brinicombe.
|
||||
|
@ -113,6 +113,73 @@ report_abort(prefix, fault_status, fault_address, fault_pc)
|
|||
#endif
|
||||
}
|
||||
|
||||
static __volatile int data_abort_expected;
|
||||
static __volatile int data_abort_received;
|
||||
|
||||
int
|
||||
badaddr_read(void *addr, size_t size, void *rptr)
|
||||
{
|
||||
u_long rcpt;
|
||||
int rv;
|
||||
|
||||
/* Tell the Data Abort handler that we're expecting one. */
|
||||
data_abort_received = 0;
|
||||
data_abort_expected = 1;
|
||||
|
||||
cpu_drain_writebuf();
|
||||
|
||||
/* Read from the test address. */
|
||||
switch (size) {
|
||||
case sizeof(uint8_t):
|
||||
__asm __volatile("ldrb %0, [%1]"
|
||||
: "=r" (rcpt)
|
||||
: "r" (addr));
|
||||
break;
|
||||
|
||||
case sizeof(uint16_t):
|
||||
__asm __volatile("ldrh %0, [%1]"
|
||||
: "=r" (rcpt)
|
||||
: "r" (addr));
|
||||
break;
|
||||
|
||||
case sizeof(uint32_t):
|
||||
__asm __volatile("ldr %0, [%1]"
|
||||
: "=r" (rcpt)
|
||||
: "r" (addr));
|
||||
break;
|
||||
|
||||
default:
|
||||
data_abort_expected = 0;
|
||||
panic("badaddr: invalid size (%lu)\n", (u_long) size);
|
||||
}
|
||||
|
||||
/* Disallow further Data Aborts. */
|
||||
data_abort_expected = 0;
|
||||
|
||||
rv = data_abort_received;
|
||||
data_abort_received = 0;
|
||||
|
||||
/* Copy the data back if no fault occurred. */
|
||||
if (rptr != NULL && rv == 0) {
|
||||
switch (size) {
|
||||
case sizeof(uint8_t):
|
||||
*(uint8_t *) rptr = rcpt;
|
||||
break;
|
||||
|
||||
case sizeof(uint16_t):
|
||||
*(uint16_t *) rptr = rcpt;
|
||||
break;
|
||||
|
||||
case sizeof(uint32_t):
|
||||
*(uint32_t *) rptr = rcpt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if the address was invalid. */
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* void data_abort_handler(trapframe_t *frame)
|
||||
*
|
||||
|
@ -138,6 +205,17 @@ data_abort_handler(frame)
|
|||
int error;
|
||||
void *onfault;
|
||||
|
||||
/*
|
||||
* If we were expecting a Data Abort, signal that we got
|
||||
* one, adjust the PC to skip the faulting insn, and
|
||||
* return.
|
||||
*/
|
||||
if (data_abort_expected) {
|
||||
data_abort_received = 1;
|
||||
frame->tf_pc += INSN_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must get fault address and status from the CPU before
|
||||
* re-enabling interrupts. (Interrupt handlers may take
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cpu.h,v 1.15 2001/07/10 20:43:57 bjh21 Exp $ */
|
||||
/* $NetBSD: cpu.h,v 1.16 2001/11/09 17:58:00 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994-1996 Mark Brinicombe.
|
||||
|
@ -252,6 +252,9 @@ void userret __P((register struct proc *p));
|
|||
/* machdep.h */
|
||||
void bootsync __P((void));
|
||||
|
||||
/* fault.c */
|
||||
int badaddr_read __P((void *, size_t, void *));
|
||||
|
||||
#endif /* !_LOCORE */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
|
Loading…
Reference in New Issue