]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/mp_machdep.c
Ensure the boot CPU is CPU 0 on arm64
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / mp_machdep.c
1 /*-
2  * Copyright (c) 2015-2016 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Andrew Turner under
6  * sponsorship from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30
31 #include "opt_acpi.h"
32 #include "opt_ddb.h"
33 #include "opt_kstack_pages.h"
34 #include "opt_platform.h"
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/bus.h>
42 #include <sys/cpu.h>
43 #include <sys/csan.h>
44 #include <sys/kernel.h>
45 #include <sys/ktr.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
49 #include <sys/pcpu.h>
50 #include <sys/proc.h>
51 #include <sys/sched.h>
52 #include <sys/smp.h>
53
54 #include <vm/vm.h>
55 #include <vm/pmap.h>
56 #include <vm/vm_extern.h>
57 #include <vm/vm_kern.h>
58 #include <vm/vm_map.h>
59
60 #include <machine/machdep.h>
61 #include <machine/debug_monitor.h>
62 #include <machine/intr.h>
63 #include <machine/smp.h>
64 #ifdef VFP
65 #include <machine/vfp.h>
66 #endif
67
68 #ifdef DEV_ACPI
69 #include <contrib/dev/acpica/include/acpi.h>
70 #include <dev/acpica/acpivar.h>
71 #endif
72
73 #ifdef FDT
74 #include <dev/ofw/openfirm.h>
75 #include <dev/ofw/ofw_bus.h>
76 #include <dev/ofw/ofw_bus_subr.h>
77 #include <dev/ofw/ofw_cpu.h>
78 #endif
79
80 #include <dev/psci/psci.h>
81
82 #include "pic_if.h"
83
84 #define MP_QUIRK_CPULIST        0x01    /* The list of cpus may be wrong, */
85                                         /* don't panic if one fails to start */
86 static uint32_t mp_quirks;
87
88 #ifdef FDT
89 static struct {
90         const char *compat;
91         uint32_t quirks;
92 } fdt_quirks[] = {
93         { "arm,foundation-aarch64",     MP_QUIRK_CPULIST },
94         { "arm,fvp-base",               MP_QUIRK_CPULIST },
95         /* This is incorrect in some DTS files */
96         { "arm,vfp-base",               MP_QUIRK_CPULIST },
97         { NULL, 0 },
98 };
99 #endif
100
101 typedef void intr_ipi_send_t(void *, cpuset_t, u_int);
102 typedef void intr_ipi_handler_t(void *);
103
104 #define INTR_IPI_NAMELEN        (MAXCOMLEN + 1)
105 struct intr_ipi {
106         intr_ipi_handler_t *    ii_handler;
107         void *                  ii_handler_arg;
108         intr_ipi_send_t *       ii_send;
109         void *                  ii_send_arg;
110         char                    ii_name[INTR_IPI_NAMELEN];
111         u_long *                ii_count;
112 };
113
114 static struct intr_ipi ipi_sources[INTR_IPI_COUNT];
115
116 static struct intr_ipi *intr_ipi_lookup(u_int);
117 static void intr_pic_ipi_setup(u_int, const char *, intr_ipi_handler_t *,
118     void *);
119
120 static void ipi_ast(void *);
121 static void ipi_hardclock(void *);
122 static void ipi_preempt(void *);
123 static void ipi_rendezvous(void *);
124 static void ipi_stop(void *);
125
126 struct pcb stoppcbs[MAXCPU];
127
128 #ifdef FDT
129 static u_int fdt_cpuid;
130 #endif
131
132 void mpentry(unsigned long cpuid);
133 void init_secondary(uint64_t);
134
135 /* Synchronize AP startup. */
136 static struct mtx ap_boot_mtx;
137
138 /* Stacks for AP initialization, discarded once idle threads are started. */
139 void *bootstack;
140 static void *bootstacks[MAXCPU];
141
142 /* Count of started APs, used to synchronize access to bootstack. */
143 static volatile int aps_started;
144
145 /* Set to 1 once we're ready to let the APs out of the pen. */
146 static volatile int aps_ready;
147
148 /* Temporary variables for init_secondary()  */
149 void *dpcpu[MAXCPU - 1];
150
151 static bool
152 is_boot_cpu(uint64_t target_cpu)
153 {
154
155         return (__pcpu[0].pc_mpidr == (target_cpu & CPU_AFF_MASK));
156 }
157
158 static void
159 release_aps(void *dummy __unused)
160 {
161         int i, started;
162
163         /* Only release CPUs if they exist */
164         if (mp_ncpus == 1)
165                 return;
166
167         intr_pic_ipi_setup(IPI_AST, "ast", ipi_ast, NULL);
168         intr_pic_ipi_setup(IPI_PREEMPT, "preempt", ipi_preempt, NULL);
169         intr_pic_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL);
170         intr_pic_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL);
171         intr_pic_ipi_setup(IPI_STOP_HARD, "stop hard", ipi_stop, NULL);
172         intr_pic_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL);
173
174         atomic_store_rel_int(&aps_ready, 1);
175         /* Wake up the other CPUs */
176         __asm __volatile(
177             "dsb ishst  \n"
178             "sev        \n"
179             ::: "memory");
180
181         printf("Release APs...");
182
183         started = 0;
184         for (i = 0; i < 2000; i++) {
185                 if (smp_started) {
186                         printf("done\n");
187                         return;
188                 }
189                 /*
190                  * Don't time out while we are making progress. Some large
191                  * systems can take a while to start all CPUs.
192                  */
193                 if (smp_cpus > started) {
194                         i = 0;
195                         started = smp_cpus;
196                 }
197                 DELAY(1000);
198         }
199
200         printf("APs not started\n");
201 }
202 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
203
204 void
205 init_secondary(uint64_t cpu)
206 {
207         struct pcpu *pcpup;
208         pmap_t pmap0;
209
210         pcpup = &__pcpu[cpu];
211         /*
212          * Set the pcpu pointer with a backup in tpidr_el1 to be
213          * loaded when entering the kernel from userland.
214          */
215         __asm __volatile(
216             "mov x18, %0 \n"
217             "msr tpidr_el1, %0" :: "r"(pcpup));
218
219         /*
220          * Identify current CPU. This is necessary to setup
221          * affinity registers and to provide support for
222          * runtime chip identification.
223          *
224          * We need this before signalling the CPU is ready to
225          * let the boot CPU use the results.
226          */
227         identify_cpu(cpu);
228
229         /* Ensure the stores in identify_cpu have completed */
230         atomic_thread_fence_acq_rel();
231
232         /* Signal the BSP and spin until it has released all APs. */
233         atomic_add_int(&aps_started, 1);
234         while (!atomic_load_int(&aps_ready))
235                 __asm __volatile("wfe");
236
237         pcpup->pc_midr = get_midr();
238
239         /* Initialize curthread */
240         KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
241         pcpup->pc_curthread = pcpup->pc_idlethread;
242
243         /* Initialize curpmap to match TTBR0's current setting. */
244         pmap0 = vmspace_pmap(&vmspace0);
245         KASSERT(pmap_to_ttbr0(pmap0) == READ_SPECIALREG(ttbr0_el1),
246             ("pmap0 doesn't match cpu %ld's ttbr0", cpu));
247         pcpup->pc_curpmap = pmap0;
248
249         install_cpu_errata();
250
251         intr_pic_init_secondary();
252
253         /* Start per-CPU event timers. */
254         cpu_initclocks_ap();
255
256 #ifdef VFP
257         vfp_init();
258 #endif
259
260         dbg_init();
261         pan_enable();
262
263         mtx_lock_spin(&ap_boot_mtx);
264         atomic_add_rel_32(&smp_cpus, 1);
265         if (smp_cpus == mp_ncpus) {
266                 /* enable IPI's, tlb shootdown, freezes etc */
267                 atomic_store_rel_int(&smp_started, 1);
268         }
269         mtx_unlock_spin(&ap_boot_mtx);
270
271         kcsan_cpu_init(cpu);
272
273         /*
274          * Assert that smp_after_idle_runnable condition is reasonable.
275          */
276         MPASS(PCPU_GET(curpcb) == NULL);
277
278         /* Enter the scheduler */
279         sched_throw(NULL);
280
281         panic("scheduler returned us to init_secondary");
282         /* NOTREACHED */
283 }
284
285 static void
286 smp_after_idle_runnable(void *arg __unused)
287 {
288         struct pcpu *pc;
289         int cpu;
290
291         for (cpu = 1; cpu < mp_ncpus; cpu++) {
292                 if (bootstacks[cpu] != NULL) {
293                         pc = pcpu_find(cpu);
294                         while (atomic_load_ptr(&pc->pc_curpcb) == NULL)
295                                 cpu_spinwait();
296                         kmem_free((vm_offset_t)bootstacks[cpu], PAGE_SIZE);
297                 }
298         }
299 }
300 SYSINIT(smp_after_idle_runnable, SI_SUB_SMP, SI_ORDER_ANY,
301     smp_after_idle_runnable, NULL);
302
303 /*
304  *  Send IPI thru interrupt controller.
305  */
306 static void
307 pic_ipi_send(void *arg, cpuset_t cpus, u_int ipi)
308 {
309
310         KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
311
312         /*
313          * Ensure that this CPU's stores will be visible to IPI
314          * recipients before starting to send the interrupts.
315          */
316         dsb(ishst);
317
318         PIC_IPI_SEND(intr_irq_root_dev, arg, cpus, ipi);
319 }
320
321 /*
322  *  Setup IPI handler on interrupt controller.
323  *
324  *  Not SMP coherent.
325  */
326 static void
327 intr_pic_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand,
328     void *arg)
329 {
330         struct intr_irqsrc *isrc;
331         struct intr_ipi *ii;
332         int error;
333
334         KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
335         KASSERT(hand != NULL, ("%s: ipi %u no handler", __func__, ipi));
336
337         error = PIC_IPI_SETUP(intr_irq_root_dev, ipi, &isrc);
338         if (error != 0)
339                 return;
340
341         isrc->isrc_handlers++;
342
343         ii = intr_ipi_lookup(ipi);
344         KASSERT(ii->ii_count == NULL, ("%s: ipi %u reused", __func__, ipi));
345
346         ii->ii_handler = hand;
347         ii->ii_handler_arg = arg;
348         ii->ii_send = pic_ipi_send;
349         ii->ii_send_arg = isrc;
350         strlcpy(ii->ii_name, name, INTR_IPI_NAMELEN);
351         ii->ii_count = intr_ipi_setup_counters(name);
352 }
353
354 static void
355 intr_ipi_send(cpuset_t cpus, u_int ipi)
356 {
357         struct intr_ipi *ii;
358
359         ii = intr_ipi_lookup(ipi);
360         if (ii->ii_count == NULL)
361                 panic("%s: not setup IPI %u", __func__, ipi);
362
363         ii->ii_send(ii->ii_send_arg, cpus, ipi);
364 }
365
366 static void
367 ipi_ast(void *dummy __unused)
368 {
369
370         CTR0(KTR_SMP, "IPI_AST");
371 }
372
373 static void
374 ipi_hardclock(void *dummy __unused)
375 {
376
377         CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
378         hardclockintr();
379 }
380
381 static void
382 ipi_preempt(void *dummy __unused)
383 {
384         CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
385         sched_preempt(curthread);
386 }
387
388 static void
389 ipi_rendezvous(void *dummy __unused)
390 {
391
392         CTR0(KTR_SMP, "IPI_RENDEZVOUS");
393         smp_rendezvous_action();
394 }
395
396 static void
397 ipi_stop(void *dummy __unused)
398 {
399         u_int cpu;
400
401         CTR0(KTR_SMP, "IPI_STOP");
402
403         cpu = PCPU_GET(cpuid);
404         savectx(&stoppcbs[cpu]);
405
406         /* Indicate we are stopped */
407         CPU_SET_ATOMIC(cpu, &stopped_cpus);
408
409         /* Wait for restart */
410         while (!CPU_ISSET(cpu, &started_cpus))
411                 cpu_spinwait();
412
413 #ifdef DDB
414         dbg_register_sync(NULL);
415 #endif
416
417         CPU_CLR_ATOMIC(cpu, &started_cpus);
418         CPU_CLR_ATOMIC(cpu, &stopped_cpus);
419         CTR0(KTR_SMP, "IPI_STOP (restart)");
420 }
421
422 struct cpu_group *
423 cpu_topo(void)
424 {
425
426         return (smp_topo_none());
427 }
428
429 /* Determine if we running MP machine */
430 int
431 cpu_mp_probe(void)
432 {
433
434         /* ARM64TODO: Read the u bit of mpidr_el1 to determine this */
435         return (1);
436 }
437
438 /*
439  * Starts a given CPU. If the CPU is already running, i.e. it is the boot CPU,
440  * do nothing. Returns true if the CPU is present and running.
441  */
442 static bool
443 start_cpu(u_int cpuid, uint64_t target_cpu)
444 {
445         struct pcpu *pcpup;
446         vm_paddr_t pa;
447         int err, naps;
448
449         /* Check we are able to start this cpu */
450         if (cpuid > mp_maxid)
451                 return (false);
452
453         /* Skip boot CPU */
454         if (is_boot_cpu(target_cpu))
455                 return (true);
456
457         KASSERT(cpuid < MAXCPU, ("Too many CPUs"));
458
459         pcpup = &__pcpu[cpuid];
460         pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
461         pcpup->pc_mpidr = target_cpu & CPU_AFF_MASK;
462
463         dpcpu[cpuid - 1] = (void *)kmem_malloc(DPCPU_SIZE, M_WAITOK | M_ZERO);
464         dpcpu_init(dpcpu[cpuid - 1], cpuid);
465
466         bootstacks[cpuid] = (void *)kmem_malloc(PAGE_SIZE, M_WAITOK | M_ZERO);
467
468         naps = atomic_load_int(&aps_started);
469         bootstack = (char *)bootstacks[cpuid] + PAGE_SIZE;
470
471         printf("Starting CPU %u (%lx)\n", cpuid, target_cpu);
472         pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry);
473         err = psci_cpu_on(target_cpu, pa, cpuid);
474         if (err != PSCI_RETVAL_SUCCESS) {
475                 /*
476                  * Panic here if INVARIANTS are enabled and PSCI failed to
477                  * start the requested CPU.  psci_cpu_on() returns PSCI_MISSING
478                  * to indicate we are unable to use it to start the given CPU.
479                  */
480                 KASSERT(err == PSCI_MISSING ||
481                     (mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST,
482                     ("Failed to start CPU %u (%lx), error %d\n",
483                     cpuid, target_cpu, err));
484
485                 pcpu_destroy(pcpup);
486                 kmem_free((vm_offset_t)dpcpu[cpuid - 1], DPCPU_SIZE);
487                 dpcpu[cpuid - 1] = NULL;
488                 kmem_free((vm_offset_t)bootstacks[cpuid], PAGE_SIZE);
489                 bootstacks[cpuid] = NULL;
490                 mp_ncpus--;
491                 return (false);
492         }
493
494         /* Wait for the AP to switch to its boot stack. */
495         while (atomic_load_int(&aps_started) < naps + 1)
496                 cpu_spinwait();
497         CPU_SET(cpuid, &all_cpus);
498
499         return (true);
500 }
501
502 #ifdef DEV_ACPI
503 static void
504 madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
505 {
506         ACPI_MADT_GENERIC_INTERRUPT *intr;
507         u_int *cpuid;
508         u_int id;
509
510         switch(entry->Type) {
511         case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
512                 intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
513                 cpuid = arg;
514
515                 if (is_boot_cpu(intr->ArmMpidr))
516                         id = 0;
517                 else
518                         id = *cpuid;
519
520                 if (start_cpu(id, intr->ArmMpidr)) {
521                         __pcpu[id].pc_acpi_id = intr->Uid;
522                         /*
523                          * Don't increment for the boot CPU, its CPU ID is
524                          * reserved.
525                          */
526                         if (!is_boot_cpu(intr->ArmMpidr))
527                                 (*cpuid)++;
528                 }
529
530                 break;
531         default:
532                 break;
533         }
534 }
535
536 static void
537 cpu_init_acpi(void)
538 {
539         ACPI_TABLE_MADT *madt;
540         vm_paddr_t physaddr;
541         u_int cpuid;
542
543         physaddr = acpi_find_table(ACPI_SIG_MADT);
544         if (physaddr == 0)
545                 return;
546
547         madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
548         if (madt == NULL) {
549                 printf("Unable to map the MADT, not starting APs\n");
550                 return;
551         }
552         /* Boot CPU is always 0 */
553         cpuid = 1;
554         acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
555             madt_handler, &cpuid);
556
557         acpi_unmap_table(madt);
558
559 #if MAXMEMDOM > 1
560         acpi_pxm_set_cpu_locality();
561 #endif
562 }
563 #endif
564
565 #ifdef FDT
566 static boolean_t
567 start_cpu_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
568 {
569         uint64_t target_cpu;
570         int domain;
571         int cpuid;
572
573         target_cpu = reg[0];
574         if (addr_size == 2) {
575                 target_cpu <<= 32;
576                 target_cpu |= reg[1];
577         }
578
579         if (is_boot_cpu(target_cpu))
580                 cpuid = 0;
581         else
582                 cpuid = fdt_cpuid;
583
584         if (!start_cpu(cpuid, target_cpu))
585                 return (FALSE);
586
587         /*
588          * Don't increment for the boot CPU, its CPU ID is reserved.
589          */
590         if (!is_boot_cpu(target_cpu))
591                 fdt_cpuid++;
592
593         /* Try to read the numa node of this cpu */
594         if (vm_ndomains == 1 ||
595             OF_getencprop(node, "numa-node-id", &domain, sizeof(domain)) <= 0)
596                 domain = 0;
597         __pcpu[cpuid].pc_domain = domain;
598         if (domain < MAXMEMDOM)
599                 CPU_SET(cpuid, &cpuset_domain[domain]);
600         return (TRUE);
601 }
602 static void
603 cpu_init_fdt(void)
604 {
605         phandle_t node;
606         int i;
607
608         node = OF_peer(0);
609         for (i = 0; fdt_quirks[i].compat != NULL; i++) {
610                 if (ofw_bus_node_is_compatible(node,
611                     fdt_quirks[i].compat) != 0) {
612                         mp_quirks = fdt_quirks[i].quirks;
613                 }
614         }
615         fdt_cpuid = 1;
616         ofw_cpu_early_foreach(start_cpu_fdt, true);
617 }
618 #endif
619
620 /* Initialize and fire up non-boot processors */
621 void
622 cpu_mp_start(void)
623 {
624         mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
625
626         /* CPU 0 is always boot CPU. */
627         CPU_SET(0, &all_cpus);
628         __pcpu[0].pc_mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
629
630         switch(arm64_bus_method) {
631 #ifdef DEV_ACPI
632         case ARM64_BUS_ACPI:
633                 mp_quirks = MP_QUIRK_CPULIST;
634                 cpu_init_acpi();
635                 break;
636 #endif
637 #ifdef FDT
638         case ARM64_BUS_FDT:
639                 cpu_init_fdt();
640                 break;
641 #endif
642         default:
643                 break;
644         }
645 }
646
647 /* Introduce rest of cores to the world */
648 void
649 cpu_mp_announce(void)
650 {
651 }
652
653 #ifdef DEV_ACPI
654 static void
655 cpu_count_acpi_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
656 {
657         ACPI_MADT_GENERIC_INTERRUPT *intr;
658         u_int *cores = arg;
659
660         switch(entry->Type) {
661         case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
662                 intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
663                 (*cores)++;
664                 break;
665         default:
666                 break;
667         }
668 }
669
670 static u_int
671 cpu_count_acpi(void)
672 {
673         ACPI_TABLE_MADT *madt;
674         vm_paddr_t physaddr;
675         u_int cores;
676
677         physaddr = acpi_find_table(ACPI_SIG_MADT);
678         if (physaddr == 0)
679                 return (0);
680
681         madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
682         if (madt == NULL) {
683                 printf("Unable to map the MADT, not starting APs\n");
684                 return (0);
685         }
686
687         cores = 0;
688         acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
689             cpu_count_acpi_handler, &cores);
690
691         acpi_unmap_table(madt);
692
693         return (cores);
694 }
695 #endif
696
697 void
698 cpu_mp_setmaxid(void)
699 {
700         int cores;
701
702         mp_ncpus = 1;
703         mp_maxid = 0;
704
705         switch(arm64_bus_method) {
706 #ifdef DEV_ACPI
707         case ARM64_BUS_ACPI:
708                 cores = cpu_count_acpi();
709                 if (cores > 0) {
710                         cores = MIN(cores, MAXCPU);
711                         if (bootverbose)
712                                 printf("Found %d CPUs in the ACPI tables\n",
713                                     cores);
714                         mp_ncpus = cores;
715                         mp_maxid = cores - 1;
716                 }
717                 break;
718 #endif
719 #ifdef FDT
720         case ARM64_BUS_FDT:
721                 cores = ofw_cpu_early_foreach(NULL, false);
722                 if (cores > 0) {
723                         cores = MIN(cores, MAXCPU);
724                         if (bootverbose)
725                                 printf("Found %d CPUs in the device tree\n",
726                                     cores);
727                         mp_ncpus = cores;
728                         mp_maxid = cores - 1;
729                 }
730                 break;
731 #endif
732         default:
733                 if (bootverbose)
734                         printf("No CPU data, limiting to 1 core\n");
735                 break;
736         }
737
738         if (TUNABLE_INT_FETCH("hw.ncpu", &cores)) {
739                 if (cores > 0 && cores < mp_ncpus) {
740                         mp_ncpus = cores;
741                         mp_maxid = cores - 1;
742                 }
743         }
744 }
745
746 /*
747  *  Lookup IPI source.
748  */
749 static struct intr_ipi *
750 intr_ipi_lookup(u_int ipi)
751 {
752
753         if (ipi >= INTR_IPI_COUNT)
754                 panic("%s: no such IPI %u", __func__, ipi);
755
756         return (&ipi_sources[ipi]);
757 }
758
759 /*
760  *  interrupt controller dispatch function for IPIs. It should
761  *  be called straight from the interrupt controller, when associated
762  *  interrupt source is learned. Or from anybody who has an interrupt
763  *  source mapped.
764  */
765 void
766 intr_ipi_dispatch(u_int ipi, struct trapframe *tf)
767 {
768         void *arg;
769         struct intr_ipi *ii;
770
771         ii = intr_ipi_lookup(ipi);
772         if (ii->ii_count == NULL)
773                 panic("%s: not setup IPI %u", __func__, ipi);
774
775         intr_ipi_increment_count(ii->ii_count, PCPU_GET(cpuid));
776
777         /*
778          * Supply ipi filter with trapframe argument
779          * if none is registered.
780          */
781         arg = ii->ii_handler_arg != NULL ? ii->ii_handler_arg : tf;
782         ii->ii_handler(arg);
783 }
784
785 #ifdef notyet
786 /*
787  *  Map IPI into interrupt controller.
788  *
789  *  Not SMP coherent.
790  */
791 static int
792 ipi_map(struct intr_irqsrc *isrc, u_int ipi)
793 {
794         boolean_t is_percpu;
795         int error;
796
797         if (ipi >= INTR_IPI_COUNT)
798                 panic("%s: no such IPI %u", __func__, ipi);
799
800         KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
801
802         isrc->isrc_type = INTR_ISRCT_NAMESPACE;
803         isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI;
804         isrc->isrc_nspc_num = ipi_next_num;
805
806         error = PIC_REGISTER(intr_irq_root_dev, isrc, &is_percpu);
807         if (error == 0) {
808                 isrc->isrc_dev = intr_irq_root_dev;
809                 ipi_next_num++;
810         }
811         return (error);
812 }
813
814 /*
815  *  Setup IPI handler to interrupt source.
816  *
817  *  Note that there could be more ways how to send and receive IPIs
818  *  on a platform like fast interrupts for example. In that case,
819  *  one can call this function with ASIF_NOALLOC flag set and then
820  *  call intr_ipi_dispatch() when appropriate.
821  *
822  *  Not SMP coherent.
823  */
824 int
825 intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
826     void *arg, u_int flags)
827 {
828         struct intr_irqsrc *isrc;
829         int error;
830
831         if (filter == NULL)
832                 return(EINVAL);
833
834         isrc = intr_ipi_lookup(ipi);
835         if (isrc->isrc_ipifilter != NULL)
836                 return (EEXIST);
837
838         if ((flags & AISHF_NOALLOC) == 0) {
839                 error = ipi_map(isrc, ipi);
840                 if (error != 0)
841                         return (error);
842         }
843
844         isrc->isrc_ipifilter = filter;
845         isrc->isrc_arg = arg;
846         isrc->isrc_handlers = 1;
847         isrc->isrc_count = intr_ipi_setup_counters(name);
848         isrc->isrc_index = 0; /* it should not be used in IPI case */
849
850         if (isrc->isrc_dev != NULL) {
851                 PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
852                 PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
853         }
854         return (0);
855 }
856 #endif
857
858 /* Sending IPI */
859 void
860 ipi_all_but_self(u_int ipi)
861 {
862         cpuset_t cpus;
863
864         cpus = all_cpus;
865         CPU_CLR(PCPU_GET(cpuid), &cpus);
866         CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
867         intr_ipi_send(cpus, ipi);
868 }
869
870 void
871 ipi_cpu(int cpu, u_int ipi)
872 {
873         cpuset_t cpus;
874
875         CPU_ZERO(&cpus);
876         CPU_SET(cpu, &cpus);
877
878         CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi);
879         intr_ipi_send(cpus, ipi);
880 }
881
882 void
883 ipi_selected(cpuset_t cpus, u_int ipi)
884 {
885
886         CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
887         intr_ipi_send(cpus, ipi);
888 }