1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#if defined(lint) 27#include <sys/types.h> 28#include <sys/cpuvar.h> 29#else /*lint */ 30#include "assym.h" 31#endif /* lint */ 32 33#include <sys/asm_linkage.h> 34#include <sys/privregs.h> 35#include <sys/x_call.h> 36#include <sys/xc_impl.h> 37 38#ifdef TRAPTRACE 39#include <sys/traptrace.h> 40#endif /* TRAPTRACE */ 41 42 43#if defined(lint) 44 45/* ARGSUSED */ 46void 47self_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func) 48{} 49 50#else 51 52/* 53 * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall(). 54 * Emulate the mondo handler - vec_interrupt(). 55 * 56 * Global registers are the Alternate Globals. 57 * Arguments: 58 * %o0 - CPU 59 * ILP32 kernel: 60 * %o5 - function to call 61 * %o1, %o2, %o3, %o4 - arguments 62 * LP64 kernel: 63 * %o3 - function to call 64 * %o1, %o2 - arguments 65 */ 66 ENTRY_NP(self_xcall) 67 ! 68 ! TL>0 handlers are expected to do "retry" 69 ! prepare their return PC and nPC now 70 ! 71 rdpr %tnpc, %g1 72 wrpr %g1, %tpc ! PC <- TNPC[TL] 73 add %g1, 4, %g1 74 wrpr %g1, %tnpc ! nPC <- TNPC[TL] + 4 75 76#ifdef TRAPTRACE 77 TRACE_PTR(%g4, %g6) 78 GET_TRACE_TICK(%g6, %g3) 79 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 80 rdpr %tl, %g6 81 stha %g6, [%g4 + TRAP_ENT_TL]%asi 82 rdpr %tt, %g6 83 stha %g6, [%g4 + TRAP_ENT_TT]%asi 84 stna %o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 85 rdpr %tpc, %g6 86 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 87 rdpr %tstate, %g6 88 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 89 stna %sp, [%g4 + TRAP_ENT_SP]%asi 90 stna %o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1 91 stna %o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2 92 stna %g0, [%g4 + TRAP_ENT_F3]%asi 93 stna %g0, [%g4 + TRAP_ENT_F4]%asi 94 TRACE_NEXT(%g4, %g6, %g3) 95#endif /* TRAPTRACE */ 96 ! 97 ! Load the arguments for the fast trap handler. 98 ! 99 mov %o1, %g1 100 jmp %o3 ! call the fast trap handler 101 mov %o2, %g2 102 /* Not Reached */ 103 SET_SIZE(self_xcall) 104 105#endif /* lint */ 106 107#ifdef TRAPTRACE 108#if defined(lint) 109 110/* ARGSUSED */ 111void 112xc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func, 113 uint64_t arg1, uint64_t arg2) 114{} 115 116#else /* lint */ 117 ENTRY(xc_trace) 118 rdpr %pstate, %g1 119 andn %g1, PSTATE_IE | PSTATE_AM, %g2 120 wrpr %g0, %g2, %pstate /* disable interrupts */ 121 TRACE_PTR(%g3, %g4) 122 GET_TRACE_TICK(%g6, %g4) 123 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 124 stha %g0, [%g3 + TRAP_ENT_TL]%asi 125 set TT_XCALL, %g2 126 or %o0, %g2, %g4 127 stha %g4, [%g3 + TRAP_ENT_TT]%asi 128 stna %o7, [%g3 + TRAP_ENT_TPC]%asi 129 ldn [%o1], %g2 130 stna %g2, [%g3 + TRAP_ENT_SP]%asi /* sp = cpuset */ 131 stna %o2, [%g3 + TRAP_ENT_TR]%asi /* tr = func */ 132 stna %o3, [%g3 + TRAP_ENT_F1]%asi /* f1 = arg1 */ 133 stna %o4, [%g3 + TRAP_ENT_F2]%asi /* f2 = arg2 */ 134 stna %g0, [%g3 + TRAP_ENT_F3]%asi /* f3 = 0 */ 135 stna %i7, [%g3 + TRAP_ENT_F4]%asi /* f4 = xcall caller */ 136 stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tstate = pstate */ 137 TRACE_NEXT(%g2, %g3, %g4) 138/* 139 * In the case of a cpuset of greater size than a long we 140 * grab extra trace buffers just to store the cpuset. 141 * Seems like a waste but popular opinion opted for this 142 * rather than increase the size of the buffer. 143 */ 144#if CPUSET_SIZE > CLONGSIZE 145 add %o1, CPUSET_SIZE, %g5 /* end of cpuset */ 146 clr %o2 1471: 148 TRACE_PTR(%g3, %g4) 149 stha %g0, [%g3 + TRAP_ENT_TL]%asi 150 set TT_XCALL_CONT, %g2 151 or %g2, %o2, %g2 /* continuation # */ 152 stha %g2, [%g3 + TRAP_ENT_TT]%asi 153 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi /* same tick */ 154 stna %g0, [%g3 + TRAP_ENT_TPC]%asi /* clr unused fields */ 155 stna %g0, [%g3 + TRAP_ENT_SP]%asi 156 stna %g0, [%g3 + TRAP_ENT_TR]%asi 157 stxa %g0, [%g3 + TRAP_ENT_TSTATE]%asi 158 stna %g0, [%g3 + TRAP_ENT_F2]%asi 159 stna %g0, [%g3 + TRAP_ENT_F3]%asi 160 stna %g0, [%g3 + TRAP_ENT_F4]%asi 161 ldn [%o1], %g2 162 stna %g2, [%g3 + TRAP_ENT_F1]%asi 163 add %o1, CLONGSIZE, %o1 164 cmp %o1, %g5 165 bge 2f 166 ldn [%o1], %g2 167 stna %g2, [%g3 + TRAP_ENT_F2]%asi 168 add %o1, CLONGSIZE, %o1 169 cmp %o1, %g5 170 bge 2f 171 ldn [%o1], %g2 172 stna %g2, [%g3 + TRAP_ENT_F3]%asi 173 add %o1, CLONGSIZE, %o1 174 cmp %o1, %g5 175 bge 2f 176 ldn [%o1], %g2 177 stna %g2, [%g3 + TRAP_ENT_F4]%asi 178 add %o1, CLONGSIZE, %o1 1792: 180 TRACE_NEXT(%g2, %g3, %g4) 181 cmp %o1, %g5 182 bl 1b 183 inc %o2 184#endif /* CPUSET_SIZE */ 185 retl 186 wrpr %g0, %g1, %pstate /* enable interrupts */ 187 SET_SIZE(xc_trace) 188 189#endif /* lint */ 190#endif /* TRAPTRACE */ 191 192#if defined(lint) 193 194/* ARGSUSED */ 195void 196xt_sync_tl1(uint64_t *cpu_sync_addr) 197{} 198 199#else 200/* 201 * This dummy tl1 function is there to ensure that previously called 202 * xtrap handlers have exececuted. The hardware (mondo dispatch 203 * mechanism) is such that return from xtrap doesn't guarantee execution 204 * of xtrap handler. So, callers can call this xtrap-handler to ensure 205 * that the previous one is complete. This is because the hardware only 206 * can handle 1 mondo at a time - when this mondo is handled, we are sure 207 * that the mondo for the previous xtrap must have been handled. 208 */ 209 ENTRY_NP(xt_sync_tl1) 210 retry 211 SET_SIZE(xt_sync_tl1) 212 213#endif /* lint */ 214