source: rtems/c/src/lib/libbsp/mips/shared/irq/exception.S @ 1973a2a6

4.11
Last change on this file since 1973a2a6 was 1973a2a6, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 30, 2010 at 6:51:12 PM

2010-07-30 Gedare Bloom <giddyup44@…>

PR 1599/cpukit

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