root/arch/sparc/kernel/entry.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* $Id: entry.S,v 1.65 1995/11/25 14:36:22 zaitcev Exp $
   2  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
   3  *
   4  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   5  */
   6 
   7 #include <linux/config.h>
   8 
   9 #include <asm/head.h>
  10 #include <asm/asi.h>
  11 #include <asm/kgdb.h>
  12 #include <asm/contregs.h>
  13 #include <asm/ptrace.h>
  14 #include <asm/psr.h>
  15 #include <asm/cprefix.h>
  16 #include <asm/vaddrs.h>
  17 #include <asm/memreg.h>
  18 #include <asm/page.h>
  19 #include <asm/winmacro.h>
  20 #include <asm/signal.h>
  21 #include <asm/errno.h>
  22 
  23 #define NR_SYSCALLS 255      /* Each OS is different... */
  24 
  25 /* All trap entry points _must_ begin with this macro or else you
  26  * lose.  It makes sure the kernel has a proper window so that
  27  * c-code can be called.  Some day for SMP we'll grab klock here.
  28  */
  29 #define SAVE_ALL \
  30         sethi   %hi(trap_setup), %l4; \
  31         jmpl    %l4 + %lo(trap_setup), %l6; \
  32          nop;
  33 
  34 /* All traps low-level code here must end with this macro.
  35  * For SMP configurations the ret_trap_entry routine will
  36  * have to appropriate code to actually release the kernel
  37  * entry lock.
  38  */
  39 #define RESTORE_ALL \
  40         b       ret_trap_entry; \
  41          nop;
  42 
  43 /* First, KGDB low level things.  This is a rewrite
  44  * of the routines found in the sparc-stub.c asm() statement
  45  * from the gdb distribution.  This is also dual-purpose
  46  * as a software trap for userlevel programs.
  47  */
  48         .data
  49         .align  4
  50 
  51 in_trap_handler:
  52         .word   0
  53 
  54         .text
  55         .align  4
  56 
  57 ! This function is called when any SPARC trap (except window overflow or
  58 ! underflow) occurs.  It makes sure that the invalid register window is still
  59 ! available before jumping into C code.  It will also restore the world if you
  60 ! return from handle_exception.
  61 
  62         .globl  C_LABEL(trap_low)
  63 C_LABEL(trap_low):
  64         rd      %wim, %l3
  65         SAVE_ALL
  66 
  67         sethi   %hi(in_trap_handler), %l4
  68         ld      [%lo(in_trap_handler) + %l4], %l5
  69         inc     %l5
  70         st      %l5, [%lo(in_trap_handler) + %l4]
  71 
  72         /* Make sure kgdb sees the same state we just saved. */
  73         LOAD_PT_GLOBALS(sp)
  74         LOAD_PT_INS(sp)
  75         ld      [%sp + STACKFRAME_SZ + PT_Y], %l4
  76         ld      [%sp + STACKFRAME_SZ + PT_WIM], %l3
  77         ld      [%sp + STACKFRAME_SZ + PT_PSR], %l0
  78         ld      [%sp + STACKFRAME_SZ + PT_PC], %l1
  79         ld      [%sp + STACKFRAME_SZ + PT_NPC], %l2
  80         rd      %tbr, %l5       /* Never changes... */
  81 
  82         /* Make kgdb exception frame. */        
  83         sub     %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
  84                                         ! + hidden arg + arg spill
  85                                         ! + doubleword alignment
  86                                         ! + registers[72] local var
  87         SAVE_KGDB_GLOBALS(sp)
  88         SAVE_KGDB_INS(sp)
  89         SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
  90 
  91         /* We are increasing PIL, so two writes. */
  92         or      %l0, PSR_PIL, %l0
  93         wr      %l0, 0, %psr
  94         wr      %l0, PSR_ET, %psr
  95         WRITE_PAUSE
  96 
  97         call    C_LABEL(handle_exception)
  98          add    %sp, STACKFRAME_SZ, %o0 ! Pass address of registers
  99 
 100         /* Load new kgdb register set. */
 101         LOAD_KGDB_GLOBALS(sp)
 102         LOAD_KGDB_INS(sp)
 103         LOAD_KGDB_SREGS(sp, l0, l2)
 104         ld      [%sp + STACKFRAME_SZ + KGDB_WIM], %l6
 105         wr      %l0, 0x0, %y
 106 
 107         sethi   %hi(in_trap_handler), %l4
 108         ld      [%lo(in_trap_handler) + %l4], %l5
 109         dec     %l5
 110         st      %l5, [%lo(in_trap_handler) + %l4]
 111 
 112         add     %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
 113 
 114         /* Now take what kgdb did and place it into the pt_regs
 115          * frame which SparcLinux RESTORE_ALL understands.,
 116          */
 117         STORE_PT_INS(sp)
 118         STORE_PT_GLOBALS(sp)
 119         STORE_PT_YREG(sp, g2)
 120         STORE_PT_PRIV(sp, l1, l2, l3, l6)
 121 
 122         /* Cross your fingers... */
 123         RESTORE_ALL
 124 
 125 
 126 #ifdef CONFIG_BLK_DEV_FD
 127 #ifdef TRACE_FLOPPY_HARDINT
 128 /* Useful tracing */
 129         .data
 130         .align  4
 131         .globl  C_LABEL(floppy_hardint_trace)
 132 C_LABEL(floppy_hardint_trace):
 133         .skip   32
 134         .globl  C_LABEL(floppy_hardint_index)
 135 C_LABEL(floppy_hardint_index):
 136         .word   0
 137 #endif
 138 
 139         .text
 140         .align  4
 141         .globl  C_LABEL(floppy_hardint)
 142 C_LABEL(floppy_hardint):
 143         /* Can only use regs %l3->%l7:
 144          * %l3 -- base address of fdc registers
 145          * %l4 -- pdma_vaddr
 146          * %l5 -- scratch for ld/st address
 147          * %l6 -- pdma_size
 148          * %l7 -- floppy_softint
 149          */
 150 
 151 #ifdef TRACE_FLOPPY_HARDINT
 152         sethi   %hi(C_LABEL(floppy_hardint_trace)), %l5
 153         or      %l5, %lo(C_LABEL(floppy_hardint_trace)), %l5
 154         ld      [%l5 + 32], %l7
 155         add     %l7, 1, %l7
 156         and     %l7, 31, %l7
 157         st      %l7, [%l5 + 32]
 158         sub     %l7, 1, %l7
 159         and     %l7, 31, %l7
 160         add     %l7, %l5, %l5
 161         or      %g0, 0xf, %l7
 162         stb     %l7, [%l5]
 163 #endif
 164 
 165         /* Do we have work to do? */
 166         sethi   %hi(C_LABEL(doing_pdma)), %l4
 167         ld      [%l4 + %lo(C_LABEL(doing_pdma))], %l4
 168         cmp     %l4, 0
 169         be      floppy_dosoftint
 170          nop
 171 
 172         /* Load fdc register base */
 173         sethi   %hi(C_LABEL(fdc_status)), %l3
 174         ld      [%l3 + %lo(C_LABEL(fdc_status))], %l3
 175 
 176         /* Setup register addresses */
 177         sethi   %hi(C_LABEL(pdma_vaddr)), %l5   ! transfer buffer
 178         ld      [%l5 + %lo(C_LABEL(pdma_vaddr))], %l4
 179         sethi   %hi(C_LABEL(pdma_size)), %l5    ! bytes to go
 180         ld      [%l5 + %lo(C_LABEL(pdma_size))], %l6
 181 next_byte:
 182 #ifdef TRACE_FLOPPY_HARDINT
 183         sethi   %hi(C_LABEL(floppy_hardint_trace)), %l5
 184         or      %l5, %lo(C_LABEL(floppy_hardint_trace)), %l5
 185         ld      [%l5 + 32], %l7
 186         add     %l7, 1, %l7
 187         and     %l7, 31, %l7
 188         st      %l7, [%l5 + 32]
 189         sub     %l7, 1, %l7
 190         and     %l7, 31, %l7
 191         add     %l7, %l5, %l5
 192         ldub    [%l3], %l7
 193         stb     %l7, [%l5]
 194 #else
 195         ldub    [%l3], %l7
 196 #endif
 197 
 198         andcc   %l7, 0x80, %g0          ! Does fifo still have data
 199         bz      floppy_fifo_emptied     ! fifo has been emptied...
 200          andcc  %l7, 0x20, %g0          ! in non-dma mode still?
 201         bz      floppy_overrun          ! nope, overrun
 202          andcc  %l7, 0x40, %g0          ! 0=write 1=read
 203         bz      floppy_write
 204          sub    %l6, 0x1, %l6
 205 
 206         /* Ok, actually read this byte */
 207         ldub    [%l3 + 1], %l7
 208         orcc    %g0, %l6, %g0
 209         stb     %l7, [%l4]
 210         bne     next_byte
 211          add    %l4, 0x1, %l4
 212 
 213         b       floppy_tdone
 214          nop
 215 
 216 floppy_write:
 217         /* Ok, actually write this byte */
 218         ldub    [%l4], %l7
 219         orcc    %g0, %l6, %g0
 220         stb     %l7, [%l3 + 1]
 221         bne     next_byte
 222          add    %l4, 0x1, %l4
 223 
 224         /* fall through... */
 225 floppy_tdone:
 226         sethi   %hi(C_LABEL(pdma_vaddr)), %l5
 227         st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
 228         sethi   %hi(C_LABEL(pdma_size)), %l5
 229         st      %l6, [%l5 + %lo(C_LABEL(pdma_size))]
 230         /* Flip terminal count pin */
 231         sethi   %hi(AUXIO_VADDR), %l4
 232         ldub    [%l4 + %lo(AUXIO_VADDR) + 0x3], %l5
 233         or      %l5, 0xf4, %l5
 234         stb     %l5, [%l4 + %lo(AUXIO_VADDR) + 0x3]
 235 
 236         /* Kill some time so the bits set */
 237         WRITE_PAUSE
 238         WRITE_PAUSE
 239 
 240         ldub    [%l4 + %lo(AUXIO_VADDR) + 0x3], %l5
 241         andn    %l5, 0x04, %l5
 242         or      %l5, 0xf0, %l5
 243         stb     %l5, [%l4 + %lo(AUXIO_VADDR) + 0x3]
 244 
 245         /* Prevent recursion */
 246         sethi   %hi(C_LABEL(doing_pdma)), %l4
 247         b       floppy_dosoftint
 248          st     %g0, [%l4 + %lo(C_LABEL(doing_pdma))]
 249 
 250         /* We emptied the FIFO, but we haven't read everything
 251          * as of yet.  Store the current transfer address and
 252          * bytes left to read so we can continue when the next
 253          * fast IRQ comes in.
 254          */
 255 floppy_fifo_emptied:
 256         sethi   %hi(C_LABEL(pdma_vaddr)), %l5
 257         st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
 258         sethi   %hi(C_LABEL(pdma_size)), %l7
 259         st      %l6, [%l7 + %lo(C_LABEL(pdma_size))]
 260 
 261         /* Restore condition codes */
 262         wr      %l0, 0x0, %psr
 263         WRITE_PAUSE
 264 
 265         jmp     %l1
 266         rett    %l2
 267 
 268 floppy_overrun:
 269         sethi   %hi(C_LABEL(pdma_vaddr)), %l5
 270         st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
 271         sethi   %hi(C_LABEL(pdma_size)), %l5
 272         st      %l6, [%l5 + %lo(C_LABEL(pdma_size))]
 273         /* Prevent recursion */
 274         sethi   %hi(C_LABEL(doing_pdma)), %l4
 275         st      %g0, [%l4 + %lo(C_LABEL(doing_pdma))]
 276 
 277         /* fall through... */
 278 floppy_dosoftint:
 279         rd      %wim, %l3
 280         SAVE_ALL
 281 
 282         /* Set all IRQs off. */
 283         or      %l0, PSR_PIL, %l4
 284         wr      %l4, 0x0, %psr
 285         wr      %l4, PSR_ET, %psr
 286         WRITE_PAUSE
 287 
 288         mov     11, %o0                 ! floppy irq level
 289         call    C_LABEL(floppy_interrupt)
 290          add    %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs
 291 
 292         RESTORE_ALL
 293         
 294 #endif /* (CONFIG_BLK_DEV_FD) */
 295 
 296         /* Bad trap handler */
 297         .globl  bad_trap_handler
 298 bad_trap_handler:
 299         SAVE_ALL
 300         wr      %l0, PSR_ET, %psr
 301         WRITE_PAUSE
 302 
 303         mov     %l7, %o0                ! trap number
 304         mov     %l0, %o1                ! psr
 305         call    C_LABEL(do_hw_interrupt)
 306          mov    %l1, %o2                ! pc
 307         RESTORE_ALL
 308         
 309 /* For now all IRQ's not registered get sent here. handler_irq() will
 310  * see if a routine is registered to handle this interrupt and if not
 311  * it will say so on the console.
 312  */
 313 
 314         .align  4
 315         .globl  real_irq_entry
 316 real_irq_entry:
 317         SAVE_ALL
 318 
 319         /* start atomic operation with respect to software interrupts */
 320         sethi   %hi(C_LABEL(intr_count)), %l4
 321         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 322         add     %l5, 0x1, %l5
 323         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 324 
 325         /* Enable traps w/IRQs off, so we can call c-code properly.
 326          * Note how we are increasing PIL so we need to do two writes
 327          * to work around a MicroSPARC bug of sorts.
 328          */
 329         or      %l0, PSR_PIL, %l4
 330         wr      %l4, 0x0, %psr
 331         wr      %l4, PSR_ET, %psr
 332         WRITE_PAUSE
 333 
 334         mov     %l7, %o0                ! irq level
 335         call    C_LABEL(handler_irq)
 336          add    %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr
 337 
 338 rie_checkbh:
 339         sethi   %hi(C_LABEL(intr_count)), %l4
 340         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 341         subcc   %l5, 0x1, %l5
 342         bne     2f      /* IRQ within IRQ, get out of here... */
 343          nop
 344         sethi   %hi(C_LABEL(bh_active)), %l3
 345         ld      [%l3 + %lo(C_LABEL(bh_active))], %g2
 346         sethi   %hi(C_LABEL(bh_mask)), %l3
 347         ld      [%l3 + %lo(C_LABEL(bh_mask))], %g3
 348         andcc   %g2, %g3, %g0
 349         be      2f
 350          nop
 351         call    C_LABEL(do_bottom_half) 
 352          nop
 353         /* Try again... */
 354         b       rie_checkbh
 355          nop
 356         
 357 2:
 358         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 359         RESTORE_ALL
 360 
 361 /* Soft IRQ's are handled just like hard IRQ's except that we
 362  * need to clear the IRQ line ourselves (in the interrupt reg)
 363  * and we don't take care of bottom-half handlers here.  We'll
 364  * just deal with it at the next clock tick, and since software
 365  * IRQ's relatively don't happen that often....
 366  * XXX BIG XXX Turn the software IRQ bit we need to clear into
 367  * XXX BIG XXX an element reference in an array that we can set
 368  * XXX BIG XXX a boot time based upon arch type
 369  * XXX BIG XXX OR... rewrite the appropriate IRQ trap table
 370  * XXX BIG XXX entries once the arch is detected (sun4/4c or sun4m)
 371  *
 372  * XXX EVEN BIGGER XXX Linux has bh_handlers for software interrupts
 373  * XXX EVEN BIGGER XXX so we do not even have to worry about this
 374  * XXX EVEN BIGGER XXX brain damaged software interrupt mechanism.
 375  */
 376 
 377         .align  4
 378         .globl  soft_irq_entry
 379 soft_irq_entry:
 380         SAVE_ALL
 381 
 382         /* We have tucked the bit to clear in the int reg into
 383          * %l4, take care of it now before we do anything else.
 384          */
 385         sethi   %hi(INTREG_VADDR), %l5
 386         ldsb    [%l5 + %lo(INTREG_VADDR)], %l6
 387         andn    %l6, %l4, %l6
 388         stb     %l6, [%l5 + %lo(INTREG_VADDR)]
 389 
 390         /* start atomic operation with respect to software interrupts */
 391         sethi   %hi(C_LABEL(intr_count)), %l4
 392         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 393         add     %l5, 0x1, %l5
 394         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 395 
 396         or      %l0, PSR_PIL, %l4
 397         wr      %l4, 0x0, %psr          ! grrr!
 398         wr      %l4, PSR_ET, %psr       ! double grrr!
 399 
 400         mov     %l7, %o0        
 401         add     %sp, STACKFRAME_SZ, %o1
 402         call    C_LABEL(handler_irq)
 403          nop
 404 
 405         sethi   %hi(C_LABEL(intr_count)), %l4
 406         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 407         subcc   %l5, 0x1, %l5
 408         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 409 
 410         RESTORE_ALL
 411 
 412         /* This routine handles illegal isntructions and privileged
 413          * instruction attempts from user code.
 414          */
 415         .align  4
 416         .globl  bad_instruction
 417 bad_instruction:
 418         SAVE_ALL
 419         wr      %l0, PSR_ET, %psr               ! re-enable traps
 420         WRITE_PAUSE
 421 
 422         add     %sp, STACKFRAME_SZ, %o0
 423         mov     %l1, %o1
 424         mov     %l2, %o2
 425         call    C_LABEL(do_illegal_instruction)
 426          mov    %l0, %o3
 427         RESTORE_ALL
 428 
 429         .align  4
 430         .globl  priv_instruction
 431 priv_instruction:
 432         SAVE_ALL
 433         wr      %l0, PSR_ET, %psr
 434         WRITE_PAUSE
 435 
 436         add     %sp, STACKFRAME_SZ, %o0
 437         mov     %l1, %o1
 438         mov     %l2, %o2
 439         call    C_LABEL(do_priv_instruction)
 440          mov    %l0, %o3
 441         RESTORE_ALL
 442 
 443         /* This routine handles unaligned data accesses.
 444          */
 445         .align  4
 446         .globl  mna_handler
 447 mna_handler:
 448         SAVE_ALL
 449         wr      %l0, PSR_ET, %psr               ! re-enable traps
 450         WRITE_PAUSE
 451 
 452         add     %sp, STACKFRAME_SZ, %o0
 453         mov     %l1, %o1
 454         mov     %l2, %o2
 455         call    C_LABEL(do_memaccess_unaligned)
 456          mov    %l0, %o3
 457         RESTORE_ALL
 458 
 459         /* This routine handles floating point disabled traps. */
 460         .align  4
 461         .globl  fpd_trap_handler
 462 fpd_trap_handler:
 463         SAVE_ALL
 464         wr      %l0, PSR_ET, %psr               ! re-enable traps
 465         WRITE_PAUSE
 466 
 467         add     %sp, STACKFRAME_SZ, %o0
 468         mov     %l1, %o1
 469         mov     %l2, %o2
 470         call    C_LABEL(do_fpd_trap)
 471          mov    %l0, %o3
 472         RESTORE_ALL
 473 
 474         /* This routine handles Floating Point Exceptions. */
 475         .align  4
 476         .globl  fpe_trap_handler
 477 fpe_trap_handler:
 478         SAVE_ALL
 479         wr      %l0, PSR_ET, %psr               ! re-enable traps
 480         WRITE_PAUSE
 481 
 482         add     %sp, STACKFRAME_SZ, %o0
 483         mov     %l1, %o1
 484         mov     %l2, %o2
 485         call    C_LABEL(do_fpe_trap)
 486          mov    %l0, %o3
 487         RESTORE_ALL
 488 
 489         /* This routine handles Tag Overflow Exceptions. */
 490         .align  4
 491         .globl  do_tag_overflow
 492 do_tag_overflow:
 493         SAVE_ALL
 494         wr      %l0, PSR_ET, %psr               ! re-enable traps
 495         WRITE_PAUSE
 496 
 497         add     %sp, STACKFRAME_SZ, %o0
 498         mov     %l1, %o1
 499         mov     %l2, %o2
 500         call    C_LABEL(handle_tag_overflow)
 501          mov    %l0, %o3
 502         RESTORE_ALL
 503 
 504         /* This routine handles Watchpoint Exceptions. */
 505         .align  4
 506         .globl  do_watchpoint
 507 do_watchpoint:
 508         SAVE_ALL
 509         wr      %l0, PSR_ET, %psr               ! re-enable traps
 510         WRITE_PAUSE
 511 
 512         add     %sp, STACKFRAME_SZ, %o0
 513         mov     %l1, %o1
 514         mov     %l2, %o2
 515         call    C_LABEL(handle_watchpoint)
 516          mov    %l0, %o3
 517         RESTORE_ALL
 518 
 519         /* This routine handles Register Access Exceptions. */
 520         .align  4
 521         .globl  do_reg_access
 522 do_reg_access:
 523         SAVE_ALL
 524         wr      %l0, PSR_ET, %psr               ! re-enable traps
 525         WRITE_PAUSE
 526 
 527         add     %sp, STACKFRAME_SZ, %o0
 528         mov     %l1, %o1
 529         mov     %l2, %o2
 530         call    C_LABEL(handle_reg_access)
 531          mov    %l0, %o3
 532         RESTORE_ALL
 533 
 534         /* This routine handles Co-Processor Disabled Exceptions. */
 535         .align  4
 536         .globl  do_cp_disabled
 537 do_cp_disabled:
 538         SAVE_ALL
 539         wr      %l0, PSR_ET, %psr               ! re-enable traps
 540         WRITE_PAUSE
 541 
 542         add     %sp, STACKFRAME_SZ, %o0
 543         mov     %l1, %o1
 544         mov     %l2, %o2
 545         call    C_LABEL(handle_cp_disabled)
 546          mov    %l0, %o3
 547         RESTORE_ALL
 548 
 549         /* This routine handles Unimplemented FLUSH Exceptions. */
 550         .align  4
 551         .globl  do_bad_flush
 552 do_bad_flush:
 553         SAVE_ALL
 554         wr      %l0, PSR_ET, %psr               ! re-enable traps
 555         WRITE_PAUSE
 556 
 557         add     %sp, STACKFRAME_SZ, %o0
 558         mov     %l1, %o1
 559         mov     %l2, %o2
 560         call    C_LABEL(handle_bad_flush)
 561          mov    %l0, %o3
 562         RESTORE_ALL
 563 
 564         /* This routine handles Co-Processor Exceptions. */
 565         .align  4
 566         .globl  do_cp_exception
 567 do_cp_exception:
 568         SAVE_ALL
 569         wr      %l0, PSR_ET, %psr               ! re-enable traps
 570         WRITE_PAUSE
 571 
 572         add     %sp, STACKFRAME_SZ, %o0
 573         mov     %l1, %o1
 574         mov     %l2, %o2
 575         call    C_LABEL(handle_cp_exception)
 576          mov    %l0, %o3
 577         RESTORE_ALL
 578 
 579         /* This routine handles Hardware Divide By Zero Exceptions. */
 580         .align  4
 581         .globl  do_hw_divzero
 582 do_hw_divzero:
 583         SAVE_ALL
 584         wr      %l0, PSR_ET, %psr               ! re-enable traps
 585         WRITE_PAUSE
 586 
 587         add     %sp, STACKFRAME_SZ, %o0
 588         mov     %l1, %o1
 589         mov     %l2, %o2
 590         call    C_LABEL(handle_hw_divzero)
 591          mov    %l0, %o3
 592         RESTORE_ALL
 593 
 594         .align  4
 595         .globl  do_flush_windows
 596 do_flush_windows:
 597         SAVE_ALL
 598 
 599         wr      %l0, PSR_ET, %psr
 600         WRITE_PAUSE
 601 
 602         call    C_LABEL(flush_user_windows)
 603          nop
 604 
 605         /* Advance over the trap instruction. */
 606         ld      [%sp + STACKFRAME_SZ + PT_NPC], %l1
 607         add     %l1, 0x4, %l2
 608         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
 609         st      %l2, [%sp + STACKFRAME_SZ + PT_NPC]
 610 
 611         RESTORE_ALL
 612 
 613         /* The getcc software trap.  The user wants the condition codes from
 614          * the %psr in register %g1.
 615          */
 616 
 617         .align  4
 618         .globl  getcc_trap_handler
 619 getcc_trap_handler:
 620         srl     %l0, 20, %g1    ! give user
 621         and     %g1, 0xf, %g1   ! only ICC bits in %psr
 622         jmp     %l2             ! advance over trap instruction
 623         rett    %l2 + 0x4       ! like this...
 624 
 625         /* The setcc software trap.  The user has condition codes in %g1
 626          * that it would like placed in the %psr.  Be careful not to flip
 627          * any unintentional bits!
 628          */
 629 
 630         .align  4
 631         .globl  setcc_trap_handler
 632 setcc_trap_handler:
 633         sll     %g1, 0x14, %l4
 634         set     PSR_ICC, %l5
 635         andn    %l0, %l5, %l0   ! clear ICC bits in current %psr
 636         and     %l4, %l5, %l4   ! clear non-ICC bits in user value
 637         or      %l4, %l0, %l4   ! or them in... mix mix mix
 638         wr      %l4, 0x0, %psr  ! set new %psr
 639         WRITE_PAUSE             ! TI scumbags...
 640 
 641         jmp     %l2             ! advance over trap instruction
 642         rett    %l2 + 0x4       ! like this...
 643 
 644         .align  4
 645         .globl  linux_trap_nmi
 646 linux_trap_nmi:
 647         SAVE_ALL
 648         /* Ugh, we need to clear the IRQ line.  This is now
 649          * a very sun4c specific trap hanler...
 650          */
 651         sethi   %hi(C_LABEL(interrupt_enable)), %l5
 652         ld      [%l5 + %lo(C_LABEL(interrupt_enable))], %l5
 653         ldub    [%l5], %l6
 654         andn    %l6, INTS_ENAB, %l6
 655         stb     %l6, [%l5]
 656 
 657         /* Now it is safe to re-enable traps without recursion. */
 658         or      %l0, PSR_PIL, %l0
 659         wr      %l0, PSR_ET, %psr
 660         WRITE_PAUSE
 661 
 662         /* Now call the c-code with the pt_regs frame ptr and the
 663          * memory error registers as arguments.  The ordering chosen
 664          * here is due to unlatching semantics.
 665          */
 666         sethi   %hi(AC_SYNC_ERR), %o0
 667         add     %o0, 0x4, %o0
 668         lda     [%o0] ASI_CONTROL, %o2  ! sync vaddr
 669         sub     %o0, 0x4, %o0
 670         lda     [%o0] ASI_CONTROL, %o1  ! sync error
 671         add     %o0, 0xc, %o0
 672         lda     [%o0] ASI_CONTROL, %o4  ! async vaddr
 673         sub     %o0, 0x4, %o0
 674         lda     [%o0] ASI_CONTROL, %o3  ! async error
 675         call    C_LABEL(sparc_lvl15_nmi)
 676          add    %sp, STACKFRAME_SZ, %o0
 677 
 678         RESTORE_ALL
 679 
 680         .align  4
 681         .globl  sparc_fault
 682 sparc_fault:
 683         SAVE_ALL
 684         rd      %tbr, %o1
 685         wr      %l0, PSR_ET, %psr
 686         WRITE_PAUSE
 687 
 688         call    C_LABEL(do_sparc_fault)
 689          add    %sp, STACKFRAME_SZ, %o0
 690         RESTORE_ALL
 691 
 692         /* SunOS uses syscall zero as the 'indirect syscall' it looks
 693          * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
 694          * This is complete brain damage.
 695          */
 696         .globl  C_LABEL(sunos_indir)
 697 C_LABEL(sunos_indir):
 698         ld      [%sp + STACKFRAME_SZ + PT_I0], %g1
 699         cmp     %g1, NR_SYSCALLS
 700         bleu,a  1f
 701          sll    %g1, 0x2, %g1
 702 
 703         set     C_LABEL(sunos_nosys), %l6
 704         b       2f
 705          nop
 706 
 707 1:
 708         set     C_LABEL(sunos_sys_table), %l7
 709         ld      [%l7 + %g1], %l6
 710 
 711 2:      
 712         ld      [%sp + STACKFRAME_SZ + PT_I1], %o0
 713         ld      [%sp + STACKFRAME_SZ + PT_I2], %o1
 714         ld      [%sp + STACKFRAME_SZ + PT_I3], %o2
 715         ld      [%sp + STACKFRAME_SZ + PT_I4], %o3
 716         call    %l6
 717          ld     [%sp + STACKFRAME_SZ + PT_I5], %o4
 718 
 719         b       scall_store_args                /* so stupid... */
 720          nop
 721 
 722         .align  4
 723         .globl  C_LABEL(sys_execve)
 724 C_LABEL(sys_execve):
 725         call    C_LABEL(sparc_execve)
 726          add    %sp, STACKFRAME_SZ, %o0         ! pt_regs *regs arg
 727 
 728         b       scall_store_args
 729          nop
 730 
 731         .align  4
 732         .globl  C_LABEL(sys_pipe)
 733 C_LABEL(sys_pipe):
 734         call    C_LABEL(sparc_pipe)
 735          add    %sp, STACKFRAME_SZ, %o0         ! pt_regs *regs arg
 736 
 737         b       C_LABEL(ret_sys_call)
 738          nop
 739 
 740         .align  4
 741         .globl  C_LABEL(sys_sigreturn)
 742 C_LABEL(sys_sigreturn):
 743         call    C_LABEL(do_sigreturn)
 744          add    %sp, STACKFRAME_SZ, %o0
 745 
 746         /* We don't want to muck with user registers like a
 747          * normal syscall, just return.
 748          */
 749         RESTORE_ALL
 750 
 751         /* Now that we have a real sys_clone, sys_fork() is
 752          * implemented in terms of it.  Our _real_ implementation
 753          * of SunOS vfork() will use sys_clone() instead.
 754          */
 755         .align  4
 756         .globl  C_LABEL(sys_fork), C_LABEL(sys_vfork)
 757 C_LABEL(sys_vfork):
 758 C_LABEL(sys_fork):
 759         /* Save the kernel state as of now. */
 760         FLUSH_ALL_KERNEL_WINDOWS;
 761         STORE_WINDOW(sp)
 762         LOAD_CURRENT(g6)
 763         rd      %psr, %g4
 764         rd      %wim, %g5
 765         std     %g4, [%g6 + THREAD_KPSR]
 766         std     %sp, [%g6 + THREAD_KSP]
 767 
 768         mov     SIGCHLD, %o0                    ! arg0: clone flags
 769         mov     %fp, %o1                        ! arg1: usp
 770         call    C_LABEL(do_fork)
 771          add    %sp, STACKFRAME_SZ, %o2         ! arg2: pt_regs ptr
 772 
 773         b       scall_store_args
 774          nop
 775         
 776         /* Whee, kernel threads! */
 777         .globl  C_LABEL(sys_clone)
 778 C_LABEL(sys_clone):
 779         /* Save the kernel state as of now. */
 780         FLUSH_ALL_KERNEL_WINDOWS;
 781         STORE_WINDOW(sp)
 782         LOAD_CURRENT(g6)
 783         rd      %psr, %g4
 784         rd      %wim, %g5
 785         std     %g4, [%g6 + THREAD_KPSR]
 786         std     %sp, [%g6 + THREAD_KSP]
 787 
 788         ldd     [%sp + STACKFRAME_SZ + PT_I0], %o0      ! arg0,1: flags,usp
 789         cmp     %o1, 0x0                                ! Is new_usp NULL?
 790         be,a    1f
 791          mov    %fp, %o1                                ! yes, use current usp
 792 1:
 793         call    C_LABEL(do_fork)
 794          add    %sp, STACKFRAME_SZ, %o2                 ! arg2: pt_regs ptr
 795 
 796         b       scall_store_args
 797          nop
 798 
 799 #if 0 /* XXX Much later... XXX */
 800         /* Whee, vfork... */
 801         .globl  C_LABEL(sys_vfork)
 802 C_LABEL(sys_vfork):
 803         /* Save the kernel state as of now. */
 804         FLUSH_ALL_KERNEL_WINDOWS;
 805         STORE_WINDOW(sp)
 806         LOAD_CURRENT(g6)
 807         rd      %psr, %g4
 808         rd      %wim, %g5
 809         std     %g4, [%g6 + THREAD_KPSR]
 810         std     %sp, [%g6 + THREAD_KSP]
 811 
 812         set     (0x2100 | SIGCHLD), %o0                 ! CLONE_VFORK,CLONE_VM,SIGCHLD
 813         mov     %fp, %o1                                ! use current usp
 814 1:
 815         call    C_LABEL(do_fork)
 816          add    %sp, STACKFRAME_SZ, %o2                 ! arg2: pt_regs ptr
 817 
 818         b       scall_store_args
 819          nop
 820 #endif
 821 
 822         /* All system calls enter here... */
 823         .align  4
 824         .globl  linux_sparc_syscall
 825 linux_sparc_syscall:
 826         /* Don't dork with %l7, it holds the pointer to the
 827          * system call vector table.  SAVE_ALL does not
 828          * modify its value.
 829          */
 830         rd      %wim, %l3
 831         SAVE_ALL
 832 
 833         wr      %l0, PSR_ET, %psr       /* Turn on traps + interrupts */
 834         WRITE_PAUSE
 835 
 836 #if 0 /* Trace all system calls... */
 837         add     %sp, STACKFRAME_SZ, %o0
 838         call    C_LABEL(syscall_trace_entry)
 839          nop
 840 #endif
 841 
 842         /* SAVE_ALL may have blown away %g1, reload it. */
 843         ld      [%sp + STACKFRAME_SZ + PT_G1], %g1
 844         cmp     %g1, NR_SYSCALLS
 845         bleu,a  1f
 846          sll    %g1, 0x2, %g1
 847 
 848         set     C_LABEL(sys_ni_syscall), %l6
 849         b       2f
 850          nop
 851 
 852 1:
 853         /* Syscall table ptr is in %l7. */
 854         ld      [%l7 + %g1], %l6        ! load up ptr to syscall handler
 855 
 856         /* Pt_regs is your friend... Make the syscall... */
 857 2:
 858         ldd     [%sp + STACKFRAME_SZ + PT_I0], %o0
 859         ldd     [%sp + STACKFRAME_SZ + PT_I2], %o2
 860         ldd     [%sp + STACKFRAME_SZ + PT_I4], %o4
 861         call    %l6
 862          nop
 863 
 864 scall_store_args:
 865         st      %o0, [%sp + STACKFRAME_SZ + PT_I0]
 866 
 867         .globl  C_LABEL(ret_sys_call)
 868 C_LABEL(ret_sys_call):
 869         ld      [%sp + STACKFRAME_SZ + PT_I0], %o0
 870         set     PSR_C, %l6
 871         cmp     %o0, -ELIBSCN
 872         bgeu    1f
 873          ld     [%sp + STACKFRAME_SZ + PT_PSR], %l5
 874 
 875         /* System call success, clear Carry condition code. */          
 876         andn    %l5, %l6, %l5
 877         b       2f
 878          st     %l5, [%sp + STACKFRAME_SZ + PT_PSR]     
 879 
 880 1:
 881         /* System call failure, set Carry condition code.
 882          * Also, get abs(errno) to return to the process.
 883          */
 884         sub     %g0, %o0, %o0
 885         st      %o0, [%sp + STACKFRAME_SZ + PT_I0]
 886         or      %l5, %l6, %l5
 887         st      %l5, [%sp + STACKFRAME_SZ + PT_PSR]
 888 
 889         /* %i6 is our frame pointer, the restore done by the rett
 890          * instruction will automatically put us back on the users
 891          * stack.  Advance the pc and npc past the trap instruction.
 892          */
 893 2:
 894         ld      [%sp + STACKFRAME_SZ + PT_NPC], %l1     /* pc  = npc   */
 895         add     %l1, 0x4, %l2                           /* npc = npc+4 */
 896         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
 897         st      %l2, [%sp + STACKFRAME_SZ + PT_NPC]
 898 
 899 #if 0 /* Trace all system calls... */
 900         add     %sp, STACKFRAME_SZ, %o0
 901         call    C_LABEL(syscall_trace_exit)
 902          nop
 903 #endif
 904 
 905         RESTORE_ALL
 906 
 907         .globl  C_LABEL(flush_user_windows)
 908 C_LABEL(flush_user_windows):
 909         LOAD_CURRENT(g2)
 910         ld      [%g2 + THREAD_UMASK], %g1
 911         orcc    %g0, %g1, %g0
 912         be      3f
 913          clr    %g3
 914 1:
 915         _SV
 916         LOAD_CURRENT(g2)
 917         ld      [%g2 + THREAD_UMASK], %g1
 918         orcc    %g0, %g1, %g0
 919         bne     1b
 920          add    %g3, 1, %g3
 921 2:
 922         subcc   %g3, 1, %g3
 923         bne     2b
 924          _RS
 925 3:
 926         jmp     %o7 + 0x8
 927          nop
 928 
 929 /* End of entry.S */

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