aboutsummaryrefslogtreecommitdiff
path: root/sys/arm64/arm64/mp_machdep.c
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2017-08-31 20:48:05 +0000
committerAndrew Turner <andrew@FreeBSD.org>2017-08-31 20:48:05 +0000
commit5ea26aec6e50722ad2298d11fdd258f0748fb361 (patch)
treeeecdf35240b11e434a00af28cbfc3e43c05c4ca8 /sys/arm64/arm64/mp_machdep.c
parent3ef74299276ae36f8e52999adc3d39f1de4cfcb3 (diff)
downloadsrc-5ea26aec6e50722ad2298d11fdd258f0748fb361.tar.gz
src-5ea26aec6e50722ad2298d11fdd258f0748fb361.zip
Add support for quirks while enabling secondary CPUs. This uses the fdt
compatible string to check if the board is compatible with a given quirk. It's possible this will be moved later, however as it's currently only used by the MP code put it there. So far the only instance of a quirk is when the list of CPUs may be incorrect. This can happen on virtual machines with a hard coded devicetree, but where the user may then set the number of CPUs as an argument. This is the case on the ARM models so include the model specific compat strings for these, including the spelling mistake found in some of the OpenplatformPkg dtb files. Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/head/; revision=323070
Diffstat (limited to 'sys/arm64/arm64/mp_machdep.c')
-rw-r--r--sys/arm64/arm64/mp_machdep.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index ab1171c777d3..99c0a745eaaf 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$");
#ifdef FDT
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_cpu.h>
#endif
@@ -74,6 +75,23 @@ __FBSDID("$FreeBSD$");
#include "pic_if.h"
+#define MP_QUIRK_CPULIST 0x01 /* The list of cpus may be wrong, */
+ /* don't panic if one fails to start */
+static uint32_t mp_quirks;
+
+#ifdef FDT
+static struct {
+ const char *compat;
+ uint32_t quirks;
+} fdt_quirks[] = {
+ { "arm,foundation-aarch64", MP_QUIRK_CPULIST },
+ { "arm,fvp-base", MP_QUIRK_CPULIST },
+ /* This is incorrect in some DTS files */
+ { "arm,vfp-base", MP_QUIRK_CPULIST },
+ { NULL, 0 },
+};
+#endif
+
typedef void intr_ipi_send_t(void *, cpuset_t, u_int);
typedef void intr_ipi_handler_t(void *);
@@ -465,13 +483,16 @@ start_cpu(u_int id, uint64_t target_cpu)
* start the requested CPU. If psci_cpu_on returns PSCI_MISSING
* to indicate we are unable to use it to start the given CPU.
*/
- KASSERT(err == PSCI_MISSING,
+ KASSERT(err == PSCI_MISSING ||
+ (mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST,
("Failed to start CPU %u (%lx)\n", id, target_cpu));
pcpu_destroy(pcpup);
kmem_free(kernel_arena, (vm_offset_t)dpcpu[cpuid - 1],
DPCPU_SIZE);
dpcpu[cpuid - 1] = NULL;
+ mp_ncpus--;
+
/* Notify the user that the CPU failed to start */
printf("Failed to start CPU %u (%lx)\n", id, target_cpu);
} else
@@ -556,6 +577,10 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
void
cpu_mp_start(void)
{
+#ifdef FDT
+ phandle_t node;
+ int i;
+#endif
mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
@@ -570,6 +595,13 @@ cpu_mp_start(void)
#endif
#ifdef FDT
case ARM64_BUS_FDT:
+ node = OF_peer(0);
+ for (i = 0; fdt_quirks[i].compat != NULL; i++) {
+ if (ofw_bus_node_is_compatible(node,
+ fdt_quirks[i].compat) != 0) {
+ mp_quirks = fdt_quirks[i].quirks;
+ }
+ }
KASSERT(cpu0 >= 0, ("Current CPU was not found"));
ofw_cpu_early_foreach(cpu_init_fdt, true);
break;