xref: /illumos-gate/usr/src/uts/sun4/sys/xc_impl.h (revision 8b9d661e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23e5900f74Sha  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #ifndef	_SYS_XC_IMPL_H
287c478bd9Sstevel@tonic-gate #define	_SYS_XC_IMPL_H
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
337c478bd9Sstevel@tonic-gate extern "C" {
347c478bd9Sstevel@tonic-gate #endif
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #ifndef _ASM
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/note.h>
397c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
407c478bd9Sstevel@tonic-gate #include <sys/panic.h>		/* for panic_quiesce */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate extern cpuset_t cpu_ready_set;	/* cpus ready for x-call */
437c478bd9Sstevel@tonic-gate extern void send_self_xcall(struct cpu *, uint64_t, uint64_t, xcfunc_t *);
447c478bd9Sstevel@tonic-gate extern uint_t xc_loop(void);
457c478bd9Sstevel@tonic-gate extern uint_t xc_serv(void);
467c478bd9Sstevel@tonic-gate extern void xc_stop(struct regs *);
477c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
487c478bd9Sstevel@tonic-gate extern void xc_trace(uint_t, cpuset_t *, xcfunc_t *, uint64_t, uint64_t);
497c478bd9Sstevel@tonic-gate #endif /* TRAPTRACE */
507c478bd9Sstevel@tonic-gate extern uint64_t xc_func_time_limit;
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate extern uint_t sendmondo_in_recover;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Lightweight XTrap Sync
567c478bd9Sstevel@tonic-gate  */
577c478bd9Sstevel@tonic-gate #ifdef sun4v
587c478bd9Sstevel@tonic-gate #define	XT_SYNC_ONE(cpuid)				\
597c478bd9Sstevel@tonic-gate {							\
607c478bd9Sstevel@tonic-gate 	cpuset_t set;					\
617c478bd9Sstevel@tonic-gate 	CPUSET_ONLY(set, cpuid);			\
627c478bd9Sstevel@tonic-gate 	xt_sync(set);					\
637c478bd9Sstevel@tonic-gate }
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	XT_SYNC_SOME(cpuset)				\
667c478bd9Sstevel@tonic-gate {							\
677c478bd9Sstevel@tonic-gate 	xt_sync(cpuset);				\
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #else /* sun4v */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #define	XT_SYNC_ONE(cpuid)				\
737c478bd9Sstevel@tonic-gate {							\
747c478bd9Sstevel@tonic-gate 	init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0);	\
757c478bd9Sstevel@tonic-gate 	send_one_mondo(cpuid);				\
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	XT_SYNC_SOME(cpuset)				\
797c478bd9Sstevel@tonic-gate {							\
807c478bd9Sstevel@tonic-gate 	init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0);	\
817c478bd9Sstevel@tonic-gate 	send_mondo_set(cpuset);				\
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #endif /* sun4v */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Protect the dispatching of the mondo vector
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate #define	XC_SPL_ENTER(cpuid, opl)					\
917c478bd9Sstevel@tonic-gate {									\
927c478bd9Sstevel@tonic-gate 	opl = splr(XCALL_PIL);						\
937c478bd9Sstevel@tonic-gate 	cpuid = CPU->cpu_id;						\
947c478bd9Sstevel@tonic-gate 	if (xc_spl_enter[cpuid] && !panic_quiesce)			\
957c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "XC SPL ENTER already entered (0x%x)",\
967c478bd9Sstevel@tonic-gate 		cpuid);							\
977c478bd9Sstevel@tonic-gate 	xc_spl_enter[cpuid] = 1;					\
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #define	XC_SPL_EXIT(cpuid, opl)				\
1017c478bd9Sstevel@tonic-gate {							\
1027c478bd9Sstevel@tonic-gate 	ASSERT(xc_spl_enter[cpuid] != 0);		\
1037c478bd9Sstevel@tonic-gate 	xc_spl_enter[cpuid] = 0;			\
1047c478bd9Sstevel@tonic-gate 	splx(opl);					\
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * set up a x-call request
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate #define	XC_SETUP(cpuid, func, arg1, arg2)		\
1117c478bd9Sstevel@tonic-gate {							\
1127c478bd9Sstevel@tonic-gate 	xc_mbox[cpuid].xc_func = func;			\
1137c478bd9Sstevel@tonic-gate 	xc_mbox[cpuid].xc_arg1 = arg1;			\
1147c478bd9Sstevel@tonic-gate 	xc_mbox[cpuid].xc_arg2 = arg2;			\
1157c478bd9Sstevel@tonic-gate 	xc_mbox[cpuid].xc_state = XC_DOIT;		\
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * set up x-call requests to the cpuset
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate #define	SEND_MBOX_ONLY(xc_cpuset, func, arg1, arg2, lcx, state)		\
1227c478bd9Sstevel@tonic-gate {									\
1237c478bd9Sstevel@tonic-gate 	int pix;							\
1247c478bd9Sstevel@tonic-gate 	cpuset_t  tmpset = xc_cpuset;					\
1257c478bd9Sstevel@tonic-gate 	for (pix = 0; pix < NCPU; pix++) {				\
1267c478bd9Sstevel@tonic-gate 		if (CPU_IN_SET(tmpset, pix)) {				\
1277c478bd9Sstevel@tonic-gate 			ASSERT(MUTEX_HELD(&xc_sys_mutex));		\
1287c478bd9Sstevel@tonic-gate 			ASSERT(CPU_IN_SET(xc_mbox[lcx].xc_cpuset, pix));\
1297c478bd9Sstevel@tonic-gate 			ASSERT(xc_mbox[pix].xc_state == state);		\
1307c478bd9Sstevel@tonic-gate 			XC_SETUP(pix, func, arg1, arg2);		\
1317c478bd9Sstevel@tonic-gate 			membar_stld();					\
1327c478bd9Sstevel@tonic-gate 			CPUSET_DEL(tmpset, pix);			\
1337c478bd9Sstevel@tonic-gate 			CPU_STATS_ADDQ(CPU, sys, xcalls, 1);		\
1347c478bd9Sstevel@tonic-gate 			if (CPUSET_ISNULL(tmpset))			\
1357c478bd9Sstevel@tonic-gate 				break;					\
1367c478bd9Sstevel@tonic-gate 		}							\
1377c478bd9Sstevel@tonic-gate 	}								\
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate  * set up and notify a x-call request to the cpuset
1427c478bd9Sstevel@tonic-gate  */
1437c478bd9Sstevel@tonic-gate #define	SEND_MBOX_MONDO(xc_cpuset, func, arg1, arg2, state)	\
1447c478bd9Sstevel@tonic-gate {								\
1457c478bd9Sstevel@tonic-gate 	int pix;						\
1467c478bd9Sstevel@tonic-gate 	cpuset_t  tmpset = xc_cpuset;				\
1477c478bd9Sstevel@tonic-gate 	for (pix = 0; pix < NCPU; pix++) {			\
1487c478bd9Sstevel@tonic-gate 		if (CPU_IN_SET(tmpset, pix)) {			\
1497c478bd9Sstevel@tonic-gate 			ASSERT(xc_mbox[pix].xc_state == state);	\
1507c478bd9Sstevel@tonic-gate 			XC_SETUP(pix, func, arg1, arg2);	\
1517c478bd9Sstevel@tonic-gate 			CPUSET_DEL(tmpset, pix);		\
1527c478bd9Sstevel@tonic-gate 			if (CPUSET_ISNULL(tmpset))		\
1537c478bd9Sstevel@tonic-gate 				break;				\
1547c478bd9Sstevel@tonic-gate 		}						\
1557c478bd9Sstevel@tonic-gate 	}							\
156e5900f74Sha 	membar_stld();						\
157e5900f74Sha 	send_mondo_set(xc_cpuset);				\
158e5900f74Sha }
159e5900f74Sha 
160e5900f74Sha /*
161e5900f74Sha  * set up and notify a x-call request, signalling xc_cpuset
162e5900f74Sha  * cpus to enter xc_loop()
163e5900f74Sha  */
164e5900f74Sha #define	SEND_MBOX_MONDO_XC_ENTER(xc_cpuset)			\
165e5900f74Sha {								\
166e5900f74Sha 	int pix;						\
167e5900f74Sha 	cpuset_t  tmpset = xc_cpuset;				\
168e5900f74Sha 	for (pix = 0; pix < NCPU; pix++) {			\
169e5900f74Sha 		if (CPU_IN_SET(tmpset, pix)) {			\
170e5900f74Sha 			ASSERT(xc_mbox[pix].xc_state ==		\
171e5900f74Sha 			    XC_IDLE);				\
172e5900f74Sha 			xc_mbox[pix].xc_state = XC_ENTER;	\
173e5900f74Sha 			CPUSET_DEL(tmpset, pix);		\
174e5900f74Sha 			if (CPUSET_ISNULL(tmpset)) {		\
175e5900f74Sha 				break;				\
176e5900f74Sha 			}					\
177e5900f74Sha 		}						\
178e5900f74Sha 	}							\
179e5900f74Sha 	send_mondo_set(xc_cpuset);				\
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate  * wait x-call requests to be completed
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate #define	WAIT_MBOX_DONE(xc_cpuset, lcx, state, sync)			\
1867c478bd9Sstevel@tonic-gate {									\
1877c478bd9Sstevel@tonic-gate 	int pix;							\
1887c478bd9Sstevel@tonic-gate 	uint64_t loop_cnt = 0;						\
1897c478bd9Sstevel@tonic-gate 	cpuset_t tmpset;						\
1907c478bd9Sstevel@tonic-gate 	cpuset_t  recv_cpuset;						\
1917c478bd9Sstevel@tonic-gate 	int first_time = 1;						\
1927c478bd9Sstevel@tonic-gate 	CPUSET_ZERO(recv_cpuset);					\
1937c478bd9Sstevel@tonic-gate 	while (!CPUSET_ISEQUAL(recv_cpuset, xc_cpuset)) {		\
1947c478bd9Sstevel@tonic-gate 		tmpset = xc_cpuset;					\
1957c478bd9Sstevel@tonic-gate 		for (pix = 0; pix < NCPU; pix++) {			\
1967c478bd9Sstevel@tonic-gate 			if (CPU_IN_SET(tmpset, pix)) {			\
1977c478bd9Sstevel@tonic-gate 				if (xc_mbox[pix].xc_state == state) {	\
1987c478bd9Sstevel@tonic-gate 					CPUSET_ADD(recv_cpuset, pix);	\
1997c478bd9Sstevel@tonic-gate 				}					\
2007c478bd9Sstevel@tonic-gate 			}						\
2017c478bd9Sstevel@tonic-gate 			CPUSET_DEL(tmpset, pix);			\
2027c478bd9Sstevel@tonic-gate 			if (CPUSET_ISNULL(tmpset))			\
2037c478bd9Sstevel@tonic-gate 				break;					\
2047c478bd9Sstevel@tonic-gate 		}							\
2057c478bd9Sstevel@tonic-gate 		if (loop_cnt++ > xc_func_time_limit) {			\
2067c478bd9Sstevel@tonic-gate 			if (sendmondo_in_recover) {			\
2077c478bd9Sstevel@tonic-gate 				drv_usecwait(1);			\
2087c478bd9Sstevel@tonic-gate 				loop_cnt = 0;				\
2097c478bd9Sstevel@tonic-gate 				continue;				\
2107c478bd9Sstevel@tonic-gate 			}						\
2117c478bd9Sstevel@tonic-gate 			_NOTE(CONSTANTCONDITION)			\
2127c478bd9Sstevel@tonic-gate 			if (sync && first_time) {			\
2137c478bd9Sstevel@tonic-gate 				XT_SYNC_SOME(xc_cpuset);		\
2147c478bd9Sstevel@tonic-gate 				first_time = 0;				\
2157c478bd9Sstevel@tonic-gate 				loop_cnt = 0;				\
2167c478bd9Sstevel@tonic-gate 				continue;				\
2177c478bd9Sstevel@tonic-gate 			}						\
2187c478bd9Sstevel@tonic-gate 			panic("WAIT_MBOX_DONE() timeout, "		\
2197c478bd9Sstevel@tonic-gate 				"recv_cpuset 0x%lx, xc cpuset 0x%lx ",	\
2201a70ae91Smathue 				*(ulong_t *)&recv_cpuset,		\
2211a70ae91Smathue 				*(ulong_t *)&xc_cpuset);		\
2227c478bd9Sstevel@tonic-gate 		}							\
2237c478bd9Sstevel@tonic-gate 	}								\
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate /*
2277c478bd9Sstevel@tonic-gate  * xc_state flags
2287c478bd9Sstevel@tonic-gate  */
2297c478bd9Sstevel@tonic-gate enum xc_states {
2307c478bd9Sstevel@tonic-gate 	XC_IDLE = 0,	/* not in the xc_loop(); set by xc_loop */
2317c478bd9Sstevel@tonic-gate 	XC_ENTER,	/* entering xc_loop(); set by xc_attention */
2327c478bd9Sstevel@tonic-gate 	XC_WAIT,	/* entered xc_loop(); set by xc_loop */
2337c478bd9Sstevel@tonic-gate 	XC_DOIT,	/* xcall request; set by xc_one, xc_some, or xc_all */
2347c478bd9Sstevel@tonic-gate 	XC_EXIT		/* exiting xc_loop(); set by xc_dismissed */
2357c478bd9Sstevel@tonic-gate };
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  * user provided handlers must be pc aligned
2397c478bd9Sstevel@tonic-gate  */
2407c478bd9Sstevel@tonic-gate #define	PC_ALIGN 4
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
2437c478bd9Sstevel@tonic-gate #define	XC_TRACE(type, cpus, func, arg1, arg2) \
2447c478bd9Sstevel@tonic-gate 		xc_trace((type), (cpus), (func), (arg1), (arg2))
2457c478bd9Sstevel@tonic-gate #else /* !TRAPTRACE */
2467c478bd9Sstevel@tonic-gate #define	XC_TRACE(type, cpus, func, arg1, arg2)
2477c478bd9Sstevel@tonic-gate #endif /* TRAPTRACE */
2487c478bd9Sstevel@tonic-gate 
249*8b9d661eSrjnoe #if defined(DEBUG) || defined(TRAPTRACE)
2507c478bd9Sstevel@tonic-gate /*
2517c478bd9Sstevel@tonic-gate  * get some statistics when xc/xt routines are called
2527c478bd9Sstevel@tonic-gate  */
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate #define	XC_STAT_INC(a)	(a)++;
2557c478bd9Sstevel@tonic-gate #define	XC_CPUID	0
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate #define	XT_ONE_SELF	1
2587c478bd9Sstevel@tonic-gate #define	XT_ONE_OTHER	2
2597c478bd9Sstevel@tonic-gate #define	XT_SOME_SELF	3
2607c478bd9Sstevel@tonic-gate #define	XT_SOME_OTHER	4
2617c478bd9Sstevel@tonic-gate #define	XT_ALL_SELF	5
2627c478bd9Sstevel@tonic-gate #define	XT_ALL_OTHER	6
2637c478bd9Sstevel@tonic-gate #define	XC_ONE_SELF	7
2647c478bd9Sstevel@tonic-gate #define	XC_ONE_OTHER	8
2657c478bd9Sstevel@tonic-gate #define	XC_ONE_OTHER_H	9
2667c478bd9Sstevel@tonic-gate #define	XC_SOME_SELF	10
2677c478bd9Sstevel@tonic-gate #define	XC_SOME_OTHER	11
2687c478bd9Sstevel@tonic-gate #define	XC_SOME_OTHER_H	12
2697c478bd9Sstevel@tonic-gate #define	XC_ALL_SELF	13
2707c478bd9Sstevel@tonic-gate #define	XC_ALL_OTHER	14
2717c478bd9Sstevel@tonic-gate #define	XC_ALL_OTHER_H	15
2727c478bd9Sstevel@tonic-gate #define	XC_ATTENTION	16
2737c478bd9Sstevel@tonic-gate #define	XC_DISMISSED	17
2747c478bd9Sstevel@tonic-gate #define	XC_LOOP_ENTER	18
2757c478bd9Sstevel@tonic-gate #define	XC_LOOP_DOIT	19
2767c478bd9Sstevel@tonic-gate #define	XC_LOOP_EXIT	20
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate extern	uint_t x_dstat[NCPU][XC_LOOP_EXIT+1];
2797c478bd9Sstevel@tonic-gate extern	uint_t x_rstat[NCPU][4];
2807c478bd9Sstevel@tonic-gate #define	XC_LOOP		1
2817c478bd9Sstevel@tonic-gate #define	XC_SERV		2
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate #define	XC_STAT_INIT(cpuid) 				\
2847c478bd9Sstevel@tonic-gate {							\
2857c478bd9Sstevel@tonic-gate 	x_dstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid;	\
2867c478bd9Sstevel@tonic-gate 	x_rstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid;	\
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
289*8b9d661eSrjnoe #else /* DEBUG || TRAPTRACE */
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate #define	XC_STAT_INIT(cpuid)
2927c478bd9Sstevel@tonic-gate #define	XC_STAT_INC(a)
2937c478bd9Sstevel@tonic-gate #define	XC_ATTENTION_CPUSET(x)
2947c478bd9Sstevel@tonic-gate #define	XC_DISMISSED_CPUSET(x)
2957c478bd9Sstevel@tonic-gate 
296*8b9d661eSrjnoe #endif /* DEBUG || TRAPTRACE */
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #endif	/* !_ASM */
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate /*
3017c478bd9Sstevel@tonic-gate  * Maximum delay in milliseconds to wait for send_mondo to complete
3027c478bd9Sstevel@tonic-gate  */
3037c478bd9Sstevel@tonic-gate #define	XC_SEND_MONDO_MSEC	1000
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate #endif
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate #endif	/* _SYS_XC_IMPL_H */
310