diff options
Diffstat (limited to 'arch/arc/kernel/entry-arcv2.S')
| -rw-r--r-- | arch/arc/kernel/entry-arcv2.S | 62 |
1 files changed, 12 insertions, 50 deletions
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index 14254b866fdc..12d5f12d10d2 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S | |||
| @@ -67,7 +67,7 @@ reserved: | |||
| 67 | 67 | ||
| 68 | ENTRY(handle_interrupt) | 68 | ENTRY(handle_interrupt) |
| 69 | 69 | ||
| 70 | INTERRUPT_PROLOGUE irq | 70 | INTERRUPT_PROLOGUE |
| 71 | 71 | ||
| 72 | # irq control APIs local_irq_save/restore/disable/enable fiddle with | 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) | 73 | # global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio) |
| @@ -79,7 +79,7 @@ ENTRY(handle_interrupt) | |||
| 79 | # | 79 | # |
| 80 | # Note this disable is only for consistent book-keeping as further interrupts | 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 | 81 | # will be disabled anyways even w/o this. Hardware tracks active interrupts |
| 82 | # seperately in AUX_IRQ_ACTIVE.active and will not take new interrupts | 82 | # seperately in AUX_IRQ_ACT.active and will not take new interrupts |
| 83 | # unless this one returns (or higher prio becomes pending in 2-prio scheme) | 83 | # unless this one returns (or higher prio becomes pending in 2-prio scheme) |
| 84 | 84 | ||
| 85 | IRQ_DISABLE | 85 | IRQ_DISABLE |
| @@ -200,17 +200,18 @@ restore_regs: | |||
| 200 | ld r0, [sp, PT_status32] ; U/K mode at time of entry | 200 | ld r0, [sp, PT_status32] ; U/K mode at time of entry |
| 201 | lr r10, [AUX_IRQ_ACT] | 201 | lr r10, [AUX_IRQ_ACT] |
| 202 | 202 | ||
| 203 | bmsk r11, r10, 15 ; AUX_IRQ_ACT.ACTIVE | 203 | bmsk r11, r10, 15 ; extract AUX_IRQ_ACT.active |
| 204 | breq r11, 0, .Lexcept_ret ; No intr active, ret from Exception | 204 | breq r11, 0, .Lexcept_ret ; No intr active, ret from Exception |
| 205 | 205 | ||
| 206 | ;####### Return from Intr ####### | 206 | ;####### Return from Intr ####### |
| 207 | 207 | ||
| 208 | .Lisr_ret: | ||
| 209 | |||
| 208 | debug_marker_l1: | 210 | debug_marker_l1: |
| 209 | ; bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot | 211 | ; bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot |
| 210 | btst r0, STATUS_DE_BIT ; Z flag set if bit clear | 212 | btst r0, STATUS_DE_BIT ; Z flag set if bit clear |
| 211 | bnz .Lintr_ret_to_delay_slot ; branch if STATUS_DE_BIT set | 213 | bnz .Lintr_ret_to_delay_slot ; branch if STATUS_DE_BIT set |
| 212 | 214 | ||
| 213 | .Lisr_ret_fast_path: | ||
| 214 | ; Handle special case #1: (Entry via Exception, Return via IRQ) | 215 | ; Handle special case #1: (Entry via Exception, Return via IRQ) |
| 215 | ; | 216 | ; |
| 216 | ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig | 217 | ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig |
| @@ -223,7 +224,7 @@ debug_marker_l1: | |||
| 223 | bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U | 224 | bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U |
| 224 | sr r11, [AUX_IRQ_ACT] | 225 | sr r11, [AUX_IRQ_ACT] |
| 225 | 226 | ||
| 226 | INTERRUPT_EPILOGUE irq | 227 | INTERRUPT_EPILOGUE |
| 227 | rtie | 228 | rtie |
| 228 | 229 | ||
| 229 | ;####### Return from Exception / pure kernel mode ####### | 230 | ;####### Return from Exception / pure kernel mode ####### |
| @@ -244,8 +245,8 @@ debug_marker_syscall: | |||
| 244 | ; | 245 | ; |
| 245 | ; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround | 246 | ; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround |
| 246 | ; | 247 | ; |
| 247 | ; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline | 248 | ; Solution is to drop out of interrupt context into pure kernel mode |
| 248 | ; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly | 249 | ; and return from pure kernel mode which does right things for delay slot |
| 249 | 250 | ||
| 250 | .Lintr_ret_to_delay_slot: | 251 | .Lintr_ret_to_delay_slot: |
| 251 | debug_marker_ds: | 252 | debug_marker_ds: |
| @@ -254,48 +255,9 @@ debug_marker_ds: | |||
| 254 | add r2, r2, 1 | 255 | add r2, r2, 1 |
| 255 | st r2, [@intr_to_DE_cnt] | 256 | st r2, [@intr_to_DE_cnt] |
| 256 | 257 | ||
| 257 | ld r2, [sp, PT_ret] | 258 | ; drop out of interrupt context (clear AUX_IRQ_ACT.active) |
| 258 | ld r3, [sp, PT_status32] | 259 | bmskn r11, r10, 15 |
| 259 | 260 | sr r11, [AUX_IRQ_ACT] | |
| 260 | ; STAT32 for Int return created from scratch | 261 | b .Lexcept_ret |
| 261 | ; (No delay dlot, disable Further intr in trampoline) | ||
| 262 | |||
| 263 | bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK | ||
| 264 | st r0, [sp, PT_status32] | ||
| 265 | |||
| 266 | mov r1, .Lintr_ret_to_delay_slot_2 | ||
| 267 | st r1, [sp, PT_ret] | ||
| 268 | |||
| 269 | ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots | ||
| 270 | st r2, [sp, 0] | ||
| 271 | st r3, [sp, 4] | ||
| 272 | |||
| 273 | b .Lisr_ret_fast_path | ||
| 274 | |||
| 275 | .Lintr_ret_to_delay_slot_2: | ||
| 276 | ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP | ||
| 277 | sub sp, sp, SZ_PT_REGS | ||
| 278 | st r9, [sp, -4] | ||
| 279 | |||
| 280 | ld r9, [sp, 0] | ||
| 281 | sr r9, [eret] | ||
| 282 | |||
| 283 | ld r9, [sp, 4] | ||
| 284 | sr r9, [erstatus] | ||
| 285 | |||
| 286 | ; restore AUX_USER_SP if returning to U mode | ||
| 287 | bbit0 r9, STATUS_U_BIT, 1f | ||
| 288 | ld r9, [sp, PT_sp] | ||
| 289 | sr r9, [AUX_USER_SP] | ||
| 290 | |||
| 291 | 1: | ||
| 292 | ld r9, [sp, 8] | ||
| 293 | sr r9, [erbta] | ||
| 294 | |||
| 295 | ld r9, [sp, -4] | ||
| 296 | add sp, sp, SZ_PT_REGS | ||
| 297 | |||
| 298 | ; return from pure kernel mode to delay slot | ||
| 299 | rtie | ||
| 300 | 262 | ||
| 301 | END(ret_from_exception) | 263 | END(ret_from_exception) |
