Back to home page

LXR

 
 

    


0001 /*
0002  * ARCv2 ISA based core Low Level Intr/Traps/Exceptions(non-TLB) Handling
0003  *
0004  * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License version 2 as
0008  * published by the Free Software Foundation.
0009  */
0010 
0011 #include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */
0012 #include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,TRAP...} */
0013 #include <asm/errno.h>
0014 #include <asm/arcregs.h>
0015 #include <asm/irqflags.h>
0016 
0017     .cpu HS
0018 
0019 #define VECTOR  .word
0020 
0021 ;############################ Vector Table #################################
0022 
0023     .section .vector,"a",@progbits
0024     .align 4
0025 
0026 # Initial 16 slots are Exception Vectors
0027 VECTOR  res_service     ; Reset Vector
0028 VECTOR  mem_service     ; Mem exception
0029 VECTOR  instr_service       ; Instrn Error
0030 VECTOR  EV_MachineCheck     ; Fatal Machine check
0031 VECTOR  EV_TLBMissI     ; Intruction TLB miss
0032 VECTOR  EV_TLBMissD     ; Data TLB miss
0033 VECTOR  EV_TLBProtV     ; Protection Violation
0034 VECTOR  EV_PrivilegeV       ; Privilege Violation
0035 VECTOR  EV_SWI          ; Software Breakpoint
0036 VECTOR  EV_Trap         ; Trap exception
0037 VECTOR  EV_Extension        ; Extn Instruction Exception
0038 VECTOR  EV_DivZero      ; Divide by Zero
0039 VECTOR  EV_DCError      ; Data Cache Error
0040 VECTOR  EV_Misaligned       ; Misaligned Data Access
0041 VECTOR  reserved        ; Reserved slots
0042 VECTOR  reserved        ; Reserved slots
0043 
0044 # Begin Interrupt Vectors
0045 VECTOR  handle_interrupt    ; (16) Timer0
0046 VECTOR  handle_interrupt    ; unused (Timer1)
0047 VECTOR  handle_interrupt    ; unused (WDT)
0048 VECTOR  handle_interrupt    ; (19) Inter core Interrupt (IPI)
0049 VECTOR  handle_interrupt    ; (20) perf Interrupt
0050 VECTOR  handle_interrupt    ; (21) Software Triggered Intr (Self IPI)
0051 VECTOR  handle_interrupt    ; unused
0052 VECTOR  handle_interrupt    ; (23) unused
0053 # End of fixed IRQs
0054 
0055 .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
0056     VECTOR  handle_interrupt
0057 .endr
0058 
0059     .section .text, "ax",@progbits
0060 
0061 reserved:
0062     flag 1      ; Unexpected event, halt
0063 
0064 ;##################### Interrupt Handling ##############################
0065 
0066 ENTRY(handle_interrupt)
0067 
0068     INTERRUPT_PROLOGUE  irq
0069 
0070     # irq control APIs local_irq_save/restore/disable/enable fiddle with
0071     # global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio)
0072     # However a taken interrupt doesn't clear these bits. Thus irqs_disabled()
0073     # query in hard ISR path would return false (since .IE is set) which would
0074     # trips genirq interrupt handling asserts.
0075     #
0076     # So do a "soft" disable of interrutps here.
0077     #
0078     # Note this disable is only for consistent book-keeping as further interrupts
0079     # will be disabled anyways even w/o this. Hardware tracks active interrupts
0080     # seperately in AUX_IRQ_ACTIVE.active and will not take new interrupts
0081     # unless this one returns (or higher prio becomes pending in 2-prio scheme)
0082 
0083     IRQ_DISABLE
0084 
0085     ; icause is banked: one per priority level
0086     ; so a higher prio interrupt taken here won't clobber prev prio icause
0087     lr  r0, [ICAUSE]
0088     mov   blink, ret_from_exception
0089 
0090     b.d  arch_do_IRQ
0091     mov r1, sp
0092 
0093 END(handle_interrupt)
0094 
0095 ;################### Non TLB Exception Handling #############################
0096 
0097 ENTRY(EV_SWI)
0098     flag 1
0099 END(EV_SWI)
0100 
0101 ENTRY(EV_DivZero)
0102     flag 1
0103 END(EV_DivZero)
0104 
0105 ENTRY(EV_DCError)
0106     flag 1
0107 END(EV_DCError)
0108 
0109 ; ---------------------------------------------
0110 ; Memory Error Exception Handler
0111 ;   - Unlike ARCompact, handles Bus errors for both User/Kernel mode,
0112 ;     Instruction fetch or Data access, under a single Exception Vector
0113 ; ---------------------------------------------
0114 
0115 ENTRY(mem_service)
0116 
0117     EXCEPTION_PROLOGUE
0118 
0119     lr  r0, [efa]
0120     mov r1, sp
0121 
0122     FAKE_RET_FROM_EXCPN
0123 
0124     bl  do_memory_error
0125     b   ret_from_exception
0126 END(mem_service)
0127 
0128 ENTRY(EV_Misaligned)
0129 
0130     EXCEPTION_PROLOGUE
0131 
0132     lr  r0, [efa]   ; Faulting Data address
0133     mov r1, sp
0134 
0135     FAKE_RET_FROM_EXCPN
0136 
0137     SAVE_CALLEE_SAVED_USER
0138     mov r2, sp              ; callee_regs
0139 
0140     bl  do_misaligned_access
0141 
0142     ; TBD: optimize - do this only if a callee reg was involved
0143     ; either a dst of emulated LD/ST or src with address-writeback
0144     RESTORE_CALLEE_SAVED_USER
0145 
0146     b   ret_from_exception
0147 END(EV_Misaligned)
0148 
0149 ; ---------------------------------------------
0150 ; Protection Violation Exception Handler
0151 ; ---------------------------------------------
0152 
0153 ENTRY(EV_TLBProtV)
0154 
0155     EXCEPTION_PROLOGUE
0156 
0157     lr  r0, [efa]   ; Faulting Data address
0158     mov r1, sp  ; pt_regs
0159 
0160     FAKE_RET_FROM_EXCPN
0161 
0162     mov blink, ret_from_exception
0163     b   do_page_fault
0164 
0165 END(EV_TLBProtV)
0166 
0167 ; From Linux standpoint Slow Path I/D TLB Miss is same a ProtV as they
0168 ; need to call do_page_fault().
0169 ; ECR in pt_regs provides whether access was R/W/X
0170 
0171 .global        call_do_page_fault
0172 .set call_do_page_fault, EV_TLBProtV
0173 
0174 ;############# Common Handlers for ARCompact and ARCv2 ##############
0175 
0176 #include "entry.S"
0177 
0178 ;############# Return from Intr/Excp/Trap (ARCv2 ISA Specifics) ##############
0179 ;
0180 ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
0181 ; IRQ shd definitely not happen between now and rtie
0182 ; All 2 entry points to here already disable interrupts
0183 
0184 .Lrestore_regs:
0185 restore_regs:
0186 
0187     # Interrpts are actually disabled from this point on, but will get
0188     # reenabled after we return from interrupt/exception.
0189     # But irq tracer needs to be told now...
0190     TRACE_ASM_IRQ_ENABLE
0191 
0192     ld  r0, [sp, PT_status32]   ; U/K mode at time of entry
0193     lr  r10, [AUX_IRQ_ACT]
0194 
0195     bmsk    r11, r10, 15    ; AUX_IRQ_ACT.ACTIVE
0196     breq    r11, 0, .Lexcept_ret    ; No intr active, ret from Exception
0197 
0198 ;####### Return from Intr #######
0199 
0200 debug_marker_l1:
0201     bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
0202 
0203 .Lisr_ret_fast_path:
0204     ; Handle special case #1: (Entry via Exception, Return via IRQ)
0205     ;
0206     ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig
0207     ; task now returning to U mode (riding the Intr)
0208     ; AUX_IRQ_ACTIVE won't have U bit set (since intr in K mode), hence SP
0209     ; won't be switched to correct U mode value (from AUX_SP)
0210     ; So force AUX_IRQ_ACT.U for such a case
0211 
0212     btst    r0, STATUS_U_BIT        ; Z flag set if K (Z clear for U)
0213     bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U
0214     sr  r11, [AUX_IRQ_ACT]
0215 
0216     INTERRUPT_EPILOGUE  irq
0217     rtie
0218 
0219 ;####### Return from Exception / pure kernel mode #######
0220 
0221 .Lexcept_ret:   ; Expects r0 has PT_status32
0222 
0223 debug_marker_syscall:
0224     EXCEPTION_EPILOGUE
0225     rtie
0226 
0227 ;####### Return from Intr to insn in delay slot #######
0228 
0229 ; Handle special case #2: (Entry via Exception in Delay Slot, Return via IRQ)
0230 ;
0231 ; Intr returning to a Delay Slot (DS) insn
0232 ; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig
0233 ; entry was via Exception in DS which got preempted in kernel).
0234 ;
0235 ; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround
0236 ;
0237 ; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline
0238 ; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly
0239 
0240 .Lintr_ret_to_delay_slot:
0241 debug_marker_ds:
0242 
0243     ld  r2, [@intr_to_DE_cnt]
0244     add r2, r2, 1
0245     st  r2, [@intr_to_DE_cnt]
0246 
0247     ld  r2, [sp, PT_ret]
0248     ld  r3, [sp, PT_status32]
0249 
0250     ; STAT32 for Int return created from scratch
0251     ; (No delay dlot, disable Further intr in trampoline)
0252 
0253     bic     r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK
0254     st  r0, [sp, PT_status32]
0255 
0256     mov r1, .Lintr_ret_to_delay_slot_2
0257     st  r1, [sp, PT_ret]
0258 
0259     ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots
0260     st  r2, [sp, 0]
0261     st  r3, [sp, 4]
0262 
0263     b   .Lisr_ret_fast_path
0264 
0265 .Lintr_ret_to_delay_slot_2:
0266     ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP
0267     sub sp, sp, SZ_PT_REGS
0268     st  r9, [sp, -4]
0269 
0270     ld  r9, [sp, 0]
0271     sr  r9, [eret]
0272 
0273     ld  r9, [sp, 4]
0274     sr  r9, [erstatus]
0275 
0276     ; restore AUX_USER_SP if returning to U mode
0277     bbit0   r9, STATUS_U_BIT, 1f
0278     ld  r9, [sp, PT_sp]
0279     sr  r9, [AUX_USER_SP]
0280 
0281 1:
0282     ld  r9, [sp, 8]
0283     sr  r9, [erbta]
0284 
0285     ld  r9, [sp, -4]
0286     add sp, sp, SZ_PT_REGS
0287 
0288     ; return from pure kernel mode to delay slot
0289     rtie
0290 
0291 END(ret_from_exception)