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 | |
| 17 | .cpu HS |
| 18 | |
| 19 | #define VECTOR .word |
| 20 | |
| 21 | ;############################ Vector Table ################################# |
| 22 | |
| 23 | .section .vector,"a",@progbits |
| 24 | .align 4 |
| 25 | |
| 26 | # Initial 16 slots are Exception Vectors |
Vineet Gupta | 3971cdc | 2015-10-09 11:26:12 +0530 | [diff] [blame^] | 27 | VECTOR res_service ; Reset Vector |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 28 | VECTOR mem_service ; Mem exception |
| 29 | VECTOR instr_service ; Instrn Error |
| 30 | VECTOR EV_MachineCheck ; Fatal Machine check |
| 31 | VECTOR EV_TLBMissI ; Intruction TLB miss |
| 32 | VECTOR EV_TLBMissD ; Data TLB miss |
| 33 | VECTOR EV_TLBProtV ; Protection Violation |
| 34 | VECTOR EV_PrivilegeV ; Privilege Violation |
| 35 | VECTOR EV_SWI ; Software Breakpoint |
| 36 | VECTOR EV_Trap ; Trap exception |
| 37 | VECTOR EV_Extension ; Extn Instruction Exception |
| 38 | VECTOR EV_DivZero ; Divide by Zero |
| 39 | VECTOR EV_DCError ; Data Cache Error |
| 40 | VECTOR EV_Misaligned ; Misaligned Data Access |
| 41 | VECTOR reserved ; Reserved slots |
| 42 | VECTOR reserved ; Reserved slots |
| 43 | |
| 44 | # Begin Interrupt Vectors |
| 45 | VECTOR handle_interrupt ; (16) Timer0 |
| 46 | VECTOR handle_interrupt ; unused (Timer1) |
| 47 | VECTOR handle_interrupt ; unused (WDT) |
| 48 | VECTOR handle_interrupt ; (19) ICI (inter core interrupt) |
| 49 | VECTOR handle_interrupt |
| 50 | VECTOR handle_interrupt |
| 51 | VECTOR handle_interrupt |
| 52 | VECTOR handle_interrupt ; (23) End of fixed IRQs |
| 53 | |
| 54 | .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8 |
| 55 | VECTOR handle_interrupt |
| 56 | .endr |
| 57 | |
| 58 | .section .text, "ax",@progbits |
| 59 | |
Vineet Gupta | 3d59265 | 2015-08-27 16:25:07 +0530 | [diff] [blame] | 60 | reserved: |
| 61 | flag 1 ; Unexpected event, halt |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 62 | |
| 63 | ;##################### Interrupt Handling ############################## |
| 64 | |
| 65 | ENTRY(handle_interrupt) |
| 66 | |
| 67 | INTERRUPT_PROLOGUE irq |
| 68 | |
| 69 | clri ; To make status32.IE agree with CPU internal state |
| 70 | |
| 71 | lr r0, [ICAUSE] |
| 72 | |
| 73 | mov blink, ret_from_exception |
| 74 | |
| 75 | b.d arch_do_IRQ |
| 76 | mov r1, sp |
| 77 | |
| 78 | END(handle_interrupt) |
| 79 | |
| 80 | ;################### Non TLB Exception Handling ############################# |
| 81 | |
| 82 | ENTRY(EV_SWI) |
| 83 | flag 1 |
| 84 | END(EV_SWI) |
| 85 | |
| 86 | ENTRY(EV_DivZero) |
| 87 | flag 1 |
| 88 | END(EV_DivZero) |
| 89 | |
| 90 | ENTRY(EV_DCError) |
| 91 | flag 1 |
| 92 | END(EV_DCError) |
| 93 | |
| 94 | ENTRY(EV_Misaligned) |
| 95 | |
| 96 | EXCEPTION_PROLOGUE |
| 97 | |
| 98 | lr r0, [efa] ; Faulting Data address |
| 99 | mov r1, sp |
| 100 | |
| 101 | FAKE_RET_FROM_EXCPN |
| 102 | |
| 103 | SAVE_CALLEE_SAVED_USER |
| 104 | mov r2, sp ; callee_regs |
| 105 | |
| 106 | bl do_misaligned_access |
| 107 | |
| 108 | ; TBD: optimize - do this only if a callee reg was involved |
| 109 | ; either a dst of emulated LD/ST or src with address-writeback |
| 110 | RESTORE_CALLEE_SAVED_USER |
| 111 | |
| 112 | b ret_from_exception |
| 113 | END(EV_Misaligned) |
| 114 | |
| 115 | ; --------------------------------------------- |
| 116 | ; Protection Violation Exception Handler |
| 117 | ; --------------------------------------------- |
| 118 | |
| 119 | ENTRY(EV_TLBProtV) |
| 120 | |
| 121 | EXCEPTION_PROLOGUE |
| 122 | |
| 123 | lr r0, [efa] ; Faulting Data address |
| 124 | mov r1, sp ; pt_regs |
| 125 | |
| 126 | FAKE_RET_FROM_EXCPN |
| 127 | |
| 128 | mov blink, ret_from_exception |
| 129 | b do_page_fault |
| 130 | |
| 131 | END(EV_TLBProtV) |
| 132 | |
| 133 | ; From Linux standpoint Slow Path I/D TLB Miss is same a ProtV as they |
| 134 | ; need to call do_page_fault(). |
| 135 | ; ECR in pt_regs provides whether access was R/W/X |
| 136 | |
| 137 | .global call_do_page_fault |
| 138 | .set call_do_page_fault, EV_TLBProtV |
| 139 | |
| 140 | ;############# Common Handlers for ARCompact and ARCv2 ############## |
| 141 | |
| 142 | #include "entry.S" |
| 143 | |
| 144 | ;############# Return from Intr/Excp/Trap (ARCv2 ISA Specifics) ############## |
| 145 | ; |
| 146 | ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap) |
| 147 | ; IRQ shd definitely not happen between now and rtie |
| 148 | ; All 2 entry points to here already disable interrupts |
| 149 | |
| 150 | .Lrestore_regs: |
| 151 | |
| 152 | ld r0, [sp, PT_status32] ; U/K mode at time of entry |
| 153 | lr r10, [AUX_IRQ_ACT] |
| 154 | |
| 155 | bmsk r11, r10, 15 ; AUX_IRQ_ACT.ACTIVE |
| 156 | breq r11, 0, .Lexcept_ret ; No intr active, ret from Exception |
| 157 | |
| 158 | ;####### Return from Intr ####### |
| 159 | |
| 160 | debug_marker_l1: |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 161 | bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot |
| 162 | |
| 163 | .Lisr_ret_fast_path: |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 164 | ; Handle special case #1: (Entry via Exception, Return via IRQ) |
| 165 | ; |
| 166 | ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig |
| 167 | ; task now returning to U mode (riding the Intr) |
| 168 | ; AUX_IRQ_ACTIVE won't have U bit set (since intr in K mode), hence SP |
| 169 | ; won't be switched to correct U mode value (from AUX_SP) |
| 170 | ; So force AUX_IRQ_ACT.U for such a case |
| 171 | |
| 172 | btst r0, STATUS_U_BIT ; Z flag set if K (Z clear for U) |
| 173 | bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U |
| 174 | sr r11, [AUX_IRQ_ACT] |
| 175 | |
| 176 | INTERRUPT_EPILOGUE irq |
| 177 | rtie |
| 178 | |
| 179 | ;####### Return from Exception / pure kernel mode ####### |
| 180 | |
| 181 | .Lexcept_ret: ; Expects r0 has PT_status32 |
| 182 | |
| 183 | debug_marker_syscall: |
| 184 | EXCEPTION_EPILOGUE |
| 185 | rtie |
| 186 | |
Vineet Gupta | 4255b07 | 2014-09-22 16:51:47 +0530 | [diff] [blame] | 187 | ;####### Return from Intr to insn in delay slot ####### |
| 188 | |
| 189 | ; Handle special case #2: (Entry via Exception in Delay Slot, Return via IRQ) |
| 190 | ; |
| 191 | ; Intr returning to a Delay Slot (DS) insn |
| 192 | ; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig |
| 193 | ; entry was via Exception in DS which got preempted in kernel). |
| 194 | ; |
| 195 | ; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling |
| 196 | .Lintr_ret_to_delay_slot: |
| 197 | debug_marker_ds: |
| 198 | |
| 199 | ld r2, [@intr_to_DE_cnt] |
| 200 | add r2, r2, 1 |
| 201 | st r2, [@intr_to_DE_cnt] |
| 202 | |
| 203 | ld r2, [sp, PT_ret] |
| 204 | ld r3, [sp, PT_status32] |
| 205 | |
| 206 | bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK |
| 207 | st r0, [sp, PT_status32] |
| 208 | |
| 209 | mov r1, .Lintr_ret_to_delay_slot_2 |
| 210 | st r1, [sp, PT_ret] |
| 211 | |
| 212 | st r2, [sp, 0] |
| 213 | st r3, [sp, 4] |
| 214 | |
| 215 | b .Lisr_ret_fast_path |
| 216 | |
| 217 | .Lintr_ret_to_delay_slot_2: |
| 218 | sub sp, sp, SZ_PT_REGS |
| 219 | st r9, [sp, -4] |
| 220 | |
| 221 | ld r9, [sp, 0] |
| 222 | sr r9, [eret] |
| 223 | |
| 224 | ld r9, [sp, 4] |
| 225 | sr r9, [erstatus] |
| 226 | |
| 227 | ld r9, [sp, 8] |
| 228 | sr r9, [erbta] |
| 229 | |
| 230 | ld r9, [sp, -4] |
| 231 | add sp, sp, SZ_PT_REGS |
| 232 | rtie |
| 233 | |
Vineet Gupta | 1f6ccff | 2013-05-13 18:30:41 +0530 | [diff] [blame] | 234 | END(ret_from_exception) |