xref: /freebsd/sys/arm64/arm64/mp_machdep.c (revision 1ae25866767d686067fe6678b62681b7a8f0d361)
1 /*-
2  * Copyright (c) 2015-2016 The FreeBSD Foundation
3  *
4  * This software was developed by Andrew Turner under
5  * sponsorship from the FreeBSD Foundation.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 #include "opt_acpi.h"
31 #include "opt_ddb.h"
32 #include "opt_kstack_pages.h"
33 #include "opt_platform.h"
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/cpu.h>
39 #include <sys/csan.h>
40 #include <sys/domainset.h>
41 #include <sys/kernel.h>
42 #include <sys/ktr.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/mutex.h>
46 #include <sys/pcpu.h>
47 #include <sys/proc.h>
48 #include <sys/sched.h>
49 #include <sys/smp.h>
50 
51 #include <vm/vm.h>
52 #include <vm/pmap.h>
53 #include <vm/vm_extern.h>
54 #include <vm/vm_kern.h>
55 #include <vm/vm_map.h>
56 
57 #include <machine/machdep.h>
58 #include <machine/cpu.h>
59 #include <machine/cpu_feat.h>
60 #include <machine/debug_monitor.h>
61 #include <machine/intr.h>
62 #include <machine/smp.h>
63 #include <machine/vmparam.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 #define	MP_BOOTSTACK_SIZE	(kstack_pages * PAGE_SIZE)
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 	{ "arm,fvp-base-revc",		MP_QUIRK_CPULIST },
96 	/* This is incorrect in some DTS files */
97 	{ "arm,vfp-base",		MP_QUIRK_CPULIST },
98 	{ NULL, 0 },
99 };
100 #endif
101 
102 static void ipi_ast(void *);
103 static void ipi_hardclock(void *);
104 static void ipi_preempt(void *);
105 static void ipi_rendezvous(void *);
106 static void ipi_stop(void *);
107 static void ipi_off(void *);
108 
109 #ifdef FDT
110 static u_int fdt_cpuid;
111 #endif
112 
113 void mpentry_psci(unsigned long cpuid);
114 void mpentry_spintable(void);
115 void init_secondary(uint64_t);
116 
117 /* Used to initialize the PCPU ahead of calling init_secondary(). */
118 void *bootpcpu;
119 uint64_t ap_cpuid;
120 
121 /* Stacks for AP initialization, discarded once idle threads are started. */
122 void *bootstack;
123 static void *bootstacks[MAXCPU];
124 
125 /* Count of started APs, used to synchronize access to bootstack. */
126 static volatile int aps_started;
127 
128 /* Set to 1 once we're ready to let the APs out of the pen. */
129 static volatile int aps_after_dev, aps_ready;
130 
131 /* Temporary variables for init_secondary()  */
132 static void *dpcpu[MAXCPU - 1];
133 
134 static bool
is_boot_cpu(uint64_t target_cpu)135 is_boot_cpu(uint64_t target_cpu)
136 {
137 
138 	return (PCPU_GET_MPIDR(cpuid_to_pcpu[0]) == (target_cpu & CPU_AFF_MASK));
139 }
140 
141 static bool
wait_for_aps(void)142 wait_for_aps(void)
143 {
144 	for (int i = 0, started = 0; i < 2000; i++) {
145 		int32_t nstarted;
146 
147 		nstarted = atomic_load_32(&aps_started);
148 		if (nstarted == mp_ncpus - 1)
149 			return (true);
150 
151 		/*
152 		 * Don't time out while we are making progress. Some large
153 		 * systems can take a while to start all CPUs.
154 		 */
155 		if (nstarted > started) {
156 			i = 0;
157 			started = nstarted;
158 		}
159 		DELAY(1000);
160 	}
161 
162 	return (false);
163 }
164 
165 static void
release_aps_after_dev(void * dummy __unused)166 release_aps_after_dev(void *dummy __unused)
167 {
168 	/* Only release CPUs if they exist */
169 	if (mp_ncpus == 1)
170 		return;
171 
172 	atomic_store_int(&aps_started, 0);
173 	atomic_store_rel_int(&aps_after_dev, 1);
174 	/* Wake up the other CPUs */
175 	__asm __volatile(
176 	    "dsb ishst	\n"
177 	    "sev	\n"
178 	    ::: "memory");
179 
180 	wait_for_aps();
181 }
182 SYSINIT(aps_after_dev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE + 1,
183     release_aps_after_dev, NULL);
184 
185 static void
release_aps(void * dummy __unused)186 release_aps(void *dummy __unused)
187 {
188 	/* Only release CPUs if they exist */
189 	if (mp_ncpus == 1)
190 		return;
191 
192 	intr_ipi_setup(IPI_AST, "ast", ipi_ast, NULL);
193 	intr_ipi_setup(IPI_PREEMPT, "preempt", ipi_preempt, NULL);
194 	intr_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL);
195 	intr_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL);
196 	intr_ipi_setup(IPI_STOP_HARD, "stop hard", ipi_stop, NULL);
197 	intr_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL);
198 	intr_ipi_setup(IPI_OFF, "off", ipi_off, NULL);
199 
200 	atomic_store_int(&aps_started, 0);
201 	atomic_store_rel_int(&aps_ready, 1);
202 	/* Wake up the other CPUs */
203 	__asm __volatile(
204 	    "dsb ishst	\n"
205 	    "sev	\n"
206 	    ::: "memory");
207 
208 	printf("Release APs...");
209 
210 	if (wait_for_aps())
211 		printf("done\n");
212 	else
213 		printf("APs not started\n");
214 
215 	smp_cpus = atomic_load_int(&aps_started) + 1;
216 	atomic_store_rel_int(&smp_started, 1);
217 }
218 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
219 
220 void
init_secondary(uint64_t cpu)221 init_secondary(uint64_t cpu)
222 {
223 	struct pcpu *pcpup;
224 	pmap_t pmap0;
225 	uint64_t mpidr;
226 
227 	ptrauth_mp_start(cpu);
228 
229 	/*
230 	 * Verify that the value passed in 'cpu' argument (aka context_id) is
231 	 * valid. Some older U-Boot based PSCI implementations are buggy,
232 	 * they can pass random value in it.
233 	 */
234 	mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
235 	if (cpu >= MAXCPU || cpuid_to_pcpu[cpu] == NULL ||
236 	    PCPU_GET_MPIDR(cpuid_to_pcpu[cpu]) != mpidr) {
237 		for (cpu = 0; cpu < mp_maxid; cpu++)
238 			if (cpuid_to_pcpu[cpu] != NULL &&
239 			    PCPU_GET_MPIDR(cpuid_to_pcpu[cpu]) == mpidr)
240 				break;
241 		if ( cpu >= MAXCPU)
242 			panic("MPIDR for this CPU is not in pcpu table");
243 	}
244 
245 	/*
246 	 * Identify current CPU. This is necessary to setup
247 	 * affinity registers and to provide support for
248 	 * runtime chip identification.
249 	 *
250 	 * We need this before signalling the CPU is ready to
251 	 * let the boot CPU use the results.
252 	 */
253 	pcpup = cpuid_to_pcpu[cpu];
254 	pcpup->pc_midr = get_midr();
255 	identify_cpu(cpu);
256 
257 	/* Ensure the stores in identify_cpu have completed */
258 	atomic_thread_fence_acq_rel();
259 
260 	/* Detect early CPU feature support */
261 	enable_cpu_feat(CPU_FEAT_EARLY_BOOT);
262 
263 	/* Signal we are waiting for aps_after_dev */
264 	atomic_add_int(&aps_started, 1);
265 
266 	/* Wait for devices to be ready */
267 	while (!atomic_load_int(&aps_after_dev))
268 		__asm __volatile("wfe");
269 
270 	install_cpu_errata();
271 	enable_cpu_feat(CPU_FEAT_AFTER_DEV);
272 
273 	/* Signal we are done */
274 	atomic_add_int(&aps_started, 1);
275 
276 	/* Wait until we can run the scheduler */
277 	while (!atomic_load_int(&aps_ready))
278 		__asm __volatile("wfe");
279 
280 	/* Initialize curthread */
281 	KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
282 	pcpup->pc_curthread = pcpup->pc_idlethread;
283 	schedinit_ap();
284 
285 	/* Initialize curpmap to match TTBR0's current setting. */
286 	pmap0 = vmspace_pmap(&vmspace0);
287 	KASSERT(pmap_to_ttbr0(pmap0) == READ_SPECIALREG(ttbr0_el1),
288 	    ("pmap0 doesn't match cpu %ld's ttbr0", cpu));
289 	pcpup->pc_curpmap = pmap0;
290 
291 	intr_pic_init_secondary();
292 
293 	/* Start per-CPU event timers. */
294 	cpu_initclocks_ap();
295 
296 #ifdef VFP
297 	vfp_init_secondary();
298 #endif
299 
300 	dbg_init();
301 
302 	/* Signal the CPU is ready */
303 	atomic_add_int(&aps_started, 1);
304 
305 	kcsan_cpu_init(cpu);
306 
307 	/* Enter the scheduler */
308 	sched_ap_entry();
309 
310 	panic("scheduler returned us to init_secondary");
311 	/* NOTREACHED */
312 }
313 
314 static void
smp_after_idle_runnable(void * arg __unused)315 smp_after_idle_runnable(void *arg __unused)
316 {
317 	int cpu;
318 
319 	if (mp_ncpus == 1)
320 		return;
321 
322 	KASSERT(smp_started != 0, ("%s: SMP not started yet", __func__));
323 
324 	/*
325 	 * Wait for all APs to handle an interrupt.  After that, we know that
326 	 * the APs have entered the scheduler at least once, so the boot stacks
327 	 * are safe to free.
328 	 */
329 	smp_rendezvous(smp_no_rendezvous_barrier, NULL,
330 	    smp_no_rendezvous_barrier, NULL);
331 
332 	for (cpu = 1; cpu < mp_ncpus; cpu++) {
333 		if (bootstacks[cpu] != NULL)
334 			kmem_free(bootstacks[cpu], MP_BOOTSTACK_SIZE);
335 	}
336 }
337 SYSINIT(smp_after_idle_runnable, SI_SUB_SMP, SI_ORDER_ANY,
338     smp_after_idle_runnable, NULL);
339 
340 static void
ipi_ast(void * dummy __unused)341 ipi_ast(void *dummy __unused)
342 {
343 
344 	CTR0(KTR_SMP, "IPI_AST");
345 }
346 
347 static void
ipi_hardclock(void * dummy __unused)348 ipi_hardclock(void *dummy __unused)
349 {
350 
351 	CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
352 	hardclockintr();
353 }
354 
355 static void
ipi_preempt(void * dummy __unused)356 ipi_preempt(void *dummy __unused)
357 {
358 	CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
359 	sched_preempt(curthread);
360 }
361 
362 static void
ipi_rendezvous(void * dummy __unused)363 ipi_rendezvous(void *dummy __unused)
364 {
365 
366 	CTR0(KTR_SMP, "IPI_RENDEZVOUS");
367 	smp_rendezvous_action();
368 }
369 
370 static void
ipi_stop(void * dummy __unused)371 ipi_stop(void *dummy __unused)
372 {
373 	u_int cpu;
374 
375 	CTR0(KTR_SMP, "IPI_STOP");
376 
377 	cpu = PCPU_GET(cpuid);
378 	savectx(&stoppcbs[cpu]);
379 
380 	/* Indicate we are stopped */
381 	CPU_SET_ATOMIC(cpu, &stopped_cpus);
382 
383 	/* Wait for restart */
384 	while (!CPU_ISSET(cpu, &started_cpus))
385 		cpu_spinwait();
386 
387 #ifdef DDB
388 	dbg_register_sync(NULL);
389 #endif
390 
391 	CPU_CLR_ATOMIC(cpu, &started_cpus);
392 	CPU_CLR_ATOMIC(cpu, &stopped_cpus);
393 	CTR0(KTR_SMP, "IPI_STOP (restart)");
394 }
395 
396 void stop_mmu(vm_paddr_t, vm_paddr_t) __dead2;
397 extern uint32_t mp_cpu_spinloop[];
398 extern uint32_t mp_cpu_spinloop_end[];
399 extern uint64_t mp_cpu_spin_table_release_addr;
400 static void
ipi_off(void * dummy __unused)401 ipi_off(void *dummy __unused)
402 {
403 	CTR0(KTR_SMP, "IPI_OFF");
404 	if (psci_present)
405 		psci_cpu_off();
406 	else {
407 		uint64_t release_addr;
408 		vm_size_t size;
409 
410 		size = (vm_offset_t)&mp_cpu_spin_table_release_addr -
411 		    (vm_offset_t)mp_cpu_spinloop;
412 		release_addr = PCPU_GET(release_addr) - size;
413 		isb();
414 		invalidate_icache();
415 		/* Go catatonic, don't take any interrupts. */
416 		intr_disable();
417 		stop_mmu(release_addr, pmap_kextract(KERNBASE));
418 
419 
420 	}
421 	CTR0(KTR_SMP, "IPI_OFF failed");
422 }
423 
424 struct cpu_group *
cpu_topo(void)425 cpu_topo(void)
426 {
427 	struct cpu_group *dom, *root;
428 	int i;
429 
430 	root = smp_topo_alloc(1);
431 	dom = smp_topo_alloc(vm_ndomains);
432 
433 	root->cg_parent = NULL;
434 	root->cg_child = dom;
435 	CPU_COPY(&all_cpus, &root->cg_mask);
436 	root->cg_count = mp_ncpus;
437 	root->cg_children = vm_ndomains;
438 	root->cg_level = CG_SHARE_NONE;
439 	root->cg_flags = 0;
440 
441 	/*
442 	 * Redundant layers will be collapsed by the caller so we don't need a
443 	 * special case for a single domain.
444 	 */
445 	for (i = 0; i < vm_ndomains; i++, dom++) {
446 		dom->cg_parent = root;
447 		dom->cg_child = NULL;
448 		CPU_COPY(&cpuset_domain[i], &dom->cg_mask);
449 		dom->cg_count = CPU_COUNT(&dom->cg_mask);
450 		dom->cg_children = 0;
451 		dom->cg_level = CG_SHARE_L3;
452 		dom->cg_flags = 0;
453 	}
454 
455 	return (root);
456 }
457 
458 /* Determine if we running MP machine */
459 int
cpu_mp_probe(void)460 cpu_mp_probe(void)
461 {
462 
463 	/* ARM64TODO: Read the u bit of mpidr_el1 to determine this */
464 	return (1);
465 }
466 
467 static int
enable_cpu_psci(uint64_t target_cpu,vm_paddr_t entry,u_int cpuid)468 enable_cpu_psci(uint64_t target_cpu, vm_paddr_t entry, u_int cpuid)
469 {
470 	int err;
471 
472 	err = psci_cpu_on(target_cpu, entry, cpuid);
473 	if (err != PSCI_RETVAL_SUCCESS) {
474 		/*
475 		 * Panic here if INVARIANTS are enabled and PSCI failed to
476 		 * start the requested CPU.  psci_cpu_on() returns PSCI_MISSING
477 		 * to indicate we are unable to use it to start the given CPU.
478 		 */
479 		KASSERT(err == PSCI_MISSING ||
480 		    (mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST,
481 		    ("Failed to start CPU %u (%lx), error %d\n",
482 		    cpuid, target_cpu, err));
483 		return (EINVAL);
484 	}
485 
486 	return (0);
487 }
488 
489 static int
enable_cpu_spin(uint64_t cpu,vm_paddr_t entry,vm_paddr_t release_paddr)490 enable_cpu_spin(uint64_t cpu, vm_paddr_t entry, vm_paddr_t release_paddr)
491 {
492 	vm_paddr_t *release_addr;
493 
494 	ap_cpuid = cpu & CPU_AFF_MASK;
495 
496 	release_addr = pmap_mapdev_attr(release_paddr, sizeof(*release_addr),
497 	    VM_MEMATTR_DEFAULT);
498 	if (release_addr == NULL)
499 		return (ENOMEM);
500 
501 	*release_addr = entry;
502 	cpu_dcache_wbinv_range(release_addr, sizeof(*release_addr));
503 	pmap_unmapdev(release_addr, sizeof(*release_addr));
504 
505 	__asm __volatile(
506 	    "sev	\n"
507 	    ::: "memory");
508 
509 	/* Wait for the target CPU to start */
510 	while (atomic_load_64(&ap_cpuid) != 0)
511 		__asm __volatile("wfe");
512 
513 	return (0);
514 }
515 
516 /*
517  * Starts a given CPU. If the CPU is already running, i.e. it is the boot CPU,
518  * do nothing. Returns true if the CPU is present and running.
519  */
520 static bool
start_cpu(u_int cpuid,uint64_t target_cpu,int domain,vm_paddr_t release_addr)521 start_cpu(u_int cpuid, uint64_t target_cpu, int domain, vm_paddr_t release_addr)
522 {
523 	struct pcpu *pcpup;
524 	vm_size_t size;
525 	vm_paddr_t pa;
526 	int err, naps;
527 
528 	/* Check we are able to start this cpu */
529 	if (cpuid > mp_maxid)
530 		return (false);
531 
532 	/* Skip boot CPU */
533 	if (is_boot_cpu(target_cpu))
534 		return (true);
535 
536 	KASSERT(cpuid < MAXCPU, ("Too many CPUs"));
537 
538 	size = round_page(sizeof(*pcpup) + DPCPU_SIZE);
539 	pcpup = kmem_malloc_domainset(DOMAINSET_PREF(domain), size,
540 	    M_WAITOK | M_ZERO);
541 	pmap_disable_promotion((vm_offset_t)pcpup, size);
542 	pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
543 	pcpup->pc_mpidr = target_cpu & CPU_AFF_MASK;
544 	bootpcpu = pcpup;
545 	pcpup->pc_release_addr = release_addr;
546 
547 	dpcpu[cpuid - 1] = (void *)(pcpup + 1);
548 	dpcpu_init(dpcpu[cpuid - 1], cpuid);
549 
550 	bootstacks[cpuid] = kmem_malloc_domainset(DOMAINSET_PREF(domain),
551 	    MP_BOOTSTACK_SIZE, M_WAITOK | M_ZERO);
552 
553 	naps = atomic_load_int(&aps_started);
554 	bootstack = (char *)bootstacks[cpuid] + MP_BOOTSTACK_SIZE;
555 
556 	printf("Starting CPU %u (%lx)\n", cpuid, target_cpu);
557 
558 	/*
559 	 * A limited set of hardware we support can only do spintables and
560 	 * remain useful, due to lack of EL3.  Thus, we'll usually fall into the
561 	 * PSCI branch here.
562 	 */
563 	MPASS(release_addr == 0 || !psci_present);
564 	if (release_addr != 0) {
565 		pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_spintable);
566 		err = enable_cpu_spin(target_cpu, pa, release_addr);
567 	} else {
568 		pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_psci);
569 		err = enable_cpu_psci(target_cpu, pa, cpuid);
570 	}
571 
572 	if (err != 0) {
573 		pcpu_destroy(pcpup);
574 		dpcpu[cpuid - 1] = NULL;
575 		kmem_free(bootstacks[cpuid], MP_BOOTSTACK_SIZE);
576 		kmem_free(pcpup, size);
577 		bootstacks[cpuid] = NULL;
578 		mp_ncpus--;
579 		return (false);
580 	}
581 
582 	/* Wait for the AP to switch to its boot stack. */
583 	while (atomic_load_int(&aps_started) < naps + 1)
584 		cpu_spinwait();
585 	CPU_SET(cpuid, &all_cpus);
586 
587 	return (true);
588 }
589 
590 #ifdef DEV_ACPI
591 static void
madt_handler(ACPI_SUBTABLE_HEADER * entry,void * arg)592 madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
593 {
594 	ACPI_MADT_GENERIC_INTERRUPT *intr;
595 	u_int *cpuid;
596 	u_int id;
597 	int domain;
598 
599 	switch(entry->Type) {
600 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
601 		intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
602 		cpuid = arg;
603 
604 		if (is_boot_cpu(intr->ArmMpidr))
605 			id = 0;
606 		else
607 			id = *cpuid;
608 
609 		domain = 0;
610 #ifdef NUMA
611 		if (vm_ndomains > 1)
612 			domain = acpi_pxm_get_cpu_locality(intr->Uid);
613 #endif
614 		if (start_cpu(id, intr->ArmMpidr, domain, 0)) {
615 			MPASS(cpuid_to_pcpu[id] != NULL);
616 			cpuid_to_pcpu[id]->pc_acpi_id = intr->Uid;
617 			/*
618 			 * Don't increment for the boot CPU, its CPU ID is
619 			 * reserved.
620 			 */
621 			if (!is_boot_cpu(intr->ArmMpidr))
622 				(*cpuid)++;
623 		}
624 
625 		break;
626 	default:
627 		break;
628 	}
629 }
630 
631 static void
cpu_init_acpi(void)632 cpu_init_acpi(void)
633 {
634 	ACPI_TABLE_MADT *madt;
635 	vm_paddr_t physaddr;
636 	u_int cpuid;
637 
638 	physaddr = acpi_find_table(ACPI_SIG_MADT);
639 	if (physaddr == 0)
640 		return;
641 
642 	madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
643 	if (madt == NULL) {
644 		printf("Unable to map the MADT, not starting APs\n");
645 		return;
646 	}
647 	/* Boot CPU is always 0 */
648 	cpuid = 1;
649 	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
650 	    madt_handler, &cpuid);
651 
652 	acpi_unmap_table(madt);
653 
654 #if MAXMEMDOM > 1
655 	acpi_pxm_set_cpu_locality();
656 #endif
657 }
658 #endif
659 
660 #ifdef FDT
661 /*
662  * Failure is indicated by failing to populate *release_addr.
663  */
664 static void
populate_release_addr(phandle_t node,vm_paddr_t * release_addr)665 populate_release_addr(phandle_t node, vm_paddr_t *release_addr)
666 {
667 	pcell_t buf[2];
668 
669 	if (OF_getencprop(node, "cpu-release-addr", buf, sizeof(buf)) !=
670 	    sizeof(buf))
671 		return;
672 
673 	*release_addr = (((uintptr_t)buf[0] << 32) | buf[1]);
674 }
675 
676 static bool
start_cpu_fdt(u_int id,phandle_t node,u_int addr_size,pcell_t * reg)677 start_cpu_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
678 {
679 	uint64_t target_cpu;
680 	vm_paddr_t release_addr;
681 	char *enable_method;
682 	int domain;
683 	int cpuid;
684 
685 	target_cpu = reg[0];
686 	if (addr_size == 2) {
687 		target_cpu <<= 32;
688 		target_cpu |= reg[1];
689 	}
690 
691 	if (is_boot_cpu(target_cpu))
692 		cpuid = 0;
693 	else
694 		cpuid = fdt_cpuid;
695 
696 	/*
697 	 * If PSCI is present, we'll always use that -- the cpu_on method is
698 	 * mandated in both v0.1 and v0.2.  We'll check the enable-method if
699 	 * we don't have PSCI and use spin table if it's provided.
700 	 */
701 	release_addr = 0;
702 	if (!psci_present && cpuid != 0) {
703 		if (OF_getprop_alloc(node, "enable-method",
704 		    (void **)&enable_method) <= 0)
705 			return (false);
706 
707 		if (strcmp(enable_method, "spin-table") != 0) {
708 			OF_prop_free(enable_method);
709 			return (false);
710 		}
711 
712 		OF_prop_free(enable_method);
713 		populate_release_addr(node, &release_addr);
714 		if (release_addr == 0) {
715 			printf("Failed to fetch release address for CPU %u",
716 			    cpuid);
717 			return (false);
718 		}
719 	}
720 
721 	if (!start_cpu(cpuid, target_cpu, 0, release_addr))
722 		return (false);
723 
724 	/*
725 	 * Don't increment for the boot CPU, its CPU ID is reserved.
726 	 */
727 	if (!is_boot_cpu(target_cpu))
728 		fdt_cpuid++;
729 
730 	/* Try to read the numa node of this cpu */
731 	if (vm_ndomains == 1 ||
732 	    OF_getencprop(node, "numa-node-id", &domain, sizeof(domain)) <= 0)
733 		domain = 0;
734 	cpuid_to_pcpu[cpuid]->pc_domain = domain;
735 	if (domain < MAXMEMDOM)
736 		CPU_SET(cpuid, &cpuset_domain[domain]);
737 	return (true);
738 }
739 static void
cpu_init_fdt(void)740 cpu_init_fdt(void)
741 {
742 	phandle_t node;
743 	int i;
744 
745 	node = OF_peer(0);
746 	for (i = 0; fdt_quirks[i].compat != NULL; i++) {
747 		if (ofw_bus_node_is_compatible(node,
748 		    fdt_quirks[i].compat) != 0) {
749 			mp_quirks = fdt_quirks[i].quirks;
750 		}
751 	}
752 	fdt_cpuid = 1;
753 	ofw_cpu_early_foreach(start_cpu_fdt, true);
754 }
755 #endif
756 
757 /* Initialize and fire up non-boot processors */
758 void
cpu_mp_start(void)759 cpu_mp_start(void)
760 {
761 	uint64_t mpidr;
762 
763 	/* CPU 0 is always boot CPU. */
764 	CPU_SET(0, &all_cpus);
765 	mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
766 	cpuid_to_pcpu[0]->pc_mpidr = mpidr;
767 
768 	cpu_desc_init();
769 
770 	switch(arm64_bus_method) {
771 #ifdef DEV_ACPI
772 	case ARM64_BUS_ACPI:
773 		mp_quirks = MP_QUIRK_CPULIST;
774 		cpu_init_acpi();
775 		break;
776 #endif
777 #ifdef FDT
778 	case ARM64_BUS_FDT:
779 		cpu_init_fdt();
780 		break;
781 #endif
782 	default:
783 		break;
784 	}
785 }
786 
787 void
cpu_mp_stop(void)788 cpu_mp_stop(void)
789 {
790 
791 	/* Short-circuit for single-CPU */
792 	if (CPU_COUNT(&all_cpus) == 1)
793 		return;
794 
795 	KASSERT(PCPU_GET(cpuid) == CPU_FIRST(), ("Not on the first CPU!\n"));
796 
797 	/*
798 	 * If we use spin-table, assume U-boot method for now (single address
799 	 * shared by all CPUs).
800 	 */
801 	if (!psci_present) {
802 		int cpu;
803 		vm_paddr_t release_addr;
804 		void *release_vaddr;
805 		vm_size_t size;
806 
807 		/* Find the shared release address. */
808 		CPU_FOREACH(cpu) {
809 			release_addr = pcpu_find(cpu)->pc_release_addr;
810 			if (release_addr != 0)
811 				break;
812 		}
813 		/* No release address? No way of notifying other CPUs. */
814 		if (release_addr == 0)
815 			return;
816 
817 		size = (vm_offset_t)&mp_cpu_spinloop_end -
818 		    (vm_offset_t)&mp_cpu_spinloop;
819 
820 		release_addr -= (vm_offset_t)&mp_cpu_spin_table_release_addr -
821 		    (vm_offset_t)mp_cpu_spinloop;
822 
823 		release_vaddr = pmap_mapdev(release_addr, size);
824 		bcopy(mp_cpu_spinloop, release_vaddr, size);
825 		cpu_dcache_wbinv_range(release_vaddr, size);
826 		pmap_unmapdev(release_vaddr, size);
827 		invalidate_icache();
828 	}
829 	ipi_all_but_self(IPI_OFF);
830 	DELAY(1000000);
831 }
832 
833 /* Introduce rest of cores to the world */
834 void
cpu_mp_announce(void)835 cpu_mp_announce(void)
836 {
837 }
838 
839 #ifdef DEV_ACPI
840 static void
cpu_count_acpi_handler(ACPI_SUBTABLE_HEADER * entry,void * arg)841 cpu_count_acpi_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
842 {
843 	u_int *cores = arg;
844 
845 	switch(entry->Type) {
846 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
847 		(*cores)++;
848 		break;
849 	default:
850 		break;
851 	}
852 }
853 
854 static u_int
cpu_count_acpi(void)855 cpu_count_acpi(void)
856 {
857 	ACPI_TABLE_MADT *madt;
858 	vm_paddr_t physaddr;
859 	u_int cores;
860 
861 	physaddr = acpi_find_table(ACPI_SIG_MADT);
862 	if (physaddr == 0)
863 		return (0);
864 
865 	madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
866 	if (madt == NULL) {
867 		printf("Unable to map the MADT, not starting APs\n");
868 		return (0);
869 	}
870 
871 	cores = 0;
872 	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
873 	    cpu_count_acpi_handler, &cores);
874 
875 	acpi_unmap_table(madt);
876 
877 	return (cores);
878 }
879 #endif
880 
881 void
cpu_mp_setmaxid(void)882 cpu_mp_setmaxid(void)
883 {
884 	int cores;
885 
886 	mp_ncpus = 1;
887 	mp_maxid = 0;
888 
889 	switch(arm64_bus_method) {
890 #ifdef DEV_ACPI
891 	case ARM64_BUS_ACPI:
892 		cores = cpu_count_acpi();
893 		if (cores > 0) {
894 			cores = MIN(cores, MAXCPU);
895 			if (bootverbose)
896 				printf("Found %d CPUs in the ACPI tables\n",
897 				    cores);
898 			mp_ncpus = cores;
899 			mp_maxid = cores - 1;
900 		}
901 		break;
902 #endif
903 #ifdef FDT
904 	case ARM64_BUS_FDT:
905 		cores = ofw_cpu_early_foreach(NULL, false);
906 		if (cores > 0) {
907 			cores = MIN(cores, MAXCPU);
908 			if (bootverbose)
909 				printf("Found %d CPUs in the device tree\n",
910 				    cores);
911 			mp_ncpus = cores;
912 			mp_maxid = cores - 1;
913 		}
914 		break;
915 #endif
916 	default:
917 		if (bootverbose)
918 			printf("No CPU data, limiting to 1 core\n");
919 		break;
920 	}
921 
922 	if (TUNABLE_INT_FETCH("hw.ncpu", &cores)) {
923 		if (cores > 0 && cores < mp_ncpus) {
924 			mp_ncpus = cores;
925 			mp_maxid = cores - 1;
926 		}
927 	}
928 }
929 
930 /* Sending IPI */
931 void
ipi_all_but_self(u_int ipi)932 ipi_all_but_self(u_int ipi)
933 {
934 	cpuset_t cpus;
935 
936 	cpus = all_cpus;
937 	CPU_CLR(PCPU_GET(cpuid), &cpus);
938 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
939 	intr_ipi_send(cpus, ipi);
940 }
941 
942 void
ipi_cpu(int cpu,u_int ipi)943 ipi_cpu(int cpu, u_int ipi)
944 {
945 	cpuset_t cpus;
946 
947 	CPU_ZERO(&cpus);
948 	CPU_SET(cpu, &cpus);
949 
950 	CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi);
951 	intr_ipi_send(cpus, ipi);
952 }
953 
954 void
ipi_selected(cpuset_t cpus,u_int ipi)955 ipi_selected(cpuset_t cpus, u_int ipi)
956 {
957 
958 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
959 	intr_ipi_send(cpus, ipi);
960 }
961