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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#if defined(lint) 30#include <sys/types.h> 31#include <sys/cpuvar.h> 32#else /*lint */ 33#include "assym.h" 34#endif /* lint */ 35 36#include <sys/asm_linkage.h> 37#include <sys/privregs.h> 38#include <sys/x_call.h> 39#include <sys/xc_impl.h> 40#include <sys/machthread.h> 41#include <sys/hypervisor_api.h> 42 43#ifdef TRAPTRACE 44#include <sys/traptrace.h> 45#endif /* TRAPTRACE */ 46 47 48#if defined(lint) 49 50/* ARGSUSED */ 51void 52self_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func) 53{} 54 55#else 56 57/* 58 * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall(). 59 * Emulate the mondo handler - vec_interrupt(). 60 * 61 * Global registers are the Alternate Globals. 62 * Arguments: 63 * %o0 - CPU 64 * ILP32 kernel: 65 * %o5 - function to call 66 * %o1, %o2, %o3, %o4 - arguments 67 * LP64 kernel: 68 * %o3 - function to call 69 * %o1, %o2 - arguments 70 */ 71 ENTRY_NP(self_xcall) 72 ! 73 ! TL>0 handlers are expected to do "retry" 74 ! prepare their return PC and nPC now 75 ! 76 rdpr %tnpc, %g1 77 wrpr %g1, %tpc ! PC <- TNPC[TL] 78 add %g1, 4, %g1 79 wrpr %g1, %tnpc ! nPC <- TNPC[TL] + 4 80 81#ifdef TRAPTRACE 82 TRACE_PTR(%g4, %g6) 83 GET_TRACE_TICK(%g6) 84 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 85 rdpr %tl, %g6 86 stha %g6, [%g4 + TRAP_ENT_TL]%asi 87 rdpr %tt, %g6 88 stha %g6, [%g4 + TRAP_ENT_TT]%asi 89 stna %o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 90 rdpr %tpc, %g6 91 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 92 rdpr %tstate, %g6 93 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 94 stna %sp, [%g4 + TRAP_ENT_SP]%asi 95 stna %o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1 96 stna %o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2 97 stna %g0, [%g4 + TRAP_ENT_F3]%asi 98 stna %g0, [%g4 + TRAP_ENT_F4]%asi 99 TRACE_NEXT(%g4, %g6, %g3) 100#endif /* TRAPTRACE */ 101 ! 102 ! Load the arguments for the fast trap handler. 103 ! 104 mov %o1, %g1 105 jmp %o3 ! call the fast trap handler 106 mov %o2, %g2 107 /* Not Reached */ 108 SET_SIZE(self_xcall) 109 110#endif /* lint */ 111 112#ifdef TRAPTRACE 113#if defined(lint) 114 115/* ARGSUSED */ 116void 117xc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func, 118 uint64_t arg1, uint64_t arg2) 119{} 120 121#else /* lint */ 122 ENTRY(xc_trace) 123 rdpr %pstate, %g1 124 andn %g1, PSTATE_IE | PSTATE_AM, %g2 125 wrpr %g0, %g2, %pstate /* disable interrupts */ 126 TRACE_PTR(%g3, %g4) 127 GET_TRACE_TICK(%g6) 128 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 129 stha %g0, [%g3 + TRAP_ENT_TL]%asi 130 set TT_XCALL, %g2 131 or %o0, %g2, %g4 132 stha %g4, [%g3 + TRAP_ENT_TT]%asi 133 stna %o7, [%g3 + TRAP_ENT_TPC]%asi 134 ldn [%o1], %g2 135 stna %g2, [%g3 + TRAP_ENT_SP]%asi /* sp = cpuset */ 136 stna %o2, [%g3 + TRAP_ENT_TR]%asi /* tr = func */ 137 stna %o3, [%g3 + TRAP_ENT_F1]%asi /* f1 = arg1 */ 138 stna %o4, [%g3 + TRAP_ENT_F2]%asi /* f2 = arg2 */ 139 stna %g0, [%g3 + TRAP_ENT_F3]%asi /* f3 = 0 */ 140 stna %i7, [%g3 + TRAP_ENT_F4]%asi /* f4 = xcall caller */ 141 stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tstate = pstate */ 142 TRACE_NEXT(%g2, %g3, %g4) 143/* 144 * In the case of a cpuset of greater size than a long we 145 * grab extra trace buffers just to store the cpuset. 146 * Seems like a waste but popular opinion opted for this 147 * rather than increase the size of the buffer. 148 */ 149#if CPUSET_SIZE > CLONGSIZE 150 add %o1, CPUSET_SIZE, %g5 /* end of cpuset */ 151 clr %o2 1521: 153 TRACE_PTR(%g3, %g4) 154 stha %g0, [%g3 + TRAP_ENT_TL]%asi 155 set TT_XCALL_CONT, %g2 156 or %g2, %o2, %g2 /* continuation # */ 157 stha %g2, [%g3 + TRAP_ENT_TT]%asi 158 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi /* same tick */ 159 stna %g0, [%g3 + TRAP_ENT_TPC]%asi /* clr unused fields */ 160 stna %g0, [%g3 + TRAP_ENT_SP]%asi 161 stna %g0, [%g3 + TRAP_ENT_TR]%asi 162 stxa %g0, [%g3 + TRAP_ENT_TSTATE]%asi 163 stna %g0, [%g3 + TRAP_ENT_F2]%asi 164 stna %g0, [%g3 + TRAP_ENT_F3]%asi 165 stna %g0, [%g3 + TRAP_ENT_F4]%asi 166 ldn [%o1], %g2 167 stna %g2, [%g3 + TRAP_ENT_F1]%asi 168 add %o1, CLONGSIZE, %o1 169 cmp %o1, %g5 170 bge 2f 171 ldn [%o1], %g2 172 stna %g2, [%g3 + TRAP_ENT_F2]%asi 173 add %o1, CLONGSIZE, %o1 174 cmp %o1, %g5 175 bge 2f 176 ldn [%o1], %g2 177 stna %g2, [%g3 + TRAP_ENT_F3]%asi 178 add %o1, CLONGSIZE, %o1 179 cmp %o1, %g5 180 bge 2f 181 ldn [%o1], %g2 182 stna %g2, [%g3 + TRAP_ENT_F4]%asi 183 add %o1, CLONGSIZE, %o1 1842: 185 TRACE_NEXT(%g2, %g3, %g4) 186 cmp %o1, %g5 187 bl 1b 188 inc %o2 189#endif /* CPUSET_SIZE */ 190 retl 191 wrpr %g0, %g1, %pstate /* enable interrupts */ 192 SET_SIZE(xc_trace) 193 194#endif /* lint */ 195#endif /* TRAPTRACE */ 196 197#if defined(lint) 198 199/*ARGSUSED*/ 200void 201init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 202{} 203 204/*ARGSUSED*/ 205int 206shipit(int n, uint64_t cpuid) 207{ return(0); } 208 209#else /* lint */ 210/* 211 * Setup interrupt dispatch data registers 212 * Entry: 213 * %o0 - function or inumber to call 214 * %o1, %o2 - arguments (2 uint64_t's) 215 */ 216 ENTRY(init_mondo) 217 ALTENTRY(init_mondo_nocheck) 218 CPU_ADDR(%g1, %g4) ! load CPU struct addr 219 add %g1, CPU_MCPU, %g1 220 ldx [%g1 + MCPU_MONDO_DATA], %g1 221 stx %o0, [%g1] 222 stx %o1, [%g1+8] 223 stx %o2, [%g1+0x10] 224 stx %g0, [%g1+0x18] 225 stx %g0, [%g1+0x20] 226 stx %g0, [%g1+0x28] 227 stx %g0, [%g1+0x30] 228 stx %g0, [%g1+0x38] 229 retl 230 membar #Sync ! allowed to be in the delay slot 231 SET_SIZE(init_mondo) 232 233/* 234 * Ship mondo to cpuid 235 */ 236 ENTRY_NP(shipit) 237 /* For now use dummy interface: cpu# func arg1 arg2 */ 238 CPU_ADDR(%g1, %g4) 239 add %g1, CPU_MCPU, %g1 240 ldx [%g1 + MCPU_MONDO_DATA_RA], %o2 241 mov HV_INTR_SEND, %o5 242 ta FAST_TRAP 243 retl 244 membar #Sync 245 SET_SIZE(shipit) 246 247#endif /* lint */ 248 249#if defined(lint) 250 251/*ARGSUSED*/ 252uint64_t 253get_cpuaddr(uint64_t reg, uint64_t scr) 254{ return (0);} 255 256#else /* lint */ 257/* 258 * Get cpu structure 259 * Entry: 260 * %o0 - register for CPU_ADDR macro 261 * %o1 - scratch for CPU_ADDR macro 262 */ 263 ENTRY(get_cpuaddr) 264 CPU_ADDR(%o0, %o1) ! %o0 == CPU struct addr 265 retl 266 nop 267 SET_SIZE(get_cpuaddr) 268 269#endif /* lint */ 270 271#if defined(lint) 272/* ARGSUSED */ 273void 274xt_sync_tl1(uint64_t *cpu_sync_addr) 275{} 276 277#else /* lint */ 278/* 279 * This is to ensure that previously called xtrap handlers have executed on 280 * sun4v. We zero out the byte corresponding to its cpuid in the 281 * array passed to us from xt_sync(), so the sender knows the previous 282 * mondo has been executed. 283 * Register: 284 * %g1 - Addr of the cpu_sync array. 285 */ 286 ENTRY_NP(xt_sync_tl1) 287 CPU_INDEX(%g3, %g4) /* %g3 = cpu id */ 288 stb %g0, [%g1 + %g3] 289 retry 290 SET_SIZE(xt_sync_tl1) 291 292#endif /* lint */ 293