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