1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <asm/asm-offsets.h>
34#include <asm/unistd.h>
35#include <asm/errno.h>
36#include <asm/page.h>
37#include <asm/psw.h>
38#include <asm/thread_info.h>
39#include <asm/assembly.h>
40#include <asm/processor.h>
41#include <asm/cache.h>
42
43#include <linux/linkage.h>
44
45
46
47
48
49#define KILL_INSN break 0,0
50
51 .level PA_ASM_LEVEL
52
53 .text
54
55 .import syscall_exit,code
56 .import syscall_exit_rfi,code
57
58
59
60
61
62
63
64
65
66 .align PAGE_SIZE
67ENTRY(linux_gateway_page)
68
69
70 .rept 44
71 KILL_INSN
72 .endr
73
74
75
76
77#define __NR_lws_entries (3)
78
79lws_entry:
80 gate lws_start, %r0
81 depi 3, 31, 2, %r31
82
83
84 .rept 10
85 KILL_INSN
86 .endr
87
88
89
90set_thread_pointer:
91 gate .+8, %r0
92 depi 3, 31, 2, %r31
93 be 0(%sr7,%r31)
94 mtctl %r26, %cr27
95
96
97
98 .rept 4
99 KILL_INSN
100 .endr
101
102
103 .align LINUX_GATEWAY_ADDR
104linux_gateway_entry:
105 gate .+8, %r0
106 mtsp %r0,%sr4
107 mtsp %r0,%sr5
108 mtsp %r0,%sr6
109
110#ifdef CONFIG_64BIT
111
112
113 ssm PSW_SM_W, %r1
114 extrd,u %r1,PSW_W_BIT,1,%r1
115
116
117 or,ev %r1,%r30,%r30
118 b,n 1f
119
120
121
122 depdi 0, 31, 32, %r26
123 depdi 0, 31, 32, %r25
124 depdi 0, 31, 32, %r24
125 depdi 0, 31, 32, %r23
126 depdi 0, 31, 32, %r22
127 depdi 0, 31, 32, %r21
1281:
129#endif
130
131
132
133
134 mfsp %sr7,%r1
135 rsm PSW_SM_I, %r0
136 mtsp %r1,%sr3
137
138 mfctl %cr30,%r1
139 xor %r1,%r30,%r30
140 xor %r1,%r30,%r1
141 xor %r1,%r30,%r30
142
143 ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30
144
145
146
147
148
149
150
151 mtsp %r0,%sr7
152 ssm PSW_SM_I, %r0
153 STREGM %r1,FRAME_SIZE(%r30)
154 mfctl %cr30,%r1
155 LDREG TI_TASK(%r1),%r1
156
157
158
159
160
161
162 STREG %r0, TASK_PT_PSW(%r1)
163 STREG %r2, TASK_PT_GR2(%r1)
164 STREG %r19, TASK_PT_GR19(%r1)
165
166 LDREGM -FRAME_SIZE(%r30), %r2
167#ifdef CONFIG_64BIT
168 extrd,u %r2,63,1,%r19
169
170 xor %r19,%r2,%r2
171 depd,z %r19,1,1,%r19
172 std %r19,TASK_PT_PSW(%r1)
173#endif
174#endif
175 STREG %r2, TASK_PT_GR30(%r1)
176
177 STREG %r20, TASK_PT_GR20(%r1)
178 STREG %r21, TASK_PT_GR21(%r1)
179 STREG %r22, TASK_PT_GR22(%r1)
180 STREG %r23, TASK_PT_GR23(%r1)
181 STREG %r24, TASK_PT_GR24(%r1)
182 STREG %r25, TASK_PT_GR25(%r1)
183 STREG %r26, TASK_PT_GR26(%r1)
184 STREG %r27, TASK_PT_GR27(%r1)
185 STREG %r28, TASK_PT_GR28(%r1)
186 STREG %r0, TASK_PT_ORIG_R28(%r1)
187 STREG %r29, TASK_PT_GR29(%r1)
188 STREG %r31, TASK_PT_GR31(%r1)
189
190 ldo TASK_PT_FR0(%r1), %r27
191 save_fp %r27
192
193 mfctl %cr11, %r27
194 STREG %r27, TASK_PT_SAR(%r1)
195
196 loadgp
197
198#ifdef CONFIG_64BIT
199 ldo -16(%r30),%r29
200 copy %r19,%r2
201#else
202
203
204 stw %r22, -52(%r30)
205 stw %r21, -56(%r30)
206#endif
207
208
209 mfctl %cr30, %r1
210 LDREG TI_FLAGS(%r1),%r1
211 ldi _TIF_SYSCALL_TRACE_MASK, %r19
212 and,COND(=) %r1, %r19, %r0
213 b,n .Ltracesys
214
215
216
217
218#ifdef CONFIG_64BIT
219 ldil L%sys_call_table, %r1
220 or,= %r2,%r2,%r2
221 addil L%(sys_call_table64-sys_call_table), %r1
222 ldo R%sys_call_table(%r1), %r19
223 or,= %r2,%r2,%r2
224 ldo R%sys_call_table64(%r1), %r19
225#else
226 load32 sys_call_table, %r19
227#endif
228 comiclr,>> __NR_Linux_syscalls, %r20, %r0
229 b,n .Lsyscall_nosys
230
231 LDREGX %r20(%r19), %r19
232
233
234
235
236
237
238 ldi __NR_rt_sigreturn,%r2
239 comb,= %r2,%r20,.Lrt_sigreturn
240.Lin_syscall:
241 ldil L%syscall_exit,%r2
242 be 0(%sr7,%r19)
243 ldo R%syscall_exit(%r2),%r2
244.Lrt_sigreturn:
245 comib,<> 0,%r25,.Lin_syscall
246 ldil L%syscall_exit_rfi,%r2
247 be 0(%sr7,%r19)
248 ldo R%syscall_exit_rfi(%r2),%r2
249
250
251
252
253
254
255.Lsyscall_nosys:
256syscall_nosys:
257 ldil L%syscall_exit,%r1
258 be R%syscall_exit(%sr7,%r1)
259 ldo -ENOSYS(%r0),%r28
260
261
262
263
264.Ltracesys:
265tracesys:
266
267
268
269
270
271
272
273
274
275 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
276 LDREG TI_TASK(%r1), %r1
277 ssm 0,%r2
278 STREG %r2,TASK_PT_PSW(%r1)
279 mfsp %sr0,%r2
280 STREG %r2,TASK_PT_SR0(%r1)
281 mfsp %sr1,%r2
282 STREG %r2,TASK_PT_SR1(%r1)
283 mfsp %sr2,%r2
284 STREG %r2,TASK_PT_SR2(%r1)
285 mfsp %sr3,%r2
286 STREG %r2,TASK_PT_SR3(%r1)
287 STREG %r2,TASK_PT_SR4(%r1)
288 STREG %r2,TASK_PT_SR5(%r1)
289 STREG %r2,TASK_PT_SR6(%r1)
290 STREG %r2,TASK_PT_SR7(%r1)
291 STREG %r2,TASK_PT_IASQ0(%r1)
292 STREG %r2,TASK_PT_IASQ1(%r1)
293 LDREG TASK_PT_GR31(%r1),%r2
294 STREG %r2,TASK_PT_IAOQ0(%r1)
295 ldo 4(%r2),%r2
296 STREG %r2,TASK_PT_IAOQ1(%r1)
297 ldo TASK_REGS(%r1),%r2
298
299 STREG %r3,PT_GR3(%r2)
300 STREG %r4,PT_GR4(%r2)
301 STREG %r5,PT_GR5(%r2)
302 STREG %r6,PT_GR6(%r2)
303 STREG %r7,PT_GR7(%r2)
304 STREG %r8,PT_GR8(%r2)
305 STREG %r9,PT_GR9(%r2)
306 STREG %r10,PT_GR10(%r2)
307 STREG %r11,PT_GR11(%r2)
308 STREG %r12,PT_GR12(%r2)
309 STREG %r13,PT_GR13(%r2)
310 STREG %r14,PT_GR14(%r2)
311 STREG %r15,PT_GR15(%r2)
312 STREG %r16,PT_GR16(%r2)
313 STREG %r17,PT_GR17(%r2)
314 STREG %r18,PT_GR18(%r2)
315
316
317 copy %r2,%r26
318 ldil L%do_syscall_trace_enter,%r1
319 ldil L%tracesys_next,%r2
320 be R%do_syscall_trace_enter(%sr7,%r1)
321 ldo R%tracesys_next(%r2),%r2
322
323tracesys_next:
324
325
326
327
328 copy %ret0,%r20
329
330 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
331 LDREG TI_TASK(%r1), %r1
332 LDREG TASK_PT_GR28(%r1), %r28
333 LDREG TASK_PT_GR26(%r1), %r26
334 LDREG TASK_PT_GR25(%r1), %r25
335 LDREG TASK_PT_GR24(%r1), %r24
336 LDREG TASK_PT_GR23(%r1), %r23
337 LDREG TASK_PT_GR22(%r1), %r22
338 LDREG TASK_PT_GR21(%r1), %r21
339#ifdef CONFIG_64BIT
340 ldo -16(%r30),%r29
341#else
342 stw %r22, -52(%r30)
343 stw %r21, -56(%r30)
344#endif
345
346 cmpib,COND(=),n -1,%r20,tracesys_exit
347 comiclr,>> __NR_Linux_syscalls, %r20, %r0
348 b,n .Ltracesys_nosys
349
350
351
352
353#ifdef CONFIG_64BIT
354 LDREG TASK_PT_GR30(%r1), %r19
355 extrd,u %r19,63,1,%r2
356
357 ldil L%sys_call_table, %r1
358 or,= %r2,%r2,%r2
359 addil L%(sys_call_table64-sys_call_table), %r1
360 ldo R%sys_call_table(%r1), %r19
361 or,= %r2,%r2,%r2
362 ldo R%sys_call_table64(%r1), %r19
363#else
364 load32 sys_call_table, %r19
365#endif
366
367 LDREGX %r20(%r19), %r19
368
369
370
371
372
373
374 ldi __NR_rt_sigreturn,%r2
375 comb,= %r2,%r20,.Ltrace_rt_sigreturn
376.Ltrace_in_syscall:
377 ldil L%tracesys_exit,%r2
378 be 0(%sr7,%r19)
379 ldo R%tracesys_exit(%r2),%r2
380
381.Ltracesys_nosys:
382 ldo -ENOSYS(%r0),%r28
383
384
385
386
387tracesys_exit:
388 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
389 LDREG TI_TASK(%r1), %r1
390#ifdef CONFIG_64BIT
391 ldo -16(%r30),%r29
392#endif
393 ldo TASK_REGS(%r1),%r26
394 BL do_syscall_trace_exit,%r2
395 STREG %r28,TASK_PT_GR28(%r1)
396 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
397 LDREG TI_TASK(%r1), %r1
398 LDREG TASK_PT_GR28(%r1), %r28
399
400 ldil L%syscall_exit,%r1
401 be,n R%syscall_exit(%sr7,%r1)
402
403.Ltrace_rt_sigreturn:
404 comib,<> 0,%r25,.Ltrace_in_syscall
405 ldil L%tracesys_sigexit,%r2
406 be 0(%sr7,%r19)
407 ldo R%tracesys_sigexit(%r2),%r2
408
409tracesys_sigexit:
410 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
411 LDREG TI_TASK(%r1), %r1
412#ifdef CONFIG_64BIT
413 ldo -16(%r30),%r29
414#endif
415 BL do_syscall_trace_exit,%r2
416 ldo TASK_REGS(%r1),%r26
417
418 ldil L%syscall_exit_rfi,%r1
419 be,n R%syscall_exit_rfi(%sr7,%r1)
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474lws_start:
475
476#ifdef CONFIG_64BIT
477 ssm PSW_SM_W, %r1
478 extrd,u %r1,PSW_W_BIT,1,%r1
479
480
481 or,ev %r1,%r30,%r30
482
483
484 depdi 0, 31, 32, %r20
485#endif
486
487
488 comiclr,>> __NR_lws_entries, %r20, %r0
489 b,n lws_exit_nosys
490
491
492 ldil L%lws_table, %r1
493 ldo R%lws_table(%r1), %r28
494 LDREGX %r20(%sr2,r28), %r21
495
496
497 be,n 0(%sr2,%r21)
498
499lws_exit_nosys:
500 ldo -ENOSYS(%r0),%r21
501
502
503lws_exit:
504#ifdef CONFIG_64BIT
505
506
507
508
509 extrd,u,*<> %r30,63,1,%r1
510 rsm PSW_SM_W, %r0
511
512 xor %r30,%r1,%r30
513#endif
514 be,n 0(%sr7, %r31)
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546#define ENABLE_LWS_DEBUG 0
547
548
549lws_compare_and_swap64:
550#ifdef CONFIG_64BIT
551 b,n lws_compare_and_swap
552#else
553
554
555
556
557 b,n lws_exit_nosys
558#endif
559
560
561lws_compare_and_swap32:
562#ifdef CONFIG_64BIT
563
564 depdi 0, 31, 32, %r26
565 depdi 0, 31, 32, %r25
566 depdi 0, 31, 32, %r24
567#endif
568
569lws_compare_and_swap:
570
571 ldil L%lws_lock_start, %r20
572 ldo R%lws_lock_start(%r20), %r28
573
574
575 extru %r26, 28, 8, %r20
576
577
578
579
580 shlw %r20, 4, %r20
581 add %r20, %r28, %r20
582
583
584
585
586
587
588
589
590
591 ldw 4(%sr2,%r20), %r28
592
593 mfctl %cr27, %r21
594 cmpb,<>,n %r21, %r28, cas_lock
595 b lws_exit
596 ldo -EDEADLOCK(%r0), %r21
597cas_lock:
598 cmpb,=,n %r0, %r28, cas_nocontend
599 ldo 1(%r0), %r28
600 b lws_exit
601 ldo -EAGAIN(%r0), %r21
602cas_nocontend:
603# endif
604
605
606 rsm PSW_SM_I, %r0
607
608 LDCW 0(%sr2,%r20), %r28
609 cmpb,<>,n %r0, %r28, cas_action
610cas_wouldblock:
611 ldo 2(%r0), %r28
612 ssm PSW_SM_I, %r0
613 b lws_exit
614 ldo -EAGAIN(%r0), %r21
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632cas_action:
633
634
635 mfctl %cr27, %r1
636 stw %r1, 4(%sr2,%r20)
637#endif
638
6391: ldw 0(%r26), %r28
640 sub,<> %r28, %r25, %r0
6412: stw %r24, 0(%r26)
642
643 stw,ma %r20, 0(%sr2,%r20)
644
645
646 stw %r0, 4(%sr2,%r20)
647#endif
648
649 ssm PSW_SM_I, %r0
650
651 b lws_exit
652 copy %r0, %r21
653
6543:
655
656
657 stw,ma %r20, 0(%sr2,%r20)
658
659 stw %r0, 4(%sr2,%r20)
660#endif
661 ssm PSW_SM_I, %r0
662 b lws_exit
663 ldo -EFAULT(%r0),%r21
664 nop
665 nop
666 nop
667 nop
668
669
670
671
672 ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 3b-linux_gateway_page)
673 ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 3b-linux_gateway_page)
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698lws_compare_and_swap_2:
699#ifdef CONFIG_64BIT
700
701
702 depdi 0, 31, 32, %r26
703 depdi 0, 31, 32, %r25
704 depdi 0, 31, 32, %r24
705#endif
706
707
708 subi,>>= 3, %r23, %r0
709 b,n lws_exit_nosys
710
711
712
713 shlw %r23, 2, %r29
714 blr %r29, %r0
715 nop
716
717
7184: ldb 0(%r25), %r25
719 b cas2_lock_start
7205: ldb 0(%r24), %r24
721 nop
722 nop
723 nop
724 nop
725 nop
726
727
7286: ldh 0(%r25), %r25
729 b cas2_lock_start
7307: ldh 0(%r24), %r24
731 nop
732 nop
733 nop
734 nop
735 nop
736
737
7388: ldw 0(%r25), %r25
739 b cas2_lock_start
7409: ldw 0(%r24), %r24
741 nop
742 nop
743 nop
744 nop
745 nop
746
747
748#ifdef CONFIG_64BIT
74910: ldd 0(%r25), %r25
75011: ldd 0(%r24), %r24
751#else
752
75310: ldw 0(%r25), %r22
75411: ldw 4(%r25), %r23
755
75612: flddx 0(%r24), %fr4
757#endif
758
759cas2_lock_start:
760
761 ldil L%lws_lock_start, %r20
762 ldo R%lws_lock_start(%r20), %r28
763
764
765 extru %r26, 28, 8, %r20
766
767
768
769
770 shlw %r20, 4, %r20
771 add %r20, %r28, %r20
772
773 rsm PSW_SM_I, %r0
774
775 LDCW 0(%sr2,%r20), %r28
776 cmpb,<>,n %r0, %r28, cas2_action
777cas2_wouldblock:
778 ldo 2(%r0), %r28
779 ssm PSW_SM_I, %r0
780 b lws_exit
781 ldo -EAGAIN(%r0), %r21
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799cas2_action:
800
801 blr %r29, %r0
802
803 ldo 1(%r0),%r28
804
805
80613: ldb 0(%r26), %r29
807 sub,= %r29, %r25, %r0
808 b,n cas2_end
80914: stb %r24, 0(%r26)
810 b cas2_end
811 copy %r0, %r28
812 nop
813 nop
814
815
81615: ldh 0(%r26), %r29
817 sub,= %r29, %r25, %r0
818 b,n cas2_end
81916: sth %r24, 0(%r26)
820 b cas2_end
821 copy %r0, %r28
822 nop
823 nop
824
825
82617: ldw 0(%r26), %r29
827 sub,= %r29, %r25, %r0
828 b,n cas2_end
82918: stw %r24, 0(%r26)
830 b cas2_end
831 copy %r0, %r28
832 nop
833 nop
834
835
836#ifdef CONFIG_64BIT
83719: ldd 0(%r26), %r29
838 sub,*= %r29, %r25, %r0
839 b,n cas2_end
84020: std %r24, 0(%r26)
841 copy %r0, %r28
842#else
843
84419: ldw 0(%r26), %r29
845 sub,= %r29, %r22, %r0
846 b,n cas2_end
847
84820: ldw 4(%r26), %r29
849 sub,= %r29, %r23, %r0
850 b,n cas2_end
851
85221: fstdx %fr4, 0(%r26)
853 copy %r0, %r28
854#endif
855
856cas2_end:
857
858 stw,ma %r20, 0(%sr2,%r20)
859
860 ssm PSW_SM_I, %r0
861
862 b lws_exit
863 copy %r0, %r21
864
86522:
866
867
868 stw,ma %r20, 0(%sr2,%r20)
869 ssm PSW_SM_I, %r0
870 ldo 1(%r0),%r28
871 b lws_exit
872 ldo -EFAULT(%r0),%r21
873 nop
874 nop
875 nop
876
877
878
879 ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 22b-linux_gateway_page)
880 ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gateway_page, 22b-linux_gateway_page)
881 ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gateway_page, 22b-linux_gateway_page)
882 ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gateway_page, 22b-linux_gateway_page)
883 ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gateway_page, 22b-linux_gateway_page)
884 ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gateway_page, 22b-linux_gateway_page)
885 ASM_EXCEPTIONTABLE_ENTRY(10b-linux_gateway_page, 22b-linux_gateway_page)
886 ASM_EXCEPTIONTABLE_ENTRY(11b-linux_gateway_page, 22b-linux_gateway_page)
887 ASM_EXCEPTIONTABLE_ENTRY(13b-linux_gateway_page, 22b-linux_gateway_page)
888 ASM_EXCEPTIONTABLE_ENTRY(14b-linux_gateway_page, 22b-linux_gateway_page)
889 ASM_EXCEPTIONTABLE_ENTRY(15b-linux_gateway_page, 22b-linux_gateway_page)
890 ASM_EXCEPTIONTABLE_ENTRY(16b-linux_gateway_page, 22b-linux_gateway_page)
891 ASM_EXCEPTIONTABLE_ENTRY(17b-linux_gateway_page, 22b-linux_gateway_page)
892 ASM_EXCEPTIONTABLE_ENTRY(18b-linux_gateway_page, 22b-linux_gateway_page)
893 ASM_EXCEPTIONTABLE_ENTRY(19b-linux_gateway_page, 22b-linux_gateway_page)
894 ASM_EXCEPTIONTABLE_ENTRY(20b-linux_gateway_page, 22b-linux_gateway_page)
895#ifndef CONFIG_64BIT
896 ASM_EXCEPTIONTABLE_ENTRY(12b-linux_gateway_page, 22b-linux_gateway_page)
897 ASM_EXCEPTIONTABLE_ENTRY(21b-linux_gateway_page, 22b-linux_gateway_page)
898#endif
899
900
901 .align PAGE_SIZE
902END(linux_gateway_page)
903ENTRY(end_linux_gateway_page)
904
905
906
907
908#define LWS_ENTRY(_name_) ASM_ULONG_INSN (lws_
909
910 .section .rodata,"a"
911
912 .align 8
913
914
915ENTRY(lws_table)
916 LWS_ENTRY(compare_and_swap32)
917 LWS_ENTRY(compare_and_swap64)
918 LWS_ENTRY(compare_and_swap_2)
919END(lws_table)
920
921
922#ifdef CONFIG_64BIT
923#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
924#else
925#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
926#endif
927#define __SYSCALL(nr, entry) ASM_ULONG_INSN entry
928 .align 8
929ENTRY(sys_call_table)
930 .export sys_call_table,data
931#include <asm/syscall_table_32.h>
932END(sys_call_table)
933
934#ifdef CONFIG_64BIT
935 .align 8
936ENTRY(sys_call_table64)
937#include <asm/syscall_table_64.h>
938END(sys_call_table64)
939#endif
940
941
942
943
944
945
946
947
948
949 .section .data
950 .align L1_CACHE_BYTES
951ENTRY(lws_lock_start)
952
953 .rept 256
954
955 .word 1
956 .word 0
957 .word 0
958 .word 0
959 .endr
960END(lws_lock_start)
961 .previous
962
963.end
964