11519f58fSDavid E. O'Brien /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
371e3c308SPedro F. Giffuni *
412640815SMarcel Moolenaar * Copyright (c) 2008 Marcel Moolenaar
51519f58fSDavid E. O'Brien * All rights reserved.
61519f58fSDavid E. O'Brien *
71519f58fSDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
81519f58fSDavid E. O'Brien * modification, are permitted provided that the following conditions
91519f58fSDavid E. O'Brien * are met:
1012640815SMarcel Moolenaar *
111519f58fSDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
121519f58fSDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
131519f58fSDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
141519f58fSDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
151519f58fSDavid E. O'Brien * documentation and/or other materials provided with the distribution.
161519f58fSDavid E. O'Brien *
1712640815SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1812640815SMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1912640815SMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2012640815SMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2112640815SMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2212640815SMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312640815SMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412640815SMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512640815SMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2612640815SMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271519f58fSDavid E. O'Brien */
281519f58fSDavid E. O'Brien
291519f58fSDavid E. O'Brien #include <sys/param.h>
301519f58fSDavid E. O'Brien #include <sys/systm.h>
311519f58fSDavid E. O'Brien #include <sys/kernel.h>
327ad9c533SRafal Jaworowski #include <sys/ktr.h>
3312640815SMarcel Moolenaar #include <sys/bus.h>
34c47dd3dbSAttilio Rao #include <sys/cpuset.h>
350cfa351eSJustin Hibbits #include <sys/domainset.h>
36d8acfb88SPeter Grehan #include <sys/lock.h>
375df87b21SJeff Roberson #include <sys/malloc.h>
38d8acfb88SPeter Grehan #include <sys/mutex.h>
3912640815SMarcel Moolenaar #include <sys/pcpu.h>
4012640815SMarcel Moolenaar #include <sys/proc.h>
4112640815SMarcel Moolenaar #include <sys/sched.h>
426caa8a15SJohn Baldwin #include <sys/smp.h>
431519f58fSDavid E. O'Brien
44b7c3d413SJeff Roberson #include <vm/vm.h>
45b7c3d413SJeff Roberson #include <vm/vm_param.h>
46b7c3d413SJeff Roberson #include <vm/pmap.h>
47b7c3d413SJeff Roberson #include <vm/vm_map.h>
48b7c3d413SJeff Roberson #include <vm/vm_extern.h>
49b7c3d413SJeff Roberson #include <vm/vm_kern.h>
50b7c3d413SJeff Roberson
5112640815SMarcel Moolenaar #include <machine/bus.h>
5212640815SMarcel Moolenaar #include <machine/cpu.h>
5312640815SMarcel Moolenaar #include <machine/intr_machdep.h>
543d20a480SAndreas Tobler #include <machine/pcb.h>
55b40ce02aSNathan Whitehorn #include <machine/platform.h>
567ad9c533SRafal Jaworowski #include <machine/md_var.h>
574702d987SJustin Hibbits #include <machine/setjmp.h>
5812640815SMarcel Moolenaar #include <machine/smp.h>
591519f58fSDavid E. O'Brien
6012640815SMarcel Moolenaar #include "pic_if.h"
611519f58fSDavid E. O'Brien
6212640815SMarcel Moolenaar volatile static int ap_awake;
637ad9c533SRafal Jaworowski volatile static u_int ap_letgo;
647ad9c533SRafal Jaworowski volatile static u_quad_t ap_timebase;
65d8acfb88SPeter Grehan static struct mtx ap_boot_mtx;
6612640815SMarcel Moolenaar
6712640815SMarcel Moolenaar void
machdep_ap_bootstrap(void)68c139f23dSMarcel Moolenaar machdep_ap_bootstrap(void)
6912640815SMarcel Moolenaar {
7012640815SMarcel Moolenaar
717ad9c533SRafal Jaworowski PCPU_SET(awake, 1);
727ad9c533SRafal Jaworowski __asm __volatile("msync; isync");
7312640815SMarcel Moolenaar
747ad9c533SRafal Jaworowski while (ap_letgo == 0)
75e92d228bSJustin Hibbits nop_prio_vlow();
76e92d228bSJustin Hibbits nop_prio_medium();
7712640815SMarcel Moolenaar
78778c8dacSNathan Whitehorn /*
79778c8dacSNathan Whitehorn * Set timebase as soon as possible to meet an implicit rendezvous
80778c8dacSNathan Whitehorn * from cpu_mp_unleash(), which sets ap_letgo and then immediately
81778c8dacSNathan Whitehorn * sets timebase.
82778c8dacSNathan Whitehorn *
83778c8dacSNathan Whitehorn * Note that this is instrinsically racy and is only relevant on
84778c8dacSNathan Whitehorn * platforms that do not support better mechanisms.
85778c8dacSNathan Whitehorn */
86778c8dacSNathan Whitehorn platform_smp_timebase_sync(ap_timebase, 1);
87778c8dacSNathan Whitehorn
88778c8dacSNathan Whitehorn /* Give platform code a chance to do anything else necessary */
89720212d3SWojciech Macek platform_smp_ap_init();
90720212d3SWojciech Macek
91778c8dacSNathan Whitehorn /* Initialize decrementer */
92707c2fb9SAlexander Motin decr_ap_init();
9312640815SMarcel Moolenaar
94d8acfb88SPeter Grehan /* Serialize console output and AP count increment */
95d8acfb88SPeter Grehan mtx_lock_spin(&ap_boot_mtx);
96d8acfb88SPeter Grehan ap_awake++;
97b465e0bbSJustin Hibbits if (bootverbose)
98999987e5SNathan Whitehorn printf("SMP: AP CPU #%d launched\n", PCPU_GET(cpuid));
99b465e0bbSJustin Hibbits else
100b465e0bbSJustin Hibbits printf("%s%d%s", ap_awake == 2 ? "Launching APs: " : "",
101b465e0bbSJustin Hibbits PCPU_GET(cpuid), ap_awake == mp_ncpus ? "\n" : " ");
102d8acfb88SPeter Grehan mtx_unlock_spin(&ap_boot_mtx);
10312640815SMarcel Moolenaar
104b74fb1e7SWojciech Macek while(smp_started == 0)
105b74fb1e7SWojciech Macek ;
106b74fb1e7SWojciech Macek
107707c2fb9SAlexander Motin /* Start per-CPU event timers. */
108707c2fb9SAlexander Motin cpu_initclocks_ap();
109707c2fb9SAlexander Motin
110999987e5SNathan Whitehorn /* Announce ourselves awake, and enter the scheduler */
1116a8ea6d1SKyle Evans sched_ap_entry();
11212640815SMarcel Moolenaar }
1131519f58fSDavid E. O'Brien
114798a4596SJohn Baldwin void
cpu_mp_setmaxid(void)115798a4596SJohn Baldwin cpu_mp_setmaxid(void)
116798a4596SJohn Baldwin {
11712640815SMarcel Moolenaar struct cpuref cpuref;
11812640815SMarcel Moolenaar int error;
11912640815SMarcel Moolenaar
12012640815SMarcel Moolenaar mp_ncpus = 0;
12196c85efbSNathan Whitehorn mp_maxid = 0;
122b40ce02aSNathan Whitehorn error = platform_smp_first_cpu(&cpuref);
12312640815SMarcel Moolenaar while (!error) {
12412640815SMarcel Moolenaar mp_ncpus++;
12596c85efbSNathan Whitehorn mp_maxid = max(cpuref.cr_cpuid, mp_maxid);
126b40ce02aSNathan Whitehorn error = platform_smp_next_cpu(&cpuref);
12712640815SMarcel Moolenaar }
12812640815SMarcel Moolenaar /* Sanity. */
12912640815SMarcel Moolenaar if (mp_ncpus == 0)
13012640815SMarcel Moolenaar mp_ncpus = 1;
131798a4596SJohn Baldwin }
132798a4596SJohn Baldwin
1331519f58fSDavid E. O'Brien int
cpu_mp_probe(void)134f2909e6cSJohn Baldwin cpu_mp_probe(void)
1351519f58fSDavid E. O'Brien {
13612640815SMarcel Moolenaar
13712640815SMarcel Moolenaar /*
13812640815SMarcel Moolenaar * We're not going to enable SMP if there's only 1 processor.
13912640815SMarcel Moolenaar */
14012640815SMarcel Moolenaar return (mp_ncpus > 1);
1411519f58fSDavid E. O'Brien }
1421519f58fSDavid E. O'Brien
1431519f58fSDavid E. O'Brien void
cpu_mp_start(void)144f2909e6cSJohn Baldwin cpu_mp_start(void)
1451519f58fSDavid E. O'Brien {
14612640815SMarcel Moolenaar struct cpuref bsp, cpu;
14712640815SMarcel Moolenaar struct pcpu *pc;
1480cfa351eSJustin Hibbits int domain, error;
14912640815SMarcel Moolenaar
150b40ce02aSNathan Whitehorn error = platform_smp_get_bsp(&bsp);
15112640815SMarcel Moolenaar KASSERT(error == 0, ("Don't know BSP"));
15212640815SMarcel Moolenaar
153b40ce02aSNathan Whitehorn error = platform_smp_first_cpu(&cpu);
15412640815SMarcel Moolenaar while (!error) {
15512640815SMarcel Moolenaar if (cpu.cr_cpuid >= MAXCPU) {
15612640815SMarcel Moolenaar printf("SMP: cpu%d: skipped -- ID out of range\n",
15712640815SMarcel Moolenaar cpu.cr_cpuid);
15812640815SMarcel Moolenaar goto next;
15912640815SMarcel Moolenaar }
160c47dd3dbSAttilio Rao if (CPU_ISSET(cpu.cr_cpuid, &all_cpus)) {
16112640815SMarcel Moolenaar printf("SMP: cpu%d: skipped - duplicate ID\n",
16212640815SMarcel Moolenaar cpu.cr_cpuid);
16312640815SMarcel Moolenaar goto next;
16412640815SMarcel Moolenaar }
1650cfa351eSJustin Hibbits
1660cfa351eSJustin Hibbits if (vm_ndomains > 1)
1670cfa351eSJustin Hibbits domain = cpu.cr_domain;
1680cfa351eSJustin Hibbits else
1690cfa351eSJustin Hibbits domain = 0;
1700cfa351eSJustin Hibbits
17112640815SMarcel Moolenaar if (cpu.cr_cpuid != bsp.cr_cpuid) {
17250c202c5SJeff Roberson void *dpcpu;
17350c202c5SJeff Roberson
17412640815SMarcel Moolenaar pc = &__pcpu[cpu.cr_cpuid];
175f49fd63aSJohn Baldwin dpcpu = kmem_malloc_domainset(DOMAINSET_PREF(domain),
1760cfa351eSJustin Hibbits DPCPU_SIZE, M_WAITOK | M_ZERO);
17712640815SMarcel Moolenaar pcpu_init(pc, cpu.cr_cpuid, sizeof(*pc));
17850c202c5SJeff Roberson dpcpu_init(dpcpu, cpu.cr_cpuid);
17912640815SMarcel Moolenaar } else {
18012640815SMarcel Moolenaar pc = pcpup;
18112640815SMarcel Moolenaar pc->pc_cpuid = bsp.cr_cpuid;
18212640815SMarcel Moolenaar pc->pc_bsp = 1;
18312640815SMarcel Moolenaar }
1840cfa351eSJustin Hibbits pc->pc_domain = domain;
18512640815SMarcel Moolenaar pc->pc_hwref = cpu.cr_hwref;
18649d9a597SJustin Hibbits
18749d9a597SJustin Hibbits CPU_SET(pc->pc_cpuid, &cpuset_domain[pc->pc_domain]);
18849d9a597SJustin Hibbits KASSERT(pc->pc_domain < MAXMEMDOM, ("bad domain value %d\n",
18949d9a597SJustin Hibbits pc->pc_domain));
190c7c2767eSAttilio Rao CPU_SET(pc->pc_cpuid, &all_cpus);
19112640815SMarcel Moolenaar next:
192b40ce02aSNathan Whitehorn error = platform_smp_next_cpu(&cpu);
19312640815SMarcel Moolenaar }
1946b83069eSConrad Meyer
1956b83069eSConrad Meyer #ifdef SMP
196bba9cbe3SConrad Meyer platform_smp_probe_threads();
1976b83069eSConrad Meyer #endif
1981519f58fSDavid E. O'Brien }
1991519f58fSDavid E. O'Brien
200f2909e6cSJohn Baldwin void
cpu_mp_announce(void)201f2909e6cSJohn Baldwin cpu_mp_announce(void)
2021519f58fSDavid E. O'Brien {
20312640815SMarcel Moolenaar struct pcpu *pc;
20412640815SMarcel Moolenaar int i;
20512640815SMarcel Moolenaar
206f04a8fd6SNathan Whitehorn if (!bootverbose)
207f04a8fd6SNathan Whitehorn return;
208f04a8fd6SNathan Whitehorn
209de2dd83fSNathan Whitehorn CPU_FOREACH(i) {
21012640815SMarcel Moolenaar pc = pcpu_find(i);
21112640815SMarcel Moolenaar if (pc == NULL)
21212640815SMarcel Moolenaar continue;
21349d9a597SJustin Hibbits printf("cpu%d: dev=%x domain=%d ", i, (int)pc->pc_hwref, pc->pc_domain);
21412640815SMarcel Moolenaar if (pc->pc_bsp)
21512640815SMarcel Moolenaar printf(" (BSP)");
21612640815SMarcel Moolenaar printf("\n");
21712640815SMarcel Moolenaar }
21812640815SMarcel Moolenaar }
21912640815SMarcel Moolenaar
22012640815SMarcel Moolenaar static void
cpu_mp_unleash(void * dummy)22112640815SMarcel Moolenaar cpu_mp_unleash(void *dummy)
22212640815SMarcel Moolenaar {
22312640815SMarcel Moolenaar struct pcpu *pc;
2247ad9c533SRafal Jaworowski int cpus, timeout;
225b74fb1e7SWojciech Macek int ret;
22612640815SMarcel Moolenaar
22712640815SMarcel Moolenaar if (mp_ncpus <= 1)
22812640815SMarcel Moolenaar return;
22912640815SMarcel Moolenaar
230d8acfb88SPeter Grehan mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
231d8acfb88SPeter Grehan
23212640815SMarcel Moolenaar cpus = 0;
23312640815SMarcel Moolenaar smp_cpus = 0;
234f60708c9SJustin Hibbits #ifdef BOOKE
235f60708c9SJustin Hibbits tlb1_ap_prep();
236f60708c9SJustin Hibbits #endif
237d098f930SNathan Whitehorn STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
23812640815SMarcel Moolenaar cpus++;
23912640815SMarcel Moolenaar if (!pc->pc_bsp) {
2407ad9c533SRafal Jaworowski if (bootverbose)
2417ad9c533SRafal Jaworowski printf("Waking up CPU %d (dev=%x)\n",
242c3e289e1SNathan Whitehorn pc->pc_cpuid, (int)pc->pc_hwref);
2437ad9c533SRafal Jaworowski
2443f24b505SJustin Hibbits pc->pc_flags = PCPU_GET(flags); /* Copy cached CPU flags */
245b74fb1e7SWojciech Macek ret = platform_smp_start_cpu(pc);
246b74fb1e7SWojciech Macek if (ret == 0) {
2477ad9c533SRafal Jaworowski timeout = 2000; /* wait 2sec for the AP */
2487ad9c533SRafal Jaworowski while (!pc->pc_awake && --timeout > 0)
2497ad9c533SRafal Jaworowski DELAY(1000);
250b74fb1e7SWojciech Macek }
25112640815SMarcel Moolenaar } else {
25212640815SMarcel Moolenaar pc->pc_awake = 1;
25312640815SMarcel Moolenaar }
2547ad9c533SRafal Jaworowski if (pc->pc_awake) {
2557ad9c533SRafal Jaworowski if (bootverbose)
2563972f4c1SNathan Whitehorn printf("Adding CPU %d, hwref=%jx, awake=%x\n",
2573972f4c1SNathan Whitehorn pc->pc_cpuid, (uintmax_t)pc->pc_hwref,
2583972f4c1SNathan Whitehorn pc->pc_awake);
25912640815SMarcel Moolenaar smp_cpus++;
2607ad9c533SRafal Jaworowski } else
261c47dd3dbSAttilio Rao CPU_SET(pc->pc_cpuid, &stopped_cpus);
26212640815SMarcel Moolenaar }
26312640815SMarcel Moolenaar
26412640815SMarcel Moolenaar ap_awake = 1;
265bdd42e42SMarcel Moolenaar
2667ad9c533SRafal Jaworowski /* Provide our current DEC and TB values for APs */
2677ad9c533SRafal Jaworowski ap_timebase = mftb() + 10;
2687ad9c533SRafal Jaworowski __asm __volatile("msync; isync");
269bdd42e42SMarcel Moolenaar
2707ad9c533SRafal Jaworowski /* Let APs continue */
2717ad9c533SRafal Jaworowski atomic_store_rel_int(&ap_letgo, 1);
2727ad9c533SRafal Jaworowski
273de2dd83fSNathan Whitehorn platform_smp_timebase_sync(ap_timebase, 0);
27412640815SMarcel Moolenaar
27512640815SMarcel Moolenaar while (ap_awake < smp_cpus)
27612640815SMarcel Moolenaar ;
27712640815SMarcel Moolenaar
27812640815SMarcel Moolenaar if (smp_cpus != cpus || cpus != mp_ncpus) {
27912640815SMarcel Moolenaar printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n",
28012640815SMarcel Moolenaar mp_ncpus, cpus, smp_cpus);
28112640815SMarcel Moolenaar }
28212640815SMarcel Moolenaar
283b74fb1e7SWojciech Macek if (smp_cpus > 1)
284b74fb1e7SWojciech Macek atomic_store_rel_int(&smp_started, 1);
285b74fb1e7SWojciech Macek
286999987e5SNathan Whitehorn /* Let the APs get into the scheduler */
287999987e5SNathan Whitehorn DELAY(10000);
288999987e5SNathan Whitehorn
28912640815SMarcel Moolenaar }
29012640815SMarcel Moolenaar
29112640815SMarcel Moolenaar SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
29212640815SMarcel Moolenaar
29312640815SMarcel Moolenaar int
powerpc_ipi_handler(void * arg)29412640815SMarcel Moolenaar powerpc_ipi_handler(void *arg)
29512640815SMarcel Moolenaar {
296c7c2767eSAttilio Rao u_int cpuid;
29712640815SMarcel Moolenaar uint32_t ipimask;
29812640815SMarcel Moolenaar
29928bb01e5SRafal Jaworowski CTR2(KTR_SMP, "%s: MSR 0x%08x", __func__, mfmsr());
30028bb01e5SRafal Jaworowski
30112640815SMarcel Moolenaar ipimask = atomic_readandclear_32(&(pcpup->pc_ipimask));
30212640815SMarcel Moolenaar if (ipimask == 0)
30312640815SMarcel Moolenaar return (FILTER_STRAY);
3047ed09a67SJustin Hibbits if (ipimask & (1 << IPI_AST)) {
30528bb01e5SRafal Jaworowski CTR1(KTR_SMP, "%s: IPI_AST", __func__);
3067ed09a67SJustin Hibbits }
3077ed09a67SJustin Hibbits if (ipimask & (1 << IPI_PREEMPT)) {
30828bb01e5SRafal Jaworowski CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
30912640815SMarcel Moolenaar sched_preempt(curthread);
3107ed09a67SJustin Hibbits }
3117ed09a67SJustin Hibbits if (ipimask & (1 << IPI_RENDEZVOUS)) {
31228bb01e5SRafal Jaworowski CTR1(KTR_SMP, "%s: IPI_RENDEZVOUS", __func__);
31312640815SMarcel Moolenaar smp_rendezvous_action();
3147ed09a67SJustin Hibbits }
3157ed09a67SJustin Hibbits if (ipimask & (1 << IPI_STOP)) {
316dc6fbf65SAttilio Rao
317dc6fbf65SAttilio Rao /*
318dc6fbf65SAttilio Rao * IPI_STOP_HARD is mapped to IPI_STOP so it is not
3197ed09a67SJustin Hibbits * necessary to add such case.
320dc6fbf65SAttilio Rao */
321dc6fbf65SAttilio Rao CTR1(KTR_SMP, "%s: IPI_STOP or IPI_STOP_HARD (stop)",
322dc6fbf65SAttilio Rao __func__);
323c7c2767eSAttilio Rao cpuid = PCPU_GET(cpuid);
324c7c2767eSAttilio Rao savectx(&stoppcbs[cpuid]);
325c7c2767eSAttilio Rao CPU_SET_ATOMIC(cpuid, &stopped_cpus);
326c7c2767eSAttilio Rao while (!CPU_ISSET(cpuid, &started_cpus))
32712640815SMarcel Moolenaar cpu_spinwait();
328c7c2767eSAttilio Rao CPU_CLR_ATOMIC(cpuid, &stopped_cpus);
329c7c2767eSAttilio Rao CPU_CLR_ATOMIC(cpuid, &started_cpus);
33028bb01e5SRafal Jaworowski CTR1(KTR_SMP, "%s: IPI_STOP (restart)", __func__);
3317ed09a67SJustin Hibbits }
3327ed09a67SJustin Hibbits if (ipimask & (1 << IPI_HARDCLOCK)) {
333707c2fb9SAlexander Motin CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
334a157e425SAlexander Motin hardclockintr();
33512640815SMarcel Moolenaar }
33612640815SMarcel Moolenaar
33712640815SMarcel Moolenaar return (FILTER_HANDLED);
33812640815SMarcel Moolenaar }
33912640815SMarcel Moolenaar
34012640815SMarcel Moolenaar static void
ipi_send(struct pcpu * pc,int ipi)34112640815SMarcel Moolenaar ipi_send(struct pcpu *pc, int ipi)
34212640815SMarcel Moolenaar {
34312640815SMarcel Moolenaar
34428bb01e5SRafal Jaworowski CTR4(KTR_SMP, "%s: pc=%p, targetcpu=%d, IPI=%d", __func__,
34528bb01e5SRafal Jaworowski pc, pc->pc_cpuid, ipi);
34628bb01e5SRafal Jaworowski
34712640815SMarcel Moolenaar atomic_set_32(&pc->pc_ipimask, (1 << ipi));
3480c50edffSNathan Whitehorn powerpc_sync();
349eaef5f0aSNathan Whitehorn PIC_IPI(root_pic, pc->pc_cpuid);
35028bb01e5SRafal Jaworowski
35128bb01e5SRafal Jaworowski CTR1(KTR_SMP, "%s: sent", __func__);
35212640815SMarcel Moolenaar }
35312640815SMarcel Moolenaar
35412640815SMarcel Moolenaar /* Send an IPI to a set of cpus. */
35512640815SMarcel Moolenaar void
ipi_selected(cpuset_t cpus,int ipi)356c47dd3dbSAttilio Rao ipi_selected(cpuset_t cpus, int ipi)
35712640815SMarcel Moolenaar {
35812640815SMarcel Moolenaar struct pcpu *pc;
35912640815SMarcel Moolenaar
360d098f930SNathan Whitehorn STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
361c7c2767eSAttilio Rao if (CPU_ISSET(pc->pc_cpuid, &cpus))
36212640815SMarcel Moolenaar ipi_send(pc, ipi);
36312640815SMarcel Moolenaar }
36412640815SMarcel Moolenaar }
36512640815SMarcel Moolenaar
366d9d8d144SJohn Baldwin /* Send an IPI to a specific CPU. */
367d9d8d144SJohn Baldwin void
ipi_cpu(int cpu,u_int ipi)368d9d8d144SJohn Baldwin ipi_cpu(int cpu, u_int ipi)
369d9d8d144SJohn Baldwin {
370d9d8d144SJohn Baldwin
371d9d8d144SJohn Baldwin ipi_send(cpuid_to_pcpu[cpu], ipi);
372d9d8d144SJohn Baldwin }
373d9d8d144SJohn Baldwin
37412640815SMarcel Moolenaar /* Send an IPI to all CPUs EXCEPT myself. */
37512640815SMarcel Moolenaar void
ipi_all_but_self(int ipi)37612640815SMarcel Moolenaar ipi_all_but_self(int ipi)
37712640815SMarcel Moolenaar {
37812640815SMarcel Moolenaar struct pcpu *pc;
37912640815SMarcel Moolenaar
380d098f930SNathan Whitehorn STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
38112640815SMarcel Moolenaar if (pc != pcpup)
38212640815SMarcel Moolenaar ipi_send(pc, ipi);
38312640815SMarcel Moolenaar }
38412640815SMarcel Moolenaar }
385