Print this page
de-linting of .s files


   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24  
  25 /*
  26  * Process switching routines.
  27  */
  28 
  29 #if !defined(lint)
  30 #include "assym.h"
  31 #else   /* lint */
  32 #include <sys/thread.h>
  33 #endif  /* lint */
  34 
  35 #include <sys/param.h>
  36 #include <sys/asm_linkage.h>
  37 #include <sys/mmu.h>
  38 #include <sys/pcb.h>
  39 #include <sys/machthread.h>
  40 #include <sys/machclock.h>
  41 #include <sys/privregs.h>
  42 #include <sys/vtrace.h>
  43 #include <vm/hat_sfmmu.h>
  44 
  45 /*
  46  * resume(kthread_id_t)
  47  *
  48  * a thread can only run on one processor at a time. there
  49  * exists a window on MPs where the current thread on one
  50  * processor is capable of being dispatched by another processor.
  51  * some overlap between outgoing and incoming threads can happen
  52  * when they are the same thread. in this case where the threads
  53  * are the same, resume() on one processor will spin on the incoming 
  54  * thread until resume() on the other processor has finished with
  55  * the outgoing thread.
  56  *
  57  * The MMU context changes when the resuming thread resides in a different
  58  * process.  Kernel threads are known by resume to reside in process 0.
  59  * The MMU context, therefore, only changes when resuming a thread in
  60  * a process different from curproc.
  61  *
  62  * resume_from_intr() is called when the thread being resumed was not 
  63  * passivated by resume (e.g. was interrupted).  This means that the
  64  * resume lock is already held and that a restore context is not needed.
  65  * Also, the MMU context is not changed on the resume in this case.
  66  *
  67  * resume_from_zombie() is the same as resume except the calling thread
  68  * is a zombie and must be put on the deathrow list after the CPU is
  69  * off the stack.
  70  */
  71 
  72 #if defined(lint)
  73 
  74 /* ARGSUSED */
  75 void
  76 resume(kthread_id_t t)
  77 {}
  78 
  79 #else   /* lint */
  80 
  81         ENTRY(resume)
  82         save    %sp, -SA(MINFRAME), %sp         ! save ins and locals
  83 
  84         call    __dtrace_probe___sched_off__cpu ! DTrace probe
  85         mov     %i0, %o0                        ! arg for DTrace probe
  86 
  87         membar  #Sync                           ! flush writebuffers
  88         flushw                                  ! flushes all but this window
  89 
  90         stn     %i7, [THREAD_REG + T_PC]        ! save return address
  91         stn     %fp, [THREAD_REG + T_SP]        ! save sp
  92 
  93         !
  94         ! Save GSR (Graphics Status Register).
  95         !
  96         ! Read fprs, call fp_save if FPRS_FEF set.
  97         ! This handles floating-point state saving.
  98         ! The fprs could be turned on by hw bcopy software,
  99         ! *or* by fp_disabled. Handle it either way.
 100         !


 437         casx    [%o2], %o1, %o0
 438         cmp     %o0, %o1
 439         be,pt   %xcc, 5b
 440           nop
 441         ! If an interrupt occurred while we were attempting to store
 442         ! the timestamp, try again.
 443         ba,pt   %xcc, 1b
 444           nop
 445 
 446         !
 447         ! lock failed - spin with regular load to avoid cache-thrashing.
 448         !
 449 7:
 450         brnz,a,pt %o0, 7b               ! spin while locked
 451           ldub  [%i0 + T_LOCK], %o0
 452         ba      %xcc, 6b
 453           ldstub  [%i0 + T_LOCK], %o0   ! delay - lock curthread's mutex
 454         SET_SIZE(_resume_from_idle)
 455         SET_SIZE(resume)
 456 
 457 #endif  /* lint */
 458 
 459 #if defined(lint)
 460 
 461 /* ARGSUSED */
 462 void
 463 resume_from_zombie(kthread_id_t t)
 464 {}
 465 
 466 #else   /* lint */
 467 
 468         ENTRY(resume_from_zombie)
 469         save    %sp, -SA(MINFRAME), %sp         ! save ins and locals
 470 
 471         call    __dtrace_probe___sched_off__cpu ! DTrace probe
 472         mov     %i0, %o0                        ! arg for DTrace probe
 473 
 474         ldn     [THREAD_REG + T_CPU], %i1       ! cpu pointer
 475                                         
 476         flushw                                  ! flushes all but this window
 477         ldn     [THREAD_REG + T_PROCP], %i2     ! old procp for mmu ctx
 478 
 479         !
 480         ! Temporarily switch to the idle thread's stack so that
 481         ! the zombie thread's stack can be reclaimed by the reaper.
 482         !
 483         ldn     [%i1 + CPU_IDLE_THREAD], %o2    ! idle thread pointer
 484         ldn     [%o2 + T_SP], %o1               ! get onto idle thread stack
 485         sub     %o1, SA(MINFRAME), %sp          ! save room for ins and locals
 486         clr     %fp
 487         !


 492         mov     %o2, THREAD_REG                 ! set %g7 to idle
 493         stn     %g0, [%i1 + CPU_MPCB]           ! clear mpcb
 494 #ifdef CPU_MPCB_PA
 495         mov     -1, %o1
 496         stx     %o1, [%i1 + CPU_MPCB_PA]
 497 #endif
 498         call    reapq_add                       ! reapq_add(old_thread);
 499         stn     %o2, [%i1 + CPU_THREAD]         ! delay - CPU's thread = idle
 500 
 501         !
 502         ! resume_from_idle args:
 503         !       %i0 = new thread
 504         !       %i1 = cpu
 505         !       %i2 = old proc
 506         !       %i3 = new proc
 507         !       
 508         b       _resume_from_idle               ! finish job of resume
 509         ldn     [%i0 + T_PROCP], %i3            ! new process
 510         SET_SIZE(resume_from_zombie)
 511 
 512 #endif  /* lint */
 513 
 514 #if defined(lint)
 515 
 516 /* ARGSUSED */
 517 void
 518 resume_from_intr(kthread_id_t t)
 519 {}
 520 
 521 #else   /* lint */
 522 
 523         ENTRY(resume_from_intr)
 524         save    %sp, -SA(MINFRAME), %sp         ! save ins and locals
 525 
 526         !
 527         ! We read in the fprs and call fp_save if FPRS_FEF is set
 528         ! to save the floating-point state if fprs has been
 529         ! modified by operations such as hw bcopy or fp_disabled.
 530         ! This is to resolve an issue where an interrupting thread
 531         ! doesn't retain their floating-point registers when
 532         ! switching out of the interrupt context.
 533         !
 534         rd      %fprs, %g4
 535         ldn     [THREAD_REG + T_STACK], %i2
 536         andcc   %g4, FPRS_FEF, %g0              ! is FPRS_FEF set
 537         bz,pt   %icc, 4f
 538           st    %g4, [%i2 + SA(MINFRAME) + FPU_FPRS]    ! save fprs
 539 
 540         ! save kernel fp state in stack
 541         add     %i2, SA(MINFRAME), %o0          ! %o0 = kfpu_t ptr
 542         rd      %gsr, %g5


 597         casx    [%o2], %o1, %o0
 598         cmp     %o0, %o1
 599         bne,pn  %xcc, 2b
 600         ldn     [THREAD_REG + T_INTR], %l1      ! delay
 601         ! Reset cpu_intrcnt if we aren't pinning anyone
 602         brz,a,pt %l1, 2f
 603         stub    %g0, [%i1 + CPU_INTRCNT]
 604 2:      
 605         ba,pt   %xcc, 1b
 606         nop
 607 3:
 608         !
 609         ! We're a non-interrupt thread and cpu_kprunrun is set. call kpreempt.
 610         !
 611         call    kpreempt
 612         mov     KPREEMPT_SYNC, %o0
 613         ba,pt   %xcc, 1b
 614         nop
 615         SET_SIZE(resume_from_intr)
 616 
 617 #endif /* lint */
 618 
 619 
 620 /*
 621  * thread_start()
 622  *
 623  * the current register window was crafted by thread_run() to contain
 624  * an address of a procedure (in register %i7), and its args in registers
 625  * %i0 through %i5. a stack trace of this thread will show the procedure
 626  * that thread_start() invoked at the bottom of the stack. an exit routine
 627  * is stored in %l0 and called when started thread returns from its called
 628  * procedure.
 629  */
 630 
 631 #if defined(lint)
 632 
 633 void
 634 thread_start(void)
 635 {}
 636 
 637 #else   /* lint */
 638 
 639         ENTRY(thread_start)
 640         mov     %i0, %o0
 641         jmpl    %i7, %o7        ! call thread_run()'s start() procedure.
 642         mov     %i1, %o1
 643 
 644         call    thread_exit     ! destroy thread if it returns.
 645         nop
 646         unimp 0
 647         SET_SIZE(thread_start)
 648 
 649 #endif  /* lint */


   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24  
  25 /*
  26  * Process switching routines.
  27  */
  28 

  29 #include "assym.h"



  30 
  31 #include <sys/param.h>
  32 #include <sys/asm_linkage.h>
  33 #include <sys/mmu.h>
  34 #include <sys/pcb.h>
  35 #include <sys/machthread.h>
  36 #include <sys/machclock.h>
  37 #include <sys/privregs.h>
  38 #include <sys/vtrace.h>
  39 #include <vm/hat_sfmmu.h>
  40 
  41 /*
  42  * resume(kthread_id_t)
  43  *
  44  * a thread can only run on one processor at a time. there
  45  * exists a window on MPs where the current thread on one
  46  * processor is capable of being dispatched by another processor.
  47  * some overlap between outgoing and incoming threads can happen
  48  * when they are the same thread. in this case where the threads
  49  * are the same, resume() on one processor will spin on the incoming 
  50  * thread until resume() on the other processor has finished with
  51  * the outgoing thread.
  52  *
  53  * The MMU context changes when the resuming thread resides in a different
  54  * process.  Kernel threads are known by resume to reside in process 0.
  55  * The MMU context, therefore, only changes when resuming a thread in
  56  * a process different from curproc.
  57  *
  58  * resume_from_intr() is called when the thread being resumed was not 
  59  * passivated by resume (e.g. was interrupted).  This means that the
  60  * resume lock is already held and that a restore context is not needed.
  61  * Also, the MMU context is not changed on the resume in this case.
  62  *
  63  * resume_from_zombie() is the same as resume except the calling thread
  64  * is a zombie and must be put on the deathrow list after the CPU is
  65  * off the stack.
  66  */
  67 









  68         ENTRY(resume)
  69         save    %sp, -SA(MINFRAME), %sp         ! save ins and locals
  70 
  71         call    __dtrace_probe___sched_off__cpu ! DTrace probe
  72         mov     %i0, %o0                        ! arg for DTrace probe
  73 
  74         membar  #Sync                           ! flush writebuffers
  75         flushw                                  ! flushes all but this window
  76 
  77         stn     %i7, [THREAD_REG + T_PC]        ! save return address
  78         stn     %fp, [THREAD_REG + T_SP]        ! save sp
  79 
  80         !
  81         ! Save GSR (Graphics Status Register).
  82         !
  83         ! Read fprs, call fp_save if FPRS_FEF set.
  84         ! This handles floating-point state saving.
  85         ! The fprs could be turned on by hw bcopy software,
  86         ! *or* by fp_disabled. Handle it either way.
  87         !


 424         casx    [%o2], %o1, %o0
 425         cmp     %o0, %o1
 426         be,pt   %xcc, 5b
 427           nop
 428         ! If an interrupt occurred while we were attempting to store
 429         ! the timestamp, try again.
 430         ba,pt   %xcc, 1b
 431           nop
 432 
 433         !
 434         ! lock failed - spin with regular load to avoid cache-thrashing.
 435         !
 436 7:
 437         brnz,a,pt %o0, 7b               ! spin while locked
 438           ldub  [%i0 + T_LOCK], %o0
 439         ba      %xcc, 6b
 440           ldstub  [%i0 + T_LOCK], %o0   ! delay - lock curthread's mutex
 441         SET_SIZE(_resume_from_idle)
 442         SET_SIZE(resume)
 443 











 444         ENTRY(resume_from_zombie)
 445         save    %sp, -SA(MINFRAME), %sp         ! save ins and locals
 446 
 447         call    __dtrace_probe___sched_off__cpu ! DTrace probe
 448         mov     %i0, %o0                        ! arg for DTrace probe
 449 
 450         ldn     [THREAD_REG + T_CPU], %i1       ! cpu pointer
 451                                         
 452         flushw                                  ! flushes all but this window
 453         ldn     [THREAD_REG + T_PROCP], %i2     ! old procp for mmu ctx
 454 
 455         !
 456         ! Temporarily switch to the idle thread's stack so that
 457         ! the zombie thread's stack can be reclaimed by the reaper.
 458         !
 459         ldn     [%i1 + CPU_IDLE_THREAD], %o2    ! idle thread pointer
 460         ldn     [%o2 + T_SP], %o1               ! get onto idle thread stack
 461         sub     %o1, SA(MINFRAME), %sp          ! save room for ins and locals
 462         clr     %fp
 463         !


 468         mov     %o2, THREAD_REG                 ! set %g7 to idle
 469         stn     %g0, [%i1 + CPU_MPCB]           ! clear mpcb
 470 #ifdef CPU_MPCB_PA
 471         mov     -1, %o1
 472         stx     %o1, [%i1 + CPU_MPCB_PA]
 473 #endif
 474         call    reapq_add                       ! reapq_add(old_thread);
 475         stn     %o2, [%i1 + CPU_THREAD]         ! delay - CPU's thread = idle
 476 
 477         !
 478         ! resume_from_idle args:
 479         !       %i0 = new thread
 480         !       %i1 = cpu
 481         !       %i2 = old proc
 482         !       %i3 = new proc
 483         !       
 484         b       _resume_from_idle               ! finish job of resume
 485         ldn     [%i0 + T_PROCP], %i3            ! new process
 486         SET_SIZE(resume_from_zombie)
 487 











 488         ENTRY(resume_from_intr)
 489         save    %sp, -SA(MINFRAME), %sp         ! save ins and locals
 490 
 491         !
 492         ! We read in the fprs and call fp_save if FPRS_FEF is set
 493         ! to save the floating-point state if fprs has been
 494         ! modified by operations such as hw bcopy or fp_disabled.
 495         ! This is to resolve an issue where an interrupting thread
 496         ! doesn't retain their floating-point registers when
 497         ! switching out of the interrupt context.
 498         !
 499         rd      %fprs, %g4
 500         ldn     [THREAD_REG + T_STACK], %i2
 501         andcc   %g4, FPRS_FEF, %g0              ! is FPRS_FEF set
 502         bz,pt   %icc, 4f
 503           st    %g4, [%i2 + SA(MINFRAME) + FPU_FPRS]    ! save fprs
 504 
 505         ! save kernel fp state in stack
 506         add     %i2, SA(MINFRAME), %o0          ! %o0 = kfpu_t ptr
 507         rd      %gsr, %g5


 562         casx    [%o2], %o1, %o0
 563         cmp     %o0, %o1
 564         bne,pn  %xcc, 2b
 565         ldn     [THREAD_REG + T_INTR], %l1      ! delay
 566         ! Reset cpu_intrcnt if we aren't pinning anyone
 567         brz,a,pt %l1, 2f
 568         stub    %g0, [%i1 + CPU_INTRCNT]
 569 2:      
 570         ba,pt   %xcc, 1b
 571         nop
 572 3:
 573         !
 574         ! We're a non-interrupt thread and cpu_kprunrun is set. call kpreempt.
 575         !
 576         call    kpreempt
 577         mov     KPREEMPT_SYNC, %o0
 578         ba,pt   %xcc, 1b
 579         nop
 580         SET_SIZE(resume_from_intr)
 581 

 582 

 583 /*
 584  * thread_start()
 585  *
 586  * the current register window was crafted by thread_run() to contain
 587  * an address of a procedure (in register %i7), and its args in registers
 588  * %i0 through %i5. a stack trace of this thread will show the procedure
 589  * that thread_start() invoked at the bottom of the stack. an exit routine
 590  * is stored in %l0 and called when started thread returns from its called
 591  * procedure.
 592  */
 593 








 594         ENTRY(thread_start)
 595         mov     %i0, %o0
 596         jmpl    %i7, %o7        ! call thread_run()'s start() procedure.
 597         mov     %i1, %o1
 598 
 599         call    thread_exit     ! destroy thread if it returns.
 600         nop
 601         unimp 0
 602         SET_SIZE(thread_start)