[PATCH 4/4 v2] SPARC: optimize IRQ enable & disable
Daniel Hellstrom
daniel at gaisler.com
Mon Nov 24 15:41:02 UTC 2014
On 11/24/2014 04:29 PM, Gedare Bloom wrote:
> On Mon, Nov 24, 2014 at 5:15 AM, Daniel Hellstrom <daniel at gaisler.com> wrote:
>> * Coding style cleanups.
>> * Use OS reserved trap 0x89 for IRQ Disable
>> * Use OS reserved trap 0x8A for IRQ Enable
>>
>> This will result in faster Disable/Enable code since the
>> system trap handler does not need to decode which function
>> the user wants. Besides the IRQ disable/enabled can now
>> be inline which avoids the caller to take into account that
>> o0-o7+g1-g4 registers are destroyed by trap handler.
>>
>> It was also possible to reduce the interrupt traphandler with
> s/traphandler/trap handler
> s/with/by
>
>> five instructions due to this.
>> ---
>> c/src/lib/libbsp/sparc/leon3/startup/spurious.c | 9 +-
>> c/src/lib/libbsp/sparc/shared/irq_asm.S | 42 ++++-----
>> c/src/lib/libbsp/sparc/shared/start/start.S | 25 ++++-
>> c/src/lib/libcpu/sparc/syscall/syscall.S | 118 +++++++++++++----------
>> c/src/lib/libcpu/sparc/syscall/syscall.h | 2 -
>> cpukit/score/cpu/sparc/rtems/score/sparc.h | 18 +++-
>> 6 files changed, 124 insertions(+), 90 deletions(-)
>>
>> diff --git a/c/src/lib/libbsp/sparc/leon3/startup/spurious.c b/c/src/lib/libbsp/sparc/leon3/startup/spurious.c
>> index a29f113..6a93670 100644
>> --- a/c/src/lib/libbsp/sparc/leon3/startup/spurious.c
>> +++ b/c/src/lib/libbsp/sparc/leon3/startup/spurious.c
>> @@ -146,14 +146,15 @@ void bsp_spurious_initialize()
>>
>> /*
>> * Skip window overflow, underflow, and flush as well as software
>> - * trap 0 which we will use as a shutdown. Also avoid trap 0x70 - 0x7f
>> - * which cannot happen and where some of the space is used to pass
>> - * paramaters to the program.
>> + * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable.
>> + * Also avoid trap 0x70 - 0x7f which cannot happen and where some of the
>> + * space is used to pass paramaters to the program.
>> */
>>
>> if (( trap == 5 || trap == 6 ) ||
>> (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
>> - (( trap >= 0x70 ) && ( trap <= 0x83 )))
>> + (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
>> + (( trap >= 0x89 ) && ( trap <= 0x8a )))
>> continue;
>>
>> set_vector(
>> diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S
>> index 2ab0def..3e08795 100644
>> --- a/c/src/lib/libbsp/sparc/shared/irq_asm.S
>> +++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S
>> @@ -499,8 +499,7 @@ dont_fix_pil2:
>> cmp %l7, 0
>> bne profiling_not_outer_most_exit
>> nop
>> - call SYM(sparc_disable_interrupts), 0
>> - nop
>> + ta SPARC_SWTRAP_IRQDIS ! Call interrupt disable trap handler
>> ld [%l4], %o2 ! o2 = 3rd arg = interrupt exit instant
>> mov %l3, %o1 ! o1 = 2nd arg = interrupt entry instant
>> call SYM(_Profiling_Outer_most_interrupt_entry_and_exit), 0
>> @@ -585,38 +584,31 @@ profiling_not_outer_most_exit:
>> nop
>> isr_dispatch:
>> call SYM(_Thread_Dispatch), 0
>> - nop
>> + nop
>>
>> - /*
>> - * We invoked _Thread_Dispatch in a state similar to the interrupted
>> - * task. In order to safely be able to tinker with the register
>> - * windows and get the task back to its pre-interrupt state,
>> - * we need to disable interrupts disabled so we can safely tinker
>> - * with the register windowing. In particular, the CWP in the PSR
>> - * is fragile during this period. (See PR578.)
>> - */
>> - mov 2,%g1 ! syscall (disable interrupts)
>> - ta 0 ! syscall (disable interrupts)
>> + /*
>> + * We invoked _Thread_Dispatch in a state similar to the interrupted
>> + * task. In order to safely be able to tinker with the register
>> + * windows and get the task back to its pre-interrupt state,
>> + * we need to disable interrupts disabled so we can safely tinker
>> + * with the register windowing. In particular, the CWP in the PSR
>> + * is fragile during this period. (See PR578.)
>> + */
>> + ta SPARC_SWTRAP_IRQDIS ! syscall (disable interrupts)
>>
>> /*
>> * While we had ISR dispatching disabled in this thread,
>> * did we miss anything. If so, then we need to do another
>> * _Thread_Dispatch before leaving this ISR Dispatch context.
>> */
>> + ldub [%g6 + PER_CPU_DISPATCH_NEEDED], %l7
>>
>> - ldub [%g6 + PER_CPU_DISPATCH_NEEDED], %l7
>> -
>> - orcc %l7, %g0, %g0 ! Is thread switch necesary?
>> - bz allow_nest_again ! No, then clear out and return
>> - nop
>> -
>> - ! Yes, then invoke the dispatcher
>> -dispatchAgain:
>> - mov 3,%g1 ! syscall (enable interrupts)
>> - ta 0 ! syscall (enable interrupts)
>> - ba isr_dispatch
>> - nop
>> + orcc %l7, %g0, %g0 ! Is thread switch necesary?
>> + bne,a isr_dispatch ! Yes, then invoke the dispatcher.
>> + ! g1 = Old PSR PIL returned from IRQDis
>> + ta SPARC_SWTRAP_IRQEN ! syscall (enable interrupts to same level)
>>
>> + ! No, then clear out and return
>> allow_nest_again:
>>
>> ! Zero out ISR stack nesting prevention flag
>> diff --git a/c/src/lib/libbsp/sparc/shared/start/start.S b/c/src/lib/libbsp/sparc/shared/start/start.S
>> index 3e0e42e..9e9bcaf 100644
>> --- a/c/src/lib/libbsp/sparc/shared/start/start.S
>> +++ b/c/src/lib/libbsp/sparc/shared/start/start.S
>> @@ -35,11 +35,20 @@
>> /*
>> * System call optimized trap table entry
>> */
>> -#define SYSCALL_TRAP(_vector, _handler) \
>> +#define IRQDIS_TRAP(_vector, _handler) \
>> mov %psr, %l0 ; \
>> sethi %hi(_handler), %l4 ; \
>> jmp %l4+%lo(_handler); \
>> - subcc %g1, 3, %g0; ! prepare for syscall 3 check
>> + or %l0, 0x0f00, %l3; ! Set PIL=0xf to disable IRQ
>> +
>> +/*
>> + * System call optimized trap table entry
>> + */
>> +#define IRQEN_TRAP(_vector, _handler) \
>> + mov %psr, %l0 ; \
>> + sethi %hi(_handler), %l4 ; \
>> + jmp %l4+%lo(_handler); \
>> + andn %l0, 0xf00, %l3; ! Set PIL=0 to Enable IRQ
>>
>> /*
>> * Window Overflow optimized trap table entry
>> @@ -183,12 +192,20 @@ SYM(CLOCK_SPEED):
>> * installed before.
>> */
>>
>> - SYSCALL_TRAP( 0x80, SYM(syscall) ); ! 80 syscall SW trap
>> + TRAP( 0x80, SYM(syscall) ); ! 80 halt syscall SW trap
>> SOFT_TRAP; SOFT_TRAP; ! 81 - 82
>> TRAP( 0x83, SYM(window_flush_trap_handler) ); ! 83 flush windows SW trap
>>
>> SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84 - 87
>> - SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88 - 8B
>> + SOFT_TRAP; ! 88
>> +
>> + /*
>> + * SW Trap 9-15 Reserved for Operating System
>> + */
>> + IRQDIS_TRAP(0x89, SYM(syscall_irqdis)); ! 89 IRQ Disable syscall trap
>> + IRQEN_TRAP(0x8A, SYM(syscall_irqen)); ! 8A IRQ Enable syscall trap
>> +
>> + SOFT_TRAP; ! 8B
>> SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8C - 8F
>> SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93
>> SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97
>> diff --git a/c/src/lib/libcpu/sparc/syscall/syscall.S b/c/src/lib/libcpu/sparc/syscall/syscall.S
>> index 9ce7fa5..64c4805 100644
>> --- a/c/src/lib/libcpu/sparc/syscall/syscall.S
>> +++ b/c/src/lib/libcpu/sparc/syscall/syscall.S
>> @@ -19,69 +19,81 @@
>> #include <rtems/asm.h>
>> #include "syscall.h"
>>
>> - .seg "text"
>> - /*
>> - * system call
>> - *
>> - * On entry:
>> - *
>> - * l0 = psr (from trap table)
>> - * l1 = pc
>> - * l2 = npc
>> - * g1 = system call id
>> - *
>> - * System Call 1 (exit):
>> - * g2 = additional exit code 1
>> - * g3 = additional exit code 2
>> - */
>> -
>> -.align 32 ! Align to 32-byte cache-line
>> - PUBLIC(syscall)
>> + .seg "text"
>> + /*
>> + * system call - halt
>> + *
>> + * On entry:
>> + *
>> + * l0 = psr (from trap table)
>> + * l1 = pc
>> + * l2 = npc
>> + * g1 = system call id (1)
>> + *
>> + * System Call 1 (exit):
>> + * g2 = additional exit code 1
>> + * g3 = additional exit code 2
>> + */
>> +
>> + PUBLIC(syscall)
>>
>> SYM(syscall):
>> + ta 0 ! syscall 1, halt with %g1,%g2,%g3 info
>>
>> - ! "subcc, %g1, 3, %g0" done in trap table
>> - bne 2f ! syscall 3? enable interrupt
>> - and %i0, SPARC_PSR_PIL_MASK, %l4
>> - andn %l0, SPARC_PSR_PIL_MASK, %l5
>> - wr %l4, %l5, %psr ! Update PSR according to syscall 3
>> -1: ! leave, with 3 inst PSR-write delay
>> - mov 0, %g1 ! clear %g1
>> - or %l0, SPARC_PSR_ET_MASK, %i0 ! return old psr with ET=1. No
>> - ! effect on syscall 3
>> - jmpl %l2, %g0
>> - rett %l2 + 4
>> -
>> -2: or %l0, 0x0f00, %l4 ! set PIL=15
>> - subcc %g1, 2, %g0 ! syscall 2? disable interrupts
>> - beq,a 1b ! Annul delay-slot for syscall 1
>> - mov %l4, %psr ! Update PSR according to Syscall 2
>> - ta 0 ! syscall 1 (not 2 or 3), halt
>> -
>> - PUBLIC(sparc_disable_interrupts)
>> + PUBLIC(sparc_syscall_exit)
>>
>> -SYM(sparc_disable_interrupts):
>> -
>> - mov SYS_irqdis, %g1
>> - retl
>> - ta 0
>> +SYM(sparc_syscall_exit):
>>
>> - PUBLIC(sparc_enable_interrupts)
>> + mov SYS_exit, %g1
>> + mov %o0, %g2 ! Additional exit code 1
>> + mov %o1, %g3 ! Additional exit code 2
>> + ta SPARC_SWTRAP_SYSCALL
>> +
>> + /*
>> + * system call - Interrupt Disable
>> + *
>> + * On entry:
>> + *
>> + * l0 = psr (from trap table)
>> + * l1 = pc
>> + * l2 = npc
>> + * l3 = psr | SPARC_PSR_PIL_MASK
>> + *
>> + * On exit:
>> + * g1 = old psr (to user)
>> + */
>>
>> -SYM(sparc_enable_interrupts):
>> +.align 32 ! Align to 32-byte cache-line
>> + PUBLIC(syscall_irqdis)
>>
>> - mov SYS_irqen, %g1
>> - retl
>> - ta 0
>> +SYM(syscall_irqdis):
>> + mov %l3, %psr ! Set PSR. Write delay 3 instr
>> + or %l0, SPARC_PSR_ET_MASK, %g1 ! return old PSR with ET=1
>> + nop ! PSR write delay
>> + jmp %l2 ! Return to after TA 9.
>> + rett %l2 + 4
>>
>> - PUBLIC(sparc_syscall_exit)
>> + /*
>> + * system call - Interrupt Enable
>> + *
>> + * On entry:
>> + *
>> + * l0 = psr (from trap table)
>> + * l1 = pc
>> + * l2 = npc
>> + * l3 = psr & ~0x0f00
>> + * g1 = new PIL to write (from user)
>> + */
>>
>> -SYM(sparc_syscall_exit):
>> +.align 32 ! Align to 32-byte cache-line
>> + PUBLIC(syscall_irqen)
>>
>> - mov SYS_exit, %g1
>> - mov %o0, %g2 ! Additional exit code 1
>> - mov %o1, %g3 ! Additional exit code 2
>> - ta 0
>> +SYM(syscall_irqen):
>> + and %g1, SPARC_PSR_PIL_MASK, %l4 ! %l4 = (%g1 & 0xf00)
>> + wr %l3, %l4, %psr ! PSR = (PSR & ~0xf00) ^ %l4
>> + nop; nop ! PSR write delay;
>> + jmp %l2 ! Return to after TA 10.
>> + rett %l2 + 4
>>
>> #if defined(RTEMS_PARAVIRT)
>>
>> diff --git a/c/src/lib/libcpu/sparc/syscall/syscall.h b/c/src/lib/libcpu/sparc/syscall/syscall.h
>> index 9af3560..2f20886 100644
>> --- a/c/src/lib/libcpu/sparc/syscall/syscall.h
>> +++ b/c/src/lib/libcpu/sparc/syscall/syscall.h
>> @@ -1,3 +1 @@
>> #define SYS_exit 1
>> -#define SYS_irqdis 2
>> -#define SYS_irqen 3
>> diff --git a/cpukit/score/cpu/sparc/rtems/score/sparc.h b/cpukit/score/cpu/sparc/rtems/score/sparc.h
>> index e3251d8..7fe7ea4 100644
>> --- a/cpukit/score/cpu/sparc/rtems/score/sparc.h
>> +++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h
>> @@ -157,6 +157,11 @@ extern "C" {
>>
>> #define LEON3_ASR17_PROCESSOR_INDEX_SHIFT 28
>>
>> +/* SPARC Software Trap number definitions */
>> +#define SPARC_SWTRAP_SYSCALL 0
>> +#define SPARC_SWTRAP_IRQDIS 9
>> +#define SPARC_SWTRAP_IRQEN 10
>> +
>> #ifndef ASM
>>
>> /**
>> @@ -306,7 +311,12 @@ void _SPARC_Set_TBR( uint32_t new_tbr );
>> *
>> * @return This method returns the entire PSR contents.
>> */
>> -uint32_t sparc_disable_interrupts(void);
>> +static inline uint32_t sparc_disable_interrupts(void)
>> +{
>> + register uint32_t psr __asm__("g1");
>> + __asm__ volatile ( "ta %1\n\t" : "=r" (psr) : "i" (SPARC_SWTRAP_IRQDIS));
> This is clever. A brief comment might be nice to help the reader
> understand that writing to g1 is a side-effect of the trap handler.
I will add a comment here.
>> + return psr;
>> +}
>>
>> /**
>> * @brief SPARC enable processor interrupts.
>> @@ -315,7 +325,11 @@ uint32_t sparc_disable_interrupts(void);
>> *
>> * @param[in] psr is the PSR returned by @ref sparc_disable_interrupts.
>> */
>> -void sparc_enable_interrupts(uint32_t psr);
>> +static inline void sparc_enable_interrupts(uint32_t psr)
>> +{
>> + register uint32_t _psr __asm__("g1") = psr;
>> + __asm__ volatile ( "ta %0\n" :: "i" (SPARC_SWTRAP_IRQEN), "r" (_psr));
> Ditto, except this could clobber the g1 register directly instead of
> through the _psr variable.
It does not clobber g1.
Thanks!
DanielH
More information about the devel
mailing list