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