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