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