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