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