17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51e2e7a75Shuah * Common Development and Distribution License (the "License"). 61e2e7a75Shuah * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22*1426d65aSsm142603 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate/* 297c478bd9Sstevel@tonic-gate * Process switching routines. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate#if !defined(lint) 337c478bd9Sstevel@tonic-gate#include "assym.h" 347c478bd9Sstevel@tonic-gate#else /* lint */ 357c478bd9Sstevel@tonic-gate#include <sys/thread.h> 367c478bd9Sstevel@tonic-gate#endif /* lint */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate#include <sys/param.h> 397c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 407c478bd9Sstevel@tonic-gate#include <sys/mmu.h> 417c478bd9Sstevel@tonic-gate#include <sys/pcb.h> 427c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 437c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 447c478bd9Sstevel@tonic-gate#include <sys/vtrace.h> 457c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate/* 487c478bd9Sstevel@tonic-gate * resume(kthread_id_t) 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * a thread can only run on one processor at a time. there 517c478bd9Sstevel@tonic-gate * exists a window on MPs where the current thread on one 527c478bd9Sstevel@tonic-gate * processor is capable of being dispatched by another processor. 537c478bd9Sstevel@tonic-gate * some overlap between outgoing and incoming threads can happen 547c478bd9Sstevel@tonic-gate * when they are the same thread. in this case where the threads 557c478bd9Sstevel@tonic-gate * are the same, resume() on one processor will spin on the incoming 567c478bd9Sstevel@tonic-gate * thread until resume() on the other processor has finished with 577c478bd9Sstevel@tonic-gate * the outgoing thread. 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate * The MMU context changes when the resuming thread resides in a different 607c478bd9Sstevel@tonic-gate * process. Kernel threads are known by resume to reside in process 0. 617c478bd9Sstevel@tonic-gate * The MMU context, therefore, only changes when resuming a thread in 627c478bd9Sstevel@tonic-gate * a process different from curproc. 637c478bd9Sstevel@tonic-gate * 647c478bd9Sstevel@tonic-gate * resume_from_intr() is called when the thread being resumed was not 657c478bd9Sstevel@tonic-gate * passivated by resume (e.g. was interrupted). This means that the 667c478bd9Sstevel@tonic-gate * resume lock is already held and that a restore context is not needed. 677c478bd9Sstevel@tonic-gate * Also, the MMU context is not changed on the resume in this case. 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * resume_from_zombie() is the same as resume except the calling thread 707c478bd9Sstevel@tonic-gate * is a zombie and must be put on the deathrow list after the CPU is 717c478bd9Sstevel@tonic-gate * off the stack. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate#if defined(lint) 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate/* ARGSUSED */ 777c478bd9Sstevel@tonic-gatevoid 787c478bd9Sstevel@tonic-gateresume(kthread_id_t t) 797c478bd9Sstevel@tonic-gate{} 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate#else /* lint */ 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate ENTRY(resume) 847c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp ! save ins and locals 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate call __dtrace_probe___sched_off__cpu ! DTrace probe 877c478bd9Sstevel@tonic-gate mov %i0, %o0 ! arg for DTrace probe 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate membar #Sync ! flush writebuffers 907c478bd9Sstevel@tonic-gate flushw ! flushes all but this window 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate stn %i7, [THREAD_REG + T_PC] ! save return address 937c478bd9Sstevel@tonic-gate stn %fp, [THREAD_REG + T_SP] ! save sp 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate ! 967c478bd9Sstevel@tonic-gate ! Save GSR (Graphics Status Register). 977c478bd9Sstevel@tonic-gate ! 987c478bd9Sstevel@tonic-gate ! Read fprs, call fp_save if FPRS_FEF set. 997c478bd9Sstevel@tonic-gate ! This handles floating-point state saving. 1007c478bd9Sstevel@tonic-gate ! The fprs could be turned on by hw bcopy software, 1017c478bd9Sstevel@tonic-gate ! *or* by fp_disabled. Handle it either way. 1027c478bd9Sstevel@tonic-gate ! 1037c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LWP], %o4 ! get lwp pointer 1047c478bd9Sstevel@tonic-gate rd %fprs, %g4 ! read fprs 1057c478bd9Sstevel@tonic-gate brnz,pt %o4, 0f ! if user thread skip 1067c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CPU], %i1 ! get CPU pointer 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate ! 1097c478bd9Sstevel@tonic-gate ! kernel thread 1107c478bd9Sstevel@tonic-gate ! 1117c478bd9Sstevel@tonic-gate ! we save fprs at the beginning the stack so we know 1127c478bd9Sstevel@tonic-gate ! where to check at resume time 1137c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_STACK], %i2 1147c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CTX], %g3 ! get ctx pointer 1157c478bd9Sstevel@tonic-gate andcc %g4, FPRS_FEF, %g0 ! is FPRS_FEF set 1167c478bd9Sstevel@tonic-gate bz,pt %icc, 1f ! nope, skip 1177c478bd9Sstevel@tonic-gate st %g4, [%i2 + SA(MINFRAME) + FPU_FPRS] ! save fprs 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate ! save kernel fp state in stack 1207c478bd9Sstevel@tonic-gate add %i2, SA(MINFRAME), %o0 ! o0 = kfpu_t ptr 1217c478bd9Sstevel@tonic-gate rd %gsr, %g5 1227c478bd9Sstevel@tonic-gate call fp_save 1237c478bd9Sstevel@tonic-gate stx %g5, [%o0 + FPU_GSR] ! store GSR 1247c478bd9Sstevel@tonic-gate ba,a,pt %icc, 1f 1257c478bd9Sstevel@tonic-gate nop 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate0: 1287c478bd9Sstevel@tonic-gate ! user thread 1297c478bd9Sstevel@tonic-gate ! o4 = lwp ptr 1307c478bd9Sstevel@tonic-gate ! g4 = fprs 1317c478bd9Sstevel@tonic-gate ! i1 = CPU ptr 1327c478bd9Sstevel@tonic-gate ldn [%o4 + LWP_FPU], %o0 ! fp pointer 1337c478bd9Sstevel@tonic-gate stn %fp, [THREAD_REG + T_SP] ! save sp 1347c478bd9Sstevel@tonic-gate andcc %g4, FPRS_FEF, %g0 ! is FPRS_FEF set 1357c478bd9Sstevel@tonic-gate st %g4, [%o0 + FPU_FPRS] ! store FPRS 1367c478bd9Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 1377c478bd9Sstevel@tonic-gate sethi %hi(fpu_exists), %g5 1387c478bd9Sstevel@tonic-gate ld [%g5 + %lo(fpu_exists)], %g5 1397c478bd9Sstevel@tonic-gate brz,pn %g5, 1f 1407c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CTX], %g3 ! get ctx pointer 1417c478bd9Sstevel@tonic-gate#endif 1427c478bd9Sstevel@tonic-gate bz,pt %icc, 1f ! most apps don't use fp 1437c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CTX], %g3 ! get ctx pointer 1447c478bd9Sstevel@tonic-gate ldn [%o4 + LWP_FPU], %o0 ! fp pointer 1457c478bd9Sstevel@tonic-gate rd %gsr, %g5 1467c478bd9Sstevel@tonic-gate call fp_save ! doesn't touch globals 1477c478bd9Sstevel@tonic-gate stx %g5, [%o0 + FPU_GSR] ! store GSR 1487c478bd9Sstevel@tonic-gate1: 1497c478bd9Sstevel@tonic-gate ! 1507c478bd9Sstevel@tonic-gate ! Perform context switch callback if set. 1517c478bd9Sstevel@tonic-gate ! This handles coprocessor state saving. 1527c478bd9Sstevel@tonic-gate ! i1 = cpu ptr 1537c478bd9Sstevel@tonic-gate ! g3 = ctx pointer 1547c478bd9Sstevel@tonic-gate ! 1557c478bd9Sstevel@tonic-gate wr %g0, %g0, %fprs ! disable fpu and clear fprs 1567c478bd9Sstevel@tonic-gate brz,pt %g3, 2f ! skip call when zero 1577c478bd9Sstevel@tonic-gate ldn [%i0 + T_PROCP], %i3 ! delay slot - get proc pointer 1587c478bd9Sstevel@tonic-gate call savectx 1597c478bd9Sstevel@tonic-gate mov THREAD_REG, %o0 ! delay - arg = thread pointer 1607c478bd9Sstevel@tonic-gate2: 1617c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_PROCP], %i2 ! load old curproc - for mmu 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate ! 1647c478bd9Sstevel@tonic-gate ! Temporarily switch to idle thread's stack 1657c478bd9Sstevel@tonic-gate ! 1667c478bd9Sstevel@tonic-gate ldn [%i1 + CPU_IDLE_THREAD], %o0 ! idle thread pointer 1677c478bd9Sstevel@tonic-gate ldn [%o0 + T_SP], %o1 ! get onto idle thread stack 1687c478bd9Sstevel@tonic-gate sub %o1, SA(MINFRAME), %sp ! save room for ins and locals 1697c478bd9Sstevel@tonic-gate clr %fp 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate ! 1727c478bd9Sstevel@tonic-gate ! Set the idle thread as the current thread 1737c478bd9Sstevel@tonic-gate ! 1747c478bd9Sstevel@tonic-gate mov THREAD_REG, %l3 ! save %g7 (current thread) 1757c478bd9Sstevel@tonic-gate mov %o0, THREAD_REG ! set %g7 to idle 1767c478bd9Sstevel@tonic-gate stn %o0, [%i1 + CPU_THREAD] ! set CPU's thread to idle 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate ! 1797c478bd9Sstevel@tonic-gate ! Clear and unlock previous thread's t_lock 1807c478bd9Sstevel@tonic-gate ! to allow it to be dispatched by another processor. 1817c478bd9Sstevel@tonic-gate ! 1827c478bd9Sstevel@tonic-gate clrb [%l3 + T_LOCK] ! clear tp->t_lock 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate ! 1857c478bd9Sstevel@tonic-gate ! IMPORTANT: Registers at this point must be: 1867c478bd9Sstevel@tonic-gate ! %i0 = new thread 1877c478bd9Sstevel@tonic-gate ! %i1 = cpu pointer 1887c478bd9Sstevel@tonic-gate ! %i2 = old proc pointer 1897c478bd9Sstevel@tonic-gate ! %i3 = new proc pointer 1907c478bd9Sstevel@tonic-gate ! 1917c478bd9Sstevel@tonic-gate ! Here we are in the idle thread, have dropped the old thread. 1927c478bd9Sstevel@tonic-gate ! 1937c478bd9Sstevel@tonic-gate ALTENTRY(_resume_from_idle) 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate ! SET_KCONTEXTREG(reg0, reg1, reg2, reg3, reg4, label1, label2, label3) 1967c478bd9Sstevel@tonic-gate SET_KCONTEXTREG(%o0, %g1, %g2, %g3, %o3, l1, l2, l3) 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate cmp %i2, %i3 ! resuming the same process? 1997c478bd9Sstevel@tonic-gate be,pt %xcc, 5f ! yes. 2007c478bd9Sstevel@tonic-gate nop 2011e2e7a75Shuah 2027c478bd9Sstevel@tonic-gate ldx [%i3 + P_AS], %o0 ! load p->p_as 2031e2e7a75Shuah ldx [%o0 + A_HAT], %i5 ! %i5 = new proc hat 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate ! 2067c478bd9Sstevel@tonic-gate ! update cpusran field 2077c478bd9Sstevel@tonic-gate ! 2087c478bd9Sstevel@tonic-gate ld [%i1 + CPU_ID], %o4 2091e2e7a75Shuah add %i5, SFMMU_CPUSRAN, %o5 2107c478bd9Sstevel@tonic-gate CPU_INDEXTOSET(%o5, %o4, %g1) 2111e2e7a75Shuah ldx [%o5], %o2 ! %o2 = cpusran field 2127c478bd9Sstevel@tonic-gate mov 1, %g2 2131e2e7a75Shuah sllx %g2, %o4, %o4 ! %o4 = bit for this cpu 2147c478bd9Sstevel@tonic-gate andcc %o4, %o2, %g0 2151e2e7a75Shuah bnz,pn %xcc, 0f ! bit already set, go to 0 2167c478bd9Sstevel@tonic-gate nop 2177c478bd9Sstevel@tonic-gate3: 2187c478bd9Sstevel@tonic-gate or %o2, %o4, %o1 ! or in this cpu's bit mask 2197c478bd9Sstevel@tonic-gate casx [%o5], %o2, %o1 2207c478bd9Sstevel@tonic-gate cmp %o2, %o1 2217c478bd9Sstevel@tonic-gate bne,a,pn %xcc, 3b 2227c478bd9Sstevel@tonic-gate ldx [%o5], %o2 ! o2 = cpusran field 2237c478bd9Sstevel@tonic-gate membar #LoadLoad|#StoreLoad 2247c478bd9Sstevel@tonic-gate 2251e2e7a75Shuah0: 2267c478bd9Sstevel@tonic-gate ! 2271e2e7a75Shuah ! disable interrupts 2287c478bd9Sstevel@tonic-gate ! 2291e2e7a75Shuah ! if resume from user to kernel thread 2301e2e7a75Shuah ! call sfmmu_setctx_sec 2311e2e7a75Shuah ! if resume from kernel (or a different user) thread to user thread 2321e2e7a75Shuah ! call sfmmu_alloc_ctx 2331e2e7a75Shuah ! sfmmu_load_mmustate 2341e2e7a75Shuah ! 2351e2e7a75Shuah ! enable interrupts 2361e2e7a75Shuah ! 2371e2e7a75Shuah ! %i5 = new proc hat 2381e2e7a75Shuah ! 2397c478bd9Sstevel@tonic-gate 2401e2e7a75Shuah sethi %hi(ksfmmup), %o2 2411e2e7a75Shuah ldx [%o2 + %lo(ksfmmup)], %o2 2421e2e7a75Shuah 2431e2e7a75Shuah rdpr %pstate, %i4 2441e2e7a75Shuah cmp %i5, %o2 ! new proc hat == ksfmmup ? 2451e2e7a75Shuah bne,pt %xcc, 3f ! new proc is not kernel as, go to 3 2461e2e7a75Shuah wrpr %i4, PSTATE_IE, %pstate 2471e2e7a75Shuah 2481e2e7a75Shuah SET_KAS_CTXSEC_ARGS(%i5, %o0, %o1) 2491e2e7a75Shuah 2501e2e7a75Shuah ! new proc is kernel as 2511e2e7a75Shuah 2521e2e7a75Shuah call sfmmu_setctx_sec ! switch to kernel context 2531e2e7a75Shuah or %o0, %o1, %o0 2541e2e7a75Shuah 2551e2e7a75Shuah ba,a,pt %icc, 4f 2561e2e7a75Shuah 2571e2e7a75Shuah ! 2581e2e7a75Shuah ! Switch to user address space. 2591e2e7a75Shuah ! 2601e2e7a75Shuah3: 2611e2e7a75Shuah mov %i5, %o0 ! %o0 = sfmmup 2621e2e7a75Shuah mov %i1, %o2 ! %o2 = CPU 26305d3dc4bSpaulsan set SFMMU_PRIVATE, %o3 ! %o3 = sfmmu private flag 2641e2e7a75Shuah call sfmmu_alloc_ctx 2651e2e7a75Shuah mov %g0, %o1 ! %o1 = allocate flag = 0 266*1426d65aSsm142603 26705d3dc4bSpaulsan brz,a,pt %o0, 4f ! %o0 == 0, no private alloc'ed 26805d3dc4bSpaulsan nop 26905d3dc4bSpaulsan 27005d3dc4bSpaulsan ldn [%i5 + SFMMU_SCDP], %o0 ! using shared contexts? 27105d3dc4bSpaulsan brz,a,pt %o0, 4f 27205d3dc4bSpaulsan nop 27305d3dc4bSpaulsan 27405d3dc4bSpaulsan ldn [%o0 + SCD_SFMMUP], %o0 ! %o0 = scdp->scd_sfmmup 27505d3dc4bSpaulsan mov %i1, %o2 ! %o2 = CPU 27605d3dc4bSpaulsan set SFMMU_SHARED, %o3 ! %o3 = sfmmu shared flag 27705d3dc4bSpaulsan call sfmmu_alloc_ctx 27805d3dc4bSpaulsan mov 1, %o1 ! %o1 = allocate flag = 1 27905d3dc4bSpaulsan 2801e2e7a75Shuah4: 2817c478bd9Sstevel@tonic-gate call sfmmu_load_mmustate ! program MMU registers 2821e2e7a75Shuah mov %i5, %o0 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate wrpr %g0, %i4, %pstate ! enable interrupts 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate5: 2877c478bd9Sstevel@tonic-gate ! 2887c478bd9Sstevel@tonic-gate ! spin until dispatched thread's mutex has 2897c478bd9Sstevel@tonic-gate ! been unlocked. this mutex is unlocked when 2907c478bd9Sstevel@tonic-gate ! it becomes safe for the thread to run. 2917c478bd9Sstevel@tonic-gate ! 2927c478bd9Sstevel@tonic-gate ldstub [%i0 + T_LOCK], %o0 ! lock curthread's t_lock 2937c478bd9Sstevel@tonic-gate6: 2947c478bd9Sstevel@tonic-gate brnz,pn %o0, 7f ! lock failed 2957c478bd9Sstevel@tonic-gate ldx [%i0 + T_PC], %i7 ! delay - restore resuming thread's pc 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate ! 2987c478bd9Sstevel@tonic-gate ! Fix CPU structure to indicate new running thread. 2997c478bd9Sstevel@tonic-gate ! Set pointer in new thread to the CPU structure. 3007c478bd9Sstevel@tonic-gate ! XXX - Move migration statistic out of here 3017c478bd9Sstevel@tonic-gate ! 3027c478bd9Sstevel@tonic-gate ldx [%i0 + T_CPU], %g2 ! last CPU to run the new thread 3037c478bd9Sstevel@tonic-gate cmp %g2, %i1 ! test for migration 3047c478bd9Sstevel@tonic-gate be,pt %xcc, 4f ! no migration 3057c478bd9Sstevel@tonic-gate ldn [%i0 + T_LWP], %o1 ! delay - get associated lwp (if any) 3067c478bd9Sstevel@tonic-gate ldx [%i1 + CPU_STATS_SYS_CPUMIGRATE], %g2 3077c478bd9Sstevel@tonic-gate inc %g2 3087c478bd9Sstevel@tonic-gate stx %g2, [%i1 + CPU_STATS_SYS_CPUMIGRATE] 3097c478bd9Sstevel@tonic-gate stx %i1, [%i0 + T_CPU] ! set new thread's CPU pointer 3107c478bd9Sstevel@tonic-gate4: 3117c478bd9Sstevel@tonic-gate stx %i0, [%i1 + CPU_THREAD] ! set CPU's thread pointer 3127c478bd9Sstevel@tonic-gate membar #StoreLoad ! synchronize with mutex_exit() 3137c478bd9Sstevel@tonic-gate mov %i0, THREAD_REG ! update global thread register 3147c478bd9Sstevel@tonic-gate stx %o1, [%i1 + CPU_LWP] ! set CPU's lwp ptr 3157c478bd9Sstevel@tonic-gate brz,a,pn %o1, 1f ! if no lwp, branch and clr mpcb 3167c478bd9Sstevel@tonic-gate stx %g0, [%i1 + CPU_MPCB] 3177c478bd9Sstevel@tonic-gate ! 3187c478bd9Sstevel@tonic-gate ! user thread 3197c478bd9Sstevel@tonic-gate ! o1 = lwp 3207c478bd9Sstevel@tonic-gate ! i0 = new thread 3217c478bd9Sstevel@tonic-gate ! 3227c478bd9Sstevel@tonic-gate ldx [%i0 + T_STACK], %o0 3237c478bd9Sstevel@tonic-gate stx %o0, [%i1 + CPU_MPCB] ! set CPU's mpcb pointer 3247c478bd9Sstevel@tonic-gate#ifdef CPU_MPCB_PA 3257c478bd9Sstevel@tonic-gate ldx [%o0 + MPCB_PA], %o0 3267c478bd9Sstevel@tonic-gate stx %o0, [%i1 + CPU_MPCB_PA] 3277c478bd9Sstevel@tonic-gate#endif 3287c478bd9Sstevel@tonic-gate ! Switch to new thread's stack 3297c478bd9Sstevel@tonic-gate ldx [%i0 + T_SP], %o0 ! restore resuming thread's sp 3307c478bd9Sstevel@tonic-gate sub %o0, SA(MINFRAME), %sp ! in case of intr or trap before restore 3317c478bd9Sstevel@tonic-gate mov %o0, %fp 3327c478bd9Sstevel@tonic-gate ! 3337c478bd9Sstevel@tonic-gate ! Restore resuming thread's GSR reg and floating-point regs 3347c478bd9Sstevel@tonic-gate ! Note that the ld to the gsr register ensures that the loading of 3357c478bd9Sstevel@tonic-gate ! the floating point saved state has completed without necessity 3367c478bd9Sstevel@tonic-gate ! of a membar #Sync. 3377c478bd9Sstevel@tonic-gate ! 3387c478bd9Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS) 3397c478bd9Sstevel@tonic-gate sethi %hi(fpu_exists), %g3 3407c478bd9Sstevel@tonic-gate ld [%g3 + %lo(fpu_exists)], %g3 3417c478bd9Sstevel@tonic-gate brz,pn %g3, 2f 3427c478bd9Sstevel@tonic-gate ldx [%i0 + T_CTX], %i5 ! should resumed thread restorectx? 3437c478bd9Sstevel@tonic-gate#endif 3447c478bd9Sstevel@tonic-gate ldx [%o1 + LWP_FPU], %o0 ! fp pointer 3457c478bd9Sstevel@tonic-gate ld [%o0 + FPU_FPRS], %g5 ! get fpu_fprs 3467c478bd9Sstevel@tonic-gate andcc %g5, FPRS_FEF, %g0 ! is FPRS_FEF set? 3477c478bd9Sstevel@tonic-gate bz,a,pt %icc, 9f ! no, skip fp_restore 3487c478bd9Sstevel@tonic-gate wr %g0, FPRS_FEF, %fprs ! enable fprs so fp_zero works 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate ldx [THREAD_REG + T_CPU], %o4 ! cpu pointer 3517c478bd9Sstevel@tonic-gate call fp_restore 3527c478bd9Sstevel@tonic-gate wr %g5, %g0, %fprs ! enable fpu and restore fprs 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate ldx [%o0 + FPU_GSR], %g5 ! load saved GSR data 3557c478bd9Sstevel@tonic-gate wr %g5, %g0, %gsr ! restore %gsr data 3567c478bd9Sstevel@tonic-gate ba,pt %icc,2f 3577c478bd9Sstevel@tonic-gate ldx [%i0 + T_CTX], %i5 ! should resumed thread restorectx? 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate9: 3607c478bd9Sstevel@tonic-gate ! 3617c478bd9Sstevel@tonic-gate ! Zero resuming thread's fp registers, for *all* non-fp program 3627c478bd9Sstevel@tonic-gate ! Remove all possibility of using the fp regs as a "covert channel". 3637c478bd9Sstevel@tonic-gate ! 3647c478bd9Sstevel@tonic-gate call fp_zero 3657c478bd9Sstevel@tonic-gate wr %g0, %g0, %gsr 3667c478bd9Sstevel@tonic-gate ldx [%i0 + T_CTX], %i5 ! should resumed thread restorectx? 3677c478bd9Sstevel@tonic-gate ba,pt %icc, 2f 3687c478bd9Sstevel@tonic-gate wr %g0, %g0, %fprs ! disable fprs 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate1: 3717c478bd9Sstevel@tonic-gate#ifdef CPU_MPCB_PA 3727c478bd9Sstevel@tonic-gate mov -1, %o1 3737c478bd9Sstevel@tonic-gate stx %o1, [%i1 + CPU_MPCB_PA] 3747c478bd9Sstevel@tonic-gate#endif 3757c478bd9Sstevel@tonic-gate ! 3767c478bd9Sstevel@tonic-gate ! kernel thread 3777c478bd9Sstevel@tonic-gate ! i0 = new thread 3787c478bd9Sstevel@tonic-gate ! 3797c478bd9Sstevel@tonic-gate ! Switch to new thread's stack 3807c478bd9Sstevel@tonic-gate ! 3817c478bd9Sstevel@tonic-gate ldx [%i0 + T_SP], %o0 ! restore resuming thread's sp 3827c478bd9Sstevel@tonic-gate sub %o0, SA(MINFRAME), %sp ! in case of intr or trap before restore 3837c478bd9Sstevel@tonic-gate mov %o0, %fp 3847c478bd9Sstevel@tonic-gate ! 3857c478bd9Sstevel@tonic-gate ! Restore resuming thread's GSR reg and floating-point regs 3867c478bd9Sstevel@tonic-gate ! Note that the ld to the gsr register ensures that the loading of 3877c478bd9Sstevel@tonic-gate ! the floating point saved state has completed without necessity 3887c478bd9Sstevel@tonic-gate ! of a membar #Sync. 3897c478bd9Sstevel@tonic-gate ! 3907c478bd9Sstevel@tonic-gate ldx [%i0 + T_STACK], %o0 3917c478bd9Sstevel@tonic-gate ld [%o0 + SA(MINFRAME) + FPU_FPRS], %g5 ! load fprs 3927c478bd9Sstevel@tonic-gate ldx [%i0 + T_CTX], %i5 ! should thread restorectx? 3937c478bd9Sstevel@tonic-gate andcc %g5, FPRS_FEF, %g0 ! did we save fp in stack? 3947c478bd9Sstevel@tonic-gate bz,a,pt %icc, 2f 3957c478bd9Sstevel@tonic-gate wr %g0, %g0, %fprs ! clr fprs 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate wr %g5, %g0, %fprs ! enable fpu and restore fprs 3987c478bd9Sstevel@tonic-gate call fp_restore 3997c478bd9Sstevel@tonic-gate add %o0, SA(MINFRAME), %o0 ! o0 = kpu_t ptr 4007c478bd9Sstevel@tonic-gate ldx [%o0 + FPU_GSR], %g5 ! load saved GSR data 4017c478bd9Sstevel@tonic-gate wr %g5, %g0, %gsr ! restore %gsr data 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate2: 4047c478bd9Sstevel@tonic-gate ! 4057c478bd9Sstevel@tonic-gate ! Restore resuming thread's context 4067c478bd9Sstevel@tonic-gate ! i5 = ctx ptr 4077c478bd9Sstevel@tonic-gate ! 4087c478bd9Sstevel@tonic-gate brz,a,pt %i5, 8f ! skip restorectx() when zero 4097c478bd9Sstevel@tonic-gate ld [%i1 + CPU_BASE_SPL], %o0 4107c478bd9Sstevel@tonic-gate call restorectx ! thread can not sleep on temp stack 4117c478bd9Sstevel@tonic-gate mov THREAD_REG, %o0 ! delay slot - arg = thread pointer 4127c478bd9Sstevel@tonic-gate ! 4137c478bd9Sstevel@tonic-gate ! Set priority as low as possible, blocking all interrupt threads 4147c478bd9Sstevel@tonic-gate ! that may be active. 4157c478bd9Sstevel@tonic-gate ! 4167c478bd9Sstevel@tonic-gate ld [%i1 + CPU_BASE_SPL], %o0 4177c478bd9Sstevel@tonic-gate8: 4187c478bd9Sstevel@tonic-gate wrpr %o0, 0, %pil 4197c478bd9Sstevel@tonic-gate wrpr %g0, WSTATE_KERN, %wstate 4207c478bd9Sstevel@tonic-gate ! 4217c478bd9Sstevel@tonic-gate ! If we are resuming an interrupt thread, store a starting timestamp 4227c478bd9Sstevel@tonic-gate ! in the thread structure. 4237c478bd9Sstevel@tonic-gate ! 4247c478bd9Sstevel@tonic-gate lduh [THREAD_REG + T_FLAGS], %o0 4257c478bd9Sstevel@tonic-gate andcc %o0, T_INTR_THREAD, %g0 4267c478bd9Sstevel@tonic-gate bnz,pn %xcc, 0f 4277c478bd9Sstevel@tonic-gate nop 4287c478bd9Sstevel@tonic-gate5: 4297c478bd9Sstevel@tonic-gate call __dtrace_probe___sched_on__cpu ! DTrace probe 4307c478bd9Sstevel@tonic-gate nop 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate ret ! resume curthread 4337c478bd9Sstevel@tonic-gate restore 4347c478bd9Sstevel@tonic-gate0: 4357c478bd9Sstevel@tonic-gate add THREAD_REG, T_INTR_START, %o2 4367c478bd9Sstevel@tonic-gate1: 4377c478bd9Sstevel@tonic-gate ldx [%o2], %o1 4387c478bd9Sstevel@tonic-gate rdpr %tick, %o0 4397c478bd9Sstevel@tonic-gate sllx %o0, 1, %o0 4407c478bd9Sstevel@tonic-gate srlx %o0, 1, %o0 ! shift off NPT bit 4417c478bd9Sstevel@tonic-gate casx [%o2], %o1, %o0 4427c478bd9Sstevel@tonic-gate cmp %o0, %o1 4437c478bd9Sstevel@tonic-gate be,pt %xcc, 5b 4447c478bd9Sstevel@tonic-gate nop 4457c478bd9Sstevel@tonic-gate ! If an interrupt occurred while we were attempting to store 4467c478bd9Sstevel@tonic-gate ! the timestamp, try again. 4477c478bd9Sstevel@tonic-gate ba,pt %xcc, 1b 4487c478bd9Sstevel@tonic-gate nop 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate ! 4517c478bd9Sstevel@tonic-gate ! lock failed - spin with regular load to avoid cache-thrashing. 4527c478bd9Sstevel@tonic-gate ! 4537c478bd9Sstevel@tonic-gate7: 4547c478bd9Sstevel@tonic-gate brnz,a,pt %o0, 7b ! spin while locked 4557c478bd9Sstevel@tonic-gate ldub [%i0 + T_LOCK], %o0 4567c478bd9Sstevel@tonic-gate ba %xcc, 6b 4577c478bd9Sstevel@tonic-gate ldstub [%i0 + T_LOCK], %o0 ! delay - lock curthread's mutex 4587c478bd9Sstevel@tonic-gate SET_SIZE(_resume_from_idle) 4597c478bd9Sstevel@tonic-gate SET_SIZE(resume) 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate#endif /* lint */ 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate#if defined(lint) 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate/* ARGSUSED */ 4667c478bd9Sstevel@tonic-gatevoid 4677c478bd9Sstevel@tonic-gateresume_from_zombie(kthread_id_t t) 4687c478bd9Sstevel@tonic-gate{} 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate#else /* lint */ 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate ENTRY(resume_from_zombie) 4737c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp ! save ins and locals 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate call __dtrace_probe___sched_off__cpu ! DTrace probe 4767c478bd9Sstevel@tonic-gate mov %i0, %o0 ! arg for DTrace probe 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CPU], %i1 ! cpu pointer 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate flushw ! flushes all but this window 4817c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_PROCP], %i2 ! old procp for mmu ctx 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate ! 4847c478bd9Sstevel@tonic-gate ! Temporarily switch to the idle thread's stack so that 4857c478bd9Sstevel@tonic-gate ! the zombie thread's stack can be reclaimed by the reaper. 4867c478bd9Sstevel@tonic-gate ! 4877c478bd9Sstevel@tonic-gate ldn [%i1 + CPU_IDLE_THREAD], %o2 ! idle thread pointer 4887c478bd9Sstevel@tonic-gate ldn [%o2 + T_SP], %o1 ! get onto idle thread stack 4897c478bd9Sstevel@tonic-gate sub %o1, SA(MINFRAME), %sp ! save room for ins and locals 4907c478bd9Sstevel@tonic-gate clr %fp 4917c478bd9Sstevel@tonic-gate ! 4927c478bd9Sstevel@tonic-gate ! Set the idle thread as the current thread. 4937c478bd9Sstevel@tonic-gate ! Put the zombie on death-row. 4947c478bd9Sstevel@tonic-gate ! 4957c478bd9Sstevel@tonic-gate mov THREAD_REG, %o0 ! save %g7 = curthread for arg 4967c478bd9Sstevel@tonic-gate mov %o2, THREAD_REG ! set %g7 to idle 4977c478bd9Sstevel@tonic-gate stn %g0, [%i1 + CPU_MPCB] ! clear mpcb 4987c478bd9Sstevel@tonic-gate#ifdef CPU_MPCB_PA 4997c478bd9Sstevel@tonic-gate mov -1, %o1 5007c478bd9Sstevel@tonic-gate stx %o1, [%i1 + CPU_MPCB_PA] 5017c478bd9Sstevel@tonic-gate#endif 5027c478bd9Sstevel@tonic-gate call reapq_add ! reapq_add(old_thread); 5037c478bd9Sstevel@tonic-gate stn %o2, [%i1 + CPU_THREAD] ! delay - CPU's thread = idle 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate ! 5067c478bd9Sstevel@tonic-gate ! resume_from_idle args: 5077c478bd9Sstevel@tonic-gate ! %i0 = new thread 5087c478bd9Sstevel@tonic-gate ! %i1 = cpu 5097c478bd9Sstevel@tonic-gate ! %i2 = old proc 5107c478bd9Sstevel@tonic-gate ! %i3 = new proc 5117c478bd9Sstevel@tonic-gate ! 5127c478bd9Sstevel@tonic-gate b _resume_from_idle ! finish job of resume 5137c478bd9Sstevel@tonic-gate ldn [%i0 + T_PROCP], %i3 ! new process 5147c478bd9Sstevel@tonic-gate SET_SIZE(resume_from_zombie) 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate#endif /* lint */ 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate#if defined(lint) 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate/* ARGSUSED */ 5217c478bd9Sstevel@tonic-gatevoid 5227c478bd9Sstevel@tonic-gateresume_from_intr(kthread_id_t t) 5237c478bd9Sstevel@tonic-gate{} 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate#else /* lint */ 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate ENTRY(resume_from_intr) 5287c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp ! save ins and locals 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate flushw ! flushes all but this window 5317c478bd9Sstevel@tonic-gate stn %fp, [THREAD_REG + T_SP] ! delay - save sp 5327c478bd9Sstevel@tonic-gate stn %i7, [THREAD_REG + T_PC] ! save return address 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate ldn [%i0 + T_PC], %i7 ! restore resuming thread's pc 5357c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CPU], %i1 ! cpu pointer 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate ! 5387c478bd9Sstevel@tonic-gate ! Fix CPU structure to indicate new running thread. 5397c478bd9Sstevel@tonic-gate ! The pinned thread we're resuming already has the CPU pointer set. 5407c478bd9Sstevel@tonic-gate ! 5417c478bd9Sstevel@tonic-gate mov THREAD_REG, %l3 ! save old thread 5427c478bd9Sstevel@tonic-gate stn %i0, [%i1 + CPU_THREAD] ! set CPU's thread pointer 5437c478bd9Sstevel@tonic-gate membar #StoreLoad ! synchronize with mutex_exit() 5447c478bd9Sstevel@tonic-gate mov %i0, THREAD_REG ! update global thread register 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate ! 5477c478bd9Sstevel@tonic-gate ! Switch to new thread's stack 5487c478bd9Sstevel@tonic-gate ! 5497c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_SP], %o0 ! restore resuming thread's sp 5507c478bd9Sstevel@tonic-gate sub %o0, SA(MINFRAME), %sp ! in case of intr or trap before restore 5517c478bd9Sstevel@tonic-gate mov %o0, %fp 5527c478bd9Sstevel@tonic-gate clrb [%l3 + T_LOCK] ! clear intr thread's tp->t_lock 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate ! 5557c478bd9Sstevel@tonic-gate ! If we are resuming an interrupt thread, store a timestamp in the 5567c478bd9Sstevel@tonic-gate ! thread structure. 5577c478bd9Sstevel@tonic-gate ! 5587c478bd9Sstevel@tonic-gate lduh [THREAD_REG + T_FLAGS], %o0 5597c478bd9Sstevel@tonic-gate andcc %o0, T_INTR_THREAD, %g0 5607c478bd9Sstevel@tonic-gate bnz,pn %xcc, 0f 5617c478bd9Sstevel@tonic-gate ! 5627c478bd9Sstevel@tonic-gate ! We're resuming a non-interrupt thread. 5637c478bd9Sstevel@tonic-gate ! Clear CPU_INTRCNT and check if cpu_kprunrun set? 5647c478bd9Sstevel@tonic-gate ! 5657c478bd9Sstevel@tonic-gate ldub [%i1 + CPU_KPRUNRUN], %o5 ! delay 5667c478bd9Sstevel@tonic-gate brnz,pn %o5, 3f ! call kpreempt(KPREEMPT_SYNC); 5677c478bd9Sstevel@tonic-gate stub %g0, [%i1 + CPU_INTRCNT] 5687c478bd9Sstevel@tonic-gate1: 5697c478bd9Sstevel@tonic-gate ret ! resume curthread 5707c478bd9Sstevel@tonic-gate restore 5717c478bd9Sstevel@tonic-gate0: 5727c478bd9Sstevel@tonic-gate ! 5737c478bd9Sstevel@tonic-gate ! We're an interrupt thread. Update t_intr_start and cpu_intrcnt 5747c478bd9Sstevel@tonic-gate ! 5757c478bd9Sstevel@tonic-gate add THREAD_REG, T_INTR_START, %o2 5767c478bd9Sstevel@tonic-gate2: 5777c478bd9Sstevel@tonic-gate ldx [%o2], %o1 5787c478bd9Sstevel@tonic-gate rdpr %tick, %o0 5797c478bd9Sstevel@tonic-gate sllx %o0, 1, %o0 5807c478bd9Sstevel@tonic-gate srlx %o0, 1, %o0 ! shift off NPT bit 5817c478bd9Sstevel@tonic-gate casx [%o2], %o1, %o0 5827c478bd9Sstevel@tonic-gate cmp %o0, %o1 5837c478bd9Sstevel@tonic-gate bne,pn %xcc, 2b 5847c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_INTR], %l1 ! delay 5857c478bd9Sstevel@tonic-gate ! Reset cpu_intrcnt if we aren't pinning anyone 5867c478bd9Sstevel@tonic-gate brz,a,pt %l1, 2f 5877c478bd9Sstevel@tonic-gate stub %g0, [%i1 + CPU_INTRCNT] 5887c478bd9Sstevel@tonic-gate2: 5897c478bd9Sstevel@tonic-gate ba,pt %xcc, 1b 5907c478bd9Sstevel@tonic-gate nop 5917c478bd9Sstevel@tonic-gate3: 5927c478bd9Sstevel@tonic-gate ! 5937c478bd9Sstevel@tonic-gate ! We're a non-interrupt thread and cpu_kprunrun is set. call kpreempt. 5947c478bd9Sstevel@tonic-gate ! 5957c478bd9Sstevel@tonic-gate call kpreempt 5967c478bd9Sstevel@tonic-gate mov KPREEMPT_SYNC, %o0 5977c478bd9Sstevel@tonic-gate ba,pt %xcc, 1b 5987c478bd9Sstevel@tonic-gate nop 5997c478bd9Sstevel@tonic-gate SET_SIZE(resume_from_intr) 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate#endif /* lint */ 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate/* 6057c478bd9Sstevel@tonic-gate * thread_start() 6067c478bd9Sstevel@tonic-gate * 6077c478bd9Sstevel@tonic-gate * the current register window was crafted by thread_run() to contain 6087c478bd9Sstevel@tonic-gate * an address of a procedure (in register %i7), and its args in registers 6097c478bd9Sstevel@tonic-gate * %i0 through %i5. a stack trace of this thread will show the procedure 6107c478bd9Sstevel@tonic-gate * that thread_start() invoked at the bottom of the stack. an exit routine 6117c478bd9Sstevel@tonic-gate * is stored in %l0 and called when started thread returns from its called 6127c478bd9Sstevel@tonic-gate * procedure. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate#if defined(lint) 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gatevoid 6187c478bd9Sstevel@tonic-gatethread_start(void) 6197c478bd9Sstevel@tonic-gate{} 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate#else /* lint */ 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate ENTRY(thread_start) 6247c478bd9Sstevel@tonic-gate mov %i0, %o0 6257c478bd9Sstevel@tonic-gate jmpl %i7, %o7 ! call thread_run()'s start() procedure. 6267c478bd9Sstevel@tonic-gate mov %i1, %o1 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate call thread_exit ! destroy thread if it returns. 6297c478bd9Sstevel@tonic-gate nop 6307c478bd9Sstevel@tonic-gate unimp 0 6317c478bd9Sstevel@tonic-gate SET_SIZE(thread_start) 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate#endif /* lint */ 634