Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm Implement a badaddr_read() routine which perfor...
details: https://anonhg.NetBSD.org/src/rev/2a417861de94
branches: trunk
changeset: 517261:2a417861de94
user: thorpej <thorpej%NetBSD.org@localhost>
date: Fri Nov 09 17:58:00 2001 +0000
description:
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").
diffstat:
sys/arch/arm/arm32/fault.c | 80 +++++++++++++++++++++++++++++++++++++++++++++-
sys/arch/arm/include/cpu.h | 5 ++-
2 files changed, 83 insertions(+), 2 deletions(-)
diffs (120 lines):
diff -r 58f60ef06441 -r 2a417861de94 sys/arch/arm/arm32/fault.c
--- a/sys/arch/arm/arm32/fault.c Fri Nov 09 17:44:43 2001 +0000
+++ b/sys/arch/arm/arm32/fault.c Fri Nov 09 17:58:00 2001 +0000
@@ -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 @@
#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)
*
@@ -139,6 +206,17 @@
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
* R/M emulation faults.)
diff -r 58f60ef06441 -r 2a417861de94 sys/arch/arm/include/cpu.h
--- a/sys/arch/arm/include/cpu.h Fri Nov 09 17:44:43 2001 +0000
+++ b/sys/arch/arm/include/cpu.h Fri Nov 09 17:58:00 2001 +0000
@@ -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 @@
/* machdep.h */
void bootsync __P((void));
+/* fault.c */
+int badaddr_read __P((void *, size_t, void *));
+
#endif /* !_LOCORE */
#endif /* _KERNEL */
Home |
Main Index |
Thread Index |
Old Index