[PATCH 4/4] SPARC: optimize IRQ enable & disable
Daniel Hellstrom
daniel at gaisler.com
Thu Nov 20 08:01:05 UTC 2014
Hi,
On 11/19/2014 08:19 PM, Gedare Bloom wrote:
> This one needs a release note as it may impede some applications if
> they assumed they could use these trap vectors.
I agree. Where should I update?
>
> Also, do these changes complicate the paravirtualization efforts done
> with sparc32 for xtratum?
I don't know, I guess it will break. Can you point me to the xtratum source code I will have a look. Of course I want xtratum to work with RTEMS/LEON, however I think that xtratum should follow RTEMS
not the other way around.
>
> Otherwise, quick skim of the patch series looked good.
Thanks!
DanielH
>
> On Wed, Nov 19, 2014 at 10:35 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
>> five instructions due to this.
>> ---
>> c/src/lib/libbsp/sparc/leon3/startup/spurious.c | 9 +-
>> c/src/lib/libbsp/sparc/shared/irq_asm.S | 35 +++----
>> c/src/lib/libbsp/sparc/shared/start/start.S | 25 ++++-
>> c/src/lib/libcpu/sparc/syscall/syscall.S | 116 +++++++++++++----------
>> c/src/lib/libcpu/sparc/syscall/syscall.h | 2 -
>> cpukit/score/cpu/sparc/rtems/score/sparc.h | 13 ++-
>> 6 files changed, 115 insertions(+), 85 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..f826c78 100644
>> --- a/c/src/lib/libbsp/sparc/shared/irq_asm.S
>> +++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S
>> @@ -585,38 +585,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 9 ! 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
>>
>> 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
>> + bne,a isr_dispatch ! Yes, then invoke the dispatcher.
>> + ! g1 = Old PSR PIL returned from IRQDis
>> + ta 10 ! 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..b13eba2 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):
>> +SYM(sparc_syscall_exit):
>>
>> - mov SYS_irqdis, %g1
>> - retl
>> - ta 0
>> + mov SYS_exit, %g1
>> + mov %o0, %g2 ! Additional exit code 1
>> + mov %o1, %g3 ! Additional exit code 2
>> + ta 0
>>
>> - PUBLIC(sparc_enable_interrupts)
>> + /*
>> + * 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..91aa65b 100644
>> --- a/cpukit/score/cpu/sparc/rtems/score/sparc.h
>> +++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h
>> @@ -306,7 +306,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 9\n\t" : "=r" (psr) ::);
>> + return psr;
>> +}
>>
>> /**
>> * @brief SPARC enable processor interrupts.
>> @@ -315,7 +320,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 10\n" :: "r" (_psr) :);
>> +}
>>
>> /**
>> * @brief SPARC exit through system call 1
>> --
>> 1.7.0.4
>>
>> _______________________________________________
>> devel mailing list
>> devel at rtems.org
>> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list