blob: ca978d7d98eb49e5d1ecdbf769b36311ed38586e [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
Marc Zyngierbe3316302018-07-20 10:56:22 +010021#include <linux/arm-smccc.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000022#include <linux/init.h>
23#include <linux/linkage.h>
24
Marc Zyngier8d883b22015-06-01 10:47:41 +010025#include <asm/alternative.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000026#include <asm/assembler.h>
27#include <asm/asm-offsets.h>
Will Deacon905e8c52015-03-23 19:07:02 +000028#include <asm/cpufeature.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000029#include <asm/errno.h>
Marc Zyngier5c1ce6f2013-04-08 17:17:03 +010030#include <asm/esr.h>
James Morse8e23dac2015-12-04 11:02:27 +000031#include <asm/irq.h>
James Morsee19a6ee2016-06-20 18:28:01 +010032#include <asm/memory.h>
Will Deacon78a0cec2018-04-03 12:09:04 +010033#include <asm/mmu.h>
Mark Rutland27eeced2018-04-12 12:10:59 +010034#include <asm/processor.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000035#include <asm/thread_info.h>
Kristina Martsenko9e09d902017-06-06 20:14:10 +010036#include <asm/asm-uaccess.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000037#include <asm/unistd.h>
Will Deacon78a0cec2018-04-03 12:09:04 +010038#include <asm/kernel-pgtable.h>
Catalin Marinas60ffc302012-03-05 11:49:27 +000039
40/*
Larry Bassel6c81fe72014-05-30 12:34:15 -070041 * Context tracking subsystem. Used to instrument transitions
42 * between user and kernel mode.
43 */
44 .macro ct_user_exit, syscall = 0
45#ifdef CONFIG_CONTEXT_TRACKING
46 bl context_tracking_user_exit
47 .if \syscall == 1
48 /*
49 * Save/restore needed during syscalls. Restore syscall arguments from
50 * the values already saved on stack during kernel_entry.
51 */
52 ldp x0, x1, [sp]
53 ldp x2, x3, [sp, #S_X2]
54 ldp x4, x5, [sp, #S_X4]
55 ldp x6, x7, [sp, #S_X6]
56 .endif
57#endif
58 .endm
59
60 .macro ct_user_enter
61#ifdef CONFIG_CONTEXT_TRACKING
62 bl context_tracking_user_enter
63#endif
64 .endm
65
66/*
Catalin Marinas60ffc302012-03-05 11:49:27 +000067 * Bad Abort numbers
68 *-----------------
69 */
70#define BAD_SYNC 0
71#define BAD_IRQ 1
72#define BAD_FIQ 2
73#define BAD_ERROR 3
74
Will Deacond0b3c712018-04-03 12:09:06 +010075 .macro kernel_ventry, el, label, regsize = 64
Mark Rutlande355d4b2018-04-03 12:09:02 +010076 .align 7
Will Deaconded93ce2018-04-03 12:09:07 +010077#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
Will Deaconbfca1572018-04-03 12:09:09 +010078alternative_if ARM64_UNMAP_KERNEL_AT_EL0
Will Deaconded93ce2018-04-03 12:09:07 +010079 .if \el == 0
80 .if \regsize == 64
81 mrs x30, tpidrro_el0
82 msr tpidrro_el0, xzr
83 .else
84 mov x30, xzr
85 .endif
86 .endif
Will Deaconbfca1572018-04-03 12:09:09 +010087alternative_else_nop_endif
Will Deaconded93ce2018-04-03 12:09:07 +010088#endif
89
Will Deacon63648dd2014-09-29 12:26:41 +010090 sub sp, sp, #S_FRAME_SIZE
Will Deacond0b3c712018-04-03 12:09:06 +010091 b el\()\el\()_\label
Mark Rutlande355d4b2018-04-03 12:09:02 +010092 .endm
93
Will Deaconded93ce2018-04-03 12:09:07 +010094 .macro tramp_alias, dst, sym
95 mov_q \dst, TRAMP_VALIAS
96 add \dst, \dst, #(\sym - .entry.tramp.text)
97 .endm
98
Marc Zyngierbe3316302018-07-20 10:56:22 +010099 // This macro corrupts x0-x3. It is the caller's duty
100 // to save/restore them if required.
Marc Zyngierd8174bd2018-07-20 10:56:23 +0100101 .macro apply_ssbd, state, targ, tmp1, tmp2
Marc Zyngierbe3316302018-07-20 10:56:22 +0100102#ifdef CONFIG_ARM64_SSBD
Marc Zyngier42f967d2018-07-20 10:56:27 +0100103alternative_cb arm64_enable_wa2_handling
104 b \targ
105alternative_cb_end
Marc Zyngierd8174bd2018-07-20 10:56:23 +0100106 ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1
107 cbz \tmp2, \targ
Marc Zyngiercf14b892018-07-20 10:56:29 +0100108 ldr \tmp2, [tsk, #TI_FLAGS]
109 tbnz \tmp2, #TIF_SSBD, \targ
Marc Zyngierbe3316302018-07-20 10:56:22 +0100110 mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
111 mov w1, #\state
112alternative_cb arm64_update_smccc_conduit
113 nop // Patched to SMC/HVC #0
114alternative_cb_end
115#endif
116 .endm
117
Mark Rutlande355d4b2018-04-03 12:09:02 +0100118 .macro kernel_entry, el, regsize = 64
Catalin Marinas60ffc302012-03-05 11:49:27 +0000119 .if \regsize == 32
120 mov w0, w0 // zero upper 32 bits of x0
121 .endif
Will Deacon63648dd2014-09-29 12:26:41 +0100122 stp x0, x1, [sp, #16 * 0]
123 stp x2, x3, [sp, #16 * 1]
124 stp x4, x5, [sp, #16 * 2]
125 stp x6, x7, [sp, #16 * 3]
126 stp x8, x9, [sp, #16 * 4]
127 stp x10, x11, [sp, #16 * 5]
128 stp x12, x13, [sp, #16 * 6]
129 stp x14, x15, [sp, #16 * 7]
130 stp x16, x17, [sp, #16 * 8]
131 stp x18, x19, [sp, #16 * 9]
132 stp x20, x21, [sp, #16 * 10]
133 stp x22, x23, [sp, #16 * 11]
134 stp x24, x25, [sp, #16 * 12]
135 stp x26, x27, [sp, #16 * 13]
136 stp x28, x29, [sp, #16 * 14]
137
Catalin Marinas60ffc302012-03-05 11:49:27 +0000138 .if \el == 0
139 mrs x21, sp_el0
Jungseok Lee6cdf9c72015-12-04 11:02:25 +0000140 mov tsk, sp
141 and tsk, tsk, #~(THREAD_SIZE - 1) // Ensure MDSCR_EL1.SS is clear,
Will Deacon2a283072014-04-29 19:04:06 +0100142 ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug
143 disable_step_tsk x19, x20 // exceptions when scheduling.
James Morse49003a82015-12-10 10:22:41 +0000144
Marc Zyngierd8174bd2018-07-20 10:56:23 +0100145 apply_ssbd 1, 1f, x22, x23
Marc Zyngierbe3316302018-07-20 10:56:22 +0100146
147#ifdef CONFIG_ARM64_SSBD
148 ldp x0, x1, [sp, #16 * 0]
149 ldp x2, x3, [sp, #16 * 1]
150#endif
Marc Zyngierd8174bd2018-07-20 10:56:23 +01001511:
Marc Zyngierbe3316302018-07-20 10:56:22 +0100152
James Morse49003a82015-12-10 10:22:41 +0000153 mov x29, xzr // fp pointed to user-space
Catalin Marinas60ffc302012-03-05 11:49:27 +0000154 .else
155 add x21, sp, #S_FRAME_SIZE
James Morsee19a6ee2016-06-20 18:28:01 +0100156 get_thread_info tsk
Mark Rutlandc9100862018-04-12 12:11:00 +0100157 /* Save the task's original addr_limit and set USER_DS */
James Morsee19a6ee2016-06-20 18:28:01 +0100158 ldr x20, [tsk, #TI_ADDR_LIMIT]
159 str x20, [sp, #S_ORIG_ADDR_LIMIT]
Mark Rutlandc9100862018-04-12 12:11:00 +0100160 mov x20, #USER_DS
James Morsee19a6ee2016-06-20 18:28:01 +0100161 str x20, [tsk, #TI_ADDR_LIMIT]
Vladimir Murzin563cada2016-09-01 14:35:59 +0100162 /* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
James Morsee19a6ee2016-06-20 18:28:01 +0100163 .endif /* \el == 0 */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000164 mrs x22, elr_el1
165 mrs x23, spsr_el1
166 stp lr, x21, [sp, #S_LR]
167 stp x22, x23, [sp, #S_PC]
168
169 /*
170 * Set syscallno to -1 by default (overridden later if real syscall).
171 */
172 .if \el == 0
173 mvn x21, xzr
174 str x21, [sp, #S_SYSCALLNO]
175 .endif
176
177 /*
Jungseok Lee6cdf9c72015-12-04 11:02:25 +0000178 * Set sp_el0 to current thread_info.
179 */
180 .if \el == 0
181 msr sp_el0, tsk
182 .endif
183
184 /*
Catalin Marinas60ffc302012-03-05 11:49:27 +0000185 * Registers that may be useful after this macro is invoked:
186 *
187 * x21 - aborted SP
188 * x22 - aborted PC
189 * x23 - aborted PSTATE
190 */
191 .endm
192
Will Deacon412fcb62015-08-19 15:57:09 +0100193 .macro kernel_exit, el
James Morsee19a6ee2016-06-20 18:28:01 +0100194 .if \el != 0
195 /* Restore the task's original addr_limit. */
196 ldr x20, [sp, #S_ORIG_ADDR_LIMIT]
197 str x20, [tsk, #TI_ADDR_LIMIT]
198
199 /* No need to restore UAO, it will be restored from SPSR_EL1 */
200 .endif
201
Catalin Marinas60ffc302012-03-05 11:49:27 +0000202 ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
203 .if \el == 0
Larry Bassel6c81fe72014-05-30 12:34:15 -0700204 ct_user_enter
Catalin Marinas60ffc302012-03-05 11:49:27 +0000205 ldr x23, [sp, #S_SP] // load return stack pointer
Catalin Marinas60ffc302012-03-05 11:49:27 +0000206 msr sp_el0, x23
Will Deaconded93ce2018-04-03 12:09:07 +0100207 tst x22, #PSR_MODE32_BIT // native task?
208 b.eq 3f
209
Will Deacon905e8c52015-03-23 19:07:02 +0000210#ifdef CONFIG_ARM64_ERRATUM_845719
Mark Rutland6ba3b552016-09-07 11:07:09 +0100211alternative_if ARM64_WORKAROUND_845719
Daniel Thompsone28cabf2015-07-22 12:21:03 +0100212#ifdef CONFIG_PID_IN_CONTEXTIDR
213 mrs x29, contextidr_el1
214 msr contextidr_el1, x29
215#else
216 msr contextidr_el1, xzr
217#endif
Mark Rutland6ba3b552016-09-07 11:07:09 +0100218alternative_else_nop_endif
Will Deacon905e8c52015-03-23 19:07:02 +0000219#endif
Will Deaconded93ce2018-04-03 12:09:07 +01002203:
Marc Zyngierd8174bd2018-07-20 10:56:23 +0100221 apply_ssbd 0, 5f, x0, x1
2225:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000223 .endif
Will Deacon63648dd2014-09-29 12:26:41 +0100224 msr elr_el1, x21 // set up the return data
225 msr spsr_el1, x22
Will Deacon63648dd2014-09-29 12:26:41 +0100226 ldp x0, x1, [sp, #16 * 0]
Will Deacon63648dd2014-09-29 12:26:41 +0100227 ldp x2, x3, [sp, #16 * 1]
228 ldp x4, x5, [sp, #16 * 2]
229 ldp x6, x7, [sp, #16 * 3]
230 ldp x8, x9, [sp, #16 * 4]
231 ldp x10, x11, [sp, #16 * 5]
232 ldp x12, x13, [sp, #16 * 6]
233 ldp x14, x15, [sp, #16 * 7]
234 ldp x16, x17, [sp, #16 * 8]
235 ldp x18, x19, [sp, #16 * 9]
236 ldp x20, x21, [sp, #16 * 10]
237 ldp x22, x23, [sp, #16 * 11]
238 ldp x24, x25, [sp, #16 * 12]
239 ldp x26, x27, [sp, #16 * 13]
240 ldp x28, x29, [sp, #16 * 14]
241 ldr lr, [sp, #S_LR]
242 add sp, sp, #S_FRAME_SIZE // restore sp
Will Deaconded93ce2018-04-03 12:09:07 +0100243
Will Deaconded93ce2018-04-03 12:09:07 +0100244 .if \el == 0
Will Deaconbfca1572018-04-03 12:09:09 +0100245alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
246#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
Will Deaconded93ce2018-04-03 12:09:07 +0100247 bne 4f
248 msr far_el1, x30
249 tramp_alias x30, tramp_exit_native
250 br x30
2514:
252 tramp_alias x30, tramp_exit_compat
253 br x30
Will Deaconbfca1572018-04-03 12:09:09 +0100254#endif
Will Deaconded93ce2018-04-03 12:09:07 +0100255 .else
256 eret
257 .endif
Catalin Marinas60ffc302012-03-05 11:49:27 +0000258 .endm
259
260 .macro get_thread_info, rd
Jungseok Lee6cdf9c72015-12-04 11:02:25 +0000261 mrs \rd, sp_el0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000262 .endm
263
James Morse971c67c2015-12-15 11:21:25 +0000264 .macro irq_stack_entry
James Morse8e23dac2015-12-04 11:02:27 +0000265 mov x19, sp // preserve the original sp
266
James Morse8e23dac2015-12-04 11:02:27 +0000267 /*
James Morsed224a692015-12-18 16:01:47 +0000268 * Compare sp with the current thread_info, if the top
269 * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and
270 * should switch to the irq stack.
James Morse8e23dac2015-12-04 11:02:27 +0000271 */
James Morsed224a692015-12-18 16:01:47 +0000272 and x25, x19, #~(THREAD_SIZE - 1)
273 cmp x25, tsk
274 b.ne 9998f
James Morse8e23dac2015-12-04 11:02:27 +0000275
Mark Rutlandc488ae42018-07-20 10:56:12 +0100276 adr_this_cpu x25, irq_stack, x26
James Morse8e23dac2015-12-04 11:02:27 +0000277 mov x26, #IRQ_STACK_START_SP
278 add x26, x25, x26
James Morsed224a692015-12-18 16:01:47 +0000279
280 /* switch to the irq stack */
James Morse8e23dac2015-12-04 11:02:27 +0000281 mov sp, x26
282
James Morse971c67c2015-12-15 11:21:25 +0000283 /*
284 * Add a dummy stack frame, this non-standard format is fixed up
285 * by unwind_frame()
286 */
287 stp x29, x19, [sp, #-16]!
James Morse8e23dac2015-12-04 11:02:27 +0000288 mov x29, sp
James Morse8e23dac2015-12-04 11:02:27 +0000289
2909998:
291 .endm
292
293 /*
294 * x19 should be preserved between irq_stack_entry and
295 * irq_stack_exit.
296 */
297 .macro irq_stack_exit
298 mov sp, x19
299 .endm
300
Catalin Marinas60ffc302012-03-05 11:49:27 +0000301/*
302 * These are the registers used in the syscall handler, and allow us to
303 * have in theory up to 7 arguments to a function - x0 to x6.
304 *
305 * x7 is reserved for the system call number in 32-bit mode.
306 */
307sc_nr .req x25 // number of system calls
308scno .req x26 // syscall number
309stbl .req x27 // syscall table pointer
310tsk .req x28 // current thread_info
311
312/*
313 * Interrupt handling.
314 */
315 .macro irq_handler
James Morse8e23dac2015-12-04 11:02:27 +0000316 ldr_l x1, handle_arch_irq
Catalin Marinas60ffc302012-03-05 11:49:27 +0000317 mov x0, sp
James Morse971c67c2015-12-15 11:21:25 +0000318 irq_stack_entry
Catalin Marinas60ffc302012-03-05 11:49:27 +0000319 blr x1
James Morse8e23dac2015-12-04 11:02:27 +0000320 irq_stack_exit
Catalin Marinas60ffc302012-03-05 11:49:27 +0000321 .endm
322
323 .text
324
325/*
326 * Exception vectors.
327 */
Pratyush Anand888b3c82016-07-08 12:35:50 -0400328 .pushsection ".entry.text", "ax"
Catalin Marinas60ffc302012-03-05 11:49:27 +0000329
330 .align 11
331ENTRY(vectors)
Will Deacond0b3c712018-04-03 12:09:06 +0100332 kernel_ventry 1, sync_invalid // Synchronous EL1t
333 kernel_ventry 1, irq_invalid // IRQ EL1t
334 kernel_ventry 1, fiq_invalid // FIQ EL1t
335 kernel_ventry 1, error_invalid // Error EL1t
Catalin Marinas60ffc302012-03-05 11:49:27 +0000336
Will Deacond0b3c712018-04-03 12:09:06 +0100337 kernel_ventry 1, sync // Synchronous EL1h
338 kernel_ventry 1, irq // IRQ EL1h
339 kernel_ventry 1, fiq_invalid // FIQ EL1h
340 kernel_ventry 1, error_invalid // Error EL1h
Catalin Marinas60ffc302012-03-05 11:49:27 +0000341
Will Deacond0b3c712018-04-03 12:09:06 +0100342 kernel_ventry 0, sync // Synchronous 64-bit EL0
343 kernel_ventry 0, irq // IRQ 64-bit EL0
344 kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
345 kernel_ventry 0, error_invalid // Error 64-bit EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000346
347#ifdef CONFIG_COMPAT
Will Deacond0b3c712018-04-03 12:09:06 +0100348 kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
349 kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
350 kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0
351 kernel_ventry 0, error_invalid_compat, 32 // Error 32-bit EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000352#else
Will Deacond0b3c712018-04-03 12:09:06 +0100353 kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
354 kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
355 kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
356 kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000357#endif
358END(vectors)
359
360/*
361 * Invalid mode handlers
362 */
363 .macro inv_entry, el, reason, regsize = 64
Ard Biesheuvelb6609502016-03-18 10:58:09 +0100364 kernel_entry \el, \regsize
Catalin Marinas60ffc302012-03-05 11:49:27 +0000365 mov x0, sp
366 mov x1, #\reason
367 mrs x2, esr_el1
368 b bad_mode
369 .endm
370
371el0_sync_invalid:
372 inv_entry 0, BAD_SYNC
373ENDPROC(el0_sync_invalid)
374
375el0_irq_invalid:
376 inv_entry 0, BAD_IRQ
377ENDPROC(el0_irq_invalid)
378
379el0_fiq_invalid:
380 inv_entry 0, BAD_FIQ
381ENDPROC(el0_fiq_invalid)
382
383el0_error_invalid:
384 inv_entry 0, BAD_ERROR
385ENDPROC(el0_error_invalid)
386
387#ifdef CONFIG_COMPAT
388el0_fiq_invalid_compat:
389 inv_entry 0, BAD_FIQ, 32
390ENDPROC(el0_fiq_invalid_compat)
391
392el0_error_invalid_compat:
393 inv_entry 0, BAD_ERROR, 32
394ENDPROC(el0_error_invalid_compat)
395#endif
396
397el1_sync_invalid:
398 inv_entry 1, BAD_SYNC
399ENDPROC(el1_sync_invalid)
400
401el1_irq_invalid:
402 inv_entry 1, BAD_IRQ
403ENDPROC(el1_irq_invalid)
404
405el1_fiq_invalid:
406 inv_entry 1, BAD_FIQ
407ENDPROC(el1_fiq_invalid)
408
409el1_error_invalid:
410 inv_entry 1, BAD_ERROR
411ENDPROC(el1_error_invalid)
412
413/*
414 * EL1 mode handlers.
415 */
416 .align 6
417el1_sync:
418 kernel_entry 1
419 mrs x1, esr_el1 // read the syndrome register
Mark Rutlandaed40e02014-11-24 12:31:40 +0000420 lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class
421 cmp x24, #ESR_ELx_EC_DABT_CUR // data abort in EL1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000422 b.eq el1_da
Laura Abbott9adeb8e2016-08-09 18:25:26 -0700423 cmp x24, #ESR_ELx_EC_IABT_CUR // instruction abort in EL1
424 b.eq el1_ia
Mark Rutlandaed40e02014-11-24 12:31:40 +0000425 cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
Catalin Marinas60ffc302012-03-05 11:49:27 +0000426 b.eq el1_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000427 cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000428 b.eq el1_sp_pc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000429 cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000430 b.eq el1_sp_pc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000431 cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000432 b.eq el1_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000433 cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000434 b.ge el1_dbg
435 b el1_inv
Laura Abbott9adeb8e2016-08-09 18:25:26 -0700436
437el1_ia:
438 /*
439 * Fall through to the Data abort case
440 */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000441el1_da:
442 /*
443 * Data abort handling
444 */
Kristina Martsenko9e09d902017-06-06 20:14:10 +0100445 mrs x3, far_el1
Will Deacon2a283072014-04-29 19:04:06 +0100446 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000447 // re-enable interrupts if they were enabled in the aborted context
448 tbnz x23, #7, 1f // PSR_I_BIT
449 enable_irq
4501:
Kristina Martsenko9e09d902017-06-06 20:14:10 +0100451 clear_address_tag x0, x3
Catalin Marinas60ffc302012-03-05 11:49:27 +0000452 mov x2, sp // struct pt_regs
453 bl do_mem_abort
454
455 // disable interrupts before pulling preserved data off the stack
456 disable_irq
457 kernel_exit 1
458el1_sp_pc:
459 /*
460 * Stack or PC alignment exception handling
461 */
462 mrs x0, far_el1
Will Deacon2a283072014-04-29 19:04:06 +0100463 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000464 mov x2, sp
465 b do_sp_pc_abort
466el1_undef:
467 /*
468 * Undefined instruction
469 */
Will Deacon2a283072014-04-29 19:04:06 +0100470 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000471 mov x0, sp
472 b do_undefinstr
473el1_dbg:
474 /*
475 * Debug exception handling
476 */
Mark Rutlandaed40e02014-11-24 12:31:40 +0000477 cmp x24, #ESR_ELx_EC_BRK64 // if BRK64
Sandeepa Prabhuee6214c2013-12-04 05:50:20 +0000478 cinc x24, x24, eq // set bit '0'
Catalin Marinas60ffc302012-03-05 11:49:27 +0000479 tbz x24, #0, el1_inv // EL1 only
480 mrs x0, far_el1
481 mov x2, sp // struct pt_regs
482 bl do_debug_exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000483 kernel_exit 1
484el1_inv:
485 // TODO: add support for undefined instructions in kernel mode
Will Deacon2a283072014-04-29 19:04:06 +0100486 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000487 mov x0, sp
Mark Rutland1b428042015-07-07 18:00:49 +0100488 mov x2, x1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000489 mov x1, #BAD_SYNC
Catalin Marinas60ffc302012-03-05 11:49:27 +0000490 b bad_mode
491ENDPROC(el1_sync)
492
493 .align 6
494el1_irq:
495 kernel_entry 1
Will Deacon2a283072014-04-29 19:04:06 +0100496 enable_dbg
Catalin Marinas60ffc302012-03-05 11:49:27 +0000497#ifdef CONFIG_TRACE_IRQFLAGS
498 bl trace_hardirqs_off
499#endif
Marc Zyngier64681782013-11-12 17:11:53 +0000500
501 irq_handler
502
Catalin Marinas60ffc302012-03-05 11:49:27 +0000503#ifdef CONFIG_PREEMPT
Neil Zhang883c0572014-01-13 08:57:56 +0000504 ldr w24, [tsk, #TI_PREEMPT] // get preempt count
Marc Zyngier717321f2013-11-04 20:14:58 +0000505 cbnz w24, 1f // preempt count != 0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000506 ldr x0, [tsk, #TI_FLAGS] // get flags
507 tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
508 bl el1_preempt
5091:
510#endif
511#ifdef CONFIG_TRACE_IRQFLAGS
512 bl trace_hardirqs_on
513#endif
514 kernel_exit 1
515ENDPROC(el1_irq)
516
517#ifdef CONFIG_PREEMPT
518el1_preempt:
519 mov x24, lr
Will Deacon2a283072014-04-29 19:04:06 +01005201: bl preempt_schedule_irq // irq en/disable is done inside
Catalin Marinas60ffc302012-03-05 11:49:27 +0000521 ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS
522 tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling?
523 ret x24
524#endif
525
526/*
527 * EL0 mode handlers.
528 */
529 .align 6
530el0_sync:
531 kernel_entry 0
532 mrs x25, esr_el1 // read the syndrome register
Mark Rutlandaed40e02014-11-24 12:31:40 +0000533 lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class
534 cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state
Catalin Marinas60ffc302012-03-05 11:49:27 +0000535 b.eq el0_svc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000536 cmp x24, #ESR_ELx_EC_DABT_LOW // data abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000537 b.eq el0_da
Mark Rutlandaed40e02014-11-24 12:31:40 +0000538 cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000539 b.eq el0_ia
Mark Rutlandaed40e02014-11-24 12:31:40 +0000540 cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
Catalin Marinas60ffc302012-03-05 11:49:27 +0000541 b.eq el0_fpsimd_acc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000542 cmp x24, #ESR_ELx_EC_FP_EXC64 // FP/ASIMD exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000543 b.eq el0_fpsimd_exc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000544 cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
Andre Przywara7dd01ae2016-06-28 18:07:32 +0100545 b.eq el0_sys
Mark Rutlandaed40e02014-11-24 12:31:40 +0000546 cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000547 b.eq el0_sp_pc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000548 cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000549 b.eq el0_sp_pc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000550 cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000551 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000552 cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000553 b.ge el0_dbg
554 b el0_inv
555
556#ifdef CONFIG_COMPAT
557 .align 6
558el0_sync_compat:
559 kernel_entry 0, 32
560 mrs x25, esr_el1 // read the syndrome register
Mark Rutlandaed40e02014-11-24 12:31:40 +0000561 lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class
562 cmp x24, #ESR_ELx_EC_SVC32 // SVC in 32-bit state
Catalin Marinas60ffc302012-03-05 11:49:27 +0000563 b.eq el0_svc_compat
Mark Rutlandaed40e02014-11-24 12:31:40 +0000564 cmp x24, #ESR_ELx_EC_DABT_LOW // data abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000565 b.eq el0_da
Mark Rutlandaed40e02014-11-24 12:31:40 +0000566 cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000567 b.eq el0_ia
Mark Rutlandaed40e02014-11-24 12:31:40 +0000568 cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
Catalin Marinas60ffc302012-03-05 11:49:27 +0000569 b.eq el0_fpsimd_acc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000570 cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
Catalin Marinas60ffc302012-03-05 11:49:27 +0000571 b.eq el0_fpsimd_exc
Mark Salyzyn77f3228f2015-10-13 14:30:51 -0700572 cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
573 b.eq el0_sp_pc
Mark Rutlandaed40e02014-11-24 12:31:40 +0000574 cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000575 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000576 cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap
Mark Rutland381cc2b2013-05-24 12:02:35 +0100577 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000578 cmp x24, #ESR_ELx_EC_CP15_64 // CP15 MRRC/MCRR trap
Mark Rutland381cc2b2013-05-24 12:02:35 +0100579 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000580 cmp x24, #ESR_ELx_EC_CP14_MR // CP14 MRC/MCR trap
Mark Rutland381cc2b2013-05-24 12:02:35 +0100581 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000582 cmp x24, #ESR_ELx_EC_CP14_LS // CP14 LDC/STC trap
Mark Rutland381cc2b2013-05-24 12:02:35 +0100583 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000584 cmp x24, #ESR_ELx_EC_CP14_64 // CP14 MRRC/MCRR trap
Mark Rutland381cc2b2013-05-24 12:02:35 +0100585 b.eq el0_undef
Mark Rutlandaed40e02014-11-24 12:31:40 +0000586 cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000587 b.ge el0_dbg
588 b el0_inv
589el0_svc_compat:
590 /*
591 * AArch32 syscall handling
592 */
Catalin Marinas01564112015-01-06 16:42:32 +0000593 adrp stbl, compat_sys_call_table // load compat syscall table pointer
Catalin Marinas60ffc302012-03-05 11:49:27 +0000594 uxtw scno, w7 // syscall number in w7 (r7)
595 mov sc_nr, #__NR_compat_syscalls
596 b el0_svc_naked
597
598 .align 6
599el0_irq_compat:
600 kernel_entry 0, 32
601 b el0_irq_naked
602#endif
603
604el0_da:
605 /*
606 * Data abort handling
607 */
Larry Bassel6ab64632014-05-30 20:34:14 +0100608 mrs x26, far_el1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000609 // enable interrupts before calling the main handler
Will Deacon2a283072014-04-29 19:04:06 +0100610 enable_dbg_and_irq
Larry Bassel6c81fe72014-05-30 12:34:15 -0700611 ct_user_exit
Kristina Martsenko9e09d902017-06-06 20:14:10 +0100612 clear_address_tag x0, x26
Catalin Marinas60ffc302012-03-05 11:49:27 +0000613 mov x1, x25
614 mov x2, sp
Will Deacond54e81f2014-09-29 11:44:01 +0100615 bl do_mem_abort
616 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000617el0_ia:
618 /*
619 * Instruction abort handling
620 */
Larry Bassel6ab64632014-05-30 20:34:14 +0100621 mrs x26, far_el1
Mark Rutland47320012018-04-12 12:11:13 +0100622 msr daifclr, #(8 | 4 | 1)
623#ifdef CONFIG_TRACE_IRQFLAGS
624 bl trace_hardirqs_off
625#endif
Larry Bassel6c81fe72014-05-30 12:34:15 -0700626 ct_user_exit
Larry Bassel6ab64632014-05-30 20:34:14 +0100627 mov x0, x26
Mark Rutland541ec872016-05-31 12:33:03 +0100628 mov x1, x25
Catalin Marinas60ffc302012-03-05 11:49:27 +0000629 mov x2, sp
Mark Rutland47320012018-04-12 12:11:13 +0100630 bl do_el0_ia_bp_hardening
Will Deacond54e81f2014-09-29 11:44:01 +0100631 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000632el0_fpsimd_acc:
633 /*
634 * Floating Point or Advanced SIMD access
635 */
Will Deacon2a283072014-04-29 19:04:06 +0100636 enable_dbg
Larry Bassel6c81fe72014-05-30 12:34:15 -0700637 ct_user_exit
Catalin Marinas60ffc302012-03-05 11:49:27 +0000638 mov x0, x25
639 mov x1, sp
Will Deacond54e81f2014-09-29 11:44:01 +0100640 bl do_fpsimd_acc
641 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000642el0_fpsimd_exc:
643 /*
644 * Floating Point or Advanced SIMD exception
645 */
Will Deacon2a283072014-04-29 19:04:06 +0100646 enable_dbg
Larry Bassel6c81fe72014-05-30 12:34:15 -0700647 ct_user_exit
Catalin Marinas60ffc302012-03-05 11:49:27 +0000648 mov x0, x25
649 mov x1, sp
Will Deacond54e81f2014-09-29 11:44:01 +0100650 bl do_fpsimd_exc
651 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000652el0_sp_pc:
653 /*
654 * Stack or PC alignment exception handling
655 */
Larry Bassel6ab64632014-05-30 20:34:14 +0100656 mrs x26, far_el1
Mark Rutlande7c3b242018-04-12 12:11:17 +0100657 enable_dbg
658#ifdef CONFIG_TRACE_IRQFLAGS
659 bl trace_hardirqs_off
660#endif
Mark Rutland46b05672015-06-15 16:40:27 +0100661 ct_user_exit
Larry Bassel6ab64632014-05-30 20:34:14 +0100662 mov x0, x26
Catalin Marinas60ffc302012-03-05 11:49:27 +0000663 mov x1, x25
664 mov x2, sp
Will Deacond54e81f2014-09-29 11:44:01 +0100665 bl do_sp_pc_abort
666 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000667el0_undef:
668 /*
669 * Undefined instruction
670 */
Catalin Marinas2600e132013-08-22 11:47:37 +0100671 // enable interrupts before calling the main handler
Will Deacon2a283072014-04-29 19:04:06 +0100672 enable_dbg_and_irq
Larry Bassel6c81fe72014-05-30 12:34:15 -0700673 ct_user_exit
Will Deacon2a283072014-04-29 19:04:06 +0100674 mov x0, sp
Will Deacond54e81f2014-09-29 11:44:01 +0100675 bl do_undefinstr
676 b ret_to_user
Andre Przywara7dd01ae2016-06-28 18:07:32 +0100677el0_sys:
678 /*
679 * System instructions, for trapped cache maintenance instructions
680 */
681 enable_dbg_and_irq
682 ct_user_exit
683 mov x0, x25
684 mov x1, sp
685 bl do_sysinstr
686 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000687el0_dbg:
688 /*
689 * Debug exception handling
690 */
691 tbnz x24, #0, el0_inv // EL0 only
692 mrs x0, far_el1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000693 mov x1, x25
694 mov x2, sp
Will Deacon2a283072014-04-29 19:04:06 +0100695 bl do_debug_exception
696 enable_dbg
Larry Bassel6c81fe72014-05-30 12:34:15 -0700697 ct_user_exit
Will Deacon2a283072014-04-29 19:04:06 +0100698 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000699el0_inv:
Will Deacon2a283072014-04-29 19:04:06 +0100700 enable_dbg
Larry Bassel6c81fe72014-05-30 12:34:15 -0700701 ct_user_exit
Catalin Marinas60ffc302012-03-05 11:49:27 +0000702 mov x0, sp
703 mov x1, #BAD_SYNC
Mark Rutland1b428042015-07-07 18:00:49 +0100704 mov x2, x25
Mark Rutlandde327942017-01-18 17:23:41 +0000705 bl bad_el0_sync
Will Deacond54e81f2014-09-29 11:44:01 +0100706 b ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000707ENDPROC(el0_sync)
708
709 .align 6
710el0_irq:
711 kernel_entry 0
712el0_irq_naked:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000713 enable_dbg
714#ifdef CONFIG_TRACE_IRQFLAGS
715 bl trace_hardirqs_off
716#endif
Marc Zyngier64681782013-11-12 17:11:53 +0000717
Larry Bassel6c81fe72014-05-30 12:34:15 -0700718 ct_user_exit
Mark Rutland34dc20b2018-04-12 12:11:18 +0100719#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
720 tbz x22, #55, 1f
721 bl do_el0_irq_bp_hardening
7221:
723#endif
Catalin Marinas60ffc302012-03-05 11:49:27 +0000724 irq_handler
Marc Zyngier64681782013-11-12 17:11:53 +0000725
Catalin Marinas60ffc302012-03-05 11:49:27 +0000726#ifdef CONFIG_TRACE_IRQFLAGS
727 bl trace_hardirqs_on
728#endif
729 b ret_to_user
730ENDPROC(el0_irq)
731
732/*
Catalin Marinas60ffc302012-03-05 11:49:27 +0000733 * Register switch for AArch64. The callee-saved registers need to be saved
734 * and restored. On entry:
735 * x0 = previous task_struct (must be preserved across the switch)
736 * x1 = next task_struct
737 * Previous and next are guaranteed not to be the same.
738 *
739 */
740ENTRY(cpu_switch_to)
Will Deaconc0d3fce2015-07-20 15:14:53 +0100741 mov x10, #THREAD_CPU_CONTEXT
742 add x8, x0, x10
Catalin Marinas60ffc302012-03-05 11:49:27 +0000743 mov x9, sp
744 stp x19, x20, [x8], #16 // store callee-saved registers
745 stp x21, x22, [x8], #16
746 stp x23, x24, [x8], #16
747 stp x25, x26, [x8], #16
748 stp x27, x28, [x8], #16
749 stp x29, x9, [x8], #16
750 str lr, [x8]
Will Deaconc0d3fce2015-07-20 15:14:53 +0100751 add x8, x1, x10
Catalin Marinas60ffc302012-03-05 11:49:27 +0000752 ldp x19, x20, [x8], #16 // restore callee-saved registers
753 ldp x21, x22, [x8], #16
754 ldp x23, x24, [x8], #16
755 ldp x25, x26, [x8], #16
756 ldp x27, x28, [x8], #16
757 ldp x29, x9, [x8], #16
758 ldr lr, [x8]
759 mov sp, x9
Jungseok Lee6cdf9c72015-12-04 11:02:25 +0000760 and x9, x9, #~(THREAD_SIZE - 1)
761 msr sp_el0, x9
Catalin Marinas60ffc302012-03-05 11:49:27 +0000762 ret
763ENDPROC(cpu_switch_to)
764
765/*
766 * This is the fast syscall return path. We do as little as possible here,
767 * and this includes saving x0 back into the kernel stack.
768 */
769ret_fast_syscall:
770 disable_irq // disable interrupts
Will Deacon412fcb62015-08-19 15:57:09 +0100771 str x0, [sp, #S_X0] // returned x0
Josh Stone04d7e092015-06-05 14:28:03 -0700772 ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing
773 and x2, x1, #_TIF_SYSCALL_WORK
774 cbnz x2, ret_fast_syscall_trace
Catalin Marinas60ffc302012-03-05 11:49:27 +0000775 and x2, x1, #_TIF_WORK_MASK
Will Deacon412fcb62015-08-19 15:57:09 +0100776 cbnz x2, work_pending
Will Deacon2a283072014-04-29 19:04:06 +0100777 enable_step_tsk x1, x2
Will Deacon412fcb62015-08-19 15:57:09 +0100778 kernel_exit 0
Josh Stone04d7e092015-06-05 14:28:03 -0700779ret_fast_syscall_trace:
780 enable_irq // enable interrupts
Will Deacon412fcb62015-08-19 15:57:09 +0100781 b __sys_trace_return_skipped // we already saved x0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000782
783/*
784 * Ok, we need to do extra processing, enter the slow path.
785 */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000786work_pending:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000787 mov x0, sp // 'regs'
Catalin Marinas60ffc302012-03-05 11:49:27 +0000788 bl do_notify_resume
Catalin Marinasdb3899a2015-12-04 12:42:29 +0000789#ifdef CONFIG_TRACE_IRQFLAGS
Chris Metcalf421dd6f2016-07-14 16:48:14 -0400790 bl trace_hardirqs_on // enabled while in userspace
Catalin Marinasdb3899a2015-12-04 12:42:29 +0000791#endif
Chris Metcalf421dd6f2016-07-14 16:48:14 -0400792 ldr x1, [tsk, #TI_FLAGS] // re-check for single-step
793 b finish_ret_to_user
Catalin Marinas60ffc302012-03-05 11:49:27 +0000794/*
795 * "slow" syscall return path.
796 */
Catalin Marinas59dc67b2012-09-10 16:11:46 +0100797ret_to_user:
Catalin Marinas60ffc302012-03-05 11:49:27 +0000798 disable_irq // disable interrupts
799 ldr x1, [tsk, #TI_FLAGS]
800 and x2, x1, #_TIF_WORK_MASK
801 cbnz x2, work_pending
Chris Metcalf421dd6f2016-07-14 16:48:14 -0400802finish_ret_to_user:
Will Deacon2a283072014-04-29 19:04:06 +0100803 enable_step_tsk x1, x2
Will Deacon412fcb62015-08-19 15:57:09 +0100804 kernel_exit 0
Catalin Marinas60ffc302012-03-05 11:49:27 +0000805ENDPROC(ret_to_user)
806
807/*
808 * This is how we return from a fork.
809 */
810ENTRY(ret_from_fork)
811 bl schedule_tail
Catalin Marinasc34501d2012-10-05 12:31:20 +0100812 cbz x19, 1f // not a kernel thread
813 mov x0, x20
814 blr x19
8151: get_thread_info tsk
Catalin Marinas60ffc302012-03-05 11:49:27 +0000816 b ret_to_user
817ENDPROC(ret_from_fork)
818
819/*
820 * SVC handler.
821 */
822 .align 6
823el0_svc:
824 adrp stbl, sys_call_table // load syscall table pointer
825 uxtw scno, w8 // syscall number in w8
826 mov sc_nr, #__NR_syscalls
827el0_svc_naked: // compat entry point
828 stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
Will Deacon2a283072014-04-29 19:04:06 +0100829 enable_dbg_and_irq
Larry Bassel6c81fe72014-05-30 12:34:15 -0700830 ct_user_exit 1
Catalin Marinas60ffc302012-03-05 11:49:27 +0000831
AKASHI Takahiro449f81a2014-04-30 10:51:29 +0100832 ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks
833 tst x16, #_TIF_SYSCALL_WORK
834 b.ne __sys_trace
Catalin Marinas60ffc302012-03-05 11:49:27 +0000835 cmp scno, sc_nr // check upper syscall limit
836 b.hs ni_sys
Mark Rutlandf3ed64a2018-04-12 12:11:02 +0100837 mask_nospec64 scno, sc_nr, x19 // enforce bounds for syscall number
Catalin Marinas60ffc302012-03-05 11:49:27 +0000838 ldr x16, [stbl, scno, lsl #3] // address in the syscall table
Will Deacond54e81f2014-09-29 11:44:01 +0100839 blr x16 // call sys_* routine
840 b ret_fast_syscall
Catalin Marinas60ffc302012-03-05 11:49:27 +0000841ni_sys:
842 mov x0, sp
Will Deacond54e81f2014-09-29 11:44:01 +0100843 bl do_ni_syscall
844 b ret_fast_syscall
Catalin Marinas60ffc302012-03-05 11:49:27 +0000845ENDPROC(el0_svc)
846
847 /*
848 * This is the really slow path. We're going to be doing context
849 * switches, and waiting for our parent to respond.
850 */
851__sys_trace:
AKASHI Takahiro1014c812014-11-28 05:26:35 +0000852 mov w0, #-1 // set default errno for
853 cmp scno, x0 // user-issued syscall(-1)
854 b.ne 1f
855 mov x0, #-ENOSYS
856 str x0, [sp, #S_X0]
8571: mov x0, sp
AKASHI Takahiro31578582014-04-30 10:51:30 +0100858 bl syscall_trace_enter
AKASHI Takahiro1014c812014-11-28 05:26:35 +0000859 cmp w0, #-1 // skip the syscall?
860 b.eq __sys_trace_return_skipped
Catalin Marinas60ffc302012-03-05 11:49:27 +0000861 uxtw scno, w0 // syscall number (possibly new)
862 mov x1, sp // pointer to regs
863 cmp scno, sc_nr // check upper syscall limit
Will Deacond54e81f2014-09-29 11:44:01 +0100864 b.hs __ni_sys_trace
Catalin Marinas60ffc302012-03-05 11:49:27 +0000865 ldp x0, x1, [sp] // restore the syscall args
866 ldp x2, x3, [sp, #S_X2]
867 ldp x4, x5, [sp, #S_X4]
868 ldp x6, x7, [sp, #S_X6]
869 ldr x16, [stbl, scno, lsl #3] // address in the syscall table
Will Deacond54e81f2014-09-29 11:44:01 +0100870 blr x16 // call sys_* routine
Catalin Marinas60ffc302012-03-05 11:49:27 +0000871
872__sys_trace_return:
AKASHI Takahiro1014c812014-11-28 05:26:35 +0000873 str x0, [sp, #S_X0] // save returned x0
874__sys_trace_return_skipped:
AKASHI Takahiro31578582014-04-30 10:51:30 +0100875 mov x0, sp
876 bl syscall_trace_exit
Catalin Marinas60ffc302012-03-05 11:49:27 +0000877 b ret_to_user
878
Will Deacond54e81f2014-09-29 11:44:01 +0100879__ni_sys_trace:
880 mov x0, sp
881 bl do_ni_syscall
882 b __sys_trace_return
883
Pratyush Anand888b3c82016-07-08 12:35:50 -0400884 .popsection // .entry.text
885
Will Deacon78a0cec2018-04-03 12:09:04 +0100886#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
887/*
888 * Exception vectors trampoline.
889 */
890 .pushsection ".entry.tramp.text", "ax"
891
892 .macro tramp_map_kernel, tmp
893 mrs \tmp, ttbr1_el1
894 sub \tmp, \tmp, #SWAPPER_DIR_SIZE
895 bic \tmp, \tmp, #USER_ASID_FLAG
896 msr ttbr1_el1, \tmp
897 .endm
898
899 .macro tramp_unmap_kernel, tmp
900 mrs \tmp, ttbr1_el1
901 add \tmp, \tmp, #SWAPPER_DIR_SIZE
902 orr \tmp, \tmp, #USER_ASID_FLAG
903 msr ttbr1_el1, \tmp
904 /*
Will Deacona80d8e22018-04-03 12:09:22 +0100905 * We avoid running the post_ttbr_update_workaround here because
906 * it's only needed by Cavium ThunderX, which requires KPTI to be
907 * disabled.
Will Deacon78a0cec2018-04-03 12:09:04 +0100908 */
909 .endm
910
911 .macro tramp_ventry, regsize = 64
912 .align 7
9131:
914 .if \regsize == 64
915 msr tpidrro_el0, x30 // Restored in kernel_ventry
916 .endif
Will Deaconf6af5322018-04-03 12:09:11 +0100917 /*
918 * Defend against branch aliasing attacks by pushing a dummy
919 * entry onto the return stack and using a RET instruction to
920 * enter the full-fat kernel vectors.
921 */
922 bl 2f
923 b .
9242:
Will Deacon78a0cec2018-04-03 12:09:04 +0100925 tramp_map_kernel x30
Will Deacon96750422018-04-03 12:09:10 +0100926#ifdef CONFIG_RANDOMIZE_BASE
927 adr x30, tramp_vectors + PAGE_SIZE
928 isb
929 ldr x30, [x30]
930#else
Will Deacon78a0cec2018-04-03 12:09:04 +0100931 ldr x30, =vectors
Will Deacon96750422018-04-03 12:09:10 +0100932#endif
Will Deacon78a0cec2018-04-03 12:09:04 +0100933 prfm plil1strm, [x30, #(1b - tramp_vectors)]
934 msr vbar_el1, x30
935 add x30, x30, #(1b - tramp_vectors)
936 isb
Will Deaconf6af5322018-04-03 12:09:11 +0100937 ret
Will Deacon78a0cec2018-04-03 12:09:04 +0100938 .endm
939
940 .macro tramp_exit, regsize = 64
941 adr x30, tramp_vectors
942 msr vbar_el1, x30
943 tramp_unmap_kernel x30
944 .if \regsize == 64
945 mrs x30, far_el1
946 .endif
947 eret
948 .endm
949
950 .align 11
951ENTRY(tramp_vectors)
952 .space 0x400
953
954 tramp_ventry
955 tramp_ventry
956 tramp_ventry
957 tramp_ventry
958
959 tramp_ventry 32
960 tramp_ventry 32
961 tramp_ventry 32
962 tramp_ventry 32
963END(tramp_vectors)
964
965ENTRY(tramp_exit_native)
966 tramp_exit
967END(tramp_exit_native)
968
969ENTRY(tramp_exit_compat)
970 tramp_exit 32
971END(tramp_exit_compat)
972
973 .ltorg
974 .popsection // .entry.tramp.text
Will Deacon96750422018-04-03 12:09:10 +0100975#ifdef CONFIG_RANDOMIZE_BASE
976 .pushsection ".rodata", "a"
977 .align PAGE_SHIFT
978 .globl __entry_tramp_data_start
979__entry_tramp_data_start:
980 .quad vectors
981 .popsection // .rodata
982#endif /* CONFIG_RANDOMIZE_BASE */
Will Deacon78a0cec2018-04-03 12:09:04 +0100983#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
984
Catalin Marinas60ffc302012-03-05 11:49:27 +0000985/*
986 * Special system call wrappers.
987 */
Catalin Marinas60ffc302012-03-05 11:49:27 +0000988ENTRY(sys_rt_sigreturn_wrapper)
989 mov x0, sp
990 b sys_rt_sigreturn
991ENDPROC(sys_rt_sigreturn_wrapper)