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#include "assym.h" 27 28#include <sys/asm_linkage.h> 29#include <sys/privregs.h> 30#include <sys/x_call.h> 31#include <sys/xc_impl.h> 32#include <sys/machthread.h> 33#include <sys/hypervisor_api.h> 34 35#ifdef TRAPTRACE 36#include <sys/traptrace.h> 37#endif /* TRAPTRACE */ 38 39 40/* 41 * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall(). 42 * Emulate the mondo handler - vec_interrupt(). 43 * 44 * Global registers are the Alternate Globals. 45 * Arguments: 46 * %o0 - CPU 47 * ILP32 kernel: 48 * %o5 - function to call 49 * %o1, %o2, %o3, %o4 - arguments 50 * LP64 kernel: 51 * %o3 - function to call 52 * %o1, %o2 - arguments 53 */ 54 ENTRY_NP(self_xcall) 55 ! 56 ! TL>0 handlers are expected to do "retry" 57 ! prepare their return PC and nPC now 58 ! 59 rdpr %tnpc, %g1 60 wrpr %g1, %tpc ! PC <- TNPC[TL] 61 add %g1, 4, %g1 62 wrpr %g1, %tnpc ! nPC <- TNPC[TL] + 4 63 64#ifdef TRAPTRACE 65 TRACE_PTR(%g4, %g6) 66 GET_TRACE_TICK(%g6, %g3) 67 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 68 rdpr %tl, %g6 69 stha %g6, [%g4 + TRAP_ENT_TL]%asi 70 rdpr %tt, %g6 71 stha %g6, [%g4 + TRAP_ENT_TT]%asi 72 stna %o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 73 rdpr %tpc, %g6 74 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 75 rdpr %tstate, %g6 76 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 77 stna %sp, [%g4 + TRAP_ENT_SP]%asi 78 stna %o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1 79 stna %o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2 80 stna %g0, [%g4 + TRAP_ENT_F3]%asi 81 stna %g0, [%g4 + TRAP_ENT_F4]%asi 82 TRACE_NEXT(%g4, %g6, %g3) 83#endif /* TRAPTRACE */ 84 ! 85 ! Load the arguments for the fast trap handler. 86 ! 87 mov %o1, %g1 88 jmp %o3 ! call the fast trap handler 89 mov %o2, %g2 90 /* Not Reached */ 91 SET_SIZE(self_xcall) 92 93#ifdef TRAPTRACE 94 ENTRY(xc_trace) 95 rdpr %pstate, %g1 96 andn %g1, PSTATE_IE | PSTATE_AM, %g2 97 wrpr %g0, %g2, %pstate /* disable interrupts */ 98 TRACE_PTR(%g3, %g4) 99 GET_TRACE_TICK(%g6, %g4) 100 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 101 stha %g0, [%g3 + TRAP_ENT_TL]%asi 102 set TT_XCALL, %g2 103 or %o0, %g2, %g4 104 stha %g4, [%g3 + TRAP_ENT_TT]%asi 105 stna %o7, [%g3 + TRAP_ENT_TPC]%asi 106 ldn [%o1], %g2 107 stna %g2, [%g3 + TRAP_ENT_SP]%asi /* sp = cpuset */ 108 stna %o2, [%g3 + TRAP_ENT_TR]%asi /* tr = func */ 109 stna %o3, [%g3 + TRAP_ENT_F1]%asi /* f1 = arg1 */ 110 stna %o4, [%g3 + TRAP_ENT_F2]%asi /* f2 = arg2 */ 111 stna %g0, [%g3 + TRAP_ENT_F3]%asi /* f3 = 0 */ 112 stna %i7, [%g3 + TRAP_ENT_F4]%asi /* f4 = xcall caller */ 113 stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tstate = pstate */ 114 TRACE_NEXT(%g2, %g3, %g4) 115/* 116 * In the case of a cpuset of greater size than a long we 117 * grab extra trace buffers just to store the cpuset. 118 * Seems like a waste but popular opinion opted for this 119 * rather than increase the size of the buffer. 120 */ 121#if CPUSET_SIZE > CLONGSIZE 122 add %o1, CPUSET_SIZE, %g5 /* end of cpuset */ 123 clr %o2 1241: 125 TRACE_PTR(%g3, %g4) 126 stha %g0, [%g3 + TRAP_ENT_TL]%asi 127 set TT_XCALL_CONT, %g2 128 or %g2, %o2, %g2 /* continuation # */ 129 stha %g2, [%g3 + TRAP_ENT_TT]%asi 130 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi /* same tick */ 131 stna %g0, [%g3 + TRAP_ENT_TPC]%asi /* clr unused fields */ 132 stna %g0, [%g3 + TRAP_ENT_SP]%asi 133 stna %g0, [%g3 + TRAP_ENT_TR]%asi 134 stxa %g0, [%g3 + TRAP_ENT_TSTATE]%asi 135 stna %g0, [%g3 + TRAP_ENT_F2]%asi 136 stna %g0, [%g3 + TRAP_ENT_F3]%asi 137 stna %g0, [%g3 + TRAP_ENT_F4]%asi 138 ldn [%o1], %g2 139 stna %g2, [%g3 + TRAP_ENT_F1]%asi 140 add %o1, CLONGSIZE, %o1 141 cmp %o1, %g5 142 bge 2f 143 ldn [%o1], %g2 144 stna %g2, [%g3 + TRAP_ENT_F2]%asi 145 add %o1, CLONGSIZE, %o1 146 cmp %o1, %g5 147 bge 2f 148 ldn [%o1], %g2 149 stna %g2, [%g3 + TRAP_ENT_F3]%asi 150 add %o1, CLONGSIZE, %o1 151 cmp %o1, %g5 152 bge 2f 153 ldn [%o1], %g2 154 stna %g2, [%g3 + TRAP_ENT_F4]%asi 155 add %o1, CLONGSIZE, %o1 1562: 157 TRACE_NEXT(%g2, %g3, %g4) 158 cmp %o1, %g5 159 bl 1b 160 inc %o2 161#endif /* CPUSET_SIZE */ 162 retl 163 wrpr %g0, %g1, %pstate /* enable interrupts */ 164 SET_SIZE(xc_trace) 165 166#endif /* TRAPTRACE */ 167 168/* 169 * Setup interrupt dispatch data registers 170 * Entry: 171 * %o0 - function or inumber to call 172 * %o1, %o2 - arguments (2 uint64_t's) 173 */ 174 ENTRY(init_mondo) 175 ALTENTRY(init_mondo_nocheck) 176 CPU_ADDR(%g1, %g4) ! load CPU struct addr 177 add %g1, CPU_MCPU, %g1 178 ldx [%g1 + MCPU_MONDO_DATA], %g1 179 stx %o0, [%g1] 180 stx %o1, [%g1+8] 181 stx %o2, [%g1+0x10] 182 stx %g0, [%g1+0x18] 183 stx %g0, [%g1+0x20] 184 stx %g0, [%g1+0x28] 185 stx %g0, [%g1+0x30] 186 stx %g0, [%g1+0x38] 187 retl 188 membar #Sync ! allowed to be in the delay slot 189 SET_SIZE(init_mondo) 190 191/* 192 * Ship mondo to cpuid 193 */ 194 ENTRY_NP(shipit) 195 /* For now use dummy interface: cpu# func arg1 arg2 */ 196 CPU_ADDR(%g1, %g4) 197 add %g1, CPU_MCPU, %g1 198 ldx [%g1 + MCPU_MONDO_DATA_RA], %o2 199 mov HV_INTR_SEND, %o5 200 ta FAST_TRAP 201 retl 202 membar #Sync 203 SET_SIZE(shipit) 204 205/* 206 * Get cpu structure 207 * Entry: 208 * %o0 - register for CPU_ADDR macro 209 * %o1 - scratch for CPU_ADDR macro 210 */ 211 ENTRY(get_cpuaddr) 212 CPU_ADDR(%o0, %o1) ! %o0 == CPU struct addr 213 retl 214 nop 215 SET_SIZE(get_cpuaddr) 216 217/* 218 * This is to ensure that previously called xtrap handlers have executed on 219 * sun4v. We zero out the byte corresponding to its cpuid in the 220 * array passed to us from xt_sync(), so the sender knows the previous 221 * mondo has been executed. 222 * Register: 223 * %g1 - Addr of the cpu_sync array. 224 */ 225 ENTRY_NP(xt_sync_tl1) 226 CPU_INDEX(%g3, %g4) /* %g3 = cpu id */ 227 stb %g0, [%g1 + %g3] 228 retry 229 SET_SIZE(xt_sync_tl1) 230 231