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 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 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