Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset eb79d60 in mainline


Ignore:
Timestamp:
2009-11-29T18:17:43Z (12 years ago)
Author:
Pavel Rimsky <pavel@…>
Branches:
lfn, master
Children:
ba50a34
Parents:
3f35634c
Message:

Merged the preemptible trap handler for userspace.

Location:
kernel/arch/sparc64
Files:
3 added
6 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/include/cpu.h

    r3f35634c reb79d60  
    6464#endif
    6565
    66 typedef struct {
    67         uint32_t mid;                   /**< Processor ID as read from
    68                                              UPA_CONFIG/FIREPLANE_CONFIG. */
    69         ver_reg_t ver;
    70         uint32_t clock_frequency;       /**< Processor frequency in Hz. */
    71         uint64_t next_tick_cmpr;        /**< Next clock interrupt should be
    72                                              generated when the TICK register
    73                                              matches this value. */
    74 } cpu_arch_t;
    7566
     67#if defined (SUN4U)
     68#include <arch/sun4u/cpu.h>
     69#elif defined (SUN4V)
     70#include <arch/sun4v/cpu.h>
     71#endif
    7672
    77 /**
    78  * Reads the module ID (agent ID/CPUID) of the current CPU.
    79  */
    80 static inline uint32_t read_mid(void)
    81 {
    82         uint64_t icbus_config = asi_u64_read(ASI_ICBUS_CONFIG, 0);
    83         icbus_config = icbus_config >> ICBUS_CONFIG_MID_SHIFT;
    84 #if defined (US)
    85         return icbus_config & 0x1f;
    86 #elif defined (US3)
    87         if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIII_I)
    88                 return icbus_config & 0x1f;
    89         else
    90                 return icbus_config & 0x3ff;
    91 #endif
    92 }
    9373
    9474#endif 
  • kernel/arch/sparc64/include/sun4u/cpu.h

    r3f35634c reb79d60  
    3333 */
    3434
    35 #ifndef KERN_sparc64_CPU_H_
    36 #define KERN_sparc64_CPU_H_
     35#ifndef KERN_sparc64_sun4u_CPU_H_
     36#define KERN_sparc64_sun4u_CPU_H_
    3737
    3838#define MANUF_FUJITSU           0x04
  • kernel/arch/sparc64/include/sun4v/cpu.h

    r3f35634c reb79d60  
    4646struct cpu;
    4747
     48/*
    4849typedef struct {
    4950        uint64_t exec_unit_id;
     
    5455        SPINLOCK_DECLARE(proposed_nrdy_lock);
    5556} exec_unit_t;
     57*/
    5658
    57 // MH
    58 #if 0
    5959typedef struct cpu_arch {
    6060        uint64_t id;                    /**< virtual processor ID */
     
    6363                                             generated when the TICK register
    6464                                             matches this value. */
    65         exec_unit_t *exec_unit;         /**< Physical core. */
    66         unsigned long proposed_nrdy;    /**< Proposed No. of ready threads
    67                                              so that cores are equally balanced. */
     65        //exec_unit_t *exec_unit;               /**< Physical core. */
     66        //unsigned long proposed_nrdy;  /**< Proposed No. of ready threads
     67        //                                   so that cores are equally balanced. */
    6868} cpu_arch_t;
    69 #endif
    7069
    7170#endif 
  • kernel/arch/sparc64/include/trap/regwin.h

    r3f35634c reb79d60  
    131131
    132132/*
    133  * Macro used to spill userspace window to userspace window buffer.
    134  * It can be either triggered from preemptible_handler doing SAVE
    135  * at (TL=1) or from normal kernel code doing SAVE when OTHERWIN>0
    136  * at (TL=0).
    137  */
    138 .macro SPILL_TO_USPACE_WINDOW_BUFFER
    139         stx %l0, [%g7 + L0_OFFSET]     
    140         stx %l1, [%g7 + L1_OFFSET]
    141         stx %l2, [%g7 + L2_OFFSET]
    142         stx %l3, [%g7 + L3_OFFSET]
    143         stx %l4, [%g7 + L4_OFFSET]
    144         stx %l5, [%g7 + L5_OFFSET]
    145         stx %l6, [%g7 + L6_OFFSET]
    146         stx %l7, [%g7 + L7_OFFSET]
    147         stx %i0, [%g7 + I0_OFFSET]
    148         stx %i1, [%g7 + I1_OFFSET]
    149         stx %i2, [%g7 + I2_OFFSET]
    150         stx %i3, [%g7 + I3_OFFSET]
    151         stx %i4, [%g7 + I4_OFFSET]
    152         stx %i5, [%g7 + I5_OFFSET]
    153         stx %i6, [%g7 + I6_OFFSET]
    154         stx %i7, [%g7 + I7_OFFSET]
    155         add %g7, STACK_WINDOW_SAVE_AREA_SIZE, %g7
    156         saved
    157         retry
    158 .endm
    159 
    160 
    161 /*
    162133 * Macro used by the nucleus and the primary context 0 during normal fills.
    163134 */
     
    232203#endif /* __ASM__ */
    233204
     205#if defined (SUN4U)
     206#include <arch/trap/sun4u/regwin.h>
     207#elif defined (SUN4V)
     208#include <arch/trap/sun4v/regwin.h>
    234209#endif
    235210
     211#endif
     212
    236213/** @}
    237214 */
  • kernel/arch/sparc64/src/mm/sun4v/tlb.c

    r3f35634c reb79d60  
    212212void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate)
    213213{
     214        asm volatile ("sethi 0x41906, %g0");
    214215        uintptr_t page_16k = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
    215216        size_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
  • kernel/arch/sparc64/src/trap/sun4v/trap_table.S

    r3f35634c reb79d60  
    136136.global data_access_exception_tl0
    137137data_access_exception_tl0:
    138         /*wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
    139         PREEMPTIBLE_HANDLER data_access_exception*/
     138        wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
     139        PREEMPTIBLE_HANDLER data_access_exception
    140140
    141141/* TT = 0x32, TL = 0, data_access_error */
     
    293293.global fast_data_access_protection_handler_tl0
    294294fast_data_access_protection_handler_tl0:
    295         /*FAST_DATA_ACCESS_PROTECTION_HANDLER 0*/
     295        FAST_DATA_ACCESS_PROTECTION_HANDLER 0
    296296
    297297/* TT = 0x80, TL = 0, spill_0_normal handler */
     
    355355.global instruction_access_exception_tl1
    356356instruction_access_exception_tl1:
    357         /*wrpr %g0, 1, %tl
     357        wrpr %g0, 1, %tl
    358358        wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
    359         PREEMPTIBLE_HANDLER instruction_access_exception*/
     359        PREEMPTIBLE_HANDLER instruction_access_exception
    360360
    361361/* TT = 0x0a, TL > 0, instruction_access_error */
     
    418418.global fast_data_access_protection_handler_tl1
    419419fast_data_access_protection_handler_tl1:
    420         /*FAST_DATA_ACCESS_PROTECTION_HANDLER 1*/
     420        FAST_DATA_ACCESS_PROTECTION_HANDLER 1
    421421
    422422/* TT = 0x80, TL > 0, spill_0_normal handler */
     
    525525.endm
    526526
     527#define NOT(x)  ((x) == 0)
     528
    527529/*
    528  * Preemptible trap handler for handling traps from kernel.
     530 * Perform all the actions of the preemptible trap handler which are common
     531 * for trapping from kernel and trapping from userspace, including call of the
     532 * higher level service routine.
     533 *
     534 * Important note:
     535 *      This macro must be inserted between the "2:" and "4:" labels. The
     536 *      inserting code must be aware of the usage of all the registers
     537 *      contained in this macro.
    529538 */
    530 .macro PREEMPTIBLE_HANDLER_KERNEL
    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, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
    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 
     539.macro MIDDLE_PART is_syscall
    560540        /* copy higher level routine's address and its argument */
    561541        mov %g1, %l0
     542.if NOT(\is_syscall)
    562543        mov %g2, %o0
     544.else
     545        ! store the syscall number on the stack as 7th argument
     546        stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6]
     547.endif
    563548
    564549        /*
     
    591576        SAVE_GLOBALS
    592577
     578.if NOT(\is_syscall)
    593579        /* call higher-level service routine, pass istate as its 2nd parameter */
    594580        call %l0
    595581        add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
     582.else
     583        /* Call the higher-level syscall handler. */
     584        !wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
     585        call syscall_handler
     586        nop
     587        /* copy the value returned by the syscall */
     588        mov %o0, %i0
     589.endif
    596590
    597591        /* l1 -> g1, ..., l7 -> g7 */
     
    664658        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
    665659        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
     660.endm
     661
     662
     663#if 0
     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
     6760:      ba 0b                                   ! this is for debugging, if we ever get here
     677        nop                                     ! it will be easy to find
     678
     679        /* prevent unnecessary CLEANWIN exceptions */
     680        wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
     6811:
     682        /*
     683         * Prevent SAVE instruction from causing a spill exception. If the
     684         * CANSAVE register is zero, explicitly spill register window
     685         * at CWP + 2.
     686         */
     687
     688        rdpr %cansave, %g3
     689        brnz %g3, 2f
     690        nop
     691        INLINE_SPILL %g3, %g4
     692
     6932:
     694        /* ask for new register window */
     695        save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
     696
     697        /* copy higher level routine's address and its argument */
     698        mov %g1, %l0
     699        mov %g2, %o0
     700
     701        /*
     702         * Save TSTATE, TPC and TNPC aside.
     703         */
     704        rdpr %tstate, %g1
     705        rdpr %tpc, %g2
     706        rdpr %tnpc, %g3
     707
     708        stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
     709        stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
     710        stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
     711
     712        /*
     713         * Save the Y register.
     714         * This register is deprecated according to SPARC V9 specification
     715         * and is only present for backward compatibility with previous
     716         * versions of the SPARC architecture.
     717         * Surprisingly, gcc makes use of this register without a notice.
     718         */
     719        rd %y, %g4
     720        stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
     721
     722        /* switch to TL = 0, explicitly enable FPU */
     723        wrpr %g0, 0, %tl
     724        wrpr %g0, 0, %gl
     725        wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
     726
     727        /* g1 -> l1, ..., g7 -> l7 */
     728        SAVE_GLOBALS
     729
     730        /* call higher-level service routine, pass istate as its 2nd parameter */
     731        call %l0
     732        add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
     733
     734        /* l1 -> g1, ..., l7 -> g7 */
     735        RESTORE_GLOBALS
     736
     737        /* we must prserve the PEF bit */
     738        rdpr %pstate, %l1
     739
     740        /* TL := 1, GL := 1 */
     741        wrpr %g0, PSTATE_PRIV_BIT, %pstate
     742        wrpr %g0, 1, %tl
     743        wrpr %g0, 1, %gl
     744
     745        /* Read TSTATE, TPC and TNPC from saved copy. */
     746        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
     747        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
     748        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
     749
     750        /* Copy PSTATE.PEF to the in-register copy of TSTATE. */
     751        and %l1, PSTATE_PEF_BIT, %l1
     752        sllx %l1, TSTATE_PSTATE_SHIFT, %l1
     753        sethi %hi(TSTATE_PEF_BIT), %g4          ! reset the PEF bit to 0 ...
     754        andn %g1, %g4, %g1
     755        or %g1, %l1, %g1                        ! ... "or" it with saved PEF
     756
     757        /* Restore TSTATE, TPC and TNPC from saved copies. */
     758        wrpr %g1, 0, %tstate
     759        wrpr %g2, 0, %tpc
     760        wrpr %g3, 0, %tnpc
     761
     762        /* Restore Y. */
     763        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
     764        wr %g4, %y
     765       
     766        /* If TSTATE.CWP + 1 == CWP, then we do not have to fix CWP. */
     767        and %g1, TSTATE_CWP_MASK, %l0
     768        inc %l0
     769        and %l0, NWINDOWS - 1, %l0      ! %l0 mod NWINDOWS
     770        rdpr %cwp, %l1
     771        cmp %l0, %l1
     772        bz 4f                           ! CWP is ok
     773        nop
     774
     7753:
     776        /*
     777         * Fix CWP.
     778         * In order to recapitulate, the input registers in the current
     779         * window are the output registers of the window to which we want
     780         * to restore. Because the fill trap fills only input and local
     781         * registers of a window, we need to preserve those output
     782         * registers manually.
     783         */
     784        mov %sp, %g2
     785        stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
     786        stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
     787        stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
     788        stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
     789        stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
     790        stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
     791        stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
     792        stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
     793        wrpr %l0, 0, %cwp
     794        mov %g2, %sp
     795        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
     796        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
     797        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
     798        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
     799        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
     800        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
     801        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
     802        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
    666803
    6678044:
     
    682819.endm
    683820
    684 
    685 #define NOT(x)  ((x) == 0)
     821#endif
     822
     823/*
     824 * Preemptible trap handler for handling traps from kernel.
     825 */
     826.macro PREEMPTIBLE_HANDLER_KERNEL
     827
     828        /*
     829         * ASSERT(%tl == 1)
     830         */
     831        rdpr %tl, %g3
     832        cmp %g3, 1
     833        be 1f
     834        nop
     8350:      ba 0b                                   ! this is for debugging, if we ever get here
     836        nop                                     ! it will be easy to find
     837
     8381:
     839        /* prevent unnecessary CLEANWIN exceptions */
     840        wrpr %g0, NWINDOWS - 1, %cleanwin
     841
     842        /*
     843         * Prevent SAVE instruction from causing a spill exception. If the
     844         * CANSAVE register is zero, explicitly spill register window
     845         * at CWP + 2.
     846         */
     847
     848        rdpr %cansave, %g3
     849        brnz %g3, 2f
     850        nop
     851        INLINE_SPILL %g3, %g4
     852
     8532:
     854        /* ask for new register window */
     855        save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
     856
     857        MIDDLE_PART 0
     858
     8594:
     860        /*
     861         * Prevent RESTORE instruction from causing a fill exception. If the
     862         * CANRESTORE register is zero, explicitly fill register window
     863         * at CWP - 1.
     864         */
     865        rdpr %canrestore, %g1
     866        brnz %g1, 5f
     867        nop
     868        INLINE_FILL %g3, %g4
     869
     8705:
     871        restore
     872        retry
     873.endm
     874
     875
     876
     877/*
     878 * Spills the window at CWP + 2 to the userspace window buffer. This macro
     879 * is to be used before doing SAVE when the spill trap is undesirable.
     880 *
     881 * Parameters:
     882 *      tmpreg1         global register to be used for scratching purposes
     883 *      tmpreg2         global register to be used for scratching purposes
     884 *      tmpreg3         global register to be used for scratching purposes
     885 */
     886.macro INLINE_SPILL_TO_WBUF tmpreg1, tmpreg2, tmpreg3
     887        ! CWP := CWP + 2
     888        rdpr %cwp, \tmpreg2
     889        add \tmpreg2, 2, \tmpreg1
     890        and \tmpreg1, NWINDOWS - 1, \tmpreg1            ! modulo NWINDOWS
     891        wrpr \tmpreg1, %cwp
     892       
     893        ! spill to userspace window buffer
     894        SAVE_TO_USPACE_WBUF \tmpreg3, \tmpreg1
     895
     896        ! CWP := CWP - 2
     897        wrpr \tmpreg2, %cwp
     898
     899        saved
     900.endm
     901
     902/*
     903 * Preemptible handler for handling traps from userspace.
     904 */
     905.macro PREEMPTIBLE_HANDLER_USPACE is_syscall
     906        /*
     907         * One of the ways this handler can be invoked is after a nested MMU trap from
     908         * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
     909         * the CWP register. We deal with the situation by simulating the MMU trap
     910         * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
     911         * trap is resolved. However, because we are in the wrong window from the
     912         * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
     913         */
     914.if NOT(\is_syscall)
     915        rdpr %tstate, %g3
     916        and %g3, TSTATE_CWP_MASK, %g4
     917        wrpr %g4, 0, %cwp                       ! resynchronize CWP
     918.endif
     919
     920        /* prevent unnecessary CLEANWIN exceptions */
     921        wrpr %g0, NWINDOWS - 1, %cleanwin
     922
     923        /*
     924         * Prevent SAVE instruction from causing a spill exception. If the
     925         * CANSAVE register is zero, explicitly spill register window
     926         * at CWP + 2.
     927         */
     928        rdpr %cansave, %g3
     929        brnz %g3, 2f
     930        nop
     931        INLINE_SPILL_TO_WBUF %g3, %g4, %g7
     932
     9332:
     934        set SCRATCHPAD_KSTACK, %g4
     935        ldxa [%g4] ASI_SCRATCHPAD, %g6
     936        save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
     937
     938.if \is_syscall
     939        /* Copy arguments for the syscall to the new window. */
     940        mov %i0, %o0
     941        mov %i1, %o1
     942        mov %i2, %o2
     943        mov %i3, %o3
     944        mov %i4, %o4
     945        mov %i5, %o5
     946.endif
     947
     948        mov VA_PRIMARY_CONTEXT_REG, %l0
     949        stxa %g0, [%l0] ASI_PRIMARY_CONTEXT_REG
     950        rd %pc, %l0
     951        flush %l0
     952
     953        /* Mark the CANRESTORE windows as OTHER windows. */
     954        rdpr %canrestore, %l0
     955        wrpr %l0, %otherwin
     956        wrpr %g0, %canrestore
     957
     958        /*
     959         * Other window spills will go to the userspace window buffer
     960         * and normal spills will go to the kernel stack.
     961         */
     962        wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
     963
     964        MIDDLE_PART \is_syscall
     965
     9664:
     967        /*
     968         * Spills and fills will be processed by the {spill,fill}_1_normal
     969         * handlers.
     970         */
     971        wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
     972
     973        /*
     974         * Set primary context according to secondary context.
     975         */
     976        wr %g0, ASI_SECONDARY_CONTEXT_REG, %asi
     977        ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
     978        wr %g0, ASI_PRIMARY_CONTEXT_REG, %asi
     979        stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
     980        rd %pc, %g1
     981        flush %g1
     982
     983        /* Restoring userspace windows: */
     984
     985        /* Save address of the userspace window buffer to the %g7 register. */
     986        set SCRATCHPAD_WBUF, %g5
     987        ldxa [%g5] ASI_SCRATCHPAD, %g7
     988
     989        rdpr %cwp, %g1
     990        rdpr %otherwin, %g2
     991
     992        /*
     993         * Skip all OTHERWIN windows and descend to the first window
     994         * in the userspace window buffer.
     995         */
     996        sub %g1, %g2, %g3
     997        dec %g3
     998        and %g3, NWINDOWS - 1, %g3
     999        wrpr %g3, 0, %cwp
     1000
     1001        /*
     1002         * CWP is now in the window last saved in the userspace window buffer.
     1003         * Fill all windows stored in the buffer.
     1004         */
     1005        clr %g4
     10065:      andcc %g7, UWB_ALIGNMENT - 1, %g0       ! alignment check
     1007        bz 6f                                   ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
     1008        nop
     1009
     1010        add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
     1011        ldx [%g7 + L0_OFFSET], %l0
     1012        ldx [%g7 + L1_OFFSET], %l1
     1013        ldx [%g7 + L2_OFFSET], %l2
     1014        ldx [%g7 + L3_OFFSET], %l3
     1015        ldx [%g7 + L4_OFFSET], %l4
     1016        ldx [%g7 + L5_OFFSET], %l5
     1017        ldx [%g7 + L6_OFFSET], %l6
     1018        ldx [%g7 + L7_OFFSET], %l7
     1019        ldx [%g7 + I0_OFFSET], %i0
     1020        ldx [%g7 + I1_OFFSET], %i1
     1021        ldx [%g7 + I2_OFFSET], %i2
     1022        ldx [%g7 + I3_OFFSET], %i3
     1023        ldx [%g7 + I4_OFFSET], %i4
     1024        ldx [%g7 + I5_OFFSET], %i5
     1025        ldx [%g7 + I6_OFFSET], %i6
     1026        ldx [%g7 + I7_OFFSET], %i7
     1027
     1028        dec %g3
     1029        and %g3, NWINDOWS - 1, %g3
     1030        wrpr %g3, 0, %cwp                       ! switch to the preceeding window
     1031
     1032        ba 5b
     1033        inc %g4
     1034
     10356:
     1036        /* Save changes of the address of the userspace window buffer. */
     1037        stxa %g7, [%g5] ASI_SCRATCHPAD
     1038
     1039        /*
     1040         * Switch back to the proper current window and adjust
     1041         * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
     1042         */
     1043        wrpr %g1, 0, %cwp
     1044        add %g4, %g2, %g2
     1045        cmp %g2, NWINDOWS - 2
     1046        bg 8f                                   ! fix the CANRESTORE=NWINDOWS-1 anomaly
     1047        mov NWINDOWS - 2, %g1                   ! use dealy slot for both cases
     1048        sub %g1, %g2, %g1
     1049       
     1050        wrpr %g0, 0, %otherwin
     1051        wrpr %g1, 0, %cansave                   ! NWINDOWS - 2 - CANRESTORE
     1052        wrpr %g2, 0, %canrestore                ! OTHERWIN + windows in the buffer
     1053        wrpr %g2, 0, %cleanwin                  ! avoid information leak
     1054
     10557:
     1056        restore
     1057
     1058.if \is_syscall
     1059        done
     1060.else
     1061        retry
     1062.endif
     1063
     10648:
     1065        /*
     1066         * We got here in order to avoid inconsistency of the window state registers.
     1067         * If the:
     1068         *
     1069         *      save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
     1070         *
     1071         * instruction trapped and spilled a register window into the userspace
     1072         * window buffer, we have just restored NWINDOWS - 1 register windows.
     1073         * However, CANRESTORE can be only NWINDOW - 2 at most.
     1074         *
     1075         * The solution is to manually switch to (CWP - 1) mod NWINDOWS
     1076         * and set the window state registers so that:
     1077         *
     1078         *      CANRESTORE      = NWINDOWS - 2
     1079         *      CLEANWIN        = NWINDOWS - 2
     1080         *      CANSAVE         = 0
     1081         *      OTHERWIN        = 0
     1082         *
     1083         * The RESTORE instruction is therfore to be skipped.
     1084         */
     1085        wrpr %g0, 0, %otherwin
     1086        wrpr %g0, 0, %cansave
     1087        wrpr %g1, 0, %canrestore
     1088        wrpr %g1, 0, %cleanwin
     1089
     1090        rdpr %cwp, %g1
     1091        dec %g1
     1092        and %g1, NWINDOWS - 1, %g1
     1093        wrpr %g1, 0, %cwp                       ! CWP--
     1094       
     1095.if \is_syscall
     1096        done
     1097.else
     1098        retry
     1099.endif
     1100
     1101.endm
     1102
     1103
    6861104
    6871105/* Preemptible trap handler for TL=1.
     
    6921110 */
    6931111.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
     1112        rdpr %tstate, %g3
     1113        and %g3, TSTATE_PRIV_BIT, %g3
     1114        brz %g3, 100f                   ! trapping from userspace
     1115        nop
     1116
    6941117        PREEMPTIBLE_HANDLER_KERNEL
     1118        ba 101f
     1119        nop
     1120
     1121        100:
     1122        PREEMPTIBLE_HANDLER_USPACE \is_syscall
     1123
     1124        101:
    6951125.endm
    6961126
Note: See TracChangeset for help on using the changeset viewer.