Subversion Repositories HelenOS

Rev

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

Rev 3743 Rev 3798
Line 444... Line 444...
444
	FILL_NORMAL_HANDLER_KERNEL
444
	FILL_NORMAL_HANDLER_KERNEL
445
 
445
 
446
.align TABLE_SIZE
446
.align TABLE_SIZE
447
 
447
 
448
 
448
 
-
 
449
/*
-
 
450
 * Spills the window at CWP + 2 to the kernel stack. This macro is to be
-
 
451
 * used before doing SAVE when the spill trap is undesirable.
-
 
452
 */
-
 
453
.macro INLINE_SPILL
-
 
454
	! CWP := CWP + 2
-
 
455
	rdpr %cwp, %g3
-
 
456
	add %g3, 2, %g3
-
 
457
	and %g3, NWINDOWS - 1, %g3		! modulo NWINDOWS
-
 
458
	wrpr %g3, %cwp
-
 
459
	
-
 
460
	! spill to kernel stack
-
 
461
	stx %l0, [%sp + STACK_BIAS + L0_OFFSET]	
-
 
462
	stx %l1, [%sp + STACK_BIAS + L1_OFFSET]
-
 
463
	stx %l2, [%sp + STACK_BIAS + L2_OFFSET]
-
 
464
	stx %l3, [%sp + STACK_BIAS + L3_OFFSET]
-
 
465
	stx %l4, [%sp + STACK_BIAS + L4_OFFSET]
-
 
466
	stx %l5, [%sp + STACK_BIAS + L5_OFFSET]
-
 
467
	stx %l6, [%sp + STACK_BIAS + L6_OFFSET]
-
 
468
	stx %l7, [%sp + STACK_BIAS + L7_OFFSET]
-
 
469
	stx %i0, [%sp + STACK_BIAS + I0_OFFSET]
-
 
470
	stx %i1, [%sp + STACK_BIAS + I1_OFFSET]
-
 
471
	stx %i2, [%sp + STACK_BIAS + I2_OFFSET]
-
 
472
	stx %i3, [%sp + STACK_BIAS + I3_OFFSET]
-
 
473
	stx %i4, [%sp + STACK_BIAS + I4_OFFSET]
-
 
474
	stx %i5, [%sp + STACK_BIAS + I5_OFFSET]
-
 
475
	stx %i6, [%sp + STACK_BIAS + I6_OFFSET]
-
 
476
	stx %i7, [%sp + STACK_BIAS + I7_OFFSET]
-
 
477
 
-
 
478
	! CWP := CWP - 2
449
#define NOT(x)	((x) == 0)
479
	add %g3, NWINDOWS - 2, %g3
-
 
480
	and %g3, NWINDOWS - 1, %g3		! modulo NWINDOWS
-
 
481
	wrpr %g3, %cwp
450
 
482
 
451
/* Preemptible trap handler for TL=1.
-
 
452
 *
-
 
453
 * This trap handler makes arrangements to make calling of scheduler() from
-
 
454
 * within a trap context possible. It is called from several other trap
-
 
455
 * handlers.
483
	saved
456
 *
484
.endm
457
 * This function can be entered either with interrupt globals or alternate
-
 
458
 * globals. Memory management trap handlers are obliged to switch to one of
-
 
459
 * those global sets prior to calling this function. Register window management
-
 
460
 * functions are not allowed to modify the alternate global registers.
-
 
461
 *
485
 
462
 * The kernel is designed to work on trap levels 0 - 4. For instance, the
-
 
463
 * following can happen:
-
 
464
 * TL0: kernel thread runs (CANSAVE=0, kernel stack not in DTLB)
-
 
465
 * TL1: preemptible trap handler started after a tick interrupt
-
 
466
 * TL2: preemptible trap handler did SAVE
-
 
467
 * TL3: spill handler touched the kernel stack  
-
 
468
 * TL4: hardware or software failure
-
 
469
 *
486
/*
470
 * Input registers:
-
 
471
 *	%g1		Address of function to call if this is not a syscall.
487
 * Fill the window at CWP - 1 from the kernel stack. This macro is to be
472
 * 	%g2	 	First argument for the function.
-
 
473
 *	%g6		Pre-set as kernel stack base if trap from userspace.
488
 * used before doing RESTORE when the fill trap is undesirable.
474
 *	%g7		Pre-set as address of the userspace window buffer.
-
 
475
 */
489
 */
-
 
490
.macro INLINE_FILL
-
 
491
	! CWP := CWP - 1
-
 
492
	rdpr %cwp, %g3
-
 
493
	add %g3, NWINDOWS - 1, %g3
-
 
494
	and %g3, NWINDOWS - 1, %g3
-
 
495
	wrpr %g3, %cwp
-
 
496
 
-
 
497
	! fill
-
 
498
	ldx [%sp + STACK_BIAS + L0_OFFSET], %l0
-
 
499
	ldx [%sp + STACK_BIAS + L1_OFFSET], %l1
-
 
500
	ldx [%sp + STACK_BIAS + L2_OFFSET], %l2
-
 
501
	ldx [%sp + STACK_BIAS + L3_OFFSET], %l3
-
 
502
	ldx [%sp + STACK_BIAS + L4_OFFSET], %l4
-
 
503
	ldx [%sp + STACK_BIAS + L5_OFFSET], %l5
-
 
504
	ldx [%sp + STACK_BIAS + L6_OFFSET], %l6
-
 
505
	ldx [%sp + STACK_BIAS + L7_OFFSET], %l7
-
 
506
	ldx [%sp + STACK_BIAS + I0_OFFSET], %i0
-
 
507
	ldx [%sp + STACK_BIAS + I1_OFFSET], %i1
-
 
508
	ldx [%sp + STACK_BIAS + I2_OFFSET], %i2
-
 
509
	ldx [%sp + STACK_BIAS + I3_OFFSET], %i3
-
 
510
	ldx [%sp + STACK_BIAS + I4_OFFSET], %i4
-
 
511
	ldx [%sp + STACK_BIAS + I5_OFFSET], %i5
-
 
512
	ldx [%sp + STACK_BIAS + I6_OFFSET], %i6
-
 
513
	ldx [%sp + STACK_BIAS + I7_OFFSET], %i7
-
 
514
 
-
 
515
	! CWP := CWP + 1
-
 
516
	add %g3, 1, %g3
-
 
517
	and %g3, NWINDOWS - 1, %g3
-
 
518
	wrpr %g3, %cwp
-
 
519
 
-
 
520
	restored
-
 
521
.endm
-
 
522
 
-
 
523
/*
-
 
524
 * Preemptible trap handler for handling traps from kernel.
-
 
525
 */
476
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
526
.macro PREEMPTIBLE_HANDLER_KERNEL
477
#if 0
527
 
478
	/*
528
	/*
479
	 * ASSERT(%tl == 1)
529
	 * ASSERT(%tl == 1)
480
	 */
530
	 */
481
	rdpr %tl, %g3
531
	rdpr %tl, %g3
482
	cmp %g3, 1
532
	cmp %g3, 1
483
	be 1f
533
	be 1f
484
	nop
534
	nop
485
0:	ba 0b					! this is for debugging, if we ever get here
535
0:	ba 0b					! this is for debugging, if we ever get here
486
	nop					! it will be easy to find
536
	nop					! it will be easy to find
487
 
537
 
-
 
538
	/* prevent unnecessary CLEANWIN exceptions */
-
 
539
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
488
1:
540
1:
489
.if NOT(\is_syscall)
-
 
490
	rdpr %tstate, %g3
-
 
491
	
-
 
492
	/*
-
 
493
	 * One of the ways this handler can be invoked is after a nested MMU trap from
-
 
494
	 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
-
 
495
	 * the CWP register. We deal with the situation by simulating the MMU trap
-
 
496
	 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
-
 
497
	 * trap is resolved. However, because we are in the wrong window from the
-
 
498
	 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
-
 
499
	 */ 
-
 
500
	and %g3, TSTATE_CWP_MASK, %g4
-
 
501
	wrpr %g4, 0, %cwp			! resynchronize CWP
-
 
502
 
-
 
503
	andcc %g3, TSTATE_PRIV_BIT, %g0		! if this trap came from the privileged mode...
-
 
504
	bnz 0f					! ...skip setting of kernel stack and primary context
-
 
505
	nop
-
 
506
	
-
 
507
.endif
-
 
508
	/*
-
 
509
	 * Normal window spills will go to the userspace window buffer.
-
 
510
	 */
-
 
511
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
-
 
512
 
-
 
513
	wrpr %g0, NWINDOWS - 1, %cleanwin	! prevent unnecessary clean_window exceptions
-
 
514
 
-
 
515
	/*
541
	/*
516
	 * Switch to kernel stack. The old stack is
542
	 * Prevent SAVE instruction from causing a spill exception. If the
517
	 * automatically saved in the old window's %sp
543
	 * CANSAVE register is zero, explicitly spill the current register
518
	 * and the new window's %fp.
544
	 * window.
519
	 */
545
	 */
520
	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
521
 
546
 
522
.if \is_syscall
-
 
523
	/*
-
 
524
	 * Copy arguments for the syscall to the new window.
-
 
525
	 */
-
 
526
	mov %i0, %o0
-
 
527
	mov %i1, %o1
-
 
528
	mov %i2, %o2
-
 
529
	mov %i3, %o3
-
 
530
	mov %i4, %o4
-
 
531
	mov %i5, %o5
-
 
532
.endif
-
 
533
 
-
 
534
	/*
-
 
535
	 * Mark the CANRESTORE windows as OTHER windows.
-
 
536
	 */
-
 
537
	rdpr %canrestore, %l0
547
	rdpr %cansave, %g3
538
	wrpr %l0, %otherwin
-
 
539
	wrpr %g0, %canrestore
-
 
540
 
-
 
541
	/*
-
 
542
	 * Switch to primary context 0.
-
 
543
	 */
-
 
544
	mov VA_PRIMARY_CONTEXT_REG, %l0
-
 
545
	stxa %g0, [%l0] ASI_DMMU
-
 
546
	rd %pc, %l0
548
	brnz %g3, 2f
547
	flush %l0
-
 
548
 
-
 
549
.if NOT(\is_syscall)
-
 
550
	ba 1f
-
 
551
	nop
549
	nop
-
 
550
	INLINE_SPILL
-
 
551
 
552
0:
552
2:
-
 
553
	/* ask for new register window */
553
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
554
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
554
 
555
 
555
	/*
-
 
556
	 * At this moment, we are using the kernel stack 
-
 
557
	 * and have successfully allocated a register window.
556
	/* copy higher level routine's address and its argument */
558
	 */
-
 
559
1:
-
 
560
.endif
-
 
561
	/*
-
 
562
	 * Other window spills will go to the userspace window buffer
-
 
563
	 * and normal spills will go to the kernel stack.
-
 
564
	 */
-
 
565
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
-
 
566
	
-
 
567
	/*
-
 
568
	 * Copy arguments.
-
 
569
	 */
-
 
570
	mov %g1, %l0
557
	mov %g1, %l0
571
.if NOT(\is_syscall)
-
 
572
	mov %g2, %o0
558
	mov %g2, %o0
573
.else
-
 
574
	! store the syscall number on the stack as 7th argument
-
 
575
	stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6] 
-
 
576
.endif
-
 
577
 
559
 
578
	/*
560
	/*
579
	 * Save TSTATE, TPC and TNPC aside.
561
	 * Save TSTATE, TPC and TNPC aside.
580
	 */
562
	 */
581
	rdpr %tstate, %g1
563
	rdpr %tstate, %g1
582
	rdpr %tpc, %g2
564
	rdpr %tpc, %g2
583
	rdpr %tnpc, %g3
565
	rdpr %tnpc, %g3
584
	rd %y, %g4
-
 
585
 
566
 
586
	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
567
	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
587
	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
568
	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
588
	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
569
	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
589
 
570
 
Line 592... Line 573...
592
	 * This register is deprecated according to SPARC V9 specification
573
	 * This register is deprecated according to SPARC V9 specification
593
	 * and is only present for backward compatibility with previous
574
	 * and is only present for backward compatibility with previous
594
	 * versions of the SPARC architecture.
575
	 * versions of the SPARC architecture.
595
	 * Surprisingly, gcc makes use of this register without a notice.
576
	 * Surprisingly, gcc makes use of this register without a notice.
596
	 */
577
	 */
-
 
578
	rd %y, %g4
597
	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
579
	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
598
	
580
 
-
 
581
	/* switch to TL = 0, explicitly enable FPU */
599
	wrpr %g0, 0, %tl
582
	wrpr %g0, 0, %tl
600
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
583
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
-
 
584
 
-
 
585
	/* g1 -> l1, ..., g7 -> l7 */
601
	SAVE_GLOBALS
586
	SAVE_GLOBALS
602
	
587
 
603
.if NOT(\is_syscall)
-
 
604
	/*
-
 
605
	 * Call the higher-level handler and pass istate as second parameter.
588
	/* call higher-level service routine, pass istate as its 2nd parameter */
606
	 */
-
 
607
	call %l0
589
	call %l0
608
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
590
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
609
.else
-
 
610
	/*
-
 
611
	 * Call the higher-level syscall handler.
-
 
612
	 */
-
 
613
	call syscall_handler
-
 
614
	nop
-
 
615
	mov %o0, %i0				! copy the value returned by the syscall
-
 
616
.endif
-
 
617
 
591
 
-
 
592
	/* l1 -> g1, ..., l7 -> g7 */
618
	RESTORE_GLOBALS
593
	RESTORE_GLOBALS
-
 
594
 
619
	rdpr %pstate, %l1			! we must preserve the PEF bit
595
	/* we must prserve the PEF bit */
-
 
596
	rdpr %pstate, %l1
-
 
597
 
-
 
598
	/* TL := 1, GL := 1 */
620
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
599
	wrpr %g0, PSTATE_PRIV_BIT, %pstate
621
	wrpr %g0, 1, %tl
600
	wrpr %g0, 1, %tl
-
 
601
	wrpr %g0, 1, %gl
622
	
602
 
623
	/*
-
 
624
	 * Read TSTATE, TPC and TNPC from saved copy.
603
	/* Read TSTATE, TPC and TNPC from saved copy. */
625
	 */
-
 
626
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
604
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
627
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
605
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
628
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
606
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
629
 
607
 
630
	/*
-
 
631
	 * Copy PSTATE.PEF to the in-register copy of TSTATE.
608
	/* Copy PSTATE.PEF to the in-register copy of TSTATE. */
632
	 */
-
 
633
	and %l1, PSTATE_PEF_BIT, %l1
609
	and %l1, PSTATE_PEF_BIT, %l1
634
	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
610
	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
635
	sethi %hi(TSTATE_PEF_BIT), %g4
611
	sethi %hi(TSTATE_PEF_BIT), %g4		! reset the PEF bit to 0 ...
636
	andn %g1, %g4, %g1
612
	andn %g1, %g4, %g1
637
	or %g1, %l1, %g1
613
	or %g1, %l1, %g1			! ... "or" it with saved PEF
638
 
614
 
639
	/*
-
 
640
	 * Restore TSTATE, TPC and TNPC from saved copies.
615
	/* Restore TSTATE, TPC and TNPC from saved copies. */
641
	 */
-
 
642
	wrpr %g1, 0, %tstate
616
	wrpr %g1, 0, %tstate
643
	wrpr %g2, 0, %tpc
617
	wrpr %g2, 0, %tpc
644
	wrpr %g3, 0, %tnpc
618
	wrpr %g3, 0, %tnpc
645
 
619
 
646
	/*
-
 
647
	 * Restore Y.
620
	/* Restore Y. */
648
	 */
-
 
649
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
621
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
650
	wr %g4, %y
622
	wr %g4, %y
651
 
623
	
652
	/*
-
 
653
	 * If OTHERWIN is zero, then all the userspace windows have been
-
 
654
	 * spilled to kernel memory (i.e. register window buffer). Moreover,
-
 
655
	 * if the scheduler was called in the meantime, all valid windows
-
 
656
	 * belonging to other threads were spilled by context_restore().
-
 
657
	 * If OTHERWIN is non-zero, then some userspace windows are still
-
 
658
	 * valid. Others might have been spilled. However, the CWP pointer
-
 
659
	 * needs no fixing because the scheduler had not been called.
-
 
660
	 */
-
 
661
	rdpr %otherwin, %l0
-
 
662
	brnz %l0, 0f
-
 
663
	nop
-
 
664
 
-
 
665
	/*
-
 
666
	 * OTHERWIN == 0
-
 
667
	 */
-
 
668
 
-
 
669
	/*
-
 
670
	 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
624
	/* If TSTATE.CWP + 1 == CWP, then we do not have to fix CWP. */
671
	 */
-
 
672
	and %g1, TSTATE_CWP_MASK, %l0
625
	and %g1, TSTATE_CWP_MASK, %l0
673
	inc %l0
626
	inc %l0
674
	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
627
	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
675
	rdpr %cwp, %l1
628
	rdpr %cwp, %l1
676
	cmp %l0, %l1
629
	cmp %l0, %l1
677
	bz 0f				! CWP is ok
630
	bz 4f				! CWP is ok
678
	nop
631
	nop
679
 
632
 
-
 
633
3:
680
	/*
634
	/*
681
	 * Fix CWP.
635
	 * Fix CWP.
682
	 * In order to recapitulate, the input registers in the current
636
	 * In order to recapitulate, the input registers in the current
683
	 * window are the output registers of the window to which we want
637
	 * window are the output registers of the window to which we want
684
	 * to restore. Because the fill trap fills only input and local
638
	 * to restore. Because the fill trap fills only input and local
Line 703... Line 657...
703
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
657
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
704
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
658
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
705
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
659
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
706
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
660
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
707
 
661
 
-
 
662
4:
708
	/*
663
	/*
709
	 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
664
	 * Prevent RESTORE instruction from causing a spill exception. If the
710
	 * The CWP has already been restored to the value it had after the SAVE
665
	 * CANRESTORE register is zero, explicitly spill the current register
711
	 * at the beginning of this function.
666
	 * window.
712
	 */
667
	 */
713
0:
-
 
714
.if NOT(\is_syscall)
668
	rdpr %canrestore, %g1
715
	rdpr %tstate, %g1
669
	brnz %g1, 5f
716
	andcc %g1, TSTATE_PRIV_BIT, %g0		! if we are not returning to userspace...,
-
 
717
	bnz 1f					! ...skip restoring userspace windows
-
 
718
	nop
670
	nop
719
.endif
671
	INLINE_FILL
720
 
672
 
721
	/*
-
 
722
	 * Spills and fills will be processed by the {spill,fill}_1_normal
-
 
723
	 * handlers.
-
 
724
	 */
-
 
725
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
-
 
726
 
-
 
727
	/*
-
 
728
	 * Set primary context according to secondary context.
-
 
729
	 */
-
 
730
	wr %g0, ASI_DMMU, %asi
-
 
731
	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
-
 
732
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
-
 
733
	rd %pc, %g1
-
 
734
	flush %g1
-
 
735
	
-
 
736
	rdpr %cwp, %g1
-
 
737
	rdpr %otherwin, %g2
-
 
738
 
-
 
739
	/*
-
 
740
	 * Skip all OTHERWIN windows and descend to the first window
-
 
741
	 * in the userspace window buffer.
-
 
742
	 */
-
 
743
	sub %g1, %g2, %g3
-
 
744
	dec %g3
-
 
745
	and %g3, NWINDOWS - 1, %g3
-
 
746
	wrpr %g3, 0, %cwp
-
 
747
 
-
 
748
	/*
-
 
749
	 * CWP is now in the window last saved in the userspace window buffer.
-
 
750
	 * Fill all windows stored in the buffer.
-
 
751
	 */
-
 
752
	clr %g4
-
 
753
0:	andcc %g7, UWB_ALIGNMENT - 1, %g0	! alignment check
-
 
754
	bz 0f					! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
-
 
755
	nop
-
 
756
 
-
 
757
	add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
-
 
758
	ldx [%g7 + L0_OFFSET], %l0
-
 
759
	ldx [%g7 + L1_OFFSET], %l1
-
 
760
	ldx [%g7 + L2_OFFSET], %l2
-
 
761
	ldx [%g7 + L3_OFFSET], %l3
-
 
762
	ldx [%g7 + L4_OFFSET], %l4
-
 
763
	ldx [%g7 + L5_OFFSET], %l5
-
 
764
	ldx [%g7 + L6_OFFSET], %l6
-
 
765
	ldx [%g7 + L7_OFFSET], %l7
-
 
766
	ldx [%g7 + I0_OFFSET], %i0
-
 
767
	ldx [%g7 + I1_OFFSET], %i1
-
 
768
	ldx [%g7 + I2_OFFSET], %i2
-
 
769
	ldx [%g7 + I3_OFFSET], %i3
-
 
770
	ldx [%g7 + I4_OFFSET], %i4
-
 
771
	ldx [%g7 + I5_OFFSET], %i5
-
 
772
	ldx [%g7 + I6_OFFSET], %i6
-
 
773
	ldx [%g7 + I7_OFFSET], %i7
-
 
774
 
-
 
775
	dec %g3
-
 
776
	and %g3, NWINDOWS - 1, %g3
-
 
777
	wrpr %g3, 0, %cwp			! switch to the preceeding window
-
 
778
 
-
 
779
	ba 0b
-
 
780
	inc %g4
-
 
781
 
-
 
782
0:
-
 
783
	/*
-
 
784
	 * Switch back to the proper current window and adjust
-
 
785
	 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
-
 
786
	 */
-
 
787
	wrpr %g1, 0, %cwp
-
 
788
	add %g4, %g2, %g2
-
 
789
	cmp %g2, NWINDOWS - 2
-
 
790
	bg 2f					! fix the CANRESTORE=NWINDOWS-1 anomaly
-
 
791
	mov NWINDOWS - 2, %g1			! use dealy slot for both cases
-
 
792
	sub %g1, %g2, %g1
-
 
793
	
-
 
794
	wrpr %g0, 0, %otherwin
-
 
795
	wrpr %g1, 0, %cansave			! NWINDOWS - 2 - CANRESTORE
-
 
796
	wrpr %g2, 0, %canrestore		! OTHERWIN + windows in the buffer
-
 
797
	wrpr %g2, 0, %cleanwin			! avoid information leak
-
 
798
 
-
 
799
1:
673
5:
800
	restore
674
	restore
801
 
675
 
802
.if \is_syscall
-
 
803
	done
-
 
804
.else
-
 
805
	retry
676
	retry
806
.endif
677
.endm
807
 
678
 
808
	/*
-
 
809
	 * We got here in order to avoid inconsistency of the window state registers.
-
 
810
	 * If the:
-
 
811
	 *
-
 
812
	 * 	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
813
	 *
-
 
814
	 * instruction trapped and spilled a register window into the userspace
-
 
815
	 * window buffer, we have just restored NWINDOWS - 1 register windows.
-
 
816
	 * However, CANRESTORE can be only NWINDOW - 2 at most.
-
 
817
	 *
-
 
818
	 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
-
 
819
	 * and set the window state registers so that:
-
 
820
	 *
-
 
821
	 * 	CANRESTORE 	= NWINDOWS - 2
-
 
822
	 *	CLEANWIN	= NWINDOWS - 2
-
 
823
	 *	CANSAVE 	= 0
-
 
824
	 *	OTHERWIN	= 0
-
 
825
	 *
-
 
826
	 * The RESTORE instruction is therfore to be skipped.
-
 
827
	 */
-
 
828
2:
-
 
829
	wrpr %g0, 0, %otherwin
-
 
830
	wrpr %g0, 0, %cansave
-
 
831
	wrpr %g1, 0, %canrestore
-
 
832
	wrpr %g1, 0, %cleanwin
-
 
833
 
-
 
834
	rdpr %cwp, %g1
-
 
835
	dec %g1
-
 
836
	and %g1, NWINDOWS - 1, %g1
-
 
837
	wrpr %g1, 0, %cwp			! CWP--
-
 
838
	
-
 
839
.if \is_syscall
-
 
840
	done
-
 
841
.else
-
 
842
	retry
-
 
843
.endif
-
 
844
 
679
 
-
 
680
#define NOT(x)	((x) == 0)
-
 
681
 
-
 
682
/* Preemptible trap handler for TL=1.
-
 
683
 *
-
 
684
 * This trap handler makes arrangements to make calling of scheduler() from
-
 
685
 * within a trap context possible. It is called from several other trap
845
#endif
686
 * handlers.
-
 
687
 */
-
 
688
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
-
 
689
	PREEMPTIBLE_HANDLER_KERNEL
846
.endm
690
.endm
847
 
691
 
848
.global preemptible_handler
692
.global preemptible_handler
849
preemptible_handler:
693
preemptible_handler:
850
	PREEMPTIBLE_HANDLER_TEMPLATE 0
694
	PREEMPTIBLE_HANDLER_TEMPLATE 0