root/arch/sparc/kernel/entry.S

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

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