/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_XC_IMPL_H #define _SYS_XC_IMPL_H #pragma ident "%Z%%M% %I% %E% SMI" #ifdef __cplusplus extern "C" { #endif #ifndef _ASM #include #include #include /* for panic_quiesce */ extern cpuset_t cpu_ready_set; /* cpus ready for x-call */ extern void send_self_xcall(struct cpu *, uint64_t, uint64_t, xcfunc_t *); extern uint_t xc_loop(void); extern uint_t xc_serv(void); extern void xc_stop(struct regs *); #ifdef TRAPTRACE extern void xc_trace(uint_t, cpuset_t *, xcfunc_t *, uint64_t, uint64_t); #endif /* TRAPTRACE */ extern uint64_t xc_func_time_limit; extern uint_t sendmondo_in_recover; /* * Lightweight XTrap Sync */ #ifdef sun4v #define XT_SYNC_ONE(cpuid) \ { \ cpuset_t set; \ CPUSET_ONLY(set, cpuid); \ xt_sync(set); \ } #define XT_SYNC_SOME(cpuset) \ { \ xt_sync(cpuset); \ } #else /* sun4v */ #define XT_SYNC_ONE(cpuid) \ { \ init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \ send_one_mondo(cpuid); \ } #define XT_SYNC_SOME(cpuset) \ { \ init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \ send_mondo_set(cpuset); \ } #endif /* sun4v */ /* * Protect the dispatching of the mondo vector */ #define XC_SPL_ENTER(cpuid, opl) \ { \ opl = splr(XCALL_PIL); \ cpuid = CPU->cpu_id; \ if (xc_spl_enter[cpuid] && !panic_quiesce) \ cmn_err(CE_PANIC, "XC SPL ENTER already entered (0x%x)",\ cpuid); \ xc_spl_enter[cpuid] = 1; \ } #define XC_SPL_EXIT(cpuid, opl) \ { \ ASSERT(xc_spl_enter[cpuid] != 0); \ xc_spl_enter[cpuid] = 0; \ splx(opl); \ } /* * set up a x-call request */ #define XC_SETUP(cpuid, func, arg1, arg2) \ { \ xc_mbox[cpuid].xc_func = func; \ xc_mbox[cpuid].xc_arg1 = arg1; \ xc_mbox[cpuid].xc_arg2 = arg2; \ xc_mbox[cpuid].xc_state = XC_DOIT; \ } /* * set up x-call requests to the cpuset */ #define SEND_MBOX_ONLY(xc_cpuset, func, arg1, arg2, lcx, state) \ { \ int pix; \ cpuset_t tmpset = xc_cpuset; \ for (pix = 0; pix < NCPU; pix++) { \ if (CPU_IN_SET(tmpset, pix)) { \ ASSERT(MUTEX_HELD(&xc_sys_mutex)); \ ASSERT(CPU_IN_SET(xc_mbox[lcx].xc_cpuset, pix));\ ASSERT(xc_mbox[pix].xc_state == state); \ XC_SETUP(pix, func, arg1, arg2); \ membar_stld(); \ CPUSET_DEL(tmpset, pix); \ CPU_STATS_ADDQ(CPU, sys, xcalls, 1); \ if (CPUSET_ISNULL(tmpset)) \ break; \ } \ } \ } /* * set up and notify a x-call request to the cpuset */ #define SEND_MBOX_MONDO(xc_cpuset, func, arg1, arg2, state) \ { \ int pix; \ cpuset_t tmpset = xc_cpuset; \ for (pix = 0; pix < NCPU; pix++) { \ if (CPU_IN_SET(tmpset, pix)) { \ ASSERT(xc_mbox[pix].xc_state == state); \ XC_SETUP(pix, func, arg1, arg2); \ CPUSET_DEL(tmpset, pix); \ if (CPUSET_ISNULL(tmpset)) \ break; \ } \ } \ membar_stld(); \ send_mondo_set(xc_cpuset); \ } /* * set up and notify a x-call request, signalling xc_cpuset * cpus to enter xc_loop() */ #define SEND_MBOX_MONDO_XC_ENTER(xc_cpuset) \ { \ int pix; \ cpuset_t tmpset = xc_cpuset; \ for (pix = 0; pix < NCPU; pix++) { \ if (CPU_IN_SET(tmpset, pix)) { \ ASSERT(xc_mbox[pix].xc_state == \ XC_IDLE); \ xc_mbox[pix].xc_state = XC_ENTER; \ CPUSET_DEL(tmpset, pix); \ if (CPUSET_ISNULL(tmpset)) { \ break; \ } \ } \ } \ send_mondo_set(xc_cpuset); \ } /* * wait x-call requests to be completed */ #define WAIT_MBOX_DONE(xc_cpuset, lcx, state, sync) \ { \ int pix; \ uint64_t loop_cnt = 0; \ cpuset_t tmpset; \ cpuset_t recv_cpuset; \ int first_time = 1; \ CPUSET_ZERO(recv_cpuset); \ while (!CPUSET_ISEQUAL(recv_cpuset, xc_cpuset)) { \ tmpset = xc_cpuset; \ for (pix = 0; pix < NCPU; pix++) { \ if (CPU_IN_SET(tmpset, pix)) { \ if (xc_mbox[pix].xc_state == state) { \ CPUSET_ADD(recv_cpuset, pix); \ } \ } \ CPUSET_DEL(tmpset, pix); \ if (CPUSET_ISNULL(tmpset)) \ break; \ } \ if (loop_cnt++ > xc_func_time_limit) { \ if (sendmondo_in_recover) { \ drv_usecwait(1); \ loop_cnt = 0; \ continue; \ } \ _NOTE(CONSTANTCONDITION) \ if (sync && first_time) { \ XT_SYNC_SOME(xc_cpuset); \ first_time = 0; \ loop_cnt = 0; \ continue; \ } \ panic("WAIT_MBOX_DONE() timeout, " \ "recv_cpuset 0x%lx, xc cpuset 0x%lx ", \ *(ulong_t *)&recv_cpuset, \ *(ulong_t *)&xc_cpuset); \ } \ } \ } /* * xc_state flags */ enum xc_states { XC_IDLE = 0, /* not in the xc_loop(); set by xc_loop */ XC_ENTER, /* entering xc_loop(); set by xc_attention */ XC_WAIT, /* entered xc_loop(); set by xc_loop */ XC_DOIT, /* xcall request; set by xc_one, xc_some, or xc_all */ XC_EXIT /* exiting xc_loop(); set by xc_dismissed */ }; /* * user provided handlers must be pc aligned */ #define PC_ALIGN 4 #ifdef TRAPTRACE #define XC_TRACE(type, cpus, func, arg1, arg2) \ xc_trace((type), (cpus), (func), (arg1), (arg2)) #else /* !TRAPTRACE */ #define XC_TRACE(type, cpus, func, arg1, arg2) #endif /* TRAPTRACE */ #if defined(DEBUG) || defined(TRAPTRACE) /* * get some statistics when xc/xt routines are called */ #define XC_STAT_INC(a) (a)++; #define XC_CPUID 0 #define XT_ONE_SELF 1 #define XT_ONE_OTHER 2 #define XT_SOME_SELF 3 #define XT_SOME_OTHER 4 #define XT_ALL_SELF 5 #define XT_ALL_OTHER 6 #define XC_ONE_SELF 7 #define XC_ONE_OTHER 8 #define XC_ONE_OTHER_H 9 #define XC_SOME_SELF 10 #define XC_SOME_OTHER 11 #define XC_SOME_OTHER_H 12 #define XC_ALL_SELF 13 #define XC_ALL_OTHER 14 #define XC_ALL_OTHER_H 15 #define XC_ATTENTION 16 #define XC_DISMISSED 17 #define XC_LOOP_ENTER 18 #define XC_LOOP_DOIT 19 #define XC_LOOP_EXIT 20 extern uint_t x_dstat[NCPU][XC_LOOP_EXIT+1]; extern uint_t x_rstat[NCPU][4]; #define XC_LOOP 1 #define XC_SERV 2 #define XC_STAT_INIT(cpuid) \ { \ x_dstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \ x_rstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \ } #else /* DEBUG || TRAPTRACE */ #define XC_STAT_INIT(cpuid) #define XC_STAT_INC(a) #define XC_ATTENTION_CPUSET(x) #define XC_DISMISSED_CPUSET(x) #endif /* DEBUG || TRAPTRACE */ #endif /* !_ASM */ /* * Maximum delay in milliseconds to wait for send_mondo to complete */ #define XC_SEND_MONDO_MSEC 1000 #ifdef __cplusplus } #endif #endif /* _SYS_XC_IMPL_H */