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 "fast" path for IRQ handling out of...



details:   https://anonhg.NetBSD.org/src/rev/032b4d1556c5
branches:  trunk
changeset: 782214:032b4d1556c5
user:      matt <matt%NetBSD.org@localhost>
date:      Sun Oct 21 09:25:16 2012 +0000

description:
Implement a "fast" path for IRQ handling out of the idle loop.  Since we
are in SVC32 already we only need to save a few registers.  Processing is
also simplified since we know we can't return to user-mode.

diffstat:

 sys/arch/arm/arm/cpufunc_asm_armv7.S |   5 ++---
 sys/arch/arm/arm32/genassym.cf       |   4 +++-
 sys/arch/arm/arm32/irq_dispatch.S    |  32 +++++++++++++++++++++++++++++++-
 sys/arch/arm/include/arm32/frame.h   |  21 ++++++++++++++++++++-
 4 files changed, 56 insertions(+), 6 deletions(-)

diffs (118 lines):

diff -r 6ffb224b3220 -r 032b4d1556c5 sys/arch/arm/arm/cpufunc_asm_armv7.S
--- a/sys/arch/arm/arm/cpufunc_asm_armv7.S      Sun Oct 21 08:18:27 2012 +0000
+++ b/sys/arch/arm/arm/cpufunc_asm_armv7.S      Sun Oct 21 09:25:16 2012 +0000
@@ -34,9 +34,8 @@
        .arch   armv7a
 
 ENTRY(armv7_cpu_sleep)
-       tst     r0, #0x00000000         @ shouldn't sleep 0
-       wfene                           @ this can cheaper when doing MP
-       bx      lr
+       wfi                             @ wait for an interrupt
+       b       irq_idle_entry          @ assume we got an interrupt
 END(armv7_cpu_sleep)
 
 ENTRY(armv7_wait)
diff -r 6ffb224b3220 -r 032b4d1556c5 sys/arch/arm/arm32/genassym.cf
--- a/sys/arch/arm/arm32/genassym.cf    Sun Oct 21 08:18:27 2012 +0000
+++ b/sys/arch/arm/arm32/genassym.cf    Sun Oct 21 09:25:16 2012 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: genassym.cf,v 1.54 2012/09/07 11:48:59 matt Exp $
+#      $NetBSD: genassym.cf,v 1.55 2012/10/21 09:25:16 matt Exp $
 
 # Copyright (c) 1982, 1990 The Regents of the University of California.
 # All rights reserved.
@@ -151,6 +151,8 @@
 
 define TF_FILL                 offsetof(struct trapframe, tf_fill)
 define TF_R0                   offsetof(struct trapframe, tf_r0)
+define TF_R4                   offsetof(struct trapframe, tf_r4)
+define TF_R6                   offsetof(struct trapframe, tf_r6)
 define TF_R10                  offsetof(struct trapframe, tf_r10)
 define TF_PC                   offsetof(struct trapframe, tf_pc)
 
diff -r 6ffb224b3220 -r 032b4d1556c5 sys/arch/arm/arm32/irq_dispatch.S
--- a/sys/arch/arm/arm32/irq_dispatch.S Sun Oct 21 08:18:27 2012 +0000
+++ b/sys/arch/arm/arm32/irq_dispatch.S Sun Oct 21 09:25:16 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: irq_dispatch.S,v 1.12 2012/08/29 07:06:27 matt Exp $   */
+/*     $NetBSD: irq_dispatch.S,v 1.13 2012/10/21 09:25:16 matt Exp $   */
 
 /*
  * Copyright (c) 2002 Fujitsu Component Limited
@@ -131,3 +131,33 @@
 LOCK_CAS_CHECK_LOCALS
 
 AST_ALIGNMENT_FAULT_LOCALS
+
+       .p2align        5
+ASENTRY_NP(irq_idle_entry)
+       PUSHIDLEFRAME
+
+       /*
+        * Increment the interrupt nesting depth and call the interrupt
+        * dispatch routine.  We've pushed a frame, so we can safely use
+        * callee-saved regs here.  We use the following registers, which
+        * we expect to persist:
+        *
+        *      r4      address of current cpu_info
+        *      r6      old value of `ci_intr_depth'
+        */
+       GET_CURCPU(r4)
+       ldr     r6, [r4, #CI_INTR_DEPTH]
+       add     r1, r6, #1
+       str     r1, [r4, #CI_INTR_DEPTH]
+
+       mov     r0, sp                  /* arg for dispatcher */
+       bl      ARM_IRQ_HANDLER
+
+       /*
+        * Restore the old interrupt depth value (which should be the
+        * same as decrementing it at this point).
+        */
+       str     r6, [r4, #CI_INTR_DEPTH]
+
+       PULLIDLEFRAME
+       RET
diff -r 6ffb224b3220 -r 032b4d1556c5 sys/arch/arm/include/arm32/frame.h
--- a/sys/arch/arm/include/arm32/frame.h        Sun Oct 21 08:18:27 2012 +0000
+++ b/sys/arch/arm/include/arm32/frame.h        Sun Oct 21 09:25:16 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: frame.h,v 1.33 2012/08/29 07:09:12 matt Exp $  */
+/*     $NetBSD: frame.h,v 1.34 2012/10/21 09:25:16 matt Exp $  */
 
 /*
  * Copyright (c) 1994-1997 Mark Brinicombe.
@@ -339,6 +339,19 @@
        str     r0, [sp, #-8]!          /* Push the SPSR on the stack */
 
 /*
+ * Push a minimal trapframe so we can dispatch an interrupt from the
+ * idle loop.  The only reason the idle loop wakes up is to dispatch
+ * interrupts so why take the avoid of a full exception when we can do
+ * something minimal.
+ */
+#define PUSHIDLEFRAME                                                     \
+       str     lr, [sp, #-4]!;         /* save SVC32 lr */                \
+       str     r6, [sp, #(TF_R6-TF_PC)]!; /* save callee-saved r6 */      \
+       str     r4, [sp, #(TF_R4-TF_R6)]!; /* save callee-saved r6 */      \
+       mrs     r0, cpsr_all;           /* Get the CPSR */                 \
+       str     r0, [sp, #(-TF_R4)]!    /* Push the CPSR on the stack */
+
+/*
  * PULLFRAME - macro to pull a trap frame from the stack in the current mode
  * Since the current mode is used, the SVC lr field is ignored.
  */
@@ -351,6 +364,12 @@
        add     sp, sp, #(4*17);        /* Adjust the stack pointer */     \
        ldr     lr, [sp], #0x0004       /* Pop the return address */
 
+#define PULLIDLEFRAME                                                     \
+       add     sp, sp, #TF_R4;         /* Adjust the stack pointer */     \
+       ldr     r4, [sp], #(TF_R6-TF_R4); /* restore callee-saved r4 */    \
+       ldr     r6, [sp], #(TF_PC-TF_R6); /* restore callee-saved r6 */    \
+       ldr     lr, [sp], #4            /* Pop the return address */
+
 /*
  * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode
  * This should only be used if the processor is not currently in SVC32



Home | Main Index | Thread Index | Old Index