[PATCH 4/4] SPARC: optimize IRQ enable & disable

Gedare Bloom gedare at rtems.org
Wed Nov 19 19:19:13 UTC 2014


This one needs a release note as it may impede some applications if
they assumed they could use these trap vectors.

Also, do these changes complicate the paravirtualization efforts done
with sparc32 for xtratum?

Otherwise, quick skim of the patch series looked good.

On Wed, Nov 19, 2014 at 10:35 AM, Daniel Hellstrom <daniel at 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
> five instructions due to this.
> ---
>  c/src/lib/libbsp/sparc/leon3/startup/spurious.c |    9 +-
>  c/src/lib/libbsp/sparc/shared/irq_asm.S         |   35 +++----
>  c/src/lib/libbsp/sparc/shared/start/start.S     |   25 ++++-
>  c/src/lib/libcpu/sparc/syscall/syscall.S        |  116 +++++++++++++----------
>  c/src/lib/libcpu/sparc/syscall/syscall.h        |    2 -
>  cpukit/score/cpu/sparc/rtems/score/sparc.h      |   13 ++-
>  6 files changed, 115 insertions(+), 85 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..f826c78 100644
> --- a/c/src/lib/libbsp/sparc/shared/irq_asm.S
> +++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S
> @@ -585,38 +585,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      9                               ! 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
>
>          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
> +        bne,a    isr_dispatch     ! Yes, then invoke the dispatcher.
> +                                  ! g1 = Old PSR PIL returned from IRQDis
> +         ta      10               ! 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..b13eba2 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):
> +SYM(sparc_syscall_exit):
>
> -       mov     SYS_irqdis, %g1
> -       retl
> -        ta     0
> +       mov     SYS_exit, %g1
> +       mov     %o0, %g2        ! Additional exit code 1
> +       mov     %o1, %g3        ! Additional exit code 2
> +       ta      0
>
> -        PUBLIC(sparc_enable_interrupts)
> +       /*
> +        *  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..91aa65b 100644
> --- a/cpukit/score/cpu/sparc/rtems/score/sparc.h
> +++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h
> @@ -306,7 +306,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 9\n\t" : "=r" (psr) ::);
> +       return psr;
> +}
>
>  /**
>   * @brief SPARC enable processor interrupts.
> @@ -315,7 +320,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 10\n" :: "r" (_psr) :);
> +}
>
>  /**
>   * @brief SPARC exit through system call 1
> --
> 1.7.0.4
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel


More information about the devel mailing list