10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 231310Sha137994 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #ifndef _SYS_XC_IMPL_H 280Sstevel@tonic-gate #define _SYS_XC_IMPL_H 290Sstevel@tonic-gate 300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate 320Sstevel@tonic-gate #ifdef __cplusplus 330Sstevel@tonic-gate extern "C" { 340Sstevel@tonic-gate #endif 350Sstevel@tonic-gate 360Sstevel@tonic-gate #ifndef _ASM 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <sys/note.h> 390Sstevel@tonic-gate #include <sys/cpu_module.h> 400Sstevel@tonic-gate #include <sys/panic.h> /* for panic_quiesce */ 410Sstevel@tonic-gate 420Sstevel@tonic-gate extern cpuset_t cpu_ready_set; /* cpus ready for x-call */ 430Sstevel@tonic-gate extern void send_self_xcall(struct cpu *, uint64_t, uint64_t, xcfunc_t *); 440Sstevel@tonic-gate extern uint_t xc_loop(void); 450Sstevel@tonic-gate extern uint_t xc_serv(void); 460Sstevel@tonic-gate extern void xc_stop(struct regs *); 470Sstevel@tonic-gate #ifdef TRAPTRACE 480Sstevel@tonic-gate extern void xc_trace(uint_t, cpuset_t *, xcfunc_t *, uint64_t, uint64_t); 490Sstevel@tonic-gate #endif /* TRAPTRACE */ 500Sstevel@tonic-gate extern uint64_t xc_func_time_limit; 510Sstevel@tonic-gate 520Sstevel@tonic-gate extern uint_t sendmondo_in_recover; 530Sstevel@tonic-gate 540Sstevel@tonic-gate /* 550Sstevel@tonic-gate * Lightweight XTrap Sync 560Sstevel@tonic-gate */ 570Sstevel@tonic-gate #ifdef sun4v 580Sstevel@tonic-gate #define XT_SYNC_ONE(cpuid) \ 590Sstevel@tonic-gate { \ 600Sstevel@tonic-gate cpuset_t set; \ 610Sstevel@tonic-gate CPUSET_ONLY(set, cpuid); \ 620Sstevel@tonic-gate xt_sync(set); \ 630Sstevel@tonic-gate } 640Sstevel@tonic-gate 650Sstevel@tonic-gate #define XT_SYNC_SOME(cpuset) \ 660Sstevel@tonic-gate { \ 670Sstevel@tonic-gate xt_sync(cpuset); \ 680Sstevel@tonic-gate } 690Sstevel@tonic-gate 700Sstevel@tonic-gate #else /* sun4v */ 710Sstevel@tonic-gate 720Sstevel@tonic-gate #define XT_SYNC_ONE(cpuid) \ 730Sstevel@tonic-gate { \ 740Sstevel@tonic-gate init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \ 750Sstevel@tonic-gate send_one_mondo(cpuid); \ 760Sstevel@tonic-gate } 770Sstevel@tonic-gate 780Sstevel@tonic-gate #define XT_SYNC_SOME(cpuset) \ 790Sstevel@tonic-gate { \ 800Sstevel@tonic-gate init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \ 810Sstevel@tonic-gate send_mondo_set(cpuset); \ 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate #endif /* sun4v */ 850Sstevel@tonic-gate 860Sstevel@tonic-gate /* 870Sstevel@tonic-gate * Protect the dispatching of the mondo vector 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate 900Sstevel@tonic-gate #define XC_SPL_ENTER(cpuid, opl) \ 910Sstevel@tonic-gate { \ 920Sstevel@tonic-gate opl = splr(XCALL_PIL); \ 930Sstevel@tonic-gate cpuid = CPU->cpu_id; \ 940Sstevel@tonic-gate if (xc_spl_enter[cpuid] && !panic_quiesce) \ 950Sstevel@tonic-gate cmn_err(CE_PANIC, "XC SPL ENTER already entered (0x%x)",\ 960Sstevel@tonic-gate cpuid); \ 970Sstevel@tonic-gate xc_spl_enter[cpuid] = 1; \ 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1000Sstevel@tonic-gate #define XC_SPL_EXIT(cpuid, opl) \ 1010Sstevel@tonic-gate { \ 1020Sstevel@tonic-gate ASSERT(xc_spl_enter[cpuid] != 0); \ 1030Sstevel@tonic-gate xc_spl_enter[cpuid] = 0; \ 1040Sstevel@tonic-gate splx(opl); \ 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* 1080Sstevel@tonic-gate * set up a x-call request 1090Sstevel@tonic-gate */ 1100Sstevel@tonic-gate #define XC_SETUP(cpuid, func, arg1, arg2) \ 1110Sstevel@tonic-gate { \ 1120Sstevel@tonic-gate xc_mbox[cpuid].xc_func = func; \ 1130Sstevel@tonic-gate xc_mbox[cpuid].xc_arg1 = arg1; \ 1140Sstevel@tonic-gate xc_mbox[cpuid].xc_arg2 = arg2; \ 1150Sstevel@tonic-gate xc_mbox[cpuid].xc_state = XC_DOIT; \ 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* 1190Sstevel@tonic-gate * set up x-call requests to the cpuset 1200Sstevel@tonic-gate */ 1210Sstevel@tonic-gate #define SEND_MBOX_ONLY(xc_cpuset, func, arg1, arg2, lcx, state) \ 1220Sstevel@tonic-gate { \ 1230Sstevel@tonic-gate int pix; \ 1240Sstevel@tonic-gate cpuset_t tmpset = xc_cpuset; \ 1250Sstevel@tonic-gate for (pix = 0; pix < NCPU; pix++) { \ 1260Sstevel@tonic-gate if (CPU_IN_SET(tmpset, pix)) { \ 1270Sstevel@tonic-gate ASSERT(MUTEX_HELD(&xc_sys_mutex)); \ 1280Sstevel@tonic-gate ASSERT(CPU_IN_SET(xc_mbox[lcx].xc_cpuset, pix));\ 1290Sstevel@tonic-gate ASSERT(xc_mbox[pix].xc_state == state); \ 1300Sstevel@tonic-gate XC_SETUP(pix, func, arg1, arg2); \ 1310Sstevel@tonic-gate membar_stld(); \ 1320Sstevel@tonic-gate CPUSET_DEL(tmpset, pix); \ 1330Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, 1); \ 1340Sstevel@tonic-gate if (CPUSET_ISNULL(tmpset)) \ 1350Sstevel@tonic-gate break; \ 1360Sstevel@tonic-gate } \ 1370Sstevel@tonic-gate } \ 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1410Sstevel@tonic-gate * set up and notify a x-call request to the cpuset 1420Sstevel@tonic-gate */ 1430Sstevel@tonic-gate #define SEND_MBOX_MONDO(xc_cpuset, func, arg1, arg2, state) \ 1440Sstevel@tonic-gate { \ 1450Sstevel@tonic-gate int pix; \ 1460Sstevel@tonic-gate cpuset_t tmpset = xc_cpuset; \ 1470Sstevel@tonic-gate for (pix = 0; pix < NCPU; pix++) { \ 1480Sstevel@tonic-gate if (CPU_IN_SET(tmpset, pix)) { \ 1490Sstevel@tonic-gate ASSERT(xc_mbox[pix].xc_state == state); \ 1500Sstevel@tonic-gate XC_SETUP(pix, func, arg1, arg2); \ 1510Sstevel@tonic-gate CPUSET_DEL(tmpset, pix); \ 1520Sstevel@tonic-gate if (CPUSET_ISNULL(tmpset)) \ 1530Sstevel@tonic-gate break; \ 1540Sstevel@tonic-gate } \ 1550Sstevel@tonic-gate } \ 1561310Sha137994 membar_stld(); \ 1571310Sha137994 send_mondo_set(xc_cpuset); \ 1581310Sha137994 } 1591310Sha137994 1601310Sha137994 /* 1611310Sha137994 * set up and notify a x-call request, signalling xc_cpuset 1621310Sha137994 * cpus to enter xc_loop() 1631310Sha137994 */ 1641310Sha137994 #define SEND_MBOX_MONDO_XC_ENTER(xc_cpuset) \ 1651310Sha137994 { \ 1661310Sha137994 int pix; \ 1671310Sha137994 cpuset_t tmpset = xc_cpuset; \ 1681310Sha137994 for (pix = 0; pix < NCPU; pix++) { \ 1691310Sha137994 if (CPU_IN_SET(tmpset, pix)) { \ 1701310Sha137994 ASSERT(xc_mbox[pix].xc_state == \ 1711310Sha137994 XC_IDLE); \ 1721310Sha137994 xc_mbox[pix].xc_state = XC_ENTER; \ 1731310Sha137994 CPUSET_DEL(tmpset, pix); \ 1741310Sha137994 if (CPUSET_ISNULL(tmpset)) { \ 1751310Sha137994 break; \ 1761310Sha137994 } \ 1771310Sha137994 } \ 1781310Sha137994 } \ 1791310Sha137994 send_mondo_set(xc_cpuset); \ 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * wait x-call requests to be completed 1840Sstevel@tonic-gate */ 1850Sstevel@tonic-gate #define WAIT_MBOX_DONE(xc_cpuset, lcx, state, sync) \ 1860Sstevel@tonic-gate { \ 1870Sstevel@tonic-gate int pix; \ 1880Sstevel@tonic-gate uint64_t loop_cnt = 0; \ 1890Sstevel@tonic-gate cpuset_t tmpset; \ 1900Sstevel@tonic-gate cpuset_t recv_cpuset; \ 1910Sstevel@tonic-gate int first_time = 1; \ 1920Sstevel@tonic-gate CPUSET_ZERO(recv_cpuset); \ 1930Sstevel@tonic-gate while (!CPUSET_ISEQUAL(recv_cpuset, xc_cpuset)) { \ 1940Sstevel@tonic-gate tmpset = xc_cpuset; \ 1950Sstevel@tonic-gate for (pix = 0; pix < NCPU; pix++) { \ 1960Sstevel@tonic-gate if (CPU_IN_SET(tmpset, pix)) { \ 1970Sstevel@tonic-gate if (xc_mbox[pix].xc_state == state) { \ 1980Sstevel@tonic-gate CPUSET_ADD(recv_cpuset, pix); \ 1990Sstevel@tonic-gate } \ 2000Sstevel@tonic-gate } \ 2010Sstevel@tonic-gate CPUSET_DEL(tmpset, pix); \ 2020Sstevel@tonic-gate if (CPUSET_ISNULL(tmpset)) \ 2030Sstevel@tonic-gate break; \ 2040Sstevel@tonic-gate } \ 2050Sstevel@tonic-gate if (loop_cnt++ > xc_func_time_limit) { \ 2060Sstevel@tonic-gate if (sendmondo_in_recover) { \ 2070Sstevel@tonic-gate drv_usecwait(1); \ 2080Sstevel@tonic-gate loop_cnt = 0; \ 2090Sstevel@tonic-gate continue; \ 2100Sstevel@tonic-gate } \ 2110Sstevel@tonic-gate _NOTE(CONSTANTCONDITION) \ 2120Sstevel@tonic-gate if (sync && first_time) { \ 2130Sstevel@tonic-gate XT_SYNC_SOME(xc_cpuset); \ 2140Sstevel@tonic-gate first_time = 0; \ 2150Sstevel@tonic-gate loop_cnt = 0; \ 2160Sstevel@tonic-gate continue; \ 2170Sstevel@tonic-gate } \ 2180Sstevel@tonic-gate panic("WAIT_MBOX_DONE() timeout, " \ 2190Sstevel@tonic-gate "recv_cpuset 0x%lx, xc cpuset 0x%lx ", \ 2201009Smathue *(ulong_t *)&recv_cpuset, \ 2211009Smathue *(ulong_t *)&xc_cpuset); \ 2220Sstevel@tonic-gate } \ 2230Sstevel@tonic-gate } \ 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate /* 2270Sstevel@tonic-gate * xc_state flags 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate enum xc_states { 2300Sstevel@tonic-gate XC_IDLE = 0, /* not in the xc_loop(); set by xc_loop */ 2310Sstevel@tonic-gate XC_ENTER, /* entering xc_loop(); set by xc_attention */ 2320Sstevel@tonic-gate XC_WAIT, /* entered xc_loop(); set by xc_loop */ 2330Sstevel@tonic-gate XC_DOIT, /* xcall request; set by xc_one, xc_some, or xc_all */ 2340Sstevel@tonic-gate XC_EXIT /* exiting xc_loop(); set by xc_dismissed */ 2350Sstevel@tonic-gate }; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* 2380Sstevel@tonic-gate * user provided handlers must be pc aligned 2390Sstevel@tonic-gate */ 2400Sstevel@tonic-gate #define PC_ALIGN 4 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate #ifdef TRAPTRACE 2430Sstevel@tonic-gate #define XC_TRACE(type, cpus, func, arg1, arg2) \ 2440Sstevel@tonic-gate xc_trace((type), (cpus), (func), (arg1), (arg2)) 2450Sstevel@tonic-gate #else /* !TRAPTRACE */ 2460Sstevel@tonic-gate #define XC_TRACE(type, cpus, func, arg1, arg2) 2470Sstevel@tonic-gate #endif /* TRAPTRACE */ 2480Sstevel@tonic-gate 249*1395Srjnoe #if defined(DEBUG) || defined(TRAPTRACE) 2500Sstevel@tonic-gate /* 2510Sstevel@tonic-gate * get some statistics when xc/xt routines are called 2520Sstevel@tonic-gate */ 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate #define XC_STAT_INC(a) (a)++; 2550Sstevel@tonic-gate #define XC_CPUID 0 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate #define XT_ONE_SELF 1 2580Sstevel@tonic-gate #define XT_ONE_OTHER 2 2590Sstevel@tonic-gate #define XT_SOME_SELF 3 2600Sstevel@tonic-gate #define XT_SOME_OTHER 4 2610Sstevel@tonic-gate #define XT_ALL_SELF 5 2620Sstevel@tonic-gate #define XT_ALL_OTHER 6 2630Sstevel@tonic-gate #define XC_ONE_SELF 7 2640Sstevel@tonic-gate #define XC_ONE_OTHER 8 2650Sstevel@tonic-gate #define XC_ONE_OTHER_H 9 2660Sstevel@tonic-gate #define XC_SOME_SELF 10 2670Sstevel@tonic-gate #define XC_SOME_OTHER 11 2680Sstevel@tonic-gate #define XC_SOME_OTHER_H 12 2690Sstevel@tonic-gate #define XC_ALL_SELF 13 2700Sstevel@tonic-gate #define XC_ALL_OTHER 14 2710Sstevel@tonic-gate #define XC_ALL_OTHER_H 15 2720Sstevel@tonic-gate #define XC_ATTENTION 16 2730Sstevel@tonic-gate #define XC_DISMISSED 17 2740Sstevel@tonic-gate #define XC_LOOP_ENTER 18 2750Sstevel@tonic-gate #define XC_LOOP_DOIT 19 2760Sstevel@tonic-gate #define XC_LOOP_EXIT 20 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate extern uint_t x_dstat[NCPU][XC_LOOP_EXIT+1]; 2790Sstevel@tonic-gate extern uint_t x_rstat[NCPU][4]; 2800Sstevel@tonic-gate #define XC_LOOP 1 2810Sstevel@tonic-gate #define XC_SERV 2 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate #define XC_STAT_INIT(cpuid) \ 2840Sstevel@tonic-gate { \ 2850Sstevel@tonic-gate x_dstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \ 2860Sstevel@tonic-gate x_rstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \ 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 289*1395Srjnoe #else /* DEBUG || TRAPTRACE */ 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate #define XC_STAT_INIT(cpuid) 2920Sstevel@tonic-gate #define XC_STAT_INC(a) 2930Sstevel@tonic-gate #define XC_ATTENTION_CPUSET(x) 2940Sstevel@tonic-gate #define XC_DISMISSED_CPUSET(x) 2950Sstevel@tonic-gate 296*1395Srjnoe #endif /* DEBUG || TRAPTRACE */ 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate #endif /* !_ASM */ 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * Maximum delay in milliseconds to wait for send_mondo to complete 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate #define XC_SEND_MONDO_MSEC 1000 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate #ifdef __cplusplus 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate #endif 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate #endif /* _SYS_XC_IMPL_H */ 310