Changeset 256226b in rtems


Ignore:
Timestamp:
Aug 9, 2001, 9:09:52 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Children:
6559511
Parents:
3bb9542c
Message:

2001-08-09 Chris Johns <ccj@…>

  • cpu_asm.S: This patch was co-developed with Eric Norum <eric.norum@…>. It closes a one instruction window on some m68k CPU cores. It fixes symptoms seen as:

1) No more `interrupt handler invoked twice for

a single interrupt'.

2) No more `lockup when mc68360 CPM and PIT interrupts

are at different levels'.

It does insert a little more overhead on machines without hardware
interrupt stacks but correctness has a price.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/score/cpu/m68k/cpu_asm.S

    r3bb9542c r256226b  
    44 *  of RTEMS.
    55 *
    6  *  COPYRIGHT (c) 1989-1999.
     6 *  COPYRIGHT (c) 1989-2001.
    77 *  On-Line Applications Research Corporation (OAR).
    88 *
     
    6969        fsave    a0@-                     | save 68881/68882 state frame
    7070        tstb     a0@                      | check for a null frame
    71         beq      nosv                     | Yes, skip save of user model
     71        beq.b    nosv                     | Yes, skip save of user model
    7272        fmovem   fp0-fp7,a0@-             | save data registers (fp0-fp7)
    7373        fmovem   fpc/fps/fpi,a0@-         | and save control registers
     
    8484        moval    a1@,a0                   | a0 = address of saved context
    8585        tstb     a0@                      | Null context frame?
    86         beq      norst                    | Yes, skip fp restore
     86        beq.b    norst                    | Yes, skip fp restore
    8787        addql    #4,a0                    | throwaway non-null flag
    8888        fmovem   a0@+,fpc/fps/fpi         | restore control registers
     
    102102 *    Upon entry, the master stack will contain an interrupt stack frame
    103103 *    back to the interrupted thread and the interrupt stack will contain
    104  *    a throwaway interrupt stack frame.  If dispatching is enabled, this
    105  *    is the outer most interrupt, and (a context switch is necessary or
    106  *    the current thread has signals), then set up the master stack to
     104 *    a throwaway interrupt stack frame.  If dispatching is enabled, and this
     105 *    is the outer most interrupt, and a context switch is necessary or
     106 *    the current thread has pending signals, then set up the master stack to
    107107 *    transfer control to the interrupt dispatcher.
    108108 */
    109109
    110 /*
    111  *  With this approach, lower priority interrupts may
    112  *  execute twice if a higher priority interrupt is
    113  *  acknowledged before _Thread_Dispatch_disable is
    114  *  incremented and the higher priority interrupt
    115  *  performs a context switch after executing. The lower
    116  *  priority interrupt will execute (1) at the end of the
    117  *  higher priority interrupt in the new context if
    118  *  permitted by the new interrupt level mask, and (2) when
    119  *  the original context regains the cpu.
    120  */
    121  
    122110#if ( M68K_COLDFIRE_ARCH == 1 )
    123111.set SR_OFFSET,    2                     | Status register offset
     
    143131#if ( M68K_COLDFIRE_ARCH == 0 )
    144132        moveml  d0-d1/a0-a1,a7@-         | save d0-d1,a0-a1
    145         movew   a7@(SAVED+FVO_OFFSET),d0 | d0 = F/VO
    146         andl    #0x0fff,d0               | d0 = vector offset in vbr
    147133#else
    148134        lea     a7@(-SAVED),a7
    149135        movm.l  d0-d1/a0-a1,a7@          | save d0-d1,a0-a1
     136#endif
    150137        movew   a7@(SAVED+FVO_OFFSET),d0 | d0 = F/VO
    151138        andl    #0x0ffc,d0               | d0 = vector offset in vbr
    152 #endif
    153139
    154140
    155141#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 )
    156   #if ( M68K_COLDFIRE_ARCH == 0 )
    157         movew   sr,d1                   | Save status register
    158         oriw    #0x700,sr               | Disable interrupts
    159   #else
    160         move.l  d0,a7@-                 | Save d0 value
    161         move.l  #0x700,d0               | Load in disable ints value
    162         move.w  sr,d1                   | Grab SR
    163         or.l    d1,d0                   | Create new SR
    164         move.w  d0,sr                   | Disable interrupts
    165         move.l  a7@+,d0                 | Restore d0 value
    166   #endif
    167  
    168         tstl    SYM (_ISR_Nest_level)   | Interrupting an interrupt handler?
    169         bne     1f                      | Yes, just skip over stack switch code
    170         movel   SYM(_CPU_Interrupt_stack_high),a0       | End of interrupt stack
    171         movel   a7,a0@-                 | Save task stack pointer
    172         movel   a0,a7                   | Switch to interrupt stack
     142        movel   _CPU_Interrupt_stack_high,a0    | a0 now point just above interrupt stack
     143        cmpl    _CPU_Interrupt_stack_low,a7     | stack below interrupt stack?
     144        bcs.b   1f                      | yes, switch to interrupt stack
     145        cmpl    a0,a7                   | stack above interrupt stack?
     146        bcs.b   2f                      | no, do not switch stacks
    1731471:
    174         addql   #1,SYM(_ISR_Nest_level) | one nest level deeper
    175         movew   d1,sr                   | Restore status register
    176 #else
    177         addql   #1,SYM (_ISR_Nest_level) | one nest level deeper
     148        movel   a7,a1                   | copy task stack pointer
     149        movel   a0,a7                   | switch to interrupt stack
     150        movel   a1,a7@-                 | store task stack pointer on interrupt stack
     1512:
    178152#endif /* CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 */
    179153
     
    181155        movel   @( SYM (_ISR_Vector_table),d0:w:1),a0| fetch the ISR
    182156#else
    183         movel   # SYM (_ISR_Vector_table),a0   | a0 = base of RTEMS table
     157        movel   # SYM (_ISR_Vector_table),a0   | a0 = base of RTEMS table
    184158        addal   d0,a0                    | a0 = address of vector
    185159        movel   (a0),a0                  | a0 = address of user routine
     
    192166
    193167#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 )
    194   #if ( M68K_COLDFIRE_ARCH == 0 )
    195         movew   sr,d0                   | Save status register
    196         oriw    #0x700,sr               | Disable interrupts
    197   #else
    198         move.l  #0x700,d1               | Load in disable int value
    199         move.w  sr,d0                   | Grab SR
    200         or.l    d0,d1                   | Create new SR
    201         move.w  d1,sr                   | Load to disable interrupts
    202   #endif
    203 
    204         subql   #1,SYM(_ISR_Nest_level) | Reduce interrupt-nesting count
    205         bne     1f                      | Skip if return to interrupt
     168        movel   _CPU_Interrupt_stack_high,a0
     169        subql   #4,a0
     170        cmpl    a0,a7                   | At top of interrupt stack?
     171        bne.b   1f                      | No, do not restore task stack pointer
    206172        movel   (a7),a7                 | Restore task stack pointer
    2071731:
    208         movew   d0,sr                   | Restore status register
    209 #else
    210         subql   #1,SYM (_ISR_Nest_level) | one less nest level
    211174#endif /* CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 */
    212175
    213176        subql   #1,SYM (_Thread_Dispatch_disable_level)
    214177                                         | unnest multitasking
    215         bne     exit                     | If dispatch disabled, exit
     178        bne.b    exit                    | If dispatch disabled, exit
    216179
    217180#if ( M68K_HAS_SEPARATE_STACKS == 1 )
     
    219182        andw    a7@(SAVED+FVO_OFFSET),d0 | get F/VO
    220183        cmpiw   #0x1000,d0               | is it a throwaway isf?
    221         bne     exit                     | NOT outer level, so branch
    222 #endif
    223 
     184        bne.b   exit                     | NOT outer level, so branch
     185#else
     186/*
     187 * If we have a CPU which allows a higher-priority interrupt to preempt a
     188 * lower priority handler before the lower-priority handler can increment
     189 * _Thread_Dispatch_disable_level then we must check the PC on the stack to
     190 * see if it is _ISR_Handler.  If it is we have the case of nesting interrupts
     191 * without the dispatch level being incremented.
     192 */
     193  #if ( M68K_COLDFIRE_ARCH == 0 && M68K_MC68060_ARCH == 0 )
     194        cmpl    #_ISR_Handler,a7@(SAVED+PC_OFFSET)
     195        beq.b   exit       
     196  #endif
     197#endif
    224198        tstl    SYM (_Context_Switch_necessary)
    225199                                         | Is thread switch necessary?
    226         bne     bframe                   | Yes, invoke dispatcher
     200        bne.b   bframe                   | Yes, invoke dispatcher
    227201
    228202        tstl    SYM (_ISR_Signals_to_thread_executing)
    229203                                         | signals sent to Run_thread
    230204                                         |   while in interrupt handler?
    231         beq     exit                     | No, then exit
    232 
     205        beq.b   exit                     | No, then exit
    233206
    234207bframe: clrl    SYM (_ISR_Signals_to_thread_executing)
Note: See TracChangeset for help on using the changeset viewer.