Module Name:    src
Committed By:   matt
Date:           Sun Oct 21 09:25:16 UTC 2012

Modified Files:
        src/sys/arch/arm/arm: cpufunc_asm_armv7.S
        src/sys/arch/arm/arm32: genassym.cf irq_dispatch.S
        src/sys/arch/arm/include/arm32: frame.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/arm/cpufunc_asm_armv7.S
cvs rdiff -u -r1.54 -r1.55 src/sys/arch/arm/arm32/genassym.cf
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/arm/arm32/irq_dispatch.S
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/arm/include/arm32/frame.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/arm/cpufunc_asm_armv7.S
diff -u src/sys/arch/arm/arm/cpufunc_asm_armv7.S:1.9 src/sys/arch/arm/arm/cpufunc_asm_armv7.S:1.10
--- src/sys/arch/arm/arm/cpufunc_asm_armv7.S:1.9	Fri Oct 19 13:47:03 2012
+++ src/sys/arch/arm/arm/cpufunc_asm_armv7.S	Sun Oct 21 09:25:16 2012
@@ -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)

Index: src/sys/arch/arm/arm32/genassym.cf
diff -u src/sys/arch/arm/arm32/genassym.cf:1.54 src/sys/arch/arm/arm32/genassym.cf:1.55
--- src/sys/arch/arm/arm32/genassym.cf:1.54	Fri Sep  7 11:48:59 2012
+++ src/sys/arch/arm/arm32/genassym.cf	Sun Oct 21 09:25:16 2012
@@ -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	SIGEMT			SIGEMT
 
 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)
 

Index: src/sys/arch/arm/arm32/irq_dispatch.S
diff -u src/sys/arch/arm/arm32/irq_dispatch.S:1.12 src/sys/arch/arm/arm32/irq_dispatch.S:1.13
--- src/sys/arch/arm/arm32/irq_dispatch.S:1.12	Wed Aug 29 07:06:27 2012
+++ src/sys/arch/arm/arm32/irq_dispatch.S	Sun Oct 21 09:25:16 2012
@@ -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 @@ ASENTRY_NP(irq_entry)
 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

Index: src/sys/arch/arm/include/arm32/frame.h
diff -u src/sys/arch/arm/include/arm32/frame.h:1.33 src/sys/arch/arm/include/arm32/frame.h:1.34
--- src/sys/arch/arm/include/arm32/frame.h:1.33	Wed Aug 29 07:09:12 2012
+++ src/sys/arch/arm/include/arm32/frame.h	Sun Oct 21 09:25:16 2012
@@ -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 @@ LOCK_CAS_DEBUG_LOCALS
 	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 @@ LOCK_CAS_DEBUG_LOCALS
 	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

Reply via email to