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