RTEMS interrupt enabling/disabling on SPARC architectures, especially Leon-2

Stephan Gruenfelder stephan.gruenfelder at space.at
Fri Apr 13 09:59:39 UTC 2007


to enable and disable interrupts on SPARC architecture RTEMS uses traps. Most 
likely the reason for that is to have the read/write sequence to the Processor 
Status Register (PSR) atomic.

I doubt that this is really necessary and want to know the reasons for that. If 
I am wrong, however, I recommend to document the reasons in a comment in the 
source code in future revisions of RTEMS.

Let me go into detail:

The SPARC V8 Architecture Manual states
"If traps are enabled (ET=1), care must be taken if software is to disable them
(ET=0). Since the “RDPSR, WRPSR” sequence is interruptible — allowing the
PSR to be changed between the two instructions — this sequence is not a reliable
mechanism to disable traps. Two alternatives are:
1) Generate a Ticc trap, the handler for which disables traps. The trap handler
should verify that it was indeed “called” from supervisor mode (by examining
the PS bit of the PSR) before returning from the trap to the supervisor.
2) Use the “RDPSR, WRPSR” sequence, but write all the interrupt and trap
handlers so that before they return to the supervisor, they restore the PSR to 
the value it had when the interrupt handler was entered."

In the RTEMS file sparc.h we find (legacy?) code in comments that enables and 
disables interrupts outside of traps:

  *  Manipulate the interrupt level in the psr

#define sparc_disable_interrupts( _level ) \
   do { \
     register unsigned int _newlevel; \
     sparc_get_psr( _level ); \
     (_newlevel) = (_level) | SPARC_PSR_PIL_MASK; \
     sparc_set_psr( _newlevel ); \
   } while ( 0 )

#define sparc_enable_interrupts( _level ) \
   do { \
     unsigned int _tmp; \
     sparc_get_psr( _tmp ); \
     _tmp &= ~SPARC_PSR_PIL_MASK; \
     _tmp |= (_level) & SPARC_PSR_PIL_MASK; \
     sparc_set_psr( _tmp ); \
   } while ( 0 )

The RTEMS interrupt handler saves the PSR upon entry and restores it as one of 
its last instructions. RTEMS always runs in supervisor mode on SPARCs.

So, strictly speaking, I see no reason why this code is commented out and 
enabling and disabling interrupts happens in slower trap handlers instead of 
this faster macros. May be the macros would need a memory barrier to work 
properly with gcc's optimizations (instructions could refer to status bits in 
the PSR register).

A possible scenario I can think of, that could disencourage the macro-approach 
is the nasty 3-cycles delay for writes to PSR. What if the CPU writes the PSR 
and right after this instruction (before the obligatory 3 nop:s, before the
PSR value is settled) an interrupt occurs? The first thing RTEMS will do is to 
save PSR in l0 register, see

#define TRAP(_vector, _handler)  \
   mov   %psr, %l0 ; \
   sethi %hi(_handler), %l4 ; \
   jmp   %l4+%lo(_handler); \
   mov   _vector, %l3

in asm.h. Will the CPU take the proper value of the PSR (the value __after__ the 
update done in the macro)?

Any comments on this?
Is this scenario the reason for the trap approach? If not, are there other threats?

Best regards
Stephan Grünfelder


   Software Engineer

   Stachegasse 16
   A-1120 Vienna, AUSTRIA / EUROPE
   Internet: http://www.space.at

   Tel.   : +43-1-80199/5530
   Fax    : +43-1-80199/5577
   E-Mail: stephan.gruenfelder at space.at
   This email is for information only!

More information about the users mailing list