* 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 | 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)); + 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)); +} /** * @brief SPARC exit through system call 1 -- 1.7.0.4 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel