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