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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Facilities for cross-processor subroutine calls using "mailbox" interrupts. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/thread.h> 32 #include <sys/cpuvar.h> 33 #include <sys/x_call.h> 34 #include <sys/systm.h> 35 #include <sys/machsystm.h> 36 #include <sys/intr.h> 37 #include <sys/xc_impl.h> 38 39 /* 40 * Interrupt another CPU. 41 * This is useful to make the other CPU go through a trap so that 42 * it recognizes an address space trap (AST) for preempting a thread. 43 * 44 * It is possible to be preempted here and be resumed on the CPU 45 * being poked, so it isn't an error to poke the current CPU. 46 * We could check this and still get preempted after the check, so 47 * we don't bother. 48 */ 49 void 50 poke_cpu(int cpun) 51 { 52 uint32_t *ptr = (uint32_t *)&cpu[cpun]->cpu_m.poke_cpu_outstanding; 53 54 /* 55 * If panicstr is set or a poke_cpu is already pending, 56 * no need to send another one. Use atomic swap to protect 57 * against multiple CPUs sending redundant pokes. 58 */ 59 if (panicstr || *ptr == B_TRUE || 60 atomic_swap_32(ptr, B_TRUE) == B_TRUE) 61 return; 62 63 xt_one(cpun, setsoftint_tl1, poke_cpu_inum, 0); 64 } 65 66 extern int xc_spl_enter[]; 67 68 /* 69 * Call a function on a target CPU 70 */ 71 void 72 cpu_call(cpu_t *cp, cpu_call_func_t func, uintptr_t arg1, uintptr_t arg2) 73 { 74 if (panicstr) 75 return; 76 77 /* 78 * Prevent CPU from going offline 79 */ 80 kpreempt_disable(); 81 82 /* 83 * If we are on the target CPU, call the function directly, but raise 84 * the PIL to XC_PIL. 85 * This guarantees that functions called via cpu_call() can not ever 86 * interrupt each other. 87 */ 88 if (CPU != cp) { 89 xc_one(cp->cpu_id, (xcfunc_t *)func, (uint64_t)arg1, 90 (uint64_t)arg2); 91 } else { 92 int lcx; 93 int opl; 94 95 XC_SPL_ENTER(lcx, opl); 96 func(arg1, arg2); 97 XC_SPL_EXIT(lcx, opl); 98 } 99 100 kpreempt_enable(); 101 } 102