source: rtems/bsps/mips/shared/irq/exception.S @ 4fea054c

5
Last change on this file since 4fea054c was 4fea054c, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/18 at 18:34:15

score: Remove _ISR_Dispatch()

This function was only used on some m68k variants. On these m68k
variants there is no need to use a global symbol. Use a local label
instead.

Remove _ISR_Dispatch() from the architecture-independent layer.

  • Property mode set to 100644
File size: 15.0 KB
Line 
1/*
2 *  This file contains a customized MIPS exception handler.
3 *  It hooks into the exception handler present in the resident
4 *  PMON debug monitor.
5 */
6
7/*
8 *  Author: Bruce Robinson
9 *
10 *  This code was derived from cpu_asm.S with the following copyright:
11 *
12 *  COPYRIGHT (c) 1996 by Transition Networks Inc.
13 *
14 *  To anyone who acknowledges that this file is provided "AS IS"
15 *  without any express or implied warranty:
16 *      permission to use, copy, modify, and distribute this file
17 *      for any purpose is hereby granted without fee, provided that
18 *      the above copyright notice and this notice appears in all
19 *      copies, and that the name of Transition Networks not be used in
20 *      advertising or publicity pertaining to distribution of the
21 *      software without specific, written prior permission.
22 *      Transition Networks makes no representations about the suitability
23 *      of this software for any purpose.
24 *
25 *  Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s:
26 *
27 *  COPYRIGHT (c) 1989-2010.
28 *  On-Line Applications Research Corporation (OAR).
29 *
30 *  The license and distribution terms for this file may be
31 *  found in the file LICENSE in this distribution or at
32 *  http://www.rtems.org/license/LICENSE.
33 */
34
35#include <bspopts.h>
36#include <rtems/asm.h>
37#include <rtems/score/percpu.h>
38#include <rtems/mips/iregdef.h>
39#include <rtems/mips/idtcpu.h>
40#if BSP_HAS_USC320
41  #include <usc.h>
42#endif
43
44#if __mips == 3
45/* 64 bit register operations */
46#define NOP     nop
47#define ADD     dadd
48#define STREG   sd
49#define LDREG   ld
50#define ADDU    addu
51#define ADDIU   addiu
52#define STREGC1 sdc1
53#define LDREGC1 ldc1
54#define R_SZ    8
55#define F_SZ    8
56#define SZ_INT  8
57#define SZ_INT_POW2 3
58
59/* XXX if we don't always want 64 bit register ops, then another ifdef */
60
61#elif __mips == 1
62/* 32 bit register operations*/
63#define NOP     nop
64#define ADD     add
65#define STREG   sw
66#define LDREG   lw
67#define ADDU    add
68#define ADDIU   addi
69#define STREGC1 swc1
70#define LDREGC1 lwc1
71#define R_SZ    4
72#define F_SZ    4
73#define SZ_INT  4
74#define SZ_INT_POW2 2
75#else
76#error "mips assembly: what size registers do I deal with?"
77#endif
78
79
80#define ISR_VEC_SIZE    4
81#define EXCP_STACK_SIZE (NREGS*R_SZ)
82
83.extern _Thread_Dispatch
84
85/*  void __ISR_Handler()
86 *
87 *  This routine provides the RTEMS interrupt management.
88 *
89 */
90
91#if 0
92void _ISR_Handler()
93{
94   /*
95    *  This discussion ignores a lot of the ugly details in a real
96    *  implementation such as saving enough registers/state to be
97    *  able to do something real.  Keep in mind that the goal is
98    *  to invoke a user's ISR handler which is written in C and
99    *  uses a certain set of registers.
100    *
101    *  Also note that the exact order is to a large extent flexible.
102    *  Hardware will dictate a sequence for a certain subset of
103    *  _ISR_Handler while requirements for setting
104    */
105
106  /*
107   *  At entry to "common" _ISR_Handler, the vector number must be
108   *  available.  On some CPUs the hardware puts either the vector
109   *  number or the offset into the vector table for this ISR in a
110   *  known place.  If the hardware does not give us this information,
111   *  then the assembly portion of RTEMS for this port will contain
112   *  a set of distinct interrupt entry points which somehow place
113   *  the vector number in a known place (which is safe if another
114   *  interrupt nests this one) and branches to _ISR_Handler.
115   *
116   */
117#endif
118FRAME(bsp_ISR_Handler,sp,0,ra)
119        .set noreorder
120
121#if 0
122/* Activate TX49xx PIO19 signal for diagnostics */
123        lui     k0,0xff1f
124        ori     k0,k0,0xf500
125        lw      k0,(k0)
126        lui     k1,0x8
127        or      k1,k1,k0
128        lui     k0,0xff1f
129        ori     k0,k0,0xf500
130        sw      k1,(k0)
131#endif
132        mfc0 k0,C0_CAUSE        /* Determine if an interrupt generated this exception */
133        nop
134        and k1,k0,CAUSE_EXCMASK
135        beq k1,zero,_chk_int    /* If so, branch to service here */
136        nop
137        la  k0,_int_esr_link    /* Otherwise, jump to next exception handler in PMON exception chain */
138        lw  k0,(k0)
139        lw  k0,4(k0)
140        j   k0
141        nop
142_chk_int:
143        mfc0 k1,C0_SR
144        nop
145        and k0,k1
146#if HAS_RM52xx
147        and k0,CAUSE_IPMASK
148#elif HAS_TX49xx
149        and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3)
150#endif
151        /* external interrupt not enabled, ignore */
152        beq k0,zero,_ISR_Handler_quick_exit
153        nop
154
155/* For debugging interrupts, clear EXL to allow breakpoints */
156#if 0
157        MFC0    k0, C0_SR
158#if __mips == 3
159        li      k1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
160        not     k1
161        and     k0,k1
162        li      k1,SR_IE
163#elif __mips == 1
164        li      k1,SR_IEC
165#endif
166        or      k0, k1
167        mtc0    k0, C0_SR
168        NOP
169#endif
170
171
172  /*
173   *  save some or all context on stack
174   *  may need to save some special interrupt information for exit
175   */
176
177        /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
178
179        /* wastes a lot of stack space for context?? */
180        ADDIU    sp,sp,-EXCP_STACK_SIZE
181
182        STREG ra, R_RA*R_SZ(sp)  /* store ra on the stack */
183        STREG v0, R_V0*R_SZ(sp)
184        STREG v1, R_V1*R_SZ(sp)
185        STREG a0, R_A0*R_SZ(sp)
186        STREG a1, R_A1*R_SZ(sp)
187        STREG a2, R_A2*R_SZ(sp)
188        STREG a3, R_A3*R_SZ(sp)
189        STREG t0, R_T0*R_SZ(sp)
190        STREG t1, R_T1*R_SZ(sp)
191        STREG t2, R_T2*R_SZ(sp)
192        STREG t3, R_T3*R_SZ(sp)
193        STREG t4, R_T4*R_SZ(sp)
194        STREG t5, R_T5*R_SZ(sp)
195        STREG t6, R_T6*R_SZ(sp)
196        STREG t7, R_T7*R_SZ(sp)
197        mflo  t0
198        STREG t8, R_T8*R_SZ(sp)
199        STREG t0, R_MDLO*R_SZ(sp)
200        STREG t9, R_T9*R_SZ(sp)
201        mfhi  t0
202        STREG gp, R_GP*R_SZ(sp)
203        STREG t0, R_MDHI*R_SZ(sp)
204        STREG fp, R_FP*R_SZ(sp)
205
206        .set noat
207        STREG AT, R_AT*R_SZ(sp)
208        .set at
209
210        mfc0     t0,C0_SR
211        dmfc0    t1,C0_EPC
212        STREG    t0,R_SR*R_SZ(sp)
213        STREG    t1,R_EPC*R_SZ(sp)
214
215  /*
216   *
217   *  if ( _ISR_Nest_level == 0 )
218   *    switch to software interrupt stack
219   */
220
221  /*
222   *  _ISR_Nest_level++;
223   */
224        lw      t0,ISR_NEST_LEVEL
225        NOP
226        add     t0,t0,1
227        sw      t0,ISR_NEST_LEVEL
228  /*
229   *  _Thread_Dispatch_disable_level++;
230   */
231        lw      t1,THREAD_DISPATCH_DISABLE_LEVEL
232        NOP
233        add     t1,t1,1
234        sw      t1,THREAD_DISPATCH_DISABLE_LEVEL
235
236        /* DEBUG - Add the following code to disable interrupts and clear
237         *         EXL in status register, this will allow memory
238         *         exceptions to occur while servicing the current interrupt
239         */
240#if 0
241        /* Disable interrupts from internal interrupt controller */
242        li t0,~CAUSE_IP2_MASK
243        mfc0 t1,C0_SR
244        nop
245        and t1,t0
246        mtc0 t1,C0_SR
247        nop
248        /* Clear EXL in status register to allow memory exceptions to occur */
249        li t0,~SR_EXL
250        mfc0 t1,C0_SR
251        nop
252        and t1,t0
253        mtc0 t1,C0_SR
254        nop
255#endif
256
257  /*
258   *  Call the CPU model or BSP specific routine to decode the
259   *  interrupt source and actually vector to device ISR handlers.
260   */
261        move     a0,sp
262        jal      mips_vector_isr_handlers
263        NOP
264
265        /* Add the following code to disable interrupts (see DEBUG above) */
266#if 0
267        li t0,SR_EXL            /* Set EXL to hold off interrupts */
268        mfc0 t1,C0_SR
269        nop
270        or t1,t0
271        mtc0 t1,C0_SR
272        nop
273        /* Enable interrupts from internal interrupt controller */
274        li t0,CAUSE_IP2_MASK
275        mfc0 t1,C0_SR
276        nop
277        or t1,t0
278        mtc0 t1,C0_SR
279        nop
280#endif
281
282_ISR_Handler_cleanup:
283
284  /*
285   *  --_ISR_Nest_level;
286   */
287        lw      t2,ISR_NEST_LEVEL
288        NOP
289        add     t2,t2,-1
290        sw      t2,ISR_NEST_LEVEL
291  /*
292   *  --_Thread_Dispatch_disable_level;
293   */
294        lw      t1,THREAD_DISPATCH_DISABLE_LEVEL
295        NOP
296        add     t1,t1,-1
297        sw      t1,THREAD_DISPATCH_DISABLE_LEVEL
298  /*
299   *  if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
300   *    goto the label "exit interrupt (simple case)"
301   */
302        or  t0,t2,t1
303        bne t0,zero,_ISR_Handler_exit
304        NOP
305
306
307  /*
308   *  restore stack
309   *
310   *  if ( !_Thread_Dispatch_necessary )
311   *    goto the label "exit interrupt (simple case)"
312   */
313        lb      t0,DISPATCH_NEEDED
314        NOP
315        or      t0,t0,t0
316        beq     t0,zero,_ISR_Handler_exit
317        NOP
318
319/*
320** Turn on interrupts before entering Thread_Dispatch which
321** will run for a while, thus allowing new interrupts to
322** be serviced.  Observe the Thread_Dispatch_disable_level interlock
323** that prevents recursive entry into Thread_Dispatch.
324*/
325
326        mfc0    t0, C0_SR
327#if __mips == 3
328        li      t1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
329        not     t1
330        and     t0,t1
331        li      t1,SR_IE
332#elif __mips == 1
333        li      t1,SR_IEC
334#endif
335        or      t0, t1
336        mtc0    t0, C0_SR
337        NOP
338
339        /* save off our stack frame so the context switcher can get to it */
340        la      t0,__exceptionStackFrame
341        STREG   sp,(t0)
342
343        jal     _Thread_Dispatch
344        NOP
345
346        /* and make sure its clear in case we didn't dispatch.  if we did, its
347        ** already cleared */
348        la      t0,__exceptionStackFrame
349        STREG   zero,(t0)
350        NOP
351
352/*
353** turn interrupts back off while we restore context so
354** a badly timed interrupt won't accidentally mess things up
355*/
356        mfc0    t0, C0_SR
357#if __mips == 3
358        li      t1,SR_IE                /* Clear IE first (recommended) */
359        not     t1
360        and     t0,t1
361        mtc0    t0, C0_SR
362        li      t1,SR_EXL | SR_IE       /* Set EXL and IE, this puts status register bits back to interrupted state */
363        or      t0,t1
364#elif __mips == 1
365        /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */
366        li      t1,SR_IEC | SR_KUP | SR_KUC
367        not     t1
368        and     t0, t1
369#endif
370        mtc0    t0, C0_SR
371        NOP
372
373  /*
374   *  prepare to get out of interrupt
375   *  return from interrupt
376   *
377   *  LABEL "exit interrupt (simple case):"
378   *  prepare to get out of interrupt
379   *  return from interrupt
380   */
381
382_ISR_Handler_exit:
383
384/* restore interrupt context from stack */
385        LDREG t8, R_MDLO*R_SZ(sp)
386        LDREG t0, R_T0*R_SZ(sp)
387        mtlo  t8
388        LDREG t8, R_MDHI*R_SZ(sp)
389        LDREG t1, R_T1*R_SZ(sp)
390        mthi  t8
391        LDREG t2, R_T2*R_SZ(sp)
392        LDREG t3, R_T3*R_SZ(sp)
393        LDREG t4, R_T4*R_SZ(sp)
394        LDREG t5, R_T5*R_SZ(sp)
395        LDREG t6, R_T6*R_SZ(sp)
396        LDREG t7, R_T7*R_SZ(sp)
397        LDREG t8, R_T8*R_SZ(sp)
398        LDREG t9, R_T9*R_SZ(sp)
399        LDREG gp, R_GP*R_SZ(sp)
400        LDREG fp, R_FP*R_SZ(sp)
401        LDREG ra, R_RA*R_SZ(sp)
402        LDREG a0, R_A0*R_SZ(sp)
403        LDREG a1, R_A1*R_SZ(sp)
404        LDREG a2, R_A2*R_SZ(sp)
405        LDREG a3, R_A3*R_SZ(sp)
406        LDREG v1, R_V1*R_SZ(sp)
407        LDREG v0, R_V0*R_SZ(sp)
408
409        LDREG k1, R_EPC*R_SZ(sp)
410        mtc0  k1,C0_EPC
411
412        .set noat
413        LDREG     AT, R_AT*R_SZ(sp)
414        .set at
415
416        ADDIU     sp,sp,EXCP_STACK_SIZE
417
418_ISR_Handler_quick_exit:
419        eret
420        nop
421
422
423#if BSP_HAS_USC320
424        /* Interrupts from USC320 are serviced here */
425        .global USC_isr
426        .extern Clock_isr
427USC_isr:
428        /* check if it's a USC320 heartbeat interrupt */
429        la      k0,INT_STAT     /* read INT_STAT register */
430        lw      k0,(k0)
431        nop                     /* reading from external device */
432        sll     k0,(31-21)      /* test bit 21 (HBI) */
433
434        bgez    k0,USC_isr2     /* branch if not a heartbeat interrupt */
435        NOP
436
437        /* clear the heartbeat interrupt */
438        la      k0,INT_STAT
439        li      t0,HBI_MASK
440        sw      t0,(k0)
441        /* wait for interrupt to clear */
442USC_isr1:
443        la      k0,INT_STAT     /* read INT_STAT register */
444        lw      k0,(k0)
445        nop                     /* reading from external device */
446        sll     k0,(31-21)      /* test bit 21 (HBI) */
447        bltz    k0,USC_isr1     /* branch if bit set */
448        nop
449        j       Clock_isr       /* Jump to clock isr */
450        nop
451USC_isr2:
452        j       ra              /* no serviceable interrupt, return without doing anything */
453        nop
454#endif
455
456#if 0
457        .global int7_isr
458        .extern Interrupt_7_isr
459int7_isr:
460        /* Verify interrupt is from Timer */
461        la      k0,IRCS         /* read Interrupt Current Status register */
462        lw      k0,(k0)
463        nop                     /* reading from external device */
464        li      k1,IRCS_CAUSE_MASK
465        and     k0,k0,k1        /* isolate interrupt cause  */
466
467        li      k1,INT7INT      /* test for interrupt 7 */
468        subu    k1,k0,k1
469        beq     k1,zero,int7_isr1
470        nop
471        j       ra              /* interrupt 7 no longer valid, return without doing anything */
472        nop
473int7_isr1:
474        j       Interrupt_7_isr /* Jump to Interrupt 7 isr */
475        nop
476#endif
477
478       .set    reorder
479
480ENDFRAME(bsp_ISR_Handler)
481
482
483FRAME(_BRK_Handler,sp,0,ra)
484        .set noreorder
485
486#if BSP_HAS_USC320
487        la      k0,INT_CFG3     /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */
488        lw      k1,(k0)
489        li      k0,~HBI_MASK
490        and     k1,k1,k0
491        la      k0,INT_CFG3
492        sw      k1,(k0)
493#endif
494
495        la  k0,_brk_esr_link    /* Jump to next exception handler in PMON exception chain */
496        lw  k0,(k0)
497        lw  k0,4(k0)
498        j   k0
499        nop
500
501        .set reorder
502ENDFRAME(_BRK_Handler)
503
504
505/**************************************************************************
506**
507**      init_exc_vecs() - moves the exception code into the addresses
508**                        reserved for exception vectors
509**
510**      UTLB Miss exception vector at address 0x80000000
511**
512**      General exception vector at address 0x80000080
513**
514**      RESET exception vector is at address 0xbfc00000
515**
516***************************************************************************/
517
518FRAME(init_exc_vecs,sp,0,ra)
519        .set noreorder
520
521        .extern mon_onintr
522
523/* Install interrupt handler in PMON exception handling chain */
524
525        addiu   sp,sp,-8
526        sw      ra,(sp)                 /* Save ra contents on stack */
527        move    a0,zero
528        la      a1,_int_esr_link
529        jal     mon_onintr              /* Make PMON system call to install interrupt exception handler */
530        nop
531        li      a0,9
532        la      a1,_brk_esr_link
533        jal     mon_onintr              /* Make PMON system call to install break exception handler */
534        nop
535        lw      ra,(sp)
536        addiu   sp,sp,8                 /* Restore ra contents from stack */
537        j       ra
538        nop
539
540        .set reorder
541ENDFRAME(init_exc_vecs)
542
543
544#if 0           /* Unused code below */
545
546/*************************************************************
547*  enable_int7(ints)
548*       Enable interrupt 7
549*/
550FRAME(enable_int7,sp,0,ra)
551        .set noreorder
552
553        la      t0,IRDM1        # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low)
554        li      t1,0x0
555        sw      t1,(t0)
556
557        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2)
558        li      t1,0x200
559        sw      t1,(t0)
560
561        la      t0,IRMSK        # Set interrupt controller mask
562        li      t1,0x0
563        sw      t1,(t0)
564
565        la      t0,IRDEN        # Enable interrupts from controller
566        li      t1,0x1
567        sw      t1,(t0)
568
569        j       ra
570        nop
571        .set reorder
572ENDFRAME(enable_int7)
573
574/*************************************************************
575*  disable_int7(ints)
576*       Disable interrupt 7
577*/
578FRAME(disable_int7,sp,0,ra)
579        .set noreorder
580
581        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 0 to diasble int 7)
582        li      t1,0x200
583        sw      t1,(t0)
584
585        j       ra
586        nop
587        .set reorder
588ENDFRAME(disable_int7)
589#endif
590
591/*************************************************************
592*  exception:
593*       Diagnostic code that can be hooked to PMON interrupt handler.
594*       Generates pulse on PIO22 pin.
595*       Called from _exception code in PMON (see mips.s of PMON).
596*       Return address is located in k1.
597*/
598FRAME(tx49xxexception,sp,0,ra)
599        .set noreorder
600        la      k0,k1tmp
601        sw      k1,(k0)
602
603/* Activate TX49xx PIO22 signal for diagnostics */
604        lui     k0,0xff1f
605        ori     k0,k0,0xf500
606        lw      k0,(k0)
607        lui     k1,0x40
608        or      k1,k1,k0
609        lui     k0,0xff1f
610        ori     k0,k0,0xf500
611        sw      k1,(k0)
612        nop
613
614/* De-activate TX49xx PIO22 signal for diagnostics */
615        lui     k0,0xff1f
616        ori     k0,k0,0xf500
617        lw      k0,(k0)
618        lui     k1,0x40
619        not     k1
620        and     k1,k1,k0
621        lui     k0,0xff1f
622        ori     k0,k0,0xf500
623        sw      k1,(k0)
624        nop
625
626        la      k0,k1tmp
627        lw      k1,(k0)
628        j       k1
629        .set reorder
630ENDFRAME(tx49xxexception)
631
632
633
634
635        .data
636
637k1tmp:  .word   0       /* Temporary strage for K1 during interrupt service */
638
639/*************************************************************
640*
641* Exception handler links, used in PMON exception handler chains
642*/
643        /* Interrupt exception service routine link */
644        .global _int_esr_link
645_int_esr_link:
646        .word   0
647        .word   bsp_ISR_Handler
648
649        /* Break exception service routine link */
650        .global _brk_esr_link
651_brk_esr_link:
652        .word   0
653        .word   _BRK_Handler
654
655
656
657
Note: See TracBrowser for help on using the repository browser.