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.
This commit is contained in:
Daniel Hellstrom
2014-12-03 11:35:52 +01:00
parent 4081032ce0
commit dff1803cfb
7 changed files with 157 additions and 96 deletions

View File

@@ -18,6 +18,7 @@
*/
#include <bsp.h>
#include <rtems/score/cpu.h>
#include <rtems/bspIo.h>
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(

View File

@@ -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

View File

@@ -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

View File

@@ -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
*/
.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
*/
.align 32 ! Align to 32-byte cache-line
PUBLIC(syscall)
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)
SYM(sparc_disable_interrupts):
mov SYS_irqdis, %g1
retl
ta 0
PUBLIC(sparc_enable_interrupts)
SYM(sparc_enable_interrupts):
mov SYS_irqen, %g1
retl
ta 0
PUBLIC(sparc_syscall_exit)
PUBLIC(sparc_syscall_exit)
SYM(sparc_syscall_exit):
mov SYS_exit, %g1
mov %o0, %g2 ! Additional exit code 1
mov %o1, %g3 ! Additional exit code 2
ta 0
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)
*/
.align 32 ! Align to 32-byte cache-line
PUBLIC(syscall_irqdis)
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
/*
* 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)
*/
.align 32 ! Align to 32-byte cache-line
PUBLIC(syscall_irqen)
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)

View File

@@ -1,3 +1 @@
#define SYS_exit 1
#define SYS_irqdis 2
#define SYS_irqen 3