]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm64/kernel/entry.S
Merge branch 'drm-next-4.12' of git://people.freedesktop.org/~agd5f/linux into drm...
[karo-tx-linux.git] / arch / arm64 / kernel / entry.S
1 /*
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/alternative.h>
25 #include <asm/assembler.h>
26 #include <asm/asm-offsets.h>
27 #include <asm/cpufeature.h>
28 #include <asm/errno.h>
29 #include <asm/esr.h>
30 #include <asm/irq.h>
31 #include <asm/memory.h>
32 #include <asm/ptrace.h>
33 #include <asm/thread_info.h>
34 #include <asm/asm-uaccess.h>
35 #include <asm/unistd.h>
36
37 /*
38  * Context tracking subsystem.  Used to instrument transitions
39  * between user and kernel mode.
40  */
41         .macro ct_user_exit, syscall = 0
42 #ifdef CONFIG_CONTEXT_TRACKING
43         bl      context_tracking_user_exit
44         .if \syscall == 1
45         /*
46          * Save/restore needed during syscalls.  Restore syscall arguments from
47          * the values already saved on stack during kernel_entry.
48          */
49         ldp     x0, x1, [sp]
50         ldp     x2, x3, [sp, #S_X2]
51         ldp     x4, x5, [sp, #S_X4]
52         ldp     x6, x7, [sp, #S_X6]
53         .endif
54 #endif
55         .endm
56
57         .macro ct_user_enter
58 #ifdef CONFIG_CONTEXT_TRACKING
59         bl      context_tracking_user_enter
60 #endif
61         .endm
62
63 /*
64  * Bad Abort numbers
65  *-----------------
66  */
67 #define BAD_SYNC        0
68 #define BAD_IRQ         1
69 #define BAD_FIQ         2
70 #define BAD_ERROR       3
71
72         .macro  kernel_entry, el, regsize = 64
73         sub     sp, sp, #S_FRAME_SIZE
74         .if     \regsize == 32
75         mov     w0, w0                          // zero upper 32 bits of x0
76         .endif
77         stp     x0, x1, [sp, #16 * 0]
78         stp     x2, x3, [sp, #16 * 1]
79         stp     x4, x5, [sp, #16 * 2]
80         stp     x6, x7, [sp, #16 * 3]
81         stp     x8, x9, [sp, #16 * 4]
82         stp     x10, x11, [sp, #16 * 5]
83         stp     x12, x13, [sp, #16 * 6]
84         stp     x14, x15, [sp, #16 * 7]
85         stp     x16, x17, [sp, #16 * 8]
86         stp     x18, x19, [sp, #16 * 9]
87         stp     x20, x21, [sp, #16 * 10]
88         stp     x22, x23, [sp, #16 * 11]
89         stp     x24, x25, [sp, #16 * 12]
90         stp     x26, x27, [sp, #16 * 13]
91         stp     x28, x29, [sp, #16 * 14]
92
93         .if     \el == 0
94         mrs     x21, sp_el0
95         ldr_this_cpu    tsk, __entry_task, x20  // Ensure MDSCR_EL1.SS is clear,
96         ldr     x19, [tsk, #TSK_TI_FLAGS]       // since we can unmask debug
97         disable_step_tsk x19, x20               // exceptions when scheduling.
98
99         mov     x29, xzr                        // fp pointed to user-space
100         .else
101         add     x21, sp, #S_FRAME_SIZE
102         get_thread_info tsk
103         /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
104         ldr     x20, [tsk, #TSK_TI_ADDR_LIMIT]
105         str     x20, [sp, #S_ORIG_ADDR_LIMIT]
106         mov     x20, #TASK_SIZE_64
107         str     x20, [tsk, #TSK_TI_ADDR_LIMIT]
108         /* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
109         .endif /* \el == 0 */
110         mrs     x22, elr_el1
111         mrs     x23, spsr_el1
112         stp     lr, x21, [sp, #S_LR]
113
114 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
115         /*
116          * Set the TTBR0 PAN bit in SPSR. When the exception is taken from
117          * EL0, there is no need to check the state of TTBR0_EL1 since
118          * accesses are always enabled.
119          * Note that the meaning of this bit differs from the ARMv8.1 PAN
120          * feature as all TTBR0_EL1 accesses are disabled, not just those to
121          * user mappings.
122          */
123 alternative_if ARM64_HAS_PAN
124         b       1f                              // skip TTBR0 PAN
125 alternative_else_nop_endif
126
127         .if     \el != 0
128         mrs     x21, ttbr0_el1
129         tst     x21, #0xffff << 48              // Check for the reserved ASID
130         orr     x23, x23, #PSR_PAN_BIT          // Set the emulated PAN in the saved SPSR
131         b.eq    1f                              // TTBR0 access already disabled
132         and     x23, x23, #~PSR_PAN_BIT         // Clear the emulated PAN in the saved SPSR
133         .endif
134
135         __uaccess_ttbr0_disable x21
136 1:
137 #endif
138
139         stp     x22, x23, [sp, #S_PC]
140
141         /*
142          * Set syscallno to -1 by default (overridden later if real syscall).
143          */
144         .if     \el == 0
145         mvn     x21, xzr
146         str     x21, [sp, #S_SYSCALLNO]
147         .endif
148
149         /*
150          * Set sp_el0 to current thread_info.
151          */
152         .if     \el == 0
153         msr     sp_el0, tsk
154         .endif
155
156         /*
157          * Registers that may be useful after this macro is invoked:
158          *
159          * x21 - aborted SP
160          * x22 - aborted PC
161          * x23 - aborted PSTATE
162         */
163         .endm
164
165         .macro  kernel_exit, el
166         .if     \el != 0
167         /* Restore the task's original addr_limit. */
168         ldr     x20, [sp, #S_ORIG_ADDR_LIMIT]
169         str     x20, [tsk, #TSK_TI_ADDR_LIMIT]
170
171         /* No need to restore UAO, it will be restored from SPSR_EL1 */
172         .endif
173
174         ldp     x21, x22, [sp, #S_PC]           // load ELR, SPSR
175         .if     \el == 0
176         ct_user_enter
177         .endif
178
179 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
180         /*
181          * Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR
182          * PAN bit checking.
183          */
184 alternative_if ARM64_HAS_PAN
185         b       2f                              // skip TTBR0 PAN
186 alternative_else_nop_endif
187
188         .if     \el != 0
189         tbnz    x22, #22, 1f                    // Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set
190         .endif
191
192         __uaccess_ttbr0_enable x0
193
194         .if     \el == 0
195         /*
196          * Enable errata workarounds only if returning to user. The only
197          * workaround currently required for TTBR0_EL1 changes are for the
198          * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache
199          * corruption).
200          */
201         post_ttbr0_update_workaround
202         .endif
203 1:
204         .if     \el != 0
205         and     x22, x22, #~PSR_PAN_BIT         // ARMv8.0 CPUs do not understand this bit
206         .endif
207 2:
208 #endif
209
210         .if     \el == 0
211         ldr     x23, [sp, #S_SP]                // load return stack pointer
212         msr     sp_el0, x23
213 #ifdef CONFIG_ARM64_ERRATUM_845719
214 alternative_if ARM64_WORKAROUND_845719
215         tbz     x22, #4, 1f
216 #ifdef CONFIG_PID_IN_CONTEXTIDR
217         mrs     x29, contextidr_el1
218         msr     contextidr_el1, x29
219 #else
220         msr contextidr_el1, xzr
221 #endif
222 1:
223 alternative_else_nop_endif
224 #endif
225         .endif
226
227         msr     elr_el1, x21                    // set up the return data
228         msr     spsr_el1, x22
229         ldp     x0, x1, [sp, #16 * 0]
230         ldp     x2, x3, [sp, #16 * 1]
231         ldp     x4, x5, [sp, #16 * 2]
232         ldp     x6, x7, [sp, #16 * 3]
233         ldp     x8, x9, [sp, #16 * 4]
234         ldp     x10, x11, [sp, #16 * 5]
235         ldp     x12, x13, [sp, #16 * 6]
236         ldp     x14, x15, [sp, #16 * 7]
237         ldp     x16, x17, [sp, #16 * 8]
238         ldp     x18, x19, [sp, #16 * 9]
239         ldp     x20, x21, [sp, #16 * 10]
240         ldp     x22, x23, [sp, #16 * 11]
241         ldp     x24, x25, [sp, #16 * 12]
242         ldp     x26, x27, [sp, #16 * 13]
243         ldp     x28, x29, [sp, #16 * 14]
244         ldr     lr, [sp, #S_LR]
245         add     sp, sp, #S_FRAME_SIZE           // restore sp
246         eret                                    // return to kernel
247         .endm
248
249         .macro  irq_stack_entry
250         mov     x19, sp                 // preserve the original sp
251
252         /*
253          * Compare sp with the base of the task stack.
254          * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
255          * and should switch to the irq stack.
256          */
257         ldr     x25, [tsk, TSK_STACK]
258         eor     x25, x25, x19
259         and     x25, x25, #~(THREAD_SIZE - 1)
260         cbnz    x25, 9998f
261
262         adr_this_cpu x25, irq_stack, x26
263         mov     x26, #IRQ_STACK_START_SP
264         add     x26, x25, x26
265
266         /* switch to the irq stack */
267         mov     sp, x26
268
269         /*
270          * Add a dummy stack frame, this non-standard format is fixed up
271          * by unwind_frame()
272          */
273         stp     x29, x19, [sp, #-16]!
274         mov     x29, sp
275
276 9998:
277         .endm
278
279         /*
280          * x19 should be preserved between irq_stack_entry and
281          * irq_stack_exit.
282          */
283         .macro  irq_stack_exit
284         mov     sp, x19
285         .endm
286
287 /*
288  * These are the registers used in the syscall handler, and allow us to
289  * have in theory up to 7 arguments to a function - x0 to x6.
290  *
291  * x7 is reserved for the system call number in 32-bit mode.
292  */
293 sc_nr   .req    x25             // number of system calls
294 scno    .req    x26             // syscall number
295 stbl    .req    x27             // syscall table pointer
296 tsk     .req    x28             // current thread_info
297
298 /*
299  * Interrupt handling.
300  */
301         .macro  irq_handler
302         ldr_l   x1, handle_arch_irq
303         mov     x0, sp
304         irq_stack_entry
305         blr     x1
306         irq_stack_exit
307         .endm
308
309         .text
310
311 /*
312  * Exception vectors.
313  */
314         .pushsection ".entry.text", "ax"
315
316         .align  11
317 ENTRY(vectors)
318         ventry  el1_sync_invalid                // Synchronous EL1t
319         ventry  el1_irq_invalid                 // IRQ EL1t
320         ventry  el1_fiq_invalid                 // FIQ EL1t
321         ventry  el1_error_invalid               // Error EL1t
322
323         ventry  el1_sync                        // Synchronous EL1h
324         ventry  el1_irq                         // IRQ EL1h
325         ventry  el1_fiq_invalid                 // FIQ EL1h
326         ventry  el1_error_invalid               // Error EL1h
327
328         ventry  el0_sync                        // Synchronous 64-bit EL0
329         ventry  el0_irq                         // IRQ 64-bit EL0
330         ventry  el0_fiq_invalid                 // FIQ 64-bit EL0
331         ventry  el0_error_invalid               // Error 64-bit EL0
332
333 #ifdef CONFIG_COMPAT
334         ventry  el0_sync_compat                 // Synchronous 32-bit EL0
335         ventry  el0_irq_compat                  // IRQ 32-bit EL0
336         ventry  el0_fiq_invalid_compat          // FIQ 32-bit EL0
337         ventry  el0_error_invalid_compat        // Error 32-bit EL0
338 #else
339         ventry  el0_sync_invalid                // Synchronous 32-bit EL0
340         ventry  el0_irq_invalid                 // IRQ 32-bit EL0
341         ventry  el0_fiq_invalid                 // FIQ 32-bit EL0
342         ventry  el0_error_invalid               // Error 32-bit EL0
343 #endif
344 END(vectors)
345
346 /*
347  * Invalid mode handlers
348  */
349         .macro  inv_entry, el, reason, regsize = 64
350         kernel_entry \el, \regsize
351         mov     x0, sp
352         mov     x1, #\reason
353         mrs     x2, esr_el1
354         b       bad_mode
355         .endm
356
357 el0_sync_invalid:
358         inv_entry 0, BAD_SYNC
359 ENDPROC(el0_sync_invalid)
360
361 el0_irq_invalid:
362         inv_entry 0, BAD_IRQ
363 ENDPROC(el0_irq_invalid)
364
365 el0_fiq_invalid:
366         inv_entry 0, BAD_FIQ
367 ENDPROC(el0_fiq_invalid)
368
369 el0_error_invalid:
370         inv_entry 0, BAD_ERROR
371 ENDPROC(el0_error_invalid)
372
373 #ifdef CONFIG_COMPAT
374 el0_fiq_invalid_compat:
375         inv_entry 0, BAD_FIQ, 32
376 ENDPROC(el0_fiq_invalid_compat)
377
378 el0_error_invalid_compat:
379         inv_entry 0, BAD_ERROR, 32
380 ENDPROC(el0_error_invalid_compat)
381 #endif
382
383 el1_sync_invalid:
384         inv_entry 1, BAD_SYNC
385 ENDPROC(el1_sync_invalid)
386
387 el1_irq_invalid:
388         inv_entry 1, BAD_IRQ
389 ENDPROC(el1_irq_invalid)
390
391 el1_fiq_invalid:
392         inv_entry 1, BAD_FIQ
393 ENDPROC(el1_fiq_invalid)
394
395 el1_error_invalid:
396         inv_entry 1, BAD_ERROR
397 ENDPROC(el1_error_invalid)
398
399 /*
400  * EL1 mode handlers.
401  */
402         .align  6
403 el1_sync:
404         kernel_entry 1
405         mrs     x1, esr_el1                     // read the syndrome register
406         lsr     x24, x1, #ESR_ELx_EC_SHIFT      // exception class
407         cmp     x24, #ESR_ELx_EC_DABT_CUR       // data abort in EL1
408         b.eq    el1_da
409         cmp     x24, #ESR_ELx_EC_IABT_CUR       // instruction abort in EL1
410         b.eq    el1_ia
411         cmp     x24, #ESR_ELx_EC_SYS64          // configurable trap
412         b.eq    el1_undef
413         cmp     x24, #ESR_ELx_EC_SP_ALIGN       // stack alignment exception
414         b.eq    el1_sp_pc
415         cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
416         b.eq    el1_sp_pc
417         cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL1
418         b.eq    el1_undef
419         cmp     x24, #ESR_ELx_EC_BREAKPT_CUR    // debug exception in EL1
420         b.ge    el1_dbg
421         b       el1_inv
422
423 el1_ia:
424         /*
425          * Fall through to the Data abort case
426          */
427 el1_da:
428         /*
429          * Data abort handling
430          */
431         mrs     x3, far_el1
432         enable_dbg
433         // re-enable interrupts if they were enabled in the aborted context
434         tbnz    x23, #7, 1f                     // PSR_I_BIT
435         enable_irq
436 1:
437         clear_address_tag x0, x3
438         mov     x2, sp                          // struct pt_regs
439         bl      do_mem_abort
440
441         // disable interrupts before pulling preserved data off the stack
442         disable_irq
443         kernel_exit 1
444 el1_sp_pc:
445         /*
446          * Stack or PC alignment exception handling
447          */
448         mrs     x0, far_el1
449         enable_dbg
450         mov     x2, sp
451         b       do_sp_pc_abort
452 el1_undef:
453         /*
454          * Undefined instruction
455          */
456         enable_dbg
457         mov     x0, sp
458         b       do_undefinstr
459 el1_dbg:
460         /*
461          * Debug exception handling
462          */
463         cmp     x24, #ESR_ELx_EC_BRK64          // if BRK64
464         cinc    x24, x24, eq                    // set bit '0'
465         tbz     x24, #0, el1_inv                // EL1 only
466         mrs     x0, far_el1
467         mov     x2, sp                          // struct pt_regs
468         bl      do_debug_exception
469         kernel_exit 1
470 el1_inv:
471         // TODO: add support for undefined instructions in kernel mode
472         enable_dbg
473         mov     x0, sp
474         mov     x2, x1
475         mov     x1, #BAD_SYNC
476         b       bad_mode
477 ENDPROC(el1_sync)
478
479         .align  6
480 el1_irq:
481         kernel_entry 1
482         enable_dbg
483 #ifdef CONFIG_TRACE_IRQFLAGS
484         bl      trace_hardirqs_off
485 #endif
486
487         irq_handler
488
489 #ifdef CONFIG_PREEMPT
490         ldr     w24, [tsk, #TSK_TI_PREEMPT]     // get preempt count
491         cbnz    w24, 1f                         // preempt count != 0
492         ldr     x0, [tsk, #TSK_TI_FLAGS]        // get flags
493         tbz     x0, #TIF_NEED_RESCHED, 1f       // needs rescheduling?
494         bl      el1_preempt
495 1:
496 #endif
497 #ifdef CONFIG_TRACE_IRQFLAGS
498         bl      trace_hardirqs_on
499 #endif
500         kernel_exit 1
501 ENDPROC(el1_irq)
502
503 #ifdef CONFIG_PREEMPT
504 el1_preempt:
505         mov     x24, lr
506 1:      bl      preempt_schedule_irq            // irq en/disable is done inside
507         ldr     x0, [tsk, #TSK_TI_FLAGS]        // get new tasks TI_FLAGS
508         tbnz    x0, #TIF_NEED_RESCHED, 1b       // needs rescheduling?
509         ret     x24
510 #endif
511
512 /*
513  * EL0 mode handlers.
514  */
515         .align  6
516 el0_sync:
517         kernel_entry 0
518         mrs     x25, esr_el1                    // read the syndrome register
519         lsr     x24, x25, #ESR_ELx_EC_SHIFT     // exception class
520         cmp     x24, #ESR_ELx_EC_SVC64          // SVC in 64-bit state
521         b.eq    el0_svc
522         cmp     x24, #ESR_ELx_EC_DABT_LOW       // data abort in EL0
523         b.eq    el0_da
524         cmp     x24, #ESR_ELx_EC_IABT_LOW       // instruction abort in EL0
525         b.eq    el0_ia
526         cmp     x24, #ESR_ELx_EC_FP_ASIMD       // FP/ASIMD access
527         b.eq    el0_fpsimd_acc
528         cmp     x24, #ESR_ELx_EC_FP_EXC64       // FP/ASIMD exception
529         b.eq    el0_fpsimd_exc
530         cmp     x24, #ESR_ELx_EC_SYS64          // configurable trap
531         b.eq    el0_sys
532         cmp     x24, #ESR_ELx_EC_SP_ALIGN       // stack alignment exception
533         b.eq    el0_sp_pc
534         cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
535         b.eq    el0_sp_pc
536         cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL0
537         b.eq    el0_undef
538         cmp     x24, #ESR_ELx_EC_BREAKPT_LOW    // debug exception in EL0
539         b.ge    el0_dbg
540         b       el0_inv
541
542 #ifdef CONFIG_COMPAT
543         .align  6
544 el0_sync_compat:
545         kernel_entry 0, 32
546         mrs     x25, esr_el1                    // read the syndrome register
547         lsr     x24, x25, #ESR_ELx_EC_SHIFT     // exception class
548         cmp     x24, #ESR_ELx_EC_SVC32          // SVC in 32-bit state
549         b.eq    el0_svc_compat
550         cmp     x24, #ESR_ELx_EC_DABT_LOW       // data abort in EL0
551         b.eq    el0_da
552         cmp     x24, #ESR_ELx_EC_IABT_LOW       // instruction abort in EL0
553         b.eq    el0_ia
554         cmp     x24, #ESR_ELx_EC_FP_ASIMD       // FP/ASIMD access
555         b.eq    el0_fpsimd_acc
556         cmp     x24, #ESR_ELx_EC_FP_EXC32       // FP/ASIMD exception
557         b.eq    el0_fpsimd_exc
558         cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
559         b.eq    el0_sp_pc
560         cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL0
561         b.eq    el0_undef
562         cmp     x24, #ESR_ELx_EC_CP15_32        // CP15 MRC/MCR trap
563         b.eq    el0_undef
564         cmp     x24, #ESR_ELx_EC_CP15_64        // CP15 MRRC/MCRR trap
565         b.eq    el0_undef
566         cmp     x24, #ESR_ELx_EC_CP14_MR        // CP14 MRC/MCR trap
567         b.eq    el0_undef
568         cmp     x24, #ESR_ELx_EC_CP14_LS        // CP14 LDC/STC trap
569         b.eq    el0_undef
570         cmp     x24, #ESR_ELx_EC_CP14_64        // CP14 MRRC/MCRR trap
571         b.eq    el0_undef
572         cmp     x24, #ESR_ELx_EC_BREAKPT_LOW    // debug exception in EL0
573         b.ge    el0_dbg
574         b       el0_inv
575 el0_svc_compat:
576         /*
577          * AArch32 syscall handling
578          */
579         adrp    stbl, compat_sys_call_table     // load compat syscall table pointer
580         uxtw    scno, w7                        // syscall number in w7 (r7)
581         mov     sc_nr, #__NR_compat_syscalls
582         b       el0_svc_naked
583
584         .align  6
585 el0_irq_compat:
586         kernel_entry 0, 32
587         b       el0_irq_naked
588 #endif
589
590 el0_da:
591         /*
592          * Data abort handling
593          */
594         mrs     x26, far_el1
595         // enable interrupts before calling the main handler
596         enable_dbg_and_irq
597         ct_user_exit
598         clear_address_tag x0, x26
599         mov     x1, x25
600         mov     x2, sp
601         bl      do_mem_abort
602         b       ret_to_user
603 el0_ia:
604         /*
605          * Instruction abort handling
606          */
607         mrs     x26, far_el1
608         // enable interrupts before calling the main handler
609         enable_dbg_and_irq
610         ct_user_exit
611         mov     x0, x26
612         mov     x1, x25
613         mov     x2, sp
614         bl      do_mem_abort
615         b       ret_to_user
616 el0_fpsimd_acc:
617         /*
618          * Floating Point or Advanced SIMD access
619          */
620         enable_dbg
621         ct_user_exit
622         mov     x0, x25
623         mov     x1, sp
624         bl      do_fpsimd_acc
625         b       ret_to_user
626 el0_fpsimd_exc:
627         /*
628          * Floating Point or Advanced SIMD exception
629          */
630         enable_dbg
631         ct_user_exit
632         mov     x0, x25
633         mov     x1, sp
634         bl      do_fpsimd_exc
635         b       ret_to_user
636 el0_sp_pc:
637         /*
638          * Stack or PC alignment exception handling
639          */
640         mrs     x26, far_el1
641         // enable interrupts before calling the main handler
642         enable_dbg_and_irq
643         ct_user_exit
644         mov     x0, x26
645         mov     x1, x25
646         mov     x2, sp
647         bl      do_sp_pc_abort
648         b       ret_to_user
649 el0_undef:
650         /*
651          * Undefined instruction
652          */
653         // enable interrupts before calling the main handler
654         enable_dbg_and_irq
655         ct_user_exit
656         mov     x0, sp
657         bl      do_undefinstr
658         b       ret_to_user
659 el0_sys:
660         /*
661          * System instructions, for trapped cache maintenance instructions
662          */
663         enable_dbg_and_irq
664         ct_user_exit
665         mov     x0, x25
666         mov     x1, sp
667         bl      do_sysinstr
668         b       ret_to_user
669 el0_dbg:
670         /*
671          * Debug exception handling
672          */
673         tbnz    x24, #0, el0_inv                // EL0 only
674         mrs     x0, far_el1
675         mov     x1, x25
676         mov     x2, sp
677         bl      do_debug_exception
678         enable_dbg
679         ct_user_exit
680         b       ret_to_user
681 el0_inv:
682         enable_dbg
683         ct_user_exit
684         mov     x0, sp
685         mov     x1, #BAD_SYNC
686         mov     x2, x25
687         bl      bad_el0_sync
688         b       ret_to_user
689 ENDPROC(el0_sync)
690
691         .align  6
692 el0_irq:
693         kernel_entry 0
694 el0_irq_naked:
695         enable_dbg
696 #ifdef CONFIG_TRACE_IRQFLAGS
697         bl      trace_hardirqs_off
698 #endif
699
700         ct_user_exit
701         irq_handler
702
703 #ifdef CONFIG_TRACE_IRQFLAGS
704         bl      trace_hardirqs_on
705 #endif
706         b       ret_to_user
707 ENDPROC(el0_irq)
708
709 /*
710  * Register switch for AArch64. The callee-saved registers need to be saved
711  * and restored. On entry:
712  *   x0 = previous task_struct (must be preserved across the switch)
713  *   x1 = next task_struct
714  * Previous and next are guaranteed not to be the same.
715  *
716  */
717 ENTRY(cpu_switch_to)
718         mov     x10, #THREAD_CPU_CONTEXT
719         add     x8, x0, x10
720         mov     x9, sp
721         stp     x19, x20, [x8], #16             // store callee-saved registers
722         stp     x21, x22, [x8], #16
723         stp     x23, x24, [x8], #16
724         stp     x25, x26, [x8], #16
725         stp     x27, x28, [x8], #16
726         stp     x29, x9, [x8], #16
727         str     lr, [x8]
728         add     x8, x1, x10
729         ldp     x19, x20, [x8], #16             // restore callee-saved registers
730         ldp     x21, x22, [x8], #16
731         ldp     x23, x24, [x8], #16
732         ldp     x25, x26, [x8], #16
733         ldp     x27, x28, [x8], #16
734         ldp     x29, x9, [x8], #16
735         ldr     lr, [x8]
736         mov     sp, x9
737         msr     sp_el0, x1
738         ret
739 ENDPROC(cpu_switch_to)
740
741 /*
742  * This is the fast syscall return path.  We do as little as possible here,
743  * and this includes saving x0 back into the kernel stack.
744  */
745 ret_fast_syscall:
746         disable_irq                             // disable interrupts
747         str     x0, [sp, #S_X0]                 // returned x0
748         ldr     x1, [tsk, #TSK_TI_FLAGS]        // re-check for syscall tracing
749         and     x2, x1, #_TIF_SYSCALL_WORK
750         cbnz    x2, ret_fast_syscall_trace
751         and     x2, x1, #_TIF_WORK_MASK
752         cbnz    x2, work_pending
753         enable_step_tsk x1, x2
754         kernel_exit 0
755 ret_fast_syscall_trace:
756         enable_irq                              // enable interrupts
757         b       __sys_trace_return_skipped      // we already saved x0
758
759 /*
760  * Ok, we need to do extra processing, enter the slow path.
761  */
762 work_pending:
763         mov     x0, sp                          // 'regs'
764         bl      do_notify_resume
765 #ifdef CONFIG_TRACE_IRQFLAGS
766         bl      trace_hardirqs_on               // enabled while in userspace
767 #endif
768         ldr     x1, [tsk, #TSK_TI_FLAGS]        // re-check for single-step
769         b       finish_ret_to_user
770 /*
771  * "slow" syscall return path.
772  */
773 ret_to_user:
774         disable_irq                             // disable interrupts
775         ldr     x1, [tsk, #TSK_TI_FLAGS]
776         and     x2, x1, #_TIF_WORK_MASK
777         cbnz    x2, work_pending
778 finish_ret_to_user:
779         enable_step_tsk x1, x2
780         kernel_exit 0
781 ENDPROC(ret_to_user)
782
783 /*
784  * This is how we return from a fork.
785  */
786 ENTRY(ret_from_fork)
787         bl      schedule_tail
788         cbz     x19, 1f                         // not a kernel thread
789         mov     x0, x20
790         blr     x19
791 1:      get_thread_info tsk
792         b       ret_to_user
793 ENDPROC(ret_from_fork)
794
795 /*
796  * SVC handler.
797  */
798         .align  6
799 el0_svc:
800         adrp    stbl, sys_call_table            // load syscall table pointer
801         uxtw    scno, w8                        // syscall number in w8
802         mov     sc_nr, #__NR_syscalls
803 el0_svc_naked:                                  // compat entry point
804         stp     x0, scno, [sp, #S_ORIG_X0]      // save the original x0 and syscall number
805         enable_dbg_and_irq
806         ct_user_exit 1
807
808         ldr     x16, [tsk, #TSK_TI_FLAGS]       // check for syscall hooks
809         tst     x16, #_TIF_SYSCALL_WORK
810         b.ne    __sys_trace
811         cmp     scno, sc_nr                     // check upper syscall limit
812         b.hs    ni_sys
813         ldr     x16, [stbl, scno, lsl #3]       // address in the syscall table
814         blr     x16                             // call sys_* routine
815         b       ret_fast_syscall
816 ni_sys:
817         mov     x0, sp
818         bl      do_ni_syscall
819         b       ret_fast_syscall
820 ENDPROC(el0_svc)
821
822         /*
823          * This is the really slow path.  We're going to be doing context
824          * switches, and waiting for our parent to respond.
825          */
826 __sys_trace:
827         mov     w0, #-1                         // set default errno for
828         cmp     scno, x0                        // user-issued syscall(-1)
829         b.ne    1f
830         mov     x0, #-ENOSYS
831         str     x0, [sp, #S_X0]
832 1:      mov     x0, sp
833         bl      syscall_trace_enter
834         cmp     w0, #-1                         // skip the syscall?
835         b.eq    __sys_trace_return_skipped
836         uxtw    scno, w0                        // syscall number (possibly new)
837         mov     x1, sp                          // pointer to regs
838         cmp     scno, sc_nr                     // check upper syscall limit
839         b.hs    __ni_sys_trace
840         ldp     x0, x1, [sp]                    // restore the syscall args
841         ldp     x2, x3, [sp, #S_X2]
842         ldp     x4, x5, [sp, #S_X4]
843         ldp     x6, x7, [sp, #S_X6]
844         ldr     x16, [stbl, scno, lsl #3]       // address in the syscall table
845         blr     x16                             // call sys_* routine
846
847 __sys_trace_return:
848         str     x0, [sp, #S_X0]                 // save returned x0
849 __sys_trace_return_skipped:
850         mov     x0, sp
851         bl      syscall_trace_exit
852         b       ret_to_user
853
854 __ni_sys_trace:
855         mov     x0, sp
856         bl      do_ni_syscall
857         b       __sys_trace_return
858
859         .popsection                             // .entry.text
860
861 /*
862  * Special system call wrappers.
863  */
864 ENTRY(sys_rt_sigreturn_wrapper)
865         mov     x0, sp
866         b       sys_rt_sigreturn
867 ENDPROC(sys_rt_sigreturn_wrapper)