1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/linkage.h>
18#include <linux/errno.h>
19#include <linux/unistd.h>
20#include <linux/init.h>
21#include <asm/ptrace.h>
22#include <asm/thread_info.h>
23#include <asm/irqflags.h>
24#include <asm/asm-offsets.h>
25#include <asm/types.h>
26#include <asm/traps.h>
27#include <asm/signal.h>
28#include <hv/hypervisor.h>
29#include <arch/abi.h>
30#include <arch/interrupts.h>
31#include <arch/spr_def.h>
32
33#define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
34
35#define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR)
36
37
38
39
40
41
42
43# define IS_KERNEL_EX1(result, ex1) andi result, ex1, CONFIG_KERNEL_PL
44#else
45
46#endif
47
48 .macro push_reg reg, ptr=sp, delta=-8
49 {
50 st \ptr, \reg
51 addli \ptr, \ptr, \delta
52 }
53 .endm
54
55 .macro pop_reg reg, ptr=sp, delta=8
56 {
57 ld \reg, \ptr
58 addli \ptr, \ptr, \delta
59 }
60 .endm
61
62 .macro pop_reg_zero reg, zreg, ptr=sp, delta=8
63 {
64 move \zreg, zero
65 ld \reg, \ptr
66 addi \ptr, \ptr, \delta
67 }
68 .endm
69
70 .macro push_extra_callee_saves reg
71 PTREGS_PTR(\reg, PTREGS_OFFSET_REG(51))
72 push_reg r51, \reg
73 push_reg r50, \reg
74 push_reg r49, \reg
75 push_reg r48, \reg
76 push_reg r47, \reg
77 push_reg r46, \reg
78 push_reg r45, \reg
79 push_reg r44, \reg
80 push_reg r43, \reg
81 push_reg r42, \reg
82 push_reg r41, \reg
83 push_reg r40, \reg
84 push_reg r39, \reg
85 push_reg r38, \reg
86 push_reg r37, \reg
87 push_reg r36, \reg
88 push_reg r35, \reg
89 push_reg r34, \reg, PTREGS_OFFSET_BASE - PTREGS_OFFSET_REG(34)
90 .endm
91
92 .macro panic str
93 .pushsection .rodata, "a"
941:
95 .asciz "\str"
96 .popsection
97 {
98 moveli r0, hw2_last(1b)
99 }
100 {
101 shl16insli r0, r0, hw1(1b)
102 }
103 {
104 shl16insli r0, r0, hw0(1b)
105 jal panic
106 }
107 .endm
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 .macro int_hand_unalign_fast vecnum, vecname
130 .org (\vecnum << 8)
131intvec_\vecname:
132
133 mtspr SPR_SYSTEM_SAVE_K_1, r3
134
135 mfspr r3, SPR_EX_CONTEXT_K_1
136
137
138
139
140 bnez r3, hand_unalign_slow_nonuser
141
142 mfspr r3, SPR_SYSTEM_SAVE_K_0
143
144
145 bfexts r3, r3, 0, CPU_SHIFT-1
146 mm r3, zero, LOG2_THREAD_SIZE, 63
147 addli r3, r3, THREAD_INFO_UNALIGN_JIT_TMP_OFFSET
148
149
150
151
152
153 st_add r3, r0, 8
154 st_add r3, r1, 8
155 {
156 st_add r3, r2, 8
157 andi r2, sp, 7
158 }
159
160
161 mfspr r1, SPR_SYSTEM_SAVE_K_1
162 st r3, r1
163
164 {
165
166 bnez r2, hand_unalign_slow_badsp
167 }
168
169
170
171
172
173 {
174 ori sp, sp, 1
175 mfspr r1, SPR_EX_CONTEXT_K_0
176 }
177
178
179 {
180 addli r0, r3, THREAD_INFO_UNALIGN_JIT_BASE_OFFSET - \
181 (THREAD_INFO_UNALIGN_JIT_TMP_OFFSET + (3 * 8))
182 bfextu r2, r1, 3, (2 + PAGE_SHIFT - UNALIGN_JIT_SHIFT)
183 }
184
185
186 {
187 ld r0, r0
188 shli r2, r2, UNALIGN_JIT_SHIFT
189 }
190
191
192
193
194
195 {
196 beqz r0, hand_unalign_slow
197 add r2, r0, r2
198 }
199
200
201
202
203
204
205
206
207ENTRY(__start_unalign_asm_code)
208
209
210 ld_add r0, r2, 8
211
212
213
214
215
216 {
217 cmpeq r0, r0, r1
218 ld r1, r1
219 }
220
221
222 beqz r0, hand_unalign_slow
223
224
225
226
227
228
229 ld_add r0, r2, 8
230
231
232ENTRY(__end_unalign_asm_code)
233
234
235 {
236 cmpeq r0, r1, r0
237 mtspr SPR_EX_CONTEXT_0_1, zero
238 }
239
240
241 beqz r0, hand_unalign_slow
242
243
244
245
246
247
248
249
250 {
251 mfspr r0, SPR_EX_CONTEXT_K_0
252 andi sp, sp, ~1
253 }
254
255
256 {
257 mtspr SPR_EX_CONTEXT_K_0, r2
258 addi r0, r0, 8
259 }
260
261
262
263
264
265
266
267
268
269 {
270 movei r1, PL_ICS_EX1(USER_PL, 1)
271 mtspr SPR_EX_CONTEXT_0_0, r0
272 }
273
274 {
275 mtspr SPR_EX_CONTEXT_K_1, r1
276 addi r3, r3, -(3 * 8)
277 }
278
279
280 ld_add r0, r3, 8
281 ld_add r1, r3, 8
282 ld_add r2, r3, 8
283 ld r3, r3
284
285 iret
286 ENDPROC(intvec_\vecname)
287 .endm
288
289#ifdef __COLLECT_LINKER_FEEDBACK__
290 .pushsection .text.intvec_feedback,"ax"
291intvec_feedback:
292 .popsection
293#endif
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 .macro __int_hand vecnum, vecname, c_routine,processing=handle_interrupt
309intvec_\vecname:
310
311
312 mtspr SPR_SYSTEM_SAVE_K_1, r0
313 mfspr r0, SPR_EX_CONTEXT_K_1
314
315
316
317
318
319 {
320 blbs sp, 2f
321 IS_KERNEL_EX1(r0, r0)
322 }
323
324 .ifc \vecnum, INT_DOUBLE_FAULT
325
326
327
328
329
330
331 beqz r0, 1f
332 j _kernel_double_fault
3331:
334 .else
335
336
337
338
339 {
340 bnez r0, 0f
341 move r0, sp
342 }
343 .endif
344
345 .ifc \c_routine, do_page_fault
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365 mfspr r0, SPR_SYSTEM_SAVE_K_2
366 {
367 bltz r0, 0f
368 move r0, sp
369 }
370 .endif
371
3722:
373
374
375
376
377
378
379 mfspr r0, SPR_SYSTEM_SAVE_K_0
380 bfexts r0, r0, 0, CPU_SHIFT-1
381
3820:
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404#endif
405 andi r0, r0, -64
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423 addli r0, r0, PTREGS_OFFSET_LR - (PTREGS_SIZE + KSTK_PTREGS_GAP)
424 wh64 r0
425 {
426 st r0, lr
427 addli r0, r0, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR
428 }
429 {
430 st r0, sp
431 addli sp, r0, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_SP
432 }
433 wh64 sp
434 {
435 st sp, r52
436 addli sp, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(52)
437 }
438 wh64 sp
439 {
440 st sp, r1
441 addli sp, sp, PTREGS_OFFSET_REG(2) - PTREGS_OFFSET_REG(1)
442 }
443 {
444 st sp, r2
445 addli sp, sp, PTREGS_OFFSET_REG(3) - PTREGS_OFFSET_REG(2)
446 }
447 {
448 st sp, r3
449 addli sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3)
450 }
451 mfspr r0, SPR_EX_CONTEXT_K_0
452 .ifc \processing,handle_syscall
453
454
455
456
457
458 addi r0, r0, 8
459 .endif
460 {
461 st sp, r0
462 addli sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC
463 }
464 mfspr r0, SPR_EX_CONTEXT_K_1
465 {
466 st sp, r0
467 addi sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1
468
469
470
471
472
473 .ifc \processing,handle_syscall
474 movei r0, \vecnum
475 }
476 {
477 st sp, r0
478 .else
479 movei r1, \vecnum
480 }
481 {
482 st sp, r1
483 .endif
484 addli sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM
485 }
486 mfspr r0, SPR_SYSTEM_SAVE_K_1
487 {
488 st sp, r0
489 addi sp, sp, -PTREGS_OFFSET_REG(0) - 8
490 }
491 {
492 st sp, zero
493 addi sp, sp, -8
494 }
495 .ifc \processing,handle_syscall
496 j handle_syscall
497 .else
498
499 .ifc \c_routine, do_page_fault
500 mfspr r2, SPR_SYSTEM_SAVE_K_3
501 mfspr r3, SPR_SYSTEM_SAVE_K_2
502 .else
503 .ifc \vecnum, INT_ILL_TRANS
504 mfspr r2, ILL_VA_PC
505 .else
506 .ifc \vecnum, INT_DOUBLE_FAULT
507 mfspr r2, SPR_SYSTEM_SAVE_K_2
508 .else
509 .ifc \c_routine, do_trap
510 mfspr r2, GPV_REASON
511 .else
512 .ifc \c_routine, handle_perf_interrupt
513 mfspr r2, PERF_COUNT_STS
514 .else
515 .ifc \c_routine, handle_perf_interrupt
516 mfspr r2, AUX_PERF_COUNT_STS
517 .endif
518 .ifc \c_routine, do_nmi
519 mfspr r2, SPR_SYSTEM_SAVE_K_2
520 .else
521 .endif
522 .endif
523 .endif
524 .endif
525 .endif
526 .endif
527
528 moveli r0, hw2_last(\c_routine)
529 shl16insli r0, r0, hw1(\c_routine)
530 {
531 shl16insli r0, r0, hw0(\c_routine)
532 j \processing
533 }
534 .endif
535 ENDPROC(intvec_\vecname)
536
537#ifdef __COLLECT_LINKER_FEEDBACK__
538 .pushsection .text.intvec_feedback,"ax"
539 .org (\vecnum << 5)
540 FEEDBACK_ENTER_EXPLICIT(intvec_\vecname, .intrpt, 1 << 8)
541 jrp lr
542 .popsection
543#endif
544
545 .endm
546
547
548
549
550
551
552 .macro finish_interrupt_save, function
553
554
555 PTREGS_PTR(r52, PTREGS_OFFSET_ORIG_R0)
556 {
557 .ifc \function,handle_syscall
558 st r52, r0
559 .else
560 st r52, zero
561 .endif
562 PTREGS_PTR(r52, PTREGS_OFFSET_TP)
563 }
564 st r52, tp
565 {
566 mfspr tp, CMPEXCH_VALUE
567 PTREGS_PTR(r52, PTREGS_OFFSET_CMPEXCH)
568 }
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605 {
606 st r52, tp
607 PTREGS_PTR(r52, PTREGS_OFFSET_REG(33))
608 }
609 wh64 r52
610 push_reg r33, r52
611 push_reg r32, r52
612 push_reg r31, r52
613 .ifc \function,handle_syscall
614 push_reg r30, r52, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(30)
615 push_reg TREG_SYSCALL_NR_NAME, r52, \
616 PTREGS_OFFSET_REG(5) - PTREGS_OFFSET_SYSCALL
617 .else
618
619 push_reg r30, r52, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(30)
620 wh64 r52
621 push_reg r29, r52
622 push_reg r28, r52
623 push_reg r27, r52
624 push_reg r26, r52
625 push_reg r25, r52
626 push_reg r24, r52
627 push_reg r23, r52
628 push_reg r22, r52
629 wh64 r52
630 push_reg r21, r52
631 push_reg r20, r52
632 push_reg r19, r52
633 push_reg r18, r52
634 push_reg r17, r52
635 push_reg r16, r52
636 push_reg r15, r52
637 push_reg r14, r52
638 wh64 r52
639 push_reg r13, r52
640 push_reg r12, r52
641 push_reg r11, r52
642 push_reg r10, r52
643 push_reg r9, r52
644 push_reg r8, r52
645 push_reg r7, r52
646 push_reg r6, r52
647
648 .endif
649
650 push_reg r5, r52
651 st r52, r4
652
653
654
655
656
657
658
659 mfspr r32, SPR_EX_CONTEXT_K_1
660 {
661 IS_KERNEL_EX1(r22, r22)
662 PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS)
663 }
664 beqzt r32, 1f
665 IRQS_DISABLED(r32)
666
667
668#endif
6691:
670 .ifnc \function,handle_syscall
671
672 ori r32, r32, PT_FLAGS_CALLER_SAVES
673 .endif
674 st r21, r32
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690 .ifc \function,handle_nmi
691 IRQ_DISABLE_ALL(r20)
692 .else
693 IRQ_DISABLE(r20, r21)
694 .endif
695 mtspr INTERRUPT_CRITICAL_SECTION, zero
696
697
698#ifdef CONFIG_SMP
699 {
700 mfspr r20, SPR_SYSTEM_SAVE_K_0
701 moveli r21, hw2_last(__per_cpu_offset)
702 }
703 {
704 shl16insli r21, r21, hw1(__per_cpu_offset)
705 bfextu r20, r20, CPU_SHIFT, 63
706 }
707 shl16insli r21, r21, hw0(__per_cpu_offset)
708 shl3add r20, r20, r21
709 ld tp, r20
710#else
711 move tp, zero
712#endif
713
714#ifdef __COLLECT_LINKER_FEEDBACK__
715
716
717
718
719
720
721
722 .ifnc \function,handle_syscall
723 shli r20, r1, 5
724 .else
725 moveli r20, INT_SWINT_1 << 5
726 .endif
727 moveli r21, hw2_last(intvec_feedback)
728 shl16insli r21, r21, hw1(intvec_feedback)
729 shl16insli r21, r21, hw0(intvec_feedback)
730 add r20, r20, r21
731 jalr r20
732
733
734 FEEDBACK_ENTER(\function)
735#endif
736
737
738
739
740
741 addi r52, sp, -64
742 {
743 wh64 r52
744 addi r52, r52, -64
745 }
746 {
747 wh64 r52
748 addi r52, r52, -64
749 }
750 {
751 wh64 r52
752 addi r52, r52, -64
753 }
754 wh64 r52
755
756#ifdef CONFIG_TRACE_IRQFLAGS
757 .ifnc \function,handle_nmi
758
759
760
761
762
763
764
765
766
767 .ifnc \function,handle_syscall
768 { move r30, r0; move r31, r1 }
769 { move r32, r2; move r33, r3 }
770 .endif
771 TRACE_IRQS_OFF
772 .ifnc \function,handle_syscall
773 { move r0, r30; move r1, r31 }
774 { move r2, r32; move r3, r33 }
775 .endif
776 .endif
777#endif
778
779 .endm
780
781
782
783
784 .macro dc_dispatch vecnum, vecname
785 .org (\vecnum << 8)
786intvec_\vecname:
787 j _hv_downcall_dispatch
788 ENDPROC(intvec_\vecname)
789 .endm
790
791
792
793
794
795
796 .pushsection .text.handle_interrupt,"ax"
797handle_interrupt:
798 finish_interrupt_save handle_interrupt
799
800
801 {
802 jalr r0
803 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
804 }
805 FEEDBACK_REENTER(handle_interrupt)
806 {
807 movei r30, 0
808 j interrupt_return
809 }
810 STD_ENDPROC(handle_interrupt)
811
812
813
814
815
816
817
818
819
820
821STD_ENTRY(interrupt_return)
822
823 {
824 bnez r30, .Lrestore_all
825 PTREGS_PTR(r29, PTREGS_OFFSET_EX1)
826 }
827 ld r29, r29
828 IS_KERNEL_EX1(r29, r29)
829 {
830 beqzt r29, .Lresume_userspace
831 move r29, sp
832 }
833
834#ifdef CONFIG_PREEMPT
835
836 EXTRACT_THREAD_INFO(r29)
837 addli r28, r29, THREAD_INFO_FLAGS_OFFSET
838 {
839 ld r28, r28
840 addli r29, r29, THREAD_INFO_PREEMPT_COUNT_OFFSET
841 }
842 {
843 andi r28, r28, _TIF_NEED_RESCHED
844 ld4s r29, r29
845 }
846 beqzt r28, 1f
847 bnez r29, 1f
848
849 IRQ_DISABLE(r20,r21)
850 TRACE_IRQS_OFF
851 jal preempt_schedule_irq
852 FEEDBACK_REENTER(interrupt_return)
8531:
854#endif
855
856
857 {
858 moveli r27, hw2_last(_cpu_idle_nap)
859 PTREGS_PTR(r29, PTREGS_OFFSET_PC)
860 }
861 {
862 ld r28, r29
863 shl16insli r27, r27, hw1(_cpu_idle_nap)
864 }
865 {
866 shl16insli r27, r27, hw0(_cpu_idle_nap)
867 }
868 {
869 cmpeq r27, r27, r28
870 }
871 {
872 blbc r27, .Lrestore_all
873 addi r28, r28, 8
874 }
875 st r29, r28
876 j .Lrestore_all
877
878.Lresume_userspace:
879 FEEDBACK_REENTER(interrupt_return)
880
881
882
883
884
885
886 {
887 movei r33, 0
888 move r32, sp
889 }
890
891
892 EXTRACT_THREAD_INFO(r32)
893
894.Lretry_work_pending:
895
896
897
898
899
900
901
902 IRQ_DISABLE(r20, r21)
903 TRACE_IRQS_OFF
904
905
906
907 {
908 addi r29, r32, THREAD_INFO_FLAGS_OFFSET
909 moveli r1, hw1_last(_TIF_ALLWORK_MASK)
910 }
911 {
912 ld r29, r29
913 shl16insli r1, r1, hw0(_TIF_ALLWORK_MASK)
914 }
915 and r1, r29, r1
916 beqzt r1, .Lrestore_all
917
918
919
920
921
922
923
924 {
925 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
926 bnez r33, 1f
927 }
928 push_extra_callee_saves r0
929 movei r33, 1
9301: jal do_work_pending
931 bnez r0, .Lretry_work_pending
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948.Lrestore_all:
949 PTREGS_PTR(r0, PTREGS_OFFSET_EX1)
950 {
951 ld r0, r0
952 PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS)
953 }
954 {
955 IS_KERNEL_EX1(r0, r0)
956 ld r32, r32
957 }
958 bnez r0, 1f
959 j 2f
960
961
962#endif
9631: blbct r32, 2f
964 IRQ_DISABLE(r20,r21)
965 TRACE_IRQS_OFF
966 movei r0, 1
967 mtspr INTERRUPT_CRITICAL_SECTION, r0
968 beqzt r30, .Lrestore_regs
969 j 3f
9702: TRACE_IRQS_ON
971 IRQ_ENABLE_LOAD(r20, r21)
972 movei r0, 1
973 mtspr INTERRUPT_CRITICAL_SECTION, r0
974 IRQ_ENABLE_APPLY(r20, r21)
975 beqzt r30, .Lrestore_regs
9763:
977
978
979
980#endif
981 {
982 movei r0, 3
983 beqz r31, .Lrestore_regs
984 }
985 shli r0, r0, INT_PERF_COUNT
986 mtspr SPR_INTERRUPT_MASK_RESET_K, r0
987
988
989
990
991
992
993
994
995
996
997
998
999.Lrestore_regs:
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010#endif
1011 {
1012 rotli r20, r32, 62
1013 PTREGS_PTR(sp, PTREGS_OFFSET_REG(0))
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023 pop_reg r0, sp, PTREGS_OFFSET_REG(30) - PTREGS_OFFSET_REG(0)
1024 pop_reg r30, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_REG(30)
1025 pop_reg_zero r52, r3, sp, PTREGS_OFFSET_CMPEXCH - PTREGS_OFFSET_REG(52)
1026 pop_reg_zero r21, r27, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_CMPEXCH
1027 pop_reg_zero lr, r2, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_EX1
1028 {
1029 mtspr CMPEXCH_VALUE, r21
1030 move r4, zero
1031 }
1032 pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC
1033 {
1034 mtspr SPR_EX_CONTEXT_K_1, lr
1035 IS_KERNEL_EX1(lr, lr)
1036 }
1037 {
1038 mtspr SPR_EX_CONTEXT_K_0, r21
1039 move r5, zero
1040 }
1041
1042
1043 pop_reg_zero r31, r6
1044 pop_reg_zero r32, r7
1045 pop_reg_zero r33, r8, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(33)
1046
1047
1048
1049
1050
1051 {
1052 move r9, zero
1053 blbs r20, .Lrestore_callees
1054 }
1055.Lcontinue_restore_regs:
1056
1057
1058 {
1059 move r10, zero
1060 bltzt r20, 1f
1061 }
1062
1063
1064
1065
1066
1067 {
1068 addli sp, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(29)
1069 bnez lr, .Lkernel_return
1070 }
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 pop_reg_zero lr, r11, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR
1081 pop_reg_zero tp, r12, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP
1082 {
1083 ld sp, sp
1084 move r13, zero
1085 move r14, zero
1086 }
1087 { move r15, zero; move r16, zero }
1088 { move r17, zero; move r18, zero }
1089 { move r19, zero; move r20, zero }
1090 { move r21, zero; move r22, zero }
1091 { move r23, zero; move r24, zero }
1092 { move r25, zero; move r26, zero }
1093
1094
1095 {
1096 moveli r29, 4096
1097 sub r1, zero, r0
1098 }
1099 {
1100 move r28, zero
1101 cmpltu r29, r1, r29
1102 }
1103 {
1104 mnz r1, r29, r1
1105 move r29, zero
1106 }
1107 iret
1108
1109
1110
1111
1112
1113
1114 .align 64
11151: pop_reg r29, sp, PTREGS_OFFSET_REG(21) - PTREGS_OFFSET_REG(29)
1116 pop_reg r21, sp, PTREGS_OFFSET_REG(13) - PTREGS_OFFSET_REG(21)
1117 pop_reg r13, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(13)
1118 pop_reg r1
1119 pop_reg r2
1120 pop_reg r3
1121 pop_reg r4
1122 pop_reg r5
1123 pop_reg r6
1124 pop_reg r7
1125 pop_reg r8
1126 pop_reg r9
1127 pop_reg r10
1128 pop_reg r11
1129 pop_reg r12, sp, 16
1130
1131 pop_reg r14
1132 pop_reg r15
1133 pop_reg r16
1134 pop_reg r17
1135 pop_reg r18
1136 pop_reg r19
1137 pop_reg r20, sp, 16
1138
1139 pop_reg r22
1140 pop_reg r23
1141 pop_reg r24
1142 pop_reg r25
1143 pop_reg r26
1144 pop_reg r27
1145 pop_reg r28, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(28)
1146
1147 bnez lr, .Lkernel_return
1148 pop_reg lr, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR
1149 pop_reg tp, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP
1150 ld sp, sp
1151 iret
1152
1153
1154
1155
1156
1157.Lkernel_return:
1158 pop_reg lr, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR
1159 ld sp, sp
1160 iret
1161
1162
1163.Lrestore_callees:
1164 addli sp, sp, PTREGS_OFFSET_REG(34) - PTREGS_OFFSET_REG(29)
1165 pop_reg r34
1166 pop_reg r35
1167 pop_reg r36
1168 pop_reg r37
1169 pop_reg r38
1170 pop_reg r39
1171 pop_reg r40
1172 pop_reg r41
1173 pop_reg r42
1174 pop_reg r43
1175 pop_reg r44
1176 pop_reg r45
1177 pop_reg r46
1178 pop_reg r47
1179 pop_reg r48
1180 pop_reg r49
1181 pop_reg r50
1182 pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51)
1183 j .Lcontinue_restore_regs
1184 STD_ENDPROC(interrupt_return)
1185
1186
1187
1188
1189
1190
1191
1192
1193 .pushsection .text.handle_nmi,"ax"
1194handle_nmi:
1195 finish_interrupt_save handle_nmi
1196 {
1197 jalr r0
1198 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
1199 }
1200 FEEDBACK_REENTER(handle_nmi)
1201 {
1202 movei r30, 1
1203 cmpeq r31, r0, zero
1204 }
1205 j interrupt_return
1206 STD_ENDPROC(handle_nmi)
1207
1208
1209
1210
1211 .pushsection .text.handle_syscall,"ax"
1212handle_syscall:
1213 finish_interrupt_save handle_syscall
1214
1215
1216 TRACE_IRQS_ON
1217 IRQ_ENABLE(r20, r21)
1218
1219
1220 moveli r20, hw2_last(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET)
1221 shl16insli r20, r20, hw1(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET)
1222 shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET)
1223 add r20, r20, tp
1224 ld4s r21, r20
1225 {
1226 addi r21, r21, 1
1227 move r31, sp
1228 }
1229 {
1230 st4 r20, r21
1231 EXTRACT_THREAD_INFO(r31)
1232 }
1233
1234
1235 addi r31, r31, THREAD_INFO_FLAGS_OFFSET
1236 {
1237 ld r30, r31
1238 moveli r32, _TIF_SYSCALL_ENTRY_WORK
1239 }
1240 and r30, r30, r32
1241 {
1242 addi r30, r31, THREAD_INFO_STATUS_OFFSET - THREAD_INFO_FLAGS_OFFSET
1243 beqzt r30, .Lrestore_syscall_regs
1244 }
1245 {
1246 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
1247 jal do_syscall_trace_enter
1248 }
1249 FEEDBACK_REENTER(handle_syscall)
1250
1251
1252
1253
1254
1255
1256
1257
1258.Lrestore_syscall_regs:
1259 {
1260 ld r30, r30
1261 PTREGS_PTR(r11, PTREGS_OFFSET_REG(0))
1262 }
1263 pop_reg r0, r11
1264 pop_reg r1, r11
1265 pop_reg r2, r11
1266 pop_reg r3, r11
1267 pop_reg r4, r11
1268 pop_reg r5, r11, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(5)
1269 {
1270 ld TREG_SYSCALL_NR_NAME, r11
1271 moveli r21, __NR_syscalls
1272 }
1273
1274
1275 {
1276 moveli r20, hw2(sys_call_table)
1277#ifdef CONFIG_COMPAT
1278 blbs r30, .Lcompat_syscall
1279#endif
1280 }
1281 {
1282 cmpltu r21, TREG_SYSCALL_NR_NAME, r21
1283 shl16insli r20, r20, hw1(sys_call_table)
1284 }
1285 {
1286 blbc r21, .Linvalid_syscall
1287 shl16insli r20, r20, hw0(sys_call_table)
1288 }
1289.Lload_syscall_pointer:
1290 shl3add r20, TREG_SYSCALL_NR_NAME, r20
1291 ld r20, r20
1292
1293
1294 jalr r20
1295.Lhandle_syscall_link:
1296
1297
1298
1299
1300
1301
1302 {
1303 PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
1304 blbct r30, 1f
1305 }
1306 addxi r0, r0, 0
13071: st r29, r0
1308
1309.Lsyscall_sigreturn_skip:
1310 FEEDBACK_REENTER(handle_syscall)
1311
1312
1313 {
1314 ld r30, r31
1315 moveli r32, _TIF_SYSCALL_EXIT_WORK
1316 }
1317 and r0, r30, r32
1318 {
1319 andi r0, r30, _TIF_SINGLESTEP
1320 beqzt r0, 1f
1321 }
1322 {
1323 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
1324 jal do_syscall_trace_exit
1325 }
1326 FEEDBACK_REENTER(handle_syscall)
1327 andi r0, r30, _TIF_SINGLESTEP
1328
13291: beqzt r0, 2f
1330
1331
1332 {
1333 movei r0, SIGTRAP
1334 jal ptrace_notify
1335 }
1336 FEEDBACK_REENTER(handle_syscall)
1337
13382: {
1339 movei r30, 0
1340 j .Lresume_userspace
1341 }
1342
1343#ifdef CONFIG_COMPAT
1344.Lcompat_syscall:
1345
1346
1347
1348
1349
1350
1351
1352 moveli r20, hw2(compat_sys_call_table)
1353 {
1354 cmpltu r21, TREG_SYSCALL_NR_NAME, r21
1355 shl16insli r20, r20, hw1(compat_sys_call_table)
1356 }
1357 {
1358 blbc r21, .Linvalid_syscall
1359 shl16insli r20, r20, hw0(compat_sys_call_table)
1360 }
1361 { move r11, r0; addxi r0, r0, 0 }
1362 { move r12, r1; addxi r1, r1, 0 }
1363 { move r13, r2; addxi r2, r2, 0 }
1364 { move r14, r3; addxi r3, r3, 0 }
1365 { move r15, r4; addxi r4, r4, 0 }
1366 { move r16, r5; addxi r5, r5, 0 }
1367 j .Lload_syscall_pointer
1368#endif
1369
1370.Linvalid_syscall:
1371
1372 {
1373 PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
1374 movei r28, -ENOSYS
1375 }
1376 st r29, r28
1377 {
1378 movei r30, 0
1379 j .Lresume_userspace
1380 }
1381 STD_ENDPROC(handle_syscall)
1382
1383
1384STD_ENTRY_SECTION(handle_syscall_link_address, .text.handle_syscall)
1385 lnk r0
1386 {
1387 addli r0, r0, .Lhandle_syscall_link - .
1388 jrp lr
1389 }
1390 STD_ENDPROC(handle_syscall_link_address)
1391
1392STD_ENTRY(ret_from_fork)
1393 jal sim_notify_fork
1394 jal schedule_tail
1395 FEEDBACK_REENTER(ret_from_fork)
1396 {
1397 movei r30, 0
1398 j .Lresume_userspace
1399 }
1400 STD_ENDPROC(ret_from_fork)
1401
1402STD_ENTRY(ret_from_kernel_thread)
1403 jal sim_notify_fork
1404 jal schedule_tail
1405 FEEDBACK_REENTER(ret_from_fork)
1406 {
1407 move r0, r31
1408 jalr r30
1409 }
1410 FEEDBACK_REENTER(ret_from_kernel_thread)
1411 {
1412 movei r30, 0
1413 j .Lresume_userspace
1414 }
1415 STD_ENDPROC(ret_from_kernel_thread)
1416
1417
1418
1419STD_ENTRY_LOCAL(_kernel_double_fault)
1420 mfspr r1, SPR_EX_CONTEXT_K_0
1421 move r2, lr
1422 move r3, sp
1423 move r4, r52
1424 addi sp, sp, -C_ABI_SAVE_AREA_SIZE
1425 j kernel_double_fault
1426 STD_ENDPROC(_kernel_double_fault)
1427
1428STD_ENTRY_LOCAL(bad_intr)
1429 mfspr r2, SPR_EX_CONTEXT_K_0
1430 panic "Unhandled interrupt %#x: PC %#lx"
1431 STD_ENDPROC(bad_intr)
1432
1433
1434
1435
1436
1437
1438
1439#define PTREGS_SYSCALL_SIGRETURN(x, reg) \
1440 STD_ENTRY(_
1441 addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \
1442 { \
1443 PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \
1444 j x \
1445 }; \
1446 STD_ENDPROC(_
1447
1448PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
1449#ifdef CONFIG_COMPAT
1450PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0)
1451#endif
1452
1453
1454STD_ENTRY(_sys_clone)
1455 push_extra_callee_saves r4
1456 j sys_clone
1457 STD_ENDPROC(_sys_clone)
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467 __HEAD
1468hand_unalign_slow:
1469 andi sp, sp, ~1
1470hand_unalign_slow_badsp:
1471 addi r3, r3, -(3 * 8)
1472 ld_add r0, r3, 8
1473 ld_add r1, r3, 8
1474 ld r2, r3
1475hand_unalign_slow_nonuser:
1476 mfspr r3, SPR_SYSTEM_SAVE_K_1
1477 __int_hand INT_UNALIGN_DATA, UNALIGN_DATA_SLOW, int_unalign
1478
1479
1480int_unalign:
1481 push_extra_callee_saves r0
1482 j do_unaligned
1483ENDPROC(hand_unalign_slow)
1484
1485
1486STD_ENTRY(fill_ra_stack)
1487 {
1488 move r0, lr
1489 jal 1f
1490 }
14911: jal 2f
14922: jal 3f
14933: jal 4f
14944: jrp r0
1495 STD_ENDPROC(fill_ra_stack)
1496
1497 .macro int_hand vecnum, vecname, c_routine, processing=handle_interrupt
1498 .org (\vecnum << 8)
1499 __int_hand \vecnum, \vecname, \c_routine, \processing
1500 .endm
1501
1502
1503 .section ".intrpt", "ax"
1504 .global intrpt_start
1505intrpt_start:
1506
1507#ifndef CONFIG_USE_PMC
1508#define handle_perf_interrupt bad_intr
1509#endif
1510
1511#ifndef CONFIG_HARDWALL
1512#define do_hardwall_trap bad_intr
1513#endif
1514
1515 int_hand INT_MEM_ERROR, MEM_ERROR, do_trap
1516 int_hand INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr
1517
1518 int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle
1519 int_hand INT_SINGLE_STEP_1, SINGLE_STEP_1, bad_intr
1520#else
1521 int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, bad_intr
1522 int_hand INT_SINGLE_STEP_1, SINGLE_STEP_1, gx_singlestep_handle
1523#endif
1524 int_hand INT_SINGLE_STEP_0, SINGLE_STEP_0, bad_intr
1525 int_hand INT_IDN_COMPLETE, IDN_COMPLETE, bad_intr
1526 int_hand INT_UDN_COMPLETE, UDN_COMPLETE, bad_intr
1527 int_hand INT_ITLB_MISS, ITLB_MISS, do_page_fault
1528 int_hand INT_ILL, ILL, do_trap
1529 int_hand INT_GPV, GPV, do_trap
1530 int_hand INT_IDN_ACCESS, IDN_ACCESS, do_trap
1531 int_hand INT_UDN_ACCESS, UDN_ACCESS, do_trap
1532 int_hand INT_SWINT_3, SWINT_3, do_trap
1533 int_hand INT_SWINT_2, SWINT_2, do_trap
1534 int_hand INT_SWINT_1, SWINT_1, SYSCALL, handle_syscall
1535 int_hand INT_SWINT_0, SWINT_0, do_trap
1536 int_hand INT_ILL_TRANS, ILL_TRANS, do_trap
1537 int_hand_unalign_fast INT_UNALIGN_DATA, UNALIGN_DATA
1538 int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault
1539 int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault
1540 int_hand INT_IDN_FIREWALL, IDN_FIREWALL, do_hardwall_trap
1541 int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap
1542 int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt
1543 int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr
1544 int_hand INT_UDN_TIMER, UDN_TIMER, bad_intr
1545 int_hand INT_IDN_AVAIL, IDN_AVAIL, bad_intr
1546 int_hand INT_UDN_AVAIL, UDN_AVAIL, bad_intr
1547 int_hand INT_IPI_3, IPI_3, bad_intr
1548
1549 int_hand INT_IPI_2, IPI_2, tile_dev_intr
1550 int_hand INT_IPI_1, IPI_1, bad_intr
1551#else
1552 int_hand INT_IPI_2, IPI_2, bad_intr
1553 int_hand INT_IPI_1, IPI_1, tile_dev_intr
1554#endif
1555 int_hand INT_IPI_0, IPI_0, bad_intr
1556 int_hand INT_PERF_COUNT, PERF_COUNT, \
1557 handle_perf_interrupt, handle_nmi
1558 int_hand INT_AUX_PERF_COUNT, AUX_PERF_COUNT, \
1559 handle_perf_interrupt, handle_nmi
1560 int_hand INT_INTCTRL_3, INTCTRL_3, bad_intr
1561
1562 dc_dispatch INT_INTCTRL_2, INTCTRL_2
1563 int_hand INT_INTCTRL_1, INTCTRL_1, bad_intr
1564#else
1565 int_hand INT_INTCTRL_2, INTCTRL_2, bad_intr
1566 dc_dispatch INT_INTCTRL_1, INTCTRL_1
1567#endif
1568 int_hand INT_INTCTRL_0, INTCTRL_0, bad_intr
1569 int_hand INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \
1570 hv_message_intr
1571 int_hand INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, bad_intr
1572 int_hand INT_I_ASID, I_ASID, bad_intr
1573 int_hand INT_D_ASID, D_ASID, bad_intr
1574 int_hand INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap
1575
1576
1577 int_hand INT_BREAKPOINT, BREAKPOINT, do_breakpoint
1578
1579 int_hand INT_NMI_DWNCL, NMI_DWNCL, do_nmi, handle_nmi
1580