Changeset d0b7c4e6 in rtems


Ignore:
Timestamp:
Apr 22, 1996, 4:30:02 PM (25 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
f581163a
Parents:
767a6c6
Message:

updartes from Tony Bennett

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/score/cpu/hppa1.1/cpu.c

    r767a6c6 rd0b7c4e6  
    2020#include <rtems/system.h>
    2121#include <rtems/score/isr.h>
     22void hppa_cpu_halt(unsigned32 the_error);
    2223
    23 void hppa_external_interrupt_initialize(void);
    24 void hppa_external_interrupt_enable(unsigned32);
    25 void hppa_external_interrupt_disable(unsigned32);
    26 void hppa_external_interrupt(unsigned32, CPU_Interrupt_frame *);
    27 void hppa_cpu_halt(unsigned32);
     24
     25/*PAGE
     26 *
     27 *  _CPU_ISR_install_raw_handler
     28 */
     29 
     30void _CPU_ISR_install_raw_handler(
     31  unsigned32  vector,
     32  proc_ptr    new_handler,
     33  proc_ptr   *old_handler
     34)
     35{
     36  /*
     37   *  This is unsupported.  For HPPA this function is handled by BSP
     38   */
     39
     40  _CPU_Fatal_halt( 0xdeaddead );
     41}
     42
     43
    2844
    2945/*
    30  * The first level interrupt handler for first 32 interrupts/traps.
    31  * Indexed by vector; generally each entry is _Generic_ISR_Handler.
    32  * Some TLB traps may have their own first level handler.
     46 * This is the default handler which is called if
     47 * _CPU_ISR_install_vector() has not been called for the
     48 * specified vector.  It simply forwards onto the spurious
     49 * handler defined in the cpu-table.
    3350 */
    3451
    35 extern void _Generic_ISR_Handler(void);
    36 unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS];
     52static ISR_Handler
     53hppa_interrupt_report_spurious(ISR_Vector_number vector,
     54                               void* rtems_isr_frame) /* HPPA extension */
     55{
     56
     57    /*
     58     * If the CPU table defines a spurious_handler, then
     59     * call it.  If the handler returns halt.
     60     */
     61    if ( _CPU_Table.spurious_handler )
     62        _CPU_Table.spurious_handler(vector, rtems_isr_frame);
     63   
     64    hppa_cpu_halt(vector);
     65}
     66
     67
     68/*PAGE
     69 *
     70 *  _CPU_ISR_Get_level
     71 */
     72 
     73unsigned32 _CPU_ISR_Get_level(void)
     74{
     75    int level;
     76    HPPA_ASM_SSM(0, level);     /* change no bits; just get copy */
     77    if (level & HPPA_PSW_I)
     78        return 0;
     79    return 1;
     80}
     81
     82/*PAGE
     83 *
     84 *  _CPU_ISR_install_vector
     85 *
     86 *  This kernel routine installs the RTEMS handler for the
     87 *  specified vector.  The handler is a C callable routine.
     88 *
     89 *  Input parameters:
     90 *    vector      - interrupt vector number
     91 *    old_handler - former ISR for this vector number
     92 *    new_handler - replacement ISR for this vector number
     93 *
     94 *  Output parameters:  NONE
     95 *
     96 */
     97
     98void _CPU_ISR_install_vector(
     99  unsigned32  vector,
     100  proc_ptr    new_handler,
     101  proc_ptr   *old_handler
     102)
     103{
     104    *old_handler = _ISR_Vector_table[vector];
     105
     106    _ISR_Vector_table[vector] = new_handler;
     107}
    37108
    38109/*  _CPU_Initialize
     
    52123{
    53124    register unsigned8  *fp_context;
    54     unsigned32 iva;
    55     unsigned32 iva_table;
    56125    int i;
    57 
    58     extern void IVA_Table(void);
     126    proc_ptr   old_handler;
    59127
    60128    /*
     
    74142
    75143    /*
    76      * Init the first level interrupt handlers
    77      */
    78 
    79     for (i=0; i <= HPPA_INTERNAL_INTERRUPTS; i++)
    80         HPPA_first_level_interrupt_handler[i] = (unsigned32) _Generic_ISR_Handler;
    81 
    82     /*
    83144     * Init the 2nd level interrupt handlers
    84145     */
    85146
    86     for (i=0; i <= CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
    87         _ISR_Vector_table[i] = (ISR_Handler_entry) hppa_cpu_halt;
    88 
    89     /*
    90      * Stabilize the interrupt stuff
    91      */
    92 
    93     (void) hppa_external_interrupt_initialize();
    94 
    95     /*
    96      * Set the IVA to point to physical address of the IVA_Table
    97      */
    98 
    99     iva_table = (unsigned32) IVA_Table;
    100 #if defined(hppa1_1)
    101     /*
    102      * HACK:  (from PA72000 TRM, page 4-19)
    103      * "The hardware TLB miss handler will never attempt to service
    104      *  a non-access TLB miss or a TLB protection violation.  It
    105      *  will only attempt to service TLB accesses that would cause
    106      *  Trap Numbers 6 (Instruction TLB miss) and 15 (Data TLB miss)."
    107      *
    108      * The LPA instruction is used to translate a virtual address to
    109      * a physical address, however, if the requested virtual address
    110      * is not currently resident in the TLB, the hardware TLB miss
    111      * handler will NOT insert it.  In this situation Trap Number
    112      * #17 is invoked (Non-access Data TLB miss fault).
    113      *
    114      * To work around this, a dummy data access is first performed
    115      * to the virtual address prior to the LPA.  The dummy access
    116      * causes the TLB entry to be inserted (if not already present)
    117      * and then the following LPA instruction will not generate
    118      * a non-access data TLB miss fault.
    119      *
    120      * It is unclear whether or not this behaves the same way for
    121      * the PA8000.
    122      *
    123      */
    124     iva = *(volatile unsigned32 *)iva_table;  /* dummy access */
    125 #endif
    126 
    127     HPPA_ASM_LPA(0, iva_table, iva);
    128     set_iva(iva);
     147    for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
     148        _CPU_ISR_install_vector(i,
     149                                hppa_interrupt_report_spurious,
     150                                &old_handler);
    129151
    130152    _CPU_Table = *cpu_table;
     153   
    131154}
    132155
    133 /*PAGE
    134  *
    135  *  _CPU_ISR_Get_level
    136  */
    137  
    138 unsigned32 _CPU_ISR_Get_level(void)
    139 {
    140     int level;
    141     HPPA_ASM_SSM(0, level);     /* change no bits; just get copy */
    142     if (level & HPPA_PSW_I)
    143         return 0;
    144     return 1;
    145 }
    146 
    147 /*PAGE
    148  *
    149  *  _CPU_ISR_install_raw_handler
    150  */
    151  
    152 void _CPU_ISR_install_raw_handler(
    153   unsigned32  vector,
    154   proc_ptr    new_handler,
    155   proc_ptr   *old_handler
    156 )
    157 {
    158   /*
    159    *  This is unsupported.
    160    */
    161 
    162   _CPU_Fatal_halt( 0xdeaddead );
    163 }
    164 
    165 /*PAGE
    166  *
    167  *  _CPU_ISR_install_vector
    168  *
    169  *  This kernel routine installs the RTEMS handler for the
    170  *  specified vector.
    171  *
    172  *  Input parameters:
    173  *    vector      - interrupt vector number
    174  *    old_handler - former ISR for this vector number
    175  *    new_handler - replacement ISR for this vector number
    176  *
    177  *  Output parameters:  NONE
    178  *
    179  */
    180 
    181 /*
    182  * HPPA has 8w for each vector instead of an address to jump to.
    183  * We put the actual ISR address in '_ISR_vector_table'.  This will
    184  * be pulled by the code in the vector.
    185  */
    186 
    187 void _CPU_ISR_install_vector(
    188   unsigned32  vector,
    189   proc_ptr    new_handler,
    190   proc_ptr   *old_handler
    191 )
    192 {
    193     *old_handler = _ISR_Vector_table[vector];
    194 
    195     _ISR_Vector_table[vector] = new_handler;
    196 
    197     if (vector >= HPPA_INTERRUPT_EXTERNAL_BASE)
    198     {
    199         unsigned32 external_vector;
    200 
    201         external_vector = vector - HPPA_INTERRUPT_EXTERNAL_BASE;
    202         if (new_handler)
    203             hppa_external_interrupt_enable(external_vector);
    204         else
    205             /* XXX this can never happen due to _ISR_Is_valid_user_handler */
    206             hppa_external_interrupt_disable(external_vector);
    207     }
    208 }
    209 
    210 
    211 /*
    212  * Support for external and spurious interrupts on HPPA
    213  *
    214  *  TODO:
    215  *    Count interrupts
    216  *    make sure interrupts disabled properly
    217  */
    218 
    219 #define DISMISS(mask)           set_eirr(mask)
    220 #define DISABLE(mask)           set_eiem(get_eiem() & ~(mask))
    221 #define ENABLE(mask)            set_eiem(get_eiem() | (mask))
    222 #define VECTOR_TO_MASK(v)       (1 << (31 - (v)))
    223 
    224 /*
    225  * Init the external interrupt scheme
    226  * called by bsp_start()
    227  */
    228 
    229 void
    230 hppa_external_interrupt_initialize(void)
    231 {
    232     proc_ptr ignore;
    233 
    234     /* mark them all unused */
    235     DISABLE(~0);
    236     DISMISS(~0);
    237 
    238     /* install the external interrupt handler */
    239     _CPU_ISR_install_vector(
    240         HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
    241         (proc_ptr)hppa_external_interrupt, &ignore
    242 );
    243 }
    244 
    245 /*
    246  * Enable a specific external interrupt
    247  */
    248 
    249 void
    250 hppa_external_interrupt_enable(unsigned32 v)
    251 {
    252     unsigned32 isrlevel;
    253 
    254     _CPU_ISR_Disable(isrlevel);
    255     ENABLE(VECTOR_TO_MASK(v));
    256     _CPU_ISR_Enable(isrlevel);
    257 }
    258 
    259 /*
    260  * Does not clear or otherwise affect any pending requests
    261  */
    262 
    263 void
    264 hppa_external_interrupt_disable(unsigned32 v)
    265 {
    266     unsigned32 isrlevel;
    267 
    268     _CPU_ISR_Disable(isrlevel);
    269     DISABLE(VECTOR_TO_MASK(v));
    270     _CPU_ISR_Enable(isrlevel);
    271 }
    272 
    273 void
    274 hppa_external_interrupt_spurious_handler(unsigned32           vector,
    275                                          CPU_Interrupt_frame *iframe)
    276 {
    277 /* XXX should not be printing :)
    278     printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
    279        vector, iframe->Interrupt.pcoqfront);
    280 */
    281 }
    282 
    283 void
    284 hppa_external_interrupt_report_spurious(unsigned32           spurious_mask,
    285                                         CPU_Interrupt_frame *iframe)
    286 {
    287     int v;
    288     for (v=0; v < HPPA_EXTERNAL_INTERRUPTS; v++)
    289         if (VECTOR_TO_MASK(v) & spurious_mask)
    290         {
    291             DISMISS(VECTOR_TO_MASK(v));
    292             DISABLE(VECTOR_TO_MASK(v));
    293             hppa_external_interrupt_spurious_handler(v, iframe);
    294         }
    295     DISMISS(spurious_mask);
    296 }
    297 
    298 
    299 /*
    300  * External interrupt handler.
    301  * This is installed as cpu interrupt handler for
    302  * HPPA_INTERRUPT_EXTERNAL_INTERRUPT. It vectors out to
    303  * specific external interrupt handlers.
    304  */
    305 
    306 void
    307 hppa_external_interrupt(unsigned32           vector,
    308                         CPU_Interrupt_frame *iframe)
    309 {
    310     unsigned32   mask;
    311     unsigned32  *vp, *max_vp;
    312     unsigned32   external_vector;
    313     unsigned32   global_vector;
    314     hppa_rtems_isr_entry handler;
    315 
    316     max_vp = &_CPU_Table.external_interrupt[_CPU_Table.external_interrupts];
    317     while ( (mask = (get_eirr() & get_eiem())) )
    318     {
    319         for (vp = _CPU_Table.external_interrupt; (vp < max_vp) && mask; vp++)
    320         {
    321             unsigned32 m;
    322 
    323             external_vector = *vp;
    324             global_vector = external_vector + HPPA_INTERRUPT_EXTERNAL_BASE;
    325             m = VECTOR_TO_MASK(external_vector);
    326             handler = (hppa_rtems_isr_entry) _ISR_Vector_table[global_vector];
    327             if ((m & mask) && handler)
    328             {
    329                 DISMISS(m);
    330                 mask &= ~m;
    331                 handler(global_vector, iframe);
    332             }
    333         }
    334 
    335         if (mask != 0) {
    336             if ( _CPU_Table.spurious_handler )
    337             {
    338                 handler = (hppa_rtems_isr_entry) _CPU_Table.spurious_handler;
    339                 handler(mask, iframe);
    340             }
    341             else
    342                 hppa_external_interrupt_report_spurious(mask, iframe);
    343         }
    344     }
    345 }
    346156
    347157/*
     
    352162 * Later on, this will allow us to return to the prom.
    353163 * For now, we just ignore 'type_of_halt'
     164 *
     165 * XXX
     166 * NOTE: for gcc, this function must be at the bottom
     167 * of the file, that is because if it is at the top
     168 * of the file, gcc will inline it's calls.  Since
     169 * the function uses the HPPA_ASM_LABEL() macro, when
     170 * gcc inlines it, you get two definitions of the same
     171 * label name, which is an assembly error.
    354172 */
     173
    355174
    356175void
     
    361180    _CPU_ISR_Disable(isrlevel);
    362181
     182    /*
     183     * XXXXX NOTE: This label is only needed that that when
     184     * the simulator stops, it shows the label name specified
     185     */
    363186    HPPA_ASM_LABEL("_hppa_cpu_halt");
    364     HPPA_ASM_BREAK(1, 0);
     187    HPPA_ASM_BREAK(0, 0);
    365188}
     189
  • c/src/exec/score/cpu/hppa1.1/cpu.h

    r767a6c6 rd0b7c4e6  
    217217  void       (*postdriver_hook)( void );
    218218  void       (*idle_task)( void );
    219 
    220                  /* HPPA simulator is slow enough; don't waste time
    221                   * zeroing memory that is already zero
    222                   */
    223219  boolean      do_zero_of_workspace;
    224 
    225220  unsigned32   interrupt_stack_size;
    226221  unsigned32   extra_mpci_receive_server_stack;
    227 
    228   /*
    229    * Control of external interrupts.
    230    * We keep a table of external vector numbers (0 - 31)
    231    * The table is sorted by priority, that is: the first entry
    232    * in the table indicates the vector that is highest priorty.
    233    * The handler function is stored in _ISR_Vector_Table[] and
    234    * is set by rtems_interrupt_catch()
    235    */
    236 
    237   unsigned32   external_interrupts;   /* # of external interrupts we use */
    238   unsigned32   external_interrupt[HPPA_EXTERNAL_INTERRUPTS];
     222  void *     (*stack_allocate_hook)( unsigned32 );
     223  void       (*stack_free_hook)( void * );
     224  /* end of fields required on all CPUs */
    239225
    240226  hppa_rtems_isr_entry spurious_handler;
     
    250236EXTERN void               *_CPU_Interrupt_stack_high;
    251237
    252 /* entry points */
    253 void hppa_external_interrupt_spurious_handler(unsigned32, CPU_Interrupt_frame *);
    254 
    255238#endif          /* ! ASM */
    256239
     
    286269/*
    287270 * HPPA has 32 interrupts, then 32 external interrupts
    288  * Rtems (_ISR_Vector_Table) is aware of the first 64
    289  * A BSP may reserve more.
    290  *
    291  * External interrupts all come thru the same vector (4)
    292  * The external handler is the only person aware of the other
    293  * interrupts (genie, rhino, etc)
    294  */
    295 
    296 #define CPU_INTERRUPT_NUMBER_OF_VECTORS      (HPPA_INTERRUPT_MAX)
     271 * Rtems (_ISR_Vector_Table) is aware ONLY of the first 32
     272 * The BSP is aware of the external interrupts and possibly more.
     273 *
     274 */
     275
     276#define CPU_INTERRUPT_NUMBER_OF_VECTORS      (HPPA_INTERNAL_INTERRUPTS)
    297277#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER  (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
    298278
  • c/src/exec/score/cpu/hppa1.1/cpu_asm.s

    r767a6c6 rd0b7c4e6  
    1 #       @(#)cpu_asm.S   1.7 - 95/09/21
    2 #       
    31#
    42# TODO:
     
    3129#include <rtems/score/cpu_asm.h>
    3230#include <rtems/score/cpu.h>
    33 
    3431#include <rtems/score/offsets.h>
    3532
     
    6562
    6663#  PAGE^L
    67 #  void __Generic_ISR_Handler()
     64#  void _Generic_ISR_Handler()
    6865#
    6966#  This routine provides the RTEMS interrupt management.
    7067#
    71 #  NOTE:
    72 #    Upon entry, the stack will contain a stack frame back to the
    73 #    interrupted task.  If dispatching is enabled, this is the
    74 #    outer most interrupt, (and a context switch is necessary or
    75 #    the current task has signals), then set up the stack to
    76 #    transfer control to the interrupt dispatcher.
    77 #
    78 #
    7968#   We jump here from the interrupt vector.
    80 #   The hardware has done some stuff for us:
     69#   The HPPA hardware has done some stuff for us:
    8170#       PSW saved in IPSW
    8271#       PSW set to 0
     
    9079#                 SHR 0 1 2  3  4  5  6
    9180#
    92 #   Our vector stub did the following
    93 #       placed vector number is in r1
    94 #
    95 #        stub
    96 #            r1 <- vector number
    97 #            save ipsw under rock
    98 #            ipsw = ipsw & ~1    --  disable ints
    99 #            save qregs under rock
    100 #            qra = _Generic_ISR_handler
    101 #            rfi
    102 #
    103 ################################################
    104 
    105 #  Distinct Interrupt Entry Points
    106 #
    107 #  The following macro and the 32 instantiations of the macro
    108 #  are necessary to determine which interrupt vector occurred.
    109 #
    110 #  r9 is loaded with the vector number and then we jump to
    111 #    the first level interrupt handler.  In most cases this
    112 #    is _Generic_ISR_Handler.  In a few cases (such as TLB misc)
    113 #    it may be to some other entry point.
    114 #
    115 
    116 # table for first level interrupt handlers
    117         .import   HPPA_first_level_interrupt_handler, data
    118 
    119 #define THANDLER(vector) \
    120         mtctl   %r9,  isr_r9 ! \
    121         mtctl   %r8,  isr_r8 ! \
    122         ldi     vector, %r9  ! \
    123         ldil    L%HPPA_first_level_interrupt_handler,%r8 ! \
    124         ldo     R%HPPA_first_level_interrupt_handler(%r8),%r8 ! \
    125         ldwx,s  %r9(%r8),%r8 ! \
    126         bv      0(%r8) ! \
    127         mfctl   isr_r8, %r8
    128 
    129         .align 4096
    130         .EXPORT IVA_Table,ENTRY,PRIV_LEV=0
    131 IVA_Table:
    132         .PROC
    133         .CALLINFO FRAME=0,NO_CALLS
    134         .ENTRY
    135 
    136         THANDLER(0)             /* unused */
    137 
    138         THANDLER(HPPA_INTERRUPT_HIGH_PRIORITY_MACHINE_CHECK)
    139 
    140         THANDLER(HPPA_INTERRUPT_POWER_FAIL)
    141 
    142         THANDLER(HPPA_INTERRUPT_RECOVERY_COUNTER)
    143 
    144         THANDLER(HPPA_INTERRUPT_EXTERNAL_INTERRUPT)
    145 
    146         THANDLER(HPPA_INTERRUPT_LOW_PRIORITY_MACHINE_CHECK)
    147 
    148         THANDLER(HPPA_INTERRUPT_INSTRUCTION_TLB_MISS)
    149 
    150         THANDLER(HPPA_INTERRUPT_INSTRUCTION_MEMORY_PROTECTION)
    151 
    152         THANDLER(HPPA_INTERRUPT_ILLEGAL_INSTRUCTION)
    153 
    154         THANDLER(HPPA_INTERRUPT_BREAK_INSTRUCTION)
    155 
    156         THANDLER(HPPA_INTERRUPT_PRIVILEGED_OPERATION)
    157 
    158         THANDLER(HPPA_INTERRUPT_PRIVILEGED_REGISTER)
    159 
    160         THANDLER(HPPA_INTERRUPT_OVERFLOW)
    161 
    162         THANDLER(HPPA_INTERRUPT_CONDITIONAL)
    163 
    164         THANDLER(HPPA_INTERRUPT_ASSIST_EXCEPTION)
    165 
    166         THANDLER(HPPA_INTERRUPT_DATA_TLB_MISS)
    167 
    168         THANDLER(HPPA_INTERRUPT_NON_ACCESS_INSTRUCTION_TLB_MISS)
    169 
    170         THANDLER(HPPA_INTERRUPT_NON_ACCESS_DATA_TLB_MISS)
    171 
    172         THANDLER(HPPA_INTERRUPT_DATA_MEMORY_PROTECTION)
    173 
    174         THANDLER(HPPA_INTERRUPT_DATA_MEMORY_BREAK)
    175 
    176         THANDLER(HPPA_INTERRUPT_TLB_DIRTY_BIT)
    177 
    178         THANDLER(HPPA_INTERRUPT_PAGE_REFERENCE)
    179 
    180         THANDLER(HPPA_INTERRUPT_ASSIST_EMULATION)
    181 
    182         THANDLER(HPPA_INTERRUPT_HIGHER_PRIVILEGE_TRANSFER)
    183 
    184         THANDLER(HPPA_INTERRUPT_LOWER_PRIVILEGE_TRANSFER)
    185 
    186         THANDLER(HPPA_INTERRUPT_TAKEN_BRANCH)
    187 
    188         THANDLER(HPPA_INTERRUPT_DATA_MEMORY_ACCESS_RIGHTS)
    189 
    190         THANDLER(HPPA_INTERRUPT_DATA_MEMORY_PROTECTION_ID)
    191 
    192         THANDLER(HPPA_INTERRUPT_UNALIGNED_DATA_REFERENCE)
    193 
    194         THANDLER(HPPA_INTERRUPT_PERFORMANCE_MONITOR)
    195 
    196         THANDLER(HPPA_INTERRUPT_INSTRUCTION_DEBUG)
    197 
    198         THANDLER(HPPA_INTERRUPT_DATA_DEBUG)
    199 
    200         .EXIT
    201         .PROCEND
    202 
     81#   Our vector stub (in the BSP) MUST have done the following: 
     82#
     83#   a) Saved the original %r9 into %isr_r9 (%cr25)
     84#   b) Placed the vector number in %r9
     85#   c) Was allowed to also destroy $isr_r8 (%cr26),
     86#      but the stub was NOT allowed to destroy any other registers.
     87#
     88#   The typical stub sequence (in the BSP) should look like this:
     89#
     90#   a)     mtctl   %r9,isr_r9     ; (save r9 in cr25)
     91#   b)     ldi     vector,%r9     ; (load constant vector number in r9)
     92#   c)     mtctl   %r8,isr_r8     ; (save r8 in cr26)
     93#   d)     ldil    L%MY_BSP_first_level_interrupt_handler,%r8
     94#   e)     ldo     R%MY_BSP_first_level_interrupt_handler(%r8),%r8
     95#                                 ; (point to BSP raw handler table)
     96#   f)     ldwx,s  %r9(%r8),%r8   ; (load value from raw handler table)
     97#   g)     bv      0(%r8)         ; (call raw handler: _Generic_ISR_Handler)
     98#   h)     mfctl   isr_r8,%r8     ; (restore r8 from cr26 in delay slot)
     99#
     100#   Optionally, steps (c) thru (h) _could_ be replaced with a single
     101#          bl,n    _Generic_ISR_Handler,%r0
     102#
     103#
     104#
    203105        .EXPORT _Generic_ISR_Handler,ENTRY,PRIV_LEV=0
    204106_Generic_ISR_Handler:
     
    236138#  reg    current value        saved value
    237139# ------------------------------------------------
    238 #  arg0   scratch               isr_arg0  (ctl)
    239 #  r9     vector number         isr_r9    (ctl)
     140#  arg0   scratch               isr_arg0  (cr24)
     141#  r9     vector number         isr_r9    (cr25)
    240142#
    241143# Point to beginning of integer context and
     
    278180#  reg    current value        saved value
    279181# ------------------------------------------------
    280 #  arg0   scratch               isr_arg0  (ctl)
    281 #  r9     vector number         isr_r9    (ctl)
     182#  arg0   scratch               isr_arg0  (cr24)
     183#  r9     vector number         isr_r9    (cr25)
    282184#
    283185# Fix them
     
    378280
    379281# load address of user handler
     282# Note:  No error checking is done, it is assumed that the
     283#        vector table contains a valid address or a stub
     284#        spurious handler.
    380285        .import   _ISR_Vector_table,data
    381286        ldil      L%_ISR_Vector_table,%r8
     
    389294#    and we are using a hard coded address from a table
    390295#  So... we fudge r2 ourselves (ala dynacall)
    391 #
     296#  arg0 = vector number, arg1 = ptr to rtems_interrupt_frame
    392297        copy      %r9, %r26
    393298        .call  ARGW0=GR, ARGW1=GR
     
    405310        ldw        -4(sp), sp
    406311
    407 #    r3  -- &_ISR_Nest_level
     312#    r3  -- (most of) &_ISR_Nest_level
    408313#    r5  -- value _ISR_Nest_level
    409 #    r4  -- &_Thread_Dispatch_disable_level
     314#    r4  -- (most of) &_Thread_Dispatch_disable_level
    410315#    r6  -- value _Thread_Dispatch_disable_level
     316#    r7  -- (most of) &_ISR_Signals_to_thread_executing
     317#    r8  -- value _ISR_Signals_to_thread_executing
    411318
    412319        .import   _ISR_Nest_level,data
    413320        ldil      L%_ISR_Nest_level,%r3
    414         ldo       R%_ISR_Nest_level(%r3),%r3
    415         ldw       0(%r3),%r5
     321        ldw       R%_ISR_Nest_level(%r3),%r5
    416322
    417323        .import   _Thread_Dispatch_disable_level,data
    418324        ldil      L%_Thread_Dispatch_disable_level,%r4
    419         ldo       R%_Thread_Dispatch_disable_level(%r4),%r4
    420         ldw       0(%r4), %r6
     325        ldw       R%_Thread_Dispatch_disable_level(%r4),%r6
     326
     327        .import    _ISR_Signals_to_thread_executing,data
     328        ldil       L%_ISR_Signals_to_thread_executing,%r7
    421329
    422330# decrement isr nest level
    423331        addi      -1, %r5, %r5
    424         stw       %r5, 0(%r3)
     332        stw       %r5, R%_ISR_Nest_level(%r3)
    425333
    426334# decrement dispatch disable level counter and, if not 0, go on
    427335        addi       -1,%r6,%r6
    428336        comibf,=   0,%r6,isr_restore
    429         stw        %r6, 0(%r4)
     337        stw        %r6, R%_Thread_Dispatch_disable_level(%r4)
    430338
    431339# check whether or not a context switch is necessary
     
    437345# check whether or not a context switch is necessary because an ISR
    438346#    sent signals to the interrupted task
    439         .import    _ISR_Signals_to_thread_executing,data
    440         ldil       L%_ISR_Signals_to_thread_executing,%r8
    441         ldw        R%_ISR_Signals_to_thread_executing(%r8),%r8
     347        ldw        R%_ISR_Signals_to_thread_executing(%r7),%r8
    442348        comibt,=,n 0,%r8,isr_restore
    443349
     
    451357
    452358ISR_dispatch:
     359        stw        %r0, R%_ISR_Signals_to_thread_executing(%r7)
     360
    453361        ssm        HPPA_PSW_I, %r0
    454362
  • c/src/exec/score/cpu/hppa1.1/hppa.h

    r767a6c6 rd0b7c4e6  
    11/*
    2  * @(#)hppa.h   1.17 - 95/12/13
    3  *
    4  *
    52 *  Description:
    63 *             
  • cpukit/score/cpu/hppa1.1/cpu.c

    r767a6c6 rd0b7c4e6  
    2020#include <rtems/system.h>
    2121#include <rtems/score/isr.h>
     22void hppa_cpu_halt(unsigned32 the_error);
    2223
    23 void hppa_external_interrupt_initialize(void);
    24 void hppa_external_interrupt_enable(unsigned32);
    25 void hppa_external_interrupt_disable(unsigned32);
    26 void hppa_external_interrupt(unsigned32, CPU_Interrupt_frame *);
    27 void hppa_cpu_halt(unsigned32);
     24
     25/*PAGE
     26 *
     27 *  _CPU_ISR_install_raw_handler
     28 */
     29 
     30void _CPU_ISR_install_raw_handler(
     31  unsigned32  vector,
     32  proc_ptr    new_handler,
     33  proc_ptr   *old_handler
     34)
     35{
     36  /*
     37   *  This is unsupported.  For HPPA this function is handled by BSP
     38   */
     39
     40  _CPU_Fatal_halt( 0xdeaddead );
     41}
     42
     43
    2844
    2945/*
    30  * The first level interrupt handler for first 32 interrupts/traps.
    31  * Indexed by vector; generally each entry is _Generic_ISR_Handler.
    32  * Some TLB traps may have their own first level handler.
     46 * This is the default handler which is called if
     47 * _CPU_ISR_install_vector() has not been called for the
     48 * specified vector.  It simply forwards onto the spurious
     49 * handler defined in the cpu-table.
    3350 */
    3451
    35 extern void _Generic_ISR_Handler(void);
    36 unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS];
     52static ISR_Handler
     53hppa_interrupt_report_spurious(ISR_Vector_number vector,
     54                               void* rtems_isr_frame) /* HPPA extension */
     55{
     56
     57    /*
     58     * If the CPU table defines a spurious_handler, then
     59     * call it.  If the handler returns halt.
     60     */
     61    if ( _CPU_Table.spurious_handler )
     62        _CPU_Table.spurious_handler(vector, rtems_isr_frame);
     63   
     64    hppa_cpu_halt(vector);
     65}
     66
     67
     68/*PAGE
     69 *
     70 *  _CPU_ISR_Get_level
     71 */
     72 
     73unsigned32 _CPU_ISR_Get_level(void)
     74{
     75    int level;
     76    HPPA_ASM_SSM(0, level);     /* change no bits; just get copy */
     77    if (level & HPPA_PSW_I)
     78        return 0;
     79    return 1;
     80}
     81
     82/*PAGE
     83 *
     84 *  _CPU_ISR_install_vector
     85 *
     86 *  This kernel routine installs the RTEMS handler for the
     87 *  specified vector.  The handler is a C callable routine.
     88 *
     89 *  Input parameters:
     90 *    vector      - interrupt vector number
     91 *    old_handler - former ISR for this vector number
     92 *    new_handler - replacement ISR for this vector number
     93 *
     94 *  Output parameters:  NONE
     95 *
     96 */
     97
     98void _CPU_ISR_install_vector(
     99  unsigned32  vector,
     100  proc_ptr    new_handler,
     101  proc_ptr   *old_handler
     102)
     103{
     104    *old_handler = _ISR_Vector_table[vector];
     105
     106    _ISR_Vector_table[vector] = new_handler;
     107}
    37108
    38109/*  _CPU_Initialize
     
    52123{
    53124    register unsigned8  *fp_context;
    54     unsigned32 iva;
    55     unsigned32 iva_table;
    56125    int i;
    57 
    58     extern void IVA_Table(void);
     126    proc_ptr   old_handler;
    59127
    60128    /*
     
    74142
    75143    /*
    76      * Init the first level interrupt handlers
    77      */
    78 
    79     for (i=0; i <= HPPA_INTERNAL_INTERRUPTS; i++)
    80         HPPA_first_level_interrupt_handler[i] = (unsigned32) _Generic_ISR_Handler;
    81 
    82     /*
    83144     * Init the 2nd level interrupt handlers
    84145     */
    85146
    86     for (i=0; i <= CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
    87         _ISR_Vector_table[i] = (ISR_Handler_entry) hppa_cpu_halt;
    88 
    89     /*
    90      * Stabilize the interrupt stuff
    91      */
    92 
    93     (void) hppa_external_interrupt_initialize();
    94 
    95     /*
    96      * Set the IVA to point to physical address of the IVA_Table
    97      */
    98 
    99     iva_table = (unsigned32) IVA_Table;
    100 #if defined(hppa1_1)
    101     /*
    102      * HACK:  (from PA72000 TRM, page 4-19)
    103      * "The hardware TLB miss handler will never attempt to service
    104      *  a non-access TLB miss or a TLB protection violation.  It
    105      *  will only attempt to service TLB accesses that would cause
    106      *  Trap Numbers 6 (Instruction TLB miss) and 15 (Data TLB miss)."
    107      *
    108      * The LPA instruction is used to translate a virtual address to
    109      * a physical address, however, if the requested virtual address
    110      * is not currently resident in the TLB, the hardware TLB miss
    111      * handler will NOT insert it.  In this situation Trap Number
    112      * #17 is invoked (Non-access Data TLB miss fault).
    113      *
    114      * To work around this, a dummy data access is first performed
    115      * to the virtual address prior to the LPA.  The dummy access
    116      * causes the TLB entry to be inserted (if not already present)
    117      * and then the following LPA instruction will not generate
    118      * a non-access data TLB miss fault.
    119      *
    120      * It is unclear whether or not this behaves the same way for
    121      * the PA8000.
    122      *
    123      */
    124     iva = *(volatile unsigned32 *)iva_table;  /* dummy access */
    125 #endif
    126 
    127     HPPA_ASM_LPA(0, iva_table, iva);
    128     set_iva(iva);
     147    for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
     148        _CPU_ISR_install_vector(i,
     149                                hppa_interrupt_report_spurious,
     150                                &old_handler);
    129151
    130152    _CPU_Table = *cpu_table;
     153   
    131154}
    132155
    133 /*PAGE
    134  *
    135  *  _CPU_ISR_Get_level
    136  */
    137  
    138 unsigned32 _CPU_ISR_Get_level(void)
    139 {
    140     int level;
    141     HPPA_ASM_SSM(0, level);     /* change no bits; just get copy */
    142     if (level & HPPA_PSW_I)
    143         return 0;
    144     return 1;
    145 }
    146 
    147 /*PAGE
    148  *
    149  *  _CPU_ISR_install_raw_handler
    150  */
    151  
    152 void _CPU_ISR_install_raw_handler(
    153   unsigned32  vector,
    154   proc_ptr    new_handler,
    155   proc_ptr   *old_handler
    156 )
    157 {
    158   /*
    159    *  This is unsupported.
    160    */
    161 
    162   _CPU_Fatal_halt( 0xdeaddead );
    163 }
    164 
    165 /*PAGE
    166  *
    167  *  _CPU_ISR_install_vector
    168  *
    169  *  This kernel routine installs the RTEMS handler for the
    170  *  specified vector.
    171  *
    172  *  Input parameters:
    173  *    vector      - interrupt vector number
    174  *    old_handler - former ISR for this vector number
    175  *    new_handler - replacement ISR for this vector number
    176  *
    177  *  Output parameters:  NONE
    178  *
    179  */
    180 
    181 /*
    182  * HPPA has 8w for each vector instead of an address to jump to.
    183  * We put the actual ISR address in '_ISR_vector_table'.  This will
    184  * be pulled by the code in the vector.
    185  */
    186 
    187 void _CPU_ISR_install_vector(
    188   unsigned32  vector,
    189   proc_ptr    new_handler,
    190   proc_ptr   *old_handler
    191 )
    192 {
    193     *old_handler = _ISR_Vector_table[vector];
    194 
    195     _ISR_Vector_table[vector] = new_handler;
    196 
    197     if (vector >= HPPA_INTERRUPT_EXTERNAL_BASE)
    198     {
    199         unsigned32 external_vector;
    200 
    201         external_vector = vector - HPPA_INTERRUPT_EXTERNAL_BASE;
    202         if (new_handler)
    203             hppa_external_interrupt_enable(external_vector);
    204         else
    205             /* XXX this can never happen due to _ISR_Is_valid_user_handler */
    206             hppa_external_interrupt_disable(external_vector);
    207     }
    208 }
    209 
    210 
    211 /*
    212  * Support for external and spurious interrupts on HPPA
    213  *
    214  *  TODO:
    215  *    Count interrupts
    216  *    make sure interrupts disabled properly
    217  */
    218 
    219 #define DISMISS(mask)           set_eirr(mask)
    220 #define DISABLE(mask)           set_eiem(get_eiem() & ~(mask))
    221 #define ENABLE(mask)            set_eiem(get_eiem() | (mask))
    222 #define VECTOR_TO_MASK(v)       (1 << (31 - (v)))
    223 
    224 /*
    225  * Init the external interrupt scheme
    226  * called by bsp_start()
    227  */
    228 
    229 void
    230 hppa_external_interrupt_initialize(void)
    231 {
    232     proc_ptr ignore;
    233 
    234     /* mark them all unused */
    235     DISABLE(~0);
    236     DISMISS(~0);
    237 
    238     /* install the external interrupt handler */
    239     _CPU_ISR_install_vector(
    240         HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
    241         (proc_ptr)hppa_external_interrupt, &ignore
    242 );
    243 }
    244 
    245 /*
    246  * Enable a specific external interrupt
    247  */
    248 
    249 void
    250 hppa_external_interrupt_enable(unsigned32 v)
    251 {
    252     unsigned32 isrlevel;
    253 
    254     _CPU_ISR_Disable(isrlevel);
    255     ENABLE(VECTOR_TO_MASK(v));
    256     _CPU_ISR_Enable(isrlevel);
    257 }
    258 
    259 /*
    260  * Does not clear or otherwise affect any pending requests
    261  */
    262 
    263 void
    264 hppa_external_interrupt_disable(unsigned32 v)
    265 {
    266     unsigned32 isrlevel;
    267 
    268     _CPU_ISR_Disable(isrlevel);
    269     DISABLE(VECTOR_TO_MASK(v));
    270     _CPU_ISR_Enable(isrlevel);
    271 }
    272 
    273 void
    274 hppa_external_interrupt_spurious_handler(unsigned32           vector,
    275                                          CPU_Interrupt_frame *iframe)
    276 {
    277 /* XXX should not be printing :)
    278     printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
    279        vector, iframe->Interrupt.pcoqfront);
    280 */
    281 }
    282 
    283 void
    284 hppa_external_interrupt_report_spurious(unsigned32           spurious_mask,
    285                                         CPU_Interrupt_frame *iframe)
    286 {
    287     int v;
    288     for (v=0; v < HPPA_EXTERNAL_INTERRUPTS; v++)
    289         if (VECTOR_TO_MASK(v) & spurious_mask)
    290         {
    291             DISMISS(VECTOR_TO_MASK(v));
    292             DISABLE(VECTOR_TO_MASK(v));
    293             hppa_external_interrupt_spurious_handler(v, iframe);
    294         }
    295     DISMISS(spurious_mask);
    296 }
    297 
    298 
    299 /*
    300  * External interrupt handler.
    301  * This is installed as cpu interrupt handler for
    302  * HPPA_INTERRUPT_EXTERNAL_INTERRUPT. It vectors out to
    303  * specific external interrupt handlers.
    304  */
    305 
    306 void
    307 hppa_external_interrupt(unsigned32           vector,
    308                         CPU_Interrupt_frame *iframe)
    309 {
    310     unsigned32   mask;
    311     unsigned32  *vp, *max_vp;
    312     unsigned32   external_vector;
    313     unsigned32   global_vector;
    314     hppa_rtems_isr_entry handler;
    315 
    316     max_vp = &_CPU_Table.external_interrupt[_CPU_Table.external_interrupts];
    317     while ( (mask = (get_eirr() & get_eiem())) )
    318     {
    319         for (vp = _CPU_Table.external_interrupt; (vp < max_vp) && mask; vp++)
    320         {
    321             unsigned32 m;
    322 
    323             external_vector = *vp;
    324             global_vector = external_vector + HPPA_INTERRUPT_EXTERNAL_BASE;
    325             m = VECTOR_TO_MASK(external_vector);
    326             handler = (hppa_rtems_isr_entry) _ISR_Vector_table[global_vector];
    327             if ((m & mask) && handler)
    328             {
    329                 DISMISS(m);
    330                 mask &= ~m;
    331                 handler(global_vector, iframe);
    332             }
    333         }
    334 
    335         if (mask != 0) {
    336             if ( _CPU_Table.spurious_handler )
    337             {
    338                 handler = (hppa_rtems_isr_entry) _CPU_Table.spurious_handler;
    339                 handler(mask, iframe);
    340             }
    341             else
    342                 hppa_external_interrupt_report_spurious(mask, iframe);
    343         }
    344     }
    345 }
    346156
    347157/*
     
    352162 * Later on, this will allow us to return to the prom.
    353163 * For now, we just ignore 'type_of_halt'
     164 *
     165 * XXX
     166 * NOTE: for gcc, this function must be at the bottom
     167 * of the file, that is because if it is at the top
     168 * of the file, gcc will inline it's calls.  Since
     169 * the function uses the HPPA_ASM_LABEL() macro, when
     170 * gcc inlines it, you get two definitions of the same
     171 * label name, which is an assembly error.
    354172 */
     173
    355174
    356175void
     
    361180    _CPU_ISR_Disable(isrlevel);
    362181
     182    /*
     183     * XXXXX NOTE: This label is only needed that that when
     184     * the simulator stops, it shows the label name specified
     185     */
    363186    HPPA_ASM_LABEL("_hppa_cpu_halt");
    364     HPPA_ASM_BREAK(1, 0);
     187    HPPA_ASM_BREAK(0, 0);
    365188}
     189
Note: See TracChangeset for help on using the changeset viewer.