gonzui


Format: Advanced Search

mtkernel_3/kernel/sysdepend/cpu/core/armv7a/exc_entry.Sbare sourcepermlink (0.01 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    micro T-Kernel 3.00.05
    4:  *
    5:  *    Copyright (C) 2006-2020 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2021/11.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: #include <sys/machine.h>
   15: #ifdef CPU_CORE_ARMV7A
   16: 
   17: /*
   18:  *      exc_entry.S  (ARMv7-A)
   19:  *      Exception entry routine
   20:  */
   21: 
   22: #define _in_asm_source_
   23: #include <sys/knldef.h>
   24: #include "offset.h"
   25: 
   26: /* GIC Register definition */
   27: #define GIC_ICC_BASE    0xE8222000
   28: #define GIC_ICC_IAR     0x000C              // Interrupt Acknowledge Register
   29: #define GIC_ICC_EOIR    0x0010             // End of Interrupt Register
   30: 
   31:         .section    EXC_ENTRY, "ax"
   32:         .arm   
   33: 
   34: /* ---------------------------------------------------------------------------------
   35:  *      IRQ exception
   36:  */
   37:         .global Csym(irq_entry)
   38:         .extern Csym(knl_intvec_tbl)
   39:         .extern Csym(Default_Handler)
   40:         
   41: Csym(irq_entry):
   42:         sub    lr, lr, #4                 // Return address adjustment
   43:         srsdb  sp!, #PSR_SVC                    // Save SPSR_irq & R14_irq to SVC stack
   44:         CPS    #PSR_SVC                   // Change to SVC mode
   45:         stmfd  sp!, {r0-r3, ip, lr}             // Save R0-R3,R12,LR to SVC stack
   46: 
   47:         /* Stack image by exception handling
   48:         *                +---------------+
   49:         *       SP_svc ->|R0             |
   50:         *                |R1             |
   51:         *                |R2             |
   52:         *                |R3             |
   53:         *                |R12(ip)        |
   54:         *                |R14_svc(lr)    |
   55:         *                |R14_irq(lr)    | <- return address from interrupt
   56:         *                |SPSR_irq       |
   57:         *                +---------------+
   58:         */
   59: 
   60:         ldr    lr, =GIC_ICC_BASE
   61:         ldr    r3, [lr, #GIC_ICC_IAR]             // Read interrupt response register
   62:         mov    r3, r3, lsl #22
   63:         mov    r3, r3, lsr #22                    // r3 <- Interrupt ID (& 0x3ff)
   64: 
   65:         ldr    r0, =N_INTVEC
   66:         cmp    r3, r0                             // Is the interrupt number correct?
   67:         bge    l_irq1                             //       NO => Jump
   68: 
   69:         mov    r0, r3
   70:         ldr    lr,  =Csym(knl_intvec_tbl)
   71:         add    lr, r3, lsl #2
   72:         ldr    lr, [lr]                   // lr <- Interrupt handler address
   73:         cmp    lr, #0                             // Is an interrupt handler registered?
   74:         bxne   lr                                //  YES => jump    r0: Interrupt ID
   75:         b      l_irq2                               // NO  => default_entry
   76: 
   77: l_irq1: // Interrupt ID is an abnormal value
   78:         ldr     r0, =0x3ff
   79:         cmp     r3, r0                         // If Interrupt ID is 0x3ff,
   80:         beq     l_irq3                         //   it is a false positive and returns.
   81: 
   82: l_irq2: // Call the default handler
   83:         ldr    lr, =GIC_ICC_BASE
   84:         str    r3, [lr, #GIC_ICC_EOIR]            // Writing the interrupt end register
   85: 
   86:         ldr    lr, =Csym(Default_Handler)
   87:         bx     lr
   88: 
   89: l_irq3: // Return without doing anything.
   90:         ldmfd  sp!, {r0-r3, ip, lr}             // restore registers
   91:         rfefd  sp!                              // restore SPSR_irq, R14_irq (return from exception)
   92: 
   93: 
   94: /* ---------------------------------------------------------------------------------
   95:  *      Supervisor call (SVC)
   96:  */
   97:         .global Csym(svc_entry)
   98:         .extern Csym(knl_svcvec_tbl)
   99:         .extern Csym(SVC_default_Handler)
  100: Csym(svc_entry):
  101:         srsdb  sp!, #PSR_SVC                    // Save SPSR_svc and R14_svc on SVC stack.
  102:         stmfd  sp!, {r0-r3, ip, lr}             // Save R0-R3,R12,LR on SVC stack.
  103:         mov    r0, #0xffffffff
  104:         str    r0, [sp, #(5 * 4)]         // Change the value of LR on the stack.
  105: 
  106:         /*
  107:         * Stack image
  108:         *          +---------------+
  109:         * SP_svc ->|R0             |
  110:         *          |R1             |
  111:         *          |R2             |
  112:         *          |R3             |
  113:         *          |R12(ip)        |
  114:         *          |0xffffffff     |
  115:         *          |R14_svc(lr)    | <- return address from exception
  116:         *          |SPSR_svc       |
  117:         *          +---------------+
  118:         */
  119: 
  120:         mrs    r0, spsr
  121:         tst    r0, #PSR_T
  122:         ldrneh r0, [lr, #-2]           // Thumb instruction
  123:         ldreq  r0, [lr, #-4]            // ARM instruction
  124:         bicne  r0, r0, #0xff00
  125:         biceq   r0, r0, #0xff000000
  126:         // r0 = SVC No.
  127: 
  128:         cmp    r0, #N_SVCHDR
  129:         bge    SVC_default_Handler        // SVC No. >= N_SVC  => SVC default_entry
  130: 
  131:         ldr    lr, =knl_svcvec_tbl
  132:         add    lr, r0, lsl #2
  133:         ldr    lr, [lr]           // lr: SVC handler address
  134:         cmp    lr, #0                     // Registered?
  135:         bxne   lr                        //   YES -> jump    r0: SVC No.
  136:         b      SVC_default_Handler          //   NO  -> SVC default_entry
  137: 
  138: 
  139: /* ---------------------------------------------------------------------------------
  140:  *      FIQ exception
  141:  */
  142:         .global Csym(fiq_entry)
  143:         .extern Csym(FIQ_Handler)
  144: Csym(fiq_entry):
  145:         sub    lr, lr, #4         // Return address adjustment
  146:         ldr    sp, =__fiq_stack_start     // Switch to exception stack
  147:         stmfd  sp!, {r0-r3, ip, lr}     // Save R0-R3,R12,LR to FIQ stack
  148: 
  149:         /* Stack image
  150:         *          +---------------+
  151:         * SP_fiq ->|R0             |
  152:         *          |R1             |
  153:         *          |R2             |
  154:         *          |R3             |
  155:         *          |R12(ip)        |
  156:         *          |R14_fiq(lr)    | <- return address from exception
  157:         *          +---------------+
  158:         */
  159: 
  160:         ldr    lr, =Csym(FIQ_Handler)
  161:         bx     lr
  162: 
  163: /* ---------------------------------------------------------------------------------
  164:  *      Undefined instruction exception
  165:  */
  166:         .global Csym(undef_entry)
  167:         .extern Csym(UndefinedInst_Handler)
  168:         .extern Csym(VFPInvalid_Handler)
  169: 
  170: Csym(undef_entry):
  171:         sub    lr, lr, #4         // Return address adjustment
  172:         ldr    sp, =__und_stack_start     // Switch to exception stack
  173:         stmfd  sp!, {r0-r3, ip, lr}     // Save R0-R3,R12,LR to UDF stack
  174: 
  175:         /* Stack image
  176:         *          +---------------+
  177:         * SP_udf ->|R0             |
  178:         *          |R1             |
  179:         *          |R2             |
  180:         *          |R3             |
  181:         *          |R12(ip)        |
  182:         *          |R14_und(lr)    | <- return address from exception
  183:         *          +---------------+
  184:         */
  185: 
  186: #if USE_FPU
  187: 
  188: #define TA_FPU  0x00001000               // TA_FPU = TA_COP0 = 0x00001000
  189: 
  190:         mrc    p15, 0, ip, c1, c0, 2      // CPACR
  191:         tst    ip, #5 << 20               // CP10,11 available ?
  192:         beq    exe_undhdr         //  no -> jump 
  193:         fmrx   ip, fpexc
  194:         tst    ip, #0x40000000            // fpexc.en ?
  195:         bne    exe_undhdr         //  no -> jump 
  196: 
  197:         /* After that, processing for FPU instructions */
  198:         ldr    ip, =Csym(knl_ctxtsk)
  199:         ldr    r0, [ip]           // r0 = ctxtsk
  200:         cmp    r0, #0                     // if ctxtsk == NULL  -> invalid use of VFP
  201:         beq    exe_undhdr
  202: 
  203:         ldr    ip, [r0, #TCB_tskatr]      
  204:         tst    ip, #TA_FPU                // if no TA_FPU attribute  ->  invalid use of VFP
  205:         beq    exe_undhdr
  206: 
  207:         ldr    ip, =Csym(knl_taskindp)
  208:         ldr    r2, [ip]           // r2 = knl_taskindp
  209:         cmp    r2, #0                     // if knl_taskindp > 0  ->  invalid use of VFP
  210:         bhi    exe_undhdr
  211: 
  212:         /* enable VFP */
  213:         fmrx   ip, fpexc
  214:         orr    ip, ip, #0x40000000        // FPEXC.EN = 1
  215:         fmxr   fpexc, ip
  216: 
  217:         ldr    r2, =Csym(knl_fpu_ctx)     // r2 = &knl_fpu_ctx
  218:         ldr    r1, [r2]           // r1 = knl_fpu_ctx
  219:         cmp    r1, r0                     // if knl_fpu_ctx == ctxtsk  -> context switching is not required.
  220:         beq    rtn_undef
  221: 
  222:         cmp    r1, #0                     // if knl_fpu_ctx == NULL  -> context saving is not required.
  223:         beq    load_fpuctx
  224: 
  225:         /* save VFP context */
  226:         fmrx   lr, fpscr         // Floating-Point Status and Control Register
  227:         ldr    ip, [r1, #TCB_isstack]     // r1 = TCB.isstack
  228:         sub    ip, ip, #FPU_context       // IP = FPU context
  229: 
  230:         stmia  ip!, {r0, lr}            // (r0 is padding)
  231:         fstmiad        ip!, {d0-d15}
  232:         fstmiad        ip!, {d16-d31}
  233: 
  234:         /* load VFP context */
  235: load_fpuctx:
  236:         ldr    ip, [r0, #TCB_isstack]     // r0 = ctxtsk
  237:         sub    ip, ip, #FPU_context       // IP = FPU context
  238: 
  239:         ldmia  ip!, {r1, lr}            // (r1 is padding)
  240:         fldmiad        ip!, {d0-d15}
  241:         fldmiad        ip!, {d16-d31}
  242:         fmxr   fpscr, lr         // Floating-Point Status and Control Register
  243: 
  244:         str    r0, [r2]           // knl_fpu_ctx = ctxtsk
  245: 
  246: rtn_undef:
  247:         ldmfd  sp!, {r0-r3, ip, lr}     // restore registers
  248:         movs   pc,lr                     // return from exception
  249: 
  250: exe_undhdr:
  251: #endif /* USE_FPU */
  252:         ldr    lr, =Csym(UndefinedInst_Handler)
  253:         bx     lr
  254: 
  255: /* ---------------------------------------------------------------------------------
  256:  *      Prefetch abort exception
  257:  */
  258:         .global Csym(iabort_entry)
  259:         .extern Csym(PrefetchAbort_Handler)
  260: 
  261: Csym(iabort_entry):
  262:         sub    lr, lr, #4         // Return address adjustment
  263:         ldr    sp, =__abt_stack_start     // Switch to exception stack
  264:         stmfd  sp!, {r0-r3, ip, lr}     // Save R0-R3,R12,LR to ABT stack
  265: 
  266:         /* Stack image
  267:         *          +---------------+
  268:         * SP_abt ->|R0             |
  269:         *          |R1             |
  270:         *          |R2             |
  271:         *          |R3             |
  272:         *          |R12(ip)        |
  273:         *          |R14_abt(lr)    | <- return address from exception
  274:         *          +---------------+
  275:         */
  276: 
  277:         ldr    lr, =Csym(PrefetchAbort_Handler)
  278:         bx     lr
  279: 
  280: /* ---------------------------------------------------------------------------------
  281:  *      Data abort exception
  282:  */
  283:         .global Csym(dabort_entry)
  284:         .extern Csym(DataAbort_Handler)
  285: 
  286: Csym(dabort_entry):
  287:         sub    lr, lr, #4         // Return address adjustment
  288:         ldr    sp, =__abt_stack_start     // Switch to exception stack
  289:         stmfd  sp!, {r0-r3, ip, lr}     // Save R0-R3,R12,LR to ABT stack
  290: 
  291:         /* Stack image
  292:         *          +---------------+
  293:         * SP_abt ->|R0             |
  294:         *          |R1             |
  295:         *          |R2             |
  296:         *          |R3             |
  297:         *          |R12(ip)        |
  298:         *          |R14_abt(lr)    | <- return address from exception
  299:         *          +---------------+
  300:         */
  301: 
  302:         ldr    lr, =Csym(DataAbort_Handler)
  303:         bx     lr
  304: 
  305: /* ---------------------------------------------------------------------------------
  306:  *      Exception Stack Area 
  307:  */
  308:         .section       .fiq_stack_section, "aw", %nobits
  309:         .global        __fiq_stack
  310: __fiq_stack:
  311:         .space FIQ_STACK_SIZE
  312: 
  313:         .section       .und_stack_section, "aw", %nobits
  314:         .global        __und_stack
  315: __und_stack:
  316:         .space UND_STACK_SIZE
  317: 
  318:         .section       .abt_stack_section, "aw", %nobits
  319:         .global        __abt_stack
  320: __abt_stack:
  321:         .space ABT_STACK_SIZE
  322: 
  323: 
  324: #endif  /* CPU_CORE_ARMV7A */