/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #if defined(lint) #include #include #else /*lint */ #include "assym.h" #endif /* lint */ #include #include #include #include #ifdef TRAPTRACE #include #endif /* TRAPTRACE */ #if defined(lint) /* ARGSUSED */ void self_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func) {} #else /* * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall(). * Emulate the mondo handler - vec_interrupt(). * * Global registers are the Alternate Globals. * Arguments: * %o0 - CPU * ILP32 kernel: * %o5 - function to call * %o1, %o2, %o3, %o4 - arguments * LP64 kernel: * %o3 - function to call * %o1, %o2 - arguments */ ENTRY_NP(self_xcall) ! ! TL>0 handlers are expected to do "retry" ! prepare their return PC and nPC now ! rdpr %tnpc, %g1 wrpr %g1, %tpc ! PC <- TNPC[TL] add %g1, 4, %g1 wrpr %g1, %tnpc ! nPC <- TNPC[TL] + 4 #ifdef TRAPTRACE TRACE_PTR(%g4, %g6) GET_TRACE_TICK(%g6) stxa %g6, [%g4 + TRAP_ENT_TICK]%asi rdpr %tl, %g6 stha %g6, [%g4 + TRAP_ENT_TL]%asi rdpr %tt, %g6 stha %g6, [%g4 + TRAP_ENT_TT]%asi stna %o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler rdpr %tpc, %g6 stna %g6, [%g4 + TRAP_ENT_TPC]%asi rdpr %tstate, %g6 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi stna %sp, [%g4 + TRAP_ENT_SP]%asi stna %o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1 stna %o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2 stna %g0, [%g4 + TRAP_ENT_F3]%asi stna %g0, [%g4 + TRAP_ENT_F4]%asi TRACE_NEXT(%g4, %g6, %g3) #endif /* TRAPTRACE */ ! ! Load the arguments for the fast trap handler. ! mov %o1, %g1 jmp %o3 ! call the fast trap handler mov %o2, %g2 /* Not Reached */ SET_SIZE(self_xcall) #endif /* lint */ #ifdef TRAPTRACE #if defined(lint) /* ARGSUSED */ void xc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func, uint64_t arg1, uint64_t arg2) {} #else /* lint */ ENTRY(xc_trace) rdpr %pstate, %g1 andn %g1, PSTATE_IE | PSTATE_AM, %g2 wrpr %g0, %g2, %pstate /* disable interrupts */ TRACE_PTR(%g3, %g4) GET_TRACE_TICK(%g6) stxa %g6, [%g3 + TRAP_ENT_TICK]%asi stha %g0, [%g3 + TRAP_ENT_TL]%asi set TT_XCALL, %g2 or %o0, %g2, %g4 stha %g4, [%g3 + TRAP_ENT_TT]%asi stna %o7, [%g3 + TRAP_ENT_TPC]%asi ldn [%o1], %g2 stna %g2, [%g3 + TRAP_ENT_SP]%asi /* sp = cpuset */ stna %o2, [%g3 + TRAP_ENT_TR]%asi /* tr = func */ stna %o3, [%g3 + TRAP_ENT_F1]%asi /* f1 = arg1 */ stna %o4, [%g3 + TRAP_ENT_F2]%asi /* f2 = arg2 */ stna %g0, [%g3 + TRAP_ENT_F3]%asi /* f3 = 0 */ stna %i7, [%g3 + TRAP_ENT_F4]%asi /* f4 = xcall caller */ stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tstate = pstate */ TRACE_NEXT(%g2, %g3, %g4) /* * In the case of a cpuset of greater size than a long we * grab extra trace buffers just to store the cpuset. * Seems like a waste but popular opinion opted for this * rather than increase the size of the buffer. */ #if CPUSET_SIZE > CLONGSIZE add %o1, CPUSET_SIZE, %g5 /* end of cpuset */ clr %o2 1: TRACE_PTR(%g3, %g4) stha %g0, [%g3 + TRAP_ENT_TL]%asi set TT_XCALL_CONT, %g2 or %g2, %o2, %g2 /* continuation # */ stha %g2, [%g3 + TRAP_ENT_TT]%asi stxa %g6, [%g3 + TRAP_ENT_TICK]%asi /* same tick */ stna %g0, [%g3 + TRAP_ENT_TPC]%asi /* clr unused fields */ stna %g0, [%g3 + TRAP_ENT_SP]%asi stna %g0, [%g3 + TRAP_ENT_TR]%asi stxa %g0, [%g3 + TRAP_ENT_TSTATE]%asi stna %g0, [%g3 + TRAP_ENT_F2]%asi stna %g0, [%g3 + TRAP_ENT_F3]%asi stna %g0, [%g3 + TRAP_ENT_F4]%asi ldn [%o1], %g2 stna %g2, [%g3 + TRAP_ENT_F1]%asi add %o1, CLONGSIZE, %o1 cmp %o1, %g5 bge 2f ldn [%o1], %g2 stna %g2, [%g3 + TRAP_ENT_F2]%asi add %o1, CLONGSIZE, %o1 cmp %o1, %g5 bge 2f ldn [%o1], %g2 stna %g2, [%g3 + TRAP_ENT_F3]%asi add %o1, CLONGSIZE, %o1 cmp %o1, %g5 bge 2f ldn [%o1], %g2 stna %g2, [%g3 + TRAP_ENT_F4]%asi add %o1, CLONGSIZE, %o1 2: TRACE_NEXT(%g2, %g3, %g4) cmp %o1, %g5 bl 1b inc %o2 #endif /* CPUSET_SIZE */ retl wrpr %g0, %g1, %pstate /* enable interrupts */ SET_SIZE(xc_trace) #endif /* lint */ #endif /* TRAPTRACE */ #if defined(lint) /* ARGSUSED */ void xt_sync_tl1(uint64_t *cpu_sync_addr) {} #else /* * This dummy tl1 function is there to ensure that previously called * xtrap handlers have exececuted. The hardware (mondo dispatch * mechanism) is such that return from xtrap doesn't guarantee execution * of xtrap handler. So, callers can call this xtrap-handler to ensure * that the previous one is complete. This is because the hardware only * can handle 1 mondo at a time - when this mondo is handled, we are sure * that the mondo for the previous xtrap must have been handled. */ ENTRY_NP(xt_sync_tl1) retry SET_SIZE(xt_sync_tl1) #endif /* lint */