Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 1 | /* |
| 2 | * ARCv2 ISA based core Low Level Intr/Traps/Exceptions(non-TLB) Handling |
| 3 | * |
| 4 | * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as |
| 8 | * published by the Free Software Foundation. |
| 9 | */ |
| 10 | |
| 11 | #include <linux/linkage.h> /* ARC_{EXTRY,EXIT} */ |
| 12 | #include <asm/entry.h> /* SAVE_ALL_{INT1,INT2,TRAP...} */ |
| 13 | #include <asm/errno.h> |
| 14 | #include <asm/arcregs.h> |
| 15 | #include <asm/irqflags.h> |
| 16 | |
Yuriy Kolerov | f33b8cd | 2017-01-31 14:45:22 +0300 | [diff] [blame^] | 17 | ; A maximum number of supported interrupts in the core interrupt controller. |
| 18 | ; This number is not equal to the maximum interrupt number (256) because |
| 19 | ; first 16 lines are reserved for exceptions and are not configurable. |
| 20 | #define NR_CPU_IRQS 240 |
| 21 | |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 22 | .cpu HS |
| 23 | |
| 24 | #define VECTOR .word |
| 25 | |
| 26 | ;############################ Vector Table ################################# |
| 27 | |
| 28 | .section .vector,"a",@progbits |
| 29 | .align 4 |
| 30 | |
| 31 | # Initial 16 slots are Exception Vectors |
Vineet Gupta | 3971cdc | 2015-10-09 11:26:12 +0530 | [diff] [blame] | 32 | VECTOR res_service ; Reset Vector |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 33 | VECTOR mem_service ; Mem exception |
| 34 | VECTOR instr_service ; Instrn Error |
| 35 | VECTOR EV_MachineCheck ; Fatal Machine check |
| 36 | VECTOR EV_TLBMissI ; Intruction TLB miss |
| 37 | VECTOR EV_TLBMissD ; Data TLB miss |
| 38 | VECTOR EV_TLBProtV ; Protection Violation |
| 39 | VECTOR EV_PrivilegeV ; Privilege Violation |
| 40 | VECTOR EV_SWI ; Software Breakpoint |
| 41 | VECTOR EV_Trap ; Trap exception |
| 42 | VECTOR EV_Extension ; Extn Instruction Exception |
| 43 | VECTOR EV_DivZero ; Divide by Zero |
| 44 | VECTOR EV_DCError ; Data Cache Error |
| 45 | VECTOR EV_Misaligned ; Misaligned Data Access |
| 46 | VECTOR reserved ; Reserved slots |
| 47 | VECTOR reserved ; Reserved slots |
| 48 | |
| 49 | # Begin Interrupt Vectors |
| 50 | VECTOR handle_interrupt ; (16) Timer0 |
| 51 | VECTOR handle_interrupt ; unused (Timer1) |
| 52 | VECTOR handle_interrupt ; unused (WDT) |
Vineet Gupta | bb143f8 | 2016-02-23 11:55:16 +0530 | [diff] [blame] | 53 | VECTOR handle_interrupt ; (19) Inter core Interrupt (IPI) |
| 54 | VECTOR handle_interrupt ; (20) perf Interrupt |
| 55 | VECTOR handle_interrupt ; (21) Software Triggered Intr (Self IPI) |
| 56 | VECTOR handle_interrupt ; unused |
| 57 | VECTOR handle_interrupt ; (23) unused |
| 58 | # End of fixed IRQs |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 59 | |
Yuriy Kolerov | f33b8cd | 2017-01-31 14:45:22 +0300 | [diff] [blame^] | 60 | .rept NR_CPU_IRQS - 8 |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 61 | VECTOR handle_interrupt |
| 62 | .endr |
| 63 | |
| 64 | .section .text, "ax",@progbits |
| 65 | |
Vineet Gupta | 3d59265 | 2015-08-27 16:25:07 +0530 | [diff] [blame] | 66 | reserved: |
| 67 | flag 1 ; Unexpected event, halt |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 68 | |
| 69 | ;##################### Interrupt Handling ############################## |
| 70 | |
| 71 | ENTRY(handle_interrupt) |
| 72 | |
| 73 | INTERRUPT_PROLOGUE irq |
| 74 | |
Vineet Gupta | 78833e7 | 2016-09-23 14:09:30 -0700 | [diff] [blame] | 75 | # irq control APIs local_irq_save/restore/disable/enable fiddle with |
| 76 | # global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio) |
| 77 | # However a taken interrupt doesn't clear these bits. Thus irqs_disabled() |
| 78 | # query in hard ISR path would return false (since .IE is set) which would |
| 79 | # trips genirq interrupt handling asserts. |
| 80 | # |
| 81 | # So do a "soft" disable of interrutps here. |
| 82 | # |
| 83 | # Note this disable is only for consistent book-keeping as further interrupts |
| 84 | # will be disabled anyways even w/o this. Hardware tracks active interrupts |
| 85 | # seperately in AUX_IRQ_ACTIVE.active and will not take new interrupts |
| 86 | # unless this one returns (or higher prio becomes pending in 2-prio scheme) |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 87 | |
Vineet Gupta | 78833e7 | 2016-09-23 14:09:30 -0700 | [diff] [blame] | 88 | IRQ_DISABLE |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 89 | |
Vineet Gupta | 78833e7 | 2016-09-23 14:09:30 -0700 | [diff] [blame] | 90 | ; icause is banked: one per priority level |
| 91 | ; so a higher prio interrupt taken here won't clobber prev prio icause |
Evgeny Voevodin | d9676fa | 2016-03-23 12:26:52 +0300 | [diff] [blame] | 92 | lr r0, [ICAUSE] |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 93 | mov blink, ret_from_exception |
| 94 | |
| 95 | b.d arch_do_IRQ |
| 96 | mov r1, sp |
| 97 | |
| 98 | END(handle_interrupt) |
| 99 | |
| 100 | ;################### Non TLB Exception Handling ############################# |
| 101 | |
| 102 | ENTRY(EV_SWI) |
| 103 | flag 1 |
| 104 | END(EV_SWI) |
| 105 | |
| 106 | ENTRY(EV_DivZero) |
| 107 | flag 1 |
| 108 | END(EV_DivZero) |
| 109 | |
| 110 | ENTRY(EV_DCError) |
| 111 | flag 1 |
| 112 | END(EV_DCError) |
| 113 | |
Vineet Gupta | 541366d | 2015-10-31 01:22:51 +0530 | [diff] [blame] | 114 | ; --------------------------------------------- |
| 115 | ; Memory Error Exception Handler |
| 116 | ; - Unlike ARCompact, handles Bus errors for both User/Kernel mode, |
| 117 | ; Instruction fetch or Data access, under a single Exception Vector |
| 118 | ; --------------------------------------------- |
| 119 | |
| 120 | ENTRY(mem_service) |
| 121 | |
| 122 | EXCEPTION_PROLOGUE |
| 123 | |
| 124 | lr r0, [efa] |
| 125 | mov r1, sp |
| 126 | |
| 127 | FAKE_RET_FROM_EXCPN |
| 128 | |
| 129 | bl do_memory_error |
| 130 | b ret_from_exception |
| 131 | END(mem_service) |
| 132 | |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 133 | ENTRY(EV_Misaligned) |
| 134 | |
| 135 | EXCEPTION_PROLOGUE |
| 136 | |
| 137 | lr r0, [efa] ; Faulting Data address |
| 138 | mov r1, sp |
| 139 | |
| 140 | FAKE_RET_FROM_EXCPN |
| 141 | |
| 142 | SAVE_CALLEE_SAVED_USER |
| 143 | mov r2, sp ; callee_regs |
| 144 | |
| 145 | bl do_misaligned_access |
| 146 | |
| 147 | ; TBD: optimize - do this only if a callee reg was involved |
| 148 | ; either a dst of emulated LD/ST or src with address-writeback |
| 149 | RESTORE_CALLEE_SAVED_USER |
| 150 | |
| 151 | b ret_from_exception |
| 152 | END(EV_Misaligned) |
| 153 | |
| 154 | ; --------------------------------------------- |
| 155 | ; Protection Violation Exception Handler |
| 156 | ; --------------------------------------------- |
| 157 | |
| 158 | ENTRY(EV_TLBProtV) |
| 159 | |
| 160 | EXCEPTION_PROLOGUE |
| 161 | |
| 162 | lr r0, [efa] ; Faulting Data address |
| 163 | mov r1, sp ; pt_regs |
| 164 | |
| 165 | FAKE_RET_FROM_EXCPN |
| 166 | |
| 167 | mov blink, ret_from_exception |
| 168 | b do_page_fault |
| 169 | |
| 170 | END(EV_TLBProtV) |
| 171 | |
| 172 | ; From Linux standpoint Slow Path I/D TLB Miss is same a ProtV as they |
| 173 | ; need to call do_page_fault(). |
| 174 | ; ECR in pt_regs provides whether access was R/W/X |
| 175 | |
| 176 | .global call_do_page_fault |
| 177 | .set call_do_page_fault, EV_TLBProtV |
| 178 | |
| 179 | ;############# Common Handlers for ARCompact and ARCv2 ############## |
| 180 | |
| 181 | #include "entry.S" |
| 182 | |
| 183 | ;############# Return from Intr/Excp/Trap (ARCv2 ISA Specifics) ############## |
| 184 | ; |
| 185 | ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap) |
| 186 | ; IRQ shd definitely not happen between now and rtie |
| 187 | ; All 2 entry points to here already disable interrupts |
| 188 | |
| 189 | .Lrestore_regs: |
Vineet Gupta | 78833e7 | 2016-09-23 14:09:30 -0700 | [diff] [blame] | 190 | restore_regs: |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 191 | |
Evgeny Voevodin | d9676fa | 2016-03-23 12:26:52 +0300 | [diff] [blame] | 192 | # Interrpts are actually disabled from this point on, but will get |
| 193 | # reenabled after we return from interrupt/exception. |
| 194 | # But irq tracer needs to be told now... |
| 195 | TRACE_ASM_IRQ_ENABLE |
| 196 | |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 197 | ld r0, [sp, PT_status32] ; U/K mode at time of entry |
| 198 | lr r10, [AUX_IRQ_ACT] |
| 199 | |
| 200 | bmsk r11, r10, 15 ; AUX_IRQ_ACT.ACTIVE |
| 201 | breq r11, 0, .Lexcept_ret ; No intr active, ret from Exception |
| 202 | |
| 203 | ;####### Return from Intr ####### |
| 204 | |
| 205 | debug_marker_l1: |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 206 | bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot |
| 207 | |
| 208 | .Lisr_ret_fast_path: |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 209 | ; Handle special case #1: (Entry via Exception, Return via IRQ) |
| 210 | ; |
| 211 | ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig |
| 212 | ; task now returning to U mode (riding the Intr) |
| 213 | ; AUX_IRQ_ACTIVE won't have U bit set (since intr in K mode), hence SP |
| 214 | ; won't be switched to correct U mode value (from AUX_SP) |
| 215 | ; So force AUX_IRQ_ACT.U for such a case |
| 216 | |
| 217 | btst r0, STATUS_U_BIT ; Z flag set if K (Z clear for U) |
| 218 | bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U |
| 219 | sr r11, [AUX_IRQ_ACT] |
| 220 | |
| 221 | INTERRUPT_EPILOGUE irq |
| 222 | rtie |
| 223 | |
| 224 | ;####### Return from Exception / pure kernel mode ####### |
| 225 | |
| 226 | .Lexcept_ret: ; Expects r0 has PT_status32 |
| 227 | |
| 228 | debug_marker_syscall: |
| 229 | EXCEPTION_EPILOGUE |
| 230 | rtie |
| 231 | |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 232 | ;####### Return from Intr to insn in delay slot ####### |
| 233 | |
| 234 | ; Handle special case #2: (Entry via Exception in Delay Slot, Return via IRQ) |
| 235 | ; |
| 236 | ; Intr returning to a Delay Slot (DS) insn |
| 237 | ; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig |
| 238 | ; entry was via Exception in DS which got preempted in kernel). |
| 239 | ; |
Vineet Gupta | cbfe74a | 2016-01-08 12:29:10 +0530 | [diff] [blame] | 240 | ; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround |
| 241 | ; |
| 242 | ; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline |
| 243 | ; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly |
| 244 | |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 245 | .Lintr_ret_to_delay_slot: |
| 246 | debug_marker_ds: |
| 247 | |
| 248 | ld r2, [@intr_to_DE_cnt] |
| 249 | add r2, r2, 1 |
| 250 | st r2, [@intr_to_DE_cnt] |
| 251 | |
| 252 | ld r2, [sp, PT_ret] |
| 253 | ld r3, [sp, PT_status32] |
| 254 | |
Vineet Gupta | cbfe74a | 2016-01-08 12:29:10 +0530 | [diff] [blame] | 255 | ; STAT32 for Int return created from scratch |
| 256 | ; (No delay dlot, disable Further intr in trampoline) |
| 257 | |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 258 | bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK |
| 259 | st r0, [sp, PT_status32] |
| 260 | |
| 261 | mov r1, .Lintr_ret_to_delay_slot_2 |
| 262 | st r1, [sp, PT_ret] |
| 263 | |
Vineet Gupta | cbfe74a | 2016-01-08 12:29:10 +0530 | [diff] [blame] | 264 | ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 265 | st r2, [sp, 0] |
| 266 | st r3, [sp, 4] |
| 267 | |
| 268 | b .Lisr_ret_fast_path |
| 269 | |
| 270 | .Lintr_ret_to_delay_slot_2: |
Vineet Gupta | cbfe74a | 2016-01-08 12:29:10 +0530 | [diff] [blame] | 271 | ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 272 | sub sp, sp, SZ_PT_REGS |
| 273 | st r9, [sp, -4] |
| 274 | |
| 275 | ld r9, [sp, 0] |
| 276 | sr r9, [eret] |
| 277 | |
| 278 | ld r9, [sp, 4] |
| 279 | sr r9, [erstatus] |
| 280 | |
Vineet Gupta | cbfe74a | 2016-01-08 12:29:10 +0530 | [diff] [blame] | 281 | ; restore AUX_USER_SP if returning to U mode |
| 282 | bbit0 r9, STATUS_U_BIT, 1f |
| 283 | ld r9, [sp, PT_sp] |
| 284 | sr r9, [AUX_USER_SP] |
| 285 | |
| 286 | 1: |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 287 | ld r9, [sp, 8] |
| 288 | sr r9, [erbta] |
| 289 | |
| 290 | ld r9, [sp, -4] |
| 291 | add sp, sp, SZ_PT_REGS |
Vineet Gupta | cbfe74a | 2016-01-08 12:29:10 +0530 | [diff] [blame] | 292 | |
| 293 | ; return from pure kernel mode to delay slot |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 294 | rtie |
| 295 | |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 296 | END(ret_from_exception) |