622a409916f32cefdc4dd7291bf1b708b5ec70bb
[firefly-linux-kernel-4.4.55.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/assembler.h>
25 #include <asm/asm-offsets.h>
26 #include <asm/errno.h>
27 #include <asm/esr.h>
28 #include <asm/thread_info.h>
29 #include <asm/unistd.h>
30
31 /*
32  * Context tracking subsystem.  Used to instrument transitions
33  * between user and kernel mode.
34  */
35         .macro ct_user_exit, syscall = 0
36 #ifdef CONFIG_CONTEXT_TRACKING
37         bl      context_tracking_user_exit
38         .if \syscall == 1
39         /*
40          * Save/restore needed during syscalls.  Restore syscall arguments from
41          * the values already saved on stack during kernel_entry.
42          */
43         ldp     x0, x1, [sp]
44         ldp     x2, x3, [sp, #S_X2]
45         ldp     x4, x5, [sp, #S_X4]
46         ldp     x6, x7, [sp, #S_X6]
47         .endif
48 #endif
49         .endm
50
51         .macro ct_user_enter
52 #ifdef CONFIG_CONTEXT_TRACKING
53         bl      context_tracking_user_enter
54 #endif
55         .endm
56
57 /*
58  * Bad Abort numbers
59  *-----------------
60  */
61 #define BAD_SYNC        0
62 #define BAD_IRQ         1
63 #define BAD_FIQ         2
64 #define BAD_ERROR       3
65
66         .macro  kernel_entry, el, regsize = 64
67         sub     sp, sp, #S_FRAME_SIZE
68         .if     \regsize == 32
69         mov     w0, w0                          // zero upper 32 bits of x0
70         .endif
71         stp     x0, x1, [sp, #16 * 0]
72         stp     x2, x3, [sp, #16 * 1]
73         stp     x4, x5, [sp, #16 * 2]
74         stp     x6, x7, [sp, #16 * 3]
75         stp     x8, x9, [sp, #16 * 4]
76         stp     x10, x11, [sp, #16 * 5]
77         stp     x12, x13, [sp, #16 * 6]
78         stp     x14, x15, [sp, #16 * 7]
79         stp     x16, x17, [sp, #16 * 8]
80         stp     x18, x19, [sp, #16 * 9]
81         stp     x20, x21, [sp, #16 * 10]
82         stp     x22, x23, [sp, #16 * 11]
83         stp     x24, x25, [sp, #16 * 12]
84         stp     x26, x27, [sp, #16 * 13]
85         stp     x28, x29, [sp, #16 * 14]
86
87         .if     \el == 0
88         mrs     x21, sp_el0
89         get_thread_info tsk                     // Ensure MDSCR_EL1.SS is clear,
90         ldr     x19, [tsk, #TI_FLAGS]           // since we can unmask debug
91         disable_step_tsk x19, x20               // exceptions when scheduling.
92         .else
93         add     x21, sp, #S_FRAME_SIZE
94         .endif
95         mrs     x22, elr_el1
96         mrs     x23, spsr_el1
97         stp     lr, x21, [sp, #S_LR]
98         stp     x22, x23, [sp, #S_PC]
99
100         /*
101          * Set syscallno to -1 by default (overridden later if real syscall).
102          */
103         .if     \el == 0
104         mvn     x21, xzr
105         str     x21, [sp, #S_SYSCALLNO]
106         .endif
107
108         /*
109          * Registers that may be useful after this macro is invoked:
110          *
111          * x21 - aborted SP
112          * x22 - aborted PC
113          * x23 - aborted PSTATE
114         */
115         .endm
116
117         .macro  kernel_exit, el, ret = 0
118         ldp     x21, x22, [sp, #S_PC]           // load ELR, SPSR
119         .if     \el == 0
120         ct_user_enter
121         ldr     x23, [sp, #S_SP]                // load return stack pointer
122         msr     sp_el0, x23
123         .endif
124         msr     elr_el1, x21                    // set up the return data
125         msr     spsr_el1, x22
126         .if     \ret
127         ldr     x1, [sp, #S_X1]                 // preserve x0 (syscall return)
128         .else
129         ldp     x0, x1, [sp, #16 * 0]
130         .endif
131         ldp     x2, x3, [sp, #16 * 1]
132         ldp     x4, x5, [sp, #16 * 2]
133         ldp     x6, x7, [sp, #16 * 3]
134         ldp     x8, x9, [sp, #16 * 4]
135         ldp     x10, x11, [sp, #16 * 5]
136         ldp     x12, x13, [sp, #16 * 6]
137         ldp     x14, x15, [sp, #16 * 7]
138         ldp     x16, x17, [sp, #16 * 8]
139         ldp     x18, x19, [sp, #16 * 9]
140         ldp     x20, x21, [sp, #16 * 10]
141         ldp     x22, x23, [sp, #16 * 11]
142         ldp     x24, x25, [sp, #16 * 12]
143         ldp     x26, x27, [sp, #16 * 13]
144         ldp     x28, x29, [sp, #16 * 14]
145         ldr     lr, [sp, #S_LR]
146         add     sp, sp, #S_FRAME_SIZE           // restore sp
147         eret                                    // return to kernel
148         .endm
149
150         .macro  get_thread_info, rd
151         mov     \rd, sp
152         and     \rd, \rd, #~(THREAD_SIZE - 1)   // top of stack
153         .endm
154
155 /*
156  * These are the registers used in the syscall handler, and allow us to
157  * have in theory up to 7 arguments to a function - x0 to x6.
158  *
159  * x7 is reserved for the system call number in 32-bit mode.
160  */
161 sc_nr   .req    x25             // number of system calls
162 scno    .req    x26             // syscall number
163 stbl    .req    x27             // syscall table pointer
164 tsk     .req    x28             // current thread_info
165
166 /*
167  * Interrupt handling.
168  */
169         .macro  irq_handler
170         ldr     x1, handle_arch_irq
171         mov     x0, sp
172         blr     x1
173         .endm
174
175         .text
176
177 /*
178  * Exception vectors.
179  */
180
181         .align  11
182 ENTRY(vectors)
183         ventry  el1_sync_invalid                // Synchronous EL1t
184         ventry  el1_irq_invalid                 // IRQ EL1t
185         ventry  el1_fiq_invalid                 // FIQ EL1t
186         ventry  el1_error_invalid               // Error EL1t
187
188         ventry  el1_sync                        // Synchronous EL1h
189         ventry  el1_irq                         // IRQ EL1h
190         ventry  el1_fiq_invalid                 // FIQ EL1h
191         ventry  el1_error_invalid               // Error EL1h
192
193         ventry  el0_sync                        // Synchronous 64-bit EL0
194         ventry  el0_irq                         // IRQ 64-bit EL0
195         ventry  el0_fiq_invalid                 // FIQ 64-bit EL0
196         ventry  el0_error_invalid               // Error 64-bit EL0
197
198 #ifdef CONFIG_COMPAT
199         ventry  el0_sync_compat                 // Synchronous 32-bit EL0
200         ventry  el0_irq_compat                  // IRQ 32-bit EL0
201         ventry  el0_fiq_invalid_compat          // FIQ 32-bit EL0
202         ventry  el0_error_invalid_compat        // Error 32-bit EL0
203 #else
204         ventry  el0_sync_invalid                // Synchronous 32-bit EL0
205         ventry  el0_irq_invalid                 // IRQ 32-bit EL0
206         ventry  el0_fiq_invalid                 // FIQ 32-bit EL0
207         ventry  el0_error_invalid               // Error 32-bit EL0
208 #endif
209 END(vectors)
210
211 /*
212  * Invalid mode handlers
213  */
214         .macro  inv_entry, el, reason, regsize = 64
215         kernel_entry el, \regsize
216         mov     x0, sp
217         mov     x1, #\reason
218         mrs     x2, esr_el1
219         b       bad_mode
220         .endm
221
222 el0_sync_invalid:
223         inv_entry 0, BAD_SYNC
224 ENDPROC(el0_sync_invalid)
225
226 el0_irq_invalid:
227         inv_entry 0, BAD_IRQ
228 ENDPROC(el0_irq_invalid)
229
230 el0_fiq_invalid:
231         inv_entry 0, BAD_FIQ
232 ENDPROC(el0_fiq_invalid)
233
234 el0_error_invalid:
235         inv_entry 0, BAD_ERROR
236 ENDPROC(el0_error_invalid)
237
238 #ifdef CONFIG_COMPAT
239 el0_fiq_invalid_compat:
240         inv_entry 0, BAD_FIQ, 32
241 ENDPROC(el0_fiq_invalid_compat)
242
243 el0_error_invalid_compat:
244         inv_entry 0, BAD_ERROR, 32
245 ENDPROC(el0_error_invalid_compat)
246 #endif
247
248 el1_sync_invalid:
249         inv_entry 1, BAD_SYNC
250 ENDPROC(el1_sync_invalid)
251
252 el1_irq_invalid:
253         inv_entry 1, BAD_IRQ
254 ENDPROC(el1_irq_invalid)
255
256 el1_fiq_invalid:
257         inv_entry 1, BAD_FIQ
258 ENDPROC(el1_fiq_invalid)
259
260 el1_error_invalid:
261         inv_entry 1, BAD_ERROR
262 ENDPROC(el1_error_invalid)
263
264 /*
265  * EL1 mode handlers.
266  */
267         .align  6
268 el1_sync:
269         kernel_entry 1
270         mrs     x1, esr_el1                     // read the syndrome register
271         lsr     x24, x1, #ESR_EL1_EC_SHIFT      // exception class
272         cmp     x24, #ESR_EL1_EC_DABT_EL1       // data abort in EL1
273         b.eq    el1_da
274         cmp     x24, #ESR_EL1_EC_SYS64          // configurable trap
275         b.eq    el1_undef
276         cmp     x24, #ESR_EL1_EC_SP_ALIGN       // stack alignment exception
277         b.eq    el1_sp_pc
278         cmp     x24, #ESR_EL1_EC_PC_ALIGN       // pc alignment exception
279         b.eq    el1_sp_pc
280         cmp     x24, #ESR_EL1_EC_UNKNOWN        // unknown exception in EL1
281         b.eq    el1_undef
282         cmp     x24, #ESR_EL1_EC_BREAKPT_EL1    // debug exception in EL1
283         b.ge    el1_dbg
284         b       el1_inv
285 el1_da:
286         /*
287          * Data abort handling
288          */
289         mrs     x0, far_el1
290         enable_dbg
291         // re-enable interrupts if they were enabled in the aborted context
292         tbnz    x23, #7, 1f                     // PSR_I_BIT
293         enable_irq
294 1:
295         mov     x2, sp                          // struct pt_regs
296         bl      do_mem_abort
297
298         // disable interrupts before pulling preserved data off the stack
299         disable_irq
300         kernel_exit 1
301 el1_sp_pc:
302         /*
303          * Stack or PC alignment exception handling
304          */
305         mrs     x0, far_el1
306         enable_dbg
307         mov     x2, sp
308         b       do_sp_pc_abort
309 el1_undef:
310         /*
311          * Undefined instruction
312          */
313         enable_dbg
314         mov     x0, sp
315         b       do_undefinstr
316 el1_dbg:
317         /*
318          * Debug exception handling
319          */
320         cmp     x24, #ESR_EL1_EC_BRK64          // if BRK64
321         cinc    x24, x24, eq                    // set bit '0'
322         tbz     x24, #0, el1_inv                // EL1 only
323         mrs     x0, far_el1
324         mov     x2, sp                          // struct pt_regs
325         bl      do_debug_exception
326         kernel_exit 1
327 el1_inv:
328         // TODO: add support for undefined instructions in kernel mode
329         enable_dbg
330         mov     x0, sp
331         mov     x1, #BAD_SYNC
332         mrs     x2, esr_el1
333         b       bad_mode
334 ENDPROC(el1_sync)
335
336         .align  6
337 el1_irq:
338         kernel_entry 1
339         enable_dbg
340 #ifdef CONFIG_TRACE_IRQFLAGS
341         bl      trace_hardirqs_off
342 #endif
343
344         irq_handler
345
346 #ifdef CONFIG_PREEMPT
347         get_thread_info tsk
348         ldr     w24, [tsk, #TI_PREEMPT]         // get preempt count
349         cbnz    w24, 1f                         // preempt count != 0
350         ldr     x0, [tsk, #TI_FLAGS]            // get flags
351         tbz     x0, #TIF_NEED_RESCHED, 1f       // needs rescheduling?
352         bl      el1_preempt
353 1:
354 #endif
355 #ifdef CONFIG_TRACE_IRQFLAGS
356         bl      trace_hardirqs_on
357 #endif
358         kernel_exit 1
359 ENDPROC(el1_irq)
360
361 #ifdef CONFIG_PREEMPT
362 el1_preempt:
363         mov     x24, lr
364 1:      bl      preempt_schedule_irq            // irq en/disable is done inside
365         ldr     x0, [tsk, #TI_FLAGS]            // get new tasks TI_FLAGS
366         tbnz    x0, #TIF_NEED_RESCHED, 1b       // needs rescheduling?
367         ret     x24
368 #endif
369
370 /*
371  * EL0 mode handlers.
372  */
373         .align  6
374 el0_sync:
375         kernel_entry 0
376         mrs     x25, esr_el1                    // read the syndrome register
377         lsr     x24, x25, #ESR_EL1_EC_SHIFT     // exception class
378         cmp     x24, #ESR_EL1_EC_SVC64          // SVC in 64-bit state
379         b.eq    el0_svc
380         cmp     x24, #ESR_EL1_EC_DABT_EL0       // data abort in EL0
381         b.eq    el0_da
382         cmp     x24, #ESR_EL1_EC_IABT_EL0       // instruction abort in EL0
383         b.eq    el0_ia
384         cmp     x24, #ESR_EL1_EC_FP_ASIMD       // FP/ASIMD access
385         b.eq    el0_fpsimd_acc
386         cmp     x24, #ESR_EL1_EC_FP_EXC64       // FP/ASIMD exception
387         b.eq    el0_fpsimd_exc
388         cmp     x24, #ESR_EL1_EC_SYS64          // configurable trap
389         b.eq    el0_undef
390         cmp     x24, #ESR_EL1_EC_SP_ALIGN       // stack alignment exception
391         b.eq    el0_sp_pc
392         cmp     x24, #ESR_EL1_EC_PC_ALIGN       // pc alignment exception
393         b.eq    el0_sp_pc
394         cmp     x24, #ESR_EL1_EC_UNKNOWN        // unknown exception in EL0
395         b.eq    el0_undef
396         cmp     x24, #ESR_EL1_EC_BREAKPT_EL0    // debug exception in EL0
397         b.ge    el0_dbg
398         b       el0_inv
399
400 #ifdef CONFIG_COMPAT
401         .align  6
402 el0_sync_compat:
403         kernel_entry 0, 32
404         mrs     x25, esr_el1                    // read the syndrome register
405         lsr     x24, x25, #ESR_EL1_EC_SHIFT     // exception class
406         cmp     x24, #ESR_EL1_EC_SVC32          // SVC in 32-bit state
407         b.eq    el0_svc_compat
408         cmp     x24, #ESR_EL1_EC_DABT_EL0       // data abort in EL0
409         b.eq    el0_da
410         cmp     x24, #ESR_EL1_EC_IABT_EL0       // instruction abort in EL0
411         b.eq    el0_ia
412         cmp     x24, #ESR_EL1_EC_FP_ASIMD       // FP/ASIMD access
413         b.eq    el0_fpsimd_acc
414         cmp     x24, #ESR_EL1_EC_FP_EXC32       // FP/ASIMD exception
415         b.eq    el0_fpsimd_exc
416         cmp     x24, #ESR_EL1_EC_UNKNOWN        // unknown exception in EL0
417         b.eq    el0_undef
418         cmp     x24, #ESR_EL1_EC_CP15_32        // CP15 MRC/MCR trap
419         b.eq    el0_undef
420         cmp     x24, #ESR_EL1_EC_CP15_64        // CP15 MRRC/MCRR trap
421         b.eq    el0_undef
422         cmp     x24, #ESR_EL1_EC_CP14_MR        // CP14 MRC/MCR trap
423         b.eq    el0_undef
424         cmp     x24, #ESR_EL1_EC_CP14_LS        // CP14 LDC/STC trap
425         b.eq    el0_undef
426         cmp     x24, #ESR_EL1_EC_CP14_64        // CP14 MRRC/MCRR trap
427         b.eq    el0_undef
428         cmp     x24, #ESR_EL1_EC_BREAKPT_EL0    // debug exception in EL0
429         b.ge    el0_dbg
430         b       el0_inv
431 el0_svc_compat:
432         /*
433          * AArch32 syscall handling
434          */
435         adr     stbl, compat_sys_call_table     // load compat syscall table pointer
436         uxtw    scno, w7                        // syscall number in w7 (r7)
437         mov     sc_nr, #__NR_compat_syscalls
438         b       el0_svc_naked
439
440         .align  6
441 el0_irq_compat:
442         kernel_entry 0, 32
443         b       el0_irq_naked
444 #endif
445
446 el0_da:
447         /*
448          * Data abort handling
449          */
450         mrs     x26, far_el1
451         // enable interrupts before calling the main handler
452         enable_dbg_and_irq
453         ct_user_exit
454         bic     x0, x26, #(0xff << 56)
455         mov     x1, x25
456         mov     x2, sp
457         bl      do_mem_abort
458         b       ret_to_user
459 el0_ia:
460         /*
461          * Instruction abort handling
462          */
463         mrs     x26, far_el1
464         // enable interrupts before calling the main handler
465         enable_dbg_and_irq
466         ct_user_exit
467         mov     x0, x26
468         orr     x1, x25, #1 << 24               // use reserved ISS bit for instruction aborts
469         mov     x2, sp
470         bl      do_mem_abort
471         b       ret_to_user
472 el0_fpsimd_acc:
473         /*
474          * Floating Point or Advanced SIMD access
475          */
476         enable_dbg
477         ct_user_exit
478         mov     x0, x25
479         mov     x1, sp
480         bl      do_fpsimd_acc
481         b       ret_to_user
482 el0_fpsimd_exc:
483         /*
484          * Floating Point or Advanced SIMD exception
485          */
486         enable_dbg
487         ct_user_exit
488         mov     x0, x25
489         mov     x1, sp
490         bl      do_fpsimd_exc
491         b       ret_to_user
492 el0_sp_pc:
493         /*
494          * Stack or PC alignment exception handling
495          */
496         mrs     x26, far_el1
497         // enable interrupts before calling the main handler
498         enable_dbg_and_irq
499         mov     x0, x26
500         mov     x1, x25
501         mov     x2, sp
502         bl      do_sp_pc_abort
503         b       ret_to_user
504 el0_undef:
505         /*
506          * Undefined instruction
507          */
508         // enable interrupts before calling the main handler
509         enable_dbg_and_irq
510         ct_user_exit
511         mov     x0, sp
512         bl      do_undefinstr
513         b       ret_to_user
514 el0_dbg:
515         /*
516          * Debug exception handling
517          */
518         tbnz    x24, #0, el0_inv                // EL0 only
519         mrs     x0, far_el1
520         mov     x1, x25
521         mov     x2, sp
522         bl      do_debug_exception
523         enable_dbg
524         ct_user_exit
525         b       ret_to_user
526 el0_inv:
527         enable_dbg
528         ct_user_exit
529         mov     x0, sp
530         mov     x1, #BAD_SYNC
531         mrs     x2, esr_el1
532         bl      bad_mode
533         b       ret_to_user
534 ENDPROC(el0_sync)
535
536         .align  6
537 el0_irq:
538         kernel_entry 0
539 el0_irq_naked:
540         enable_dbg
541 #ifdef CONFIG_TRACE_IRQFLAGS
542         bl      trace_hardirqs_off
543 #endif
544
545         ct_user_exit
546         irq_handler
547
548 #ifdef CONFIG_TRACE_IRQFLAGS
549         bl      trace_hardirqs_on
550 #endif
551         b       ret_to_user
552 ENDPROC(el0_irq)
553
554 /*
555  * Register switch for AArch64. The callee-saved registers need to be saved
556  * and restored. On entry:
557  *   x0 = previous task_struct (must be preserved across the switch)
558  *   x1 = next task_struct
559  * Previous and next are guaranteed not to be the same.
560  *
561  */
562 ENTRY(cpu_switch_to)
563         add     x8, x0, #THREAD_CPU_CONTEXT
564         mov     x9, sp
565         stp     x19, x20, [x8], #16             // store callee-saved registers
566         stp     x21, x22, [x8], #16
567         stp     x23, x24, [x8], #16
568         stp     x25, x26, [x8], #16
569         stp     x27, x28, [x8], #16
570         stp     x29, x9, [x8], #16
571         str     lr, [x8]
572         add     x8, x1, #THREAD_CPU_CONTEXT
573         ldp     x19, x20, [x8], #16             // restore callee-saved registers
574         ldp     x21, x22, [x8], #16
575         ldp     x23, x24, [x8], #16
576         ldp     x25, x26, [x8], #16
577         ldp     x27, x28, [x8], #16
578         ldp     x29, x9, [x8], #16
579         ldr     lr, [x8]
580         mov     sp, x9
581         ret
582 ENDPROC(cpu_switch_to)
583
584 /*
585  * This is the fast syscall return path.  We do as little as possible here,
586  * and this includes saving x0 back into the kernel stack.
587  */
588 ret_fast_syscall:
589         disable_irq                             // disable interrupts
590         ldr     x1, [tsk, #TI_FLAGS]
591         and     x2, x1, #_TIF_WORK_MASK
592         cbnz    x2, fast_work_pending
593         enable_step_tsk x1, x2
594         kernel_exit 0, ret = 1
595
596 /*
597  * Ok, we need to do extra processing, enter the slow path.
598  */
599 fast_work_pending:
600         str     x0, [sp, #S_X0]                 // returned x0
601 work_pending:
602         tbnz    x1, #TIF_NEED_RESCHED, work_resched
603         /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
604         ldr     x2, [sp, #S_PSTATE]
605         mov     x0, sp                          // 'regs'
606         tst     x2, #PSR_MODE_MASK              // user mode regs?
607         b.ne    no_work_pending                 // returning to kernel
608         enable_irq                              // enable interrupts for do_notify_resume()
609         bl      do_notify_resume
610         b       ret_to_user
611 work_resched:
612         bl      schedule
613
614 /*
615  * "slow" syscall return path.
616  */
617 ret_to_user:
618         disable_irq                             // disable interrupts
619         ldr     x1, [tsk, #TI_FLAGS]
620         and     x2, x1, #_TIF_WORK_MASK
621         cbnz    x2, work_pending
622         enable_step_tsk x1, x2
623 no_work_pending:
624         kernel_exit 0, ret = 0
625 ENDPROC(ret_to_user)
626
627 /*
628  * This is how we return from a fork.
629  */
630 ENTRY(ret_from_fork)
631         bl      schedule_tail
632         cbz     x19, 1f                         // not a kernel thread
633         mov     x0, x20
634         blr     x19
635 1:      get_thread_info tsk
636         b       ret_to_user
637 ENDPROC(ret_from_fork)
638
639 /*
640  * SVC handler.
641  */
642         .align  6
643 el0_svc:
644         adrp    stbl, sys_call_table            // load syscall table pointer
645         uxtw    scno, w8                        // syscall number in w8
646         mov     sc_nr, #__NR_syscalls
647 el0_svc_naked:                                  // compat entry point
648         stp     x0, scno, [sp, #S_ORIG_X0]      // save the original x0 and syscall number
649         enable_dbg_and_irq
650         ct_user_exit 1
651
652         ldr     x16, [tsk, #TI_FLAGS]           // check for syscall hooks
653         tst     x16, #_TIF_SYSCALL_WORK
654         b.ne    __sys_trace
655         cmp     scno, sc_nr                     // check upper syscall limit
656         b.hs    ni_sys
657         ldr     x16, [stbl, scno, lsl #3]       // address in the syscall table
658         blr     x16                             // call sys_* routine
659         b       ret_fast_syscall
660 ni_sys:
661         mov     x0, sp
662         bl      do_ni_syscall
663         b       ret_fast_syscall
664 ENDPROC(el0_svc)
665
666         /*
667          * This is the really slow path.  We're going to be doing context
668          * switches, and waiting for our parent to respond.
669          */
670 __sys_trace:
671         mov     x0, sp
672         bl      syscall_trace_enter
673         uxtw    scno, w0                        // syscall number (possibly new)
674         mov     x1, sp                          // pointer to regs
675         cmp     scno, sc_nr                     // check upper syscall limit
676         b.hs    __ni_sys_trace
677         ldp     x0, x1, [sp]                    // restore the syscall args
678         ldp     x2, x3, [sp, #S_X2]
679         ldp     x4, x5, [sp, #S_X4]
680         ldp     x6, x7, [sp, #S_X6]
681         ldr     x16, [stbl, scno, lsl #3]       // address in the syscall table
682         blr     x16                             // call sys_* routine
683
684 __sys_trace_return:
685         str     x0, [sp]                        // save returned x0
686         mov     x0, sp
687         bl      syscall_trace_exit
688         b       ret_to_user
689
690 __ni_sys_trace:
691         mov     x0, sp
692         bl      do_ni_syscall
693         b       __sys_trace_return
694
695 /*
696  * Special system call wrappers.
697  */
698 ENTRY(sys_rt_sigreturn_wrapper)
699         mov     x0, sp
700         b       sys_rt_sigreturn
701 ENDPROC(sys_rt_sigreturn_wrapper)
702
703 ENTRY(handle_arch_irq)
704         .quad   0