1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/init.h>
22#include <linux/linkage.h>
23
24#include <asm/alternative-asm.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/thread_info.h>
31#include <asm/unistd.h>
32
33
34
35
36
37 .macro ct_user_exit, syscall = 0
38#ifdef CONFIG_CONTEXT_TRACKING
39 bl context_tracking_user_exit
40 .if \syscall == 1
41
42
43
44
45 ldp x0, x1, [sp]
46 ldp x2, x3, [sp,
47 ldp x4, x5, [sp,
48 ldp x6, x7, [sp,
49 .endif
50#endif
51 .endm
52
53 .macro ct_user_enter
54#ifdef CONFIG_CONTEXT_TRACKING
55 bl context_tracking_user_enter
56#endif
57 .endm
58
59
60
61
62
63#define BAD_SYNC 0
64#define BAD_IRQ 1
65#define BAD_FIQ 2
66#define BAD_ERROR 3
67
68 .macro kernel_entry, el, regsize = 64
69 sub sp, sp,
70 .if \regsize == 32
71 mov w0, w0
72 .endif
73 stp x0, x1, [sp,
74 stp x2, x3, [sp,
75 stp x4, x5, [sp,
76 stp x6, x7, [sp,
77 stp x8, x9, [sp,
78 stp x10, x11, [sp,
79 stp x12, x13, [sp,
80 stp x14, x15, [sp,
81 stp x16, x17, [sp,
82 stp x18, x19, [sp,
83 stp x20, x21, [sp,
84 stp x22, x23, [sp,
85 stp x24, x25, [sp,
86 stp x26, x27, [sp,
87 stp x28, x29, [sp,
88
89 .if \el == 0
90 mrs x21, sp_el0
91 get_thread_info tsk
92 ldr x19, [tsk,
93 disable_step_tsk x19, x20
94 .else
95 add x21, sp,
96 .endif
97 mrs x22, elr_el1
98 mrs x23, spsr_el1
99 stp lr, x21, [sp,
100 stp x22, x23, [sp,
101
102
103
104
105 .if \el == 0
106 mvn x21, xzr
107 str x21, [sp,
108 .endif
109
110
111
112
113
114
115
116
117 .endm
118
119 .macro kernel_exit, el, ret = 0
120 ldp x21, x22, [sp,
121 .if \el == 0
122 ct_user_enter
123 ldr x23, [sp,
124 msr sp_el0, x23
125
126#ifdef CONFIG_ARM64_ERRATUM_845719
127 alternative_insn \
128 "nop", \
129 "tbz x22, #4, 1f", \
130 ARM64_WORKAROUND_845719
131#ifdef CONFIG_PID_IN_CONTEXTIDR
132 alternative_insn \
133 "nop; nop", \
134 "mrs x29, contextidr_el1; msr contextidr_el1, x29; 1:", \
135 ARM64_WORKAROUND_845719
136#else
137 alternative_insn \
138 "nop", \
139 "msr contextidr_el1, xzr; 1:", \
140 ARM64_WORKAROUND_845719
141#endif
142#endif
143 .endif
144 msr elr_el1, x21
145 msr spsr_el1, x22
146 .if \ret
147 ldr x1, [sp,
148 .else
149 ldp x0, x1, [sp,
150 .endif
151 ldp x2, x3, [sp,
152 ldp x4, x5, [sp,
153 ldp x6, x7, [sp,
154 ldp x8, x9, [sp,
155 ldp x10, x11, [sp,
156 ldp x12, x13, [sp,
157 ldp x14, x15, [sp,
158 ldp x16, x17, [sp,
159 ldp x18, x19, [sp,
160 ldp x20, x21, [sp,
161 ldp x22, x23, [sp,
162 ldp x24, x25, [sp,
163 ldp x26, x27, [sp,
164 ldp x28, x29, [sp,
165 ldr lr, [sp,
166 add sp, sp,
167 eret
168 .endm
169
170 .macro get_thread_info, rd
171 mov \rd, sp
172 and \rd, \rd,
173 .endm
174
175
176
177
178
179
180
181sc_nr .req x25
182scno .req x26
183stbl .req x27
184tsk .req x28
185
186
187
188
189 .macro irq_handler
190 adrp x1, handle_arch_irq
191 ldr x1, [x1,
192 mov x0, sp
193 blr x1
194 .endm
195
196 .text
197
198
199
200
201
202 .align 11
203ENTRY(vectors)
204 ventry el1_sync_invalid
205 ventry el1_irq_invalid
206 ventry el1_fiq_invalid
207 ventry el1_error_invalid
208
209 ventry el1_sync
210 ventry el1_irq
211 ventry el1_fiq_invalid
212 ventry el1_error_invalid
213
214 ventry el0_sync
215 ventry el0_irq
216 ventry el0_fiq_invalid
217 ventry el0_error_invalid
218
219#ifdef CONFIG_COMPAT
220 ventry el0_sync_compat
221 ventry el0_irq_compat
222 ventry el0_fiq_invalid_compat
223 ventry el0_error_invalid_compat
224#else
225 ventry el0_sync_invalid
226 ventry el0_irq_invalid
227 ventry el0_fiq_invalid
228 ventry el0_error_invalid
229#endif
230END(vectors)
231
232
233
234
235 .macro inv_entry, el, reason, regsize = 64
236 kernel_entry el, \regsize
237 mov x0, sp
238 mov x1,
239 mrs x2, esr_el1
240 b bad_mode
241 .endm
242
243el0_sync_invalid:
244 inv_entry 0, BAD_SYNC
245ENDPROC(el0_sync_invalid)
246
247el0_irq_invalid:
248 inv_entry 0, BAD_IRQ
249ENDPROC(el0_irq_invalid)
250
251el0_fiq_invalid:
252 inv_entry 0, BAD_FIQ
253ENDPROC(el0_fiq_invalid)
254
255el0_error_invalid:
256 inv_entry 0, BAD_ERROR
257ENDPROC(el0_error_invalid)
258
259#ifdef CONFIG_COMPAT
260el0_fiq_invalid_compat:
261 inv_entry 0, BAD_FIQ, 32
262ENDPROC(el0_fiq_invalid_compat)
263
264el0_error_invalid_compat:
265 inv_entry 0, BAD_ERROR, 32
266ENDPROC(el0_error_invalid_compat)
267#endif
268
269el1_sync_invalid:
270 inv_entry 1, BAD_SYNC
271ENDPROC(el1_sync_invalid)
272
273el1_irq_invalid:
274 inv_entry 1, BAD_IRQ
275ENDPROC(el1_irq_invalid)
276
277el1_fiq_invalid:
278 inv_entry 1, BAD_FIQ
279ENDPROC(el1_fiq_invalid)
280
281el1_error_invalid:
282 inv_entry 1, BAD_ERROR
283ENDPROC(el1_error_invalid)
284
285
286
287
288 .align 6
289el1_sync:
290 kernel_entry 1
291 mrs x1, esr_el1
292 lsr x24, x1,
293 cmp x24,
294 b.eq el1_da
295 cmp x24,
296 b.eq el1_undef
297 cmp x24,
298 b.eq el1_sp_pc
299 cmp x24,
300 b.eq el1_sp_pc
301 cmp x24,
302 b.eq el1_undef
303 cmp x24,
304 b.ge el1_dbg
305 b el1_inv
306el1_da:
307
308
309
310 mrs x0, far_el1
311 enable_dbg
312
313 tbnz x23,
314 enable_irq
3151:
316 mov x2, sp
317 bl do_mem_abort
318
319
320 disable_irq
321 kernel_exit 1
322el1_sp_pc:
323
324
325
326 mrs x0, far_el1
327 enable_dbg
328 mov x2, sp
329 b do_sp_pc_abort
330el1_undef:
331
332
333
334 enable_dbg
335 mov x0, sp
336 b do_undefinstr
337el1_dbg:
338
339
340
341 cmp x24,
342 cinc x24, x24, eq
343 tbz x24,
344 mrs x0, far_el1
345 mov x2, sp
346 bl do_debug_exception
347 kernel_exit 1
348el1_inv:
349
350 enable_dbg
351 mov x0, sp
352 mov x1,
353 mrs x2, esr_el1
354 b bad_mode
355ENDPROC(el1_sync)
356
357 .align 6
358el1_irq:
359 kernel_entry 1
360 enable_dbg
361#ifdef CONFIG_TRACE_IRQFLAGS
362 bl trace_hardirqs_off
363#endif
364
365 irq_handler
366
367#ifdef CONFIG_PREEMPT
368 get_thread_info tsk
369 ldr w24, [tsk,
370 cbnz w24, 1f
371 ldr x0, [tsk,
372 tbz x0,
373 bl el1_preempt
3741:
375#endif
376#ifdef CONFIG_TRACE_IRQFLAGS
377 bl trace_hardirqs_on
378#endif
379 kernel_exit 1
380ENDPROC(el1_irq)
381
382#ifdef CONFIG_PREEMPT
383el1_preempt:
384 mov x24, lr
3851: bl preempt_schedule_irq
386 ldr x0, [tsk,
387 tbnz x0,
388 ret x24
389#endif
390
391
392
393
394 .align 6
395el0_sync:
396 kernel_entry 0
397 mrs x25, esr_el1
398 lsr x24, x25,
399 cmp x24,
400 b.eq el0_svc
401 cmp x24,
402 b.eq el0_da
403 cmp x24,
404 b.eq el0_ia
405 cmp x24,
406 b.eq el0_fpsimd_acc
407 cmp x24,
408 b.eq el0_fpsimd_exc
409 cmp x24,
410 b.eq el0_undef
411 cmp x24,
412 b.eq el0_sp_pc
413 cmp x24,
414 b.eq el0_sp_pc
415 cmp x24,
416 b.eq el0_undef
417 cmp x24,
418 b.ge el0_dbg
419 b el0_inv
420
421#ifdef CONFIG_COMPAT
422 .align 6
423el0_sync_compat:
424 kernel_entry 0, 32
425 mrs x25, esr_el1
426 lsr x24, x25,
427 cmp x24,
428 b.eq el0_svc_compat
429 cmp x24,
430 b.eq el0_da
431 cmp x24,
432 b.eq el0_ia
433 cmp x24,
434 b.eq el0_fpsimd_acc
435 cmp x24,
436 b.eq el0_fpsimd_exc
437 cmp x24,
438 b.eq el0_undef
439 cmp x24,
440 b.eq el0_undef
441 cmp x24,
442 b.eq el0_undef
443 cmp x24,
444 b.eq el0_undef
445 cmp x24,
446 b.eq el0_undef
447 cmp x24,
448 b.eq el0_undef
449 cmp x24,
450 b.ge el0_dbg
451 b el0_inv
452el0_svc_compat:
453
454
455
456 adrp stbl, compat_sys_call_table
457 uxtw scno, w7
458 mov sc_nr,
459 b el0_svc_naked
460
461 .align 6
462el0_irq_compat:
463 kernel_entry 0, 32
464 b el0_irq_naked
465#endif
466
467el0_da:
468
469
470
471 mrs x26, far_el1
472
473 enable_dbg_and_irq
474 ct_user_exit
475 bic x0, x26,
476 mov x1, x25
477 mov x2, sp
478 bl do_mem_abort
479 b ret_to_user
480el0_ia:
481
482
483
484 mrs x26, far_el1
485
486 enable_dbg_and_irq
487 ct_user_exit
488 mov x0, x26
489 orr x1, x25,
490 mov x2, sp
491 bl do_mem_abort
492 b ret_to_user
493el0_fpsimd_acc:
494
495
496
497 enable_dbg
498 ct_user_exit
499 mov x0, x25
500 mov x1, sp
501 bl do_fpsimd_acc
502 b ret_to_user
503el0_fpsimd_exc:
504
505
506
507 enable_dbg
508 ct_user_exit
509 mov x0, x25
510 mov x1, sp
511 bl do_fpsimd_exc
512 b ret_to_user
513el0_sp_pc:
514
515
516
517 mrs x26, far_el1
518
519 enable_dbg_and_irq
520 mov x0, x26
521 mov x1, x25
522 mov x2, sp
523 bl do_sp_pc_abort
524 b ret_to_user
525el0_undef:
526
527
528
529
530 enable_dbg_and_irq
531 ct_user_exit
532 mov x0, sp
533 bl do_undefinstr
534 b ret_to_user
535el0_dbg:
536
537
538
539 tbnz x24,
540 mrs x0, far_el1
541 mov x1, x25
542 mov x2, sp
543 bl do_debug_exception
544 enable_dbg
545 ct_user_exit
546 b ret_to_user
547el0_inv:
548 enable_dbg
549 ct_user_exit
550 mov x0, sp
551 mov x1,
552 mrs x2, esr_el1
553 bl bad_mode
554 b ret_to_user
555ENDPROC(el0_sync)
556
557 .align 6
558el0_irq:
559 kernel_entry 0
560el0_irq_naked:
561 enable_dbg
562#ifdef CONFIG_TRACE_IRQFLAGS
563 bl trace_hardirqs_off
564#endif
565
566 ct_user_exit
567 irq_handler
568
569#ifdef CONFIG_TRACE_IRQFLAGS
570 bl trace_hardirqs_on
571#endif
572 b ret_to_user
573ENDPROC(el0_irq)
574
575
576
577
578
579
580
581
582
583ENTRY(cpu_switch_to)
584 add x8, x0,
585 mov x9, sp
586 stp x19, x20, [x8],
587 stp x21, x22, [x8],
588 stp x23, x24, [x8],
589 stp x25, x26, [x8],
590 stp x27, x28, [x8],
591 stp x29, x9, [x8],
592 str lr, [x8]
593 add x8, x1,
594 ldp x19, x20, [x8],
595 ldp x21, x22, [x8],
596 ldp x23, x24, [x8],
597 ldp x25, x26, [x8],
598 ldp x27, x28, [x8],
599 ldp x29, x9, [x8],
600 ldr lr, [x8]
601 mov sp, x9
602 ret
603ENDPROC(cpu_switch_to)
604
605
606
607
608
609ret_fast_syscall:
610 disable_irq
611 ldr x1, [tsk,
612 and x2, x1,
613 cbnz x2, fast_work_pending
614 enable_step_tsk x1, x2
615 kernel_exit 0, ret = 1
616
617
618
619
620fast_work_pending:
621 str x0, [sp,
622work_pending:
623 tbnz x1,
624
625 ldr x2, [sp,
626 mov x0, sp
627 tst x2,
628 b.ne no_work_pending
629 enable_irq
630 bl do_notify_resume
631 b ret_to_user
632work_resched:
633 bl schedule
634
635
636
637
638ret_to_user:
639 disable_irq
640 ldr x1, [tsk,
641 and x2, x1,
642 cbnz x2, work_pending
643 enable_step_tsk x1, x2
644no_work_pending:
645 kernel_exit 0, ret = 0
646ENDPROC(ret_to_user)
647
648
649
650
651ENTRY(ret_from_fork)
652 bl schedule_tail
653 cbz x19, 1f
654 mov x0, x20
655 blr x19
6561: get_thread_info tsk
657 b ret_to_user
658ENDPROC(ret_from_fork)
659
660
661
662
663 .align 6
664el0_svc:
665 adrp stbl, sys_call_table
666 uxtw scno, w8
667 mov sc_nr,
668el0_svc_naked:
669 stp x0, scno, [sp,
670 enable_dbg_and_irq
671 ct_user_exit 1
672
673 ldr x16, [tsk,
674 tst x16,
675 b.ne __sys_trace
676 cmp scno, sc_nr
677 b.hs ni_sys
678 ldr x16, [stbl, scno, lsl
679 blr x16
680 b ret_fast_syscall
681ni_sys:
682 mov x0, sp
683 bl do_ni_syscall
684 b ret_fast_syscall
685ENDPROC(el0_svc)
686
687
688
689
690
691__sys_trace:
692 mov w0,
693 cmp scno, x0
694 b.ne 1f
695 mov x0,
696 str x0, [sp,
6971: mov x0, sp
698 bl syscall_trace_enter
699 cmp w0,
700 b.eq __sys_trace_return_skipped
701 uxtw scno, w0
702 mov x1, sp
703 cmp scno, sc_nr
704 b.hs __ni_sys_trace
705 ldp x0, x1, [sp]
706 ldp x2, x3, [sp,
707 ldp x4, x5, [sp,
708 ldp x6, x7, [sp,
709 ldr x16, [stbl, scno, lsl
710 blr x16
711
712__sys_trace_return:
713 str x0, [sp,
714__sys_trace_return_skipped:
715 mov x0, sp
716 bl syscall_trace_exit
717 b ret_to_user
718
719__ni_sys_trace:
720 mov x0, sp
721 bl do_ni_syscall
722 b __sys_trace_return
723
724
725
726
727ENTRY(sys_rt_sigreturn_wrapper)
728 mov x0, sp
729 b sys_rt_sigreturn
730ENDPROC(sys_rt_sigreturn_wrapper)
731