Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arc/kernel/entry-compact.S
26439 views
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
/*
3
* Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARCompact ISA
4
*
5
* Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
6
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
7
*
8
* vineetg: May 2011
9
* -Userspace unaligned access emulation
10
*
11
* vineetg: Feb 2011 (ptrace low level code fixes)
12
* -traced syscall return code (r0) was not saved into pt_regs for restoring
13
* into user reg-file when traded task rets to user space.
14
* -syscalls needing arch-wrappers (mainly for passing sp as pt_regs)
15
* were not invoking post-syscall trace hook (jumping directly into
16
* ret_from_system_call)
17
*
18
* vineetg: Nov 2010:
19
* -Vector table jumps (@8 bytes) converted into branches (@4 bytes)
20
* -To maintain the slot size of 8 bytes/vector, added nop, which is
21
* not executed at runtime.
22
*
23
* vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
24
* -do_signal()invoked upon TIF_RESTORE_SIGMASK as well
25
* -Wrappers for sys_{,rt_}sigsuspend() no longer needed as they don't
26
* need ptregs anymore
27
*
28
* Vineetg: Oct 2009
29
* -In a rare scenario, Process gets a Priv-V exception and gets scheduled
30
* out. Since we don't do FAKE RTIE for Priv-V, CPU exception state remains
31
* active (AE bit enabled). This causes a double fault for a subseq valid
32
* exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
33
* Instr Error could also cause similar scenario, so same there as well.
34
*
35
* Vineetg: March 2009 (Supporting 2 levels of Interrupts)
36
*
37
* Vineetg: Aug 28th 2008: Bug #94984
38
* -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
39
* Normally CPU does this automatically, however when doing FAKE rtie,
40
* we need to explicitly do this. The problem in macros
41
* FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
42
* was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit,
43
* setting it and not clearing it clears ZOL context
44
*
45
* Vineetg: May 16th, 2008
46
* - r25 now contains the Current Task when in kernel
47
*
48
* Vineetg: Dec 22, 2007
49
* Minor Surgery of Low Level ISR to make it SMP safe
50
* - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR
51
* - _current_task is made an array of NR_CPUS
52
* - Access of _current_task wrapped inside a macro so that if hardware
53
* team agrees for a dedicated reg, no other code is touched
54
*
55
* Amit Bhor, Rahul Trivedi, Kanika Nema, Sameer Dhavale : Codito Tech 2004
56
*/
57
58
#include <linux/errno.h>
59
#include <linux/linkage.h> /* {ENTRY,EXIT} */
60
#include <asm/entry.h>
61
#include <asm/irqflags.h>
62
63
.cpu A7
64
65
;############################ Vector Table #################################
66
67
.macro VECTOR lbl
68
#if 1 /* Just in case, build breaks */
69
j \lbl
70
#else
71
b \lbl
72
nop
73
#endif
74
.endm
75
76
.section .vector, "ax",@progbits
77
.align 4
78
79
/* Each entry in the vector table must occupy 2 words. Since it is a jump
80
* across sections (.vector to .text) we are guaranteed that 'j somewhere'
81
* will use the 'j limm' form of the instruction as long as somewhere is in
82
* a section other than .vector.
83
*/
84
85
; ********* Critical System Events **********************
86
VECTOR res_service ; 0x0, Reset Vector (0x0)
87
VECTOR mem_service ; 0x8, Mem exception (0x1)
88
VECTOR instr_service ; 0x10, Instrn Error (0x2)
89
90
; ******************** Device ISRs **********************
91
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
92
VECTOR handle_interrupt_level2
93
#else
94
VECTOR handle_interrupt_level1
95
#endif
96
97
.rept 28
98
VECTOR handle_interrupt_level1 ; Other devices
99
.endr
100
101
/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
102
103
; ******************** Exceptions **********************
104
VECTOR EV_MachineCheck ; 0x100, Fatal Machine check (0x20)
105
VECTOR EV_TLBMissI ; 0x108, Instruction TLB miss (0x21)
106
VECTOR EV_TLBMissD ; 0x110, Data TLB miss (0x22)
107
VECTOR EV_TLBProtV ; 0x118, Protection Violation (0x23)
108
; or Misaligned Access
109
VECTOR EV_PrivilegeV ; 0x120, Privilege Violation (0x24)
110
VECTOR EV_Trap ; 0x128, Trap exception (0x25)
111
VECTOR EV_Extension ; 0x130, Extn Instruction Excp (0x26)
112
113
.rept 24
114
VECTOR reserved ; Reserved Exceptions
115
.endr
116
117
118
;##################### Scratch Mem for IRQ stack switching #############
119
120
ARCFP_DATA int1_saved_reg
121
.align 32
122
.type int1_saved_reg, @object
123
.size int1_saved_reg, 4
124
int1_saved_reg:
125
.zero 4
126
127
/* Each Interrupt level needs its own scratch */
128
ARCFP_DATA int2_saved_reg
129
.type int2_saved_reg, @object
130
.size int2_saved_reg, 4
131
int2_saved_reg:
132
.zero 4
133
134
; ---------------------------------------------
135
.section .text, "ax",@progbits
136
137
138
reserved:
139
flag 1 ; Unexpected event, halt
140
141
;##################### Interrupt Handling ##############################
142
143
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
144
; ---------------------------------------------
145
; Level 2 ISR: Can interrupt a Level 1 ISR
146
; ---------------------------------------------
147
ENTRY(handle_interrupt_level2)
148
149
INTERRUPT_PROLOGUE 2
150
151
;------------------------------------------------------
152
; if L2 IRQ interrupted a L1 ISR, disable preemption
153
;
154
; This is to avoid a potential L1-L2-L1 scenario
155
; -L1 IRQ taken
156
; -L2 interrupts L1 (before L1 ISR could run)
157
; -preemption off IRQ, user task in syscall picked to run
158
; -RTIE to userspace
159
; Returns from L2 context fine
160
; But both L1 and L2 re-enabled, so another L1 can be taken
161
; while prev L1 is still unserviced
162
;
163
;------------------------------------------------------
164
165
; L2 interrupting L1 implies both L2 and L1 active
166
; However both A2 and A1 are NOT set in STATUS32, thus
167
; need to check STATUS32_L2 to determine if L1 was active
168
169
ld r9, [sp, PT_status32] ; get statu32_l2 (saved in pt_regs)
170
bbit0 r9, STATUS_A1_BIT, 1f ; L1 not active when L2 IRQ, so normal
171
172
; bump thread_info->preempt_count (Disable preemption)
173
GET_CURR_THR_INFO_FROM_SP r10
174
ld r9, [r10, THREAD_INFO_PREEMPT_COUNT]
175
add r9, r9, 1
176
st r9, [r10, THREAD_INFO_PREEMPT_COUNT]
177
178
1:
179
;------------------------------------------------------
180
; setup params for Linux common ISR and invoke it
181
;------------------------------------------------------
182
lr r0, [icause2]
183
and r0, r0, 0x1f
184
185
bl.d @arch_do_IRQ
186
mov r1, sp
187
188
mov r8,0x2
189
sr r8, [AUX_IRQ_LV12] ; clear bit in Sticky Status Reg
190
191
b ret_from_exception
192
193
END(handle_interrupt_level2)
194
195
#endif
196
197
; ---------------------------------------------
198
; User Mode Memory Bus Error Interrupt Handler
199
; (Kernel mode memory errors handled via separate exception vectors)
200
; ---------------------------------------------
201
ENTRY(mem_service)
202
203
INTERRUPT_PROLOGUE 2
204
205
mov r0, ilink2
206
mov r1, sp
207
208
; User process needs to be killed with SIGBUS, but first need to get
209
; out of the L2 interrupt context (drop to pure kernel mode) and jump
210
; off to "C" code where SIGBUS in enqueued
211
lr r3, [status32]
212
bclr r3, r3, STATUS_A2_BIT
213
or r3, r3, (STATUS_E1_MASK|STATUS_E2_MASK)
214
sr r3, [status32_l2]
215
mov ilink2, 1f
216
rtie
217
1:
218
bl do_memory_error
219
b ret_from_exception
220
END(mem_service)
221
222
; ---------------------------------------------
223
; Level 1 ISR
224
; ---------------------------------------------
225
ENTRY(handle_interrupt_level1)
226
227
INTERRUPT_PROLOGUE 1
228
229
lr r0, [icause1]
230
and r0, r0, 0x1f
231
232
#ifdef CONFIG_TRACE_IRQFLAGS
233
; icause1 needs to be read early, before calling tracing, which
234
; can clobber scratch regs, hence use of stack to stash it
235
push r0
236
TRACE_ASM_IRQ_DISABLE
237
pop r0
238
#endif
239
240
bl.d @arch_do_IRQ
241
mov r1, sp
242
243
mov r8,0x1
244
sr r8, [AUX_IRQ_LV12] ; clear bit in Sticky Status Reg
245
246
b ret_from_exception
247
END(handle_interrupt_level1)
248
249
;################### Non TLB Exception Handling #############################
250
251
; ---------------------------------------------
252
; Protection Violation Exception Handler
253
; ---------------------------------------------
254
255
ENTRY(EV_TLBProtV)
256
257
EXCEPTION_PROLOGUE ; ECR returned in r10
258
259
;------ (5) Type of Protection Violation? ----------
260
;
261
; ProtV Hardware Exception is triggered for Access Faults of 2 types
262
; -Access Violation : 00_23_(00|01|02|03)_00
263
; x r w r+w
264
; -Unaligned Access : 00_23_04_00
265
bbit1 r10, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
266
267
;========= (6a) Access Violation Processing ========
268
bl do_page_fault
269
b ret_from_exception
270
271
;========== (6b) Non aligned access ============
272
4:
273
274
SAVE_CALLEE_SAVED_USER
275
mov r2, sp ; callee_regs
276
277
bl do_misaligned_access
278
279
; TBD: optimize - do this only if a callee reg was involved
280
; either a dst of emulated LD/ST or src with address-writeback
281
RESTORE_CALLEE_SAVED_USER
282
283
b ret_from_exception
284
285
END(EV_TLBProtV)
286
287
; Wrapper for Linux page fault handler called from EV_TLBMiss*
288
; Very similar to ProtV handler case (6a) above, but avoids the extra checks
289
; for Misaligned access
290
;
291
ENTRY(call_do_page_fault)
292
293
EXCEPTION_PROLOGUE
294
295
mov blink, ret_from_exception
296
b do_page_fault
297
298
END(call_do_page_fault)
299
300
;############# Common Handlers for ARCompact and ARCv2 ##############
301
302
#include "entry.S"
303
304
;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
305
;
306
; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
307
; IRQ shd definitely not happen between now and rtie
308
; All 2 entry points to here already disable interrupts
309
310
.Lrestore_regs:
311
312
# Interrupts are actually disabled from this point on, but will get
313
# reenabled after we return from interrupt/exception.
314
# But irq tracer needs to be told now...
315
TRACE_ASM_IRQ_ENABLE
316
317
lr r10, [status32]
318
319
; Restore REG File. In case multiple Events outstanding,
320
; use the same priority as rtie: EXCPN, L2 IRQ, L1 IRQ, None
321
; Note that we use realtime STATUS32 (not pt_regs->status32) to
322
; decide that.
323
324
and.f 0, r10, (STATUS_A1_MASK|STATUS_A2_MASK)
325
bz .Lexcep_or_pure_K_ret
326
327
; Returning from Interrupts (Level 1 or 2)
328
329
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
330
331
; Level 2 interrupt return Path - from hardware standpoint
332
bbit0 r10, STATUS_A2_BIT, not_level2_interrupt
333
334
;------------------------------------------------------------------
335
; However the context returning might not have taken L2 intr itself
336
; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
337
; Special considerations needed for the context which took L2 intr
338
339
ld r9, [sp, PT_event] ; Ensure this is L2 intr context
340
brne r9, event_IRQ2, 149f
341
342
;------------------------------------------------------------------
343
; if L2 IRQ interrupted an L1 ISR, we'd disabled preemption earlier
344
; so that sched doesn't move to new task, causing L1 to be delayed
345
; undeterministically. Now that we've achieved that, let's reset
346
; things to what they were, before returning from L2 context
347
;----------------------------------------------------------------
348
349
ld r9, [sp, PT_status32] ; get statu32_l2 (saved in pt_regs)
350
bbit0 r9, STATUS_A1_BIT, 149f ; L1 not active when L2 IRQ, so normal
351
352
; decrement thread_info->preempt_count (re-enable preemption)
353
GET_CURR_THR_INFO_FROM_SP r10
354
ld r9, [r10, THREAD_INFO_PREEMPT_COUNT]
355
356
; paranoid check, given A1 was active when A2 happened, preempt count
357
; must not be 0 because we would have incremented it.
358
; If this does happen we simply HALT as it means a BUG !!!
359
cmp r9, 0
360
bnz 2f
361
flag 1
362
363
2:
364
sub r9, r9, 1
365
st r9, [r10, THREAD_INFO_PREEMPT_COUNT]
366
367
149:
368
INTERRUPT_EPILOGUE 2 ; return from level 2 interrupt
369
debug_marker_l2:
370
rtie
371
372
not_level2_interrupt:
373
374
#endif
375
376
INTERRUPT_EPILOGUE 1 ; return from level 1 interrupt
377
debug_marker_l1:
378
rtie
379
380
.Lexcep_or_pure_K_ret:
381
382
;this case is for syscalls or Exceptions or pure kernel mode
383
384
EXCEPTION_EPILOGUE
385
debug_marker_syscall:
386
rtie
387
388
END(ret_from_exception)
389
390