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