On Mon, Nov 24, 2014 at 5:15 AM, Daniel Hellstrom <dan...@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. > + 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. > +} > > /** > * @brief SPARC exit through system call 1 > -- > 1.7.0.4 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel