From dff1803cfbec3775fff1b9c34cc707c05494dc3b Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Wed, 3 Dec 2014 11:35:52 +0100 Subject: SPARC: optimize IRQ enable & disable * Coding style cleanups. * Use OS reserved trap 0x89 for IRQ Disable * Use OS reserved trap 0x8A for IRQ Enable * Add to SPARC CPU supplement documentation 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 trap handler by five instructions due to this. --- c/src/lib/libbsp/sparc/leon3/startup/spurious.c | 12 ++- c/src/lib/libbsp/sparc/shared/irq_asm.S | 42 ++++----- c/src/lib/libbsp/sparc/shared/start/start.S | 30 +++++- c/src/lib/libcpu/sparc/syscall/syscall.S | 118 +++++++++++++----------- c/src/lib/libcpu/sparc/syscall/syscall.h | 2 - 5 files changed, 114 insertions(+), 90 deletions(-) (limited to 'c/src') diff --git a/c/src/lib/libbsp/sparc/leon3/startup/spurious.c b/c/src/lib/libbsp/sparc/leon3/startup/spurious.c index a29f113226..8801f6e933 100644 --- a/c/src/lib/libbsp/sparc/leon3/startup/spurious.c +++ b/c/src/lib/libbsp/sparc/leon3/startup/spurious.c @@ -18,6 +18,7 @@ */ #include +#include #include void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) @@ -146,14 +147,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 ) || + if (( trap == 5 ) || ( trap == 6 ) || (( trap >= 0x11 ) && ( trap <= 0x1f )) || - (( trap >= 0x70 ) && ( trap <= 0x83 ))) + (( trap >= 0x70 ) && ( trap <= 0x83 )) || + ( trap == SPARC_SWTRAP_IRQDIS ) || ( trap == SPARC_SWTRAP_IRQEN )) 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 2ab0defa72..3e08795a2b 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 3e0e42e7df..f38fe8cb99 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(_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(_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,23 @@ SYM(CLOCK_SPEED): * installed before. */ - SYSCALL_TRAP( 0x80, SYM(syscall) ); ! 80 syscall SW trap - SOFT_TRAP; SOFT_TRAP; ! 81 - 82 + 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 + * + * SPARC_SWTRAP_IRQDIS + * SPARC_SWTRAP_IRQEN + */ + IRQDIS_TRAP(SYM(syscall_irqdis)); ! 89 IRQ Disable syscall trap + IRQEN_TRAP(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 9ce7fa54ef..64c4805af6 100644 --- a/c/src/lib/libcpu/sparc/syscall/syscall.S +++ b/c/src/lib/libcpu/sparc/syscall/syscall.S @@ -19,69 +19,81 @@ #include #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 9af3560267..2f20886840 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 -- cgit v1.2.3