source: rtems/c/src/lib/libbsp/mips/shared/irq/exception.S @ 5a0b7914

4.115
Last change on this file since 5a0b7914 was 5a0b7914, checked in by Joel Sherrill <joel.sherrill@…>, on 06/29/10 at 00:38:20

2010-06-28 Joel Sherrill <joel.sherrill@…>

PR 1573/cpukit

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