xref: /freebsd/sys/powerpc/powerpc/mp_machdep.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
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