The below code is set up to attach and identify processors for arm64
currently it only identifies model, not cache size, but that can be added
later. It is set up to attach secondary processors later (for when SMP
is present).

diff --git a/sys/arch/arm64/arm64/cpu.c b/sys/arch/arm64/arm64/cpu.c
new file mode 100644
index 00000000000..7535522d1ed
--- /dev/null
+++ b/sys/arch/arm64/arm64/cpu.c
@@ -0,0 +1,138 @@
+/*     $OpenBSD$ */
+
+/*
+ * Copyright (c) 2016 Dale Rahn <dr...@dalerahn.com>
+ * Copyright (c) 1997-2004 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/atomic.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <dev/rndvar.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/fdt.h>
+#include <machine/cpufunc.h>
+
+#include <arm64/arm64/arm64var.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+int    cpumatch(struct device *, void *, void *);
+void   cpuattach(struct device *, struct device *, void *);
+
+struct cpu_cores {
+       int      id;
+       char    *name;
+};
+
+struct cpu_cores cpu_cores_none[] = {
+       { 0x0, "Unknown" },
+};
+
+struct cpu_cores cpu_cores_arm[] = {
+       { CPU_PART_CORTEX_A53, "Cortex-A53" },
+       { CPU_PART_CORTEX_A57, "Cortex-A57" },
+       { CPU_PART_CORTEX_A72, "Cortex-A72" },
+       { 0x0, "Unknown" },
+};
+
+/* arm cores makers */
+const struct implementers {
+       int                       id;
+       char                     *name;
+       struct cpu_cores        *corelist;
+} cpu_implementers[] = {
+       { CPU_IMPL_ARM,         "ARM",          cpu_cores_arm },
+       { 0,                    "",     NULL },
+};
+
+
+void
+cpu_identify(struct cpu_info *ci)
+{
+       uint64_t midr, impl, part;
+       char *impl_name = "Unknown";
+       char *part_name = "Unknown";
+       struct cpu_cores *coreselecter = NULL;
+
+       int i;
+
+       midr = READ_SPECIALREG(midr_el1);
+
+       impl = CPU_IMPL(midr);
+       part = CPU_PART(midr);
+
+       for (i = 0; cpu_implementers[i].id != 0; i++) {
+               if (cpu_implementers[i].id == impl) {
+                       impl_name = cpu_implementers[i].name;
+                       coreselecter =  cpu_implementers[i].corelist;
+                       break;
+               }
+       }
+
+       if (impl_name != NULL) {
+               for (i = 0; coreselecter[i].id != 0; i++) {
+                       if (part == coreselecter[i].id) {
+                               part_name = coreselecter[i].name; 
+                       }
+               }
+               printf(" %s %s r%dp%d", impl_name, part_name, CPU_VAR(midr),
+                   CPU_REV(midr));
+       } else {
+               printf (" unknown implementer");
+               
+       }
+}
+
+void
+cpuattach(struct device *parent, struct device *dev, void *aux)
+{
+       struct cpu_info *ci;
+       int cpuno = dev->dv_unit;
+
+       if (cpuno == 0) {
+               ci = &cpu_info_primary;
+               ci->ci_cpuid = cpuno;
+               ci->ci_dev = dev;
+
+               printf(":");
+               cpu_identify(ci);
+       } else {
+               printf(": cpu not attached");
+       }
+
+       printf("\n");
+}
+
diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC
index 44ab4f3e39f..3a0f9433491 100644
--- a/sys/arch/arm64/conf/GENERIC
+++ b/sys/arch/arm64/conf/GENERIC
@@ -51,6 +51,9 @@ ahci*         at fdt?
 pciecam*       at fdt?
 pci*           at pciecam?
 
+cpubus0                at mainbus?
+cpu0           at cpubus?
+
 # NS16550 compatible serial ports
 com*           at fdt?
 
diff --git a/sys/arch/arm64/conf/files.arm64 b/sys/arch/arm64/conf/files.arm64
index e2370431497..79789833096 100644
--- a/sys/arch/arm64/conf/files.arm64
+++ b/sys/arch/arm64/conf/files.arm64
@@ -23,6 +23,7 @@ file  arch/arm64/arm64/sig_machdep.c
 file   arch/arm64/arm64/syscall.c
 file   arch/arm64/arm64/sys_machdep.c
 
+file   arch/arm64/arm64/cpu.c
 file   arch/arm64/arm64/intr.c
 file   arch/arm64/arm64/softintr.c
 file   arch/arm64/arm64/vfp.c
@@ -75,6 +76,13 @@ include "dev/wscons/files.wscons"
 include "dev/rasops/files.rasops"
 include "dev/wsfont/files.wsfont"
 
+device  cpubus {}
+attach  cpubus at mainbus
+
+device  cpu {}
+attach  cpu at cpubus with cpu_fdt
+file    arch/arm64/dev/cpu_fdt.c
+
 #
 # Machine-independent HID support
 #
diff --git a/sys/arch/arm64/dev/cpu_fdt.c b/sys/arch/arm64/dev/cpu_fdt.c
new file mode 100644
index 00000000000..36679954121
--- /dev/null
+++ b/sys/arch/arm64/dev/cpu_fdt.c
@@ -0,0 +1,205 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2011,2015,2017 Dale Rahn <dr...@dalerahn.com>
+ * Copyright (c) 2013 Patrick Wildt <patr...@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <machine/fdt.h>
+#include <sys/evcount.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <arm64/arm64/arm64var.h>
+#include <arm64/dev/mainbus.h>
+
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
+
+int            cpu_fdt_match(struct device *, void *, void *);
+void           cpuattach(struct device *, struct device *, void *);
+int            cpubus_match(struct device *, void *, void *);
+void           cpubus_attach(struct device *, struct device *, void *);
+void           cpu_attach_deferred(struct device *self);
+
+int cpubus_only_attach_boot_processor = 1;
+
+struct cpubus_softc {
+       struct device   sc_dev;
+       int             sc_pnode;
+       int             sc_acells;
+       int             sc_scells;
+};
+
+struct cpu_softc {
+       struct device   sc_dev;
+};
+
+struct cfattach cpubus_ca = {
+       sizeof (struct cpubus_softc), cpubus_match, cpubus_attach
+};
+
+int
+cpubus_match(struct device *parent, void *cfdata, void *aux)
+{
+       union mainbus_attach_args *ma = aux;
+
+       if (strcmp(ma->ma_name, "cpu"))
+               return 1;
+       return 0;
+}
+
+void cpubus_attach_node(struct device *self, int node);
+
+void
+cpubus_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct cpubus_softc *sc = (struct cpubus_softc *)self;
+       int node, pnode;
+
+       pnode = OF_finddevice("/cpus");
+       if (pnode == 0) {
+               return ;
+       }
+       sc->sc_pnode = pnode;
+
+       sc->sc_acells = OF_getpropint(pnode, "#address-cells", 1);
+       sc->sc_scells = OF_getpropint(pnode, "#size-cells", 0);
+
+       printf("\n");
+
+       for (node = OF_child(sc->sc_pnode); node; node = OF_peer(node)) {
+               cpubus_attach_node(self, node);
+       }
+       cpubus_only_attach_boot_processor = 0;
+       
+       config_defer(self, cpu_attach_deferred);
+}
+
+void
+cpu_attach_deferred(struct device *self)
+{
+       struct cpubus_softc *sc = (struct cpubus_softc *)self;
+       int node;
+
+       for (node = OF_child(sc->sc_pnode); node; node = OF_peer(node)) {
+               cpubus_attach_node(self, node);
+       }
+}
+
+
+
+int
+cpubus_submatch(struct device *self, void *match, void *aux)
+{
+       struct cfdata *cf = match;
+
+       return (*cf->cf_attach->ca_match)(self, match, aux);
+}
+
+void
+cpubus_attach_node(struct device *self, int node)
+{
+       struct cpubus_softc *sc = (struct cpubus_softc *)self;
+       uint64_t mpidr = READ_SPECIALREG(mpidr_el1) & MPIDR_AFF;
+       struct fdt_attach_args   fa;
+       char buffer[128];
+       int i, len, line;
+       uint32_t                *cell, *reg;
+
+       if (!OF_getprop(node, "compatible", buffer, sizeof(buffer)))
+               return;
+
+       memset(&fa, 0, sizeof(fa));
+       fa.fa_name = "";
+       fa.fa_node = node;
+       fa.fa_acells = sc->sc_acells;
+       fa.fa_scells = sc->sc_scells;
+
+       len = OF_getproplen(node, "reg");
+
+       line = (sc->sc_acells + sc->sc_scells) * sizeof(uint32_t);
+       if (len > 0 && line > 0 && (len % line) == 0) {
+               reg = malloc(len, M_TEMP, M_WAITOK);
+               OF_getpropintarray(node, "reg", reg, len);
+
+               fa.fa_reg = malloc((len / line) * sizeof(struct fdt_reg),
+                   M_DEVBUF, M_WAITOK | M_ZERO);
+               fa.fa_nreg = (len / line);
+
+               for (i = 0, cell = reg; i < len / line; i++) {
+                       if (sc->sc_acells >= 1)
+                               fa.fa_reg[i].addr = cell[0];
+                       if (sc->sc_acells == 2) {
+                               fa.fa_reg[i].addr <<= 32;
+                               fa.fa_reg[i].addr |= cell[1];
+                       }
+                       cell += sc->sc_acells;
+                       if (sc->sc_scells >= 1)
+                               fa.fa_reg[i].size = cell[0];
+                       if (sc->sc_scells == 2) {
+                               fa.fa_reg[i].size <<= 32;
+                               fa.fa_reg[i].size |= cell[1];
+                       }
+                       cell += sc->sc_scells;
+               }
+
+               free(reg, M_TEMP, len);
+       }
+
+       if (cpubus_only_attach_boot_processor == 1) {
+               if (fa.fa_reg[0].addr != mpidr)
+                       return;
+       } else {
+               if (fa.fa_reg[0].addr == mpidr)
+                       return;
+       }
+       config_found_sm(self, &fa, NULL, cpubus_submatch);
+
+       free(fa.fa_reg, M_DEVBUF, fa.fa_nreg * sizeof(struct fdt_reg));
+}
+
+struct cfdriver cpubus_cd = {
+       NULL, "cpubus", DV_DULL
+};
+
+struct cfattach cpu_fdt_ca = {
+       sizeof (struct cpu_softc), cpu_fdt_match, cpuattach
+};
+
+struct cfdriver cpu_cd = {
+       NULL, "cpu", DV_DULL
+};
+
+int
+cpu_fdt_match(struct device *parent, void *cfdata, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+       char buffer[128];
+       OF_getprop(faa->fa_node, "compatible", buffer, sizeof(buffer));
+
+       if (OF_is_compatible(faa->fa_node, "arm,cortex-a53") ||
+           OF_is_compatible(faa->fa_node, "arm,cortex-a57") ||
+           OF_is_compatible(faa->fa_node, "arm,cortex-a72") ||
+           OF_is_compatible(faa->fa_node, "arm,armv8"))
+               return (1);
+
+       return 0;
+}
diff --git a/sys/arch/arm64/include/armreg.h b/sys/arch/arm64/include/armreg.h
index 1a1802b1dbb..2dc1d93d233 100644
--- a/sys/arch/arm64/include/armreg.h
+++ b/sys/arch/arm64/include/armreg.h
@@ -67,6 +67,13 @@
 #define        CTR_ILINE_MASK          (0xf << CTR_ILINE_SHIFT)
 #define        CTR_ILINE_SIZE(reg)     (((reg) & CTR_ILINE_MASK) >> 
CTR_ILINE_SHIFT)
 
+/* MPIDR_EL1 - Multiprocessor Affinity Register */
+#define MPIDR_AFF3             (0xFFULL << 32)
+#define MPIDR_AFF2             (0xFFULL << 16)
+#define MPIDR_AFF1             (0xFFULL << 8)
+#define MPIDR_AFF0             (0xFFULL << 0)
+#define MPIDR_AFF              (MPIDR_AFF3|MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0)
+
 /* DCZID_EL0 - Data Cache Zero ID register */
 #define DCZID_DZP              (1 << 4) /* DC ZVA prohibited if non-0 */
 #define DCZID_BS_SHIFT         0
diff --git a/sys/arch/arm64/include/cpu.h b/sys/arch/arm64/include/cpu.h
index 2497cb33ccf..9aee1148615 100644
--- a/sys/arch/arm64/include/cpu.h
+++ b/sys/arch/arm64/include/cpu.h
@@ -251,6 +251,18 @@ disable_irq_daif_ret()
 void   delay (unsigned);
 #define        DELAY(x)        delay(x)
 
+/* CPU Identification */
+#define CPU_IMPL_ARM            0x41
+
+#define CPU_PART_CORTEX_A53     0xD03
+#define CPU_PART_CORTEX_A57     0xD07
+#define CPU_PART_CORTEX_A72     0xD08
+
+#define CPU_IMPL(midr)  (((midr) >> 24) & 0xff)
+#define CPU_PART(midr)  (((midr) >> 4) & 0xfff)
+#define CPU_VAR(midr)   (((midr) >> 20) & 0xf)
+#define CPU_REV(midr)   (((midr) >> 0) & 0xf)
+
 #endif /* !_LOCORE */
 
 #endif /* _KERNEL */
Dale Rahn                               dr...@dalerahn.com

Reply via email to