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 #ifndef _SYS_XC_IMPL_H 28 #define _SYS_XC_IMPL_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #ifndef _ASM 37 38 #include <sys/note.h> 39 #include <sys/cpu_module.h> 40 #include <sys/panic.h> /* for panic_quiesce */ 41 42 extern cpuset_t cpu_ready_set; /* cpus ready for x-call */ 43 extern void send_self_xcall(struct cpu *, uint64_t, uint64_t, xcfunc_t *); 44 extern uint_t xc_loop(void); 45 extern uint_t xc_serv(void); 46 extern void xc_stop(struct regs *); 47 #ifdef TRAPTRACE 48 extern void xc_trace(uint_t, cpuset_t *, xcfunc_t *, uint64_t, uint64_t); 49 #endif /* TRAPTRACE */ 50 extern uint64_t xc_func_time_limit; 51 52 extern uint_t sendmondo_in_recover; 53 54 /* 55 * Lightweight XTrap Sync 56 */ 57 #ifdef sun4v 58 #define XT_SYNC_ONE(cpuid) \ 59 { \ 60 cpuset_t set; \ 61 CPUSET_ONLY(set, cpuid); \ 62 xt_sync(set); \ 63 } 64 65 #define XT_SYNC_SOME(cpuset) \ 66 { \ 67 xt_sync(cpuset); \ 68 } 69 70 #else /* sun4v */ 71 72 #define XT_SYNC_ONE(cpuid) \ 73 { \ 74 init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \ 75 send_one_mondo(cpuid); \ 76 } 77 78 #define XT_SYNC_SOME(cpuset) \ 79 { \ 80 init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \ 81 send_mondo_set(cpuset); \ 82 } 83 84 #endif /* sun4v */ 85 86 /* 87 * Protect the dispatching of the mondo vector 88 */ 89 90 #define XC_SPL_ENTER(cpuid, opl) \ 91 { \ 92 opl = splr(XCALL_PIL); \ 93 cpuid = CPU->cpu_id; \ 94 if (xc_spl_enter[cpuid] && !panic_quiesce) \ 95 cmn_err(CE_PANIC, "XC SPL ENTER already entered (0x%x)",\ 96 cpuid); \ 97 xc_spl_enter[cpuid] = 1; \ 98 } 99 100 #define XC_SPL_EXIT(cpuid, opl) \ 101 { \ 102 ASSERT(xc_spl_enter[cpuid] != 0); \ 103 xc_spl_enter[cpuid] = 0; \ 104 splx(opl); \ 105 } 106 107 /* 108 * set up a x-call request 109 */ 110 #define XC_SETUP(cpuid, func, arg1, arg2) \ 111 { \ 112 xc_mbox[cpuid].xc_func = func; \ 113 xc_mbox[cpuid].xc_arg1 = arg1; \ 114 xc_mbox[cpuid].xc_arg2 = arg2; \ 115 xc_mbox[cpuid].xc_state = XC_DOIT; \ 116 } 117 118 /* 119 * set up x-call requests to the cpuset 120 */ 121 #define SEND_MBOX_ONLY(xc_cpuset, func, arg1, arg2, lcx, state) \ 122 { \ 123 int pix; \ 124 cpuset_t tmpset = xc_cpuset; \ 125 for (pix = 0; pix < NCPU; pix++) { \ 126 if (CPU_IN_SET(tmpset, pix)) { \ 127 ASSERT(MUTEX_HELD(&xc_sys_mutex)); \ 128 ASSERT(CPU_IN_SET(xc_mbox[lcx].xc_cpuset, pix));\ 129 ASSERT(xc_mbox[pix].xc_state == state); \ 130 XC_SETUP(pix, func, arg1, arg2); \ 131 membar_stld(); \ 132 CPUSET_DEL(tmpset, pix); \ 133 CPU_STATS_ADDQ(CPU, sys, xcalls, 1); \ 134 if (CPUSET_ISNULL(tmpset)) \ 135 break; \ 136 } \ 137 } \ 138 } 139 140 /* 141 * set up and notify a x-call request to the cpuset 142 */ 143 #define SEND_MBOX_MONDO(xc_cpuset, func, arg1, arg2, state) \ 144 { \ 145 int pix; \ 146 cpuset_t tmpset = xc_cpuset; \ 147 for (pix = 0; pix < NCPU; pix++) { \ 148 if (CPU_IN_SET(tmpset, pix)) { \ 149 ASSERT(xc_mbox[pix].xc_state == state); \ 150 XC_SETUP(pix, func, arg1, arg2); \ 151 membar_stld(); \ 152 send_one_mondo(pix); \ 153 CPUSET_DEL(tmpset, pix); \ 154 if (CPUSET_ISNULL(tmpset)) \ 155 break; \ 156 } \ 157 } \ 158 } 159 160 /* 161 * wait x-call requests to be completed 162 */ 163 #define WAIT_MBOX_DONE(xc_cpuset, lcx, state, sync) \ 164 { \ 165 int pix; \ 166 uint64_t loop_cnt = 0; \ 167 cpuset_t tmpset; \ 168 cpuset_t recv_cpuset; \ 169 int first_time = 1; \ 170 CPUSET_ZERO(recv_cpuset); \ 171 while (!CPUSET_ISEQUAL(recv_cpuset, xc_cpuset)) { \ 172 tmpset = xc_cpuset; \ 173 for (pix = 0; pix < NCPU; pix++) { \ 174 if (CPU_IN_SET(tmpset, pix)) { \ 175 if (xc_mbox[pix].xc_state == state) { \ 176 CPUSET_ADD(recv_cpuset, pix); \ 177 } \ 178 } \ 179 CPUSET_DEL(tmpset, pix); \ 180 if (CPUSET_ISNULL(tmpset)) \ 181 break; \ 182 } \ 183 if (loop_cnt++ > xc_func_time_limit) { \ 184 if (sendmondo_in_recover) { \ 185 drv_usecwait(1); \ 186 loop_cnt = 0; \ 187 continue; \ 188 } \ 189 _NOTE(CONSTANTCONDITION) \ 190 if (sync && first_time) { \ 191 XT_SYNC_SOME(xc_cpuset); \ 192 first_time = 0; \ 193 loop_cnt = 0; \ 194 continue; \ 195 } \ 196 panic("WAIT_MBOX_DONE() timeout, " \ 197 "recv_cpuset 0x%lx, xc cpuset 0x%lx ", \ 198 *(ulong_t *)&recv_cpuset, \ 199 *(ulong_t *)&xc_cpuset); \ 200 } \ 201 } \ 202 } 203 204 /* 205 * xc_state flags 206 */ 207 enum xc_states { 208 XC_IDLE = 0, /* not in the xc_loop(); set by xc_loop */ 209 XC_ENTER, /* entering xc_loop(); set by xc_attention */ 210 XC_WAIT, /* entered xc_loop(); set by xc_loop */ 211 XC_DOIT, /* xcall request; set by xc_one, xc_some, or xc_all */ 212 XC_EXIT /* exiting xc_loop(); set by xc_dismissed */ 213 }; 214 215 /* 216 * user provided handlers must be pc aligned 217 */ 218 #define PC_ALIGN 4 219 220 #ifdef TRAPTRACE 221 #define XC_TRACE(type, cpus, func, arg1, arg2) \ 222 xc_trace((type), (cpus), (func), (arg1), (arg2)) 223 #else /* !TRAPTRACE */ 224 #define XC_TRACE(type, cpus, func, arg1, arg2) 225 #endif /* TRAPTRACE */ 226 227 #ifdef DEBUG 228 /* 229 * get some statistics when xc/xt routines are called 230 */ 231 232 #define XC_STAT_INC(a) (a)++; 233 #define XC_CPUID 0 234 235 #define XT_ONE_SELF 1 236 #define XT_ONE_OTHER 2 237 #define XT_SOME_SELF 3 238 #define XT_SOME_OTHER 4 239 #define XT_ALL_SELF 5 240 #define XT_ALL_OTHER 6 241 #define XC_ONE_SELF 7 242 #define XC_ONE_OTHER 8 243 #define XC_ONE_OTHER_H 9 244 #define XC_SOME_SELF 10 245 #define XC_SOME_OTHER 11 246 #define XC_SOME_OTHER_H 12 247 #define XC_ALL_SELF 13 248 #define XC_ALL_OTHER 14 249 #define XC_ALL_OTHER_H 15 250 #define XC_ATTENTION 16 251 #define XC_DISMISSED 17 252 #define XC_LOOP_ENTER 18 253 #define XC_LOOP_DOIT 19 254 #define XC_LOOP_EXIT 20 255 256 extern uint_t x_dstat[NCPU][XC_LOOP_EXIT+1]; 257 extern uint_t x_rstat[NCPU][4]; 258 #define XC_LOOP 1 259 #define XC_SERV 2 260 261 #define XC_STAT_INIT(cpuid) \ 262 { \ 263 x_dstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \ 264 x_rstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \ 265 } 266 267 #else /* DEBUG */ 268 269 #define XC_STAT_INIT(cpuid) 270 #define XC_STAT_INC(a) 271 #define XC_ATTENTION_CPUSET(x) 272 #define XC_DISMISSED_CPUSET(x) 273 274 #endif /* DEBUG */ 275 276 #endif /* !_ASM */ 277 278 /* 279 * Maximum delay in milliseconds to wait for send_mondo to complete 280 */ 281 #define XC_SEND_MONDO_MSEC 1000 282 283 #ifdef __cplusplus 284 } 285 #endif 286 287 #endif /* _SYS_XC_IMPL_H */ 288