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