xref: /onnv-gate/usr/src/uts/sun4/os/mp_call.c (revision 11389:dd00b884e84f)
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
5*11389SAlexander.Kolbasov@Sun.COM  * Common Development and Distribution License (the "License").
6*11389SAlexander.Kolbasov@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11389SAlexander.Kolbasov@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * Facilities for cross-processor subroutine calls using "mailbox" interrupts.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/thread.h>
320Sstevel@tonic-gate #include <sys/cpuvar.h>
330Sstevel@tonic-gate #include <sys/x_call.h>
340Sstevel@tonic-gate #include <sys/systm.h>
350Sstevel@tonic-gate #include <sys/machsystm.h>
360Sstevel@tonic-gate #include <sys/intr.h>
37*11389SAlexander.Kolbasov@Sun.COM #include <sys/xc_impl.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate  * Interrupt another CPU.
410Sstevel@tonic-gate  * 	This is useful to make the other CPU go through a trap so that
420Sstevel@tonic-gate  *	it recognizes an address space trap (AST) for preempting a thread.
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  *	It is possible to be preempted here and be resumed on the CPU
450Sstevel@tonic-gate  *	being poked, so it isn't an error to poke the current CPU.
460Sstevel@tonic-gate  *	We could check this and still get preempted after the check, so
470Sstevel@tonic-gate  *	we don't bother.
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate void
poke_cpu(int cpun)500Sstevel@tonic-gate poke_cpu(int cpun)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	uint32_t *ptr = (uint32_t *)&cpu[cpun]->cpu_m.poke_cpu_outstanding;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	/*
550Sstevel@tonic-gate 	 * If panicstr is set or a poke_cpu is already pending,
560Sstevel@tonic-gate 	 * no need to send another one. Use atomic swap to protect
570Sstevel@tonic-gate 	 * against multiple CPUs sending redundant pokes.
580Sstevel@tonic-gate 	 */
590Sstevel@tonic-gate 	if (panicstr || *ptr == B_TRUE ||
600Sstevel@tonic-gate 	    atomic_swap_32(ptr, B_TRUE) == B_TRUE)
610Sstevel@tonic-gate 		return;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	xt_one(cpun, setsoftint_tl1, poke_cpu_inum, 0);
640Sstevel@tonic-gate }
65*11389SAlexander.Kolbasov@Sun.COM 
66*11389SAlexander.Kolbasov@Sun.COM extern int xc_spl_enter[];
67*11389SAlexander.Kolbasov@Sun.COM 
68*11389SAlexander.Kolbasov@Sun.COM /*
69*11389SAlexander.Kolbasov@Sun.COM  * Call a function on a target CPU
70*11389SAlexander.Kolbasov@Sun.COM  */
71*11389SAlexander.Kolbasov@Sun.COM void
cpu_call(cpu_t * cp,cpu_call_func_t func,uintptr_t arg1,uintptr_t arg2)72*11389SAlexander.Kolbasov@Sun.COM cpu_call(cpu_t *cp, cpu_call_func_t func, uintptr_t arg1, uintptr_t arg2)
73*11389SAlexander.Kolbasov@Sun.COM {
74*11389SAlexander.Kolbasov@Sun.COM 	if (panicstr)
75*11389SAlexander.Kolbasov@Sun.COM 		return;
76*11389SAlexander.Kolbasov@Sun.COM 
77*11389SAlexander.Kolbasov@Sun.COM 	/*
78*11389SAlexander.Kolbasov@Sun.COM 	 * Prevent CPU from going offline
79*11389SAlexander.Kolbasov@Sun.COM 	 */
80*11389SAlexander.Kolbasov@Sun.COM 	kpreempt_disable();
81*11389SAlexander.Kolbasov@Sun.COM 
82*11389SAlexander.Kolbasov@Sun.COM 	/*
83*11389SAlexander.Kolbasov@Sun.COM 	 * If we are on the target CPU, call the function directly, but raise
84*11389SAlexander.Kolbasov@Sun.COM 	 * the PIL to XC_PIL.
85*11389SAlexander.Kolbasov@Sun.COM 	 * This guarantees that functions called via cpu_call() can not ever
86*11389SAlexander.Kolbasov@Sun.COM 	 * interrupt each other.
87*11389SAlexander.Kolbasov@Sun.COM 	 */
88*11389SAlexander.Kolbasov@Sun.COM 	if (CPU != cp) {
89*11389SAlexander.Kolbasov@Sun.COM 		xc_one(cp->cpu_id, (xcfunc_t *)func, (uint64_t)arg1,
90*11389SAlexander.Kolbasov@Sun.COM 		    (uint64_t)arg2);
91*11389SAlexander.Kolbasov@Sun.COM 	} else {
92*11389SAlexander.Kolbasov@Sun.COM 		int lcx;
93*11389SAlexander.Kolbasov@Sun.COM 		int opl;
94*11389SAlexander.Kolbasov@Sun.COM 
95*11389SAlexander.Kolbasov@Sun.COM 		XC_SPL_ENTER(lcx, opl);
96*11389SAlexander.Kolbasov@Sun.COM 		func(arg1, arg2);
97*11389SAlexander.Kolbasov@Sun.COM 		XC_SPL_EXIT(lcx, opl);
98*11389SAlexander.Kolbasov@Sun.COM 	}
99*11389SAlexander.Kolbasov@Sun.COM 
100*11389SAlexander.Kolbasov@Sun.COM 	kpreempt_enable();
101*11389SAlexander.Kolbasov@Sun.COM }
102