blob: d7230bf68ad155144fef43e746de89ce72969e11 [file] [log] [blame]
Catalin Marinas60ffc302012-03-05 11:49:27 +00001/*
2 * Low-level exception handling code
3 *
4 * Copyright (C) 2012 ARM Ltd.
5 * Authors: Catalin Marinas <catalin.marinas@arm.com>
6 * Will Deacon <will.deacon@arm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/init.h>
22#include <linux/linkage.h>
23
24#include <asm/assembler.h>
25#include <asm/asm-offsets.h>
26#include <asm/errno.h>
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +010027#include <asm/esr.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000028#include <asm/thread_info.h>
29#include <asm/unistd.h>
Catalin Marinasf3d447a2012-10-10 15:27:04 +010030#include <asm/unistd32.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000031
32/*
33 * Bad Abort numbers
34 *-----------------
35 */
36#define BAD_SYNC 0
37#define BAD_IRQ 1
38#define BAD_FIQ 2
39#define BAD_ERROR 3
40
41 .macro kernel_entry, el, regsize = 64
42 sub sp, sp, #S_FRAME_SIZE - S_LR // room for LR, SP, SPSR, ELR
43 .if \regsize == 32
44 mov w0, w0 // zero upper 32 bits of x0
45 .endif
46 push x28, x29
47 push x26, x27
48 push x24, x25
49 push x22, x23
50 push x20, x21
51 push x18, x19
52 push x16, x17
53 push x14, x15
54 push x12, x13
55 push x10, x11
56 push x8, x9
57 push x6, x7
58 push x4, x5
59 push x2, x3
60 push x0, x1
61 .if \el == 0
62 mrs x21, sp_el0
Will Deacon2a283072014-04-29 19:04:06 +010063 get_thread_info tsk // Ensure MDSCR_EL1.SS is clear,
64 ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug
65 disable_step_tsk x19, x20 // exceptions when scheduling.
Catalin Marinas60ffc302012-03-05 11:49:27 +000066 .else
67 add x21, sp, #S_FRAME_SIZE
68 .endif
69 mrs x22, elr_el1
70 mrs x23, spsr_el1
71 stp lr, x21, [sp, #S_LR]
72 stp x22, x23, [sp, #S_PC]
73
74 /*
75 * Set syscallno to -1 by default (overridden later if real syscall).
76 */
77 .if \el == 0
78 mvn x21, xzr
79 str x21, [sp, #S_SYSCALLNO]
80 .endif
81
82 /*
83 * Registers that may be useful after this macro is invoked:
84 *
85 * x21 - aborted SP
86 * x22 - aborted PC
87 * x23 - aborted PSTATE
88 */
89 .endm
90
91 .macro kernel_exit, el, ret = 0
92 ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
93 .if \el == 0
94 ldr x23, [sp, #S_SP] // load return stack pointer
95 .endif
96 .if \ret
97 ldr x1, [sp, #S_X1] // preserve x0 (syscall return)
98 add sp, sp, S_X2
99 .else
100 pop x0, x1
101 .endif
102 pop x2, x3 // load the rest of the registers
103 pop x4, x5
104 pop x6, x7
105 pop x8, x9
106 msr elr_el1, x21 // set up the return data
107 msr spsr_el1, x22
108 .if \el == 0
109 msr sp_el0, x23
110 .endif
111 pop x10, x11
112 pop x12, x13
113 pop x14, x15
114 pop x16, x17
115 pop x18, x19
116 pop x20, x21
117 pop x22, x23
118 pop x24, x25
119 pop x26, x27
120 pop x28, x29
121 ldr lr, [sp], #S_FRAME_SIZE - S_LR // load LR and restore SP
122 eret // return to kernel
123 .endm
124
125 .macro get_thread_info, rd
126 mov \rd, sp
Feng Kan845ad052013-07-23 18:52:31 +0100127 and \rd, \rd, #~(THREAD_SIZE - 1) // top of stack
Catalin Marinas60ffc302012-03-05 11:49:27 +0000128 .endm
129
130/*
131 * These are the registers used in the syscall handler, and allow us to
132 * have in theory up to 7 arguments to a function - x0 to x6.
133 *
134 * x7 is reserved for the system call number in 32-bit mode.
135 */
136sc_nr .req x25 // number of system calls
137scno .req x26 // syscall number
138stbl .req x27 // syscall table pointer
139tsk .req x28 // current thread_info
140
141/*
142 * Interrupt handling.
143 */
144 .macro irq_handler
145 ldr x1, handle_arch_irq
146 mov x0, sp
147 blr x1
148 .endm
149
150 .text
151
152/*
153 * Exception vectors.
154 */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000155
156 .align 11
157ENTRY(vectors)
158 ventry el1_sync_invalid // Synchronous EL1t
159 ventry el1_irq_invalid // IRQ EL1t
160 ventry el1_fiq_invalid // FIQ EL1t
161 ventry el1_error_invalid // Error EL1t
162
163 ventry el1_sync // Synchronous EL1h
164 ventry el1_irq // IRQ EL1h
165 ventry el1_fiq_invalid // FIQ EL1h
166 ventry el1_error_invalid // Error EL1h
167
168 ventry el0_sync // Synchronous 64-bit EL0
169 ventry el0_irq // IRQ 64-bit EL0
170 ventry el0_fiq_invalid // FIQ 64-bit EL0
171 ventry el0_error_invalid // Error 64-bit EL0
172
173#ifdef CONFIG_COMPAT
174 ventry el0_sync_compat // Synchronous 32-bit EL0
175 ventry el0_irq_compat // IRQ 32-bit EL0
176 ventry el0_fiq_invalid_compat // FIQ 32-bit EL0
177 ventry el0_error_invalid_compat // Error 32-bit EL0
178#else
179 ventry el0_sync_invalid // Synchronous 32-bit EL0
180 ventry el0_irq_invalid // IRQ 32-bit EL0
181 ventry el0_fiq_invalid // FIQ 32-bit EL0
182 ventry el0_error_invalid // Error 32-bit EL0
183#endif
184END(vectors)
185
186/*
187 * Invalid mode handlers
188 */
189 .macro inv_entry, el, reason, regsize = 64
190 kernel_entry el, \regsize
191 mov x0, sp
192 mov x1, #\reason
193 mrs x2, esr_el1
194 b bad_mode
195 .endm
196
197el0_sync_invalid:
198 inv_entry 0, BAD_SYNC
199ENDPROC(el0_sync_invalid)
200
201el0_irq_invalid:
202 inv_entry 0, BAD_IRQ
203ENDPROC(el0_irq_invalid)
204
205el0_fiq_invalid:
206 inv_entry 0, BAD_FIQ
207ENDPROC(el0_fiq_invalid)
208
209el0_error_invalid:
210 inv_entry 0, BAD_ERROR
211ENDPROC(el0_error_invalid)
212
213#ifdef CONFIG_COMPAT
214el0_fiq_invalid_compat:
215 inv_entry 0, BAD_FIQ, 32
216ENDPROC(el0_fiq_invalid_compat)
217
218el0_error_invalid_compat:
219 inv_entry 0, BAD_ERROR, 32
220ENDPROC(el0_error_invalid_compat)
221#endif
222
223el1_sync_invalid:
224 inv_entry 1, BAD_SYNC
225ENDPROC(el1_sync_invalid)
226
227el1_irq_invalid:
228 inv_entry 1, BAD_IRQ
229ENDPROC(el1_irq_invalid)
230
231el1_fiq_invalid:
232 inv_entry 1, BAD_FIQ
233ENDPROC(el1_fiq_invalid)
234
235el1_error_invalid:
236 inv_entry 1, BAD_ERROR
237ENDPROC(el1_error_invalid)
238
239/*
240 * EL1 mode handlers.
241 */
242 .align 6
243el1_sync:
244 kernel_entry 1
245 mrs x1, esr_el1 // read the syndrome register
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100246 lsr x24, x1, #ESR_EL1_EC_SHIFT // exception class
247 cmp x24, #ESR_EL1_EC_DABT_EL1 // data abort in EL1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000248 b.eq el1_da
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100249 cmp x24, #ESR_EL1_EC_SYS64 // configurable trap
Catalin Marinas60ffc302012-03-05 11:49:27 +0000250 b.eq el1_undef
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100251 cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000252 b.eq el1_sp_pc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100253 cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000254 b.eq el1_sp_pc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100255 cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000256 b.eq el1_undef
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100257 cmp x24, #ESR_EL1_EC_BREAKPT_EL1 // debug exception in EL1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000258 b.ge el1_dbg
259 b el1_inv
260el1_da:
261 /*
262 * Data abort handling
263 */
264 mrs x0, far_el1
Will Deacon2a283072014-04-29 19:04:06 +0100265 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000266 // re-enable interrupts if they were enabled in the aborted context
267 tbnz x23, #7, 1f // PSR_I_BIT
268 enable_irq
2691:
270 mov x2, sp // struct pt_regs
271 bl do_mem_abort
272
273 // disable interrupts before pulling preserved data off the stack
274 disable_irq
275 kernel_exit 1
276el1_sp_pc:
277 /*
278 * Stack or PC alignment exception handling
279 */
280 mrs x0, far_el1
Will Deacon2a283072014-04-29 19:04:06 +0100281 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000282 mov x2, sp
283 b do_sp_pc_abort
284el1_undef:
285 /*
286 * Undefined instruction
287 */
Will Deacon2a283072014-04-29 19:04:06 +0100288 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000289 mov x0, sp
290 b do_undefinstr
291el1_dbg:
292 /*
293 * Debug exception handling
294 */
Sandeepa Prabhuee6214c2013-12-04 05:50:20 +0000295 cmp x24, #ESR_EL1_EC_BRK64 // if BRK64
296 cinc x24, x24, eq // set bit '0'
Catalin Marinas60ffc302012-03-05 11:49:27 +0000297 tbz x24, #0, el1_inv // EL1 only
298 mrs x0, far_el1
299 mov x2, sp // struct pt_regs
300 bl do_debug_exception
Will Deacon2a283072014-04-29 19:04:06 +0100301 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000302 kernel_exit 1
303el1_inv:
304 // TODO: add support for undefined instructions in kernel mode
Will Deacon2a283072014-04-29 19:04:06 +0100305 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000306 mov x0, sp
307 mov x1, #BAD_SYNC
308 mrs x2, esr_el1
309 b bad_mode
310ENDPROC(el1_sync)
311
312 .align 6
313el1_irq:
314 kernel_entry 1
Will Deacon2a283072014-04-29 19:04:06 +0100315 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000316#ifdef CONFIG_TRACE_IRQFLAGS
317 bl trace_hardirqs_off
318#endif
Marc Zyngier64681782013-11-12 17:11:53 +0000319
320 irq_handler
321
Catalin Marinas60ffc302012-03-05 11:49:27 +0000322#ifdef CONFIG_PREEMPT
323 get_thread_info tsk
Neil Zhang883c0572014-01-13 08:57:56 +0000324 ldr w24, [tsk, #TI_PREEMPT] // get preempt count
Marc Zyngier717321f2013-11-04 20:14:58 +0000325 cbnz w24, 1f // preempt count != 0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000326 ldr x0, [tsk, #TI_FLAGS] // get flags
327 tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
328 bl el1_preempt
3291:
330#endif
331#ifdef CONFIG_TRACE_IRQFLAGS
332 bl trace_hardirqs_on
333#endif
334 kernel_exit 1
335ENDPROC(el1_irq)
336
337#ifdef CONFIG_PREEMPT
338el1_preempt:
339 mov x24, lr
Will Deacon2a283072014-04-29 19:04:06 +01003401: bl preempt_schedule_irq // irq en/disable is done inside
Catalin Marinas60ffc302012-03-05 11:49:27 +0000341 ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS
342 tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling?
343 ret x24
344#endif
345
346/*
347 * EL0 mode handlers.
348 */
349 .align 6
350el0_sync:
351 kernel_entry 0
352 mrs x25, esr_el1 // read the syndrome register
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100353 lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class
354 cmp x24, #ESR_EL1_EC_SVC64 // SVC in 64-bit state
Catalin Marinas60ffc302012-03-05 11:49:27 +0000355 b.eq el0_svc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100356 cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000357 b.eq el0_da
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100358 cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000359 b.eq el0_ia
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100360 cmp x24, #ESR_EL1_EC_FP_ASIMD // FP/ASIMD access
Catalin Marinas60ffc302012-03-05 11:49:27 +0000361 b.eq el0_fpsimd_acc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100362 cmp x24, #ESR_EL1_EC_FP_EXC64 // FP/ASIMD exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000363 b.eq el0_fpsimd_exc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100364 cmp x24, #ESR_EL1_EC_SYS64 // configurable trap
Catalin Marinas60ffc302012-03-05 11:49:27 +0000365 b.eq el0_undef
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100366 cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000367 b.eq el0_sp_pc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100368 cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000369 b.eq el0_sp_pc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100370 cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000371 b.eq el0_undef
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100372 cmp x24, #ESR_EL1_EC_BREAKPT_EL0 // debug exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000373 b.ge el0_dbg
374 b el0_inv
375
376#ifdef CONFIG_COMPAT
377 .align 6
378el0_sync_compat:
379 kernel_entry 0, 32
380 mrs x25, esr_el1 // read the syndrome register
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100381 lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class
382 cmp x24, #ESR_EL1_EC_SVC32 // SVC in 32-bit state
Catalin Marinas60ffc302012-03-05 11:49:27 +0000383 b.eq el0_svc_compat
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100384 cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000385 b.eq el0_da
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100386 cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000387 b.eq el0_ia
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100388 cmp x24, #ESR_EL1_EC_FP_ASIMD // FP/ASIMD access
Catalin Marinas60ffc302012-03-05 11:49:27 +0000389 b.eq el0_fpsimd_acc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100390 cmp x24, #ESR_EL1_EC_FP_EXC32 // FP/ASIMD exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000391 b.eq el0_fpsimd_exc
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100392 cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000393 b.eq el0_undef
Mark Rutland381cc2b2013-05-24 12:02:35 +0100394 cmp x24, #ESR_EL1_EC_CP15_32 // CP15 MRC/MCR trap
395 b.eq el0_undef
396 cmp x24, #ESR_EL1_EC_CP15_64 // CP15 MRRC/MCRR trap
397 b.eq el0_undef
398 cmp x24, #ESR_EL1_EC_CP14_MR // CP14 MRC/MCR trap
399 b.eq el0_undef
400 cmp x24, #ESR_EL1_EC_CP14_LS // CP14 LDC/STC trap
401 b.eq el0_undef
402 cmp x24, #ESR_EL1_EC_CP14_64 // CP14 MRRC/MCRR trap
403 b.eq el0_undef
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +0100404 cmp x24, #ESR_EL1_EC_BREAKPT_EL0 // debug exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000405 b.ge el0_dbg
406 b el0_inv
407el0_svc_compat:
408 /*
409 * AArch32 syscall handling
410 */
411 adr stbl, compat_sys_call_table // load compat syscall table pointer
412 uxtw scno, w7 // syscall number in w7 (r7)
413 mov sc_nr, #__NR_compat_syscalls
414 b el0_svc_naked
415
416 .align 6
417el0_irq_compat:
418 kernel_entry 0, 32
419 b el0_irq_naked
420#endif
421
422el0_da:
423 /*
424 * Data abort handling
425 */
Larry Bassel6ab64632014-05-30 20:34:14 +0100426 mrs x26, far_el1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000427 // enable interrupts before calling the main handler
Will Deacon2a283072014-04-29 19:04:06 +0100428 enable_dbg_and_irq
Larry Bassel6ab64632014-05-30 20:34:14 +0100429 bic x0, x26, #(0xff << 56)
Catalin Marinas60ffc302012-03-05 11:49:27 +0000430 mov x1, x25
431 mov x2, sp
Larry Bassel6ab64632014-05-30 20:34:14 +0100432 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000433 b do_mem_abort
434el0_ia:
435 /*
436 * Instruction abort handling
437 */
Larry Bassel6ab64632014-05-30 20:34:14 +0100438 mrs x26, far_el1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000439 // enable interrupts before calling the main handler
Will Deacon2a283072014-04-29 19:04:06 +0100440 enable_dbg_and_irq
Larry Bassel6ab64632014-05-30 20:34:14 +0100441 mov x0, x26
Catalin Marinas60ffc302012-03-05 11:49:27 +0000442 orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts
443 mov x2, sp
Larry Bassel6ab64632014-05-30 20:34:14 +0100444 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000445 b do_mem_abort
446el0_fpsimd_acc:
447 /*
448 * Floating Point or Advanced SIMD access
449 */
Will Deacon2a283072014-04-29 19:04:06 +0100450 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000451 mov x0, x25
452 mov x1, sp
Larry Bassel6ab64632014-05-30 20:34:14 +0100453 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000454 b do_fpsimd_acc
455el0_fpsimd_exc:
456 /*
457 * Floating Point or Advanced SIMD exception
458 */
Will Deacon2a283072014-04-29 19:04:06 +0100459 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000460 mov x0, x25
461 mov x1, sp
Larry Bassel6ab64632014-05-30 20:34:14 +0100462 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000463 b do_fpsimd_exc
464el0_sp_pc:
465 /*
466 * Stack or PC alignment exception handling
467 */
Larry Bassel6ab64632014-05-30 20:34:14 +0100468 mrs x26, far_el1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000469 // enable interrupts before calling the main handler
Will Deacon2a283072014-04-29 19:04:06 +0100470 enable_dbg_and_irq
Larry Bassel6ab64632014-05-30 20:34:14 +0100471 mov x0, x26
Catalin Marinas60ffc302012-03-05 11:49:27 +0000472 mov x1, x25
473 mov x2, sp
Larry Bassel6ab64632014-05-30 20:34:14 +0100474 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000475 b do_sp_pc_abort
476el0_undef:
477 /*
478 * Undefined instruction
479 */
Catalin Marinas2600e132013-08-22 11:47:37 +0100480 // enable interrupts before calling the main handler
Will Deacon2a283072014-04-29 19:04:06 +0100481 enable_dbg_and_irq
482 mov x0, sp
Larry Bassel6ab64632014-05-30 20:34:14 +0100483 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000484 b do_undefinstr
485el0_dbg:
486 /*
487 * Debug exception handling
488 */
489 tbnz x24, #0, el0_inv // EL0 only
490 mrs x0, far_el1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000491 mov x1, x25
492 mov x2, sp
Will Deacon2a283072014-04-29 19:04:06 +0100493 bl do_debug_exception
494 enable_dbg
495 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000496el0_inv:
Will Deacon2a283072014-04-29 19:04:06 +0100497 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000498 mov x0, sp
499 mov x1, #BAD_SYNC
500 mrs x2, esr_el1
Larry Bassel6ab64632014-05-30 20:34:14 +0100501 adr lr, ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000502 b bad_mode
503ENDPROC(el0_sync)
504
505 .align 6
506el0_irq:
507 kernel_entry 0
508el0_irq_naked:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000509 enable_dbg
510#ifdef CONFIG_TRACE_IRQFLAGS
511 bl trace_hardirqs_off
512#endif
Marc Zyngier64681782013-11-12 17:11:53 +0000513
Catalin Marinas60ffc302012-03-05 11:49:27 +0000514 irq_handler
Marc Zyngier64681782013-11-12 17:11:53 +0000515
Catalin Marinas60ffc302012-03-05 11:49:27 +0000516#ifdef CONFIG_TRACE_IRQFLAGS
517 bl trace_hardirqs_on
518#endif
519 b ret_to_user
520ENDPROC(el0_irq)
521
522/*
Catalin Marinas60ffc302012-03-05 11:49:27 +0000523 * Register switch for AArch64. The callee-saved registers need to be saved
524 * and restored. On entry:
525 * x0 = previous task_struct (must be preserved across the switch)
526 * x1 = next task_struct
527 * Previous and next are guaranteed not to be the same.
528 *
529 */
530ENTRY(cpu_switch_to)
531 add x8, x0, #THREAD_CPU_CONTEXT
532 mov x9, sp
533 stp x19, x20, [x8], #16 // store callee-saved registers
534 stp x21, x22, [x8], #16
535 stp x23, x24, [x8], #16
536 stp x25, x26, [x8], #16
537 stp x27, x28, [x8], #16
538 stp x29, x9, [x8], #16
539 str lr, [x8]
540 add x8, x1, #THREAD_CPU_CONTEXT
541 ldp x19, x20, [x8], #16 // restore callee-saved registers
542 ldp x21, x22, [x8], #16
543 ldp x23, x24, [x8], #16
544 ldp x25, x26, [x8], #16
545 ldp x27, x28, [x8], #16
546 ldp x29, x9, [x8], #16
547 ldr lr, [x8]
548 mov sp, x9
549 ret
550ENDPROC(cpu_switch_to)
551
552/*
553 * This is the fast syscall return path. We do as little as possible here,
554 * and this includes saving x0 back into the kernel stack.
555 */
556ret_fast_syscall:
557 disable_irq // disable interrupts
558 ldr x1, [tsk, #TI_FLAGS]
559 and x2, x1, #_TIF_WORK_MASK
560 cbnz x2, fast_work_pending
Will Deacon2a283072014-04-29 19:04:06 +0100561 enable_step_tsk x1, x2
Catalin Marinas60ffc302012-03-05 11:49:27 +0000562 kernel_exit 0, ret = 1
563
564/*
565 * Ok, we need to do extra processing, enter the slow path.
566 */
567fast_work_pending:
568 str x0, [sp, #S_X0] // returned x0
569work_pending:
570 tbnz x1, #TIF_NEED_RESCHED, work_resched
Ard Biesheuvel005f78c2014-05-08 11:20:23 +0200571 /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000572 ldr x2, [sp, #S_PSTATE]
573 mov x0, sp // 'regs'
574 tst x2, #PSR_MODE_MASK // user mode regs?
575 b.ne no_work_pending // returning to kernel
Catalin Marinas6916fd02012-10-08 18:04:21 +0100576 enable_irq // enable interrupts for do_notify_resume()
Catalin Marinas60ffc302012-03-05 11:49:27 +0000577 bl do_notify_resume
578 b ret_to_user
579work_resched:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000580 bl schedule
581
582/*
583 * "slow" syscall return path.
584 */
Catalin Marinas59dc67b2012-09-10 16:11:46 +0100585ret_to_user:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000586 disable_irq // disable interrupts
587 ldr x1, [tsk, #TI_FLAGS]
588 and x2, x1, #_TIF_WORK_MASK
589 cbnz x2, work_pending
Will Deacon2a283072014-04-29 19:04:06 +0100590 enable_step_tsk x1, x2
Catalin Marinas60ffc302012-03-05 11:49:27 +0000591no_work_pending:
592 kernel_exit 0, ret = 0
593ENDPROC(ret_to_user)
594
595/*
596 * This is how we return from a fork.
597 */
598ENTRY(ret_from_fork)
599 bl schedule_tail
Catalin Marinasc34501d2012-10-05 12:31:20 +0100600 cbz x19, 1f // not a kernel thread
601 mov x0, x20
602 blr x19
6031: get_thread_info tsk
Catalin Marinas60ffc302012-03-05 11:49:27 +0000604 b ret_to_user
605ENDPROC(ret_from_fork)
606
607/*
608 * SVC handler.
609 */
610 .align 6
611el0_svc:
612 adrp stbl, sys_call_table // load syscall table pointer
613 uxtw scno, w8 // syscall number in w8
614 mov sc_nr, #__NR_syscalls
615el0_svc_naked: // compat entry point
616 stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
Will Deacon2a283072014-04-29 19:04:06 +0100617 enable_dbg_and_irq
Catalin Marinas60ffc302012-03-05 11:49:27 +0000618
AKASHI Takahiro449f81a2014-04-30 10:51:29 +0100619 ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks
620 tst x16, #_TIF_SYSCALL_WORK
621 b.ne __sys_trace
Catalin Marinas60ffc302012-03-05 11:49:27 +0000622 adr lr, ret_fast_syscall // return address
623 cmp scno, sc_nr // check upper syscall limit
624 b.hs ni_sys
625 ldr x16, [stbl, scno, lsl #3] // address in the syscall table
626 br x16 // call sys_* routine
627ni_sys:
628 mov x0, sp
629 b do_ni_syscall
630ENDPROC(el0_svc)
631
632 /*
633 * This is the really slow path. We're going to be doing context
634 * switches, and waiting for our parent to respond.
635 */
636__sys_trace:
AKASHI Takahiro31578582014-04-30 10:51:30 +0100637 mov x0, sp
638 bl syscall_trace_enter
Catalin Marinas60ffc302012-03-05 11:49:27 +0000639 adr lr, __sys_trace_return // return address
640 uxtw scno, w0 // syscall number (possibly new)
641 mov x1, sp // pointer to regs
642 cmp scno, sc_nr // check upper syscall limit
643 b.hs ni_sys
644 ldp x0, x1, [sp] // restore the syscall args
645 ldp x2, x3, [sp, #S_X2]
646 ldp x4, x5, [sp, #S_X4]
647 ldp x6, x7, [sp, #S_X6]
648 ldr x16, [stbl, scno, lsl #3] // address in the syscall table
649 br x16 // call sys_* routine
650
651__sys_trace_return:
652 str x0, [sp] // save returned x0
AKASHI Takahiro31578582014-04-30 10:51:30 +0100653 mov x0, sp
654 bl syscall_trace_exit
Catalin Marinas60ffc302012-03-05 11:49:27 +0000655 b ret_to_user
656
657/*
658 * Special system call wrappers.
659 */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000660ENTRY(sys_rt_sigreturn_wrapper)
661 mov x0, sp
662 b sys_rt_sigreturn
663ENDPROC(sys_rt_sigreturn_wrapper)
664
Catalin Marinas60ffc302012-03-05 11:49:27 +0000665ENTRY(handle_arch_irq)
666 .quad 0