root/arch/sparc/kernel/entry.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* $Id: entry.S,v 1.93 1996/04/25 06:08:32 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 #include <linux/errno.h>
   9 
  10 #include <asm/head.h>
  11 #include <asm/asi.h>
  12 #include <asm/smp.h>
  13 #include <asm/kgdb.h>
  14 #include <asm/contregs.h>
  15 #include <asm/ptrace.h>
  16 #include <asm/psr.h>
  17 #include <asm/cprefix.h>
  18 #include <asm/vaddrs.h>
  19 #include <asm/memreg.h>
  20 #include <asm/page.h>
  21 #include <asm/winmacro.h>
  22 #include <asm/signal.h>
  23 
  24 #include <asm/asmmacro.h>
  25 
  26 #define NR_SYSCALLS 255      /* Each OS is different... */
  27 
  28 /* First, KGDB low level things.  This is a rewrite
  29  * of the routines found in the sparc-stub.c asm() statement
  30  * from the gdb distribution.  This is also dual-purpose
  31  * as a software trap for userlevel programs.
  32  */
  33         .data
  34         .align  4
  35 
  36 in_trap_handler:
  37         .word   0
  38 
  39         .text
  40         .align  4
  41 
  42 ! This function is called when any SPARC trap (except window overflow or
  43 ! underflow) occurs.  It makes sure that the invalid register window is still
  44 ! available before jumping into C code.  It will also restore the world if you
  45 ! return from handle_exception.
  46 
  47         .globl  C_LABEL(trap_low)
  48 C_LABEL(trap_low):
  49         rd      %wim, %l3
  50         SAVE_ALL
  51         ENTER_SYSCALL
  52 
  53         sethi   %hi(in_trap_handler), %l4
  54         ld      [%lo(in_trap_handler) + %l4], %l5
  55         inc     %l5
  56         st      %l5, [%lo(in_trap_handler) + %l4]
  57 
  58         /* Make sure kgdb sees the same state we just saved. */
  59         LOAD_PT_GLOBALS(sp)
  60         LOAD_PT_INS(sp)
  61         ld      [%sp + REGWIN_SZ + PT_Y], %l4
  62         ld      [%sp + REGWIN_SZ + PT_WIM], %l3
  63         ld      [%sp + REGWIN_SZ + PT_PSR], %l0
  64         ld      [%sp + REGWIN_SZ + PT_PC], %l1
  65         ld      [%sp + REGWIN_SZ + PT_NPC], %l2
  66         rd      %tbr, %l5       /* Never changes... */
  67 
  68         /* Make kgdb exception frame. */        
  69         sub     %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
  70                                         ! + hidden arg + arg spill
  71                                         ! + doubleword alignment
  72                                         ! + registers[72] local var
  73         SAVE_KGDB_GLOBALS(sp)
  74         SAVE_KGDB_INS(sp)
  75         SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
  76 
  77         /* We are increasing PIL, so two writes. */
  78         or      %l0, PSR_PIL, %l0
  79         wr      %l0, 0, %psr
  80         wr      %l0, PSR_ET, %psr
  81         WRITE_PAUSE
  82 
  83         call    C_LABEL(handle_exception)
  84          add    %sp, REGWIN_SZ, %o0     ! Pass address of registers
  85 
  86         /* Load new kgdb register set. */
  87         LOAD_KGDB_GLOBALS(sp)
  88         LOAD_KGDB_INS(sp)
  89         LOAD_KGDB_SREGS(sp, l0, l2)
  90         wr      %l0, 0x0, %y
  91 
  92         sethi   %hi(in_trap_handler), %l4
  93         ld      [%lo(in_trap_handler) + %l4], %l5
  94         dec     %l5
  95         st      %l5, [%lo(in_trap_handler) + %l4]
  96 
  97         add     %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
  98 
  99         /* Now take what kgdb did and place it into the pt_regs
 100          * frame which SparcLinux RESTORE_ALL understands.,
 101          */
 102         STORE_PT_INS(sp)
 103         STORE_PT_GLOBALS(sp)
 104         STORE_PT_YREG(sp, g2)
 105         STORE_PT_PRIV(sp, l1, l2, l3)
 106 
 107         RESTORE_ALL
 108 
 109 
 110 #ifdef CONFIG_BLK_DEV_FD
 111 #ifdef TRACE_FLOPPY_HARDINT
 112 /* Useful tracing */
 113         .data
 114         .align  4
 115         .globl  C_LABEL(floppy_hardint_trace)
 116 C_LABEL(floppy_hardint_trace):
 117         .skip   32
 118         .globl  C_LABEL(floppy_hardint_index)
 119 C_LABEL(floppy_hardint_index):
 120         .word   0
 121 #endif
 122 
 123         .text
 124         .align  4
 125         .globl  C_LABEL(floppy_hardint)
 126 C_LABEL(floppy_hardint):
 127         /* Can only use regs %l3->%l7:
 128          * %l3 -- base address of fdc registers
 129          * %l4 -- pdma_vaddr
 130          * %l5 -- scratch for ld/st address
 131          * %l6 -- pdma_size
 132          * %l7 -- floppy_softint
 133          */
 134 
 135 #ifdef TRACE_FLOPPY_HARDINT
 136         sethi   %hi(C_LABEL(floppy_hardint_trace)), %l5
 137         or      %l5, %lo(C_LABEL(floppy_hardint_trace)), %l5
 138         ld      [%l5 + 32], %l7
 139         add     %l7, 1, %l7
 140         and     %l7, 31, %l7
 141         st      %l7, [%l5 + 32]
 142         sub     %l7, 1, %l7
 143         and     %l7, 31, %l7
 144         add     %l7, %l5, %l5
 145         or      %g0, 0xf, %l7
 146         stb     %l7, [%l5]
 147 #endif
 148 
 149         /* Do we have work to do? */
 150         sethi   %hi(C_LABEL(doing_pdma)), %l4
 151         ld      [%l4 + %lo(C_LABEL(doing_pdma))], %l4
 152         cmp     %l4, 0
 153         be      floppy_dosoftint
 154          nop
 155 
 156         /* Load fdc register base */
 157         sethi   %hi(C_LABEL(fdc_status)), %l3
 158         ld      [%l3 + %lo(C_LABEL(fdc_status))], %l3
 159 
 160         /* Setup register addresses */
 161         sethi   %hi(C_LABEL(pdma_vaddr)), %l5   ! transfer buffer
 162         ld      [%l5 + %lo(C_LABEL(pdma_vaddr))], %l4
 163         sethi   %hi(C_LABEL(pdma_size)), %l5    ! bytes to go
 164         ld      [%l5 + %lo(C_LABEL(pdma_size))], %l6
 165 next_byte:
 166 #ifdef TRACE_FLOPPY_HARDINT
 167         sethi   %hi(C_LABEL(floppy_hardint_trace)), %l5
 168         or      %l5, %lo(C_LABEL(floppy_hardint_trace)), %l5
 169         ld      [%l5 + 32], %l7
 170         add     %l7, 1, %l7
 171         and     %l7, 31, %l7
 172         st      %l7, [%l5 + 32]
 173         sub     %l7, 1, %l7
 174         and     %l7, 31, %l7
 175         add     %l7, %l5, %l5
 176         ldub    [%l3], %l7
 177         stb     %l7, [%l5]
 178 #else
 179         ldub    [%l3], %l7
 180 #endif
 181 
 182         andcc   %l7, 0x80, %g0          ! Does fifo still have data
 183         bz      floppy_fifo_emptied     ! fifo has been emptied...
 184          andcc  %l7, 0x20, %g0          ! in non-dma mode still?
 185         bz      floppy_overrun          ! nope, overrun
 186          andcc  %l7, 0x40, %g0          ! 0=write 1=read
 187         bz      floppy_write
 188          sub    %l6, 0x1, %l6
 189 
 190         /* Ok, actually read this byte */
 191         ldub    [%l3 + 1], %l7
 192         orcc    %g0, %l6, %g0
 193         stb     %l7, [%l4]
 194         bne     next_byte
 195          add    %l4, 0x1, %l4
 196 
 197         b       floppy_tdone
 198          nop
 199 
 200 floppy_write:
 201         /* Ok, actually write this byte */
 202         ldub    [%l4], %l7
 203         orcc    %g0, %l6, %g0
 204         stb     %l7, [%l3 + 1]
 205         bne     next_byte
 206          add    %l4, 0x1, %l4
 207 
 208         /* fall through... */
 209 floppy_tdone:
 210         sethi   %hi(C_LABEL(pdma_vaddr)), %l5
 211         st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
 212         sethi   %hi(C_LABEL(pdma_size)), %l5
 213         st      %l6, [%l5 + %lo(C_LABEL(pdma_size))]
 214         /* Flip terminal count pin */
 215         set     C_LABEL(auxio_register), %l4
 216         ld      [%l4], %l4
 217 
 218         set     C_LABEL(sparc_cpu_model), %l5
 219         ld      [%l5], %l5
 220         subcc   %l5, 1, %g0             /* enum { sun4c = 1 }; */
 221         be      1f
 222          ldub   [%l4], %l5
 223 
 224         or      %l5, 0xc2, %l5
 225         stb     %l5, [%l4]
 226         andn    %l5, 0x02, %l5
 227         b       2f
 228          nop
 229 
 230 1:
 231         or      %l5, 0xf4, %l5
 232         stb     %l5, [%l4]
 233         andn    %l5, 0x04, %l5
 234 
 235 2:
 236         /* Kill some time so the bits set */
 237         WRITE_PAUSE
 238         WRITE_PAUSE
 239 
 240         stb     %l5, [%l4]
 241 
 242         /* Prevent recursion */
 243         sethi   %hi(C_LABEL(doing_pdma)), %l4
 244         b       floppy_dosoftint
 245          st     %g0, [%l4 + %lo(C_LABEL(doing_pdma))]
 246 
 247         /* We emptied the FIFO, but we haven't read everything
 248          * as of yet.  Store the current transfer address and
 249          * bytes left to read so we can continue when the next
 250          * fast IRQ comes in.
 251          */
 252 floppy_fifo_emptied:
 253         sethi   %hi(C_LABEL(pdma_vaddr)), %l5
 254         st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
 255         sethi   %hi(C_LABEL(pdma_size)), %l7
 256         st      %l6, [%l7 + %lo(C_LABEL(pdma_size))]
 257 
 258         /* Restore condition codes */
 259         wr      %l0, 0x0, %psr
 260         WRITE_PAUSE
 261 
 262         jmp     %l1
 263         rett    %l2
 264 
 265 floppy_overrun:
 266         sethi   %hi(C_LABEL(pdma_vaddr)), %l5
 267         st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
 268         sethi   %hi(C_LABEL(pdma_size)), %l5
 269         st      %l6, [%l5 + %lo(C_LABEL(pdma_size))]
 270         /* Prevent recursion */
 271         sethi   %hi(C_LABEL(doing_pdma)), %l4
 272         st      %g0, [%l4 + %lo(C_LABEL(doing_pdma))]
 273 
 274         /* fall through... */
 275 floppy_dosoftint:
 276         rd      %wim, %l3
 277         SAVE_ALL
 278         ENTER_IRQ
 279 
 280         /* Set all IRQs off. */
 281         or      %l0, PSR_PIL, %l4
 282         wr      %l4, 0x0, %psr
 283         wr      %l4, PSR_ET, %psr
 284         WRITE_PAUSE
 285 
 286         mov     11, %o0                 ! floppy irq level
 287         call    C_LABEL(floppy_interrupt)
 288          add    %sp, REGWIN_SZ, %o1     ! struct pt_regs *regs
 289 
 290         LEAVE_IRQ
 291         RESTORE_ALL
 292         
 293 #endif /* (CONFIG_BLK_DEV_FD) */
 294 
 295         /* Bad trap handler */
 296         .globl  bad_trap_handler
 297 bad_trap_handler:
 298         SAVE_ALL
 299         ENTER_SYSCALL
 300 
 301         wr      %l0, PSR_ET, %psr
 302         WRITE_PAUSE
 303 
 304         mov     %l7, %o0                ! trap number
 305         mov     %l0, %o1                ! psr
 306         call    C_LABEL(do_hw_interrupt)
 307          mov    %l1, %o2                ! pc
 308 
 309         RESTORE_ALL
 310         
 311 /* For now all IRQ's not registered get sent here. handler_irq() will
 312  * see if a routine is registered to handle this interrupt and if not
 313  * it will say so on the console.
 314  */
 315 
 316         .align  4
 317         .globl  real_irq_entry
 318 real_irq_entry:
 319         SAVE_ALL
 320 #ifdef __SMP__
 321         cmp     %l7, 9
 322         bne     1f
 323          nop
 324 
 325         GET_PROCESSOR_MID(l4, l5)
 326         set     C_LABEL(sun4m_interrupts), %l5
 327         ld      [%l5], %l5
 328         sethi   %hi(0x02000000), %l6
 329         sll     %l4, 12, %l4
 330         add     %l5, %l4, %l5
 331         ld      [%l5], %l4
 332         andcc   %l4, %l6, %g0
 333         be      1f
 334          nop
 335 
 336         b       linux_trap_ipi9_sun4m
 337          nop
 338 
 339 1:
 340 #endif
 341         ENTER_IRQ
 342 
 343 #ifdef __SMP__
 344         cmp     %l7, 13
 345         bne     1f
 346          nop
 347 
 348         /* This is where we catch the level 13 reschedule soft-IRQ. */
 349         GET_PROCESSOR_MID(o3, o2)
 350         set     C_LABEL(sun4m_interrupts), %l5
 351         ld      [%l5], %o5
 352         sethi   %hi(0x20000000), %o4
 353         sll     %o3, 12, %o3
 354         add     %o5, %o3, %o5
 355         ld      [%o5], %o1              ! read processor irq pending reg
 356         andcc   %o1, %o4, %g0
 357         be      1f
 358          nop
 359 
 360         b       linux_trap_ipi13_sun4m
 361          nop
 362 
 363 1:      
 364 
 365 #endif
 366 
 367         /* start atomic operation with respect to software interrupts */
 368         sethi   %hi(C_LABEL(intr_count)), %l4
 369         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 370         add     %l5, 0x1, %l5
 371         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 372 
 373         /* Enable traps w/IRQs off, so we can call c-code properly.
 374          * Note how we are increasing PIL so we need to do two writes
 375          * to work around a MicroSPARC bug of sorts.
 376          */
 377         or      %l0, PSR_PIL, %l4
 378 
 379         wr      %l4, 0x0, %psr
 380         WRITE_PAUSE
 381         wr      %l4, PSR_ET, %psr
 382         WRITE_PAUSE
 383 
 384         mov     %l7, %o0                ! irq level
 385         call    C_LABEL(handler_irq)
 386          add    %sp, REGWIN_SZ, %o1     ! pt_regs ptr
 387 
 388 rie_checkbh:
 389         sethi   %hi(C_LABEL(intr_count)), %l4
 390         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 391         subcc   %l5, 0x1, %l5
 392         bne     2f      /* IRQ within IRQ, get out of here... */
 393          nop
 394 
 395         sethi   %hi(C_LABEL(bh_active)), %l3
 396         ld      [%l3 + %lo(C_LABEL(bh_active))], %g2
 397         sethi   %hi(C_LABEL(bh_mask)), %l3
 398         ld      [%l3 + %lo(C_LABEL(bh_mask))], %g3
 399         andcc   %g2, %g3, %g0
 400         be      2f
 401          nop
 402 
 403         call    C_LABEL(do_bottom_half) 
 404          nop
 405 
 406         /* Try again... */
 407         b       rie_checkbh
 408          nop
 409         
 410 2:
 411         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 412 
 413         LEAVE_IRQ
 414         RESTORE_ALL
 415 
 416         /* This routine handles illegal instructions and privileged
 417          * instruction attempts from user code.
 418          */
 419         .align  4
 420         .globl  bad_instruction
 421 bad_instruction:
 422         SAVE_ALL
 423         ENTER_SYSCALL
 424 
 425         wr      %l0, PSR_ET, %psr               ! re-enable traps
 426         WRITE_PAUSE
 427 
 428         add     %sp, REGWIN_SZ, %o0
 429         mov     %l1, %o1
 430         mov     %l2, %o2
 431         call    C_LABEL(do_illegal_instruction)
 432          mov    %l0, %o3
 433 
 434         RESTORE_ALL
 435 
 436         .align  4
 437         .globl  priv_instruction
 438 priv_instruction:
 439         SAVE_ALL
 440         ENTER_SYSCALL
 441 
 442         wr      %l0, PSR_ET, %psr
 443         WRITE_PAUSE
 444 
 445         add     %sp, REGWIN_SZ, %o0
 446         mov     %l1, %o1
 447         mov     %l2, %o2
 448         call    C_LABEL(do_priv_instruction)
 449          mov    %l0, %o3
 450 
 451         RESTORE_ALL
 452 
 453         /* This routine handles unaligned data accesses.
 454          */
 455         .align  4
 456         .globl  mna_handler
 457 mna_handler:
 458         SAVE_ALL
 459         ENTER_SYSCALL
 460 
 461         wr      %l0, PSR_ET, %psr               ! re-enable traps
 462         WRITE_PAUSE
 463 
 464         add     %sp, REGWIN_SZ, %o0
 465         mov     %l1, %o1
 466         mov     %l2, %o2
 467         call    C_LABEL(do_memaccess_unaligned)
 468          mov    %l0, %o3
 469 
 470         RESTORE_ALL
 471 
 472         /* This routine handles floating point disabled traps. */
 473         .align  4
 474         .globl  fpd_trap_handler
 475 fpd_trap_handler:
 476         SAVE_ALL
 477         ENTER_SYSCALL
 478 
 479         wr      %l0, PSR_ET, %psr               ! re-enable traps
 480         WRITE_PAUSE
 481 
 482         add     %sp, REGWIN_SZ, %o0
 483         mov     %l1, %o1
 484         mov     %l2, %o2
 485         call    C_LABEL(do_fpd_trap)
 486          mov    %l0, %o3
 487 
 488         RESTORE_ALL
 489 
 490         /* This routine handles Floating Point Exceptions. */
 491         .align  4
 492         .globl  fpe_trap_handler
 493 fpe_trap_handler:
 494         set     fpsave_magic, %l5
 495         cmp     %l1, %l5
 496         be      1f
 497          sethi  %hi(C_LABEL(fpsave)), %l5
 498         or      %l5, %lo(C_LABEL(fpsave)), %l5
 499         cmp     %l1, %l5
 500         bne     2f
 501          sethi  %hi(fpsave_catch2), %l5
 502         or      %l5, %lo(fpsave_catch2), %l5
 503         wr      %l0, 0x0, %psr
 504         WRITE_PAUSE
 505         jmp     %l5
 506          rett   %l5 + 4
 507 1:      
 508         sethi   %hi(fpsave_catch), %l5
 509         or      %l5, %lo(fpsave_catch), %l5
 510         wr      %l0, 0x0, %psr
 511         WRITE_PAUSE
 512         jmp     %l5
 513          rett   %l5 + 4
 514 
 515 2:
 516         SAVE_ALL
 517         ENTER_SYSCALL
 518 
 519         wr      %l0, PSR_ET, %psr               ! re-enable traps
 520         WRITE_PAUSE
 521 
 522         add     %sp, REGWIN_SZ, %o0
 523         mov     %l1, %o1
 524         mov     %l2, %o2
 525         call    C_LABEL(do_fpe_trap)
 526          mov    %l0, %o3
 527 
 528         RESTORE_ALL
 529 
 530         /* This routine handles Tag Overflow Exceptions. */
 531         .align  4
 532         .globl  do_tag_overflow
 533 do_tag_overflow:
 534         SAVE_ALL
 535         ENTER_SYSCALL
 536 
 537         wr      %l0, PSR_ET, %psr               ! re-enable traps
 538         WRITE_PAUSE
 539 
 540         add     %sp, REGWIN_SZ, %o0
 541         mov     %l1, %o1
 542         mov     %l2, %o2
 543         call    C_LABEL(handle_tag_overflow)
 544          mov    %l0, %o3
 545 
 546         RESTORE_ALL
 547 
 548         /* This routine handles Watchpoint Exceptions. */
 549         .align  4
 550         .globl  do_watchpoint
 551 do_watchpoint:
 552         SAVE_ALL
 553         ENTER_SYSCALL
 554 
 555         wr      %l0, PSR_ET, %psr               ! re-enable traps
 556         WRITE_PAUSE
 557 
 558         add     %sp, REGWIN_SZ, %o0
 559         mov     %l1, %o1
 560         mov     %l2, %o2
 561         call    C_LABEL(handle_watchpoint)
 562          mov    %l0, %o3
 563 
 564         RESTORE_ALL
 565 
 566         /* This routine handles Register Access Exceptions. */
 567         .align  4
 568         .globl  do_reg_access
 569 do_reg_access:
 570         SAVE_ALL
 571         ENTER_SYSCALL
 572 
 573         wr      %l0, PSR_ET, %psr               ! re-enable traps
 574         WRITE_PAUSE
 575 
 576         add     %sp, REGWIN_SZ, %o0
 577         mov     %l1, %o1
 578         mov     %l2, %o2
 579         call    C_LABEL(handle_reg_access)
 580          mov    %l0, %o3
 581 
 582         RESTORE_ALL
 583 
 584         /* This routine handles Co-Processor Disabled Exceptions. */
 585         .align  4
 586         .globl  do_cp_disabled
 587 do_cp_disabled:
 588         SAVE_ALL
 589         ENTER_SYSCALL
 590 
 591         wr      %l0, PSR_ET, %psr               ! re-enable traps
 592         WRITE_PAUSE
 593 
 594         add     %sp, REGWIN_SZ, %o0
 595         mov     %l1, %o1
 596         mov     %l2, %o2
 597         call    C_LABEL(handle_cp_disabled)
 598          mov    %l0, %o3
 599 
 600         RESTORE_ALL
 601 
 602         /* This routine handles Unimplemented FLUSH Exceptions. */
 603         .align  4
 604         .globl  do_bad_flush
 605 do_bad_flush:
 606         SAVE_ALL
 607         ENTER_SYSCALL
 608 
 609         wr      %l0, PSR_ET, %psr               ! re-enable traps
 610         WRITE_PAUSE
 611 
 612         add     %sp, REGWIN_SZ, %o0
 613         mov     %l1, %o1
 614         mov     %l2, %o2
 615         call    C_LABEL(handle_bad_flush)
 616          mov    %l0, %o3
 617 
 618         RESTORE_ALL
 619 
 620         /* This routine handles Co-Processor Exceptions. */
 621         .align  4
 622         .globl  do_cp_exception
 623 do_cp_exception:
 624         SAVE_ALL
 625         ENTER_SYSCALL
 626 
 627         wr      %l0, PSR_ET, %psr               ! re-enable traps
 628         WRITE_PAUSE
 629 
 630         add     %sp, REGWIN_SZ, %o0
 631         mov     %l1, %o1
 632         mov     %l2, %o2
 633         call    C_LABEL(handle_cp_exception)
 634          mov    %l0, %o3
 635 
 636         RESTORE_ALL
 637 
 638         /* This routine handles Hardware Divide By Zero Exceptions. */
 639         .align  4
 640         .globl  do_hw_divzero
 641 do_hw_divzero:
 642         SAVE_ALL
 643         ENTER_SYSCALL
 644 
 645         wr      %l0, PSR_ET, %psr               ! re-enable traps
 646         WRITE_PAUSE
 647 
 648         add     %sp, REGWIN_SZ, %o0
 649         mov     %l1, %o1
 650         mov     %l2, %o2
 651         call    C_LABEL(handle_hw_divzero)
 652          mov    %l0, %o3
 653 
 654         RESTORE_ALL
 655 
 656         .align  4
 657         .globl  do_flush_windows
 658 do_flush_windows:
 659         SAVE_ALL
 660         ENTER_SYSCALL
 661 
 662         wr      %l0, PSR_ET, %psr
 663         WRITE_PAUSE
 664 
 665         andcc   %l0, PSR_PS, %g0
 666         bne     dfw_kernel
 667          nop
 668 
 669         call    C_LABEL(flush_user_windows)
 670          nop
 671 
 672         /* Advance over the trap instruction. */
 673         ld      [%sp + REGWIN_SZ + PT_NPC], %l1
 674         add     %l1, 0x4, %l2
 675         st      %l1, [%sp + REGWIN_SZ + PT_PC]
 676         st      %l2, [%sp + REGWIN_SZ + PT_NPC]
 677 
 678         RESTORE_ALL
 679 
 680         /* We get these for debugging routines using __builtin_return_address() */
 681 dfw_kernel:
 682         FLUSH_ALL_KERNEL_WINDOWS
 683 
 684         /* Advance over the trap instruction. */
 685         ld      [%sp + REGWIN_SZ + PT_NPC], %l1
 686         add     %l1, 0x4, %l2
 687         st      %l1, [%sp + REGWIN_SZ + PT_PC]
 688         st      %l2, [%sp + REGWIN_SZ + PT_NPC]
 689 
 690         RESTORE_ALL
 691 
 692         /* The getcc software trap.  The user wants the condition codes from
 693          * the %psr in register %g1.
 694          */
 695 
 696         .align  4
 697         .globl  getcc_trap_handler
 698 getcc_trap_handler:
 699         srl     %l0, 20, %g1    ! give user
 700         and     %g1, 0xf, %g1   ! only ICC bits in %psr
 701         jmp     %l2             ! advance over trap instruction
 702         rett    %l2 + 0x4       ! like this...
 703 
 704         /* The setcc software trap.  The user has condition codes in %g1
 705          * that it would like placed in the %psr.  Be careful not to flip
 706          * any unintentional bits!
 707          */
 708 
 709         .align  4
 710         .globl  setcc_trap_handler
 711 setcc_trap_handler:
 712         sll     %g1, 0x14, %l4
 713         set     PSR_ICC, %l5
 714         andn    %l0, %l5, %l0   ! clear ICC bits in current %psr
 715         and     %l4, %l5, %l4   ! clear non-ICC bits in user value
 716         or      %l4, %l0, %l4   ! or them in... mix mix mix
 717 
 718         wr      %l4, 0x0, %psr  ! set new %psr
 719         WRITE_PAUSE             ! TI scumbags...
 720 
 721         jmp     %l2             ! advance over trap instruction
 722         rett    %l2 + 0x4       ! like this...
 723 
 724         .align  4
 725         .globl  linux_trap_nmi_sun4c
 726 linux_trap_nmi_sun4c:
 727         SAVE_ALL
 728         ENTER_SYSCALL
 729 
 730         /* Ugh, we need to clear the IRQ line.  This is now
 731          * a very sun4c specific trap handler...
 732          */
 733         sethi   %hi(C_LABEL(interrupt_enable)), %l5
 734         ld      [%l5 + %lo(C_LABEL(interrupt_enable))], %l5
 735         ldub    [%l5], %l6
 736         andn    %l6, INTS_ENAB, %l6
 737         stb     %l6, [%l5]
 738 
 739         /* Now it is safe to re-enable traps without recursion. */
 740         or      %l0, PSR_PIL, %l0
 741         wr      %l0, PSR_ET, %psr
 742         WRITE_PAUSE
 743 
 744         /* Now call the c-code with the pt_regs frame ptr and the
 745          * memory error registers as arguments.  The ordering chosen
 746          * here is due to unlatching semantics.
 747          */
 748         sethi   %hi(AC_SYNC_ERR), %o0
 749         add     %o0, 0x4, %o0
 750         lda     [%o0] ASI_CONTROL, %o2  ! sync vaddr
 751         sub     %o0, 0x4, %o0
 752         lda     [%o0] ASI_CONTROL, %o1  ! sync error
 753         add     %o0, 0xc, %o0
 754         lda     [%o0] ASI_CONTROL, %o4  ! async vaddr
 755         sub     %o0, 0x4, %o0
 756         lda     [%o0] ASI_CONTROL, %o3  ! async error
 757         call    C_LABEL(sparc_lvl15_nmi)
 758          add    %sp, REGWIN_SZ, %o0
 759 
 760         RESTORE_ALL
 761 
 762 #ifdef __SMP__
 763 
 764         .align  4
 765         .globl  linux_trap_ipi9_sun4m
 766 linux_trap_ipi9_sun4m:
 767         sethi   %hi(0x02000000), %o2
 768         GET_PROCESSOR_MID(o0, o1)
 769         set     C_LABEL(sun4m_interrupts), %l5
 770         ld      [%l5], %o5
 771         sll     %o0, 12, %o0
 772         add     %o5, %o0, %o5
 773         st      %o2, [%o5 + 4]
 774         WRITE_PAUSE
 775 
 776         ld      [%o5], %g0
 777         WRITE_PAUSE
 778 
 779         /* IRQ's off else we deadlock. */
 780         or      %l0, PSR_PIL, %l4
 781         wr      %l4, 0x0, %psr
 782         WRITE_PAUSE
 783 
 784         wr      %l4, PSR_ET, %psr
 785         WRITE_PAUSE
 786 
 787         call    C_LABEL(smp_message_irq)
 788          nop
 789 
 790         RESTORE_ALL_FASTIRQ
 791 
 792         .align  4
 793         .globl  linux_trap_ipi13_sun4m
 794 linux_trap_ipi13_sun4m:
 795         /* NOTE: real_irq_entry saved state and grabbed klock already. */
 796 
 797         /* start atomic operation with respect to software interrupts */
 798         sethi   %hi(C_LABEL(intr_count)), %l4
 799         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 800         add     %l5, 0x1, %l5
 801         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 802 
 803         sethi   %hi(0x20000000), %o2
 804         GET_PROCESSOR_MID(o0, o1)
 805         set     C_LABEL(sun4m_interrupts), %l5
 806         ld      [%l5], %o5
 807         sll     %o0, 12, %o0
 808         add     %o5, %o0, %o5
 809         st      %o2, [%o5 + 4]
 810         WRITE_PAUSE
 811 
 812         ld      [%o5], %g0
 813         WRITE_PAUSE
 814 
 815         /* IRQ's off else we deadlock. */
 816         or      %l0, PSR_PIL, %l4
 817         wr      %l4, 0x0, %psr
 818         WRITE_PAUSE
 819 
 820         wr      %l4, PSR_ET, %psr
 821         WRITE_PAUSE
 822 
 823         call    C_LABEL(smp_reschedule_irq)
 824          nop
 825 
 826         sethi   %hi(C_LABEL(intr_count)), %l4
 827         ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
 828         sub     %l5, 0x1, %l5
 829         st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
 830 
 831         LEAVE_IRQ
 832         RESTORE_ALL
 833 
 834         .align  4
 835         .globl  linux_trap_ipi15_sun4m
 836 linux_trap_ipi15_sun4m:
 837         SAVE_ALL
 838 
 839         /* First check for hard NMI memory error. */
 840         sethi   %hi(0xf0000000), %o2
 841         set     C_LABEL(sun4m_interrupts), %l5
 842         set     0x4000, %o3
 843         ld      [%l5], %l5
 844         add     %l5, %o3, %l5
 845         ld      [%l5], %l6
 846         andcc   %o2, %l6, %o2
 847         be      1f
 848          nop
 849 
 850         /* Asynchronous fault, why you little ?!#&%@... */
 851         sethi   %hi(0x80000000), %o2
 852         st      %o2, [%l5 + 0xc]
 853         WRITE_PAUSE
 854         ld      [%l5], %g0
 855         WRITE_PAUSE
 856 
 857         /* All interrupts are off... now safe to enable traps
 858          * and call C-code.
 859          */     
 860         or      %l0, PSR_PIL, %l4       ! I am very paranoid...
 861         wr      %l4, 0x0, %psr
 862         WRITE_PAUSE
 863         wr      %l4, PSR_ET, %psr
 864         WRITE_PAUSE
 865         call    C_LABEL(sun4m_nmi)
 866          nop
 867 
 868         sethi   %hi(0x80000000), %o2
 869         st      %o2, [%l5 + 0x8]
 870         WRITE_PAUSE
 871         ld      [%l5], %g0
 872         WRITE_PAUSE
 873 
 874         RESTORE_ALL_FASTIRQ
 875 
 876 1:
 877         sethi   %hi(0x80000000), %o2
 878         GET_PROCESSOR_MID(o0, o1)
 879         set     C_LABEL(sun4m_interrupts), %l5
 880         ld      [%l5], %o5
 881         sll     %o0, 12, %o0
 882         add     %o5, %o0, %o5
 883         st      %o2, [%o5 + 4]
 884         WRITE_PAUSE
 885 
 886         ld      [%o5], %g0
 887         WRITE_PAUSE
 888 
 889         /* IRQ's off else we deadlock. */
 890         or      %l0, PSR_PIL, %l4
 891         wr      %l4, 0x0, %psr
 892         WRITE_PAUSE
 893 
 894         wr      %l4, PSR_ET, %psr
 895         WRITE_PAUSE
 896 
 897         call    C_LABEL(smp_message_irq)
 898          nop
 899 
 900         RESTORE_ALL_FASTIRQ
 901 
 902 #endif
 903 
 904         .align  4
 905         .globl  sun4c_fault
 906 sun4c_fault:
 907         SAVE_ALL
 908         ENTER_SYSCALL
 909 
 910         /* XXX This needs to be scheduled better */
 911         sethi   %hi(AC_SYNC_ERR), %l4
 912         add     %l4, 0x4, %l5           ! AC_SYNC_VA in %l5
 913         lda     [%l5] ASI_CONTROL, %o3          /* Address */
 914         lda     [%l4] ASI_CONTROL, %l6
 915         srl     %l6, 15, %l6
 916         and     %l6, 1, %o2     /* Write? */
 917 
 918         wr      %l0, PSR_ET, %psr
 919         WRITE_PAUSE
 920 
 921         mov     %l7, %o1                        /* Text fault? */
 922         call    C_LABEL(do_sparc_fault)
 923          add    %sp, REGWIN_SZ, %o0             /* pt_regs */
 924 
 925         RESTORE_ALL
 926 
 927         .align  4
 928         .globl  C_LABEL(srmmu_fault)
 929 C_LABEL(srmmu_fault):
 930         mov     0x400, %l5
 931         mov     0x300, %l4
 932 
 933         lda     [%l5] ASI_M_MMUREGS, %l6        ! read sfar first
 934         lda     [%l4] ASI_M_MMUREGS, %l5        ! read sfsr last
 935 
 936         andn    %l6, 0xfff, %l6
 937         srl     %l5, 6, %l5                     ! and encode all info into l7
 938 
 939         and     %l5, 2, %l5
 940         or      %l5, %l6, %l6
 941 
 942         or      %l6, %l7, %l7                   ! l7 = [addr,write,txtfault]
 943 
 944         SAVE_ALL
 945         ENTER_SYSCALL
 946 
 947         mov     %l7, %o1
 948         mov     %l7, %o2
 949         and     %o1, 1, %o1             ! arg2 = text_faultp
 950         mov     %l7, %o3
 951         and     %o2, 2, %o2             ! arg3 = writep
 952         andn    %o3, 0xfff, %o3         ! arg4 = faulting address
 953 
 954         wr      %l0, PSR_ET, %psr
 955         WRITE_PAUSE
 956 
 957         call    C_LABEL(do_sparc_fault)
 958          add    %sp, REGWIN_SZ, %o0     ! arg1 = pt_regs ptr
 959 
 960         RESTORE_ALL
 961 
 962         /* SunOS uses syscall zero as the 'indirect syscall' it looks
 963          * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
 964          * This is complete brain damage.
 965          */
 966         .globl  C_LABEL(sunos_indir)
 967 C_LABEL(sunos_indir):
 968         ld      [%sp + REGWIN_SZ + PT_I0], %g1
 969         cmp     %g1, NR_SYSCALLS
 970         blu,a   1f
 971          sll    %g1, 0x2, %g1
 972 
 973         set     C_LABEL(sunos_nosys), %l6
 974         b       2f
 975          nop
 976 
 977 1:
 978         set     C_LABEL(sunos_sys_table), %l7
 979         ld      [%l7 + %g1], %l6
 980 
 981 2:      
 982         ld      [%sp + REGWIN_SZ + PT_I1], %o0
 983         ld      [%sp + REGWIN_SZ + PT_I2], %o1
 984         ld      [%sp + REGWIN_SZ + PT_I3], %o2
 985         mov     %o7, %l5
 986         ld      [%sp + REGWIN_SZ + PT_I4], %o3
 987         call    %l6
 988          ld     [%sp + REGWIN_SZ + PT_I5], %o4
 989 
 990         jmp     %l5 + 0x8               /* so stupid... */
 991          nop
 992 
 993         /* Note how we really return to ret_syscall because we share the
 994          * register window with our caller.
 995          */
 996 
 997         .align 4
 998         .globl  C_LABEL(sys_ptrace)
 999 C_LABEL(sys_ptrace):
1000         call    C_LABEL(do_ptrace)
1001          add    %sp, REGWIN_SZ, %o0
1002 
1003         LOAD_CURRENT(l4, l5)
1004         ld      [%l4 + 0x14], %l5
1005         andcc   %l5, 0x20, %g0
1006         be      1f
1007          nop
1008 
1009         call    C_LABEL(syscall_trace)
1010          nop
1011 
1012 1:
1013         RESTORE_ALL
1014 
1015         .align  4
1016         .globl  C_LABEL(sys_execve)
1017 C_LABEL(sys_execve):
1018         mov     %o7, %l5
1019         call    C_LABEL(sparc_execve)
1020          add    %sp, REGWIN_SZ, %o0             ! pt_regs *regs arg
1021 
1022         jmp     %l5 + 0x8
1023          nop
1024 
1025         .align  4
1026         .globl  C_LABEL(sys_pipe)
1027 C_LABEL(sys_pipe):
1028         mov     %o7, %l5
1029 
1030         call    C_LABEL(sparc_pipe)
1031          add    %sp, REGWIN_SZ, %o0             ! pt_regs *regs arg
1032 
1033         jmp     %l5 + 0x8
1034          nop
1035 
1036         .align  4
1037         .globl  C_LABEL(sys_sigpause)
1038 C_LABEL(sys_sigpause):
1039         ld      [%sp + REGWIN_SZ + PT_I0], %o0
1040         call    C_LABEL(do_sigpause)
1041          add    %sp, REGWIN_SZ, %o1
1042 
1043         LOAD_CURRENT(l4, l5)
1044         ld      [%l4 + 0x14], %l5
1045         andcc   %l5, 0x20, %g0
1046         be      1f
1047          nop
1048 
1049         call    C_LABEL(syscall_trace)
1050          nop
1051 
1052 1:
1053         /* We are returning to a signal handler. */
1054         RESTORE_ALL
1055 
1056         .align  4
1057         .globl  C_LABEL(sys_sigsuspend)
1058 C_LABEL(sys_sigsuspend):
1059         call    C_LABEL(do_sigsuspend)
1060          add    %sp, REGWIN_SZ, %o0
1061 
1062         LOAD_CURRENT(l4, l5)
1063         ld      [%l4 + 0x14], %l5
1064         andcc   %l5, 0x20, %g0
1065         be      1f
1066          nop
1067 
1068         call    C_LABEL(syscall_trace)
1069          nop
1070 
1071 1:
1072         /* We are returning to a signal handler. */
1073         RESTORE_ALL
1074 
1075         .align  4
1076         .globl  C_LABEL(sys_sigreturn)
1077 C_LABEL(sys_sigreturn):
1078         call    C_LABEL(do_sigreturn)
1079          add    %sp, REGWIN_SZ, %o0
1080 
1081         LOAD_CURRENT(l4, l5)
1082         ld      [%l4 + 0x14], %l5
1083         andcc   %l5, 0x20, %g0
1084         be      1f
1085          nop
1086 
1087         call    C_LABEL(syscall_trace)
1088          nop
1089 
1090 1:
1091         /* We don't want to muck with user registers like a
1092          * normal syscall, just return.
1093          */
1094         RESTORE_ALL
1095 
1096         /* Now that we have a real sys_clone, sys_fork() is
1097          * implemented in terms of it.  Our _real_ implementation
1098          * of SunOS vfork() will use sys_clone() instead.
1099          */
1100         .align  4
1101         .globl  C_LABEL(sys_fork), C_LABEL(sys_vfork)
1102 C_LABEL(sys_vfork):
1103 C_LABEL(sys_fork):
1104         mov     %o7, %l5
1105 
1106         /* Save the kernel state as of now. */
1107         FLUSH_ALL_KERNEL_WINDOWS;
1108         STORE_WINDOW(sp)
1109         LOAD_CURRENT(g6, g5)
1110         rd      %psr, %g4
1111         rd      %wim, %g5
1112         std     %g4, [%g6 + THREAD_FORK_KPSR]
1113 
1114         mov     SIGCHLD, %o0                    ! arg0: clone flags
1115         ld      [%sp + REGWIN_SZ + PT_FP], %o1  ! arg1: usp
1116         call    C_LABEL(do_fork)
1117          add    %sp, REGWIN_SZ, %o2             ! arg2: pt_regs ptr
1118 
1119         jmp     %l5 + 0x8
1120          nop
1121         
1122         /* Whee, kernel threads! */
1123         .globl  C_LABEL(sys_clone)
1124 C_LABEL(sys_clone):
1125         mov     %o7, %l5
1126 
1127         /* Save the kernel state as of now. */
1128         FLUSH_ALL_KERNEL_WINDOWS;
1129         STORE_WINDOW(sp)
1130         LOAD_CURRENT(g6, g5)
1131         rd      %psr, %g4
1132         rd      %wim, %g5
1133         std     %g4, [%g6 + THREAD_FORK_KPSR]
1134 
1135         ldd     [%sp + REGWIN_SZ + PT_I0], %o0  ! arg0,1: flags,usp
1136         cmp     %o1, 0x0                        ! Is new_usp NULL?
1137         be,a    1f
1138          ld     [%sp + REGWIN_SZ + PT_FP], %o1  ! yes, use current usp
1139 1:
1140         call    C_LABEL(do_fork)
1141          add    %sp, REGWIN_SZ, %o2             ! arg2: pt_regs ptr
1142 
1143         jmp     %l5 + 0x8
1144          nop
1145 
1146         /* Linux native and SunOS system calls enter here... */
1147         .align  4
1148         .globl  linux_sparc_syscall
1149 linux_sparc_syscall:
1150         /* While we are here trying to optimize our lives
1151          * away, handle the easy bogus cases like a
1152          * ni_syscall or sysnum > NR_SYSCALLS etc.
1153          * In the cases where we cannot optimize the
1154          * call inline we don't really lose anything
1155          * performance wise because we are doing here
1156          * things which we did anyway in the original
1157          * routine.  The only added complexity is a
1158          * bit test, compare, and branch to decide
1159          * if we need to save process state or not.
1160          */
1161 
1162         /* XXX TODO: When we have ptrace working test
1163          * XXX       test for PF_TRACESYS in task flags.
1164          */
1165 
1166         /* Direct access to user regs, must faster. */
1167         cmp     %g1, NR_SYSCALLS
1168         blu,a   1f
1169          sll    %g1, 2, %l4
1170 
1171         set     C_LABEL(sys_ni_syscall), %l7
1172         b       syscall_is_too_hard
1173          nop
1174 
1175 1:
1176         ld      [%l7 + %l4], %l7
1177 
1178         /* If bit-1 is set, this is a "fast" syscall.
1179          * This is the _complete_ overhead of this optimization,
1180          * and we save ourselves a load, so it evens out to nothing.
1181          */
1182         andcc   %l7, 0x1, %g0
1183         be      syscall_is_too_hard
1184          andn   %l7, 0x1, %l7
1185 
1186         jmpl    %l7, %g0
1187          nop
1188 
1189         .globl  syscall_is_too_hard
1190 syscall_is_too_hard:
1191         rd      %wim, %l3
1192         SAVE_ALL
1193         ENTER_SYSCALL
1194 
1195         wr      %l0, PSR_ET, %psr
1196         WRITE_PAUSE
1197 
1198         LOAD_CURRENT(l4, l5)
1199         ld      [%l4 + 0x14], %l5
1200         andcc   %l5, 0x20, %g0
1201         be      2f
1202          nop
1203 
1204         call    C_LABEL(syscall_trace)
1205          nop
1206 
1207 2:
1208         ldd     [%sp + REGWIN_SZ + PT_I0], %o0
1209         st      %o0, [%sp + REGWIN_SZ + PT_G0]  ! for restarting syscalls
1210         ldd     [%sp + REGWIN_SZ + PT_I2], %o2
1211         call    %l7
1212          ldd    [%sp + REGWIN_SZ + PT_I4], %o4
1213 
1214         st      %o0, [%sp + REGWIN_SZ + PT_I0]
1215 
1216         .globl  C_LABEL(ret_sys_call)
1217 C_LABEL(ret_sys_call):
1218         ld      [%sp + REGWIN_SZ + PT_I0], %o0
1219         set     PSR_C, %l6
1220         cmp     %o0, -ENOIOCTLCMD
1221         bgeu    1f
1222          ld     [%sp + REGWIN_SZ + PT_PSR], %l5
1223 
1224         /* System call success, clear Carry condition code. */          
1225         andn    %l5, %l6, %l5
1226         b       2f
1227          st     %l5, [%sp + REGWIN_SZ + PT_PSR] 
1228 
1229 1:
1230         /* System call failure, set Carry condition code.
1231          * Also, get abs(errno) to return to the process.
1232          */
1233         sub     %g0, %o0, %o0
1234         st      %o0, [%sp + REGWIN_SZ + PT_I0]
1235         or      %l5, %l6, %l5
1236         st      %l5, [%sp + REGWIN_SZ + PT_PSR]
1237 
1238 2:
1239         LOAD_CURRENT(l4, l5)
1240         ld      [%l4 + 0x14], %l5
1241         andcc   %l5, 0x20, %g0
1242         be      3f
1243          nop
1244 
1245         call    C_LABEL(syscall_trace)
1246          nop
1247 
1248         /* Advance the pc and npc over the trap instruction. */
1249 3:
1250         ld      [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
1251         add     %l1, 0x4, %l2                   /* npc = npc+4 */
1252         st      %l1, [%sp + REGWIN_SZ + PT_PC]
1253         st      %l2, [%sp + REGWIN_SZ + PT_NPC]
1254 
1255         RESTORE_ALL
1256 
1257         /* Solaris system calls enter here... */
1258         .align  4
1259         .globl  solaris_syscall
1260 solaris_syscall:
1261         /* While we are here trying to optimize our lives
1262          * away, handle the easy bogus cases like a
1263          * ni_syscall or sysnum > NR_SYSCALLS etc.
1264          * In the cases where we cannot optimize the
1265          * call inline we don't really lose anything
1266          * performance wise because we are doing here
1267          * things which we did anyway in the original
1268          * routine.  The only added complexity is a
1269          * bit test, compare, and branch to decide
1270          * if we need to save process state or not.
1271          */
1272 
1273         /* XXX TODO: When we have ptrace working test
1274          * XXX       test for PF_TRACESYS in task flags.
1275          */
1276 
1277         /* Direct access to user regs, must faster. */
1278         cmp     %g1, NR_SYSCALLS
1279         blu,a   1f
1280          sll    %g1, 2, %l4
1281 
1282         set     C_LABEL(sys_ni_syscall), %l7
1283         b       solaris_is_too_hard
1284          nop
1285 
1286 1:
1287         ld      [%l7 + %l4], %l7
1288 
1289         /* If bit-1 is set, this is a "fast" syscall.
1290          * This is the _complete_ overhead of this optimization,
1291          * and we save ourselves a load, so it evens out to nothing.
1292          */
1293         andcc   %l7, 0x1, %g0
1294         be      solaris_is_too_hard
1295          andn   %l7, 0x1, %l7
1296 
1297         jmpl    %l7, %g0
1298          nop
1299 
1300         .globl  solaris_is_too_hard
1301 solaris_is_too_hard:
1302         rd      %wim, %l3
1303         SAVE_ALL
1304         ENTER_SYSCALL
1305 
1306         wr      %l0, PSR_ET, %psr
1307         WRITE_PAUSE
1308 
1309 2:
1310         ldd     [%sp + REGWIN_SZ + PT_I0], %o0
1311         st      %o0, [%sp + REGWIN_SZ + PT_G0]  ! for restarting syscalls
1312         ldd     [%sp + REGWIN_SZ + PT_I2], %o2
1313         call    %l7
1314          ldd    [%sp + REGWIN_SZ + PT_I4], %o4
1315 
1316         st      %o0, [%sp + REGWIN_SZ + PT_I0]
1317         set     PSR_C, %l6
1318         cmp     %o0, -ENOIOCTLCMD
1319         bgeu    1f
1320          ld     [%sp + REGWIN_SZ + PT_PSR], %l5
1321 
1322         /* System call success, clear Carry condition code. */          
1323         andn    %l5, %l6, %l5
1324         b       2f
1325          st     %l5, [%sp + REGWIN_SZ + PT_PSR] 
1326 
1327 1:
1328         /* System call failure, set Carry condition code.
1329          * Also, get abs(errno) to return to the process.
1330          */
1331         sub     %g0, %o0, %o0
1332         sethi   %hi(C_LABEL(solaris_xlatb_rorl)), %o3
1333         or      %o3, %lo(C_LABEL(solaris_xlatb_rorl)), %o3
1334         sll     %o0, 2, %o0
1335         ld      [%o3 + %o0], %o0
1336         st      %o0, [%sp + REGWIN_SZ + PT_I0]
1337         or      %l5, %l6, %l5
1338         st      %l5, [%sp + REGWIN_SZ + PT_PSR]
1339 
1340         /* Advance the pc and npc over the trap instruction. */
1341 2:
1342         ld      [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
1343         add     %l1, 0x4, %l2                   /* npc = npc+4 */
1344         st      %l1, [%sp + REGWIN_SZ + PT_PC]
1345         st      %l2, [%sp + REGWIN_SZ + PT_NPC]
1346 
1347         RESTORE_ALL
1348 
1349         /* {net, open}bsd system calls enter here... */
1350         .align  4
1351         .globl  bsd_syscall
1352 bsd_syscall:
1353         /* While we are here trying to optimize our lives
1354          * away, handle the easy bogus cases like a
1355          * ni_syscall or sysnum > NR_SYSCALLS etc.
1356          * In the cases where we cannot optimize the
1357          * call inline we don't really lose anything
1358          * performance wise because we are doing here
1359          * things which we did anyway in the original
1360          * routine.  The only added complexity is a
1361          * bit test, compare, and branch to decide
1362          * if we need to save process state or not.
1363          */
1364 
1365         /* XXX TODO: When we have ptrace working test
1366          * XXX       test for PF_TRACESYS in task flags.
1367          */
1368 
1369         /* Direct access to user regs, must faster. */
1370         cmp     %g1, NR_SYSCALLS
1371         blu,a   1f
1372          sll    %g1, 2, %l4
1373 
1374         set     C_LABEL(sys_ni_syscall), %l7
1375         b       bsd_is_too_hard
1376          nop
1377 
1378 1:
1379         ld      [%l7 + %l4], %l7
1380 
1381         /* If bit-1 is set, this is a "fast" syscall.
1382          * This is the _complete_ overhead of this optimization,
1383          * and we save ourselves a load, so it evens out to nothing.
1384          */
1385         andcc   %l7, 0x1, %g0
1386         be      bsd_is_too_hard
1387          andn   %l7, 0x1, %l7
1388 
1389         jmpl    %l7, %g0
1390          nop
1391 
1392         .globl  bsd_is_too_hard
1393 bsd_is_too_hard:
1394         rd      %wim, %l3
1395         SAVE_ALL
1396         ENTER_SYSCALL
1397 
1398         wr      %l0, PSR_ET, %psr
1399         WRITE_PAUSE
1400 
1401 2:
1402         ldd     [%sp + REGWIN_SZ + PT_I0], %o0
1403         st      %o0, [%sp + REGWIN_SZ + PT_G0]  ! for restarting syscalls
1404         ldd     [%sp + REGWIN_SZ + PT_I2], %o2
1405         call    %l7
1406          ldd    [%sp + REGWIN_SZ + PT_I4], %o4
1407 
1408         st      %o0, [%sp + REGWIN_SZ + PT_I0]
1409         set     PSR_C, %l6
1410         cmp     %o0, -ENOIOCTLCMD
1411         bgeu    1f
1412          ld     [%sp + REGWIN_SZ + PT_PSR], %l5
1413 
1414         /* System call success, clear Carry condition code. */          
1415         andn    %l5, %l6, %l5
1416         b       2f
1417          st     %l5, [%sp + REGWIN_SZ + PT_PSR] 
1418 
1419 1:
1420         /* System call failure, set Carry condition code.
1421          * Also, get abs(errno) to return to the process.
1422          */
1423         sub     %g0, %o0, %o0
1424 #if 0 /* XXX todo XXX */
1425         sethi   %hi(C_LABEL(bsd_xlatb_rorl), %o3
1426         or      %o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3
1427         sll     %o0, 2, %o0
1428         ld      [%o3 + %o0], %o0
1429 #endif
1430         st      %o0, [%sp + REGWIN_SZ + PT_I0]
1431         or      %l5, %l6, %l5
1432         st      %l5, [%sp + REGWIN_SZ + PT_PSR]
1433 
1434         /* Advance the pc and npc over the trap instruction. */
1435 2:
1436         ld      [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
1437         add     %l1, 0x4, %l2                   /* npc = npc+4 */
1438         st      %l1, [%sp + REGWIN_SZ + PT_PC]
1439         st      %l2, [%sp + REGWIN_SZ + PT_NPC]
1440 
1441         RESTORE_ALL
1442 
1443 /* Saving and restoring the FPU state is best done from lowlevel code.
1444  *
1445  * void fpsave(unsigned long *fpregs, unsigned long *fsr,
1446  *             void *fpqueue, unsigned long *fpqdepth)
1447  */
1448 
1449         .globl  C_LABEL(fpsave)
1450 C_LABEL(fpsave):
1451         st      %fsr, [%o1]     ! this can trap on us if fpu is in bogon state
1452         ld      [%o1], %g1
1453         set     0x2000, %g4
1454         andcc   %g1, %g4, %g0
1455         be      2f
1456          mov    0, %g2
1457 
1458         /* We have an fpqueue to save. */
1459 1:
1460         std     %fq, [%o2]
1461 fpsave_magic:
1462         st      %fsr, [%o1]
1463         ld      [%o1], %g3
1464         andcc   %g3, %g4, %g0
1465         add     %g2, 1, %g2
1466         bne     1b
1467          add    %o2, 8, %o2
1468 
1469 2:
1470         st      %g2, [%o3]
1471 
1472         std     %f0, [%o0 + 0x00]
1473         std     %f2, [%o0 + 0x08]
1474         std     %f4, [%o0 + 0x10]
1475         std     %f6, [%o0 + 0x18]
1476         std     %f8, [%o0 + 0x20]
1477         std     %f10, [%o0 + 0x28]
1478         std     %f12, [%o0 + 0x30]
1479         std     %f14, [%o0 + 0x38]
1480         std     %f16, [%o0 + 0x40]
1481         std     %f18, [%o0 + 0x48]
1482         std     %f20, [%o0 + 0x50]
1483         std     %f22, [%o0 + 0x58]
1484         std     %f24, [%o0 + 0x60]
1485         std     %f26, [%o0 + 0x68]
1486         std     %f28, [%o0 + 0x70]
1487         retl
1488          std    %f30, [%o0 + 0x78]
1489 
1490         /* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd
1491          * code for pointing out this possible deadlock, while we save state
1492          * above we could trap on the fsr store so our low level fpu trap
1493          * code has to know how to deal with this.
1494          */
1495 fpsave_catch:
1496         b       fpsave_magic + 4
1497          st     %fsr, [%o1]
1498 
1499 fpsave_catch2:
1500         b       C_LABEL(fpsave) + 4
1501          st     %fsr, [%o1]
1502 
1503         /* void fpload(unsigned long *fpregs, unsigned long *fsr); */
1504 
1505         .globl  C_LABEL(fpload)
1506 C_LABEL(fpload):
1507         ldd     [%o0 + 0x00], %f0
1508         ldd     [%o0 + 0x08], %f2
1509         ldd     [%o0 + 0x10], %f4
1510         ldd     [%o0 + 0x18], %f6
1511         ldd     [%o0 + 0x20], %f8
1512         ldd     [%o0 + 0x28], %f10
1513         ldd     [%o0 + 0x30], %f12
1514         ldd     [%o0 + 0x38], %f14
1515         ldd     [%o0 + 0x40], %f16
1516         ldd     [%o0 + 0x48], %f18
1517         ldd     [%o0 + 0x50], %f20
1518         ldd     [%o0 + 0x58], %f22
1519         ldd     [%o0 + 0x60], %f24
1520         ldd     [%o0 + 0x68], %f26
1521         ldd     [%o0 + 0x70], %f28
1522         ldd     [%o0 + 0x78], %f30
1523         ld      [%o1], %fsr
1524         retl
1525          nop
1526 
1527         .globl  C_LABEL(udelay)
1528 C_LABEL(udelay):
1529         save    %sp, -REGWIN_SZ, %sp
1530         mov     %i0, %o0
1531         sethi   %hi(0x10c6), %o1
1532         call    .umul
1533          or     %o1, %lo(0x10c6), %o1
1534 #ifndef __SMP__
1535         sethi   %hi(C_LABEL(loops_per_sec)), %o3
1536         call    .umul
1537          ld     [%o3 + %lo(C_LABEL(loops_per_sec))], %o1
1538 #else
1539         GET_PROCESSOR_OFFSET(o4)
1540         set     C_LABEL(cpu_data), %o3
1541         call    .umul
1542          ld     [%o3 + %o4], %o1
1543 #endif
1544 
1545         cmp     %o1, 0x0
1546 1:
1547         bne     1b
1548          subcc  %o1, 1, %o1
1549         
1550         ret
1551         restore
1552 
1553 /* End of entry.S */

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