xref: /illumos-gate/usr/src/uts/sun4/sys/xc_impl.h (revision e4d060fb4c00d44cd578713eb9a921f594b733b8)
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 2006 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 			CPUSET_DEL(tmpset, pix);		\
152 			if (CPUSET_ISNULL(tmpset))		\
153 				break;				\
154 		}						\
155 	}							\
156 	membar_stld();						\
157 	send_mondo_set(xc_cpuset);				\
158 }
159 
160 /*
161  * set up and notify a x-call request, signalling xc_cpuset
162  * cpus to enter xc_loop()
163  */
164 #define	SEND_MBOX_MONDO_XC_ENTER(xc_cpuset)			\
165 {								\
166 	int pix;						\
167 	cpuset_t  tmpset = xc_cpuset;				\
168 	for (pix = 0; pix < NCPU; pix++) {			\
169 		if (CPU_IN_SET(tmpset, pix)) {			\
170 			ASSERT(xc_mbox[pix].xc_state ==		\
171 			    XC_IDLE);				\
172 			xc_mbox[pix].xc_state = XC_ENTER;	\
173 			CPUSET_DEL(tmpset, pix);		\
174 			if (CPUSET_ISNULL(tmpset)) {		\
175 				break;				\
176 			}					\
177 		}						\
178 	}							\
179 	send_mondo_set(xc_cpuset);				\
180 }
181 
182 /*
183  * wait x-call requests to be completed
184  */
185 #define	WAIT_MBOX_DONE(xc_cpuset, lcx, state, sync)			\
186 {									\
187 	int pix;							\
188 	uint64_t loop_cnt = 0;						\
189 	cpuset_t tmpset;						\
190 	cpuset_t  recv_cpuset;						\
191 	int first_time = 1;						\
192 	CPUSET_ZERO(recv_cpuset);					\
193 	while (!CPUSET_ISEQUAL(recv_cpuset, xc_cpuset)) {		\
194 		tmpset = xc_cpuset;					\
195 		for (pix = 0; pix < NCPU; pix++) {			\
196 			if (CPU_IN_SET(tmpset, pix)) {			\
197 				if (xc_mbox[pix].xc_state == state) {	\
198 					CPUSET_ADD(recv_cpuset, pix);	\
199 				}					\
200 			}						\
201 			CPUSET_DEL(tmpset, pix);			\
202 			if (CPUSET_ISNULL(tmpset))			\
203 				break;					\
204 		}							\
205 		if (loop_cnt++ > xc_func_time_limit) {			\
206 			if (sendmondo_in_recover) {			\
207 				drv_usecwait(1);			\
208 				loop_cnt = 0;				\
209 				continue;				\
210 			}						\
211 			_NOTE(CONSTANTCONDITION)			\
212 			if (sync && first_time) {			\
213 				XT_SYNC_SOME(xc_cpuset);		\
214 				first_time = 0;				\
215 				loop_cnt = 0;				\
216 				continue;				\
217 			}						\
218 			panic("WAIT_MBOX_DONE() timeout, "		\
219 				"recv_cpuset 0x%lx, xc cpuset 0x%lx ",	\
220 				*(ulong_t *)&recv_cpuset,		\
221 				*(ulong_t *)&xc_cpuset);		\
222 		}							\
223 	}								\
224 }
225 
226 /*
227  * xc_state flags
228  */
229 enum xc_states {
230 	XC_IDLE = 0,	/* not in the xc_loop(); set by xc_loop */
231 	XC_ENTER,	/* entering xc_loop(); set by xc_attention */
232 	XC_WAIT,	/* entered xc_loop(); set by xc_loop */
233 	XC_DOIT,	/* xcall request; set by xc_one, xc_some, or xc_all */
234 	XC_EXIT		/* exiting xc_loop(); set by xc_dismissed */
235 };
236 
237 /*
238  * user provided handlers must be pc aligned
239  */
240 #define	PC_ALIGN 4
241 
242 #ifdef TRAPTRACE
243 #define	XC_TRACE(type, cpus, func, arg1, arg2) \
244 		xc_trace((type), (cpus), (func), (arg1), (arg2))
245 #else /* !TRAPTRACE */
246 #define	XC_TRACE(type, cpus, func, arg1, arg2)
247 #endif /* TRAPTRACE */
248 
249 #if defined(DEBUG) || defined(TRAPTRACE)
250 /*
251  * get some statistics when xc/xt routines are called
252  */
253 
254 #define	XC_STAT_INC(a)	(a)++;
255 #define	XC_CPUID	0
256 
257 #define	XT_ONE_SELF	1
258 #define	XT_ONE_OTHER	2
259 #define	XT_SOME_SELF	3
260 #define	XT_SOME_OTHER	4
261 #define	XT_ALL_SELF	5
262 #define	XT_ALL_OTHER	6
263 #define	XC_ONE_SELF	7
264 #define	XC_ONE_OTHER	8
265 #define	XC_ONE_OTHER_H	9
266 #define	XC_SOME_SELF	10
267 #define	XC_SOME_OTHER	11
268 #define	XC_SOME_OTHER_H	12
269 #define	XC_ALL_SELF	13
270 #define	XC_ALL_OTHER	14
271 #define	XC_ALL_OTHER_H	15
272 #define	XC_ATTENTION	16
273 #define	XC_DISMISSED	17
274 #define	XC_LOOP_ENTER	18
275 #define	XC_LOOP_DOIT	19
276 #define	XC_LOOP_EXIT	20
277 
278 extern	uint_t x_dstat[NCPU][XC_LOOP_EXIT+1];
279 extern	uint_t x_rstat[NCPU][4];
280 #define	XC_LOOP		1
281 #define	XC_SERV		2
282 
283 #define	XC_STAT_INIT(cpuid) 				\
284 {							\
285 	x_dstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid;	\
286 	x_rstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid;	\
287 }
288 
289 #else /* DEBUG || TRAPTRACE */
290 
291 #define	XC_STAT_INIT(cpuid)
292 #define	XC_STAT_INC(a)
293 #define	XC_ATTENTION_CPUSET(x)
294 #define	XC_DISMISSED_CPUSET(x)
295 
296 #endif /* DEBUG || TRAPTRACE */
297 
298 #endif	/* !_ASM */
299 
300 /*
301  * Maximum delay in milliseconds to wait for send_mondo to complete
302  */
303 #define	XC_SEND_MONDO_MSEC	1000
304 
305 #ifdef	__cplusplus
306 }
307 #endif
308 
309 #endif	/* _SYS_XC_IMPL_H */
310