Subversion Repositories HelenOS

Rev

Rev 3863 | Rev 4068 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3863 Rev 3993
Line 45... Line 45...
45
#include <arch/trap/sun4v/mmu.h>
45
#include <arch/trap/sun4v/mmu.h>
46
#include <arch/mm/sun4v/mmu.h>
46
#include <arch/mm/sun4v/mmu.h>
47
#include <arch/mm/page.h>
47
#include <arch/mm/page.h>
48
#include <arch/stack.h>
48
#include <arch/stack.h>
49
#include <arch/sun4v/regdef.h>
49
#include <arch/sun4v/regdef.h>
-
 
50
#include <arch/sun4v/arch.h>
-
 
51
#include <arch/sun4v/cpu.h>
50
 
52
 
51
#define TABLE_SIZE	TRAP_TABLE_SIZE
53
#define TABLE_SIZE	TRAP_TABLE_SIZE
52
#define ENTRY_SIZE	TRAP_TABLE_ENTRY_SIZE
54
#define ENTRY_SIZE	TRAP_TABLE_ENTRY_SIZE
53
 
55
 
54
/*
56
/*
Line 290... Line 292...
290
 
292
 
291
/* TT = 0x6c, TL = 0, fast_data_access_protection */
293
/* TT = 0x6c, TL = 0, fast_data_access_protection */
292
.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
294
.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
293
.global fast_data_access_protection_handler_tl0
295
.global fast_data_access_protection_handler_tl0
294
fast_data_access_protection_handler_tl0:
296
fast_data_access_protection_handler_tl0:
295
	/*FAST_DATA_ACCESS_PROTECTION_HANDLER 0*/
297
	FAST_DATA_ACCESS_PROTECTION_HANDLER 0
296
 
298
 
297
/* TT = 0x80, TL = 0, spill_0_normal handler */
299
/* TT = 0x80, TL = 0, spill_0_normal handler */
298
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
300
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
299
.global spill_0_normal_tl0
301
.global spill_0_normal_tl0
300
spill_0_normal_tl0:
302
spill_0_normal_tl0:
Line 522... Line 524...
522
	wrpr \tmpreg2, %cwp
524
	wrpr \tmpreg2, %cwp
523
 
525
 
524
	restored
526
	restored
525
.endm
527
.endm
526
 
528
 
-
 
529
#define NOT(x)	((x) == 0)
-
 
530
 
527
/*
531
/*
-
 
532
 * Perform all the actions of the preemptible trap handler which are common
-
 
533
 * for trapping from kernel and trapping from userspace, including call of the
-
 
534
 * higher level service routine.
-
 
535
 *
-
 
536
 * Important note:
-
 
537
 * 	This macro must be inserted between the "2:" and "4:" labels. The
528
 * Preemptible trap handler for handling traps from kernel.
538
 *	inserting code must be aware of the usage of all the registers
-
 
539
 *	contained in this macro.
529
 */
540
 */
530
.macro PREEMPTIBLE_HANDLER_KERNEL
541
.macro MIDDLE_PART is_syscall
531
 
-
 
532
	/*
-
 
533
	 * ASSERT(%tl == 1)
-
 
534
	 */
-
 
535
	rdpr %tl, %g3
-
 
536
	cmp %g3, 1
-
 
537
	be 1f
-
 
538
	nop
-
 
539
0:	ba 0b					! this is for debugging, if we ever get here
-
 
540
	nop					! it will be easy to find
-
 
541
 
-
 
542
	/* prevent unnecessary CLEANWIN exceptions */
-
 
543
	wrpr %g0, NWINDOWS - 1, %cleanwin
-
 
544
1:
-
 
545
	/*
-
 
546
	 * Prevent SAVE instruction from causing a spill exception. If the
-
 
547
	 * CANSAVE register is zero, explicitly spill register window
-
 
548
	 * at CWP + 2.
-
 
549
	 */
-
 
550
 
-
 
551
	rdpr %cansave, %g3
-
 
552
	brnz %g3, 2f
-
 
553
	nop
-
 
554
	INLINE_SPILL %g3, %g4
-
 
555
 
-
 
556
2:
-
 
557
	/* ask for new register window */
-
 
558
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
559
 
-
 
560
	/* copy higher level routine's address and its argument */
542
	/* copy higher level routine's address and its argument */
561
	mov %g1, %l0
543
	mov %g1, %l0
-
 
544
.if NOT(\is_syscall)
562
	mov %g2, %o0
545
	mov %g2, %o0
-
 
546
.else
-
 
547
	! store the syscall number on the stack as 7th argument
-
 
548
	stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6] 
-
 
549
.endif
563
 
550
 
564
	/*
551
	/*
565
	 * Save TSTATE, TPC and TNPC aside.
552
	 * Save TSTATE, TPC and TNPC aside.
566
	 */
553
	 */
567
	rdpr %tstate, %g1
554
	rdpr %tstate, %g1
Line 588... Line 575...
588
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
575
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
589
 
576
 
590
	/* g1 -> l1, ..., g7 -> l7 */
577
	/* g1 -> l1, ..., g7 -> l7 */
591
	SAVE_GLOBALS
578
	SAVE_GLOBALS
592
 
579
 
-
 
580
.if NOT(\is_syscall)
593
	/* call higher-level service routine, pass istate as its 2nd parameter */
581
	/* call higher-level service routine, pass istate as its 2nd parameter */
594
	call %l0
582
	call %l0
595
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
583
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
-
 
584
.else
-
 
585
	/* Call the higher-level syscall handler. */
-
 
586
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
-
 
587
	call syscall_handler
-
 
588
	nop
-
 
589
	/* copy the value returned by the syscall */
-
 
590
	mov %o0, %i0
-
 
591
.endif
596
 
592
 
597
	/* l1 -> g1, ..., l7 -> g7 */
593
	/* l1 -> g1, ..., l7 -> g7 */
598
	RESTORE_GLOBALS
594
	RESTORE_GLOBALS
599
 
595
 
600
	/* we must prserve the PEF bit */
596
	/* we must prserve the PEF bit */
Line 661... Line 657...
661
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
657
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
662
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
658
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
663
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
659
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
664
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
660
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
665
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
661
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
-
 
662
.endm
-
 
663
 
-
 
664
/*
-
 
665
 * Preemptible trap handler for handling traps from kernel.
-
 
666
 */
-
 
667
.macro PREEMPTIBLE_HANDLER_KERNEL
-
 
668
 
-
 
669
	/*
-
 
670
	 * ASSERT(%tl == 1)
-
 
671
	 */
-
 
672
	rdpr %tl, %g3
-
 
673
	cmp %g3, 1
-
 
674
	be 1f
-
 
675
	nop
-
 
676
0:	ba 0b					! this is for debugging, if we ever get here
-
 
677
	nop					! it will be easy to find
-
 
678
 
-
 
679
1:
-
 
680
	/* prevent unnecessary CLEANWIN exceptions */
-
 
681
	wrpr %g0, NWINDOWS - 1, %cleanwin
-
 
682
 
-
 
683
	/*
-
 
684
	 * Prevent SAVE instruction from causing a spill exception. If the
-
 
685
	 * CANSAVE register is zero, explicitly spill register window
-
 
686
	 * at CWP + 2.
-
 
687
	 */
-
 
688
 
-
 
689
	rdpr %cansave, %g3
-
 
690
	brnz %g3, 2f
-
 
691
	nop
-
 
692
	INLINE_SPILL %g3, %g4
-
 
693
 
-
 
694
2:
-
 
695
	/* ask for new register window */
-
 
696
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
697
 
-
 
698
	MIDDLE_PART 0
666
 
699
 
667
4:
700
4:
668
	/*
701
	/*
669
	 * Prevent RESTORE instruction from causing a fill exception. If the
702
	 * Prevent RESTORE instruction from causing a fill exception. If the
670
	 * CANRESTORE register is zero, explicitly fill register window
703
	 * CANRESTORE register is zero, explicitly fill register window
Line 679... Line 712...
679
	restore
712
	restore
680
 
713
 
681
	retry
714
	retry
682
.endm
715
.endm
683
 
716
 
-
 
717
/*
-
 
718
 * Spills the window at CWP + 2 to the userspace window buffer. This macro
-
 
719
 * is to be used before doing SAVE when the spill trap is undesirable.
-
 
720
 * 
-
 
721
 * Parameters:
-
 
722
 * 	tmpreg1		global register to be used for scratching purposes
-
 
723
 * 	tmpreg2		global register to be used for scratching purposes
-
 
724
 * 	tmpreg3		global register to be used for scratching purposes
-
 
725
 */
-
 
726
.macro INLINE_SPILL_TO_WBUF tmpreg1, tmpreg2, tmpreg3
-
 
727
	! CWP := CWP + 2
-
 
728
	rdpr %cwp, \tmpreg2
-
 
729
	add \tmpreg2, 2, \tmpreg1
-
 
730
	and \tmpreg1, NWINDOWS - 1, \tmpreg1		! modulo NWINDOWS
-
 
731
	wrpr \tmpreg1, %cwp
-
 
732
	
-
 
733
	! spill to userspace window buffer
-
 
734
	SAVE_TO_USPACE_WBUF \tmpreg3, \tmpreg1
684
 
735
 
-
 
736
	! CWP := CWP - 2
-
 
737
	wrpr \tmpreg2, %cwp
-
 
738
 
-
 
739
	saved
-
 
740
.endm
-
 
741
 
-
 
742
/*
-
 
743
 * Preemptible handler for handling traps from userspace.
-
 
744
 */
-
 
745
.macro PREEMPTIBLE_HANDLER_USPACE is_syscall
-
 
746
	/*
-
 
747
	 * One of the ways this handler can be invoked is after a nested MMU trap from
-
 
748
	 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
-
 
749
	 * the CWP register. We deal with the situation by simulating the MMU trap
-
 
750
	 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
-
 
751
	 * trap is resolved. However, because we are in the wrong window from the
-
 
752
	 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
-
 
753
	 */ 
685
#define NOT(x)	((x) == 0)
754
.if NOT(\is_syscall)
-
 
755
	rdpr %tstate, %g3
-
 
756
	and %g3, TSTATE_CWP_MASK, %g4
-
 
757
	wrpr %g4, 0, %cwp			! resynchronize CWP
-
 
758
.endif
-
 
759
 
-
 
760
	/* prevent unnecessary CLEANWIN exceptions */
-
 
761
	wrpr %g0, NWINDOWS - 1, %cleanwin
-
 
762
 
-
 
763
	/*
-
 
764
	 * Prevent SAVE instruction from causing a spill exception. If the
-
 
765
	 * CANSAVE register is zero, explicitly spill register window
-
 
766
	 * at CWP + 2.
-
 
767
	 */
-
 
768
	rdpr %cansave, %g3
-
 
769
	brnz %g3, 2f
-
 
770
	nop
-
 
771
	INLINE_SPILL_TO_WBUF %g3, %g4, %g7
-
 
772
 
-
 
773
2:
-
 
774
	get_kstack_wbuf_ptr %g3, %g4
-
 
775
	ldx [%g4], %g6
-
 
776
	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
777
 
-
 
778
.if \is_syscall
-
 
779
	/* Copy arguments for the syscall to the new window. */
-
 
780
	mov %i0, %o0
-
 
781
	mov %i1, %o1
-
 
782
	mov %i2, %o2
-
 
783
	mov %i3, %o3
-
 
784
	mov %i4, %o4
-
 
785
	mov %i5, %o5
-
 
786
.endif
-
 
787
 
-
 
788
	mov VA_PRIMARY_CONTEXT_REG, %l0 
-
 
789
	stxa %g0, [%l0] ASI_PRIMARY_CONTEXT_REG
-
 
790
	rd %pc, %l0
-
 
791
	flush %l0
-
 
792
 
-
 
793
	/* Mark the CANRESTORE windows as OTHER windows. */
-
 
794
	rdpr %canrestore, %l0
-
 
795
	wrpr %l0, %otherwin
-
 
796
	wrpr %g0, %canrestore
-
 
797
 
-
 
798
	/*
-
 
799
	 * Other window spills will go to the userspace window buffer
-
 
800
	 * and normal spills will go to the kernel stack.
-
 
801
	 */
-
 
802
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
-
 
803
 
-
 
804
	MIDDLE_PART \is_syscall
-
 
805
 
-
 
806
4:
-
 
807
	/*
-
 
808
	 * Spills and fills will be processed by the {spill,fill}_1_normal
-
 
809
	 * handlers.
-
 
810
	 */
-
 
811
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
-
 
812
 
-
 
813
	/*
-
 
814
	 * Set primary context according to secondary context.
-
 
815
	 */
-
 
816
	wr %g0, ASI_SECONDARY_CONTEXT_REG, %asi
-
 
817
	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
-
 
818
	wr %g0, ASI_PRIMARY_CONTEXT_REG, %asi
-
 
819
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
-
 
820
	rd %pc, %g1
-
 
821
	flush %g1
-
 
822
 
-
 
823
	/* Restoring userspace windows: */
-
 
824
 
-
 
825
	/* Save address of the userspace window buffer to the %g7 register. */
-
 
826
	get_kstack_wbuf_ptr %g1, %g5
-
 
827
	ldx [%g5 + 8], %g7
-
 
828
 
-
 
829
	rdpr %cwp, %g1
-
 
830
	rdpr %otherwin, %g2
-
 
831
 
-
 
832
	/*
-
 
833
	 * Skip all OTHERWIN windows and descend to the first window
-
 
834
	 * in the userspace window buffer.
-
 
835
	 */
-
 
836
	sub %g1, %g2, %g3
-
 
837
	dec %g3
-
 
838
	and %g3, NWINDOWS - 1, %g3
-
 
839
	wrpr %g3, 0, %cwp
-
 
840
 
-
 
841
	/*
-
 
842
	 * CWP is now in the window last saved in the userspace window buffer.
-
 
843
	 * Fill all windows stored in the buffer.
-
 
844
	 */
-
 
845
	clr %g4
-
 
846
5:	andcc %g7, UWB_ALIGNMENT - 1, %g0	! alignment check
-
 
847
	bz 6f					! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
-
 
848
	nop
-
 
849
 
-
 
850
	add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
-
 
851
	ldx [%g7 + L0_OFFSET], %l0
-
 
852
	ldx [%g7 + L1_OFFSET], %l1
-
 
853
	ldx [%g7 + L2_OFFSET], %l2
-
 
854
	ldx [%g7 + L3_OFFSET], %l3
-
 
855
	ldx [%g7 + L4_OFFSET], %l4
-
 
856
	ldx [%g7 + L5_OFFSET], %l5
-
 
857
	ldx [%g7 + L6_OFFSET], %l6
-
 
858
	ldx [%g7 + L7_OFFSET], %l7
-
 
859
	ldx [%g7 + I0_OFFSET], %i0
-
 
860
	ldx [%g7 + I1_OFFSET], %i1
-
 
861
	ldx [%g7 + I2_OFFSET], %i2
-
 
862
	ldx [%g7 + I3_OFFSET], %i3
-
 
863
	ldx [%g7 + I4_OFFSET], %i4
-
 
864
	ldx [%g7 + I5_OFFSET], %i5
-
 
865
	ldx [%g7 + I6_OFFSET], %i6
-
 
866
	ldx [%g7 + I7_OFFSET], %i7
-
 
867
 
-
 
868
	dec %g3
-
 
869
	and %g3, NWINDOWS - 1, %g3
-
 
870
	wrpr %g3, 0, %cwp			! switch to the preceeding window
-
 
871
 
-
 
872
	ba 5b
-
 
873
	inc %g4
-
 
874
 
-
 
875
6:
-
 
876
	/* Save changes of the address of the userspace window buffer. */
-
 
877
	stx %g7, [%g5 + 8]
-
 
878
 
-
 
879
	/*
-
 
880
	 * Switch back to the proper current window and adjust
-
 
881
	 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
-
 
882
	 */
-
 
883
	wrpr %g1, 0, %cwp
-
 
884
	add %g4, %g2, %g2
-
 
885
	cmp %g2, NWINDOWS - 2
-
 
886
	bg 8f					! fix the CANRESTORE=NWINDOWS-1 anomaly
-
 
887
	mov NWINDOWS - 2, %g1			! use dealy slot for both cases
-
 
888
	sub %g1, %g2, %g1
-
 
889
	
-
 
890
	wrpr %g0, 0, %otherwin
-
 
891
	wrpr %g1, 0, %cansave			! NWINDOWS - 2 - CANRESTORE
-
 
892
	wrpr %g2, 0, %canrestore		! OTHERWIN + windows in the buffer
-
 
893
	wrpr %g2, 0, %cleanwin			! avoid information leak
-
 
894
 
-
 
895
7:
-
 
896
	restore
-
 
897
 
-
 
898
.if \is_syscall
-
 
899
	done
-
 
900
.else
-
 
901
	retry
-
 
902
.endif
-
 
903
 
-
 
904
8:
-
 
905
	/*
-
 
906
	 * We got here in order to avoid inconsistency of the window state registers.
-
 
907
	 * If the:
-
 
908
	 *
-
 
909
	 * 	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
910
	 *
-
 
911
	 * instruction trapped and spilled a register window into the userspace
-
 
912
	 * window buffer, we have just restored NWINDOWS - 1 register windows.
-
 
913
	 * However, CANRESTORE can be only NWINDOW - 2 at most.
-
 
914
	 *
-
 
915
	 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
-
 
916
	 * and set the window state registers so that:
-
 
917
	 *
-
 
918
	 * 	CANRESTORE 	= NWINDOWS - 2
-
 
919
	 *	CLEANWIN	= NWINDOWS - 2
-
 
920
	 *	CANSAVE 	= 0
-
 
921
	 *	OTHERWIN	= 0
-
 
922
	 *
-
 
923
	 * The RESTORE instruction is therfore to be skipped.
-
 
924
	 */
-
 
925
	wrpr %g0, 0, %otherwin
-
 
926
	wrpr %g0, 0, %cansave
-
 
927
	wrpr %g1, 0, %canrestore
-
 
928
	wrpr %g1, 0, %cleanwin
-
 
929
 
-
 
930
	rdpr %cwp, %g1
-
 
931
	dec %g1
-
 
932
	and %g1, NWINDOWS - 1, %g1
-
 
933
	wrpr %g1, 0, %cwp			! CWP--
-
 
934
	
-
 
935
.if \is_syscall
-
 
936
	done
-
 
937
.else
-
 
938
	retry
-
 
939
.endif
-
 
940
 
-
 
941
.endm
686
 
942
 
687
/* Preemptible trap handler for TL=1.
943
/* Preemptible trap handler for TL=1.
688
 *
944
 *
689
 * This trap handler makes arrangements to make calling of scheduler() from
945
 * This trap handler makes arrangements to make calling of scheduler() from
690
 * within a trap context possible. It is called from several other trap
946
 * within a trap context possible. It is called from several other trap
691
 * handlers.
947
 * handlers.
692
 */
948
 */
693
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
949
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
-
 
950
	rdpr %tstate, %g3
-
 
951
	and %g3, TSTATE_PRIV_BIT, %g3
-
 
952
	brz %g3, 100f			! trapping from userspace
-
 
953
	nop
-
 
954
 
694
	PREEMPTIBLE_HANDLER_KERNEL
955
	PREEMPTIBLE_HANDLER_KERNEL
-
 
956
	ba 101f
-
 
957
	nop
-
 
958
 
-
 
959
	100:
-
 
960
	PREEMPTIBLE_HANDLER_USPACE \is_syscall
-
 
961
 
-
 
962
	101:
695
.endm
963
.endm
696
 
964
 
697
.global preemptible_handler
965
.global preemptible_handler
698
preemptible_handler:
966
preemptible_handler:
699
	PREEMPTIBLE_HANDLER_TEMPLATE 0
967
	PREEMPTIBLE_HANDLER_TEMPLATE 0