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