home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / sparc / kernel / entry.S next >
Encoding:
Text File  |  1995-02-20  |  23.7 KB  |  928 lines

  1. /* arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  2.  *
  3.  * Sparc traps are so ugly, this code is going to go through a lot
  4.  * of changes as I find out more interesting things. See head.S for
  5.  * the trap table and how it works, this will show you how we get
  6.  * to these routines.
  7.  *
  8.  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  9.  */
  10.  
  11. #include <asm/head.h>
  12. #include <asm/asi.h>
  13. #include <asm/psr.h>
  14. #include <asm/cprefix.h>
  15. #include <asm/vaddrs.h>
  16.  
  17. /* Here are macros for routines we do often, this allows me to inline this
  18.  * without making the code look real ugly. Well, the macro looks ugly too but
  19.  * makes the trap entry code easier to understand.
  20.  */
  21.  
  22. /* I really don't like synthetic instructions. So I avoid them like the
  23.  * plague.
  24.  */
  25.  
  26. /* Note that when I have to write a window out, and it is a user's window, I
  27.  * have to check that the pages of memory that I am going to throw the window(s)
  28.  * onto are valid and are writable by the user (this is %sp to %sp + 64) before
  29.  * I start dumping stuff there. We always assume that kernels stack is ok.
  30.  *
  31.  * If we have to save a kernel window, only one branch is taken. This should
  32.  * make trap handlers quicker in this scenario.
  33.  *
  34.  * Once 'current' is loaded into %g6, it stays there until we leave
  35.  * this macro.
  36.  *
  37.  * XXX must do some checking on the assumption that kernel stack is always ok
  38.  */
  39.  
  40. /* I will document how this works real soon. TODO */
  41.  
  42. #define TRAP_WIN_CLEAN \
  43.     or    %g0, %g5, %l5;    /* we need the globals to do our work */ \
  44.     or    %g0, %g6, %l6;    /* and %l0 to %l4 are loaded with important */ \
  45.     or    %g0, %g7, %l7;      /* information like the psr and pc's to return to */ \
  46.     sethi    %hi( C_LABEL(current) ), %g6; \
  47.     ld    [%g6 + %lo( C_LABEL(current) )], %g6; \
  48.     ld    [%g6 + THREAD_UWINDOWS], %g7; /* how many user wins are active? */ \
  49.     subcc    %g7, 0x0, %g0; \
  50.     bne    2f;                            /* If there are any, branch. */ \
  51.     save    %g0, %g0, %g0;                 /* Save into that window either way. */ \
  52.     std    %l0, [%sp];                    /* If above shows only kernel windows */ \
  53. 1:    std    %l2, [%sp + 0x8];              /* then we get here. */ \
  54.     std    %l4, [%sp + 0x10]; \
  55.     std    %l6, [%sp + 0x18]; \
  56.     std    %i0, [%sp + 0x20]; \
  57.     std    %i2, [%sp + 0x28]; \
  58.     std    %i4, [%sp + 0x30]; \
  59.     std    %i6, [%sp + 0x38]; \
  60.     or    %g0, 0x1, %g5; \
  61.     rd    %psr, %g7; \
  62.     sll    %g5, %g7, %g5; \
  63.     wr    %g5, 0x0, %wim;                 /* update %wim to 'now' invalid */ \
  64.     and    %g7, 0x1f, %g7; \
  65.     st    %g7, [%g6 + THREAD_WIM];        /* save 'this' threads mask */ \
  66.     restore    %g0, %g0, %g0; \
  67.     or    %g0, %l5, %g5;                  /* restore the globals we used */ \
  68.     or    %g0, %l6, %g6; \
  69.     b    8f;                             /* we are done */ \
  70.     or    %g0, %l7, %g7; \
  71. 2:    sub    %g7, 0x1, %g7; \
  72.     st    %g7, [%g6 + THREAD_UWINDOWS];   /* There are user windows if we */ \
  73.     andcc    %sp, 0x7, %g0;                  /* get here. Check for stack alignment. */ \
  74.     bne    5f;                             /* Stack is unaligned, yuck. */ \
  75.     sra    %sp, 0x1e, %g7;                 /* This stuff checks to see if top 3-bits */ \
  76.     subcc    %g7, 0x0, %g0;                  /* of stack pointer address are ok. */ \
  77.     be,a    3f; \
  78.     andn    %sp, 0xfff, %g7; \
  79.     subcc    %g7, -1, %g0; \
  80.     bne    5f;                 /* bad stack pointer, ugh */ \
  81.     andn    %sp, 0xfff, %g7; \
  82. 3:    lda    [%g7] ASI_PTE, %g7;             /* Ok, user stack is a valid address */ \
  83.     srl    %g7, 0x1d, %g7; \
  84.     subcc    %g7, 0x6, %g0;                  /* Can the user write to it? */ \
  85.     bne    5f; \
  86.     and    %sp, 0xfff, %g7; \
  87.     subcc    %g7, 0xfc1, %g0;                /* Is our save area on one page? */ \
  88.     bl,a    1b; \
  89.     std    %l0, [%sp]; \
  90.     add    %sp, 0x38, %g5;                 /* Nope, have to check both pages */ \
  91.     sra    %g5, 0x1e, %g7; \
  92.     subcc    %g7, 0x0, %g0; \
  93.     be,a    4f; \
  94.     andn    %g5, 0xfff, %g7; \
  95.     subcc    %g7, -1, %g0; \
  96.     bne    5f; \
  97.     andn    %g5, 0xfff, %g7; \
  98. 4:    lda    [%g7] ASI_PTE, %g7;             /* Stack space in 2nd page is valid */ \
  99.     srl    %g7, 0x1d, %g7; \
  100.     subcc    %g7, 0x6, %g0;                  /* Can user write here too? */ \
  101.     be,a    1b; \
  102.     std    %l0, [%sp]; \
  103. 5:    ld    [%g6 + THREAD_UWINDOWS], %g7;   /* This is due to either bad page perms */ \
  104.     add    %g6, THREAD_REG_WINDOW, %g5;    /* for the users stack area, or the stack */ \
  105. 6:    std    %l0, [%g5];                     /* pointer is misaligned. See above. */ \
  106.     std    %l2, [%g5 + 0x8]; \
  107.     std    %l4, [%g5 + 0x10]; \
  108.     std    %l6, [%g5 + 0x18]; \
  109.     std    %i0, [%g5 + 0x20]; \
  110.     std    %i2, [%g5 + 0x28]; \
  111.     std    %i4, [%g5 + 0x30]; \
  112.     std    %i6, [%g5 + 0x38]; \
  113.     subcc    %g7, 0x1, %g7; \
  114.     bge,a    6b;                             /* while(uwindows>=0) { write_win(); */ \
  115.     save    %g5, 0x40, %g5;                 /*     uwindows--; } */ \
  116.     st    %sp, [%g6 + THREAD_USP]; \
  117.     or    %g0, 0x1, %g5; \
  118.     rd    %psr, %g7; \
  119.     sll    %g5, %g7, %g5; \
  120.     wr    %g5, 0x0, %wim; \
  121.     and    %g7, 0x1f, %g7; \
  122.     st    %g7, [%g6 + THREAD_WIM];        /* Update thread_struct fields */ \
  123.     ld    [%g6 + THREAD_UWINDOWS], %g7; \
  124.     add    %g7, 0x1, %g5; \
  125.     st    %g5, [%g6 + THREAD_W_SAVED]; \
  126.     st    %g0, [%g6 + THREAD_UWINDOWS]; \
  127. 7:    subcc    %g7, 0x1, %g7;                  /* Restore back to where we started. */ \
  128.     bge    7b; \
  129.     restore    %g0, %g0, %g0; \
  130.     or    %g0, %l5, %g5;                  /* Restore the globals. */ \
  131.     or    %g0, %l6, %g6; \
  132.     or    %g0, %l7, %g7; \
  133. 8:      nop;                                     /* We are done when we get here. */ \
  134.  
  135. /* As if the last macro wasn't enough, we have to go through a very similar routine
  136.  * upon entry to most traps and interrupts. This is save away the current window
  137.  * if it is the trap window, clean it, and adjust the stack for the handler c-code
  138.  * to work.
  139.  */
  140.  
  141. #define ENTER_TRAP \
  142.     rd    %wim, %l4; \
  143.     or    %g0, 0x1, %l5; \
  144.     sll    %l5, %l0, %l5; \
  145.     andcc    %l0, 0x40, %g0; \
  146.     bz    1f; \
  147.     andcc    %l4, %l5, %g0; \
  148.     bz,a    3f; \
  149.     sub    %fp, 0xb0, %sp; \
  150.     TRAP_WIN_CLEAN \
  151.     b    3f; \
  152.     sub    %fp, 0xb0, %sp; \
  153. 1:    sethi    %hi( C_LABEL(current) ), %l6; \
  154.     ld    [%l6 + %lo( C_LABEL(current) )], %l6; \
  155.     ld    [%l6 + THREAD_WIM], %l5; \
  156.     and    %l0, 0x1f, %l4; \
  157.     cmp    %l5, %l3; \
  158.     ble,a    4f; \
  159.     sethi    %hi( C_LABEL(nwindowsm1) ), %l4; \
  160.     sub    %l5, %l3, %l3; \
  161.     b    5f; \
  162.     sub    %l3, 0x1, %l5; \
  163. 4:    ld    [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4; \
  164.     sub    %l4, %l3, %l4; \
  165.     add    %l5, %l4, %l5; \
  166. 5:    st    %l5, [%l6 + THREAD_UWINDOWS]; \
  167.     bz,a    2f; \
  168.     sethi    %hi(TASK_SIZE-176), %l5; \
  169.     TRAP_WIN_CLEAN; \
  170.     sethi    %hi( C_LABEL(current) ), %l6; \
  171.     ld    [%l6 + %lo( C_LABEL(current) )], %l6; \
  172.     sethi    %hi(TASK_SIZE-176), %l5; \
  173. 2:    or    %l5, %lo(TASK_SIZE-176), %l5; \
  174.     add    %l6, %l5, %sp; \
  175. 3: \
  176.  
  177. #define ENTER_IRQ \
  178.     rd    %wim, %l4; \
  179.     or    %g0, 0x1, %l5; \
  180.     sll    %l5, %l0, %l5; \
  181.     andcc    %l0, 0x40, %g0; \
  182.     bz    1f; \
  183.     andcc    %l4, %l5, %g0; \
  184.     sethi    %hi( C_LABEL(eintstack) ), %l7; \
  185.     or    %l7, %lo( C_LABEL(eintstack) ), %l7; \
  186.     bz    0f; \
  187.     nop; \
  188.     TRAP_WIN_CLEAN \
  189.     sethi    %hi( C_LABEL(eintstack) ), %l7; \
  190.     or    %l7, %lo( C_LABEL(eintstack) ), %l7; \
  191. 0:    subcc    %fp, %l7, %g0; \
  192.     bg,a    3f; \
  193.     sub    %l7, 0xb0, %sp; \
  194.     b    3f; \
  195.     sub    %fp, 0xb0, %sp; \
  196. 1:     sethi    %hi( C_LABEL(current) ), %l6; \
  197.     ld    [%l6 + %lo( C_LABEL(current) )], %l6; \
  198.     ld    [%l6 + THREAD_WIM], %l5; \
  199.     and    %l0, 0x1f, %l7; \
  200.     cmp    %l5, %l7; \
  201.     ble,a    4f; \
  202.     sethi    %hi( C_LABEL(nwindowsm1) ), %l4; \
  203.     sub    %l5, %l7, %l7; \
  204.     b    5f; \
  205.     sub    %l7, 0x1, %l5; \
  206. 4:    ld    [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4; \
  207.     sub    %l4, %l7, %l4; \
  208.     add    %l5, %l4, %l5; \
  209. 5:    st    %l5, [%l6 + THREAD_UWINDOWS]; \
  210.     bz,a    2f; \
  211.     sethi    %hi( C_LABEL(eintstack) ), %l7; \
  212.     TRAP_WIN_CLEAN \
  213.     sethi    %hi( C_LABEL(eintstack) ), %l7; \
  214. 2: \
  215.     sub    %l7, 0xb0, %sp; \
  216. 3:
  217.  
  218.  
  219.     .text
  220.     .align 4
  221.  
  222. /* Default trap handler */
  223.     .globl my_trap_handler
  224. my_trap_handler:
  225. #if 1
  226.         jmp    %l1
  227.         rett    %l2
  228.         nop
  229. #else
  230.         rd %wim, %l4
  231.         or %g0, 0x1, %l5
  232.         sll %l5, %l0, %l5
  233.         cmp %l4, %l5        ! are we in the invalid window?
  234.     
  235.         TRAP_WIN_CLEAN
  236.  
  237.         nop
  238.         or %g0, %l3, %o0
  239.         call C_LABEL(do_hw_interrupt)
  240.         or %g0, %g0, %o1
  241.         wr %l0, 0x20, %psr  ! re-enable traps and reset the condition codes
  242.         nop
  243.         nop
  244.         nop                 ! click our heels three times, "no place like home"
  245.         jmp %l1
  246.         rett %l2
  247. #endif /* bogon */
  248.     
  249.     .align 4
  250.     .globl sparc_timer
  251. sparc_timer:
  252.     sethi    %hi(TIMER_VADDR), %l4
  253.     or    %l4, %lo(TIMER_VADDR), %l4    ! read the limit register
  254.     ld    [%l4 + 0xc], %l4        ! to clear the interrupt
  255.     rd    %wim, %l4
  256.     or    %g0, 0x1, %l5
  257.     sll    %l5, %l0, %l5
  258.     andcc    %l0, 0x40, %g0
  259.     bz    st1
  260.     sethi    %hi( C_LABEL(eintstack) ), %l7
  261.     andcc    %l4, %l5, %g0
  262.     bz    st0
  263.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  264.     TRAP_WIN_CLEAN
  265.     sethi    %hi( C_LABEL(eintstack) ), %l7
  266.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  267. st0:    subcc    %fp, %l7, %g0
  268.     bg,a    st3
  269.     sub    %l7, 0xb0, %sp
  270.     b    st3
  271.     sub    %fp, 0xb0, %sp
  272. st1:     sethi    %hi( C_LABEL(current) ), %l6
  273.     ld    [%l6 + %lo( C_LABEL(current) )], %l6
  274.     ld    [%l6 + THREAD_WIM], %l5
  275.     and    %l0, 0x1f, %l7
  276.     cmp    %l5, %l7
  277.     ble,a    st4
  278.     sethi    %hi( C_LABEL(nwindowsm1) ), %l4
  279.     sub    %l5, %l7, %l7
  280.     b    st5
  281.     sub    %l7, 0x1, %l5
  282. st4:    ld    [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4
  283.     sub    %l4, %l7, %l4
  284.     add    %l5, %l4, %l5
  285. st5:    st    %l5, [%l6 + THREAD_UWINDOWS]
  286.     sethi    %hi( C_LABEL(eintstack) ), %l7
  287.     bz,a    st2
  288.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  289.     TRAP_WIN_CLEAN
  290.     sethi    %hi( C_LABEL(eintstack) ), %l7
  291.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  292. st2:    sub    %l7, 0xb0, %sp
  293.  
  294. st3:    std    %g2, [%sp + 96 + 24]
  295.     or    %g0, %g1, %l7
  296.     rd    %y, %l6
  297.     std    %g4, [%sp + 96 + 32]
  298.     andn    %l0, PSR_PIL, %l4
  299.     sll    %l3, 0x8, %l5
  300.     std    %g6, [%sp + 96 + 40]
  301.     or    %l5, %l4, %l4
  302.  
  303.     wr    %l4, 0x0, %psr
  304.     wr    %l4, PSR_ET, %psr
  305.  
  306.     std    %l0, [%sp + 96 + 0]
  307.     std    %l2, [%sp + 96 + 8]
  308.     st    %fp, [%sp + 96 + 16]
  309.     
  310.     or    %g0, 14, %o0    
  311.     or    %g0, %g0, %o1
  312.     call    C_LABEL(do_sparc_timer)
  313.     nop
  314.  
  315.     or    %g0, %l7, %g1
  316.     wr    %l6, 0x0, %y
  317.     ldd    [%sp + 96 + 24], %g2
  318.     ldd    [%sp + 96 + 32], %g4
  319.     ldd    [%sp + 96 + 40], %g6
  320.     wr    %l0, 0x0, %psr
  321.     nop
  322.     nop
  323.     nop
  324.  
  325.     and    %l0, 31, %l5
  326.     sethi    %hi(lnx_winmask), %l6
  327.     or    %l6, %lo(lnx_winmask), %l6
  328.     ldub    [%l6 + %l5], %l5
  329.     andcc    %l0, PSR_PS, %g0
  330.     bnz    1f
  331.     rd    %wim, %l4
  332.  
  333. 1:    andcc    %l5, %l4, %g0
  334.     bnz    2f
  335.     wr    %l0, 0x0, %psr
  336.     nop
  337.     nop
  338.     nop
  339.  
  340.     jmp    %l1
  341.     rett    %l2
  342.  
  343. 2:    wr    %g0, 0x0, %wim
  344.     nop
  345.     nop
  346.     nop
  347.  
  348.     restore
  349.     restore    %g0, 0x1, %l1
  350.     rd    %psr, %l0
  351.     and    %l0, 31, %l0
  352.     sll    %l1, %l0, %l1
  353.     wr    %l1, 0x0, %wim
  354.     sethi    %hi( C_LABEL(current) ), %l1
  355.     ld    [%l1 + %lo( C_LABEL(current) ) ], %l1
  356.     st    %l0, [%l1 + THREAD_WIM]
  357.     save    %g0, %g0, %g0
  358.     
  359.     ldd    [%sp], %l0
  360.     ldd    [%sp + 0x8], %l2
  361.     ldd    [%sp + 0x10], %l4
  362.     ldd    [%sp + 0x18], %l6
  363.     ldd    [%sp + 0x20], %i0
  364.     ldd    [%sp + 0x28], %i2
  365.     ldd    [%sp + 0x30], %i4
  366.     ldd    [%sp + 0x38], %i6
  367.     
  368.     save    %g0, %g0, %g0
  369.     
  370.     jmp    %l1
  371.     rett    %l2
  372.  
  373.  
  374. /* For now all IRQ's not registered get sent here so I can see
  375.  * what is poking the chip.
  376.  */
  377.  
  378.     .align 4
  379.     .globl stray_irq_entry
  380. stray_irq_entry:
  381.     rd    %wim, %l4
  382.     or    %g0, 0x1, %l5
  383.     sll    %l5, %l0, %l5
  384.     andcc    %l0, 0x40, %g0
  385.     bz    tt1
  386.     sethi    %hi( C_LABEL(eintstack) ), %l7
  387.     andcc    %l4, %l5, %g0
  388.     bz    tt0
  389.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  390.     TRAP_WIN_CLEAN
  391.     sethi    %hi( C_LABEL(eintstack) ), %l7
  392.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  393. tt0:    subcc    %fp, %l7, %g0
  394.     bg,a    tt3
  395.     sub    %l7, 0xb0, %sp
  396.     b    tt3
  397.     sub    %fp, 0xb0, %sp
  398. tt1:     sethi    %hi( C_LABEL(current) ), %l6
  399.     ld    [%l6 + %lo( C_LABEL(current) )], %l6
  400.     ld    [%l6 + THREAD_WIM], %l5
  401.     and    %l0, 0x1f, %l7
  402.     cmp    %l5, %l7
  403.     ble,a    tt4
  404.     sethi    %hi( C_LABEL(nwindowsm1) ), %l4
  405.     sub    %l5, %l7, %l7
  406.     b    tt5
  407.     sub    %l7, 0x1, %l5
  408. tt4:    ld    [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4
  409.     sub    %l4, %l7, %l4
  410.     add    %l5, %l4, %l5
  411. tt5:    st    %l5, [%l6 + THREAD_UWINDOWS]
  412.     sethi    %hi( C_LABEL(eintstack) ), %l7
  413.     bz,a    tt2
  414.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  415.     TRAP_WIN_CLEAN
  416.     sethi    %hi( C_LABEL(eintstack) ), %l7
  417.     or    %l7, %lo( C_LABEL(eintstack) ), %l7
  418. tt2:    sub    %l7, 0xb0, %sp
  419.  
  420. tt3:    std    %g2, [%sp + 96 + 24]
  421.     or    %g0, %g1, %l7
  422.     rd    %y, %l6
  423.     std    %g4, [%sp + 96 + 32]
  424.     andn    %l0, PSR_PIL, %l4
  425.     sll    %l3, 0x8, %l5
  426.     std    %g6, [%sp + 96 + 40]
  427.     or    %l5, %l4, %l4
  428.  
  429.     wr    %l4, 0x0, %psr
  430.     wr    %l4, PSR_ET, %psr
  431.  
  432.     std    %l0, [%sp + 96 + 0]
  433.     std    %l2, [%sp + 96 + 8]
  434.     st    %fp, [%sp + 96 + 16]
  435.     
  436.     or    %g0, %l3, %o0    
  437.     or    %g0, %g0, %o1
  438.     call    C_LABEL(unexpected_irq)
  439.     nop
  440.  
  441.     or    %g0, %l7, %g1
  442.     wr    %l6, 0x0, %y
  443.     ldd    [%sp + 96 + 24], %g2
  444.     ldd    [%sp + 96 + 32], %g4
  445.     ldd    [%sp + 96 + 40], %g6
  446.     wr    %l0, 0x0, %psr
  447.     nop
  448.     nop
  449.     nop
  450.  
  451.     and    %l0, 31, %l5
  452.     sethi    %hi(lnx_winmask), %l6
  453.     or    %l6, %lo(lnx_winmask), %l6
  454.     ldub    [%l6 + %l5], %l5
  455.     andcc    %l0, PSR_PS, %g0
  456.     bnz    1f
  457.     rd    %wim, %l4
  458.  
  459. 1:    andcc    %l5, %l4, %g0
  460.     bnz    2f
  461.     wr    %l0, 0x0, %psr
  462.     nop
  463.     nop
  464.     nop
  465.  
  466.     jmp    %l1
  467.     rett    %l2
  468.  
  469. 2:    wr    %g0, 0x0, %wim
  470.     nop
  471.     nop
  472.     nop
  473.  
  474.     restore
  475.     restore    %g0, 0x1, %l1
  476.     rd    %psr, %l0
  477.     and    %l0, 31, %l0
  478.     sll    %l1, %l0, %l1
  479.     wr    %l1, 0x0, %wim
  480.     sethi    %hi( C_LABEL(current) ), %l1
  481.     ld    [%l1 + %lo( C_LABEL(current) ) ], %l1
  482.     st    %l0, [%l1 + THREAD_WIM]
  483.     save    %g0, %g0, %g0
  484.     
  485.     ldd    [%sp], %l0
  486.     ldd    [%sp + 0x8], %l2
  487.     ldd    [%sp + 0x10], %l4
  488.     ldd    [%sp + 0x18], %l6
  489.     ldd    [%sp + 0x20], %i0
  490.     ldd    [%sp + 0x28], %i2
  491.     ldd    [%sp + 0x30], %i4
  492.     ldd    [%sp + 0x38], %i6
  493.     
  494.     save    %g0, %g0, %g0
  495.     
  496.     jmp    %l1
  497.     rett    %l2
  498.  
  499.  
  500.  
  501. /* This routine is optimized for kernel window fills. User fills take about two
  502.  * or three extra jumps on the average. We'll see how this works out.
  503.  */
  504.  
  505. /* Don't use local labels, or if you do be REAL CAREFUL. TRAP_WIN_CLEAN is
  506.  * full of them! If you think this routine is hairy, window spills are worse,
  507.  * see below.
  508.  */
  509.  
  510.     .align 4
  511.     .globl spill_window_entry
  512. spill_window_entry:
  513.     andcc    %l0, 0x40, %g0        ! see if this is a user window fill
  514.     bz,a    spill_from_user
  515.     nop
  516.  
  517.     TRAP_WIN_CLEAN            /* danger, danger... */
  518.     wr    %l0, 0x0, %psr    
  519.     nop
  520.     jmp    %l1
  521.     rett    %l2
  522.  
  523. spill_from_user:
  524.     sethi    %hi( C_LABEL(current) ), %l6
  525.     ld    [%l6 + %lo( C_LABEL(current) )], %l6
  526.     ld    [%l6 + THREAD_WIM], %l5
  527.     and    %l0, 0x1f, %l3
  528.  
  529. /* I don't know what's worse, the extra comparison here, or an extra load
  530.  * from a lookup table, we'll see.
  531.  */
  532.     cmp    %l5, %l3
  533.     ble,a    1f
  534.     sethi    %hi( C_LABEL(nwindowsm1) ), %l4
  535.     sub    %l5, %l3, %l3
  536.     b    2f
  537.     sub    %l3, 0x1, %l5
  538. 1:    ld    [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4
  539.     sub    %l4, %l3, %l4
  540.     add    %l5, %l4, %l5
  541. 2:    st    %l5, [%l6 + THREAD_UWINDOWS]
  542.  
  543.     TRAP_WIN_CLEAN           /* danger, danger... */
  544.     sethi    %hi( C_LABEL(current) ), %l6
  545.     ld    [%l6 + %lo( C_LABEL(current) )], %l6
  546.     ld    [%l6 + THREAD_KSP], %sp
  547.     and    %l0, 0x1f, %l3
  548.     sethi    %hi(lnx_winmask), %l6
  549.     or    %l6, %lo(lnx_winmask), %l6
  550.     ldub    [%l6 + %l3], %l5
  551.     rd    %wim, %l4
  552.     jmp    %l1
  553.     rett    %l2
  554.  
  555. /* A window spill has occurred.  This presents a weird situation, a restore
  556.  * was attempted and a trap occurred. Therefore the restore attempt had no
  557.  * effect on window movement and the trap saved, which means it went in the
  558.  * other direction. :-( We are in a trap window which is two restores away
  559.  * from the window we want to un-invalidate so to speak and three away from
  560.  * the one which will become invalid after this routine. There are probably
  561.  * bugs already this routine. Bugs suck.
  562.  */
  563.  
  564. /* This is a very complicated and hairy routine, don't expect to understand
  565.  * it the first time. :>
  566.  */
  567.  
  568.     .align 4
  569.     .globl fill_window_entry
  570. fill_window_entry:
  571.     wr    %g0, 0, %wim        ! Can not enter invalid register without this.
  572.     andcc    %l0, 0x40, %g0          ! From user?
  573.     restore                ! restore to where trap occurred
  574.     bz    fill_from_user
  575.     restore                ! enter invalid register, whee...
  576.     restore %g0, 0x1, %l1        ! enter one-past invalid register
  577.     rd    %psr, %l0        ! this is the window we need to save
  578.     and    %l0, 0x1f, %l0
  579.     sll    %l1, %l0, %l1
  580.     wr    %l1, 0x0, %wim
  581.     sethi    %hi( C_LABEL(current) ), %l1
  582.     ld    [%l1 + %lo( C_LABEL(current) )], %l1
  583.     st    %l0, [%l1 + THREAD_WIM]
  584.     save    %g0, %g0, %g0        ! back to invalid register
  585.     ldd    [%sp], %l0        ! load the window from stack
  586.     ldd    [%sp + 8], %l2
  587.     ldd    [%sp + 16], %l4
  588.     ldd    [%sp + 24], %l6
  589.     ldd    [%sp + 32], %i0
  590.     ldd    [%sp + 40], %i2
  591.     ldd    [%sp + 48], %i4
  592.     ldd    [%sp + 56], %i6
  593.     save    %g0, %g0, %g0        ! to window where trap happened
  594.     save    %g0, %g0, %g0        ! back to trap window, so rett works
  595.     wr    %l0, 0x0, %psr        ! load condition codes
  596.     nop
  597.     jmp    %l1
  598.     rett    %l2            ! are you as confused as I am?
  599.  
  600. fill_from_user:
  601.     andcc    %sp, 0x7, %g0        ! check for alignment of user stack
  602.     bne    fill_bad_stack
  603.     sra    %sp, 0x1e, %l7
  604.     cmp    %l7, 0x0
  605.     be,a    1f
  606.     andn    %sp, 0xfff, %l7
  607.     cmp    %l7, -1
  608.     bne    fill_bad_stack
  609.     andn    %sp, 0xfff, %l7
  610. 1:    lda    [%l7] ASI_PTE, %l7
  611.     srl    %l7, 0x1d, %l7
  612.     andn    %l7, 0x2, %l7
  613.     cmp    %l7, 0x4
  614.     bne    fill_bad_stack
  615.     and    %sp, 0xfff, %l7
  616.     cmp    %l7, 0xfc1
  617.     bl,a    fill_stack_ok
  618.     restore    %g0, 1, %l1
  619.     add    %sp, 0x38, %l5
  620.     sra    %sp, 0x1e, %l7
  621.     cmp    %l7, 0x0
  622.     be,a    1f
  623.     andn    %sp, 0xfff, %l7
  624.     cmp    %l7, -1
  625.     bne    fill_bad_stack
  626.     andn    %sp, 0xfff, %l7
  627. 1:    lda    [%l7] ASI_PTE, %l7
  628.     srl    %l7, 0x1d, %l7
  629.     andn    %l7, 0x2, %l7
  630.     cmp    %l7, 0x4
  631.     be,a    fill_stack_ok
  632.     restore    %g0, 0x1, %l1
  633.  
  634. fill_bad_stack:
  635.     save    %g0, %g0, %g0            ! save to where restore happened
  636.     save    %g0, 0x1, %l4            ! save is an add remember? to trap window
  637.     sethi    %hi( C_LABEL(current) ), %l6
  638.     ld    [%l6 + %lo( C_LABEL(current) )], %l6
  639.     st    %l4, [%l6 + THREAD_UWINDOWS]    ! update current->tss values
  640.     ld    [%l6 + THREAD_WIM], %l5
  641.     sll    %l4, %l5, %l4
  642.     wr    %l4, 0x0, %wim
  643.     ld    [%l6 + THREAD_KSP], %sp        ! set to kernel stack pointer
  644.     wr    %l0, 0x20, %psr            ! turn off traps
  645.     std    %l0, [%sp + C_STACK]        ! set up thread_frame on stack
  646.     rd    %y, %l3
  647.     std    %l2, [%sp + C_STACK + 0x8]
  648.     or    %g0, 0x6, %o0            ! so _sparc_trap knows what to do
  649.     st    %g1, [%sp + C_STACK + 0x14]    ! no need to save %g0, always zero
  650.     or    %g0, %l0, %o1
  651.     std    %g2, [%sp + C_STACK + 0x18]
  652.     or    %g0, %l1, %o2
  653.     std    %g4, [%sp + C_STACK + 0x20]
  654.     add    %sp, C_STACK, %o3
  655.     std    %g6, [%sp + C_STACK + 0x28]
  656.     std    %i0, [%sp + C_STACK + 0x30]
  657.     std    %i2, [%sp + C_STACK + 0x38]
  658.     std    %i4, [%sp + C_STACK + 0x40]
  659.     call    sparc_trap
  660.     std    %i6, [%sp + C_STACK + 0x48]
  661.     
  662.     ldd    [%sp + C_STACK], %l0
  663.     ldd    [%sp + C_STACK + 0x8], %l2
  664.     wr    %l3, 0, %y
  665.     ld    [%sp + C_STACK + 0x14], %g1
  666.     ldd    [%sp + C_STACK + 0x18], %g2
  667.     ldd    [%sp + C_STACK + 0x20], %g4
  668.     ldd    [%sp + C_STACK + 0x28], %g6
  669.     ldd    [%sp + C_STACK + 0x30], %i0
  670.     ldd    [%sp + C_STACK + 0x38], %i2
  671.     ldd    [%sp + C_STACK + 0x40], %i4
  672.     wr    %l0, 0, %psr            ! disable traps again
  673.     ldd    [%sp + C_STACK + 0x48], %i6
  674.     sethi    %hi( C_LABEL(current) ), %l6
  675.     ld    [%l6 + %lo( C_LABEL(current) )], %l6
  676.     ld    [%l6 + THREAD_W_SAVED], %l7
  677.     cmp    %l7, 0x0
  678.     bl,a    1f
  679.     wr    %g0, 0x0, %wim
  680.     b,a    leave_trap
  681.  
  682. 1:    or    %g0, %g6, %l3
  683.     or    %g0, %l6, %g6
  684.     st    %g0, [%g6 + THREAD_W_SAVED]
  685.     restore    %g0, %g0, %g0
  686.     restore    %g0, %g0, %g0
  687.     restore    %g0, 0x1, %l1
  688.     rd    %psr, %l0
  689.     sll    %l1, %l0, %l1
  690.     wr    %l1, 0x0, %wim
  691.     and    %l0, 0x1f, %l0
  692.     st    %l0, [%g6 + THREAD_WIM]
  693.     nop
  694.     save    %g0, %g0, %g0
  695.     ldd    [%sp], %l0            ! load number one
  696.     ldd    [%sp + 0x8], %l2
  697.     ldd    [%sp + 0x10], %l4
  698.     ldd    [%sp + 0x18], %l6
  699.     ldd    [%sp + 0x20], %i0
  700.     ldd    [%sp + 0x28], %i2
  701.     ldd    [%sp + 0x30], %i4
  702.     ldd    [%sp + 0x38], %i6
  703.     save    %g0, %g0, %g0
  704.     ldd    [%sp], %l0            ! load number two
  705.     ldd    [%sp + 0x8], %l2    
  706.     ldd    [%sp + 0x10], %l4
  707.     ldd    [%sp + 0x18], %l6
  708.     ldd    [%sp + 0x20], %i0
  709.     ldd    [%sp + 0x28], %i2
  710.     ldd    [%sp + 0x30], %i4
  711.     ldd    [%sp + 0x38], %i6
  712.     save    %g0, %g0, %g0            ! re-enter trap window
  713.     wr    %l0, 0x0, %psr            ! restore condition codes
  714.     or    %g0, %l3, %g6            ! restore scratch register
  715.     jmp    %l1
  716.     rett    %l2
  717.  
  718. fill_stack_ok:
  719.     rd    %psr, %l0
  720.     sll    %l1, %l0, %l1
  721.     wr    %l1, 0x0, %wim
  722.     sethi    %hi( C_LABEL(current) ), %l2
  723.     ld    [%l2 + %lo( C_LABEL(current) )], %l2
  724.     and    %l0, 0x1f, %l0
  725.     st    %l0, [%l2 + THREAD_WIM]
  726.     save    %g0, %g0, %g0
  727.     ldd    [%sp], %l0            ! only one load necessary
  728.     ldd    [%sp + 0x8], %l2
  729.     ldd    [%sp + 0x10], %l4
  730.     ldd    [%sp + 0x18], %l6
  731.     ldd    [%sp + 0x20], %i0
  732.     ldd    [%sp + 0x28], %i2
  733.     ldd    [%sp + 0x30], %i4
  734.     ldd    [%sp + 0x38], %i6
  735.     save    %g0, %g0, %g0
  736.     save    %g0, %g0, %g0            ! save into trap window
  737.     wr    %l0, 0x0, %psr            ! local number 0 here has cond codes
  738.     nop
  739.     jmp    %l1
  740.     rett    %l2
  741.  
  742.     .align 4
  743.     .globl trap_entry
  744. trap_entry:
  745.     TRAP_WIN_CLEAN
  746.     jmp    %l1
  747.     rett    %l2
  748.  
  749.     .align 4
  750.     .globl linux_trap_nmi
  751. linux_trap_nmi:
  752.     TRAP_WIN_CLEAN
  753.     jmp    %l1
  754.     rett    %l2
  755.  
  756.     .align 4
  757.     .globl sparc_trap
  758. sparc_trap:
  759.     TRAP_WIN_CLEAN
  760.     jmp    %l1
  761.     rett    %l2
  762.  
  763.     .align 4
  764.     .globl leave_trap
  765. leave_trap:
  766.     jmp    %l1
  767.     rett    %l2
  768.  
  769. /* The following two things point to window management tables. The first
  770.    one is used to quickly look up how many user windows there are from
  771.    trap-land. The second is used in a trap handler to determine if a rett
  772.    instruction will land us smack inside the invalid window that possibly
  773.    the trap was called to fix-up.
  774. */
  775.  
  776. /* For now these are static tables geared for a 7 window sparc. */
  777.  
  778.         .data
  779.         .align 4
  780. lnx_winmask:    .byte    2, 4, 8, 16, 32, 64, 128, 1  ! lnx_winmask[0..7]
  781.  
  782.     
  783.         .align 4
  784.         .globl C_LABEL(sys_call_table)
  785. C_LABEL(sys_call_table):
  786.     .long C_LABEL(sys_setup)        /* 0 */
  787.     .long C_LABEL(sys_exit)
  788.     .long C_LABEL(sys_fork)
  789.     .long C_LABEL(sys_read)
  790.     .long C_LABEL(sys_write)
  791.     .long C_LABEL(sys_open)            /* 5 */
  792.     .long C_LABEL(sys_close)
  793.     .long C_LABEL(sys_waitpid)
  794.     .long C_LABEL(sys_creat)
  795.     .long C_LABEL(sys_link)
  796.     .long C_LABEL(sys_unlink)        /* 10 */
  797.     .long C_LABEL(sys_execve)
  798.     .long C_LABEL(sys_chdir)
  799.     .long C_LABEL(sys_time)
  800.     .long C_LABEL(sys_mknod)
  801.     .long C_LABEL(sys_chmod)        /* 15 */
  802.     .long C_LABEL(sys_chown)
  803.     .long C_LABEL(sys_break)
  804.     .long C_LABEL(sys_stat)
  805.     .long C_LABEL(sys_lseek)
  806.     .long C_LABEL(sys_getpid)        /* 20 */
  807.     .long C_LABEL(sys_mount)
  808.     .long C_LABEL(sys_umount)
  809.     .long C_LABEL(sys_setuid)
  810.     .long C_LABEL(sys_getuid)
  811.     .long C_LABEL(sys_stime)        /* 25 */
  812.     .long C_LABEL(sys_ni_syscall)        /* this will be sys_ptrace() */
  813.     .long C_LABEL(sys_alarm)
  814.     .long C_LABEL(sys_fstat)
  815.     .long C_LABEL(sys_pause)
  816.     .long C_LABEL(sys_utime)        /* 30 */
  817.     .long C_LABEL(sys_stty)
  818.     .long C_LABEL(sys_gtty)
  819.     .long C_LABEL(sys_access)
  820.     .long C_LABEL(sys_nice)
  821.     .long C_LABEL(sys_ftime)        /* 35 */
  822.     .long C_LABEL(sys_sync)
  823.     .long C_LABEL(sys_kill)
  824.     .long C_LABEL(sys_rename)
  825.     .long C_LABEL(sys_mkdir)
  826.     .long C_LABEL(sys_rmdir)        /* 40 */
  827.     .long C_LABEL(sys_dup)
  828.     .long C_LABEL(sys_pipe)
  829.     .long C_LABEL(sys_times)
  830.     .long C_LABEL(sys_prof)
  831.     .long C_LABEL(sys_brk)            /* 45 */
  832.     .long C_LABEL(sys_setgid)
  833.     .long C_LABEL(sys_getgid)
  834.     .long C_LABEL(sys_signal)
  835.     .long C_LABEL(sys_geteuid)
  836.     .long C_LABEL(sys_getegid)        /* 50 */
  837.     .long C_LABEL(sys_acct)
  838.     .long C_LABEL(sys_phys)
  839.     .long C_LABEL(sys_lock)
  840.     .long C_LABEL(sys_ioctl)
  841.     .long C_LABEL(sys_fcntl)        /* 55 */
  842.     .long C_LABEL(sys_mpx)
  843.     .long C_LABEL(sys_setpgid)
  844.     .long C_LABEL(sys_ulimit)
  845.     .long C_LABEL(sys_olduname)
  846.     .long C_LABEL(sys_umask)    /* 60 */
  847.     .long C_LABEL(sys_chroot)
  848.     .long C_LABEL(sys_ustat)
  849.     .long C_LABEL(sys_dup2)
  850.     .long C_LABEL(sys_getppid)
  851.     .long C_LABEL(sys_getpgrp)        /* 65 */
  852.     .long C_LABEL(sys_setsid)
  853.     .long C_LABEL(sys_sigaction)
  854.     .long C_LABEL(sys_sgetmask)
  855.     .long C_LABEL(sys_ssetmask)
  856.     .long C_LABEL(sys_setreuid)        /* 70 */
  857.     .long C_LABEL(sys_setregid)
  858.     .long C_LABEL(sys_sigsuspend)
  859.     .long C_LABEL(sys_sigpending)
  860.     .long C_LABEL(sys_sethostname)
  861.     .long C_LABEL(sys_setrlimit)        /* 75 */
  862.     .long C_LABEL(sys_getrlimit)
  863.     .long C_LABEL(sys_getrusage)
  864.     .long C_LABEL(sys_gettimeofday)
  865.     .long C_LABEL(sys_settimeofday)
  866.     .long C_LABEL(sys_getgroups)        /* 80 */
  867.     .long C_LABEL(sys_setgroups)
  868.     .long C_LABEL(sys_select)
  869.     .long C_LABEL(sys_symlink)
  870.     .long C_LABEL(sys_lstat)
  871.     .long C_LABEL(sys_readlink)        /* 85 */
  872.     .long C_LABEL(sys_uselib)
  873.     .long C_LABEL(sys_swapon)
  874.     .long C_LABEL(sys_reboot)
  875.     .long C_LABEL(sys_readdir)
  876.     .long C_LABEL(sys_mmap)            /* 90 */
  877.     .long C_LABEL(sys_munmap)
  878.     .long C_LABEL(sys_truncate)
  879.     .long C_LABEL(sys_ftruncate)
  880.     .long C_LABEL(sys_fchmod)
  881.     .long C_LABEL(sys_fchown)        /* 95 */
  882.     .long C_LABEL(sys_getpriority)
  883.     .long C_LABEL(sys_setpriority)
  884.     .long C_LABEL(sys_profil)
  885.     .long C_LABEL(sys_statfs)
  886.     .long C_LABEL(sys_fstatfs)        /* 100 */
  887.     .long C_LABEL(sys_ni_syscall)
  888.     .long C_LABEL(sys_socketcall)
  889.     .long C_LABEL(sys_syslog)
  890.     .long C_LABEL(sys_setitimer)
  891.     .long C_LABEL(sys_getitimer)        /* 105 */
  892.     .long C_LABEL(sys_newstat)
  893.     .long C_LABEL(sys_newlstat)
  894.     .long C_LABEL(sys_newfstat)
  895.     .long C_LABEL(sys_uname)
  896.     .long C_LABEL(sys_ni_syscall)        /* 110 */
  897.     .long C_LABEL(sys_vhangup)
  898.     .long C_LABEL(sys_idle)
  899.     .long C_LABEL(sys_ni_syscall)           /* was vm86, meaningless on Sparc */
  900.     .long C_LABEL(sys_wait4)
  901.     .long C_LABEL(sys_swapoff)        /* 115 */
  902.     .long C_LABEL(sys_sysinfo)
  903.     .long C_LABEL(sys_ipc)
  904.     .long C_LABEL(sys_fsync)
  905.     .long C_LABEL(sys_sigreturn)
  906.     .long C_LABEL(sys_ni_syscall)        /* 120 */
  907.     .long C_LABEL(sys_setdomainname)
  908.     .long C_LABEL(sys_newuname)
  909.     .long C_LABEL(sys_ni_syscall)
  910.     .long C_LABEL(sys_adjtimex)
  911.     .long C_LABEL(sys_mprotect)        /* 125 */
  912.     .long C_LABEL(sys_sigprocmask)
  913.     .long C_LABEL(sys_create_module)
  914.     .long C_LABEL(sys_init_module)
  915.     .long C_LABEL(sys_delete_module)
  916.     .long C_LABEL(sys_get_kernel_syms)    /* 130 */
  917.     .long C_LABEL(sys_ni_syscall)
  918.     .long C_LABEL(sys_getpgid)
  919.     .long C_LABEL(sys_fchdir)
  920.     .long C_LABEL(sys_bdflush)
  921.     .long C_LABEL(sys_sysfs)    /* 135 */
  922.     .long C_LABEL(sys_personality)
  923.     .long 0                /* for afs_syscall */
  924.     .long C_LABEL(sys_setfsuid)
  925.     .long C_LABEL(sys_setfsgid)
  926.     .long C_LABEL(sys_llseek)        /* 140 */
  927.     .align 4
  928.