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