xref: /freebsd/sys/arm64/arm64/mp_machdep.c (revision 77d5df3b9261173f10afb7ba739f98c62a41395f)
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 #ifdef VFP
64 #include <machine/vfp.h>
65 #endif
66 
67 #ifdef DEV_ACPI
68 #include <contrib/dev/acpica/include/acpi.h>
69 #include <dev/acpica/acpivar.h>
70 #endif
71 
72 #ifdef FDT
73 #include <dev/ofw/openfirm.h>
74 #include <dev/ofw/ofw_bus.h>
75 #include <dev/ofw/ofw_bus_subr.h>
76 #include <dev/ofw/ofw_cpu.h>
77 #endif
78 
79 #include <dev/psci/psci.h>
80 
81 #define	MP_BOOTSTACK_SIZE	(kstack_pages * PAGE_SIZE)
82 
83 #define	MP_QUIRK_CPULIST	0x01	/* The list of cpus may be wrong, */
84 					/* don't panic if one fails to start */
85 static uint32_t mp_quirks;
86 
87 #ifdef FDT
88 static struct {
89 	const char *compat;
90 	uint32_t quirks;
91 } fdt_quirks[] = {
92 	{ "arm,foundation-aarch64",	MP_QUIRK_CPULIST },
93 	{ "arm,fvp-base",		MP_QUIRK_CPULIST },
94 	{ "arm,fvp-base-revc",		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 static void ipi_ast(void *);
102 static void ipi_hardclock(void *);
103 static void ipi_preempt(void *);
104 static void ipi_rendezvous(void *);
105 static void ipi_stop(void *);
106 
107 #ifdef FDT
108 static u_int fdt_cpuid;
109 #endif
110 
111 void mpentry_psci(unsigned long cpuid);
112 void mpentry_spintable(void);
113 void init_secondary(uint64_t);
114 
115 /* Used to initialize the PCPU ahead of calling init_secondary(). */
116 void *bootpcpu;
117 uint64_t ap_cpuid;
118 
119 /* Stacks for AP initialization, discarded once idle threads are started. */
120 void *bootstack;
121 static void *bootstacks[MAXCPU];
122 
123 /* Count of started APs, used to synchronize access to bootstack. */
124 static volatile int aps_started;
125 
126 /* Set to 1 once we're ready to let the APs out of the pen. */
127 static volatile int aps_after_dev, aps_ready;
128 
129 /* Temporary variables for init_secondary()  */
130 static void *dpcpu[MAXCPU - 1];
131 
132 static bool
is_boot_cpu(uint64_t target_cpu)133 is_boot_cpu(uint64_t target_cpu)
134 {
135 
136 	return (PCPU_GET_MPIDR(cpuid_to_pcpu[0]) == (target_cpu & CPU_AFF_MASK));
137 }
138 
139 static bool
wait_for_aps(void)140 wait_for_aps(void)
141 {
142 	for (int i = 0, started = 0; i < 2000; i++) {
143 		int32_t nstarted;
144 
145 		nstarted = atomic_load_32(&aps_started);
146 		if (nstarted == mp_ncpus - 1)
147 			return (true);
148 
149 		/*
150 		 * Don't time out while we are making progress. Some large
151 		 * systems can take a while to start all CPUs.
152 		 */
153 		if (nstarted > started) {
154 			i = 0;
155 			started = nstarted;
156 		}
157 		DELAY(1000);
158 	}
159 
160 	return (false);
161 }
162 
163 static void
release_aps_after_dev(void * dummy __unused)164 release_aps_after_dev(void *dummy __unused)
165 {
166 	/* Only release CPUs if they exist */
167 	if (mp_ncpus == 1)
168 		return;
169 
170 	atomic_store_int(&aps_started, 0);
171 	atomic_store_rel_int(&aps_after_dev, 1);
172 	/* Wake up the other CPUs */
173 	__asm __volatile(
174 	    "dsb ishst	\n"
175 	    "sev	\n"
176 	    ::: "memory");
177 
178 	wait_for_aps();
179 }
180 SYSINIT(aps_after_dev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE + 1,
181     release_aps_after_dev, NULL);
182 
183 static void
release_aps(void * dummy __unused)184 release_aps(void *dummy __unused)
185 {
186 	/* Only release CPUs if they exist */
187 	if (mp_ncpus == 1)
188 		return;
189 
190 	intr_ipi_setup(IPI_AST, "ast", ipi_ast, NULL);
191 	intr_ipi_setup(IPI_PREEMPT, "preempt", ipi_preempt, NULL);
192 	intr_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL);
193 	intr_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL);
194 	intr_ipi_setup(IPI_STOP_HARD, "stop hard", ipi_stop, NULL);
195 	intr_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL);
196 
197 	atomic_store_int(&aps_started, 0);
198 	atomic_store_rel_int(&aps_ready, 1);
199 	/* Wake up the other CPUs */
200 	__asm __volatile(
201 	    "dsb ishst	\n"
202 	    "sev	\n"
203 	    ::: "memory");
204 
205 	printf("Release APs...");
206 
207 	if (wait_for_aps())
208 		printf("done\n");
209 	else
210 		printf("APs not started\n");
211 
212 	smp_cpus = atomic_load_int(&aps_started) + 1;
213 	atomic_store_rel_int(&smp_started, 1);
214 }
215 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
216 
217 void
init_secondary(uint64_t cpu)218 init_secondary(uint64_t cpu)
219 {
220 	struct pcpu *pcpup;
221 	pmap_t pmap0;
222 	uint64_t mpidr;
223 
224 	ptrauth_mp_start(cpu);
225 
226 	/*
227 	 * Verify that the value passed in 'cpu' argument (aka context_id) is
228 	 * valid. Some older U-Boot based PSCI implementations are buggy,
229 	 * they can pass random value in it.
230 	 */
231 	mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
232 	if (cpu >= MAXCPU || cpuid_to_pcpu[cpu] == NULL ||
233 	    PCPU_GET_MPIDR(cpuid_to_pcpu[cpu]) != mpidr) {
234 		for (cpu = 0; cpu < mp_maxid; cpu++)
235 			if (cpuid_to_pcpu[cpu] != NULL &&
236 			    PCPU_GET_MPIDR(cpuid_to_pcpu[cpu]) == mpidr)
237 				break;
238 		if ( cpu >= MAXCPU)
239 			panic("MPIDR for this CPU is not in pcpu table");
240 	}
241 
242 	/*
243 	 * Identify current CPU. This is necessary to setup
244 	 * affinity registers and to provide support for
245 	 * runtime chip identification.
246 	 *
247 	 * We need this before signalling the CPU is ready to
248 	 * let the boot CPU use the results.
249 	 */
250 	pcpup = cpuid_to_pcpu[cpu];
251 	pcpup->pc_midr = get_midr();
252 	identify_cpu(cpu);
253 
254 	/* Ensure the stores in identify_cpu have completed */
255 	atomic_thread_fence_acq_rel();
256 
257 	/* Detect early CPU feature support */
258 	enable_cpu_feat(CPU_FEAT_EARLY_BOOT);
259 
260 	/* Signal we are waiting for aps_after_dev */
261 	atomic_add_int(&aps_started, 1);
262 
263 	/* Wait for devices to be ready */
264 	while (!atomic_load_int(&aps_after_dev))
265 		__asm __volatile("wfe");
266 
267 	install_cpu_errata();
268 	enable_cpu_feat(CPU_FEAT_AFTER_DEV);
269 
270 	/* Signal we are done */
271 	atomic_add_int(&aps_started, 1);
272 
273 	/* Wait until we can run the scheduler */
274 	while (!atomic_load_int(&aps_ready))
275 		__asm __volatile("wfe");
276 
277 	/* Initialize curthread */
278 	KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
279 	pcpup->pc_curthread = pcpup->pc_idlethread;
280 	schedinit_ap();
281 
282 	/* Initialize curpmap to match TTBR0's current setting. */
283 	pmap0 = vmspace_pmap(&vmspace0);
284 	KASSERT(pmap_to_ttbr0(pmap0) == READ_SPECIALREG(ttbr0_el1),
285 	    ("pmap0 doesn't match cpu %ld's ttbr0", cpu));
286 	pcpup->pc_curpmap = pmap0;
287 
288 	intr_pic_init_secondary();
289 
290 	/* Start per-CPU event timers. */
291 	cpu_initclocks_ap();
292 
293 #ifdef VFP
294 	vfp_init_secondary();
295 #endif
296 
297 	dbg_init();
298 
299 	/* Signal the CPU is ready */
300 	atomic_add_int(&aps_started, 1);
301 
302 	kcsan_cpu_init(cpu);
303 
304 	/* Enter the scheduler */
305 	sched_ap_entry();
306 
307 	panic("scheduler returned us to init_secondary");
308 	/* NOTREACHED */
309 }
310 
311 static void
smp_after_idle_runnable(void * arg __unused)312 smp_after_idle_runnable(void *arg __unused)
313 {
314 	int cpu;
315 
316 	if (mp_ncpus == 1)
317 		return;
318 
319 	KASSERT(smp_started != 0, ("%s: SMP not started yet", __func__));
320 
321 	/*
322 	 * Wait for all APs to handle an interrupt.  After that, we know that
323 	 * the APs have entered the scheduler at least once, so the boot stacks
324 	 * are safe to free.
325 	 */
326 	smp_rendezvous(smp_no_rendezvous_barrier, NULL,
327 	    smp_no_rendezvous_barrier, NULL);
328 
329 	for (cpu = 1; cpu < mp_ncpus; cpu++) {
330 		if (bootstacks[cpu] != NULL)
331 			kmem_free(bootstacks[cpu], MP_BOOTSTACK_SIZE);
332 	}
333 }
334 SYSINIT(smp_after_idle_runnable, SI_SUB_SMP, SI_ORDER_ANY,
335     smp_after_idle_runnable, NULL);
336 
337 static void
ipi_ast(void * dummy __unused)338 ipi_ast(void *dummy __unused)
339 {
340 
341 	CTR0(KTR_SMP, "IPI_AST");
342 }
343 
344 static void
ipi_hardclock(void * dummy __unused)345 ipi_hardclock(void *dummy __unused)
346 {
347 
348 	CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
349 	hardclockintr();
350 }
351 
352 static void
ipi_preempt(void * dummy __unused)353 ipi_preempt(void *dummy __unused)
354 {
355 	CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
356 	sched_preempt(curthread);
357 }
358 
359 static void
ipi_rendezvous(void * dummy __unused)360 ipi_rendezvous(void *dummy __unused)
361 {
362 
363 	CTR0(KTR_SMP, "IPI_RENDEZVOUS");
364 	smp_rendezvous_action();
365 }
366 
367 static void
ipi_stop(void * dummy __unused)368 ipi_stop(void *dummy __unused)
369 {
370 	u_int cpu;
371 
372 	CTR0(KTR_SMP, "IPI_STOP");
373 
374 	cpu = PCPU_GET(cpuid);
375 	savectx(&stoppcbs[cpu]);
376 
377 	/* Indicate we are stopped */
378 	CPU_SET_ATOMIC(cpu, &stopped_cpus);
379 
380 	/* Wait for restart */
381 	while (!CPU_ISSET(cpu, &started_cpus))
382 		cpu_spinwait();
383 
384 #ifdef DDB
385 	dbg_register_sync(NULL);
386 #endif
387 
388 	CPU_CLR_ATOMIC(cpu, &started_cpus);
389 	CPU_CLR_ATOMIC(cpu, &stopped_cpus);
390 	CTR0(KTR_SMP, "IPI_STOP (restart)");
391 }
392 
393 struct cpu_group *
cpu_topo(void)394 cpu_topo(void)
395 {
396 	struct cpu_group *dom, *root;
397 	int i;
398 
399 	root = smp_topo_alloc(1);
400 	dom = smp_topo_alloc(vm_ndomains);
401 
402 	root->cg_parent = NULL;
403 	root->cg_child = dom;
404 	CPU_COPY(&all_cpus, &root->cg_mask);
405 	root->cg_count = mp_ncpus;
406 	root->cg_children = vm_ndomains;
407 	root->cg_level = CG_SHARE_NONE;
408 	root->cg_flags = 0;
409 
410 	/*
411 	 * Redundant layers will be collapsed by the caller so we don't need a
412 	 * special case for a single domain.
413 	 */
414 	for (i = 0; i < vm_ndomains; i++, dom++) {
415 		dom->cg_parent = root;
416 		dom->cg_child = NULL;
417 		CPU_COPY(&cpuset_domain[i], &dom->cg_mask);
418 		dom->cg_count = CPU_COUNT(&dom->cg_mask);
419 		dom->cg_children = 0;
420 		dom->cg_level = CG_SHARE_L3;
421 		dom->cg_flags = 0;
422 	}
423 
424 	return (root);
425 }
426 
427 /* Determine if we running MP machine */
428 int
cpu_mp_probe(void)429 cpu_mp_probe(void)
430 {
431 
432 	/* ARM64TODO: Read the u bit of mpidr_el1 to determine this */
433 	return (1);
434 }
435 
436 static int
enable_cpu_psci(uint64_t target_cpu,vm_paddr_t entry,u_int cpuid)437 enable_cpu_psci(uint64_t target_cpu, vm_paddr_t entry, u_int cpuid)
438 {
439 	int err;
440 
441 	err = psci_cpu_on(target_cpu, entry, cpuid);
442 	if (err != PSCI_RETVAL_SUCCESS) {
443 		/*
444 		 * Panic here if INVARIANTS are enabled and PSCI failed to
445 		 * start the requested CPU.  psci_cpu_on() returns PSCI_MISSING
446 		 * to indicate we are unable to use it to start the given CPU.
447 		 */
448 		KASSERT(err == PSCI_MISSING ||
449 		    (mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST,
450 		    ("Failed to start CPU %u (%lx), error %d\n",
451 		    cpuid, target_cpu, err));
452 		return (EINVAL);
453 	}
454 
455 	return (0);
456 }
457 
458 static int
enable_cpu_spin(uint64_t cpu,vm_paddr_t entry,vm_paddr_t release_paddr)459 enable_cpu_spin(uint64_t cpu, vm_paddr_t entry, vm_paddr_t release_paddr)
460 {
461 	vm_paddr_t *release_addr;
462 
463 	ap_cpuid = cpu & CPU_AFF_MASK;
464 
465 	release_addr = pmap_mapdev_attr(release_paddr, sizeof(*release_addr),
466 	    VM_MEMATTR_DEFAULT);
467 	if (release_addr == NULL)
468 		return (ENOMEM);
469 
470 	*release_addr = entry;
471 	cpu_dcache_wbinv_range(release_addr, sizeof(*release_addr));
472 	pmap_unmapdev(release_addr, sizeof(*release_addr));
473 
474 	__asm __volatile(
475 	    "sev	\n"
476 	    ::: "memory");
477 
478 	/* Wait for the target CPU to start */
479 	while (atomic_load_64(&ap_cpuid) != 0)
480 		__asm __volatile("wfe");
481 
482 	return (0);
483 }
484 
485 /*
486  * Starts a given CPU. If the CPU is already running, i.e. it is the boot CPU,
487  * do nothing. Returns true if the CPU is present and running.
488  */
489 static bool
start_cpu(u_int cpuid,uint64_t target_cpu,int domain,vm_paddr_t release_addr)490 start_cpu(u_int cpuid, uint64_t target_cpu, int domain, vm_paddr_t release_addr)
491 {
492 	struct pcpu *pcpup;
493 	vm_size_t size;
494 	vm_paddr_t pa;
495 	int err, naps;
496 
497 	/* Check we are able to start this cpu */
498 	if (cpuid > mp_maxid)
499 		return (false);
500 
501 	/* Skip boot CPU */
502 	if (is_boot_cpu(target_cpu))
503 		return (true);
504 
505 	KASSERT(cpuid < MAXCPU, ("Too many CPUs"));
506 
507 	size = round_page(sizeof(*pcpup) + DPCPU_SIZE);
508 	pcpup = kmem_malloc_domainset(DOMAINSET_PREF(domain), size,
509 	    M_WAITOK | M_ZERO);
510 	pmap_disable_promotion((vm_offset_t)pcpup, size);
511 	pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
512 	pcpup->pc_mpidr = target_cpu & CPU_AFF_MASK;
513 	bootpcpu = pcpup;
514 
515 	dpcpu[cpuid - 1] = (void *)(pcpup + 1);
516 	dpcpu_init(dpcpu[cpuid - 1], cpuid);
517 
518 	bootstacks[cpuid] = kmem_malloc_domainset(DOMAINSET_PREF(domain),
519 	    MP_BOOTSTACK_SIZE, M_WAITOK | M_ZERO);
520 
521 	naps = atomic_load_int(&aps_started);
522 	bootstack = (char *)bootstacks[cpuid] + MP_BOOTSTACK_SIZE;
523 
524 	printf("Starting CPU %u (%lx)\n", cpuid, target_cpu);
525 
526 	/*
527 	 * A limited set of hardware we support can only do spintables and
528 	 * remain useful, due to lack of EL3.  Thus, we'll usually fall into the
529 	 * PSCI branch here.
530 	 */
531 	MPASS(release_addr == 0 || !psci_present);
532 	if (release_addr != 0) {
533 		pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_spintable);
534 		err = enable_cpu_spin(target_cpu, pa, release_addr);
535 	} else {
536 		pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_psci);
537 		err = enable_cpu_psci(target_cpu, pa, cpuid);
538 	}
539 
540 	if (err != 0) {
541 		pcpu_destroy(pcpup);
542 		dpcpu[cpuid - 1] = NULL;
543 		kmem_free(bootstacks[cpuid], MP_BOOTSTACK_SIZE);
544 		kmem_free(pcpup, size);
545 		bootstacks[cpuid] = NULL;
546 		mp_ncpus--;
547 		return (false);
548 	}
549 
550 	/* Wait for the AP to switch to its boot stack. */
551 	while (atomic_load_int(&aps_started) < naps + 1)
552 		cpu_spinwait();
553 	CPU_SET(cpuid, &all_cpus);
554 
555 	return (true);
556 }
557 
558 #ifdef DEV_ACPI
559 static void
madt_handler(ACPI_SUBTABLE_HEADER * entry,void * arg)560 madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
561 {
562 	ACPI_MADT_GENERIC_INTERRUPT *intr;
563 	u_int *cpuid;
564 	u_int id;
565 	int domain;
566 
567 	switch(entry->Type) {
568 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
569 		intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
570 		cpuid = arg;
571 
572 		if (is_boot_cpu(intr->ArmMpidr))
573 			id = 0;
574 		else
575 			id = *cpuid;
576 
577 		domain = 0;
578 #ifdef NUMA
579 		if (vm_ndomains > 1)
580 			domain = acpi_pxm_get_cpu_locality(intr->Uid);
581 #endif
582 		if (start_cpu(id, intr->ArmMpidr, domain, 0)) {
583 			MPASS(cpuid_to_pcpu[id] != NULL);
584 			cpuid_to_pcpu[id]->pc_acpi_id = intr->Uid;
585 			/*
586 			 * Don't increment for the boot CPU, its CPU ID is
587 			 * reserved.
588 			 */
589 			if (!is_boot_cpu(intr->ArmMpidr))
590 				(*cpuid)++;
591 		}
592 
593 		break;
594 	default:
595 		break;
596 	}
597 }
598 
599 static void
cpu_init_acpi(void)600 cpu_init_acpi(void)
601 {
602 	ACPI_TABLE_MADT *madt;
603 	vm_paddr_t physaddr;
604 	u_int cpuid;
605 
606 	physaddr = acpi_find_table(ACPI_SIG_MADT);
607 	if (physaddr == 0)
608 		return;
609 
610 	madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
611 	if (madt == NULL) {
612 		printf("Unable to map the MADT, not starting APs\n");
613 		return;
614 	}
615 	/* Boot CPU is always 0 */
616 	cpuid = 1;
617 	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
618 	    madt_handler, &cpuid);
619 
620 	acpi_unmap_table(madt);
621 
622 #if MAXMEMDOM > 1
623 	acpi_pxm_set_cpu_locality();
624 #endif
625 }
626 #endif
627 
628 #ifdef FDT
629 /*
630  * Failure is indicated by failing to populate *release_addr.
631  */
632 static void
populate_release_addr(phandle_t node,vm_paddr_t * release_addr)633 populate_release_addr(phandle_t node, vm_paddr_t *release_addr)
634 {
635 	pcell_t buf[2];
636 
637 	if (OF_getencprop(node, "cpu-release-addr", buf, sizeof(buf)) !=
638 	    sizeof(buf))
639 		return;
640 
641 	*release_addr = (((uintptr_t)buf[0] << 32) | buf[1]);
642 }
643 
644 static bool
start_cpu_fdt(u_int id,phandle_t node,u_int addr_size,pcell_t * reg)645 start_cpu_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
646 {
647 	uint64_t target_cpu;
648 	vm_paddr_t release_addr;
649 	char *enable_method;
650 	int domain;
651 	int cpuid;
652 
653 	target_cpu = reg[0];
654 	if (addr_size == 2) {
655 		target_cpu <<= 32;
656 		target_cpu |= reg[1];
657 	}
658 
659 	if (is_boot_cpu(target_cpu))
660 		cpuid = 0;
661 	else
662 		cpuid = fdt_cpuid;
663 
664 	/*
665 	 * If PSCI is present, we'll always use that -- the cpu_on method is
666 	 * mandated in both v0.1 and v0.2.  We'll check the enable-method if
667 	 * we don't have PSCI and use spin table if it's provided.
668 	 */
669 	release_addr = 0;
670 	if (!psci_present && cpuid != 0) {
671 		if (OF_getprop_alloc(node, "enable-method",
672 		    (void **)&enable_method) <= 0)
673 			return (false);
674 
675 		if (strcmp(enable_method, "spin-table") != 0) {
676 			OF_prop_free(enable_method);
677 			return (false);
678 		}
679 
680 		OF_prop_free(enable_method);
681 		populate_release_addr(node, &release_addr);
682 		if (release_addr == 0) {
683 			printf("Failed to fetch release address for CPU %u",
684 			    cpuid);
685 			return (false);
686 		}
687 	}
688 
689 	if (!start_cpu(cpuid, target_cpu, 0, release_addr))
690 		return (false);
691 
692 	/*
693 	 * Don't increment for the boot CPU, its CPU ID is reserved.
694 	 */
695 	if (!is_boot_cpu(target_cpu))
696 		fdt_cpuid++;
697 
698 	/* Try to read the numa node of this cpu */
699 	if (vm_ndomains == 1 ||
700 	    OF_getencprop(node, "numa-node-id", &domain, sizeof(domain)) <= 0)
701 		domain = 0;
702 	cpuid_to_pcpu[cpuid]->pc_domain = domain;
703 	if (domain < MAXMEMDOM)
704 		CPU_SET(cpuid, &cpuset_domain[domain]);
705 	return (true);
706 }
707 static void
cpu_init_fdt(void)708 cpu_init_fdt(void)
709 {
710 	phandle_t node;
711 	int i;
712 
713 	node = OF_peer(0);
714 	for (i = 0; fdt_quirks[i].compat != NULL; i++) {
715 		if (ofw_bus_node_is_compatible(node,
716 		    fdt_quirks[i].compat) != 0) {
717 			mp_quirks = fdt_quirks[i].quirks;
718 		}
719 	}
720 	fdt_cpuid = 1;
721 	ofw_cpu_early_foreach(start_cpu_fdt, true);
722 }
723 #endif
724 
725 /* Initialize and fire up non-boot processors */
726 void
cpu_mp_start(void)727 cpu_mp_start(void)
728 {
729 	uint64_t mpidr;
730 
731 	/* CPU 0 is always boot CPU. */
732 	CPU_SET(0, &all_cpus);
733 	mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
734 	cpuid_to_pcpu[0]->pc_mpidr = mpidr;
735 
736 	cpu_desc_init();
737 
738 	switch(arm64_bus_method) {
739 #ifdef DEV_ACPI
740 	case ARM64_BUS_ACPI:
741 		mp_quirks = MP_QUIRK_CPULIST;
742 		cpu_init_acpi();
743 		break;
744 #endif
745 #ifdef FDT
746 	case ARM64_BUS_FDT:
747 		cpu_init_fdt();
748 		break;
749 #endif
750 	default:
751 		break;
752 	}
753 }
754 
755 /* Introduce rest of cores to the world */
756 void
cpu_mp_announce(void)757 cpu_mp_announce(void)
758 {
759 }
760 
761 #ifdef DEV_ACPI
762 static void
cpu_count_acpi_handler(ACPI_SUBTABLE_HEADER * entry,void * arg)763 cpu_count_acpi_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
764 {
765 	u_int *cores = arg;
766 
767 	switch(entry->Type) {
768 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
769 		(*cores)++;
770 		break;
771 	default:
772 		break;
773 	}
774 }
775 
776 static u_int
cpu_count_acpi(void)777 cpu_count_acpi(void)
778 {
779 	ACPI_TABLE_MADT *madt;
780 	vm_paddr_t physaddr;
781 	u_int cores;
782 
783 	physaddr = acpi_find_table(ACPI_SIG_MADT);
784 	if (physaddr == 0)
785 		return (0);
786 
787 	madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
788 	if (madt == NULL) {
789 		printf("Unable to map the MADT, not starting APs\n");
790 		return (0);
791 	}
792 
793 	cores = 0;
794 	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
795 	    cpu_count_acpi_handler, &cores);
796 
797 	acpi_unmap_table(madt);
798 
799 	return (cores);
800 }
801 #endif
802 
803 void
cpu_mp_setmaxid(void)804 cpu_mp_setmaxid(void)
805 {
806 	int cores;
807 
808 	mp_ncpus = 1;
809 	mp_maxid = 0;
810 
811 	switch(arm64_bus_method) {
812 #ifdef DEV_ACPI
813 	case ARM64_BUS_ACPI:
814 		cores = cpu_count_acpi();
815 		if (cores > 0) {
816 			cores = MIN(cores, MAXCPU);
817 			if (bootverbose)
818 				printf("Found %d CPUs in the ACPI tables\n",
819 				    cores);
820 			mp_ncpus = cores;
821 			mp_maxid = cores - 1;
822 		}
823 		break;
824 #endif
825 #ifdef FDT
826 	case ARM64_BUS_FDT:
827 		cores = ofw_cpu_early_foreach(NULL, false);
828 		if (cores > 0) {
829 			cores = MIN(cores, MAXCPU);
830 			if (bootverbose)
831 				printf("Found %d CPUs in the device tree\n",
832 				    cores);
833 			mp_ncpus = cores;
834 			mp_maxid = cores - 1;
835 		}
836 		break;
837 #endif
838 	default:
839 		if (bootverbose)
840 			printf("No CPU data, limiting to 1 core\n");
841 		break;
842 	}
843 
844 	if (TUNABLE_INT_FETCH("hw.ncpu", &cores)) {
845 		if (cores > 0 && cores < mp_ncpus) {
846 			mp_ncpus = cores;
847 			mp_maxid = cores - 1;
848 		}
849 	}
850 }
851 
852 /* Sending IPI */
853 void
ipi_all_but_self(u_int ipi)854 ipi_all_but_self(u_int ipi)
855 {
856 	cpuset_t cpus;
857 
858 	cpus = all_cpus;
859 	CPU_CLR(PCPU_GET(cpuid), &cpus);
860 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
861 	intr_ipi_send(cpus, ipi);
862 }
863 
864 void
ipi_cpu(int cpu,u_int ipi)865 ipi_cpu(int cpu, u_int ipi)
866 {
867 	cpuset_t cpus;
868 
869 	CPU_ZERO(&cpus);
870 	CPU_SET(cpu, &cpus);
871 
872 	CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi);
873 	intr_ipi_send(cpus, ipi);
874 }
875 
876 void
ipi_selected(cpuset_t cpus,u_int ipi)877 ipi_selected(cpuset_t cpus, u_int ipi)
878 {
879 
880 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
881 	intr_ipi_send(cpus, ipi);
882 }
883