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