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