root/arch/sparc/kernel/entry.S

/* [previous][next][first][last][top][bottom][index][help] */
   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

/* [previous][next][first][last][top][bottom][index][help] */